[evolution-data-server/cursor-staging: 6/26] EBookClient: Added async apis to connect to a DRA book.



commit 58ca10f7baac8b30aab14c64159758e75c17487e
Author: Tristan Van Berkom <tristanvb openismus com>
Date:   Wed Apr 24 16:16:57 2013 +0900

    EBookClient: Added async apis to connect to a DRA book.
    
    Added e_book_client_connect_direct() and e_book_client_connect_direct_finish()

 addressbook/libebook/e-book-client.c |  234 ++++++++++++++++++++++++++++++----
 addressbook/libebook/e-book-client.h |    7 +
 2 files changed, 214 insertions(+), 27 deletions(-)
---
diff --git a/addressbook/libebook/e-book-client.c b/addressbook/libebook/e-book-client.c
index 14bd38b..9a09c62 100644
--- a/addressbook/libebook/e-book-client.c
+++ b/addressbook/libebook/e-book-client.c
@@ -1309,38 +1309,35 @@ e_book_client_new (ESource *source,
                "source", source, NULL);
 }
 
-/**
- * e_book_client_connect_direct_sync:
- * @registry: an #ESourceRegistry
- * @source: an #ESource
- * @cancellable: (allow-none): optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Like e_book_client_connect_sync(), except creates the book client for
- * direct read access to the underlying addressbook.
- *
- * Returns: (transfer full) (type EBookClient): a new but unopened #EBookClient.
- *
- * Since: 3.8
- **/
-EClient *
-e_book_client_connect_direct_sync (ESourceRegistry *registry,
-                                   ESource *source,
-                                   GCancellable *cancellable,
-                                   GError **error)
+/* Direct Read Access connect helper */
+static void
+connect_direct (EBookClient     *client,
+               GCancellable    *cancellable,
+               ESourceRegistry *registry)
 {
-       EClient *client;
        EBookClientPrivate *priv;
        EDBusDirectBook *direct_config;
        const gchar *backend_name, *backend_path, *config;
        GError *local_error = NULL;
 
-       client = e_book_client_connect_sync (source, cancellable, error);
+       priv = E_BOOK_CLIENT_GET_PRIVATE (client);
 
-       if (!client)
-               return NULL;
+       if (registry)
+               g_object_ref (registry);
+       else {
+               registry = e_source_registry_new_sync (NULL, &local_error);
 
-       priv = E_BOOK_CLIENT_GET_PRIVATE (client);
+               if (!registry) {
+                       g_warning (
+                               "Failed to open addressbook in direct read "
+                               "access mode, falling back to normal read "
+                               "access mode. Reason: failed to open registry %s",
+                               local_error->message);
+
+                       g_error_free (local_error);
+                       return;
+               }
+       }
 
        direct_config = e_dbus_direct_book_proxy_new_sync (
                g_dbus_proxy_get_connection (G_DBUS_PROXY (priv->dbus_proxy)),
@@ -1356,7 +1353,7 @@ e_book_client_connect_direct_sync (ESourceRegistry *registry,
        if (backend_path != NULL && *backend_path != '\0' &&
            backend_name != NULL && *backend_name != '\0') {
                priv->direct_backend = book_client_load_direct_backend (
-                       registry, source,
+                       registry, e_client_get_source (E_CLIENT (client)),
                        backend_path,
                        backend_name,
                        config, &local_error);
@@ -1376,6 +1373,7 @@ e_book_client_connect_direct_sync (ESourceRegistry *registry,
        }
 
        g_object_unref (direct_config);
+       g_object_unref (registry);
 
        /* We have to perform the opening of the direct backend separately
         * from the EClient->open() implementation, because the direct
@@ -1386,20 +1384,202 @@ e_book_client_connect_direct_sync (ESourceRegistry *registry,
                /* Direct backend is not using D-Bus (obviously),
                 * so no need to strip D-Bus info from the error. */
                success = e_book_backend_open_sync (
-                       priv->direct_backend, cancellable, error);
+                       priv->direct_backend, cancellable, &local_error);
 
                if (!success) {
                        g_warning (
                                "Unable to open direct read access book, "
-                               "falling back to normal read access mode");
+                               "falling back to normal read access mode: %s",
+                               local_error->message);
                        g_clear_object (&priv->direct_backend);
+                       g_error_free (local_error);
                }
        }
+}
+
+/**
+ * e_book_client_connect_direct_sync:
+ * @registry: an #ESourceRegistry
+ * @source: an #ESource
+ * @cancellable: (allow-none): optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Like e_book_client_connect_sync(), except creates the book client for
+ * direct read access to the underlying addressbook.
+ *
+ * Returns: (transfer full) (type EBookClient): a new but unopened #EBookClient.
+ *
+ * Since: 3.8
+ **/
+EClient *
+e_book_client_connect_direct_sync (ESourceRegistry *registry,
+                                   ESource *source,
+                                   GCancellable *cancellable,
+                                   GError **error)
+{
+       EClient *client;
+
+       client = e_book_client_connect_sync (source, cancellable, error);
+
+       if (!client)
+               return NULL;
+
+       /* Connect the direct EDataBook connection */
+       connect_direct (E_BOOK_CLIENT (client), cancellable, registry);
 
        return client;
 
 }
 
