[evolution-kolab/ek-wip-porting] CamelIMAPXExtdConnManager: implement our own paths to the IMAPX untagged
- From: Christian Hilberg <chilberg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-kolab/ek-wip-porting] CamelIMAPXExtdConnManager: implement our own paths to the IMAPX untagged
- Date: Fri, 20 Jan 2012 16:28:10 +0000 (UTC)
commit f4b3a3e2ee19ca269ee12bc6b8fd52ef7609d09b
Author: Christian Hilberg <hilberg kernelconcepts de>
Date: Fri Jan 20 17:19:15 2012 +0100
CamelIMAPXExtdConnManager: implement our own paths to the IMAPX
untagged response handler
* our extended conn manager needs to make sure that the
code paths in our own extended objects are followed
down the road to the IMAPX untagged response handler
* without intervention, CamelIMAPXServer::imapx_untagged()
will be called upon untagged responses, whereas we
need to end in CamelIMAPXExtdServer::extd_server_untagged()
.../imapx/camel-imapx-extd-conn-manager.c | 258 ++++++++++++++++++--
1 files changed, 241 insertions(+), 17 deletions(-)
---
diff --git a/src/camel/providers/imapx/camel-imapx-extd-conn-manager.c b/src/camel/providers/imapx/camel-imapx-extd-conn-manager.c
index 6b828f7..9e009db 100644
--- a/src/camel/providers/imapx/camel-imapx-extd-conn-manager.c
+++ b/src/camel/providers/imapx/camel-imapx-extd-conn-manager.c
@@ -29,19 +29,21 @@
#include <config.h>
#endif
+#include "camel-imapx-utils.h"
#include "camel-imapx-extd-conn-manager.h"
+#include "camel-imapx-conn-manager-defs.h"
+#include "camel-imapx-conn-manager-friend.h"
/*----------------------------------------------------------------------------*/
-/* dupe of enum in camel-imapx-conn-manager.c */
-enum {
- PROP_0,
- PROP_STORE
-};
-
G_DEFINE_TYPE (CamelIMAPXExtdConnManager, camel_imapx_extd_conn_manager, CAMEL_TYPE_IMAPX_CONN_MANAGER)
/*----------------------------------------------------------------------------*/
+/* forward declarations */
+
+static void extd_conn_manager_prune_connections (CamelIMAPXConnManager *self);
+
+/*----------------------------------------------------------------------------*/
/* object init */
static void
@@ -55,6 +57,8 @@ camel_imapx_extd_conn_manager_dispose (GObject *object)
{
g_assert (CAMEL_IS_IMAPX_EXTD_CONN_MANAGER (object));
+ extd_conn_manager_prune_connections (CAMEL_IMAPX_CONN_MANAGER (object));
+
G_OBJECT_CLASS (camel_imapx_extd_conn_manager_parent_class)->dispose (object);
}
@@ -67,6 +71,219 @@ camel_imapx_extd_conn_manager_finalize (GObject *object)
}
/*----------------------------------------------------------------------------*/
+/* local statics */
+
+static void
+extd_conn_manager_free_connection (gpointer data,
+ gpointer user_data)
+{
+ /* modified dupe of free_connection() */
+
+ ConnectionInfo *cinfo = (ConnectionInfo *) data;
+ CamelIMAPXExtdServer *eserver = CAMEL_IMAPX_EXTD_SERVER (cinfo->conn);
+
+ /* modified */
+ camel_imapx_extd_server_connect (CAMEL_IMAPX_SERVER (eserver),
+ NULL,
+ NULL);
+
+ g_object_unref (eserver);
+ g_hash_table_destroy (cinfo->folders);
+ g_free (cinfo->selected_folder);
+
+ g_free (cinfo);
+}
+
+static void
+extd_conn_manager_prune_connections (CamelIMAPXConnManager *self)
+{
+ /* modified dupe of imapx_prune_connections */
+
+ g_assert (CAMEL_IS_IMAPX_EXTD_CONN_MANAGER (self));
+
+ CON_LOCK (self);
+
+ self->priv->clearing_connections = TRUE;
+ g_list_foreach (self->priv->connections,
+ /* modified */
+ (GFunc) extd_conn_manager_free_connection,
+ NULL);
+ self->priv->connections = NULL;
+ self->priv->clearing_connections = FALSE;
+
+ CON_UNLOCK (self);
+}
+
+/* TODO destroy unused connections in a time-out loop */
+static void
+extd_conn_manager_shutdown (CamelIMAPXConnManager *self,
+ CamelIMAPXServer *server)
+{
+ /* modified dupe of imapx_conn_shutdown() */
+
+ GList *l = NULL;
+ ConnectionInfo *cinfo = NULL;
+ gboolean found = FALSE;
+
+ g_assert (CAMEL_IS_IMAPX_EXTD_CONN_MANAGER (self));
+ g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (server));
+
+ /* when clearing connections then other thread than a parser thread,
+ * in which this function is called, holds the CON_LOCK, thus skip
+ * this all, because otherwise a deadlock will happen.
+ * The connection will be freed later anyway. */
+ if (self->priv->clearing_connections) {
+ c(server->tagprefix, "%s: called on %p when clearing connections, skipping it...\n", G_STRFUNC, server);
+ return;
+ }
+
+ CON_LOCK (self);
+
+ for (l = self->priv->connections; l != NULL; l = g_list_next (l)) {
+ cinfo = (ConnectionInfo *) l->data;
+ if (cinfo->conn == server) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found) {
+ self->priv->connections = g_list_remove (self->priv->connections, cinfo);
+ /* modified */
+ extd_conn_manager_free_connection (cinfo, GINT_TO_POINTER (1));
+ }
+
+ CON_UNLOCK (self);
+}
+
+static void
+extd_conn_manager_update_select (CamelIMAPXServer *self,
+ const gchar *selected_folder,
+ CamelIMAPXConnManager *con_man)
+{
+ GList *l = NULL;
+ ConnectionInfo *cinfo = NULL;
+ gboolean found = FALSE;
+
+ CON_LOCK (con_man);
+
+ for (l = con_man->priv->connections; l != NULL; l = g_list_next (l)) {
+ cinfo = (ConnectionInfo *) l->data;
+ if (cinfo->conn == self) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found) {
+ if (cinfo->selected_folder) {
+ IMAPXJobQueueInfo *jinfo;
+
+ jinfo = camel_imapx_server_get_job_queue_info (cinfo->conn);
+ if (!g_hash_table_lookup (jinfo->folders, cinfo->selected_folder)) {
+ g_hash_table_remove (cinfo->folders, cinfo->selected_folder);
+ c(self->tagprefix, "Removed folder %s from connection folder list - select changed \n", cinfo->selected_folder);
+ }
+ camel_imapx_destroy_job_queue_info (jinfo);
+ g_free (cinfo->selected_folder);
+ }
+
+ cinfo->selected_folder = g_strdup (selected_folder);
+ }
+
+ CON_UNLOCK (con_man);
+}
+
+static CamelIMAPXExtdServer*
+extd_conn_manager_create_new_connection (CamelIMAPXConnManager *self,
+ const gchar *foldername,
+ GCancellable *cancellable,
+ GError **err)
+{
+ /* modified dupe of imapx_create_new_connection() */
+
+ CamelIMAPXExtdServer *eserver = NULL;
+ CamelIMAPXStore *imapx_store = NULL;
+ CamelStore *store = NULL;
+ CamelService *service = NULL;
+ ConnectionInfo *cinfo = NULL;
+ gboolean success = FALSE;
+
+ g_assert (CAMEL_IS_IMAPX_EXTD_CONN_MANAGER (self));
+ g_assert (foldername != NULL);
+ /* cancellable may be NULL */
+ g_return_val_if_fail (err == NULL || *err == NULL, NULL);
+
+ store = self->priv->store;
+ service = CAMEL_SERVICE (store);
+ imapx_store = CAMEL_IMAPX_STORE (store);
+
+ CON_LOCK (self);
+
+ camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+
+ eserver = camel_imapx_extd_server_new (CAMEL_IMAPX_EXTD_STORE (store));
+
+ /* 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
+ * (and our own CON_LOCK for that matter) 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 (eserver);
+ success = camel_imapx_extd_server_connect (CAMEL_IMAPX_SERVER (eserver),
+ cancellable,
+ err);
+ g_object_unref (imapx_store->authenticating_server);
+ imapx_store->authenticating_server = NULL;
+
+ if (success) {
+ g_object_ref (eserver);
+ } else {
+ g_object_unref (eserver);
+
+ camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+ CON_UNLOCK (self);
+
+ return NULL;
+ }
+
+ /* modified */
+ g_signal_connect (eserver, "shutdown", G_CALLBACK (extd_conn_manager_shutdown), self);
+ g_signal_connect (eserver, "select_changed", G_CALLBACK (extd_conn_manager_update_select), self);
+
+ camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+
+ cinfo = g_new0 (ConnectionInfo, 1);
+ cinfo->conn = CAMEL_IMAPX_SERVER (eserver);
+ cinfo->folders = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
+
+ if (foldername)
+ g_hash_table_insert (cinfo->folders, g_strdup (foldername), GINT_TO_POINTER (1));
+
+ self->priv->connections = g_list_prepend (self->priv->connections, cinfo);
+
+ c(CAMEL_IMAPX_SERVER (eserver)->tagprefix,
+ "Created new connection for %s and total connections %d \n",
+ foldername,
+ g_list_length (self->priv->connections));
+
+ CON_UNLOCK (self);
+
+ return eserver;
+}
+
+/*----------------------------------------------------------------------------*/
/* class functions */
static CamelStore*
@@ -88,25 +305,32 @@ imapx_extd_conn_manager_get_connection (CamelIMAPXConnManager *self,
GCancellable *cancellable,
GError **err)
{
+ /* modified dupe of imapx_conn_manager_get_connection() */
+
+ CamelIMAPXExtdServer *eserver = NULL;
CamelIMAPXServer *server = NULL;
- GError *tmp_err = NULL;
g_assert (CAMEL_IS_IMAPX_EXTD_CONN_MANAGER (self));
g_assert (foldername != NULL);
/* cancellable may be NULL */
g_return_val_if_fail (err == NULL || *err == NULL, NULL);
- server = camel_imapx_conn_manager_get_connection (self,
- foldername,
- cancellable,
- &tmp_err);
- if (server == NULL) {
- if (tmp_err != NULL)
- g_propagate_error (err, tmp_err);
- return NULL;
+ CON_LOCK (self);
+
+ /* modified */
+ server = camel_imapx_conn_manager_find_connection (self, foldername);
+ if (!server) {
+ /* modified */
+ eserver = extd_conn_manager_create_new_connection (self,
+ foldername,
+ cancellable,
+ err);
}
- g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (server));
+ CON_UNLOCK (self);
+
+ if (eserver != NULL)
+ server = CAMEL_IMAPX_SERVER (eserver);
return server;
}
@@ -116,7 +340,7 @@ imapx_extd_conn_manager_close_connections (CamelIMAPXConnManager *self)
{
g_assert (CAMEL_IS_IMAPX_EXTD_CONN_MANAGER (self));
- camel_imapx_conn_manager_close_connections (self);
+ extd_conn_manager_prune_connections (CAMEL_IMAPX_CONN_MANAGER (self));
}
static GList*
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]