[tracker/tracker-store] trackerd: Make class signals work when writes take place in trackerd



commit 7559590a7b5cf6a7f3fc07ed0254199491b02916
Author: Philip Van Hoof <philip codeminded be>
Date:   Thu Apr 23 12:05:56 2009 +0200

    trackerd: Make class signals work when writes take place in trackerd
---
 src/tracker-indexer/tracker-events.c  |    1 +
 src/tracker-indexer/tracker-events.h  |    2 +
 src/trackerd/Makefile.am              |    2 +
 src/trackerd/tracker-events.c         |  220 +++++++++++++++++++++++++++++++++
 src/trackerd/tracker-events.h         |   45 +++++++
 src/trackerd/tracker-main.c           |   24 ++++
 src/trackerd/tracker-resource-class.c |   93 ++++++++++++++
 7 files changed, 387 insertions(+), 0 deletions(-)

diff --git a/src/tracker-indexer/tracker-events.c b/src/tracker-indexer/tracker-events.c
index 1c2df13..e4ef793 100644
--- a/src/tracker-indexer/tracker-events.c
+++ b/src/tracker-indexer/tracker-events.c
@@ -27,6 +27,7 @@
 
 #include "tracker-events.h"
 
+/* TODO: once all writes are vanished from tracker-indexer, this file can be removed */
 
 typedef struct {
 	GPtrArray *allowances;
diff --git a/src/tracker-indexer/tracker-events.h b/src/tracker-indexer/tracker-events.h
index 9c0197a..fb1d04b 100644
--- a/src/tracker-indexer/tracker-events.h
+++ b/src/tracker-indexer/tracker-events.h
@@ -26,6 +26,8 @@
 
 #include <libtracker-common/tracker-dbus.h>
 
+/* TODO: once all writes are vanished from tracker-indexer, this file can be removed */
+
 G_BEGIN_DECLS
 
 typedef GStrv (*TrackerNotifyClassGetter) (void);
diff --git a/src/trackerd/Makefile.am b/src/trackerd/Makefile.am
index f04fb33..53902d9 100644
--- a/src/trackerd/Makefile.am
+++ b/src/trackerd/Makefile.am
@@ -39,6 +39,8 @@ trackerd_SOURCES =							\
 	tracker-daemon.h						\
 	tracker-dbus.c							\
 	tracker-dbus.h							\
+	tracker-events.c						\
+	tracker-events.h						\
 	tracker-processor.c						\
 	tracker-processor.h						\
 	tracker-main.c							\
diff --git a/src/trackerd/tracker-events.c b/src/trackerd/tracker-events.c
new file mode 100644
index 0000000..1c2df13
--- /dev/null
+++ b/src/trackerd/tracker-events.c
@@ -0,0 +1,220 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors:
+ *  Philip Van Hoof <philip codeminded be>
+ */
+
+#include "config.h"
+
+#include <libtracker-common/tracker-ontology.h>
+
+#include "tracker-events.h"
+
+
+typedef struct {
+	GPtrArray *allowances;
+	GPtrArray *events;
+} EventsPrivate;
+
+static GStaticPrivate private_key = G_STATIC_PRIVATE_INIT;
+
+static void 
+tracker_events_add_allow (const gchar *rdf_class)
+{
+	EventsPrivate *private;
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	g_ptr_array_add (private->allowances, g_strdup (rdf_class));
+}
+
+static gboolean
+is_allowed (EventsPrivate *private, const gchar *rdf_class)
+{
+	guint i;
+	gboolean found = FALSE;
+
+	for (i = 0; i < private->allowances->len;  i++) {
+		if (g_strcmp0 (rdf_class, private->allowances->pdata[i]) == 0) {
+			found = TRUE;
+			break;
+		}
+	}
+
+	return found;
+}
+
+typedef struct {
+	const gchar *uri;
+	TrackerDBusEventsType type;
+} PreparableEvent;
+
+static void 
+prepare_event_for_rdf_types (gpointer data, gpointer user_data)
+{
+	const gchar *rdf_class = data;
+	PreparableEvent *info = user_data;
+	const gchar *uri = info->uri;
+	TrackerDBusEventsType type = info->type;
+
+	EventsPrivate *private;
+	GValueArray *event;
+	GValue uri_value = { 0 , };
+	GValue rdfclass_value = { 0 , };
+	GValue type_value = { 0 , };
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	if (!is_allowed (private, rdf_class))
+		return;
+
+	if (!private->events) {
+		private->events = g_ptr_array_new ();
+	}
+
+	g_value_init (&uri_value, G_TYPE_STRING);
+	g_value_init (&rdfclass_value, G_TYPE_STRING);
+	g_value_init (&type_value, G_TYPE_INT);
+
+	event = g_value_array_new (3);
+
+	g_value_set_string (&uri_value, uri);
+	g_value_set_string (&rdfclass_value, rdf_class);
+	g_value_set_int (&type_value, type);
+
+	g_value_array_append (event, &uri_value);
+	g_value_array_append (event, &rdfclass_value);
+	g_value_array_append (event, &type_value);
+
+	g_ptr_array_add (private->events, event);
+
+	g_value_unset (&uri_value);
+	g_value_unset (&rdfclass_value);
+	g_value_unset (&type_value);
+}
+
+void 
+tracker_events_insert (const gchar *uri, 
+		       const gchar *object, 
+		       GPtrArray *rdf_types, 
+		       TrackerDBusEventsType type)
+{
+	PreparableEvent info;
+
+	info.uri = uri;
+	info.type = type;
+
+	if (rdf_types && type == TRACKER_DBUS_EVENTS_TYPE_UPDATE) {
+		/* object is not very important for updates (we don't expose
+		 * the value being set to the user's DBus API in trackerd) */
+		g_ptr_array_foreach (rdf_types, prepare_event_for_rdf_types, &info);
+	} else if (type == TRACKER_DBUS_EVENTS_TYPE_UPDATE) {
+		/* In this case we had an INSERT for a resource that didn't exist 
+		 * yet, but it was not the rdf:type predicate being inserted */
+		prepare_event_for_rdf_types ((gpointer) TRACKER_RDFS_PREFIX "Resource", &info);
+	} else {
+		/* In case of delete and create, object is the rdf:type */
+		prepare_event_for_rdf_types ((gpointer) object, &info);
+	}
+}
+
+void 
+tracker_events_reset (void)
+{
+	EventsPrivate *private;
+	guint i;
+
+	private = g_static_private_get (&private_key);
+	g_return_if_fail (private != NULL);
+
+	if (private->events) {
+		for (i = 0; i < private->events->len; i++) {
+			g_value_array_free (private->events->pdata[i]);
+		}
+		g_ptr_array_free (private->events, TRUE);
+
+		private->events = NULL;
+	}
+}
+
+GPtrArray *
+tracker_events_get_pending (void)
+{
+	EventsPrivate *private;
+
+	private = g_static_private_get (&private_key);
+	g_return_val_if_fail (private != NULL, NULL);
+
+	return private->events;
+}
+
+static void
+free_private (EventsPrivate *private)
+{
+	g_ptr_array_foreach (private->allowances, (GFunc)g_free, NULL);
+	g_ptr_array_free (private->allowances, TRUE);
+	g_free (private);
+}
+
+void 
+tracker_events_init (TrackerNotifyClassGetter callback)
+{
+	EventsPrivate *private;
+	GStrv          classes_to_signal;
+	gint           i, count;
+
+	private = g_new0 (EventsPrivate, 1);
+
+	g_static_private_set (&private_key,
+			      private,
+			      (GDestroyNotify) free_private);
+
+	private->allowances = g_ptr_array_new ();
+	private->events = NULL;
+
+	if (!callback) {
+		return;
+	}
+
+	classes_to_signal = (*callback)();
+	count = g_strv_length (classes_to_signal);
+	for (i = 0; i < count; i++) {
+		tracker_events_add_allow (classes_to_signal[i]);
+	}
+
+	g_strfreev (classes_to_signal);
+}
+
+void 
+tracker_events_shutdown (void)
+{
+	EventsPrivate *private;
+
+	private = g_static_private_get (&private_key);
+	if (private != NULL) {
+		/* Shutdown with pending events = ERROR */
+		g_return_if_fail (private->events == NULL);
+		g_static_private_set (&private_key, NULL, NULL);
+	} else {
+		g_warning ("tracker_events already shutdown");
+	}
+}
diff --git a/src/trackerd/tracker-events.h b/src/trackerd/tracker-events.h
new file mode 100644
index 0000000..9c0197a
--- /dev/null
+++ b/src/trackerd/tracker-events.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors:
+ *  Philip Van Hoof <philip codeminded be>
+ */
+
+#ifndef __TRACKER_INDEXER_EVENTS_H__
+#define __TRACKER_INDEXER_EVENTS_H__
+
+#include <libtracker-common/tracker-dbus.h>
+
+G_BEGIN_DECLS
+
+typedef GStrv (*TrackerNotifyClassGetter) (void);
+
+void       tracker_events_init        (TrackerNotifyClassGetter callback);
+void       tracker_events_shutdown    (void);
+void       tracker_events_insert      (const gchar           *uri,
+				       const gchar           *object,
+				       GPtrArray             *rdf_types,
+				       TrackerDBusEventsType  type);
+GPtrArray *tracker_events_get_pending (void);
+void       tracker_events_reset       (void);
+
+
+G_END_DECLS
+
+#endif /* __TRACKER_INDEXER_PUSH_H__ */
diff --git a/src/trackerd/tracker-main.c b/src/trackerd/tracker-main.c
index 5b986b7..4ec50fa 100644
--- a/src/trackerd/tracker-main.c
+++ b/src/trackerd/tracker-main.c
@@ -52,12 +52,15 @@
 #include <libtracker-common/tracker-nfs-lock.h>
 #include <libtracker-common/tracker-ontology.h>
 #include <libtracker-common/tracker-thumbnailer.h>
+#include <libtracker-common/tracker-events.h>
 
 #include <libtracker-db/tracker-db-manager.h>
+#include <libtracker-db/tracker-db-dbus.h>
 
 #include <libtracker-data/tracker-data-manager.h>
 #include <libtracker-data/tracker-turtle.h>
 #include <libtracker-data/tracker-data-backup.h>
+#include <libtracker-data/tracker-data-query.h>
 
 #include <tracker-push.h>
 
@@ -815,6 +818,25 @@ start_cb (gpointer user_data)
 	return FALSE;
 }
 
