[tracker/rss-enclosures] libtracker-miner: Use DBus arg0 filtering for NameOwnerChanged



commit f8729bf51645584fae9697245c153a14354dd763
Author: Philip Van Hoof <philip codeminded be>
Date:   Tue Sep 14 17:22:14 2010 +0200

    libtracker-miner: Use DBus arg0 filtering for NameOwnerChanged
    
    Fixes NB#188031

 src/libtracker-miner/tracker-dbus.c         |  206 +++++++++++++++++----------
 src/libtracker-miner/tracker-miner-object.c |    2 +-
 2 files changed, 132 insertions(+), 76 deletions(-)
---
diff --git a/src/libtracker-miner/tracker-dbus.c b/src/libtracker-miner/tracker-dbus.c
index be6e32b..f9b12bd 100644
--- a/src/libtracker-miner/tracker-dbus.c
+++ b/src/libtracker-miner/tracker-dbus.c
@@ -27,12 +27,14 @@
 #include "tracker-miner-dbus.h"
 
 typedef struct {
-        DBusGConnection *connection;
-        DBusGProxy *gproxy;
-        GHashTable *name_monitors;
+	DBusGConnection *connection;
+	DBusGProxy *gproxy;
+	GHashTable *name_monitors;
 } DBusData;
 
 static GQuark dbus_data = 0;
+static GQuark dbus_interface_quark = 0;
+static GQuark name_owner_changed_signal_quark = 0;
 
 static gboolean
 dbus_register_service (DBusGProxy  *proxy,
@@ -42,16 +44,16 @@ dbus_register_service (DBusGProxy  *proxy,
 	guint	result;
 
 	g_message ("Registering D-Bus service...\n"
-		   "  Name:'%s'",
-		   name);
+	           "  Name:'%s'",
+	           name);
 
 	if (!org_freedesktop_DBus_request_name (proxy,
-						name,
-						DBUS_NAME_FLAG_DO_NOT_QUEUE,
-						&result, &error)) {
+	                                        name,
+	                                        DBUS_NAME_FLAG_DO_NOT_QUEUE,
+	                                        &result, &error)) {
 		g_critical ("Could not acquire name:'%s', %s",
-			    name,
-			    error ? error->message : "no error given");
+		            name,
+		            error ? error->message : "no error given");
 		g_error_free (error);
 
 		return FALSE;
@@ -59,8 +61,8 @@ dbus_register_service (DBusGProxy  *proxy,
 
 	if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
 		g_critical ("D-Bus service name:'%s' is already taken, "
-			    "perhaps the application is already running?",
-			    name);
+		            "perhaps the application is already running?",
+		            name);
 		return FALSE;
 	}
 
@@ -68,11 +70,11 @@ dbus_register_service (DBusGProxy  *proxy,
 }
 
 static gboolean
