[evolution-data-server] Bug #592159 - Support multiple factories for address-book with dbus



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]