diff options
-rw-r--r-- | src/tracker/grl-tracker-source-notif.c | 739 | ||||
-rw-r--r-- | src/tracker/grl-tracker-source-notif.h | 3 | ||||
-rw-r--r-- | src/tracker/grl-tracker.c | 1 |
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; |