[tracker] Add class signals
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Subject: [tracker] Add class signals
- Date: Thu, 16 Apr 2009 11:25:16 -0400 (EDT)
commit 1a8e11987df109705985b7f446f8ad22a6b3663f
Author: Philip Van Hoof <philip codeminded be>
Date: Thu Apr 9 18:06:13 2009 +0200
Add class signals
---
data/dbus/Makefile.am | 3 +-
data/dbus/tracker-indexer.xml | 3 +
data/dbus/tracker-resources-class.xml | 25 +++
data/ontologies/33-nfo.ontology | 4 +
data/ontologies/34-nmo.ontology | 1 +
data/ontologies/90-tracker.ontology | 4 +
src/libtracker-common/tracker-dbus.h | 8 +
src/libtracker-data/tracker-data-query.c | 42 +++++
src/libtracker-data/tracker-data-query.h | 2 +
src/libtracker-data/tracker-data-update.c | 64 ++++++++
src/libtracker-data/tracker-data-update.h | 15 ++
src/tracker-indexer/Makefile.am | 4 +-
src/tracker-indexer/tracker-events.c | 220 +++++++++++++++++++++++++
src/tracker-indexer/tracker-events.h | 45 +++++
src/tracker-indexer/tracker-indexer.c | 86 ++++++++++
src/tracker-indexer/tracker-indexer.h | 6 +
src/tracker-indexer/tracker-main.c | 7 +-
src/trackerd/Makefile.am | 5 +-
src/trackerd/tracker-dbus.c | 81 +++++++++-
src/trackerd/tracker-resource-class.c | 232 +++++++++++++++++++++++++++
src/trackerd/tracker-resource-class.h | 65 ++++++++
src/trackerd/tracker-resources.c | 106 ++++++++++++
src/trackerd/tracker-resources.h | 6 +
tests/tracker-indexer/Makefile.am | 16 ++-
tests/tracker-indexer/tracker-events-test.c | 187 +++++++++++++++++++++
25 files changed, 1231 insertions(+), 6 deletions(-)
diff --git a/data/dbus/Makefile.am b/data/dbus/Makefile.am
index ae6ae5f..f4fc891 100644
--- a/data/dbus/Makefile.am
+++ b/data/dbus/Makefile.am
@@ -8,7 +8,8 @@ config_DATA = \
tracker-resources.xml \
tracker-search.xml \
tracker-indexer.xml \
- tracker-extract.xml
+ tracker-extract.xml \
+ tracker-resources-class.xml
# Services
servicedir = $(DBUS_SERVICES_DIR)
diff --git a/data/dbus/tracker-indexer.xml b/data/dbus/tracker-indexer.xml
index 0c26ef9..1594783 100644
--- a/data/dbus/tracker-indexer.xml
+++ b/data/dbus/tracker-indexer.xml
@@ -117,5 +117,8 @@
<arg type="s" name="reason" />
<arg type="b" name="requires_reindexing" />
</signal>
+ <signal name="EventHappened">
+ <arg type="a(ssi)" name="events" />
+ </signal>
</interface>
</node>
diff --git a/data/dbus/tracker-resources-class.xml b/data/dbus/tracker-resources-class.xml
new file mode 100644
index 0000000..c595933
--- /dev/null
+++ b/data/dbus/tracker-resources-class.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<node name="/">
+ <interface name="org.freedesktop.Tracker.Resources.Class">
+
+ <!-- Signal for changed subjects -->
+
+ <signal name="SubjectsChanged">
+ <arg type="as" name="subject" />
+ </signal>
+
+ <!-- Signal for added subjects -->
+
+ <signal name="SubjectsAdded">
+ <arg type="as" name="subject" />
+ </signal>
+
+ <!-- Signal for removed subjects -->
+
+ <signal name="SubjectsRemoved">
+ <arg type="as" name="subject" />
+ </signal>
+
+ </interface>
+</node>
diff --git a/data/ontologies/33-nfo.ontology b/data/ontologies/33-nfo.ontology
index 28ec288..af56503 100644
--- a/data/ontologies/33-nfo.ontology
+++ b/data/ontologies/33-nfo.ontology
@@ -39,6 +39,7 @@ nfo:Visual a rdfs:Class ;
nfo:Image a rdfs:Class ;
rdfs:label "Image" ;
rdfs:comment "A file containing an image." ;
+ tracker:notify true ;
rdfs:subClassOf nfo:Visual .
nfo:RasterImage a rdfs:Class ;
@@ -68,6 +69,7 @@ nfo:VectorImage a rdfs:Class ;
nfo:Audio a rdfs:Class ;
rdfs:label "Audio" ;
rdfs:comment "A file containing audio content" ;
+ tracker:notify true ;
rdfs:subClassOf nfo:Media .
nfo:CompressionType a rdfs:Class ;
@@ -233,6 +235,7 @@ nfo:Cursor a rdfs:Class ;
nfo:Bookmark a rdfs:Class ;
rdfs:label "Bookmark" ;
rdfs:comment "['A bookmark of a webbrowser. Use nie:title for the name/label', 'nie:contentCreated to represent the date when the user added the bookmark', 'and nie:contentLastModified for modifications. nfo:bookmarks to store the link.']" ;
+ tracker:notify true ;
rdfs:subClassOf nie:InformationElement .
nfo:DeletedResource a rdfs:Class ;
@@ -248,6 +251,7 @@ nfo:Website a rdfs:Class ;
nfo:WebHistory a rdfs:Class ;
rdfs:label "Web History" ;
rdfs:comment "A web history entry" ;
+ tracker:notify true ;
rdfs:subClassOf nie:InformationElement .
nfo:count a rdf:Property ;
diff --git a/data/ontologies/34-nmo.ontology b/data/ontologies/34-nmo.ontology
index c1e457f..a173272 100644
--- a/data/ontologies/34-nmo.ontology
+++ b/data/ontologies/34-nmo.ontology
@@ -61,6 +61,7 @@ nmo:FeedChannel a rdfs:Class ;
rdfs:subClassOf nmo:CommunicationChannel .
nmo:FeedMessage a rdfs:Class ;
+ tracker:notify true ;
rdfs:subClassOf nmo:Message .
nmo:VOIPCall a rdfs:Class ;
diff --git a/data/ontologies/90-tracker.ontology b/data/ontologies/90-tracker.ontology
index 14ca0c9..0144dc0 100644
--- a/data/ontologies/90-tracker.ontology
+++ b/data/ontologies/90-tracker.ontology
@@ -14,6 +14,10 @@ tracker:tagRelatedTo a rdf:Property ;
rdfs:domain nao:Tag ;
rdfs:range rdfs:Class .
+tracker:notify a rdf:Property ;
+ rdfs:domain rdfs:Class ;
+ rdfs:range xsd:boolean .
+
tracker:Volume a rdfs:Class ;
rdfs:label "Storage media" ;
rdfs:subClassOf nie:DataSource .
diff --git a/src/libtracker-common/tracker-dbus.h b/src/libtracker-common/tracker-dbus.h
index 8f44f30..b2fcd1d 100644
--- a/src/libtracker-common/tracker-dbus.h
+++ b/src/libtracker-common/tracker-dbus.h
@@ -72,6 +72,14 @@ G_BEGIN_DECLS
}; \
} G_STMT_END
+typedef enum {
+ TRACKER_DBUS_EVENTS_TYPE_ADD,
+ TRACKER_DBUS_EVENTS_TYPE_UPDATE,
+ TRACKER_DBUS_EVENTS_TYPE_DELETE
+} TrackerDBusEventsType;
+
+#define TRACKER_TYPE_EVENT_ARRAY dbus_g_type_get_collection ("GPtrArray", dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID))
+
typedef struct TrackerDBusRequestHandler TrackerDBusRequestHandler;
typedef void (*TrackerDBusRequestFunc) (guint request_id,
diff --git a/src/libtracker-data/tracker-data-query.c b/src/libtracker-data/tracker-data-query.c
index 7f08bc8..cc79296 100644
--- a/src/libtracker-data/tracker-data-query.c
+++ b/src/libtracker-data/tracker-data-query.c
@@ -210,6 +210,48 @@ tracker_data_query_all_metadata (guint32 resource_id)
}
+
+GPtrArray*
+tracker_data_query_rdf_type (guint32 id)
+{
+ TrackerDBResultSet *result_set;
+ TrackerDBInterface *iface;
+ TrackerDBStatement *stmt;
+ GPtrArray *ret = NULL;
+
+ iface = tracker_db_manager_get_db_interface ();
+
+ stmt = tracker_db_interface_create_statement (iface,
+ "SELECT \"rdfs:Resource\".\"Uri\" "
+ "FROM \"rdfs:Resource_rdf:type\" "
+ "INNER JOIN \"rdfs:Resource\" "
+ "ON \"rdfs:Resource_rdf:type\".\"rdf:type\" = \"rdfs:Resource\".\"ID\" "
+ "WHERE \"rdfs:Resource_rdf:type\".\"ID\" = ?");
+
+ tracker_db_statement_bind_int (stmt, 0, id);
+ result_set = tracker_db_statement_execute (stmt, NULL);
+ g_object_unref (stmt);
+
+ if (result_set) {
+ guint rows;
+
+ rows = tracker_db_result_set_get_n_rows (result_set);
+ ret = g_ptr_array_sized_new (rows);
+ do {
+ gchar *uri;
+
+ tracker_db_result_set_get (result_set, 0, &uri, -1);
+
+ g_ptr_array_add (ret, uri);
+
+ } while (tracker_db_result_set_iter_next (result_set));
+
+ g_object_unref (result_set);
+ }
+
+ return ret;
+}
+
guint32
tracker_data_query_resource_id (const gchar *uri)
{
diff --git a/src/libtracker-data/tracker-data-query.h b/src/libtracker-data/tracker-data-query.h
index 6743f89..0d56441 100644
--- a/src/libtracker-data/tracker-data-query.h
+++ b/src/libtracker-data/tracker-data-query.h
@@ -60,6 +60,8 @@ guint32 tracker_data_query_resource_id (const gchar
TrackerDBResultSet *tracker_data_query_sparql (const gchar *query,
GError **error);
+GPtrArray* tracker_data_query_rdf_type (guint32 id);
+
G_END_DECLS
#endif /* __TRACKER_DATA_QUERY_H__ */
diff --git a/src/libtracker-data/tracker-data-update.c b/src/libtracker-data/tracker-data-update.c
index 7c4e8c8..ec6b33f 100644
--- a/src/libtracker-data/tracker-data-update.c
+++ b/src/libtracker-data/tracker-data-update.c
@@ -52,6 +52,7 @@ struct _TrackerDataUpdateBuffer {
gchar *subject;
guint32 id;
GHashTable *tables;
+ GPtrArray *types;
};
struct _TrackerDataUpdateBufferProperty {
@@ -85,6 +86,37 @@ static gboolean auto_commit = TRUE;
static TrackerDataUpdateBuffer update_buffer;
static TrackerDataBlankBuffer blank_buffer;
+static TrackerStatementCallback insert_callback = NULL;
+static gpointer insert_data;
+static TrackerStatementCallback delete_callback = NULL;
+static gpointer delete_data;
+static TrackerCommitCallback commit_callback = NULL;
+static gpointer commit_data;
+
+void
+tracker_data_set_commit_statement_callback (TrackerCommitCallback callback,
+ gpointer user_data)
+{
+ commit_callback = callback;
+ commit_data = user_data;
+}
+
+void
+tracker_data_set_insert_statement_callback (TrackerStatementCallback callback,
+ gpointer user_data)
+{
+ insert_callback = callback;
+ insert_data = user_data;
+}
+
+void
+tracker_data_set_delete_statement_callback (TrackerStatementCallback callback,
+ gpointer user_data)
+{
+ delete_callback = callback;
+ delete_data = user_data;
+}
+
static guint32
tracker_data_update_get_new_service_id (TrackerDBInterface *iface)
{
@@ -348,6 +380,12 @@ tracker_data_update_buffer_flush (void)
g_hash_table_remove_all (update_buffer.tables);
g_free (update_buffer.subject);
update_buffer.subject = NULL;
+
+ if (update_buffer.types) {
+ g_ptr_array_foreach (update_buffer.types, (GFunc) g_free, NULL);
+ g_ptr_array_free (update_buffer.types, TRUE);
+ update_buffer.types = NULL;
+ }
}
static void
@@ -794,6 +832,7 @@ tracker_data_delete_statement (const gchar *subject,
TrackerClass *class;
TrackerProperty *field;
gint subject_id;
+ GPtrArray *types;
if (auto_commit) {
tracker_data_begin_implicit_transaction ();
@@ -811,6 +850,8 @@ tracker_data_delete_statement (const gchar *subject,
return;
}
+ types = tracker_data_query_rdf_type (subject_id);
+
if (object && g_strcmp0 (predicate, RDF_PREFIX "type") == 0) {
class = tracker_ontology_get_class_by_uri (object);
if (class != NULL) {
@@ -910,6 +951,15 @@ tracker_data_delete_statement (const gchar *subject,
}
}
+ if (delete_callback) {
+ delete_callback (subject, predicate, object, types, delete_data);
+ }
+
+ if (types) {
+ g_ptr_array_foreach (types, (GFunc) g_free, NULL);
+ g_ptr_array_free (types, TRUE);
+ }
+
if (auto_commit) {
tracker_data_commit_transaction ();
}
@@ -997,6 +1047,7 @@ tracker_data_insert_statement (const gchar *subject,
/* subject not yet in cache, retrieve or create ID */
update_buffer.subject = g_strdup (subject);
update_buffer.id = ensure_resource_id (update_buffer.subject);
+ update_buffer.types = tracker_data_query_rdf_type (update_buffer.id);
g_value_set_int64 (&gvalue, (gint64) time (NULL));
cache_insert_value ("rdfs:Resource", "Modified", &gvalue, FALSE);
@@ -1008,6 +1059,11 @@ tracker_data_insert_statement (const gchar *subject,
service = tracker_ontology_get_class_by_uri (object);
if (service != NULL) {
cache_create_service_decomposed (service);
+
+ if (!update_buffer.types)
+ update_buffer.types = g_ptr_array_new ();
+ g_ptr_array_add (update_buffer.types, g_strdup (object));
+
} else {
g_warning ("Class '%s' not found in the ontology", object);
}
@@ -1044,9 +1100,14 @@ tracker_data_insert_statement (const gchar *subject,
}
}
+ if (insert_callback) {
+ insert_callback (subject, predicate, object, update_buffer.types, insert_data);
+ }
+
if (auto_commit) {
tracker_data_commit_transaction ();
}
+
}
void
@@ -1390,6 +1451,9 @@ tracker_data_commit_transaction (void)
g_hash_table_unref (update_buffer.resource_cache);
+ if (commit_callback)
+ commit_callback (commit_data);
+
auto_commit = TRUE;
}
diff --git a/src/libtracker-data/tracker-data-update.h b/src/libtracker-data/tracker-data-update.h
index 14e1639..2f1bcf0 100644
--- a/src/libtracker-data/tracker-data-update.h
+++ b/src/libtracker-data/tracker-data-update.h
@@ -61,6 +61,21 @@ void tracker_data_update_disable_volume (const gchar *ud
void tracker_data_update_disable_all_volumes (void);
void tracker_data_update_reset_volume (const gchar *uri);
+/* Calling back */
+typedef void (*TrackerStatementCallback) (const gchar *subject,
+ const gchar *predicate,
+ const gchar *object,
+ GPtrArray *rdf_types,
+ gpointer user_data);
+typedef void (*TrackerCommitCallback) (gpointer user_data);
+
+void tracker_data_set_insert_statement_callback (TrackerStatementCallback callback,
+ gpointer user_data);
+void tracker_data_set_delete_statement_callback (TrackerStatementCallback callback,
+ gpointer user_data);
+void tracker_data_set_commit_statement_callback (TrackerCommitCallback callback,
+ gpointer user_data);
+
G_END_DECLS
#endif /* __TRACKER_DATA_UPDATE_H__ */
diff --git a/src/tracker-indexer/Makefile.am b/src/tracker-indexer/Makefile.am
index c4a3a47..99dd9c7 100644
--- a/src/tracker-indexer/Makefile.am
+++ b/src/tracker-indexer/Makefile.am
@@ -54,7 +54,9 @@ tracker_indexer_SOURCES = \
tracker-removable-device.c \
tracker-removable-device.h \
tracker-push.c \
- tracker-push.h
+ tracker-push.h \
+ tracker-events.c \
+ tracker-events.h
tracker_indexer_LDADD = \
$(plugin_libs) \
diff --git a/src/tracker-indexer/tracker-events.c b/src/tracker-indexer/tracker-events.c
new file mode 100644
index 0000000..1c2df13
--- /dev/null
+++ b/src/tracker-indexer/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/tracker-indexer/tracker-events.h b/src/tracker-indexer/tracker-events.h
new file mode 100644
index 0000000..9c0197a
--- /dev/null
+++ b/src/tracker-indexer/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/tracker-indexer/tracker-indexer.c b/src/tracker-indexer/tracker-indexer.c
index 5153325..7d68960 100644
--- a/src/tracker-indexer/tracker-indexer.c
+++ b/src/tracker-indexer/tracker-indexer.c
@@ -70,6 +70,7 @@
#include <libtracker-common/tracker-thumbnailer.h>
#include <libtracker-db/tracker-db-index-manager.h>
+#include <libtracker-db/tracker-db-dbus.h>
#include <libtracker-data/tracker-data-manager.h>
#include <libtracker-data/tracker-data-query.h>
@@ -83,6 +84,7 @@
#include "tracker-marshal.h"
#include "tracker-module-metadata-private.h"
#include "tracker-removable-device.h"
+#include "tracker-events.h"
#define TRACKER_INDEXER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_INDEXER, TrackerIndexerPrivate))
@@ -201,6 +203,7 @@ enum {
PAUSED,
CONTINUED,
INDEXING_ERROR,
+ EVENT_HAPPENED,
LAST_SIGNAL
};
@@ -226,6 +229,49 @@ static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (TrackerIndexer, tracker_indexer, G_TYPE_OBJECT)
+
+static void
+on_statements_committed (gpointer user_data)
+{
+ GPtrArray *events;
+ TrackerIndexer *indexer = user_data;
+
+ events = tracker_events_get_pending ();
+ if (events) {
+ tracker_indexer_make_event_happen (indexer, events);
+ }
+ 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);
+ }
+}
+
+
static PathInfo *
path_info_new (TrackerIndexerModule *module,
GFile *file,
@@ -770,6 +816,17 @@ tracker_indexer_class_init (TrackerIndexerClass *class)
G_TYPE_NONE,
2, G_TYPE_STRING, G_TYPE_BOOLEAN);
+ signals[EVENT_HAPPENED] =
+ g_signal_new ("event-happened",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TrackerIndexerClass, event_happened),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE,
+ 1,
+ TRACKER_TYPE_EVENT_ARRAY);
+
g_object_class_install_property (object_class,
PROP_RUNNING,
g_param_spec_boolean ("running",
@@ -781,6 +838,13 @@ tracker_indexer_class_init (TrackerIndexerClass *class)
g_type_class_add_private (object_class, sizeof (TrackerIndexerPrivate));
}
+void
+tracker_indexer_make_event_happen (TrackerIndexer *indexer,
+ GPtrArray *events)
+{
+ g_signal_emit (indexer, signals[EVENT_HAPPENED], 0, events);
+}
+
static void
check_started (TrackerIndexer *indexer)
{
@@ -950,6 +1014,10 @@ tracker_indexer_init (TrackerIndexer *indexer)
priv = indexer->private = TRACKER_INDEXER_GET_PRIVATE (indexer);
+ tracker_data_set_insert_statement_callback (on_statement_inserted, indexer);
+ tracker_data_set_delete_statement_callback (on_statement_deleted, indexer);
+ tracker_data_set_commit_statement_callback (on_statements_committed, indexer);
+
/* NOTE: We set this to stopped because it is likely the
* daemon sends a request for something other than to check
* files initially and we don't want to signal finished and
@@ -1903,6 +1971,24 @@ process_func (gpointer data)
return TRUE;
}
+GStrv
+tracker_indexer_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;
+}
+
TrackerIndexer *
tracker_indexer_new (void)
{
diff --git a/src/tracker-indexer/tracker-indexer.h b/src/tracker-indexer/tracker-indexer.h
index 11740b2..fd13613 100644
--- a/src/tracker-indexer/tracker-indexer.h
+++ b/src/tracker-indexer/tracker-indexer.h
@@ -76,6 +76,8 @@ struct TrackerIndexerClass {
void (*indexing_error) (TrackerIndexer *indexer,
const gchar *reason,
gboolean requires_reindex);
+ void (*event_happened) (TrackerIndexer *indexer,
+ GPtrArray *events);
};
GType tracker_indexer_get_type (void) G_GNUC_CONST;
@@ -91,6 +93,8 @@ void tracker_indexer_process_modules (TrackerIndexer *ind
gchar **modules);
void tracker_indexer_transaction_commit (TrackerIndexer *indexer);
void tracker_indexer_transaction_open (TrackerIndexer *indexer);
+void tracker_indexer_make_event_happen (TrackerIndexer *indexer,
+ GPtrArray *events);
/* DBus methods */
void tracker_indexer_pause (TrackerIndexer *indexer,
@@ -161,6 +165,8 @@ void tracker_indexer_shutdown (TrackerIndexer *ind
DBusGMethodInvocation *context,
GError **error);
+GStrv tracker_indexer_get_notifiable_classes (void);
+
G_END_DECLS
#endif /* __TRACKER_INDEXER_H__ */
diff --git a/src/tracker-indexer/tracker-main.c b/src/tracker-indexer/tracker-main.c
index 7ea7588..6da6005 100644
--- a/src/tracker-indexer/tracker-main.c
+++ b/src/tracker-indexer/tracker-main.c
@@ -45,15 +45,18 @@
#include <libtracker-db/tracker-db-manager.h>
#include <libtracker-db/tracker-db-index-manager.h>
+#include <libtracker-db/tracker-db-dbus.h>
#include <libtracker-data/tracker-data-manager.h>
#include <libtracker-data/tracker-data-update.h>
+#include <libtracker-data/tracker-data-query.h>
#include <libtracker-data/tracker-turtle.h>
#include "tracker-dbus.h"
+#include "tracker-events.h"
#include "tracker-indexer.h"
-#include "tracker-push.h"
#include "tracker-indexer-glue.h"
+#include "tracker-push.h"
#define ABOUT \
"Tracker " PACKAGE_VERSION "\n"
@@ -413,6 +416,7 @@ main (gint argc, gchar *argv[])
tracker_indexer_process_modules (indexer, modules);
}
+ tracker_events_init (tracker_indexer_get_notifiable_classes);
tracker_push_init (config, indexer);
tracker_turtle_init ();
@@ -437,6 +441,7 @@ main (gint argc, gchar *argv[])
g_object_unref (language);
tracker_push_shutdown ();
+ tracker_events_shutdown ();
tracker_thumbnailer_shutdown ();
tracker_dbus_shutdown ();
diff --git a/src/trackerd/Makefile.am b/src/trackerd/Makefile.am
index 97ceed2..5bd9fa5 100644
--- a/src/trackerd/Makefile.am
+++ b/src/trackerd/Makefile.am
@@ -60,7 +60,9 @@ trackerd_SOURCES = \
tracker-push.c \
tracker-push.h \
tracker-push-registrar.c \
- tracker-push-registrar.h
+ tracker-push-registrar.h \
+ tracker-resource-class.c \
+ tracker-resource-class.h
if OS_WIN32
trackerd_win_libs = -lws2_32 -lkernel32
@@ -106,6 +108,7 @@ dbus_sources = \
tracker-daemon-glue.h \
tracker-resources-glue.h \
tracker-search-glue.h \
+ tracker-resources-class-glue.h \
tracker-indexer-client.h
%-glue.h: $(top_srcdir)/data/dbus/%.xml
diff --git a/src/trackerd/tracker-dbus.c b/src/trackerd/tracker-dbus.c
index e85c169..8d536d0 100644
--- a/src/trackerd/tracker-dbus.c
+++ b/src/trackerd/tracker-dbus.c
@@ -25,16 +25,21 @@
#include <libtracker-common/tracker-dbus.h>
#include <libtracker-common/tracker-log.h>
#include <libtracker-common/tracker-utils.h>
+#include <libtracker-common/tracker-ontology.h>
+#include <libtracker-db/tracker-db-dbus.h>
#include <libtracker-db/tracker-db-manager.h>
#include <libtracker-data/tracker-data-manager.h>
+#include <libtracker-data/tracker-data-query.h>
#include "tracker-dbus.h"
#include "tracker-daemon.h"
#include "tracker-daemon-glue.h"
#include "tracker-resources.h"
#include "tracker-resources-glue.h"
+#include "tracker-resource-class.h"
+#include "tracker-resources-class-glue.h"
#include "tracker-search.h"
#include "tracker-search-glue.h"
#include "tracker-backup.h"
@@ -259,7 +264,9 @@ tracker_dbus_register_objects (TrackerConfig *config,
TrackerDBIndex *resources_index,
TrackerProcessor *processor)
{
- gpointer object;
+ gpointer object, resources;
+ GSList *event_sources = NULL;
+ TrackerDBResultSet *result_set;
g_return_val_if_fail (TRACKER_IS_CONFIG (config), FALSE);
g_return_val_if_fail (TRACKER_IS_LANGUAGE (language), FALSE);
@@ -290,6 +297,7 @@ tracker_dbus_register_objects (TrackerConfig *config,
g_critical ("Could not create TrackerResources object to register");
return FALSE;
}
+ resources = object;
dbus_register_object (connection,
gproxy,
@@ -329,6 +337,72 @@ tracker_dbus_register_objects (TrackerConfig *config,
/* Reverse list since we added objects at the top each time */
objects = g_slist_reverse (objects);
+ result_set = tracker_data_query_sparql ("SELECT ?class WHERE { ?class tracker:notify true }", NULL);
+
+ if (result_set) {
+ GStrv classes_to_signal;
+ guint ui, count = 0;
+
+ classes_to_signal = tracker_dbus_query_result_to_strv (result_set, 0, &count);
+
+ for (ui = 0; ui < count; ui++) {
+ const gchar *rdf_class = classes_to_signal[ui];
+ gchar *replaced;
+ gchar *path, *uri, *hash;
+
+ uri = g_strdup (rdf_class);
+
+ hash = strrchr (uri, '#');
+ if (hash == NULL) {
+ /* support ontologies whose namespace uri does not end in a hash, e.g. dc */
+ hash = strrchr (uri, '/');
+ }
+ if (hash == NULL) {
+ g_critical ("Unknown namespace of property %s", uri);
+ } else {
+ gchar *namespace_uri = g_strndup (uri, hash - uri + 1);
+ TrackerNamespace *namespace;
+
+ namespace = tracker_ontology_get_namespace_by_uri (namespace_uri);
+ if (namespace == NULL) {
+ g_critical ("Unknown namespace %s of property %s", namespace_uri, uri);
+ } else {
+ replaced = g_strdup_printf ("%s/%s", tracker_namespace_get_prefix (namespace), hash + 1);
+ }
+ g_free (namespace_uri);
+ }
+
+ path = g_strdup_printf (TRACKER_RESOURCES_CLASS_PATH,
+ replaced);
+
+ g_free (replaced);
+
+ /* Add a org.freedesktop.Tracker.Resources.Class */
+ object = tracker_resource_class_new (rdf_class);
+ if (!object) {
+ g_critical ("Could not create TrackerResourcesClass object to register");
+ return FALSE;
+ }
+
+ dbus_register_object (connection,
+ gproxy,
+ G_OBJECT (object),
+ &dbus_glib_tracker_resources_class_object_info,
+ path);
+ g_free (path);
+
+ /* TrackerResources takes over ownership and unrefs the gobjects too */
+ event_sources = g_slist_prepend (event_sources, g_object_ref (object));
+ objects = g_slist_prepend (objects, object);
+ }
+
+ g_strfreev (classes_to_signal);
+ g_object_unref (result_set);
+ }
+
+
+ tracker_resources_set_event_sources (resources, event_sources);
+
return TRUE;
}
@@ -491,6 +565,11 @@ tracker_dbus_indexer_get_proxy (void)
G_TYPE_STRING,
G_TYPE_BOOLEAN,
G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (proxy_for_indexer,
+ "EventHappened",
+ TRACKER_TYPE_EVENT_ARRAY,
+ G_TYPE_INVALID);
+
}
return proxy_for_indexer;
diff --git a/src/trackerd/tracker-resource-class.c b/src/trackerd/tracker-resource-class.c
new file mode 100644
index 0000000..93ca6d3
--- /dev/null
+++ b/src/trackerd/tracker-resource-class.c
@@ -0,0 +1,232 @@
+/* -*- 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 <string.h>
+
+#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 "tracker-dbus.h"
+#include "tracker-resource-class.h"
+#include "tracker-marshal.h"
+
+#define TRACKER_RESOURCE_CLASS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_RESOURCE_CLASS, TrackerResourceClassPrivate))
+
+typedef struct {
+ gchar *rdf_class;
+ GPtrArray *adds, *ups, *dels;
+} TrackerResourceClassPrivate;
+
+enum {
+ SUBJECTS_ADDED,
+ SUBJECTS_REMOVED,
+ SUBJECTS_CHANGED,
+ LAST_SIGNAL
+};
+
+static void tracker_resource_class_finalize (GObject *object);
+
+G_DEFINE_TYPE(TrackerResourceClass, tracker_resource_class, G_TYPE_OBJECT)
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static void
+tracker_resource_class_class_init (TrackerResourceClassClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = tracker_resource_class_finalize;
+
+ signals[SUBJECTS_ADDED] =
+ g_signal_new ("subjects-added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ tracker_marshal_VOID__BOXED,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRV);
+
+ signals[SUBJECTS_REMOVED] =
+ g_signal_new ("subjects-removed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ tracker_marshal_VOID__BOXED,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRV);
+
+ signals[SUBJECTS_CHANGED] =
+ g_signal_new ("subjects-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ tracker_marshal_VOID__BOXED,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRV);
+
+ g_type_class_add_private (object_class, sizeof (TrackerResourceClassPrivate));
+}
+
+static void
+tracker_resource_class_init (TrackerResourceClass *object)
+{
+}
+
+static void
+tracker_resource_class_finalize (GObject *object)
+{
+ TrackerResourceClassPrivate *priv;
+
+ priv = TRACKER_RESOURCE_CLASS_GET_PRIVATE (object);
+
+ /* Emit pending events */
+ tracker_resource_class_emit_events ((TrackerResourceClass *) object);
+
+ g_free (priv->rdf_class);
+
+ G_OBJECT_CLASS (tracker_resource_class_parent_class)->finalize (object);
+}
+
+TrackerResourceClass *
+tracker_resource_class_new (const gchar *rdf_class)
+{
+ TrackerResourceClass *object;
+ TrackerResourceClassPrivate *priv;
+
+ object = g_object_new (TRACKER_TYPE_RESOURCE_CLASS, NULL);
+
+ priv = TRACKER_RESOURCE_CLASS_GET_PRIVATE (object);
+
+ priv->rdf_class = g_strdup (rdf_class);
+
+ return object;
+}
+
+
+const gchar *
+tracker_resource_class_get_rdf_class (TrackerResourceClass *object)
+{
+ TrackerResourceClassPrivate *priv;
+
+ priv = TRACKER_RESOURCE_CLASS_GET_PRIVATE (object);
+
+ return priv->rdf_class;
+}
+
+void
+tracker_resource_class_add_event (TrackerResourceClass *object,
+ const gchar *uri,
+ TrackerDBusEventsType type)
+{
+ TrackerResourceClassPrivate *priv;
+
+ priv = TRACKER_RESOURCE_CLASS_GET_PRIVATE (object);
+
+ switch (type) {
+ case TRACKER_DBUS_EVENTS_TYPE_ADD:
+ if (!priv->adds)
+ priv->adds = g_ptr_array_new ();
+ g_ptr_array_add (priv->adds, g_strdup (uri));
+ break;
+ case TRACKER_DBUS_EVENTS_TYPE_UPDATE:
+ if (!priv->ups)
+ priv->ups = g_ptr_array_new ();
+ g_ptr_array_add (priv->ups, g_strdup (uri));
+ break;
+ case TRACKER_DBUS_EVENTS_TYPE_DELETE:
+ if (!priv->dels)
+ priv->dels = g_ptr_array_new ();
+ g_ptr_array_add (priv->dels, g_strdup (uri));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+emit_strings (TrackerResourceClass *object, gint signal_, GPtrArray *array)
+{
+ GStrv strings_to_emit;
+ guint i;
+
+ if (array->len > 0) {
+ strings_to_emit = (GStrv) g_malloc0 (sizeof (gchar *) * (array->len + 1));
+
+ for (i = 0; i < array->len; i++) {
+ strings_to_emit[i] = array->pdata [i];
+ }
+
+ g_signal_emit (object, signal_, 0, strings_to_emit);
+
+ /* Normal free, not a GStrv free, we free the strings later */
+ g_free (strings_to_emit);
+ }
+}
+
+static void
+free_array (GPtrArray *array)
+{
+ guint i;
+ for (i = 0; i < array->len; i++) {
+ g_free (array->pdata [i]);
+ }
+ g_ptr_array_free (array, TRUE);
+}
+
+void
+tracker_resource_class_emit_events (TrackerResourceClass *object)
+{
+ TrackerResourceClassPrivate *priv;
+
+ priv = TRACKER_RESOURCE_CLASS_GET_PRIVATE (object);
+
+ if (priv->adds) {
+ emit_strings (object, signals[SUBJECTS_ADDED], priv->adds);
+ free_array (priv->adds);
+ priv->adds = NULL;
+ }
+
+ if (priv->ups) {
+ emit_strings (object, signals[SUBJECTS_CHANGED], priv->ups);
+ free_array (priv->ups);
+ priv->ups = NULL;
+ }
+
+ if (priv->dels) {
+ emit_strings (object, signals[SUBJECTS_REMOVED], priv->dels);
+ free_array (priv->dels);
+ priv->dels = NULL;
+ }
+}
diff --git a/src/trackerd/tracker-resource-class.h b/src/trackerd/tracker-resource-class.h
new file mode 100644
index 0000000..0c8eb5f
--- /dev/null
+++ b/src/trackerd/tracker-resource-class.h
@@ -0,0 +1,65 @@
+/* -*- 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 __TRACKERD_RESOURCES_CLASS_H__
+#define __TRACKERD_RESOURCES_CLASS_H__
+
+#include <glib-object.h>
+#include <libtracker-common/tracker-dbus.h>
+
+#define TRACKER_RESOURCES_CLASS_SERVICE "org.freedesktop.Tracker"
+#define TRACKER_RESOURCES_CLASS_PATH "/org/freedesktop/Tracker/Resources/Classes/%s"
+#define TRACKER_RESOURCES_CLASS_INTERFACE "org.freedesktop.Tracker.Resources.Class"
+
+G_BEGIN_DECLS
+
+#define TRACKER_TYPE_RESOURCE_CLASS (tracker_resource_class_get_type ())
+#define TRACKER_RESOURCE_CLASS(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TRACKER_TYPE_RESOURCE_CLASS, TrackerResourceClass))
+#define TRACKER_RESOURCE_CLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_RESOURCE_CLASS, TrackerResourceClassClass))
+#define TRACKER_IS_RESOURCE_CLASS(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TRACKER_TYPE_RESOURCE_CLASS))
+#define TRACKER_IS_RESOURCE_CLASS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_RESOURCE_CLASS))
+#define TRACKER_RESOURCE_CLASS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TRACKER_TYPE_RESOURCE_CLASS, TrackerResourceClassClass))
+
+typedef struct TrackerResourceClass TrackerResourceClass;
+typedef struct TrackerResourceClassClass TrackerResourceClassClass;
+
+struct TrackerResourceClass {
+ GObject parent;
+};
+
+struct TrackerResourceClassClass {
+ GObjectClass parent;
+};
+
+GType tracker_resource_class_get_type (void);
+TrackerResourceClass *tracker_resource_class_new (const gchar *rdf_class);
+
+const gchar * tracker_resource_class_get_rdf_class (TrackerResourceClass *object);
+void tracker_resource_class_add_event (TrackerResourceClass *object,
+ const gchar *uri,
+ TrackerDBusEventsType type);
+void tracker_resource_class_emit_events (TrackerResourceClass *object);
+
+G_END_DECLS
+
+#endif /* __TRACKERD_RESOURCES_CLASS_H__ */
diff --git a/src/trackerd/tracker-resources.c b/src/trackerd/tracker-resources.c
index a822cd5..9f4676f 100644
--- a/src/trackerd/tracker-resources.c
+++ b/src/trackerd/tracker-resources.c
@@ -38,17 +38,111 @@
#include "tracker-dbus.h"
#include "tracker-marshal.h"
#include "tracker-resources.h"
+#include "tracker-resource-class.h"
G_DEFINE_TYPE(TrackerResources, tracker_resources, G_TYPE_OBJECT)
+#define TRACKER_RESOURCES_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_RESOURCES, TrackerResourcesPrivate))
+
+
+typedef struct {
+ GSList *event_sources;
+ DBusGProxy *indexer_proxy;
+} TrackerResourcesPrivate;
+
+static void
+free_event_sources (TrackerResourcesPrivate *priv)
+{
+ if (priv->event_sources) {
+ g_slist_foreach (priv->event_sources,
+ (GFunc) g_object_unref, NULL);
+ g_slist_free (priv->event_sources);
+
+ priv->event_sources = NULL;
+ }
+}
+
+static void
+tracker_resources_finalize (GObject *object)
+{
+ TrackerResourcesPrivate *priv;
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (object);
+
+ free_event_sources (priv);
+
+ g_object_unref (priv->indexer_proxy);
+
+ G_OBJECT_CLASS (tracker_resources_parent_class)->finalize (object);
+}
+
static void
tracker_resources_class_init (TrackerResourcesClass *klass)
{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = tracker_resources_finalize;
+
+ g_type_class_add_private (object_class, sizeof (TrackerResourcesPrivate));
+}
+
+
+static void
+event_happened_cb (DBusGProxy *proxy,
+ GPtrArray *events,
+ gpointer user_data)
+{
+ TrackerResources *object = user_data;
+ TrackerResourcesPrivate *priv;
+ GSList *event_sources, *l, *to_emit = NULL;
+ guint i;
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (object);
+
+ event_sources = priv->event_sources;
+
+ 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);
+ }
}
static void
tracker_resources_init (TrackerResources *object)
{
+ TrackerResourcesPrivate *priv;
+ DBusGProxy *proxy = tracker_dbus_indexer_get_proxy ();
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (object);
+
+ priv->indexer_proxy = g_object_ref (proxy);
+
+ dbus_g_proxy_connect_signal (proxy, "EventHappened",
+ G_CALLBACK (event_happened_cb),
+ object,
+ NULL);
+
}
TrackerResources *
@@ -261,3 +355,15 @@ tracker_resources_sparql_update (TrackerResources *self,
tracker_dbus_request_success (request_id);
}
+void
+tracker_resources_set_event_sources (TrackerResources *object,
+ GSList *event_sources)
+{
+ TrackerResourcesPrivate *priv;
+
+ priv = TRACKER_RESOURCES_GET_PRIVATE (object);
+
+ free_event_sources (priv);
+
+ priv->event_sources = event_sources;
+}
diff --git a/src/trackerd/tracker-resources.h b/src/trackerd/tracker-resources.h
index a673b62..cedc4d7 100644
--- a/src/trackerd/tracker-resources.h
+++ b/src/trackerd/tracker-resources.h
@@ -52,6 +52,11 @@ struct TrackerResourcesClass {
GType tracker_resources_get_type (void);
TrackerResources *tracker_resources_new (void);
+
+void tracker_resources_set_event_sources (TrackerResources *object,
+ GSList *event_sources);
+
+/* DBus methods */
void tracker_resources_insert (TrackerResources *self,
const gchar *subject,
const gchar *predicate,
@@ -77,6 +82,7 @@ void tracker_resources_sparql_update (TrackerResources *object,
DBusGMethodInvocation *context,
GError **error);
+
G_END_DECLS
#endif /* __TRACKERD_RESOURCES_H__ */
diff --git a/tests/tracker-indexer/Makefile.am b/tests/tracker-indexer/Makefile.am
index 1462ef6..7b65263 100644
--- a/tests/tracker-indexer/Makefile.am
+++ b/tests/tracker-indexer/Makefile.am
@@ -2,7 +2,8 @@ include $(top_srcdir)/Makefile.decl
noinst_PROGRAMS = $(TEST_PROGS)
-TEST_PROGS += tracker-metadata-utils
+TEST_PROGS += tracker-metadata-utils \
+ tracker-events
INCLUDES = \
-DTEST \
@@ -25,6 +26,7 @@ INCLUDES = \
tracker_metadata_utils_SOURCES = \
$(top_srcdir)/src/tracker-indexer/tracker-dbus.c \
+ $(top_srcdir)/src/tracker-indexer/tracker-events.c \
$(top_srcdir)/src/tracker-indexer/tracker-indexer.c \
$(top_srcdir)/src/tracker-indexer/tracker-indexer-module.c \
$(top_srcdir)/src/tracker-indexer/tracker-marshal-main.c \
@@ -49,3 +51,15 @@ tracker_metadata_utils_LDADD = \
$(GCOV_LIBS) \
$(RAPTOR_LIBS) \
$(GLIB2_LIBS)
+
+tracker_events_SOURCES = \
+ tracker-events-test.c \
+ $(top_srcdir)/src/tracker-indexer/tracker-events.c
+
+tracker_events_LDADD = \
+ $(top_builddir)/src/libtracker-common/libtracker-common.la \
+ $(DBUS_LIBS) \
+ $(GCOV_LIBS) \
+ $(GMODULE_LIBS) \
+ $(GTHREAD_LIBS) \
+ $(GLIB2_LIBS)
diff --git a/tests/tracker-indexer/tracker-events-test.c b/tests/tracker-indexer/tracker-events-test.c
new file mode 100644
index 0000000..605318d
--- /dev/null
+++ b/tests/tracker-indexer/tracker-events-test.c
@@ -0,0 +1,187 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia (urho konttori nokia com)
+ *
+ * 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.
+ */
+#include <glib.h>
+#include <glib-object.h>
+#include <libtracker-common/tracker-dbus.h>
+#include <tracker-events.h>
+
+
+#define EMAIL_CLASS "http://namespace1/nmo/Email"
+#define FEED_CLASS "http://namespace1/nmo/FeedMessage"
+#define CONTACT_CLASS "http://namespace2/nco/Contact"
+#define NON_SIGNAL_CLASS "http://namespace100/myapp/MyClass"
+
+static GPtrArray *types;
+
+static GStrv
+initialization_callback (void)
+{
+ gchar *klasses[] = {
+ EMAIL_CLASS,
+ FEED_CLASS,
+ CONTACT_CLASS,
+ NULL};
+
+ return g_strdupv (klasses);
+}
+
+static void
+test_events_empty (void)
+{
+ GPtrArray *events = NULL;
+
+ tracker_events_init (initialization_callback);
+
+ events = tracker_events_get_pending ();
+ g_assert (events == NULL);
+
+ tracker_events_reset ();
+
+ tracker_events_shutdown ();
+}
+
+static void
+test_events_reset (void)
+{
+ GPtrArray *events;
+
+ tracker_events_init (initialization_callback);
+
+ tracker_events_insert ("uri://1", EMAIL_CLASS, types,
+ TRACKER_DBUS_EVENTS_TYPE_ADD);
+
+ events = tracker_events_get_pending ();
+ g_assert_cmpint (events->len, ==, 1);
+
+ /* Try again without reset to ensure the data is
+ * still there
+ */
+ events = tracker_events_get_pending ();
+ g_assert_cmpint (events->len, ==, 1);
+
+ tracker_events_reset ();
+ tracker_events_shutdown ();
+}
+
+static void
+test_events_insertions (void)
+{
+ GPtrArray *events;
+
+ tracker_events_init (initialization_callback);
+
+ tracker_events_insert ("uri://1", EMAIL_CLASS, types,
+ TRACKER_DBUS_EVENTS_TYPE_ADD);
+
+ tracker_events_insert ("uri://2", EMAIL_CLASS, types,
+ TRACKER_DBUS_EVENTS_TYPE_UPDATE);
+
+ tracker_events_insert ("uri://3", EMAIL_CLASS, types,
+ TRACKER_DBUS_EVENTS_TYPE_DELETE);
+
+ events = tracker_events_get_pending ();
+ g_assert_cmpint (events->len, ==, 2);
+
+ /* Insert class we dont want to signal */
+ tracker_events_insert ("uri://x", NON_SIGNAL_CLASS, types,
+ TRACKER_DBUS_EVENTS_TYPE_DELETE);
+
+ events = tracker_events_get_pending ();
+ g_assert_cmpint (events->len, ==, 2);
+
+ tracker_events_reset ();
+ tracker_events_shutdown ();
+}
+
+static void
+test_events_no_allows (void)
+{
+ gint i;
+
+ tracker_events_init (NULL);
+ g_assert (tracker_events_get_pending () == NULL);
+ tracker_events_reset ();
+ g_assert (tracker_events_get_pending () == NULL);
+
+ for (i = 0; i < 10; i++) {
+ tracker_events_insert (g_strdup_printf ("uri://%d", i),
+ EMAIL_CLASS, types,
+ TRACKER_DBUS_EVENTS_TYPE_ADD);
+ }
+
+ g_assert (tracker_events_get_pending () == NULL);
+
+ tracker_events_shutdown ();
+}
+
+static void
+test_events_lifecycle (void)
+{
+ /* Shutdown - no init */
+ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR)) {
+ tracker_events_shutdown ();
+ }
+ g_test_trap_assert_stderr ("*tracker_events already shutdown*");
+
+ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR)) {
+ tracker_events_get_pending ();
+ }
+ g_test_trap_assert_stderr ("*assertion `private != NULL' failed*");
+
+ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR)) {
+ tracker_events_reset ();
+ }
+ g_test_trap_assert_stderr ("*assertion `private != NULL' failed*");
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ GStrv types_s;
+ guint i;
+
+ g_type_init ();
+ g_thread_init (NULL);
+ g_test_init (&argc, &argv, NULL);
+
+ types = g_ptr_array_new ();
+
+ types_s = initialization_callback ();
+
+ for (i = 0; types_s[i]; i++) {
+ g_ptr_array_add (types, types_s[i]);
+ }
+
+ g_test_add_func ("/tracker/tracker-indexer/tracker-events/empty",
+ test_events_empty);
+ g_test_add_func ("/tracker/tracker-indexer/tracker-events/reset",
+ test_events_reset);
+ g_test_add_func ("/tracker/tracker-indexer/tracker-events/insertions",
+ test_events_insertions);
+ g_test_add_func ("/tracker/tracker-indexer/tracker-events/no-allows",
+ test_events_no_allows);
+ g_test_add_func ("/tracker/tracker-indexer/tracker-events/lifecycle",
+ test_events_lifecycle);
+
+ g_ptr_array_free (types, TRUE);
+
+ return g_test_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]