summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tracker/grl-tracker-source-notif.c739
-rw-r--r--src/tracker/grl-tracker-source-notif.h3
-rw-r--r--src/tracker/grl-tracker.c1
3 files changed, 273 insertions, 470 deletions
diff --git a/src/tracker/grl-tracker-source-notif.c b/src/tracker/grl-tracker-source-notif.c
index beabf6b..4b35e0e 100644
--- a/src/tracker/grl-tracker-source-notif.c
+++ b/src/tracker/grl-tracker-source-notif.c
@@ -1,11 +1,13 @@
/*
* Copyright (C) 2011-2012 Igalia S.L.
* Copyright (C) 2011 Intel Corporation.
+ * Copyright (C) 2015 Collabora Ltd.
*
* Contact: Iago Toral Quiroga <itoral@igalia.com>
*
* Authors: Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com>
* Juan A. Suarez Romero <jasuarez@igalia.com>
+ * Xavier Claessens <xavier.claessens@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -31,592 +33,395 @@
#include "grl-tracker-source-priv.h"
#include "grl-tracker-utils.h"
-/* --------- Logging -------- */
-
#define GRL_LOG_DOMAIN_DEFAULT tracker_notif_log_domain
GRL_LOG_DOMAIN_STATIC(tracker_notif_log_domain);
-/* ------- Definitions ------- */
-
-#define TRACKER_MEDIA_ITEM \
- "SELECT rdf:type(?urn) tracker:id(?urn) nie:dataSource(?urn) " \
- "WHERE { ?urn a nfo:FileDataObject . " \
- "FILTER (tracker:id(?urn) IN (%s)) }"
+#define GRL_TRACKER_TYPE_SOURCE_NOTIFY grl_tracker_source_notify_get_type ()
+G_DECLARE_FINAL_TYPE (GrlTrackerSourceNotify, grl_tracker_source_notify, GRL_TRACKER, SOURCE_NOTIFY, GObject)
-/**/
+struct _GrlTrackerSourceNotify {
+ GObject parent;
-typedef struct {
- /* tables of items for which we know the source */
- GHashTable *inserted_items;
- GHashTable *deleted_items;
- GHashTable *updated_items;
+ GDBusConnection *conn;
- /* table of items for which we don't know the source */
- GHashTable *orphan_items;
+ /* subject id -> GrlSourceChangeType */
+ GHashTable *updates;
+ /* Number of updates being queried */
+ guint updates_count;
+ /* subject id -> MediaInfo (NULL means it's being queried) */
+ GHashTable *cache;
- /* List of new/old sources */
- GList *new_sources;
- GList *old_sources;
+ guint graph_updated_id;
+ gint rdf_type_id;
+ gint nfo_filedataobject_id;
+};
- /* Convenient stuff (for tracker/own callbacks...) */
- TrackerSparqlCursor *cursor;
- gboolean in_use;
- GrlSourceChangeType change_type;
-} tracker_evt_update_t;
+static void grl_tracker_source_notify_initable_iface_init (GInitableIface *iface);
-/**/
+G_DEFINE_TYPE_WITH_CODE (GrlTrackerSourceNotify, grl_tracker_source_notify, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, grl_tracker_source_notify_initable_iface_init))
-static guint tracker_dbus_signal_id = 0;
+static GrlTrackerSourceNotify *singleton = NULL;
-/**/
-static tracker_evt_update_t *
-tracker_evt_update_new (void)
+typedef struct {
+ gchar *type;
+ gchar *datasource;
+ gchar *url;
+} MediaInfo;
+
+static MediaInfo *
+media_info_new (const gchar *type,
+ const gchar *datasource,
+ const gchar *url)
{
- tracker_evt_update_t *evt = g_slice_new0 (tracker_evt_update_t);
+ MediaInfo *info;
- evt->inserted_items = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
- evt->deleted_items = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
- evt->updated_items = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
+ info = g_slice_new (MediaInfo);
+ info->type = g_strdup (type);
+ info->datasource = g_strdup (datasource);
+ info->url = g_strdup (url);
- evt->orphan_items = g_hash_table_new (g_direct_hash, g_direct_equal);
-
- return evt;
+ return info;
}
static void
-tracker_evt_update_free (tracker_evt_update_t *evt)
+media_info_free (MediaInfo *info)
{
- if (!evt)
+ if (info == NULL)
return;
- GRL_DEBUG ("free evt=%p", evt);
-
- g_hash_table_destroy (evt->inserted_items);
- g_hash_table_destroy (evt->deleted_items);
- g_hash_table_destroy (evt->updated_items);
-
- g_hash_table_destroy (evt->orphan_items);
-
- g_list_free (evt->new_sources);
- g_list_free (evt->old_sources);
+ g_free (info->type);
+ g_free (info->datasource);
+ g_free (info->url);
- g_slice_free (tracker_evt_update_t, evt);
+ g_slice_free (MediaInfo, info);
}
static void
-tracker_evt_update_source_add (tracker_evt_update_t *evt,
- const gchar *id,
- const gchar *source_name)
+notify_change (GrlTrackerSourceNotify *self,
+ gint id,
+ GrlSourceChangeType change_type)
{
- GrlTrackerSource *source;
- GrlTrackerSourcePriv *priv;
-
- source = g_hash_table_lookup (grl_tracker_source_sources_modified, id);
- if (!source) {
- source = g_object_new (GRL_TRACKER_SOURCE_TYPE,
- "source-id", id,
- "source-name", source_name,
- "source-desc", GRL_TRACKER_SOURCE_DESC,
- "tracker-connection", grl_tracker_connection,
- "tracker-datasource", id,
- NULL);
- g_hash_table_insert (grl_tracker_source_sources_modified,
- (gpointer) grl_tracker_source_get_tracker_source (source),
- g_object_ref (source));
- } else {
- g_object_ref (source);
- }
+ GrlTrackerSource *source = NULL;
+ gchar *id_str = NULL;
+ GrlMedia *media = NULL;
+ MediaInfo *info;
- priv = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
- priv->state = GRL_TRACKER_SOURCE_STATE_INSERTING;
- priv->notification_ref++;
+ info = g_hash_table_lookup (self->cache, GINT_TO_POINTER (id));
+ if (info == NULL)
+ goto out;
- evt->new_sources = g_list_append (evt->new_sources, source);
+ if (!grl_tracker_per_device_source)
+ source = grl_tracker_source_find ("");
- GRL_DEBUG ("Preadd source p=%p name=%s id=%s count=%u",
- source, source_name, id, priv->notification_ref);
+ if (!source && info->datasource)
+ source = grl_tracker_source_find (info->datasource);
- g_object_unref (source);
-}
+ if (!source || !GRL_IS_TRACKER_SOURCE (source) ||
+ !grl_tracker_source_can_notify (source))
+ goto out;
-static void
-tracker_evt_update_source_del (tracker_evt_update_t *evt,
- GrlTrackerSource *source)
-{
- GrlTrackerSourcePriv *priv = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
+ id_str = g_strdup_printf ("%i", id);
+ media = grl_tracker_build_grilo_media (info->type);
+ grl_media_set_id (media, id_str);
+ grl_media_set_url (media, info->url);
- priv->notification_ref++;
- priv->state = GRL_TRACKER_SOURCE_STATE_DELETING;
+ GRL_DEBUG ("Notify: source=%s, change_type=%d, url=%s",
+ grl_source_get_name (GRL_SOURCE (source)),
+ change_type, info->url);
- evt->old_sources = g_list_append (evt->old_sources, source);
+ grl_source_notify_change (GRL_SOURCE (source), media, change_type, FALSE);
- GRL_DEBUG ("Predel source p=%p name=%s id=%s count=%u", source,
- grl_source_get_name (GRL_SOURCE (source)),
- grl_tracker_source_get_tracker_source (source),
- priv->notification_ref);
+out:
+ if (change_type == GRL_CONTENT_REMOVED)
+ g_hash_table_remove (self->cache, GINT_TO_POINTER (id));
+ g_clear_object (&media);
+ g_free (id_str);
}
static void
-tracker_evt_postupdate_sources (tracker_evt_update_t *evt)
+update_query_done (GrlTrackerSourceNotify *self)
{
- GList *source;
+ GHashTableIter iter;
+ gpointer key, value;
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
+ /* If more updates came while we were querying, wait for them so we can
+ * aggregate notifications. */
+ self->updates_count--;
+ if (self->updates_count > 0)
+ return;
- source = evt->old_sources;
- while (source != NULL) {
- grl_tracker_del_source (GRL_TRACKER_SOURCE (source->data));
- source = source->next;
- }
+ g_hash_table_iter_init (&iter, self->updates);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ gint id = GPOINTER_TO_INT (key);
+ GrlSourceChangeType change_type = GPOINTER_TO_INT (value);
- source = evt->new_sources;
- while (source != NULL) {
- grl_tracker_add_source (GRL_TRACKER_SOURCE (source->data));
- source = source->next;
+ notify_change (self, id, change_type);
}
- tracker_evt_update_free (evt);
+ g_hash_table_remove_all (self->updates);
}
static void
-tracker_evt_update_orphan_item_cb (GObject *object,
- GAsyncResult *result,
- tracker_evt_update_t *evt)
+update_cursor_next_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- guint id;
- const gchar *type, *datasource;
- GrlTrackerSource *source = NULL;
+ GrlTrackerSourceNotify *self = user_data;
+ TrackerSparqlCursor *cursor = (TrackerSparqlCursor *) source_object;
+ const gchar *type;
+ const gchar *datasource;
+ const gchar *url;
+ gint id;
GError *error = NULL;
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
-
- if (!tracker_sparql_cursor_next_finish (evt->cursor, result, &error)) {
+ if (!tracker_sparql_cursor_next_finish (cursor, result, &error)) {
if (error != NULL) {
- GRL_DEBUG ("\terror in parsing : %s", error->message);
- g_error_free (error);
- } else {
- GRL_DEBUG ("\tend of parsing...");
+ GRL_WARNING ("Error: %s", error->message);
+ g_clear_error (&error);
}
-
- g_clear_object (&evt->cursor);
-
- if (grl_tracker_per_device_source) {
- /* Once all items have been processed, add new sources and we're
- done. */
- tracker_evt_postupdate_sources (evt);
- } else {
- tracker_evt_update_free (evt);
- }
-
+ update_query_done (self);
+ g_object_unref (self);
return;
}
- type = tracker_sparql_cursor_get_string (evt->cursor, 0, NULL);
- id = tracker_sparql_cursor_get_integer (evt->cursor, 1);
- datasource = tracker_sparql_cursor_get_string (evt->cursor, 2, NULL);
+ type = tracker_sparql_cursor_get_string (cursor, 0, NULL);
+ id = tracker_sparql_cursor_get_integer (cursor, 1);
+ datasource = tracker_sparql_cursor_get_string (cursor, 2, NULL);
+ url = tracker_sparql_cursor_get_string (cursor, 3, NULL);
- GRL_DEBUG ("\tOrphan item: id=%u datasource=%s", id, datasource);
+ g_hash_table_insert (self->cache,
+ GINT_TO_POINTER (id),
+ media_info_new (type, datasource, url));
- if (!grl_tracker_per_device_source)
- source = grl_tracker_source_find ("");
-
- if (!source && datasource)
- source = grl_tracker_source_find (datasource);
-
- if (source && GRL_IS_TRACKER_SOURCE (source)) {
- GrlMedia *media;
-
- GRL_DEBUG (" \tAdding to cache id=%u", id);
- grl_tracker_source_cache_add_item (grl_tracker_item_cache, id, source);
-
- if (grl_tracker_source_can_notify (source)) {
- media = grl_tracker_build_grilo_media (type);
- if (media) {
- gchar *str_id = g_strdup_printf ("%i", id);
- gint change_type =
- GPOINTER_TO_INT (g_hash_table_lookup (evt->orphan_items,
- GSIZE_TO_POINTER (id)));
-
- grl_media_set_id (media, str_id);
- g_free (str_id);
-
- GRL_DEBUG ("\tNotify id=%u source=%s p=%p", id,
- grl_source_get_name (GRL_SOURCE (source)),
- source);
- grl_source_notify_change (GRL_SOURCE (source),
- media, change_type, FALSE);
-
- g_object_unref (media);
- }
- }
- }
-
- tracker_sparql_cursor_next_async (evt->cursor, NULL,
- (GAsyncReadyCallback) tracker_evt_update_orphan_item_cb,
- (gpointer) evt);
+ tracker_sparql_cursor_next_async (cursor,
+ NULL,
+ update_cursor_next_cb,
+ self);
}
static void
-tracker_evt_update_orphans_cb (GObject *object,
- GAsyncResult *result,
- tracker_evt_update_t *evt)
+update_query_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
+ GrlTrackerSourceNotify *self = user_data;
+ TrackerSparqlCursor *cursor;
GError *error = NULL;
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
-
- evt->cursor = tracker_sparql_connection_query_finish (grl_tracker_connection,
- result, &error);
-
- if (error != NULL) {
- GRL_WARNING ("Could not execute sparql query: %s", error->message);
-
- g_error_free (error);
- tracker_evt_postupdate_sources (evt);
+ cursor = tracker_sparql_connection_query_finish (grl_tracker_connection,
+ result,
+ &error);
+ if (cursor == NULL) {
+ if (error != NULL) {
+ GRL_WARNING ("Error: %s", error->message);
+ g_clear_error (&error);
+ }
+ update_query_done (self);
+ g_object_unref (self);
return;
}
- tracker_sparql_cursor_next_async (evt->cursor, NULL,
- (GAsyncReadyCallback) tracker_evt_update_orphan_item_cb,
- (gpointer) evt);
+ tracker_sparql_cursor_next_async (cursor,
+ NULL,
+ update_cursor_next_cb,
+ self);
}
+#define CHANGED GINT_TO_POINTER (GRL_CONTENT_CHANGED)
+#define ADDED GINT_TO_POINTER (GRL_CONTENT_ADDED)
+#define REMOVED GINT_TO_POINTER (GRL_CONTENT_REMOVED)
+
static void
-tracker_evt_update_orphans (tracker_evt_update_t *evt)
+graph_updated_cb (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+
{
- gboolean first = TRUE;
- GString *request_str;
- GHashTableIter iter;
- gpointer key, value;
- GList *source, *sources;
+ GrlTrackerSourceNotify *self = user_data;
+ const gchar *class_name;
+ GVariantIter *iter1, *iter2;
+ gint graph, subject, predicate, object;
+ GString *query;
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
+ g_variant_get (parameters, "(&sa(iiii)a(iiii))", &class_name, &iter1, &iter2);
- if (g_hash_table_size (evt->orphan_items) < 1) {
- tracker_evt_postupdate_sources (evt);
- return;
+ GRL_DEBUG ("Tracker update event for class=%s ins=%"G_GSIZE_FORMAT" del=%"G_GSIZE_FORMAT,
+ class_name,
+ g_variant_iter_n_children (iter2),
+ g_variant_iter_n_children (iter1));
+
+ query = g_string_new (NULL);
+
+ /* DELETE */
+ while (g_variant_iter_loop (iter1, "(iiii)", &graph, &subject, &predicate, &object)) {
+ gpointer key = GINT_TO_POINTER (subject);
+
+ /* If a rdf:type is removed, it probably means everything is going to be
+ * removed. The media has been deleted. If some other property is deleted
+ * it means the media already existed but changed.
+ */
+
+ if (predicate == self->rdf_type_id && object == self->nfo_filedataobject_id) {
+ g_hash_table_insert (self->updates, key, REMOVED);
+ } else if (g_hash_table_lookup (self->updates, key) != REMOVED) {
+ g_hash_table_insert (self->updates, key, CHANGED);
+ }
}
- sources = grl_registry_get_sources (grl_registry_get_default (),
- FALSE);
+ /* UPDATE */
+ while (g_variant_iter_loop (iter2, "(iiii)", &graph, &subject, &predicate, &object)) {
+ gpointer key = GINT_TO_POINTER (subject);
- request_str = g_string_new ("");
+ /* If a rdf:type is added it means it's a new media, otherwise it's an
+ * update of an existing media
+ */
- g_hash_table_iter_init (&iter, evt->orphan_items);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- guint id = GPOINTER_TO_UINT (key);
- GrlSourceChangeType change_type = GPOINTER_TO_INT (value);
+ if (predicate == self->rdf_type_id && object == self->nfo_filedataobject_id) {
+ g_hash_table_insert (self->updates, key, ADDED);
+ } else if (g_hash_table_lookup (self->updates, key) != ADDED) {
+ g_hash_table_insert (self->updates, key, CHANGED);
+ }
- if (change_type != GRL_CONTENT_REMOVED) {
- if (first) {
- g_string_append_printf (request_str, "%u", id);
- first = FALSE;
- }
- else {
- g_string_append_printf (request_str, ", %u", id);
- }
- } else {
- /* Notify all sources that a media been removed */
- source = sources;
- while (source != NULL) {
- if (GRL_IS_TRACKER_SOURCE (source->data)) {
- GRL_DEBUG ("\tNotify id=%u source=%s p=%p", id,
- grl_source_get_name (GRL_SOURCE (source->data)),
- source->data);
- if (grl_tracker_source_can_notify (GRL_TRACKER_SOURCE (source->data))) {
- GrlMedia *media = grl_media_new ();
- gchar *str_id = g_strdup_printf ("%u", id);
-
- grl_media_set_id (media, str_id);
- g_free (str_id);
-
- grl_source_notify_change (GRL_SOURCE (source->data),
- media,
- GRL_CONTENT_REMOVED,
- FALSE);
- g_object_unref (media);
- }
- }
- source = source->next;
- }
+ /* If we don't yet have info about this subject query it and add NULL in
+ * the table so we won't query it twice. */
+ if (!g_hash_table_contains (self->cache, key)) {
+ g_string_append_printf (query, "%d,", subject);
+ g_hash_table_insert (self->cache, key, NULL);
}
}
- if (request_str->len > 0) {
- gchar *sparql_final = g_strdup_printf (TRACKER_MEDIA_ITEM, request_str->str);
+ self->updates_count++;
+
+ if (query->len > 0) {
+ /* Remove trailing coma */
+ g_string_truncate (query, query->len - 1);
- GRL_DEBUG ("\trequest : '%s'", sparql_final);
+ g_string_prepend (query,
+ "SELECT rdf:type(?urn) tracker:id(?urn) nie:dataSource(?urn) nie:url(?urn) "
+ "WHERE { ?urn a nfo:FileDataObject . "
+ "FILTER (tracker:id(?urn) IN (");
+ g_string_append (query, "))}");
+ GRL_DEBUG ("Query: %s", query->str);
tracker_sparql_connection_query_async (grl_tracker_connection,
- sparql_final,
+ query->str,
NULL,
- (GAsyncReadyCallback) tracker_evt_update_orphans_cb,
- evt);
-
- g_free (sparql_final);
+ update_query_cb,
+ g_object_ref (self));
} else {
- tracker_evt_postupdate_sources (evt);
+ update_query_done (self);
}
- g_string_free (request_str, TRUE);
+ g_variant_iter_free (iter1);
+ g_variant_iter_free (iter2);
+ g_string_free (query, TRUE);
}
-static void
-tracker_evt_update_items_cb (gpointer key,
- gpointer value,
- tracker_evt_update_t *evt)
+static gboolean
+grl_tracker_source_notify_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
{
- guint id = GPOINTER_TO_INT (key);
- gchar *str_id;
- GrlTrackerSource *source = (GrlTrackerSource *) value;
- GrlMedia *media;
-
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
-
- g_assert (source != NULL);
-
- if (!grl_tracker_source_can_notify (source)) {
- GRL_DEBUG ("\tno notification for source %s...",
- grl_source_get_name (GRL_SOURCE (source)));
- return;
+ GrlTrackerSourceNotify *self = GRL_TRACKER_SOURCE_NOTIFY (initable);
+ TrackerSparqlCursor *cursor;
+
+ self->conn = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, error);
+ if (self->conn == NULL)
+ return FALSE;
+
+ self->graph_updated_id = g_dbus_connection_signal_subscribe (
+ self->conn,
+ TRACKER_DBUS_SERVICE,
+ TRACKER_DBUS_INTERFACE_RESOURCES,
+ "GraphUpdated",
+ TRACKER_DBUS_OBJECT_RESOURCES,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ graph_updated_cb,
+ self, NULL);
+
+ /* Query tracker to know the id of the rdf:type predicate so we can easily
+ * identify them in graph_updated_cb(). */
+ cursor = tracker_sparql_connection_query (grl_tracker_connection,
+ "select tracker:id(rdf:type) tracker:id(nfo:FileDataObject) {}",
+ NULL, error);
+ if (cursor == NULL)
+ return FALSE;
+
+ if (!tracker_sparql_cursor_next (cursor, NULL, error)) {
+ g_object_unref (cursor);
+ return FALSE;
}
- media = grl_media_new ();
- str_id = g_strdup_printf ("%i", id);
- grl_media_set_id (media, str_id);
- g_free (str_id);
+ self->rdf_type_id = tracker_sparql_cursor_get_integer (cursor, 0);
+ self->nfo_filedataobject_id = tracker_sparql_cursor_get_integer (cursor, 1);
- GRL_DEBUG ("\tNotify id=%u source=%s", id,
- grl_source_get_name (GRL_SOURCE (source)));
- grl_source_notify_change (GRL_SOURCE (source), media, evt->change_type, FALSE);
+ g_object_unref (cursor);
- g_object_unref (media);
-}
-
-static void
-tracker_evt_update_items (tracker_evt_update_t *evt)
-{
- evt->change_type = GRL_CONTENT_REMOVED;
- g_hash_table_foreach (evt->deleted_items,
- (GHFunc) tracker_evt_update_items_cb, evt);
- evt->change_type = GRL_CONTENT_ADDED;
- g_hash_table_foreach (evt->inserted_items,
- (GHFunc) tracker_evt_update_items_cb, evt);
- evt->change_type = GRL_CONTENT_CHANGED;
- g_hash_table_foreach (evt->updated_items,
- (GHFunc) tracker_evt_update_items_cb, evt);
+ return TRUE;
}
static void
-tracker_evt_preupdate_sources_item_cb (GObject *object,
- GAsyncResult *result,
- tracker_evt_update_t *evt)
+grl_tracker_source_notify_finalize (GObject *object)
{
- const gchar *type, *datasource, *uri, *datasource_name;
- gboolean source_available = FALSE;
- GrlTrackerSource *source;
- GError *error = NULL;
-
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
-
- if (!tracker_sparql_cursor_next_finish (evt->cursor, result, &error)) {
- if (error != NULL) {
- GRL_DEBUG ("\terror in parsing : %s", error->message);
- g_error_free (error);
- } else {
- GRL_DEBUG ("\tend of parsing... start notifying sources");
- }
+ GrlTrackerSourceNotify *self = GRL_TRACKER_SOURCE_NOTIFY (object);
- g_clear_object (&evt->cursor);
+ if (self->conn && self->graph_updated_id)
+ g_dbus_connection_signal_unsubscribe (self->conn, self->graph_updated_id);
- /* Once all sources have been preupdated, start items
- updates. */
- tracker_evt_update_items (evt);
- tracker_evt_update_orphans (evt);
+ g_clear_object (&self->conn);
+ g_clear_pointer (&self->updates, g_hash_table_unref);
+ g_clear_pointer (&self->cache, g_hash_table_unref);
- return;
- }
-
- type = tracker_sparql_cursor_get_string (evt->cursor, 0, NULL);
- datasource = tracker_sparql_cursor_get_string (evt->cursor, 1, NULL);
- datasource_name = tracker_sparql_cursor_get_string (evt->cursor, 2, NULL);
- uri = tracker_sparql_cursor_get_string (evt->cursor, 3, NULL);
- if (tracker_sparql_cursor_is_bound (evt->cursor, 4))
- source_available = tracker_sparql_cursor_get_boolean (evt->cursor, 4);
-
- source = grl_tracker_source_find (datasource);
-
- GRL_DEBUG ("\tdatasource=%s uri=%s available=%i source=%p",
- datasource, uri, source_available, source);
-
- if (source_available) {
- if (source == NULL) {
- gchar *source_name = grl_tracker_get_source_name (type, uri, datasource,
- datasource_name);
- /* Defer source creation until we have processed all sources */
- if (source_name) {
- tracker_evt_update_source_add (evt, datasource, source_name);
- g_free (source_name);
- }
- } else {
- GRL_DEBUG ("\tChanges on source %p / %s", source, datasource);
- }
- } else if (!source_available && source != NULL) {
- tracker_evt_update_source_del (evt, GRL_TRACKER_SOURCE (source));
- }
-
- tracker_sparql_cursor_next_async (evt->cursor, NULL,
- (GAsyncReadyCallback) tracker_evt_preupdate_sources_item_cb,
- (gpointer) evt);
+ G_OBJECT_CLASS (grl_tracker_source_notify_parent_class)->finalize (object);
}
static void
-tracker_evt_preupdate_sources_cb (GObject *object,
- GAsyncResult *result,
- tracker_evt_update_t *evt)
+grl_tracker_source_notify_class_init (GrlTrackerSourceNotifyClass *klass)
{
- GError *error = NULL;
-
- GRL_DEBUG ("%s: evt=%p", __FUNCTION__, evt);
-
- evt->cursor = tracker_sparql_connection_query_finish (grl_tracker_connection,
- result, &error);
+ GObjectClass *object_class = (GObjectClass *) klass;
- if (error != NULL) {
- GRL_WARNING ("\tCannot handle datasource request : %s", error->message);
-
- g_error_free (error);
-
- tracker_evt_update_items (evt);
- tracker_evt_update_orphans (evt);
- return;
- }
-
- tracker_sparql_cursor_next_async (evt->cursor, NULL,
- (GAsyncReadyCallback) tracker_evt_preupdate_sources_item_cb,
- (gpointer) evt);
+ GRL_LOG_DOMAIN_INIT (tracker_notif_log_domain, "tracker-notif");
+ object_class->finalize = grl_tracker_source_notify_finalize;
}
static void
-tracker_evt_preupdate_sources (tracker_evt_update_t *evt)
+grl_tracker_source_notify_init (GrlTrackerSourceNotify *self)
{
- tracker_sparql_connection_query_async (grl_tracker_connection,
- TRACKER_DATASOURCES_REQUEST,
- NULL,
- (GAsyncReadyCallback) tracker_evt_preupdate_sources_cb,
- evt);
+ self->updates = g_hash_table_new (NULL, NULL);
+ self->cache = g_hash_table_new_full (NULL, NULL,
+ NULL,
+ (GDestroyNotify) media_info_free);
}
static void
-tracker_dbus_signal_cb (GDBusConnection *connection,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters,
- gpointer user_data)
-
+grl_tracker_source_notify_initable_iface_init (GInitableIface *iface)
{
- gchar *class_name;
- gint graph = 0, subject = 0, predicate = 0, object = 0;
- GVariantIter *iter1, *iter2;
- tracker_evt_update_t *evt = tracker_evt_update_new ();
-
- g_variant_get (parameters, "(&sa(iiii)a(iiii))", &class_name, &iter1, &iter2);
-
- GRL_DEBUG ("Tracker update event for class=%s ins=%lu del=%lu evt=%p",
- class_name,
- (unsigned long) g_variant_iter_n_children (iter1),
- (unsigned long) g_variant_iter_n_children (iter2),
- evt);
-
- /* Process deleted items */
- while (g_variant_iter_loop (iter1, "(iiii)", &graph,
- &subject, &predicate, &object)) {
- gpointer psubject = GSIZE_TO_POINTER (subject);
- GrlTrackerSource *source =
- grl_tracker_source_cache_get_source (grl_tracker_item_cache, subject);
-
- /* GRL_DEBUG ("\tdelete=> subject=%i", subject); */
-
- if (source) {
- g_hash_table_insert (evt->deleted_items, psubject,
- g_object_ref (source));
- } else {
- g_hash_table_insert (evt->orphan_items, psubject,
- GSIZE_TO_POINTER (GRL_CONTENT_REMOVED));
- }
- }
-
- while (g_variant_iter_loop (iter2, "(iiii)", &graph,
- &subject, &predicate, &object)) {
- gpointer psubject = GSIZE_TO_POINTER (subject);
- GrlTrackerSource *source =
- grl_tracker_source_cache_get_source (grl_tracker_item_cache, subject);
-
- /* GRL_DEBUG ("\tinsert=> subject=%i", subject); */
-
- if (source) {
- /* Removed & inserted items are probably just renamed items... */
- if (g_hash_table_lookup (evt->deleted_items, psubject)) {
- g_hash_table_remove (evt->deleted_items, psubject);
- g_hash_table_insert (evt->updated_items, psubject,
- g_object_ref (source));
- } else if (!g_hash_table_lookup (evt->updated_items, psubject)) {
- g_hash_table_insert (evt->inserted_items, psubject,
- g_object_ref (source));
- }
- } else {
- gpointer state;
-
- if (g_hash_table_lookup_extended (evt->orphan_items, psubject,
- NULL, &state) &&
- (GPOINTER_TO_INT (state) == GRL_CONTENT_REMOVED)) {
- g_hash_table_insert (evt->orphan_items, psubject,
- GSIZE_TO_POINTER (GRL_CONTENT_CHANGED));
- } else {
- g_hash_table_insert (evt->orphan_items, psubject,
- GSIZE_TO_POINTER (GRL_CONTENT_ADDED));
- }
- }
- }
-
- g_variant_iter_free (iter1);
- g_variant_iter_free (iter2);
-
- GRL_DEBUG ("\tinserted=%i deleted=%i updated=%i orphan=%i",
- g_hash_table_size (evt->inserted_items),
- g_hash_table_size (evt->deleted_items),
- g_hash_table_size (evt->updated_items),
- g_hash_table_size (evt->orphan_items));
-
- if (grl_tracker_per_device_source) {
- tracker_evt_preupdate_sources (evt);
- } else {
- tracker_evt_update_items (evt);
- tracker_evt_update_orphans (evt);
- }
+ iface->init = grl_tracker_source_notify_initable_init;
}
void
grl_tracker_source_dbus_start_watch (void)
{
- GDBusConnection *connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
-
- tracker_dbus_signal_id = g_dbus_connection_signal_subscribe (connection,
- TRACKER_DBUS_SERVICE,
- TRACKER_DBUS_INTERFACE_RESOURCES,
- "GraphUpdated",
- TRACKER_DBUS_OBJECT_RESOURCES,
- NULL,
- G_DBUS_SIGNAL_FLAGS_NONE,
- tracker_dbus_signal_cb,
- NULL,
- NULL);
+ GError *error = NULL;
+
+ if (singleton != NULL)
+ return;
+
+ singleton = g_initable_new (GRL_TRACKER_TYPE_SOURCE_NOTIFY, NULL, &error, NULL);
+ if (singleton == NULL) {
+ GRL_WARNING ("Error: %s", error->message);
+ g_clear_error (&error);
+ }
}
void
-grl_tracker_source_init_notifs (void)
+grl_tracker_source_dbus_stop_watch (void)
{
- GRL_LOG_DOMAIN_INIT (tracker_notif_log_domain, "tracker-notif");
+ g_clear_object (&singleton);
}
diff --git a/src/tracker/grl-tracker-source-notif.h b/src/tracker/grl-tracker-source-notif.h
index 8ba3e3d..5646c15 100644
--- a/src/tracker/grl-tracker-source-notif.h
+++ b/src/tracker/grl-tracker-source-notif.h
@@ -50,7 +50,6 @@
/**/
void grl_tracker_source_dbus_start_watch (void);
-
-void grl_tracker_source_init_notifs (void);
+void grl_tracker_source_dbus_stop_watch (void);
#endif /* _GRL_TRACKER_SOURCE_NOTIF_H_ */
diff --git a/src/tracker/grl-tracker.c b/src/tracker/grl-tracker.c
index e3a1a7b..0eee368 100644
--- a/src/tracker/grl-tracker.c
+++ b/src/tracker/grl-tracker.c
@@ -228,7 +228,6 @@ grl_tracker_plugin_init (GrlRegistry *registry,
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- grl_tracker_source_init_notifs ();
grl_tracker_source_init_requests ();
grl_tracker_plugin = plugin;