+
+static GStrv
+tracker_daemon_get_notifiable_classes (void)
+{
+	TrackerDBResultSet *result_set;
+	GStrv               classes_to_signal = NULL;
+
+	result_set = tracker_data_query_sparql ("SELECT ?class WHERE { ?class tracker:notify true }", NULL);
+
+	if (result_set) {
+		guint count = 0;
+
+		classes_to_signal = tracker_dbus_query_result_to_strv (result_set, 0, &count);
+		g_object_unref (result_set);
+	}
+
+	return classes_to_signal;
+}
+
 gint
 main (gint argc, gchar *argv[])
 {
@@ -1026,6 +1048,7 @@ main (gint argc, gchar *argv[])
 		return EXIT_FAILURE;
 	}
 
+	tracker_events_init (tracker_daemon_get_notifiable_classes);
 	tracker_push_init (config);
 
 	g_message ("Waiting for DBus requests...");
@@ -1090,6 +1113,7 @@ main (gint argc, gchar *argv[])
 	/* Shutdown major subsystems */
 
 	tracker_push_shutdown ();
+	tracker_events_shutdown ();
 
 	tracker_volume_cleanup_shutdown ();
 	tracker_dbus_shutdown ();
diff --git a/src/trackerd/tracker-resource-class.c b/src/trackerd/tracker-resource-class.c
index 93ca6d3..cf42ed6 100644
--- a/src/trackerd/tracker-resource-class.c
+++ b/src/trackerd/tracker-resource-class.c
@@ -28,12 +28,31 @@
 #include <libtracker-common/tracker-dbus.h>
 #include <libtracker-common/tracker-config.h>
 #include <libtracker-common/tracker-ontology.h>