-dbus_register_object (GObject		    *object,
-		      DBusGConnection	    *connection,
-		      DBusGProxy	    *proxy,
-		      const DBusGObjectInfo *info,
-		      const gchar	    *path)
+dbus_register_object (GObject               *object,
+                      DBusGConnection       *connection,
+                      DBusGProxy            *proxy,
+                      const DBusGObjectInfo *info,
+                      const gchar           *path)
 {
 	g_message ("Registering D-Bus object...");
 	g_message ("  Path:'%s'", path);
@@ -84,51 +86,90 @@ dbus_register_object (GObject		    *object,
 	return TRUE;
 }
 
+static gchar *
+get_name_owner_changed_match_rule (const gchar *name)
+{
+	return g_strdup_printf ("type='signal',"
+	                        "sender='" DBUS_SERVICE_DBUS "',"
+	                        "interface='" DBUS_INTERFACE_DBUS "',"
+	                        "path='" DBUS_PATH_DBUS "',"
+	                        "member='NameOwnerChanged',"
+	                        "arg0='%s'", name);
+}
+
 static void
-name_owner_changed_cb (DBusGProxy *proxy,
-		       gchar	  *name,
-		       gchar	  *old_owner,
-		       gchar	  *new_owner,
-		       gpointer    user_data)
+name_owner_changed_cb (const gchar      *name,
+                       const gchar      *old_owner,
+                       const gchar      *new_owner,
+                       gpointer          user_data)
 {
 	TrackerMinerDBusNameFunc func;
-        TrackerMiner *miner;
-        gboolean available;
-        DBusData *data;
+	TrackerMiner *miner;
+	gboolean available;
+	DBusData *data;
 
-        miner = user_data;
+	miner = user_data;
 
-        if (!name || !*name) {
-                return;
-        }
+	if (!name || !*name) {
+		return;
+	}
 
 	data = g_object_get_qdata (G_OBJECT (miner), dbus_data);
 
-        if (!data) {
-                return;
-        }
+	if (!data) {
+		return;
+	}
 
-        func = g_hash_table_lookup (data->name_monitors, name);
+	func = g_hash_table_lookup (data->name_monitors, name);
 
-        if (!func) {
-                return;
-        }
+	if (!func) {
+		return;
+	}
 
 	available = (new_owner && *new_owner);
-        (func) (miner, name, available);
+
+	(func) (miner, name, available);
+
+	if (g_strcmp0 (new_owner, "") == 0 && g_strcmp0 (name, old_owner) == 0) {
+		gchar *match_rule;
+		/* "name" disappeared from the bus and we have a registry for it */
+		g_hash_table_remove (data->name_monitors, name);
+		match_rule = get_name_owner_changed_match_rule (name);
+		dbus_bus_remove_match (dbus_g_connection_get_connection (data->connection),
+		                       match_rule, NULL);
+		g_free (match_rule);
+	}
 }
 
-static void
-dbus_set_name_monitor (TrackerMiner *miner,
-		       DBusGProxy   *proxy)
+static DBusHandlerResult
+message_filter (DBusConnection *connection,
+                DBusMessage    *message,
+                gpointer        user_data)
 {
-	dbus_g_proxy_add_signal (proxy, "NameOwnerChanged",
-				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-				 G_TYPE_INVALID);
+	const char *tmp;
+	GQuark interface, member;
+	int message_type;
+
+	tmp = dbus_message_get_interface (message);
+	interface = tmp ? g_quark_try_string (tmp) : 0;
+	tmp = dbus_message_get_member (message);
+	member = tmp ? g_quark_try_string (tmp) : 0;
+	message_type = dbus_message_get_type (message);
+
+	if (interface == dbus_interface_quark &&
+		message_type == DBUS_MESSAGE_TYPE_SIGNAL &&
+		member == name_owner_changed_signal_quark) {
+			const gchar *name, *prev_owner, *new_owner;
+			if (dbus_message_get_args (message, NULL,
+			                           DBUS_TYPE_STRING, &name,
+			                           DBUS_TYPE_STRING, &prev_owner,
+			                           DBUS_TYPE_STRING, &new_owner,
+			                           DBUS_TYPE_INVALID)) {
+			name_owner_changed_cb (name, prev_owner, new_owner, user_data);
+		}
+	}
 
-	dbus_g_proxy_connect_signal (proxy, "NameOwnerChanged",
-				     G_CALLBACK (name_owner_changed_cb),
-				     miner, NULL);
+	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
 static void
@@ -155,7 +196,7 @@ dbus_data_destroy (gpointer data)
 
 static DBusData *
 dbus_data_create (TrackerMiner          *miner,
-		  const gchar           *name,
+                  const gchar           *name,
                   const DBusGObjectInfo *info)
 {
 	DBusData *data;
@@ -174,9 +215,9 @@ dbus_data_create (TrackerMiner          *miner,
 	}
 
 	gproxy = dbus_g_proxy_new_for_name (connection,
-					    DBUS_SERVICE_DBUS,
-					    DBUS_PATH_DBUS,
-					    DBUS_INTERFACE_DBUS);
+	                                    DBUS_SERVICE_DBUS,
+	                                    DBUS_PATH_DBUS,
+	                                    DBUS_INTERFACE_DBUS);
 
 	/* Register the service name for the miner */
 	full_name = g_strconcat (TRACKER_MINER_DBUS_NAME_PREFIX, name, NULL);
@@ -192,18 +233,19 @@ dbus_data_create (TrackerMiner          *miner,
 	full_path = g_strconcat (TRACKER_MINER_DBUS_PATH_PREFIX, name, NULL);
 
 	if (!dbus_register_object (G_OBJECT (miner),
-				   connection, gproxy,
-                                   info,
-				   full_path)) {
+	                           connection, gproxy,
+	                           info,
+	                           full_path)) {
 		g_object_unref (gproxy);
 		g_free (full_path);
 		return NULL;
 	}
 
-        dbus_set_name_monitor (miner, gproxy);
-
 	g_free (full_path);
 
+	dbus_connection_add_filter (dbus_g_connection_get_connection (connection),
+	                            message_filter, miner, NULL);
+
 	/* Now we're successfully connected and registered, create the data */
 	data = g_slice_new0 (DBusData);
 	/* Connection object is a shared one, so we need to keep our own
@@ -223,7 +265,7 @@ _tracker_miner_dbus_init (TrackerMiner          *miner,
                           const DBusGObjectInfo *info)
 {
 	DBusData *data;
-        gchar *name;
+	gchar *name;
 
 	g_return_if_fail (TRACKER_IS_MINER (miner));
 	g_return_if_fail (info != NULL);
@@ -234,19 +276,22 @@ _tracker_miner_dbus_init (TrackerMiner          *miner,
 
 	data = g_object_get_qdata (G_OBJECT (miner), dbus_data);
 
-        if (data) {
-                return;
-        }
+	if (data) {
+		return;
+	}
 
-        g_object_get (miner, "name", &name, NULL);
+	g_object_get (miner, "name", &name, NULL);
 
 	if (!name) {
 		g_critical ("Miner '%s' should have been given a name, bailing out",
-                            G_OBJECT_TYPE_NAME (miner));
+		            G_OBJECT_TYPE_NAME (miner));
 		g_assert_not_reached ();
 	}
 
-        data = dbus_data_create (miner, name, info);
+	dbus_interface_quark = g_quark_from_static_string ("org.freedesktop.DBus");
+	name_owner_changed_signal_quark = g_quark_from_static_string ("NameOwnerChanged");
+
+	data = dbus_data_create (miner, name, info);
 
 	if (G_UNLIKELY (!data)) {
 		g_critical ("Miner could not register object on D-Bus session");
@@ -255,9 +300,9 @@ _tracker_miner_dbus_init (TrackerMiner          *miner,
 	}
 
 	g_object_set_qdata_full (G_OBJECT (miner),
-				 dbus_data,
-				 data,
-				 dbus_data_destroy);
+	                         dbus_data,
+	                         data,
+	                         dbus_data_destroy);
 
 	g_free (name);
 }
@@ -279,7 +324,8 @@ _tracker_miner_dbus_add_name_watch (TrackerMiner             *miner,
                                     const gchar              *name,
                                     TrackerMinerDBusNameFunc  func)
 {
-        DBusData *data;
+	DBusData *data;
+	gchar *match_rule;
 
 	g_return_if_fail (TRACKER_IS_MINER (miner));
 	g_return_if_fail (name != NULL);
@@ -287,14 +333,24 @@ _tracker_miner_dbus_add_name_watch (TrackerMiner             *miner,
 
 	data = g_object_get_qdata (G_OBJECT (miner), dbus_data);
 
-        if (!data) {
-                g_critical ("Miner '%s' was not registered on "
-                            "DBus, can watch for owner changes",
-                            G_OBJECT_TYPE_NAME (miner));
-                return;
-        }
+	if (!data) {
+		g_critical ("Miner '%s' was not registered on "
+		            "DBus, can watch for owner changes",
+		            G_OBJECT_TYPE_NAME (miner));
+		return;
+	}
 
-        g_hash_table_insert (data->name_monitors,
-                             g_strdup (name),
-                             func);
+	g_hash_table_insert (data->name_monitors,
+	                     g_strdup (name),
+	                     func);
+
+	match_rule = get_name_owner_changed_match_rule (name);
+	dbus_bus_add_match (dbus_g_connection_get_connection (data->connection),
+	                    match_rule, NULL);
+	if (!dbus_bus_name_has_owner (dbus_g_connection_get_connection (data->connection),
+	                              name, NULL)) {
+		/* Ops, the name went away before we could receive NameOwnerChanged for it */
+		name_owner_changed_cb ("", name, name, miner);
+	}
+	g_free (match_rule);
 }
diff --git a/src/libtracker-miner/tracker-miner-object.c b/src/libtracker-miner/tracker-miner-object.c
index 073fb35..8211ac8 100644
--- a/src/libtracker-miner/tracker-miner-object.c
+++ b/src/libtracker-miner/tracker-miner-object.c
@@ -371,7 +371,7 @@ miner_constructed (GObject *object)
 
 	_tracker_miner_dbus_init (miner, &dbus_glib__tracker_miner_object_info);
 	_tracker_miner_dbus_add_name_watch (miner, "org.freedesktop.Tracker1",
-                                            store_name_monitor_cb);
+	                                    store_name_monitor_cb);
 }
 
 static void



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