[grilo-plugins] tracker: rewrite notification code
- From: Xavier Claessens <xclaesse src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [grilo-plugins] tracker: rewrite notification code
- Date: Tue, 3 Nov 2015 18:13:00 +0000 (UTC)
commit 41e4a212f202130ed4c3a311e700ec91494023f2
Author: Xavier Claessens <xavier claessens collabora com>
Date: Fri Sep 25 10:36:14 2015 -0400
tracker: rewrite notification code
The GrlMedia object passed to "content-changed" signal was useless
because it didn't even contain an URL. To have at least that bare
minimum information we have to query tracker for all subjects when
we receive GraphUpdated.
https://bugzilla.gnome.org/show_bug.cgi?id=746974
src/tracker/grl-tracker-source-notif.c | 739 ++++++++++++--------------------
src/tracker/grl-tracker-source-notif.h | 3 +-
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;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]