[evolution-data-server] EBookClient: Use g_bus_watch_name_on_connection().
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] EBookClient: Use g_bus_watch_name_on_connection().
- Date: Sat, 9 Feb 2013 22:06:33 +0000 (UTC)
commit 8726e44eac95b7966061d5bada845160a8ecc464
Author: Matthew Barnes <mbarnes redhat com>
Date: Sat Feb 9 10:37:31 2013 -0500
EBookClient: Use g_bus_watch_name_on_connection().
g_bus_watch_name_on_connection() handles "NameOwnerChanged" signals
as well as "closed" signals from the GDBusConnection. In the event
the bus name vanishes, we schedule an idle callback on the client's
GMainContext to emit a "backend-died" signal.
Also while we're at it, call the close() method asynchronously from
dispose() so we don't block.
addressbook/libebook/e-book-client.c | 286 ++++++++++++++--------------------
1 files changed, 116 insertions(+), 170 deletions(-)
---
diff --git a/addressbook/libebook/e-book-client.c b/addressbook/libebook/e-book-client.c
index 79ff390..f13c623 100644
--- a/addressbook/libebook/e-book-client.c
+++ b/addressbook/libebook/e-book-client.c
@@ -51,9 +51,9 @@ typedef struct _ConnectClosure ConnectClosure;
typedef struct _RunInThreadClosure RunInThreadClosure;
struct _EBookClientPrivate {
- EDBusAddressBook *dbus_proxy;
GMainContext *main_context;
- guint gone_signal_id;
+ EDBusAddressBook *dbus_proxy;
+ guint name_watcher_id;
gulong dbus_proxy_error_handler_id;
gulong dbus_proxy_notify_handler_id;
@@ -285,87 +285,46 @@ set_proxy_gone_error (GError **error)
}
static volatile gint active_book_clients = 0;
-static guint book_connection_closed_id = 0;
+static guint book_factory_watcher_id = 0;
static EDBusAddressBookFactory *book_factory = NULL;
static GRecMutex book_factory_lock;
#define LOCK_FACTORY() g_rec_mutex_lock (&book_factory_lock)
#define UNLOCK_FACTORY() g_rec_mutex_unlock (&book_factory_lock)
-static void gdbus_book_factory_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, gpointer user_data);
-
static void
-gdbus_book_factory_disconnect (GDBusConnection *connection)
+book_factory_disconnect (void)
{
LOCK_FACTORY ();
- if (!connection && book_factory)
- connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory));
-
- if (connection && book_connection_closed_id) {
- g_dbus_connection_signal_unsubscribe (connection, book_connection_closed_id);
- g_signal_handlers_disconnect_by_func (connection, gdbus_book_factory_closed_cb, NULL);
+ if (book_factory_watcher_id > 0) {
+ g_bus_unwatch_name (book_factory_watcher_id);
+ book_factory_watcher_id = 0;
}
- if (book_factory != NULL)
- g_object_unref (book_factory);
-
- book_connection_closed_id = 0;
- book_factory = NULL;
+ g_clear_object (&book_factory);
UNLOCK_FACTORY ();
}
static void
-gdbus_book_factory_closed_cb (GDBusConnection *connection,
- gboolean remote_peer_vanished,
- GError *error,
- gpointer user_data)
-{
- GError *err = NULL;
-
- LOCK_FACTORY ();
-
- gdbus_book_factory_disconnect (connection);
-
- if (error)
- unwrap_dbus_error (g_error_copy (error), &err);
-
- if (err) {
- g_debug ("GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
- g_error_free (err);
- } else if (active_book_clients > 0) {
- g_debug ("GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
- }
-
- UNLOCK_FACTORY ();
-}
-
-static void
-gdbus_book_factory_connection_gone_cb (GDBusConnection *connection,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters,
- gpointer user_data)
+book_factory_name_vanished_cb (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
{
- /* signal subscription takes care of correct parameters,
- * thus just do what is to be done here */
- gdbus_book_factory_closed_cb (connection, TRUE, NULL, user_data);
+ book_factory_disconnect ();
}
static gboolean
-gdbus_book_factory_activate (GCancellable *cancellable,
- GError **error)
+book_factory_activate (GCancellable *cancellable,
+ GError **error)
{
- GDBusConnection *connection;
+ GDBusProxy *proxy;
+ gboolean success = TRUE;
LOCK_FACTORY ();
- if (G_LIKELY (book_factory != NULL)) {
- UNLOCK_FACTORY ();
- return TRUE;
- }
+ if (G_LIKELY (book_factory != NULL))
+ goto exit;
book_factory = e_dbus_address_book_factory_proxy_new_for_bus_sync (
G_BUS_TYPE_SESSION,
@@ -375,28 +334,24 @@ gdbus_book_factory_activate (GCancellable *cancellable,
cancellable, error);
if (book_factory == NULL) {
- UNLOCK_FACTORY ();
- return FALSE;
+ success = FALSE;
+ goto exit;
}
- connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory));
- book_connection_closed_id = g_dbus_connection_signal_subscribe (
- connection,
- NULL, /* sender */
- "org.freedesktop.DBus", /* interface */
- "NameOwnerChanged", /* member */
- "/org/freedesktop/DBus", /* object_path */
- "org.gnome.evolution.dataserver.AddressBook", /* arg0 */
- G_DBUS_SIGNAL_FLAGS_NONE,
- gdbus_book_factory_connection_gone_cb, NULL, NULL);
-
- g_signal_connect (
- connection, "closed",
- G_CALLBACK (gdbus_book_factory_closed_cb), NULL);
+ proxy = G_DBUS_PROXY (book_factory);
+
+ book_factory_watcher_id = g_bus_watch_name_on_connection (
+ g_dbus_proxy_get_connection (proxy),
+ g_dbus_proxy_get_name (proxy),
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ (GBusNameAppearedCallback) NULL,
+ (GBusNameVanishedCallback) book_factory_name_vanished_cb,
+ NULL, (GDestroyNotify) NULL);
+exit:
UNLOCK_FACTORY ();
- return TRUE;
+ return success;
}
static gpointer
@@ -500,72 +455,16 @@ book_client_run_in_dbus_thread (GSimpleAsyncResult *simple,
g_main_context_unref (main_context);
}
-static void gdbus_book_client_disconnect (EBookClient *client);
-
-/*
- * Called when the addressbook server dies.
- */
-static void
-gdbus_book_client_closed_cb (GDBusConnection *connection,
- gboolean remote_peer_vanished,
- GError *error,
- EBookClient *client)
-{
- GError *err = NULL;
-
- g_assert (E_IS_BOOK_CLIENT (client));
-
- if (error)
- unwrap_dbus_error (g_error_copy (error), &err);
-
- if (err) {
- g_debug (G_STRLOC ": EBookClient GDBus connection is closed%s: %s", remote_peer_vanished ? ", remote peer vanished" : "", err->message);
- g_error_free (err);
- } else {
- g_debug (G_STRLOC ": EBookClient GDBus connection is closed%s", remote_peer_vanished ? ", remote peer vanished" : "");
- }
-
- gdbus_book_client_disconnect (client);
-
- e_client_emit_backend_died (E_CLIENT (client));
-}
-
-static void
-gdbus_book_client_connection_gone_cb (GDBusConnection *connection,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters,
- gpointer user_data)
-{
- /* signal subscription takes care of correct parameters,
- * thus just do what is to be done here */
- gdbus_book_client_closed_cb (connection, TRUE, NULL, user_data);
-}
-
-static void
-gdbus_book_client_disconnect (EBookClient *client)
+static gboolean
+book_client_emit_backend_died_idle_cb (gpointer user_data)
{
- g_return_if_fail (E_IS_BOOK_CLIENT (client));
-
- /* Ensure that everything relevant is NULL */
- LOCK_FACTORY ();
-
- if (client->priv->dbus_proxy != NULL) {
- GDBusConnection *connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (client->priv->dbus_proxy));
-
- g_signal_handlers_disconnect_by_func (connection, gdbus_book_client_closed_cb, client);
- g_dbus_connection_signal_unsubscribe (connection, client->priv->gone_signal_id);
- client->priv->gone_signal_id = 0;
+ SignalClosure *signal_closure = user_data;
- e_dbus_address_book_call_close_sync (
- client->priv->dbus_proxy, NULL, NULL);
- g_object_unref (client->priv->dbus_proxy);
- client->priv->dbus_proxy = NULL;
- }
+ g_signal_emit_by_name (
+ signal_closure->client,
+ "backend-died");
- UNLOCK_FACTORY ();
+ return FALSE;
}
static gboolean
@@ -703,6 +602,43 @@ book_client_dbus_proxy_notify_cb (EDBusAddressBook *dbus_proxy,
}
static void
+book_client_name_vanished_cb (GDBusConnection *connection,
+ const gchar *name,
+ EBookClient *book_client)
+{
+ GSource *idle_source;
+ SignalClosure *signal_closure;
+
+ signal_closure = g_slice_new0 (SignalClosure);
+ signal_closure->client = g_object_ref (book_client);
+
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (
+ idle_source,
+ book_client_emit_backend_died_idle_cb,
+ signal_closure,
+ (GDestroyNotify) signal_closure_free);
+ g_source_attach (idle_source, book_client->priv->main_context);
+ g_source_unref (idle_source);
+}
+
+static void
+book_client_close_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ e_dbus_address_book_call_close_finish (
+ E_DBUS_ADDRESS_BOOK (source_object), result, &error);
+
+ if (error != NULL) {
+ g_warning ("%s: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+}
+
+static void
book_client_dispose (GObject *object)
{
EBookClientPrivate *priv;
@@ -725,7 +661,15 @@ book_client_dispose (GObject *object)
priv->dbus_proxy_notify_handler_id = 0;
}
- gdbus_book_client_disconnect (E_BOOK_CLIENT (object));
+ if (priv->dbus_proxy != NULL) {
+ /* Call close() asynchronously
+ * so we don't block dispose(). */
+ e_dbus_address_book_call_close (
+ priv->dbus_proxy, NULL,
+ book_client_close_cb, NULL);
+ g_object_unref (priv->dbus_proxy);
+ priv->dbus_proxy = NULL;
+ }
if (priv->main_context != NULL) {
g_main_context_unref (priv->main_context);
@@ -739,11 +683,18 @@ book_client_dispose (GObject *object)
static void
book_client_finalize (GObject *object)
{
+ EBookClientPrivate *priv;
+
+ priv = E_BOOK_CLIENT_GET_PRIVATE (object);
+
+ if (priv->name_watcher_id > 0)
+ g_bus_unwatch_name (priv->name_watcher_id);
+
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_book_client_parent_class)->finalize (object);
if (g_atomic_int_dec_and_test (&active_book_clients))
- gdbus_book_factory_disconnect (NULL);
+ book_factory_disconnect ();
}
static GDBusProxy *
@@ -916,7 +867,8 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
EBookClientPrivate *priv;
EClient *client;
ESource *source;
- GDBusConnection *connection;
+ GDBusProxy *factory_proxy;
+ GDBusProxy *proxy;
const gchar *uid;
gchar *object_path = NULL;
gulong handler_id;
@@ -928,9 +880,7 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
source = e_client_get_source (client);
uid = e_source_get_uid (source);
- LOCK_FACTORY ();
- gdbus_book_factory_activate (cancellable, &error);
- UNLOCK_FACTORY ();
+ book_factory_activate (cancellable, &error);
if (error != NULL) {
unwrap_dbus_error (error, &error);
@@ -946,20 +896,19 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
((object_path != NULL) && (error == NULL)) ||
((object_path == NULL) && (error != NULL)));
- if (object_path == NULL) {
+ if (error != NULL) {
unwrap_dbus_error (error, &error);
g_simple_async_result_take_error (simple, error);
return;
}
- connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (book_factory));
+ factory_proxy = G_DBUS_PROXY (book_factory);
priv->dbus_proxy = e_dbus_address_book_proxy_new_sync (
- connection,
+ g_dbus_proxy_get_connection (factory_proxy),
G_DBUS_PROXY_FLAGS_NONE,
- ADDRESS_BOOK_DBUS_SERVICE_NAME,
- object_path,
- cancellable, &error);
+ g_dbus_proxy_get_name (factory_proxy),
+ object_path, cancellable, &error);
g_free (object_path);
@@ -974,39 +923,36 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple,
return;
}
- g_dbus_proxy_set_default_timeout (
- G_DBUS_PROXY (priv->dbus_proxy), DBUS_PROXY_TIMEOUT_MS);
+ /* Configure our new GDBusProxy. */
+
+ proxy = G_DBUS_PROXY (priv->dbus_proxy);
- priv->gone_signal_id = g_dbus_connection_signal_subscribe (
- connection,
- "org.freedesktop.DBus", /* sender */
- "org.freedesktop.DBus", /* interface */
- "NameOwnerChanged", /* member */
- "/org/freedesktop/DBus", /* object_path */
- "org.gnome.evolution.dataserver.AddressBook", /* arg0 */
- G_DBUS_SIGNAL_FLAGS_NONE,
- gdbus_book_client_connection_gone_cb, client, NULL);
+ g_dbus_proxy_set_default_timeout (proxy, DBUS_PROXY_TIMEOUT_MS);
- g_signal_connect (
- connection, "closed",
- G_CALLBACK (gdbus_book_client_closed_cb), client);
+ priv->name_watcher_id = g_bus_watch_name_on_connection (
+ g_dbus_proxy_get_connection (proxy),
+ g_dbus_proxy_get_name (proxy),
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ (GBusNameAppearedCallback) NULL,
+ (GBusNameVanishedCallback) book_client_name_vanished_cb,
+ client, (GDestroyNotify) NULL);
handler_id = g_signal_connect_object (
- priv->dbus_proxy, "error",
+ proxy, "error",
G_CALLBACK (book_client_dbus_proxy_error_cb),
client, 0);
priv->dbus_proxy_error_handler_id = handler_id;
handler_id = g_signal_connect_object (
- priv->dbus_proxy, "notify",
+ proxy, "notify",
G_CALLBACK (book_client_dbus_proxy_notify_cb),
client, 0);
priv->dbus_proxy_notify_handler_id = handler_id;
/* Initialize our public-facing GObject properties. */
- g_object_notify (G_OBJECT (priv->dbus_proxy), "online");
- g_object_notify (G_OBJECT (priv->dbus_proxy), "writable");
- g_object_notify (G_OBJECT (priv->dbus_proxy), "capabilities");
+ g_object_notify (G_OBJECT (proxy), "online");
+ g_object_notify (G_OBJECT (proxy), "writable");
+ g_object_notify (G_OBJECT (proxy), "capabilities");
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]