aboutsummaryrefslogtreecommitdiffstats
path: root/addressbook/backend/pas/pas-book-factory.c
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@helixcode.com>2000-05-01 12:19:47 +0800
committerFederico Mena Quintero <federico@src.gnome.org>2000-05-01 12:19:47 +0800
commitd936a5c38a6125548ec44eac981a26d42ce72413 (patch)
tree3b8b7793b3d25ab602d8e2d5c78b6a9dd68cb70b /addressbook/backend/pas/pas-book-factory.c
parenteb5dc08dc91a593357a6c1b1db98fac8cdb1662e (diff)
downloadgsoc2013-evolution-d936a5c38a6125548ec44eac981a26d42ce72413.tar
gsoc2013-evolution-d936a5c38a6125548ec44eac981a26d42ce72413.tar.gz
gsoc2013-evolution-d936a5c38a6125548ec44eac981a26d42ce72413.tar.bz2
gsoc2013-evolution-d936a5c38a6125548ec44eac981a26d42ce72413.tar.lz
gsoc2013-evolution-d936a5c38a6125548ec44eac981a26d42ce72413.tar.xz
gsoc2013-evolution-d936a5c38a6125548ec44eac981a26d42ce72413.tar.zst
gsoc2013-evolution-d936a5c38a6125548ec44eac981a26d42ce72413.zip
Added new status values for the IDL stuff.
2000-04-30 Federico Mena Quintero <federico@helixcode.com> * backend/ebook/e-book-types.h (EBookStatus): Added new status values for the IDL stuff. * backend/pas/pas-book-factory.h (PASBookFactoryClass): New "last_book_gone" signal. * backend/pas/pas-book-factory.c (pas_book_factory_launch_backend): Better error handling. (pas_book_factory_process_queue): Let pas_book_factory_process_request() free the request. (pas_book_factory_process_request): Free the request here. Perform better error handling. (free_active_server_map_entry): Free an active server map entry; free the URI key and unref the backend value. This function was renamed; the old one was trying to CORBA_Object_unref() a GTK+ object! (remove_backends_entry): Free a backend table entry; free the URI key. (backend_last_client_gone_cb): Remove the backend from the active server map and emit the "last_book_gone" signal if appropriate. (pas_book_factory_get_n_backends): New function to query the number of running backends in an addressbook factory. * backend/idl/addressbook.idl (BookListener::CallStatus): Added a ProtocolNotSupported code. This is for when the addressbook factory cannot find a provider for the requested URI. * backend/pas/pas-backend.h (PASBackendClass): New "last_client_gone" signal. (PASBackendClass): New get_uri virtual method. * backend/pas/pas-backend.c (pas_backend_load_uri): Return a gboolean success code. (pas_backend_add_client): Return a gboolean success code. (pas_backend_last_client_gone): New function used by backend implementations to notify upwards when the backend's last client is destroyed. (pas_backend_get_uri): New function to get the URI of a backend. * backend/pas/pas-backend-file.c (pas_backend_file_add_client): Pass the backend as the closure data to the "destroy" handler of the book. We cannot call pas_book_get_backend() in the callback since the book's private data has already been destroyed when the callback is invoked. Alternatively, we could move the private data destruction step to the book's ::finalize() method. (pas_backend_file_book_destroy_cb): Get the backend from the callback's data, not from the book. (pas_backend_file_remove_client): Remove the book from the list of clients. When all clients go away, call pas_backend_last_client_gone(). (PASBackendFilePrivate): Added an uri field. (pas_backend_file_get_uri): Implement the get_uri method. (pas_backend_file_load_uri): Return a gboolean success code. Also, store the URI in the private structure. (pas_backend_file_add_client): Return a gboolean success code. Also, call pas_backend_last_client_gone() if appropriate. (pas_backend_file_destroy): Free the bf->priv->uri. * backend/pas/pas-backend-ldap.c (pas_backend_ldap_add_client): Pass the backend as the closure data to the "destroy" handler of the book. See above for rationale. (pas_backend_ldap_book_destroy_cb): Get the backend from the callback's data. (pas_backend_ldap_remove_client): Remove the book from the list of clients. When all clients go away, call pas_backend_last_client_gone(). (pas_backend_ldap_load_uri): Return a gboolean success code. (pas_backend_ldap_add_client): Return a gboolean success code. Also, call pas_backend_last_client_gone() if appropriate. (PASBackendLDAPPrivate): New uri field. (pas_backend_ldap_get_uri): Implement the get_uri method. (pas_backend_ldap_load_uri): Store the uri in the private structure. (pas_backend_ldap_destroy): Free the bl->priv->uri. svn path=/trunk/; revision=2705
Diffstat (limited to 'addressbook/backend/pas/pas-book-factory.c')
-rw-r--r--addressbook/backend/pas/pas-book-factory.c221
1 files changed, 173 insertions, 48 deletions
diff --git a/addressbook/backend/pas/pas-book-factory.c b/addressbook/backend/pas/pas-book-factory.c
index 77cc269f19..aec28c650e 100644
--- a/addressbook/backend/pas/pas-book-factory.c
+++ b/addressbook/backend/pas/pas-book-factory.c
@@ -35,6 +35,14 @@ struct _PASBookFactoryPrivate {
GList *queued_requests;
};
+/* Signal IDs */
+enum {
+ LAST_BOOK_GONE,
+ LAST_SIGNAL
+};
+
+static guint factory_signals[LAST_SIGNAL];
+
static char *
pas_book_factory_canonicalize_uri (const char *uri)
{
@@ -77,8 +85,6 @@ pas_book_factory_register_backend (PASBookFactory *factory,
g_return_if_fail (proto != NULL);
g_return_if_fail (backend != NULL);
-
-
if (g_hash_table_lookup (factory->priv->backends, proto) != NULL) {
g_warning ("pas_book_factory_register_backend: "
"Proto \"%s\" already registered!\n", proto);
@@ -88,11 +94,62 @@ pas_book_factory_register_backend (PASBookFactory *factory,
g_strdup (proto), backend);
}
+/**
+ * pas_book_factory_get_n_backends:
+ * @factory: An addressbook factory.
+ *
+ * Queries the number of running addressbook backends in an addressbook factory.
+ *
+ * Return value: Number of running backends.
+ **/
+int
+pas_book_factory_get_n_backends (PASBookFactory *factory)
+{
+ g_return_val_if_fail (factory != NULL, -1);
+ g_return_val_if_fail (PAS_IS_BOOK_FACTORY (factory), -1);
+
+ return g_hash_table_size (factory->priv->active_server_map);
+}
+
+/* Callback used when a backend loses its last connected client */
+static void
+backend_last_client_gone_cb (PASBackend *backend, gpointer data)
+{
+ PASBookFactory *factory;
+ const char *uri;
+ gpointer orig_key;
+ gboolean result;
+ char *orig_uri;
+
+ factory = PAS_BOOK_FACTORY (data);
+
+ /* Remove the backend from the active server map */
+
+ uri = pas_backend_get_uri (backend);
+ g_assert (uri != NULL);
+
+ result = g_hash_table_lookup_extended (factory->priv->active_server_map, uri,
+ &orig_key, NULL);
+ g_assert (result != FALSE);
+
+ orig_uri = orig_key;
+
+ g_hash_table_remove (factory->priv->active_server_map, orig_uri);
+ g_free (orig_uri);
+
+ gtk_object_unref (GTK_OBJECT (backend));
+
+ /* Notify upstream if there are no more backends */
+
+ if (g_hash_table_size (factory->priv->active_server_map) == 0)
+ gtk_signal_emit (GTK_OBJECT (factory), factory_signals[LAST_BOOK_GONE]);
+}
+
static PASBackendFactoryFn
pas_book_factory_lookup_backend_factory (PASBookFactory *factory,
const char *uri)
{
- PASBackendFactoryFn backend;
+ PASBackendFactoryFn backend_fn;
char *proto;
char *canonical_uri;
@@ -110,32 +167,70 @@ pas_book_factory_lookup_backend_factory (PASBookFactory *factory,
return NULL;
}
- backend = g_hash_table_lookup (factory->priv->backends, proto);
+ backend_fn = g_hash_table_lookup (factory->priv->backends, proto);
g_free (proto);
g_free (canonical_uri);
- return backend;
+ return backend_fn;
}
static PASBackend *
pas_book_factory_launch_backend (PASBookFactory *factory,
- PASBookFactoryQueuedRequest *request)
+ Evolution_BookListener listener,
+ const char *uri)
{
PASBackendFactoryFn backend_factory;
PASBackend *backend;
backend_factory = pas_book_factory_lookup_backend_factory (
- factory, request->uri);
- g_assert (backend_factory != NULL);
+ factory, uri);
+
+ if (!backend_factory) {
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+ Evolution_BookListener_respond_open_book (
+ listener,
+ Evolution_BookListener_ProtocolNotSupported,
+ CORBA_OBJECT_NIL,
+ &ev);
- backend = (backend_factory) ();
- g_assert (backend != NULL);
+ if (ev._major != CORBA_NO_EXCEPTION)
+ g_message ("pas_book_factory_launch_backend(): could not notify "
+ "the listener");
+
+ CORBA_exception_free (&ev);
+ return NULL;
+ }
+
+ backend = (* backend_factory) ();
+ if (!backend) {
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+ Evolution_BookListener_respond_open_book (
+ listener,
+ Evolution_BookListener_OtherError,
+ CORBA_OBJECT_NIL,
+ &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION)
+ g_message ("pas_book_factory_launch_backend(): could not notify "
+ "the listener");
+
+ CORBA_exception_free (&ev);
+ return NULL;
+ }
g_hash_table_insert (factory->priv->active_server_map,
- g_strdup (request->uri),
+ g_strdup (uri),
backend);
+ gtk_signal_connect (GTK_OBJECT (backend), "last_client_gone",
+ backend_last_client_gone_cb,
+ factory);
+
return backend;
}
@@ -144,24 +239,43 @@ pas_book_factory_process_request (PASBookFactory *factory,
PASBookFactoryQueuedRequest *request)
{
PASBackend *backend;
+ char *uri;
+ Evolution_BookListener listener;
+ CORBA_Environment ev;
- request = factory->priv->queued_requests->data;
+ uri = request->uri;
+ listener = request->listener;
+ g_free (request);
- backend = g_hash_table_lookup (factory->priv->active_server_map, request->uri);
+ /* Look up the backend and create one if needed */
- if (backend == NULL) {
+ backend = g_hash_table_lookup (factory->priv->active_server_map, uri);
- backend = pas_book_factory_launch_backend (factory, request);
- pas_backend_add_client (backend, request->listener);
- pas_backend_load_uri (backend, request->uri);
- g_free (request->uri);
+ if (!backend) {
+ backend = pas_book_factory_launch_backend (factory, listener, uri);
+ if (!backend)
+ goto out;
- return;
+ if (!pas_backend_add_client (backend, listener))
+ goto out;
+
+ pas_backend_load_uri (backend, uri);
+
+ goto out;
}
- g_free (request->uri);
+ pas_backend_add_client (backend, listener);
+
+ out:
+ g_free (uri);
- pas_backend_add_client (backend, request->listener);
+ CORBA_exception_init (&ev);
+ CORBA_Object_release (listener, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION)
+ g_message ("pas_book_factory_process_request(): could not release the listener");
+
+ CORBA_exception_free (&ev);
}
static gboolean
@@ -170,15 +284,16 @@ pas_book_factory_process_queue (PASBookFactory *factory)
/* Process pending Book-creation requests. */
if (factory->priv->queued_requests != NULL) {
PASBookFactoryQueuedRequest *request;
+ GList *l;
- request = factory->priv->queued_requests->data;
+ l = factory->priv->queued_requests;
+ request = l->data;
pas_book_factory_process_request (factory, request);
- factory->priv->queued_requests = g_list_remove (
- factory->priv->queued_requests, request);
-
- g_free (request);
+ factory->priv->queued_requests = g_list_remove_link (
+ factory->priv->queued_requests, l);
+ g_list_free_1 (l);
}
if (factory->priv->queued_requests == NULL) {
@@ -343,7 +458,6 @@ register_factory (CORBA_Object obj)
int ret;
CORBA_exception_init (&ev);
-
ret = goad_server_register (NULL, obj, PAS_BOOK_FACTORY_GOAD_ID, "server", &ev);
if (ev._major != CORBA_NO_EXCEPTION) {
@@ -394,27 +508,26 @@ pas_book_factory_init (PASBookFactory *factory)
factory->priv->queued_requests = NULL;
}
-static gboolean
-pas_book_factory_remove_asm_entry (gpointer key, gpointer value,
- gpointer data)
+static void
+free_active_server_map_entry (gpointer key, gpointer value, gpointer data)
{
- CORBA_Environment ev;
+ char *uri;
+ PASBackend *backend;
- g_free (key);
+ uri = key;
+ g_free (uri);
- CORBA_exception_init (&ev);
- CORBA_Object_release ((CORBA_Object) value, &ev);
- CORBA_exception_free (&ev);
-
- return TRUE;
+ backend = PAS_BACKEND (value);
+ gtk_object_unref (GTK_OBJECT (backend));
}
-static gboolean
-pas_book_factory_remove_backend_entry (gpointer key, gpointer value,
- gpointer data)
+static void
+remove_backends_entry (gpointer key, gpointer value, gpointer data)
{
- g_free (key);
- return TRUE;
+ char *uri;
+
+ uri = key;
+ g_free (uri);
}
static void
@@ -438,15 +551,17 @@ pas_book_factory_destroy (GtkObject *object)
g_list_free (factory->priv->queued_requests);
factory->priv->queued_requests = NULL;
- g_hash_table_foreach_remove (factory->priv->active_server_map,
- pas_book_factory_remove_asm_entry,
- NULL);
+ g_hash_table_foreach (factory->priv->active_server_map,
+ free_active_server_map_entry,
+ NULL);
g_hash_table_destroy (factory->priv->active_server_map);
+ factory->priv->active_server_map = NULL;
- g_hash_table_foreach_remove (factory->priv->backends,
- pas_book_factory_remove_backend_entry,
- NULL);
+ g_hash_table_foreach (factory->priv->backends,
+ remove_backends_entry,
+ NULL);
g_hash_table_destroy (factory->priv->backends);
+ factory->priv->backends = NULL;
g_free (factory->priv);
@@ -480,6 +595,16 @@ pas_book_factory_class_init (PASBookFactoryClass *klass)
pas_book_factory_parent_class = gtk_type_class (bonobo_object_get_type ());
+ factory_signals[LAST_BOOK_GONE] =
+ gtk_signal_new ("last_book_gone",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (PASBookFactoryClass, last_book_gone),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, factory_signals, LAST_SIGNAL);
+
object_class->destroy = pas_book_factory_destroy;
pas_book_factory_corba_class_init ();