[evolution-data-server] Bug #592159 - Support multiple factories for address-book with dbus
- From: Milan Crha <mcrha src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug #592159 - Support multiple factories for address-book with dbus
- Date: Fri, 16 Oct 2009 12:45:08 +0000 (UTC)
commit b1a100acd8b8f169e1b1312a8323724f580f085c
Author: Milan Crha <mcrha redhat com>
Date: Fri Oct 16 14:44:32 2009 +0200
Bug #592159 - Support multiple factories for address-book with dbus
addressbook/libedata-book/e-book-backend.c | 26 ----
addressbook/libedata-book/e-book-backend.h | 2 +-
addressbook/libedata-book/e-data-book-factory.c | 154 ++++++++++++-----------
addressbook/libedata-book/e-data-book.c | 14 +--
addressbook/libedata-book/e-data-book.h | 12 +--
5 files changed, 86 insertions(+), 122 deletions(-)
---
diff --git a/addressbook/libedata-book/e-book-backend.c b/addressbook/libedata-book/e-book-backend.c
index 61460e2..80f2740 100644
--- a/addressbook/libedata-book/e-book-backend.c
+++ b/addressbook/libedata-book/e-book-backend.c
@@ -470,31 +470,6 @@ e_book_backend_cancel_operation (EBookBackend *backend,
}
static void
-book_destroy_cb (gpointer data, GObject *where_book_was)
-{
- EBookBackend *backend = E_BOOK_BACKEND (data);
-
- e_book_backend_remove_client (backend, (EDataBook *)where_book_was);
-}
-
-static gboolean
-idle_remove_client (gpointer data)
-{
- EDataBook *book = (EDataBook *) data;
-
- e_book_backend_remove_client (e_data_book_get_backend (book), book);
- g_object_unref ((GObject *) book);
-
- return FALSE;
-}
-static void
-listener_died_cb (gpointer cnx, gpointer user_data)
-{
- g_object_ref ((GObject *)user_data);
- g_idle_add (idle_remove_client, user_data);
-}
-
-static void
last_client_gone (EBookBackend *backend)
{
g_signal_emit (backend, e_book_backend_signals[LAST_CLIENT_GONE], 0);
@@ -572,7 +547,6 @@ e_book_backend_add_client (EBookBackend *backend,
g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), FALSE);
g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
- g_object_weak_ref (G_OBJECT (book), book_destroy_cb, backend);
g_mutex_lock (backend->priv->clients_mutex);
backend->priv->clients = g_list_prepend (backend->priv->clients, book);
g_mutex_unlock (backend->priv->clients_mutex);
diff --git a/addressbook/libedata-book/e-book-backend.h b/addressbook/libedata-book/e-book-backend.h
index 27d03b7..f33e6ee 100644
--- a/addressbook/libedata-book/e-book-backend.h
+++ b/addressbook/libedata-book/e-book-backend.h
@@ -67,7 +67,7 @@ struct _EBookBackendClass {
void (*get_supported_fields) (EBookBackend *backend, EDataBook *book, guint32 opid);
void (*get_supported_auth_methods) (EBookBackend *backend, EDataBook *book, guint32 opid);
GNOME_Evolution_Addressbook_CallStatus (*cancel_operation) (EBookBackend *backend, EDataBook *book);
- void (*set_mode) (EBookBackend *backend, GNOME_Evolution_Addressbook_BookMode mode);
+ void (*set_mode) (EBookBackend *backend, GNOME_Evolution_Addressbook_BookMode mode);
/* Notification signals */
void (* last_client_gone) (EBookBackend *backend);
diff --git a/addressbook/libedata-book/e-data-book-factory.c b/addressbook/libedata-book/e-data-book-factory.c
index d455472..47e7b6e 100644
--- a/addressbook/libedata-book/e-data-book-factory.c
+++ b/addressbook/libedata-book/e-data-book-factory.c
@@ -23,6 +23,7 @@
#include <config.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <glib-object.h>
#include <glib/gi18n.h>
#include <dbus/dbus-protocol.h>
@@ -37,11 +38,11 @@
#include "e-book-backend.h"
#include "e-book-backend-factory.h"
+#define d(x)
+
static void impl_BookFactory_getBook(EDataBookFactory *factory, const char *IN_uri, DBusGMethodInvocation *context);
#include "e-data-book-factory-glue.h"
-static gchar *nm_dbus_escape_object_path (const gchar *utf8_string);
-
static GMainLoop *loop;
static EDataBookFactory *factory;
extern DBusGConnection *connection;
@@ -61,7 +62,7 @@ G_DEFINE_TYPE(EDataBookFactory, e_data_book_factory, G_TYPE_OBJECT);
struct _EDataBookFactoryPrivate {
/* TODO: as the factory is not threaded these locks could be removed */
- GMutex *backend_lock;
+ GMutex *backends_lock;
GHashTable *backends;
GMutex *books_lock;
@@ -184,7 +185,7 @@ e_data_book_factory_init (EDataBookFactory *factory)
{
factory->priv = E_DATA_BOOK_FACTORY_GET_PRIVATE (factory);
- factory->priv->backend_lock = g_mutex_new ();
+ factory->priv->backends_lock = g_mutex_new ();
factory->priv->backends = g_hash_table_new (g_str_hash, g_str_equal);
factory->priv->books_lock = g_mutex_new ();
@@ -233,45 +234,57 @@ e_data_book_factory_lookup_backend_factory (EDataBookFactory *factory,
return backend_factory;
}
-static char *
-make_path_name (const char* uri)
+static gchar *
+construct_book_factory_path (void)
{
- char *s, *path;
- s = nm_dbus_escape_object_path (uri);
- path = g_strdup_printf ("/org/gnome/evolution/dataserver/addressbook/%s", s);
- g_free (s);
- return path;
+ static volatile gint counter = 1;
+
+ return g_strdup_printf (
+ "/org/gnome/evolution/dataserver/addressbook/%d/%u",
+ getpid (),
+ g_atomic_int_exchange_and_add (&counter, 1));
}
static void
my_remove (char *key, GObject *dead)
{
- g_mutex_lock (factory->priv->books_lock);
- g_hash_table_remove (factory->priv->books, key);
- g_mutex_unlock (factory->priv->books_lock);
+ EDataBookFactoryPrivate *priv = factory->priv;
+ GHashTableIter iter;
+ gpointer hkey, hvalue;
- g_free (key);
+ d (g_debug ("%s (%p) is dead", key, dead));
- /* If there are no open books, start a timer to quit */
- if (factory->priv->exit_timeout == 0 && g_hash_table_size (factory->priv->books) == 0) {
- factory->priv->exit_timeout = g_timeout_add (10000, (GSourceFunc)g_main_loop_quit, loop);
+ g_hash_table_remove (priv->books, key);
+
+ g_hash_table_iter_init (&iter, priv->connections);
+ while (g_hash_table_iter_next (&iter, &hkey, &hvalue)) {
+ GList *books = hvalue;
+
+ if (g_list_find (books, dead)) {
+ books = g_list_remove (books, dead);
+ if (books) {
+ g_hash_table_insert (priv->connections, g_strdup (hkey), books);
+ } else {
+ g_hash_table_remove (priv->connections, hkey);
+ }
+
+ break;
+ }
}
-}
-static void
-book_closed_cb (EDataBook *book, const char *client)
-{
- GList *list;
+ g_free (key);
- list = g_hash_table_lookup (factory->priv->connections, client);
- list = g_list_remove (list, book);
- g_hash_table_insert (factory->priv->connections, g_strdup (client), list);
+ /* If there are no open books, start a timer to quit */
+ if (priv->exit_timeout == 0 && g_hash_table_size (priv->books) == 0) {
+ priv->exit_timeout = g_timeout_add (10000, (GSourceFunc)g_main_loop_quit, loop);
+ }
}
static void
impl_BookFactory_getBook(EDataBookFactory *factory, const char *IN_source, DBusGMethodInvocation *context)
{
EDataBook *book;
+ EBookBackend *backend;
EDataBookFactoryPrivate *priv = factory->priv;
ESource *source;
char *uri, *path, *sender;
@@ -288,30 +301,47 @@ impl_BookFactory_getBook(EDataBookFactory *factory, const char *IN_source, DBusG
priv->exit_timeout = 0;
}
- g_mutex_lock (priv->books_lock);
+ g_mutex_lock (priv->backends_lock);
source = e_source_new_from_standalone_xml (IN_source);
if (!source) {
+ g_mutex_unlock (priv->backends_lock);
dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_NO_SUCH_BOOK, _("Invalid source")));
+ return;
}
uri = e_source_get_uri (source);
- path = make_path_name (uri);
- book = g_hash_table_lookup (priv->books, path);
- if (book == NULL) {
- EBookBackend *backend = NULL;
- backend = e_book_backend_factory_new_backend (e_data_book_factory_lookup_backend_factory (factory, uri));
- book = e_data_book_new (backend, source, book_closed_cb);
- e_book_backend_set_mode (backend, factory->priv->mode);
- g_hash_table_insert (priv->books, g_strdup (path), book);
- e_book_backend_add_client (backend, book);
- dbus_g_connection_register_g_object (connection, path, G_OBJECT (book));
- g_object_weak_ref (G_OBJECT (book), (GWeakNotify)my_remove, g_strdup (path));
- g_object_unref (backend); /* The book takes a reference to the backend */
- } else {
- g_object_ref (book);
+
+ g_mutex_lock (priv->books_lock);
+ backend = g_hash_table_lookup (priv->backends, uri);
+
+ if (!backend) {
+ EBookBackendFactory *backend_factory = e_data_book_factory_lookup_backend_factory (factory, uri);
+
+ if (backend_factory)
+ backend = e_book_backend_factory_new_backend (backend_factory);
+
+ if (backend)
+ g_hash_table_insert (priv->backends, g_strdup (uri), backend);
}
- g_object_unref (source);
+
+ if (!backend) {
+ g_free (uri);
+ g_object_unref (source);
+
+ g_mutex_unlock (priv->books_lock);
+ g_mutex_unlock (priv->backends_lock);
+ dbus_g_method_return_error (context, g_error_new (E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_NO_SUCH_BOOK, _("Invalid source")));
+ return;
+ }
+
+ path = construct_book_factory_path ();
+ book = e_data_book_new (backend, source);
+ e_book_backend_set_mode (backend, priv->mode);
+ g_hash_table_insert (priv->books, g_strdup (path), book);
+ e_book_backend_add_client (backend, book);
+ dbus_g_connection_register_g_object (connection, path, G_OBJECT (book));
+ g_object_weak_ref (G_OBJECT (book), (GWeakNotify)my_remove, g_strdup (path));
/* Update the hash of open connections */
g_mutex_lock (priv->connections_lock);
@@ -322,6 +352,10 @@ impl_BookFactory_getBook(EDataBookFactory *factory, const char *IN_source, DBusG
g_mutex_unlock (priv->connections_lock);
g_mutex_unlock (priv->books_lock);
+ g_mutex_unlock (priv->backends_lock);
+
+ g_object_unref (source);
+ g_free (uri);
dbus_g_method_return (context, path);
}
@@ -419,39 +453,7 @@ main (int argc, char **argv)
dbus_g_connection_unref (connection);
- return 0;
-}
-
-/* Stolen from http://cvs.gnome.org/viewcvs/NetworkManager/utils/nm-utils.c */
-static gchar *nm_dbus_escape_object_path (const gchar *utf8_string)
-{
- const gchar *p;
- GString *string;
-
- g_return_val_if_fail (utf8_string != NULL, NULL);
- g_return_val_if_fail (g_utf8_validate (utf8_string, -1, NULL), NULL);
-
- string = g_string_sized_new ((strlen (utf8_string) + 1) * 2);
-
- for (p = utf8_string; *p != '\0'; p = g_utf8_next_char (p))
- {
- gunichar character;
+ printf ("Bye.\n");
- character = g_utf8_get_char (p);
-
- if (((character >= ((gunichar) 'a')) &&
- (character <= ((gunichar) 'z'))) ||
- ((character >= ((gunichar) 'A')) &&
- (character <= ((gunichar) 'Z'))) ||
- ((character >= ((gunichar) '0')) &&
- (character <= ((gunichar) '9'))))
- {
- g_string_append_c (string, (gchar) character);
- continue;
- }
-
- g_string_append_printf (string, "_%x_", character);
- }
-
- return g_string_free (string, FALSE);
+ return 0;
}
diff --git a/addressbook/libedata-book/e-data-book.c b/addressbook/libedata-book/e-data-book.c
index 81fd46f..da21c06 100644
--- a/addressbook/libedata-book/e-data-book.c
+++ b/addressbook/libedata-book/e-data-book.c
@@ -257,13 +257,14 @@ e_data_book_init (EDataBook *ebook)
}
EDataBook *
-e_data_book_new (EBookBackend *backend, ESource *source, EDataBookClosedCallback closed_cb)
+e_data_book_new (EBookBackend *backend, ESource *source)
{
EDataBook *book;
+
book = g_object_new (E_TYPE_DATA_BOOK, NULL);
book->backend = g_object_ref (backend);
book->source = g_object_ref (source);
- book->closed_cb = closed_cb;
+
return book;
}
@@ -645,14 +646,7 @@ impl_AddressBook_Book_cancelOperation(EDataBook *book, GError **error)
static void
impl_AddressBook_Book_close(EDataBook *book, DBusGMethodInvocation *context)
{
- char *sender;
-
- sender = dbus_g_method_get_sender (context);
-
- book->closed_cb (book, sender);
-
- g_free (sender);
-
+ e_book_backend_remove_client (e_data_book_get_backend (book), book);
g_object_unref (book);
dbus_g_method_return (context);
diff --git a/addressbook/libedata-book/e-data-book.h b/addressbook/libedata-book/e-data-book.h
index d7c9d7d..6b58a0d 100644
--- a/addressbook/libedata-book/e-data-book.h
+++ b/addressbook/libedata-book/e-data-book.h
@@ -38,14 +38,10 @@ G_BEGIN_DECLS
#define E_IS_DATA_BOOK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_DATA_BOOK))
#define E_DATA_BOOK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), E_TYPE_DATA_BOOK, EDataBookClass))
-typedef void (* EDataBookClosedCallback) (EDataBook *book, const char *client);
-
struct _EDataBook {
GObject parent;
EBookBackend *backend;
ESource *source;
- /* TODO: move to private data */
- EDataBookClosedCallback closed_cb;
};
struct _EDataBookClass {
@@ -55,11 +51,9 @@ struct _EDataBookClass {
GQuark e_data_book_error_quark (void);
#define E_DATA_BOOK_ERROR e_data_book_error_quark ()
-EDataBook *e_data_book_new (EBookBackend *backend,
- ESource *source,
- EDataBookClosedCallback closed_cb);
-EBookBackend *e_data_book_get_backend (EDataBook *book);
-ESource *e_data_book_get_source (EDataBook *book);
+EDataBook *e_data_book_new (EBookBackend *backend, ESource *source);
+EBookBackend *e_data_book_get_backend (EDataBook *book);
+ESource *e_data_book_get_source (EDataBook *book);
void e_data_book_respond_open (EDataBook *book,
guint32 opid,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]