+
 #include <libtracker-db/tracker-db-dbus.h>
 
+#include <libtracker-data/tracker-data-update.h>
+
 #include "tracker-dbus.h"
+#include "tracker-events.h"
 #include "tracker-resource-class.h"
 #include "tracker-marshal.h"
 
+#define RDF_PREFIX TRACKER_RDF_PREFIX
+#define RDF_TYPE RDF_PREFIX "type"
+
+static void on_statements_committed (gpointer user_data);
+static void on_statement_inserted   (const gchar *subject,
+				     const gchar *predicate,
+				     const gchar *object,
+				     GPtrArray   *rdf_types,
+				     gpointer user_data);
+static void on_statement_deleted    (const gchar *subject,
+				     const gchar *predicate,
+				     const gchar *object,
+				     GPtrArray   *rdf_types,
+				     gpointer user_data);
+
 #define TRACKER_RESOURCE_CLASS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_RESOURCE_CLASS, TrackerResourceClassPrivate))
 
 typedef struct {
@@ -99,9 +118,15 @@ tracker_resource_class_class_init (TrackerResourceClassClass *klass)
 	g_type_class_add_private (object_class, sizeof (TrackerResourceClassPrivate));
 }
 
+
+
+
 static void
 tracker_resource_class_init (TrackerResourceClass *object)
 {
+	tracker_data_set_insert_statement_callback (on_statement_inserted, object);
+	tracker_data_set_delete_statement_callback (on_statement_deleted, object);
+	tracker_data_set_commit_statement_callback (on_statements_committed, object);
 }
 
 static void
