[gvfs/gdbus-core: 4/17] gdbus: Improve registered paths activation on daemon side
- From: Tomas Bzatek <tbzatek src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs/gdbus-core: 4/17] gdbus: Improve registered paths activation on daemon side
- Date: Mon, 4 Jun 2012 17:39:56 +0000 (UTC)
commit 165f276e55376032a25bc27def580a9060475f56
Author: Tomas Bzatek <tbzatek redhat com>
Date: Fri Apr 13 15:03:23 2012 +0200
gdbus: Improve registered paths activation on daemon side
This changes the way registered paths (i.e. interface skeleton exports)
are activated on daemon side. We're keeping a list of connections on which every
registered path is exported so that if connection is closed or the path is
unregistered we always free the right interface skeletons.
We also keep track of active client (peer-to-peer) connections so that if a new
path is registered, it's automatically exported to all active connections. Needed
since client connections are usually shared.
It also has a nice side-effect of reacting to dirty disconnects (e.g. the client
dies).
This whole registration machinery needs unique object paths (for the hash table)
but that's not a problem in the current state.
daemon/gvfsbackend.c | 1 -
daemon/gvfsdaemon.c | 100 +++++++++++++++++++++++++++++++++----------------
daemon/gvfsdaemon.h | 1 -
3 files changed, 67 insertions(+), 35 deletions(-)
---
diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c
index 6df4fbf..70db255 100644
--- a/daemon/gvfsbackend.c
+++ b/daemon/gvfsbackend.c
@@ -314,7 +314,6 @@ g_vfs_backend_constructor (GType type,
g_vfs_daemon_register_path (backend->priv->daemon,
backend->priv->object_path,
- "backend_path",
register_path_cb,
backend);
diff --git a/daemon/gvfsdaemon.c b/daemon/gvfsdaemon.c
index 224a6bc..16e89f3 100644
--- a/daemon/gvfsdaemon.c
+++ b/daemon/gvfsdaemon.c
@@ -48,10 +48,10 @@ enum {
typedef struct {
char *obj_path;
- char *name;
GVfsRegisterPathCallback callback;
gpointer data;
- GDBusInterfaceSkeleton *skeleton;
+ GDBusInterfaceSkeleton *session_skeleton;
+ GHashTable *client_skeletons;
} RegisteredPath;
struct _GVfsDaemon
@@ -63,6 +63,7 @@ struct _GVfsDaemon
GThreadPool *thread_pool;
GHashTable *registered_paths;
+ GHashTable *client_connections;
GList *jobs;
GList *job_sources;
@@ -124,13 +125,14 @@ static void
registered_path_free (RegisteredPath *data)
{
g_free (data->obj_path);
- g_free (data->name);
- if (data->skeleton)
+ if (data->session_skeleton)
{
/* Unexport the interface skeleton on session bus */
- g_dbus_interface_skeleton_unexport (data->skeleton);
- g_object_unref (data->skeleton);
+ g_dbus_interface_skeleton_unexport (data->session_skeleton);
+ g_object_unref (data->session_skeleton);
}
+ g_hash_table_destroy (data->client_skeletons);
+
g_free (data);
}
@@ -160,6 +162,7 @@ g_vfs_daemon_finalize (GObject *object)
g_object_unref (daemon->conn);
g_hash_table_destroy (daemon->registered_paths);
+ g_hash_table_destroy (daemon->client_connections);
g_mutex_clear (&daemon->lock);
if (G_OBJECT_CLASS (g_vfs_daemon_parent_class)->finalize)
@@ -239,8 +242,12 @@ g_vfs_daemon_init (GVfsDaemon *daemon)
daemon->jobs = NULL;
daemon->registered_paths =
g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, (GDestroyNotify)registered_path_free);
-
+ g_free, (GDestroyNotify)registered_path_free);
+
+ /* This is where we store active client connections so when a new filter is registered,
+ * we re-register them on all active connections */
+ daemon->client_connections =
+ g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
daemon->conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
g_assert (daemon->conn != NULL);
@@ -462,11 +469,49 @@ g_vfs_daemon_add_job_source (GVfsDaemon *daemon,
g_mutex_unlock (&daemon->lock);
}
+static void
+unref_skeleton (gpointer object)
+{
+ GDBusInterfaceSkeleton *skeleton = object;
+
+ g_print ("unref_skeleton: unreffing skeleton %p\n", skeleton);
+ g_dbus_interface_skeleton_unexport (skeleton);
+ g_object_unref (skeleton);
+}
+
+static void
+peer_register_skeleton (const gchar *obj_path,
+ RegisteredPath *reg_path,
+ GDBusConnection *dbus_conn)
+{
+ GDBusInterfaceSkeleton *skeleton;
+
+ if (! g_hash_table_contains (reg_path->client_skeletons, dbus_conn))
+ {
+ skeleton = reg_path->callback (dbus_conn, obj_path, reg_path->data);
+ g_print ("registering '%s' on the %p connection\n", obj_path, dbus_conn);
+
+ g_hash_table_insert (reg_path->client_skeletons, dbus_conn, skeleton);
+ }
+ else
+ {
+ g_print ("interface skeleton '%s' already registered on the %p connection, skipping\n", obj_path, dbus_conn);
+ }
+}
+
+static void
+client_conn_register_skeleton (GDBusConnection *dbus_conn,
+ gpointer value,
+ RegisteredPath *reg_path)
+{
+ peer_register_skeleton (reg_path->obj_path, reg_path, dbus_conn);
+}
+
/* This registers a dbus interface skeleton on *all* connections, client and session bus */
+/* The object path needs to be unique globally. */
void
g_vfs_daemon_register_path (GVfsDaemon *daemon,
const char *obj_path,
- const char *name,
GVfsRegisterPathCallback callback,
gpointer user_data)
{
@@ -476,18 +521,20 @@ g_vfs_daemon_register_path (GVfsDaemon *daemon,
data = g_new0 (RegisteredPath, 1);
data->obj_path = g_strdup (obj_path);
- data->name = g_strdup (name);
data->callback = callback;
data->data = user_data;
+ data->client_skeletons = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)unref_skeleton);
- g_hash_table_insert (daemon->registered_paths, data->obj_path,
- data);
+ g_hash_table_insert (daemon->registered_paths, g_strdup (obj_path), data);
/* Export the newly registered interface skeleton on session bus */
/* TODO: change the way we export skeletons on connections once
* https://bugzilla.gnome.org/show_bug.cgi?id=662718 is in place.
*/
- data->skeleton = callback (daemon->conn, data->obj_path, user_data);
+ data->session_skeleton = callback (daemon->conn, obj_path, user_data);
+
+ /* Export this newly registered path to all active client connections */
+ g_hash_table_foreach (daemon->client_connections, (GHFunc) client_conn_register_skeleton, data);
}
void
@@ -565,16 +612,12 @@ new_connection_data_free (void *memory)
}
static void
-peer_unregister_skeleton (gpointer key,
+peer_unregister_skeleton (const gchar *obj_path,
RegisteredPath *reg_path,
GDBusConnection *dbus_conn)
{
- GDBusInterfaceSkeleton *skeleton;
-
- g_print ("unregistering '%s' on the %p connection\n", reg_path->name, dbus_conn);
-
- skeleton = g_object_get_data (G_OBJECT (dbus_conn), reg_path->name);
- g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (skeleton));
+ g_print ("unregistering '%s' on the %p connection\n", obj_path, dbus_conn);
+ g_hash_table_remove (reg_path->client_skeletons, dbus_conn);
}
static void
@@ -606,6 +649,8 @@ peer_connection_closed (GDBusConnection *connection,
/* daemon_skeleton should be always valid in this case */
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (daemon_skeleton));
+ g_hash_table_remove (daemon->client_connections, connection);
+
/* Unexport the registered interface skeletons */
g_hash_table_foreach (daemon->registered_paths, (GHFunc) peer_unregister_skeleton, connection);
@@ -614,19 +659,6 @@ peer_connection_closed (GDBusConnection *connection,
}
static void
-peer_register_skeleton (gpointer key,
- RegisteredPath *reg_path,
- GDBusConnection *dbus_conn)
-{
- GDBusInterfaceSkeleton *skeleton;
-
- g_print ("registering '%s' on the %p connection\n", reg_path->name, dbus_conn);
-
- skeleton = reg_path->callback (dbus_conn, reg_path->obj_path, reg_path->data);
- g_object_set_data_full (G_OBJECT (dbus_conn), reg_path->name, skeleton, (GDestroyNotify) g_object_unref);
-}
-
-static void
daemon_peer_connection_setup (GVfsDaemon *daemon,
GDBusConnection *dbus_conn,
NewConnectionData *data)
@@ -667,6 +699,8 @@ daemon_peer_connection_setup (GVfsDaemon *daemon,
/* Export registered interface skeletons on this new connection */
g_hash_table_foreach (daemon->registered_paths, (GHFunc) peer_register_skeleton, dbus_conn);
+ g_hash_table_insert (daemon->client_connections, g_object_ref (dbus_conn), NULL);
+
g_print ("daemon_peer_connection_setup: interface registration complete.\n");
g_signal_connect (data->conn, "closed", G_CALLBACK (peer_connection_closed), data->daemon);
diff --git a/daemon/gvfsdaemon.h b/daemon/gvfsdaemon.h
index 5f13bef..2658f0d 100644
--- a/daemon/gvfsdaemon.h
+++ b/daemon/gvfsdaemon.h
@@ -65,7 +65,6 @@ void g_vfs_daemon_queue_job (GVfsDaemon *daemon,
GVfsJob *job);
void g_vfs_daemon_register_path (GVfsDaemon *daemon,
const char *obj_path,
- const char *name,
GVfsRegisterPathCallback callback,
gpointer user_data);
void g_vfs_daemon_unregister_path (GVfsDaemon *daemon,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]