[evolution-kolab/ek-wip-porting] CamelKolabIMAPXConnManager: implemented our own "get_connection" path
- From: Christian Hilberg <chilberg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-kolab/ek-wip-porting] CamelKolabIMAPXConnManager: implemented our own "get_connection" path
- Date: Wed, 7 Mar 2012 15:32:09 +0000 (UTC)
commit 61dc29bd277f51a7f5d0f773aff7ca01b891f7b2
Author: Christian Hilberg <hilberg kernelconcepts de>
Date: Wed Mar 7 16:28:29 2012 +0100
CamelKolabIMAPXConnManager: implemented our own "get_connection" path
* same as in the parent, we need to implement our own
code path for getting a connection here
* otherwise we will not get a CamelKolabIMAPXServer
when requesting a new server connection, but it's
parent type
* moreover, the locking mechanisms will fail since
they will try to get a connection lock on the
wrong object
src/camel/camel-kolab-imapx-conn-manager.c | 155 ++++++++++++++++++++++++----
src/camel/camel-kolab-imapx-conn-manager.h | 1 -
2 files changed, 135 insertions(+), 21 deletions(-)
---
diff --git a/src/camel/camel-kolab-imapx-conn-manager.c b/src/camel/camel-kolab-imapx-conn-manager.c
index b9ce755..b2b1c37 100644
--- a/src/camel/camel-kolab-imapx-conn-manager.c
+++ b/src/camel/camel-kolab-imapx-conn-manager.c
@@ -29,15 +29,15 @@
#include <config.h>
#endif
+#include "camel-kolab-imapx-server.h"
+
#include "camel-kolab-imapx-conn-manager.h"
-/*----------------------------------------------------------------------------*/
+#include <camel/providers/imapx/camel-imapx-conn-manager-defs.h>
+#include <camel/providers/imapx/camel-imapx-conn-manager-friend.h>
+#include <camel/providers/imapx/camel-imapx-extd-conn-manager-friend.h>
-/* dupe of enum in camel/providers/imapx/camel-imapx-conn-manager.c */
-enum {
- PROP_0,
- PROP_STORE
-};
+/*----------------------------------------------------------------------------*/
G_DEFINE_TYPE (CamelKolabIMAPXConnManager, camel_kolab_imapx_conn_manager, CAMEL_TYPE_IMAPX_EXTD_CONN_MANAGER)
@@ -67,6 +67,116 @@ camel_kolab_imapx_conn_manager_finalize (GObject *object)
}
/*----------------------------------------------------------------------------*/
+/* local statics */
+
+static void
+kolab_imapx_conn_manager_conn_shutdown (CamelIMAPXServer *is,
+ CamelIMAPXConnManager *con_man)
+{
+ g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (is));
+ g_assert (CAMEL_IS_IMAPX_EXTD_CONN_MANAGER (con_man));
+
+ camel_imapx_extd_conn_manager_conn_shutdown (is, con_man);
+}
+
+static void
+kolab_imapx_conn_manager_conn_update_select (CamelIMAPXServer *is,
+ const gchar *selected_folder,
+ CamelIMAPXConnManager *con_man)
+{
+ g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (is));
+ g_assert (selected_folder != NULL);
+ g_assert (CAMEL_IS_IMAPX_EXTD_CONN_MANAGER (con_man));
+
+ camel_imapx_extd_conn_manager_conn_update_select (is,
+ selected_folder,
+ con_man);
+}
+
+static CamelIMAPXServer*
+kolab_imapx_conn_manager_new_connection_unlocked (CamelIMAPXConnManager *con_man,
+ const gchar *folder_name,
+ GCancellable *cancellable,
+ GError **error)
+{
+ /* modified dupe of imapx_conn_manager_get_connection() */
+
+ CamelKolabIMAPXServer *ks = NULL;
+ CamelIMAPXServer *is = NULL;
+ CamelIMAPXStore *imapx_store = NULL;
+ CamelStore *store = con_man->priv->store;
+ CamelService *service = NULL;
+ struct _ConnectionInfo *cinfo = NULL;
+ gboolean success = FALSE;
+
+ g_assert (CAMEL_IS_KOLAB_IMAPX_CONN_MANAGER (con_man));
+ /* folder_name may be NULL */
+ /* cancellable may be NULL */
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ /* Caller must be holding CON_WRITE_LOCK. */
+
+ service = CAMEL_SERVICE (store);
+
+ imapx_store = CAMEL_IMAPX_STORE (store);
+
+ camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+
+ /* Check if we got cancelled while we were waiting. */
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ goto exit;
+
+ ks = camel_kolab_imapx_server_new (CAMEL_KOLAB_IMAPX_STORE (store));
+ is = CAMEL_IMAPX_SERVER (ks);
+
+ /* XXX As part of the connect operation the CamelIMAPXServer will
+ * have to call camel_session_authenticate_sync(), but it has
+ * no way to pass itself through in that call so the service
+ * knows which CamelIMAPXServer is trying to authenticate.
+ *
+ * IMAPX is the only provider that does multiple connections
+ * like this, so I didn't want to pollute the CamelSession and
+ * CamelService authentication APIs with an extra argument.
+ * Instead we do this little hack so the service knows which
+ * CamelIMAPXServer to act on in its authenticate_sync() method.
+ *
+ * Because we're holding the CAMEL_SERVICE_REC_CONNECT_LOCK
+ * we should not have multiple IMAPX connections trying to
+ * authenticate at once, so this should be thread-safe.
+ */
+ imapx_store->authenticating_server = g_object_ref (is);
+ success = camel_imapx_extd_server_connect (is, cancellable, error);
+ g_object_unref (imapx_store->authenticating_server);
+ imapx_store->authenticating_server = NULL;
+
+ if (!success) {
+ g_object_unref (ks);
+ is = NULL;
+ goto exit;
+ }
+
+ g_signal_connect (ks, "shutdown",
+ G_CALLBACK (kolab_imapx_conn_manager_conn_shutdown), con_man);
+ g_signal_connect (ks, "select_changed",
+ G_CALLBACK (kolab_imapx_conn_manager_conn_update_select), con_man);
+
+ cinfo = camel_imapx_conn_manager_connection_info_new (is);
+
+ if (folder_name != NULL)
+ camel_imapx_conn_manager_connection_info_insert_folder_name (cinfo, folder_name);
+
+ /* Takes ownership of the ConnectionInfo. */
+ con_man->priv->connections = g_list_prepend (con_man->priv->connections, cinfo);
+
+ c(is->tagprefix, "Created new connection for %s and total connections %d \n", folder_name, g_list_length (con_man->priv->connections));
+
+ exit:
+ camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+
+ return is;
+}
+
+/*----------------------------------------------------------------------------*/
/* class functions */
static CamelStore*
@@ -88,27 +198,32 @@ kolab_imapx_conn_manager_get_connection (CamelIMAPXConnManager *self,
GCancellable *cancellable,
GError **err)
{
- CamelIMAPXServer *server = NULL;
- GError *tmp_err = NULL;
+ /* modified dupe of function in parent class */
- g_assert (CAMEL_IS_KOLAB_IMAPX_CONN_MANAGER (self));
- g_assert (foldername != NULL);
+ CamelIMAPXServer *is = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_KOLAB_IMAPX_CONN_MANAGER (self), NULL);
+ /* foldername may be NULL */
/* cancellable may be NULL */
g_return_val_if_fail (err == NULL || *err == NULL, NULL);
- server = camel_imapx_extd_conn_manager_get_connection (self,
- foldername,
- cancellable,
- &tmp_err);
- if (server == NULL) {
- if (tmp_err != NULL)
- g_propagate_error (err, tmp_err);
- return NULL;
+ /* Hold the writer lock while we requisition a CamelIMAPXServer
+ * to prevent other threads from adding or removing connections. */
+ CON_WRITE_LOCK (self);
+
+ /* Check if we got cancelled while waiting for the lock. */
+ if (!g_cancellable_set_error_if_cancelled (cancellable, err)) {
+ is = camel_imapx_conn_manager_find_connection_unlocked (self, foldername);
+ if (is == NULL)
+ is = kolab_imapx_conn_manager_new_connection_unlocked (self,
+ foldername,
+ cancellable,
+ err);
}
- g_assert (CAMEL_IS_KOLAB_IMAPX_SERVER (server));
+ CON_WRITE_UNLOCK (self);
- return server;
+ return is;
}
static void
diff --git a/src/camel/camel-kolab-imapx-conn-manager.h b/src/camel/camel-kolab-imapx-conn-manager.h
index fd0b2a4..ba38737 100644
--- a/src/camel/camel-kolab-imapx-conn-manager.h
+++ b/src/camel/camel-kolab-imapx-conn-manager.h
@@ -36,7 +36,6 @@
#include <camel/providers/imapx/camel-imapx-extd-conn-manager.h>
-#include "camel-kolab-imapx-server.h"
#include "camel-kolab-imapx-store.h"
/*----------------------------------------------------------------------------*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]