@@ -230,3 +255,71 @@ tracker_resource_class_emit_events (TrackerResourceClass  *object)
 		priv->dels = NULL;
 	}
 }
+
+
+static void
+on_statements_committed (gpointer user_data)
+{
+	GPtrArray *events;
+
+	events = tracker_events_get_pending ();
+
+	if (events) {
+		GSList *event_sources, *l, *to_emit = NULL;
+		guint i;
+
+		for (i = 0; i < events->len; i++) {
+			GValueArray *event = events->pdata[i];
+			const gchar *uri = g_value_get_string (g_value_array_get_nth (event, 0));
+			const gchar *rdf_class = g_value_get_string (g_value_array_get_nth (event, 1));
+			TrackerDBusEventsType type = g_value_get_int (g_value_array_get_nth (event, 2));
+
+			for (l = event_sources; l; l = l->next) {
+				TrackerResourceClass *class_ = l->data;
+				if (g_strcmp0 (rdf_class, tracker_resource_class_get_rdf_class (class_)) == 0) {
+					tracker_resource_class_add_event (class_, uri, type);
+					to_emit = g_slist_prepend (to_emit, class_);
+				}
+			}
+		}
+
+		if (to_emit) {
+			for (l = to_emit; l; l = l->next) {
+				TrackerResourceClass *class_ = l->data;
+				tracker_resource_class_emit_events (class_);
+			}
+
+			g_slist_free (to_emit);
+		}
+	}
+
+	tracker_events_reset ();
+}
+
+static void
+on_statement_inserted (const gchar *subject,
+		       const gchar *predicate,
+		       const gchar *object,
+		       GPtrArray   *rdf_types,
+		       gpointer user_data)
+{
+	if (g_strcmp0 (predicate, RDF_PREFIX "type") == 0) {
+		tracker_events_insert (subject, object, rdf_types, TRACKER_DBUS_EVENTS_TYPE_ADD);
+	} else {
+		tracker_events_insert (subject, object, rdf_types, TRACKER_DBUS_EVENTS_TYPE_UPDATE);
+	}
+}
+
+static void
+on_statement_deleted (const gchar *subject,
+		      const gchar *predicate,
+		      const gchar *object,
+		      GPtrArray   *rdf_types,
+		      gpointer user_data)
+{
+	if (g_strcmp0 (predicate, RDF_PREFIX "type") == 0) {
+		tracker_events_insert (subject, object, rdf_types, TRACKER_DBUS_EVENTS_TYPE_DELETE);
+	} else {
+		tracker_events_insert (subject, object, rdf_types, TRACKER_DBUS_EVENTS_TYPE_UPDATE);
+	}
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]