+/* Helper for e_book_client_connect_direct() */
+static void
+book_client_connect_direct_init_cb (GObject *source_object,
+                                   GAsyncResult *result,
+                                   gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       EBookClientPrivate *priv;
+       ConnectClosure *closure;
+       GError *error = NULL;
+
+       simple = G_SIMPLE_ASYNC_RESULT (user_data);
+
+       g_async_initable_init_finish (
+               G_ASYNC_INITABLE (source_object), result, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_take_error (simple, error);
+               g_simple_async_result_complete (simple);
+               goto exit;
+       }
+
+       /* Note, we're repurposing some function parameters. */
+       result = G_ASYNC_RESULT (simple);
+       source_object = g_async_result_get_source_object (result);
+       closure = g_simple_async_result_get_op_res_gpointer (simple);
+
+       priv = E_BOOK_CLIENT_GET_PRIVATE (source_object);
+
+       e_dbus_address_book_call_open (
+               priv->dbus_proxy,
+               closure->cancellable,
+               book_client_connect_open_cb,
+               g_object_ref (simple));
+
+       /* Make the DRA connection */
+       connect_direct (E_BOOK_CLIENT (source_object), closure->cancellable, NULL);
+
+       g_object_unref (source_object);
+
+exit:
+       g_object_unref (simple);
+}
+
+/**
+ * e_book_client_connect_direct:
+ * @source: an #ESource
+ * @cancellable: (allow-none): optional #GCancellable object, or %NULL
+ * @callback: (scope async): a #GAsyncReadyCallback to call when the request
+ *            is satisfied
+ * @user_data: (closure): data to pass to the callback function
+ *
+ * Like e_book_client_connect(), except creates the book client for
+ * direct read access to the underlying addressbook.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call e_book_client_connect_direct_finish() to get the result of the operation.
+ *
+ * Since: 3.10
+ **/
+void
+e_book_client_connect_direct (ESource *source,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       ConnectClosure *closure;
+       EBookClient *client;
+
+       g_return_if_fail (E_IS_SOURCE (source));
+
+       /* Two things with this: 1) instantiate the client object
+        * immediately to make sure the thread-default GMainContext
+        * gets plucked, and 2) do not call the D-Bus open() method
+        * from our designated D-Bus thread -- it may take a long
+        * time and block other clients from receiving signals. */
+       closure = g_slice_new0 (ConnectClosure);
+       closure->source = g_object_ref (source);
+
+       if (G_IS_CANCELLABLE (cancellable))
+               closure->cancellable = g_object_ref (cancellable);
+
+       client = g_object_new (
+               E_TYPE_BOOK_CLIENT,
+               "source", source, NULL);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (client), callback,
+               user_data, e_book_client_connect_direct);
+
+       g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, closure, (GDestroyNotify) connect_closure_free);
+
+       g_async_initable_init_async (
+               G_ASYNC_INITABLE (client),
+               G_PRIORITY_DEFAULT, cancellable,
+               book_client_connect_direct_init_cb,
+               g_object_ref (simple));
+
+       g_object_unref (simple);
+       g_object_unref (client);
+}
+
+/**
+ * e_book_client_connect_direct_finish:
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with e_book_client_connect_direct().
+ * If an error occurs in connecting to the D-Bus service, the function sets
+ * @error and returns %NULL.
+ *
+ * For error handling convenience, any error message returned by this
+ * function will have a descriptive prefix that includes the display
+ * name of the #ESource passed to e_book_client_connect_direct().
+ *
+ * Returns: (transfer full) (type EBookClient): a new #EBookClient, or %NULL
+ *
+ * Since: 3.10
+ **/
+EClient *
+e_book_client_connect_direct_finish (GAsyncResult *result,
+                                    GError **error)
+{
+       GSimpleAsyncResult *simple;
+       ConnectClosure *closure;
+       gpointer source_tag;
+
+       g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       closure = g_simple_async_result_get_op_res_gpointer (simple);
+
+       source_tag = g_simple_async_result_get_source_tag (simple);
+       g_return_val_if_fail (source_tag == e_book_client_connect_direct, NULL);
+
+       if (g_simple_async_result_propagate_error (simple, error)) {
+               g_prefix_error (
+                       error, _("Unable to connect to '%s': "),
+                       e_source_get_display_name (closure->source));
+               return NULL;
+       }
+
+       return E_CLIENT (g_async_result_get_source_object (result));
+}
+
 #define SELF_UID_PATH_ID "org.gnome.evolution-data-server.addressbook"
 #define SELF_UID_KEY "self-contact-uid"
 
diff --git a/addressbook/libebook/e-book-client.h b/addressbook/libebook/e-book-client.h
index 4e00cb7..9339879 100644
--- a/addressbook/libebook/e-book-client.h
+++ b/addressbook/libebook/e-book-client.h
@@ -107,6 +107,13 @@ EClient *       e_book_client_connect_direct_sync
                                                 ESource *source,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           e_book_client_connect_direct    (ESource *source,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+EClient *      e_book_client_connect_direct_finish
+                                                (GAsyncResult *result,
+                                                GError **error);
 gboolean       e_book_client_get_self          (ESourceRegistry *registry,
                                                 EContact **out_contact,
                                                 EBookClient **out_client,


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