[evolution-data-server] Add connection manager to imapx
- From: Chenthill Palanisamy <pchen src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Add connection manager to imapx
- Date: Tue, 13 Jul 2010 19:56:16 +0000 (UTC)
commit 0076e53b1f46d5c028db6ed9328c55ca40b44579
Author: Chenthill Palanisamy <pchenthill novell com>
Date: Wed Jul 14 01:00:57 2010 +0530
Add connection manager to imapx
camel/providers/imapx/Makefile.am | 4 +-
camel/providers/imapx/camel-imapx-conn-manager.c | 337 ++++++++++++++++++++++
camel/providers/imapx/camel-imapx-conn-manager.h | 69 +++++
camel/providers/imapx/camel-imapx-folder.c | 31 +-
camel/providers/imapx/camel-imapx-provider.c | 2 -
camel/providers/imapx/camel-imapx-server.c | 14 +-
camel/providers/imapx/camel-imapx-server.h | 2 +-
camel/providers/imapx/camel-imapx-store.c | 90 ++++---
camel/providers/imapx/camel-imapx-store.h | 12 +-
camel/providers/imapx/camel-imapx-utils.c | 4 +-
camel/providers/imapx/camel-imapx-utils.h | 13 +-
11 files changed, 507 insertions(+), 71 deletions(-)
---
diff --git a/camel/providers/imapx/Makefile.am b/camel/providers/imapx/Makefile.am
index 6fc3b8c..1e7a0a3 100644
--- a/camel/providers/imapx/Makefile.am
+++ b/camel/providers/imapx/Makefile.am
@@ -18,7 +18,8 @@ libcamelimapx_la_SOURCES = \
camel-imapx-summary.c \
camel-imapx-store.c \
camel-imapx-folder.c \
- camel-imapx-server.c
+ camel-imapx-server.c \
+ camel-imapx-conn-manager.c
noinst_HEADERS = \
camel-imapx-stream.h \
@@ -27,6 +28,7 @@ noinst_HEADERS = \
camel-imapx-folder.h \
camel-imapx-store.h \
camel-imapx-server.h \
+ camel-imapx-conn-manager.h \
camel-imapx-utils.h
camel-imapx-tokenise.h: camel-imapx-tokens.txt
diff --git a/camel/providers/imapx/camel-imapx-conn-manager.c b/camel/providers/imapx/camel-imapx-conn-manager.c
new file mode 100644
index 0000000..669ff8a
--- /dev/null
+++ b/camel/providers/imapx/camel-imapx-conn-manager.c
@@ -0,0 +1,337 @@
+/*-*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* camel-imap-conn-manager.h
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ * Authors: Chenthill Palanisamy <pchenthill novell com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <glib.h>
+#include "camel-imapx-conn-manager.h"
+#include "camel-imapx-utils.h"
+
+#define c(x) camel_imapx_debug(conman, x)
+
+#define CAMEL_IMAPX_CONN_MANAGER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), CAMEL_TYPE_OBJECT, CamelIMAPXConnManager))
+
+#define CON_LOCK(x) (g_static_rec_mutex_lock(&(x)->priv->con_man_lock))
+#define CON_UNLOCK(x) (g_static_rec_mutex_unlock(&(x)->priv->con_man_lock))
+
+G_DEFINE_TYPE (CamelIMAPXConnManager, camel_imapx_conn_manager, CAMEL_TYPE_OBJECT)
+
+struct _CamelIMAPXConnManagerPrivate {
+ GSList *connections;
+ guint n_connections;
+ CamelStore *store;
+ GStaticRecMutex con_man_lock;
+};
+
+typedef struct {
+ GHashTable *folders;
+ CamelIMAPXServer *conn;
+ gchar *selected_folder;
+} ConnectionInfo;
+
+
+static void
+free_connection (gpointer data, gpointer user_data)
+{
+ ConnectionInfo *cinfo = (ConnectionInfo *) data;
+ CamelIMAPXServer *conn = cinfo->conn;
+
+ camel_imapx_server_connect (conn, 0);
+
+ g_object_unref (conn);
+ g_hash_table_destroy (cinfo->folders);
+
+ g_free (cinfo);
+}
+
+static void
+imapx_prune_connections (CamelIMAPXConnManager *con_man)
+{
+ CON_LOCK(con_man);
+
+ g_slist_foreach (con_man->priv->connections, (GFunc) free_connection, NULL);
+ con_man->priv->connections = NULL;
+
+ CON_UNLOCK(con_man);
+}
+
+static void
+imapx_conn_manager_finalize (GObject *object)
+{
+ CamelIMAPXConnManager *con_man = CAMEL_IMAPX_CONN_MANAGER(object);
+
+ imapx_prune_connections (con_man);
+ g_static_rec_mutex_free (&con_man->priv->con_man_lock);
+ g_object_unref (con_man->priv->store);
+}
+
+static void
+camel_imapx_conn_manager_class_init (CamelIMAPXConnManagerClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (CamelIMAPXConnManagerPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = imapx_conn_manager_finalize;
+}
+
+static void
+camel_imapx_conn_manager_init (CamelIMAPXConnManager *con_man)
+{
+ CamelIMAPXConnManagerPrivate *priv;
+
+ priv = g_new0 (CamelIMAPXConnManagerPrivate, 1);
+ con_man->priv = priv;
+
+ /* default is 1 connection */
+ con_man->priv->n_connections = 1;
+ g_static_rec_mutex_init (&con_man->priv->con_man_lock);
+}
+
+
+/* Static functions go here */
+
+/* TODO destroy unused connections in a time-out loop */
+static void
+imapx_conn_shutdown (CamelIMAPXServer *conn, CamelIMAPXConnManager *con_man)
+{
+ GSList *l;
+ ConnectionInfo *cinfo;
+ gboolean found = FALSE;
+
+ CON_LOCK(con_man);
+
+ for (l = con_man->priv->connections; l != NULL; l = g_slist_next (l)) {
+ cinfo = (ConnectionInfo *) l->data;
+ if (cinfo->conn == conn) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found) {
+ con_man->priv->connections = g_slist_remove (con_man->priv->connections, cinfo);
+ free_connection (cinfo, GINT_TO_POINTER (1));
+ }
+
+ CON_UNLOCK(con_man);
+}
+
+static void
+imapx_conn_update_select (CamelIMAPXServer *conn, const gchar *selected_folder, CamelIMAPXConnManager *con_man)
+{
+ GSList *l;
+ ConnectionInfo *cinfo;
+ gboolean found = FALSE;
+
+ CON_LOCK(con_man);
+
+ for (l = con_man->priv->connections; l != NULL; l = g_slist_next (l)) {
+ cinfo = (ConnectionInfo *) l->data;
+ if (cinfo->conn == conn) {
+ 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(printf ("Removed folder %s from connection folder list \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);
+}
+
+/* This should find a connection if the slots are full, returns NULL if there are slots available for a new connection for a folder */
+static CamelIMAPXServer *
+imapx_find_connection (CamelIMAPXConnManager *con_man, const gchar *folder_name)
+{
+ guint i = 0, prev_len = -1, n = -1;
+ GSList *l;
+ CamelIMAPXServer *conn = NULL;
+ ConnectionInfo *cinfo = NULL;
+
+ CON_LOCK(con_man);
+
+ /* Have a dedicated connection for INBOX ? */
+ for (l = con_man->priv->connections, i = 0; l != NULL; l = g_slist_next (l), i++) {
+ IMAPXJobQueueInfo *jinfo = NULL;
+
+ cinfo = (ConnectionInfo *) l->data;
+ jinfo = camel_imapx_server_get_job_queue_info (cinfo->conn);
+
+ if (prev_len == -1) {
+ prev_len = jinfo->queue_len;
+ n = 0;
+ }
+
+ if (jinfo->queue_len < prev_len)
+ n = i;
+
+ camel_imapx_destroy_job_queue_info (jinfo);
+
+ if (folder_name && (g_hash_table_lookup (cinfo->folders, folder_name) || g_hash_table_size (cinfo->folders) == 0)) {
+ conn = g_object_ref (cinfo->conn);
+
+ if (folder_name)
+ g_hash_table_insert (cinfo->folders, g_strdup (folder_name), GINT_TO_POINTER (1));
+ c(printf ("Found connection for %s and connection number %d \n", folder_name, i+1));
+ break;
+ }
+ }
+
+ if (!conn && n != -1 && (!folder_name || con_man->priv->n_connections == g_slist_length (con_man->priv->connections))) {
+ cinfo = g_slist_nth_data (con_man->priv->connections, n);
+ conn = g_object_ref (cinfo->conn);
+
+ if (folder_name) {
+ g_hash_table_insert (cinfo->folders, g_strdup (folder_name), GINT_TO_POINTER (1));
+ c(printf ("Adding folder %s to connection number %d \n", folder_name, n+1));
+ }
+ }
+
+ c(g_assert (!(con_man->priv->n_connections == g_slist_length (con_man->priv->connections) && !conn)));
+
+ CON_UNLOCK(con_man);
+
+ return conn;
+}
+
+static CamelIMAPXServer *
+imapx_create_new_connection (CamelIMAPXConnManager *con_man, const gchar *folder_name, GError **error)
+{
+ CamelIMAPXServer *conn;
+ CamelStore *store = con_man->priv->store;
+ ConnectionInfo *cinfo = NULL;
+
+ CON_LOCK(con_man);
+
+ camel_service_lock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+
+ conn = camel_imapx_server_new (CAMEL_STORE(store), CAMEL_SERVICE(store)->url);
+ if (camel_imapx_server_connect(conn, error)) {
+ g_object_ref (conn);
+ } else {
+ g_object_unref (conn);
+
+ camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+ CON_UNLOCK (con_man);
+
+ return NULL;
+ }
+
+ g_signal_connect (conn, "shutdown", G_CALLBACK (imapx_conn_shutdown), con_man);
+ g_signal_connect (conn, "select_changed", G_CALLBACK (imapx_conn_update_select), con_man);
+
+ camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+
+ cinfo = g_new0 (ConnectionInfo, 1);
+ cinfo->conn = conn;
+ cinfo->folders = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
+
+ if (folder_name)
+ g_hash_table_insert (cinfo->folders, g_strdup (folder_name), GINT_TO_POINTER (1));
+
+ con_man->priv->connections = g_slist_prepend (con_man->priv->connections, cinfo);
+
+ c(printf ("Created new connection for %s and total connections %d \n", folder_name, g_slist_length (con_man->priv->connections)));
+
+ CON_UNLOCK(con_man);
+
+ return conn;
+}
+
+/****************************/
+
+CamelIMAPXConnManager *
+camel_imapx_conn_manager_new (CamelStore *store)
+{
+ CamelIMAPXConnManager *con_man;
+
+ con_man = g_object_new (CAMEL_TYPE_IMAPX_CONN_MANAGER, NULL);
+ con_man->priv->store = g_object_ref (store);
+
+ return con_man;
+}
+
+void
+camel_imapx_conn_manager_set_n_connections (CamelIMAPXConnManager *con_man, guint n_connections)
+{
+ g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (con_man));
+
+ con_man->priv->n_connections = n_connections;
+}
+
+CamelIMAPXServer *
+camel_imapx_conn_manager_get_connection (CamelIMAPXConnManager *con_man, const gchar *folder_name, GError **error)
+{
+ CamelIMAPXServer *conn = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (con_man), NULL);
+
+ CON_LOCK(con_man);
+
+ conn = imapx_find_connection (con_man, folder_name);
+ if (!conn)
+ conn = imapx_create_new_connection (con_man, folder_name, error);
+
+ CON_UNLOCK(con_man);
+
+ return conn;
+}
+
+GSList *
+camel_imapx_conn_manager_get_connections (CamelIMAPXConnManager *con_man)
+{
+ GSList *l, *conns = NULL;
+
+ CON_LOCK(con_man);
+
+ for (l = con_man->priv->connections; l != NULL; l = g_slist_next (l)) {
+ ConnectionInfo *cinfo = (ConnectionInfo *) l->data;
+
+ conns = g_slist_prepend (conns, g_object_ref (cinfo->conn));
+ }
+
+ CON_UNLOCK(con_man);
+
+ return conns;
+}
+
+void
+camel_imapx_conn_manager_close_connections (CamelIMAPXConnManager *con_man)
+{
+ g_return_if_fail (CAMEL_IS_IMAPX_CONN_MANAGER (con_man));
+
+ imapx_prune_connections (con_man);
+}
diff --git a/camel/providers/imapx/camel-imapx-conn-manager.h b/camel/providers/imapx/camel-imapx-conn-manager.h
new file mode 100644
index 0000000..6bd17dc
--- /dev/null
+++ b/camel/providers/imapx/camel-imapx-conn-manager.h
@@ -0,0 +1,69 @@
+/*-*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* camel-imap-conn-manager.h
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ * Authors: Chenthill Palanisamy <pchenthill novell com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _CAMEL_IMAPX_CONN_MANAGER_H
+#define _CAMEL_IMAPX_CONN_MANAGER_H
+
+#include "camel-imapx-server.h"
+
+#define CAMEL_TYPE_IMAPX_CONN_MANAGER \
+ (camel_imapx_conn_manager_get_type ())
+#define CAMEL_IMAPX_CONN_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), CAMEL_TYPE_IMAPX_CONN_MANAGER, CamelIMAPXConnManager))
+#define CAMEL_IMAPX_CONN_MANAGER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), CAMEL_TYPE_IMAPX_CONN_MANAGER, CamelIMAPXConnManagerClass))
+#define CAMEL_IS_IMAPX_CONN_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), CAMEL_TYPE_IMAPX_CONN_MANAGER))
+#define CAMEL_IS_CONN_MANAGER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), CAMEL_TYPE_IMAPX_CONN_MANAGER))
+#define CAMEL_IMAPX_CONN_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), CAMEL_TYPE_IMAPX_CONN_MANAGER, CamelIMAPXConnManagerClass))
+
+
+typedef struct _CamelIMAPXConnManager CamelIMAPXConnManager;
+typedef struct _CamelIMAPXConnManagerClass CamelIMAPXConnManagerClass;
+typedef struct _CamelIMAPXConnManagerPrivate CamelIMAPXConnManagerPrivate;
+
+struct _CamelIMAPXConnManager {
+ CamelObject cobject;
+ CamelIMAPXConnManagerPrivate *priv;
+};
+
+struct _CamelIMAPXConnManagerClass {
+ CamelObjectClass cclass;
+};
+
+GType camel_imapx_conn_manager_get_type (void);
+CamelIMAPXConnManager * camel_imapx_conn_manager_new (CamelStore *store);
+void camel_imapx_conn_manager_set_n_connections (CamelIMAPXConnManager *con_man,
+ guint n_connections);
+CamelIMAPXServer * camel_imapx_conn_manager_get_connection (CamelIMAPXConnManager *con_man,
+ const gchar *folder_name,
+ GError **error);
+void camel_imapx_conn_manager_close_connections (CamelIMAPXConnManager *con_man);
+GSList * camel_imapx_conn_manager_get_connections (CamelIMAPXConnManager *con_man);
+
+#endif /* ! _CAMEL_IMAPX_SERVER_H */
diff --git a/camel/providers/imapx/camel-imapx-folder.c b/camel/providers/imapx/camel-imapx-folder.c
index 1d529bf..7255334 100644
--- a/camel/providers/imapx/camel-imapx-folder.c
+++ b/camel/providers/imapx/camel-imapx-folder.c
@@ -164,7 +164,7 @@ imapx_refresh_info (CamelFolder *folder, GError **error)
if (!camel_service_connect((CamelService *)istore, error))
return FALSE;
- server = camel_imapx_store_get_server(istore, error);
+ server = camel_imapx_store_get_server(istore, camel_folder_get_full_name (folder), error);
if (server != NULL) {
success = camel_imapx_server_refresh_info(server, folder, error);
g_object_unref(server);
@@ -177,16 +177,16 @@ static gboolean
imapx_expunge (CamelFolder *folder, GError **error)
{
CamelStore *parent_store;
- CamelIMAPXStore *is;
+ CamelIMAPXStore *istore;
CamelIMAPXServer *server;
parent_store = camel_folder_get_parent_store (folder);
- is = CAMEL_IMAPX_STORE (parent_store);
+ istore = CAMEL_IMAPX_STORE (parent_store);
- if (CAMEL_OFFLINE_STORE (is)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
+ if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
return TRUE;
- server = camel_imapx_store_get_server(is, error);
+ server = camel_imapx_store_get_server(istore, camel_folder_get_full_name (folder), error);
if (server) {
camel_imapx_server_expunge(server, folder, error);
g_object_unref(server);
@@ -200,16 +200,16 @@ static gboolean
imapx_sync (CamelFolder *folder, gboolean expunge, GError **error)
{
CamelStore *parent_store;
- CamelIMAPXStore *is;
+ CamelIMAPXStore *istore;
CamelIMAPXServer *server;
parent_store = camel_folder_get_parent_store (folder);
- is = CAMEL_IMAPX_STORE (parent_store);
+ istore = CAMEL_IMAPX_STORE (parent_store);
- if (CAMEL_OFFLINE_STORE (is)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
+ if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
return TRUE;
- server = camel_imapx_store_get_server(is, NULL);
+ server = camel_imapx_store_get_server(istore, camel_folder_get_full_name (folder), NULL);
if (server)
camel_imapx_server_sync_changes (server, folder, NULL);
@@ -218,8 +218,9 @@ imapx_sync (CamelFolder *folder, gboolean expunge, GError **error)
if (server && expunge)
camel_imapx_server_expunge(server, folder, NULL);
- if (server)
+ if (server) {
g_object_unref(server);
+ }
return TRUE;
}
@@ -259,7 +260,7 @@ imapx_get_message (CamelFolder *folder, const gchar *uid, GError **error)
if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
return NULL;
- server = camel_imapx_store_get_server(istore, error);
+ server = camel_imapx_store_get_server(istore, camel_folder_get_full_name (folder), error);
if (server) {
stream = camel_imapx_server_get_message(server, folder, uid, error);
g_object_unref(server);
@@ -296,7 +297,7 @@ imapx_sync_message (CamelFolder *folder, const gchar *uid, GError **error)
if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
return TRUE;
- server = camel_imapx_store_get_server(istore, error);
+ server = camel_imapx_store_get_server (istore, camel_folder_get_full_name (folder), error);
if (server == NULL)
return FALSE;
@@ -322,7 +323,7 @@ imapx_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
return TRUE;
- server = camel_imapx_store_get_server(istore, error);
+ server = camel_imapx_store_get_server (istore, camel_folder_get_full_name (source), error);
if (server) {
success = camel_imapx_server_copy_message (server, source, dest, uids, delete_originals, error);
g_object_unref(server);
@@ -350,9 +351,9 @@ imapx_append_message(CamelFolder *folder, CamelMimeMessage *message, const Camel
if (appended_uid)
*appended_uid = NULL;
- server = camel_imapx_store_get_server(istore, error);
+ server = camel_imapx_store_get_server (istore, NULL, error);
if (server) {
- success = camel_imapx_server_append_message(server, folder, message, info, error);
+ success = camel_imapx_server_append_message (server, folder, message, info, error);
g_object_unref(server);
}
diff --git a/camel/providers/imapx/camel-imapx-provider.c b/camel/providers/imapx/camel-imapx-provider.c
index 1c5b71a..9bf6558 100644
--- a/camel/providers/imapx/camel-imapx-provider.c
+++ b/camel/providers/imapx/camel-imapx-provider.c
@@ -55,10 +55,8 @@ CamelProviderConfEntry imapx_conf_entries[] = {
N_("_Use custom command to connect to server"), "0" },
{ CAMEL_PROVIDER_CONF_ENTRY, "command", "use_command",
N_("Command:"), "ssh -C -l %u %h exec /usr/sbin/dovecot --exec-mail imap" },
-#if 0
{ CAMEL_PROVIDER_CONF_CHECKSPIN, "cachedconn", NULL,
N_("Numbe_r of cached connections to use"), "y:1:5:7" },
-#endif
{ CAMEL_PROVIDER_CONF_SECTION_END },
#endif
{ CAMEL_PROVIDER_CONF_SECTION_START, "folders", NULL,
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index d62e417..b807bdd 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -2341,6 +2341,8 @@ imapx_idle_supported (CamelIMAPXServer *is)
static void
imapx_command_select_done (CamelIMAPXServer *is, CamelIMAPXCommand *ic)
{
+ const gchar *selected_folder = NULL;
+
if (ic->error != NULL || ic->status->result != IMAPX_OK) {
CamelDList failed;
CamelIMAPXCommand *cw, *cn;
@@ -2412,6 +2414,7 @@ imapx_command_select_done (CamelIMAPXServer *is, CamelIMAPXCommand *ic)
//ifolder->uidnext_on_server = is->uidnext;
}
ifolder->uidvalidity_on_server = is->uidvalidity;
+ selected_folder = camel_folder_get_full_name (is->select_folder);
#if 0
/* This must trigger a complete index rebuild! */
if (is->uidvalidity && is->uidvalidity != ((CamelIMAPXSummary *)is->select_folder->summary)->uidvalidity)
@@ -2428,7 +2431,7 @@ imapx_command_select_done (CamelIMAPXServer *is, CamelIMAPXCommand *ic)
is->select_pending = NULL;
camel_imapx_command_free (ic);
- g_signal_emit (is, signals[SELECT_CHANGED], 0);
+ g_signal_emit (is, signals[SELECT_CHANGED], 0, selected_folder);
}
/* Should have a queue lock. TODO Change the way select is written */
@@ -4790,8 +4793,8 @@ camel_imapx_server_class_init(CamelIMAPXServerClass *class)
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (CamelIMAPXServerClass, select_changed),
NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
/**
* CamelIMAPXServer::shutdown
@@ -5563,7 +5566,7 @@ camel_imapx_server_get_job_queue_info (CamelIMAPXServer *is)
QUEUE_LOCK(is);
jinfo->queue_len = camel_dlist_length (&is->jobs);
- jinfo->folders = g_hash_table_new_full (g_int_hash, g_int_equal, (GDestroyNotify) g_free, NULL);
+ jinfo->folders = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
for (node = is->jobs.head;node->next;node = job->msg.ln.next) {
job = (CamelIMAPXJob *) node;
@@ -5574,6 +5577,9 @@ camel_imapx_server_get_job_queue_info (CamelIMAPXServer *is)
}
}
+ if (is->select_folder)
+ g_hash_table_insert (jinfo->folders, g_strdup (camel_folder_get_full_name (is->select_folder)), GINT_TO_POINTER (1));
+
QUEUE_UNLOCK(is);
return jinfo;
diff --git a/camel/providers/imapx/camel-imapx-server.h b/camel/providers/imapx/camel-imapx-server.h
index a23d0b2..69bf5d3 100644
--- a/camel/providers/imapx/camel-imapx-server.h
+++ b/camel/providers/imapx/camel-imapx-server.h
@@ -130,7 +130,7 @@ struct _CamelIMAPXServerClass {
CamelObjectClass parent_class;
/* Signals */
- void (*select_changed) (CamelIMAPXServer *server);
+ void (*select_changed) (CamelIMAPXServer *server, const gchar *selected_folder);
void (*shutdown) (CamelIMAPXServer *server);
gchar tagprefix;
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index 88de8a4..b140bf9 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -78,6 +78,8 @@ imapx_name_equal(gconstpointer a, gconstpointer b)
static void
imapx_parse_receiving_options (CamelIMAPXStore *istore, CamelURL *url)
{
+ const gchar *val;
+
if (camel_url_get_param (url, "use_lsub"))
istore->rec_options |= IMAPX_SUBSCRIPTIONS;
@@ -109,6 +111,12 @@ imapx_parse_receiving_options (CamelIMAPXStore *istore, CamelURL *url)
if (camel_url_get_param (url, "use_qresync"))
istore->rec_options |= IMAPX_USE_QRESYNC;
+
+ val = camel_url_get_param (url, "cachedconn");
+ if (val) {
+ guint n = strtod (val, NULL);
+ camel_imapx_conn_manager_set_n_connections (istore->con_man, n);
+ }
}
static void
@@ -168,6 +176,7 @@ imapx_query_auth_types (CamelService *service, GError **error)
CamelServiceAuthType *authtype;
GList *sasl_types, *t, *next;
gboolean connected;
+ CamelIMAPXServer *server;
if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
g_set_error (
@@ -179,12 +188,11 @@ imapx_query_auth_types (CamelService *service, GError **error)
camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
- if (istore->server == NULL)
- istore->server = camel_imapx_server_new((CamelStore *)istore, service->url);
+ server = camel_imapx_server_new((CamelStore *)istore, service->url);
- connected = istore->server->stream != NULL;
+ connected = server->stream != NULL;
if (!connected)
- connected = imapx_connect_to_server (istore->server, error);
+ connected = imapx_connect_to_server (server, error);
camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
if (!connected)
return NULL;
@@ -194,12 +202,14 @@ imapx_query_auth_types (CamelService *service, GError **error)
authtype = t->data;
next = t->next;
- if (!g_hash_table_lookup (istore->server->cinfo->auth_types, authtype->authproto)) {
+ if (!g_hash_table_lookup (server->cinfo->auth_types, authtype->authproto)) {
sasl_types = g_list_remove_link (sasl_types, t);
g_list_free_1 (t);
}
}
+ g_object_unref (server);
+
return g_list_prepend (sasl_types, &camel_imapx_password_authtype);
}
@@ -214,41 +224,33 @@ imapx_get_name (CamelService *service, gboolean brief)
}
CamelIMAPXServer *
-camel_imapx_store_get_server(CamelIMAPXStore *store, GError **error)
+camel_imapx_store_get_server (CamelIMAPXStore *istore, const gchar *folder_name, GError **error)
{
CamelIMAPXServer *server = NULL;
- camel_service_lock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+ camel_service_lock (CAMEL_SERVICE (istore), CAMEL_SERVICE_REC_CONNECT_LOCK);
+
+ server = camel_imapx_conn_manager_get_connection (istore->con_man, folder_name, error);
- if (store->server && camel_imapx_server_connect(store->server, NULL)) {
- g_object_ref(store->server);
- server = store->server;
- } else {
- if (store->server) {
- g_object_unref(store->server);
- store->server = NULL;
- }
+ camel_service_unlock (CAMEL_SERVICE (istore), CAMEL_SERVICE_REC_CONNECT_LOCK);
- server = camel_imapx_server_new(CAMEL_STORE(store), CAMEL_SERVICE(store)->url);
- if (camel_imapx_server_connect(server, error)) {
- store->server = server;
- g_object_ref(server);
- } else {
- g_object_unref(server);
- server = NULL;
- }
- }
- camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
return server;
}
+void
+camel_imapx_store_op_done (CamelIMAPXStore *istore, CamelIMAPXServer *server, const gchar *folder_name)
+{
+ g_return_if_fail (server != NULL);
+
+}
+
static gboolean
imapx_connect (CamelService *service, GError **error)
{
CamelIMAPXStore *istore = (CamelIMAPXStore *)service;
CamelIMAPXServer *server;
- server = camel_imapx_store_get_server(istore, error);
+ server = camel_imapx_store_get_server(istore, NULL, error);
if (server) {
g_object_unref(server);
return TRUE;
@@ -269,9 +271,10 @@ imapx_disconnect (CamelService *service, gboolean clean, GError **error)
camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
- if (istore->server) {
- g_object_unref(istore->server);
- istore->server = NULL;
+ if (istore->con_man) {
+ camel_imapx_conn_manager_close_connections (istore->con_man);
+ g_object_unref (istore->con_man);
+ istore->con_man = NULL;
}
camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
@@ -327,18 +330,24 @@ static gboolean
imapx_noop (CamelStore *store, GError **error)
{
CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
- CamelIMAPXServer *server;
+ GSList *servers = NULL, *l;
gboolean success = FALSE;
if (CAMEL_OFFLINE_STORE(store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
return TRUE;
- server = camel_imapx_store_get_server(istore, error);
- if (server) {
+ servers = camel_imapx_conn_manager_get_connections (istore->con_man);
+
+ for (l = servers; l != NULL; l = g_slist_next (l)) {
+ CamelIMAPXServer *server = CAMEL_IMAPX_SERVER (l->data);
+
+ /* we just return last noops value, technically not correct though */
success = camel_imapx_server_noop (server, NULL, error);
g_object_unref(server);
}
+ g_slist_free (servers);
+
return success;
}
@@ -598,7 +607,7 @@ imapx_subscribe_folder (CamelStore *store, const gchar *folder_name, gboolean em
if (CAMEL_OFFLINE_STORE(store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
return TRUE;
- server = camel_imapx_store_get_server(istore, error);
+ server = camel_imapx_store_get_server (istore, NULL, error);
if (!server)
return FALSE;
@@ -621,7 +630,7 @@ imapx_unsubscribe_folder (CamelStore *store, const gchar *folder_name, gboolean
if (CAMEL_OFFLINE_STORE(store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
return TRUE;
- server = camel_imapx_store_get_server(istore, error);
+ server = camel_imapx_store_get_server (istore, NULL, error);
if (!server)
return FALSE;
@@ -699,7 +708,9 @@ imapx_delete_folder (CamelStore *store, const gchar *folder_name, GError **error
_("You must be working online to complete this operation"));
return FALSE;
}
- server = camel_imapx_store_get_server(istore, error);
+ /* Use INBOX connection as the implementation would try to select inbox to ensure
+ we are not selected on the folder being deleted */
+ server = camel_imapx_store_get_server (istore, "INBOX", error);
if (!server)
return FALSE;
@@ -764,7 +775,9 @@ imapx_rename_folder (CamelStore *store, const gchar *old, const gchar *new, GErr
if (istore->rec_options & IMAPX_SUBSCRIPTIONS)
imapx_unsubscribe_folder (store, old, FALSE, NULL);
- server = camel_imapx_store_get_server(istore, error);
+ /* Use INBOX connection as the implementation would try to select inbox to ensure
+ we are not selected on the folder being renamed */
+ server = camel_imapx_store_get_server(istore, "INBOX", error);
if (server) {
success = camel_imapx_server_rename_folder (server, old, new, error);
g_object_unref(server);
@@ -818,7 +831,7 @@ imapx_create_folder (CamelStore *store, const gchar *parent_name, const gchar *f
return NULL;
}
- server = camel_imapx_store_get_server(istore, error);
+ server = camel_imapx_store_get_server(istore, NULL, error);
if (!server)
return NULL;
@@ -1126,7 +1139,7 @@ fetch_folders_for_namespaces (CamelIMAPXStore *istore, const gchar *pattern, gbo
GHashTable *folders = NULL;
GSList *namespaces = NULL, *l;
- server = camel_imapx_store_get_server(istore, error);
+ server = camel_imapx_store_get_server (istore, NULL, error);
if (!server)
return NULL;
@@ -1482,4 +1495,5 @@ camel_imapx_store_init (CamelIMAPXStore *istore)
istore->get_finfo_lock = g_mutex_new ();
istore->last_refresh_time = time (NULL) - (FINFO_REFRESH_INTERVAL + 10);
istore->dir_sep = '/';
+ istore->con_man = camel_imapx_conn_manager_new (store);
}
diff --git a/camel/providers/imapx/camel-imapx-store.h b/camel/providers/imapx/camel-imapx-store.h
index 922c5f2..c94de00 100644
--- a/camel/providers/imapx/camel-imapx-store.h
+++ b/camel/providers/imapx/camel-imapx-store.h
@@ -28,6 +28,7 @@
#include "camel-imapx-server.h"
#include "camel-imapx-store-summary.h"
+#include "camel-imapx-conn-manager.h"
/* Standard GObject macros */
#define CAMEL_TYPE_IMAPX_STORE \
@@ -66,7 +67,7 @@ typedef struct _CamelIMAPXStoreClass CamelIMAPXStoreClass;
struct _CamelIMAPXStore {
CamelOfflineStore parent;
- CamelIMAPXServer *server;
+ CamelIMAPXConnManager *con_man;
CamelIMAPXStoreSummary *summary; /* in-memory list of folders */
gchar *namespace, dir_sep, *base_url, *storage_path;
@@ -91,8 +92,13 @@ struct _CamelIMAPXStoreClass {
CamelOfflineStoreClass parent_class;
};
-GType camel_imapx_store_get_type (void);
-CamelIMAPXServer *camel_imapx_store_get_server(CamelIMAPXStore *store, GError **error);
+GType camel_imapx_store_get_type (void);
+CamelIMAPXServer * camel_imapx_store_get_server (CamelIMAPXStore *store,
+ const gchar *folder_name,
+ GError **error);
+void camel_imapx_store_op_done (CamelIMAPXStore *istore,
+ CamelIMAPXServer *server,
+ const gchar *folder_name);
G_END_DECLS
diff --git a/camel/providers/imapx/camel-imapx-utils.c b/camel/providers/imapx/camel-imapx-utils.c
index dd27f98..451da87 100644
--- a/camel/providers/imapx/camel-imapx-utils.c
+++ b/camel/providers/imapx/camel-imapx-utils.c
@@ -6,6 +6,7 @@
#include "camel-imapx-folder.h"
#include "camel-imapx-stream.h"
#include "camel-imapx-summary.h"
+#include "camel-imapx-store.h"
#include "camel-imapx-store-summary.h"
#include "camel-imapx-utils.h"
@@ -35,6 +36,7 @@ static void camel_imapx_set_debug_flags(void)
debug_set_flag(io);
debug_set_flag(token);
debug_set_flag(parse);
+ debug_set_flag(conman);
}
#include "camel-imapx-tokenise.h"
@@ -2115,7 +2117,7 @@ imapx_get_temp_uid (void)
}
void
-camel_imapx_server_destroy_job_queue_info (IMAPXJobQueueInfo *jinfo)
+camel_imapx_destroy_job_queue_info (IMAPXJobQueueInfo *jinfo)
{
g_hash_table_destroy (jinfo->folders);
g_free (jinfo);
diff --git a/camel/providers/imapx/camel-imapx-utils.h b/camel/providers/imapx/camel-imapx-utils.h
index 08d11ae..b0032c6 100644
--- a/camel/providers/imapx/camel-imapx-utils.h
+++ b/camel/providers/imapx/camel-imapx-utils.h
@@ -3,12 +3,12 @@
#define CAMEL_IMAPX_UTILS_H
#include <camel/camel.h>
-
-#include "camel-imapx-store.h"
+#include <glib.h>
struct _CamelIMAPXStream;
struct _CamelFlag;
struct _CamelIMAPXNamespaceList;
+struct _CamelIMAPXStore;
/* list of strings we know about that can be *quickly* tokenised */
typedef enum _camel_imapx_id_t {
@@ -66,7 +66,7 @@ enum {
/* ********************************************************************** */
-GPtrArray *imapx_parse_uids (CamelIMAPXStream *is, GError **error);
+GPtrArray *imapx_parse_uids (struct _CamelIMAPXStream *is, GError **error);
void imapx_parse_flags(struct _CamelIMAPXStream *stream, guint32 *flagsp, struct _CamelFlag **user_flagsp, GError **error);
void imapx_write_flags(CamelStream *stream, guint32 flags, struct _CamelFlag *user_flags, GError **error);
gboolean imapx_update_message_info_flags (CamelMessageInfo *info, guint32 server_flags, CamelFlag *server_user_flags, CamelFolder *folder, gboolean unsolicited);
@@ -217,7 +217,7 @@ typedef struct _IMAPXJobQueueInfo {
GHashTable *folders;
} IMAPXJobQueueInfo;
-void camel_imapx_server_destroy_job_queue_info (IMAPXJobQueueInfo *jinfo);
+void camel_imapx_destroy_job_queue_info (IMAPXJobQueueInfo *jinfo);
/* ********************************************************************** */
@@ -247,9 +247,10 @@ extern gint camel_imapx_debug_flags;
#define CAMEL_IMAPX_DEBUG_io (1<<3)
#define CAMEL_IMAPX_DEBUG_token (1<<4)
#define CAMEL_IMAPX_DEBUG_parse (1<<5)
+#define CAMEL_IMAPX_DEBUG_conman (1<<6)
/* Set this to zero to remove all debug output at build time */
-#define CAMEL_IMAPX_DEBUG_ALL ((1<<6)-1)
+#define CAMEL_IMAPX_DEBUG_ALL ((1<<7)-1)
#define camel_imapx_debug(type, ...) do { if (camel_imapx_debug_flags & CAMEL_IMAPX_DEBUG_ALL & CAMEL_IMAPX_DEBUG_ ## type) { __VA_ARGS__ ; } } while (0)
@@ -259,7 +260,7 @@ void imapx_utils_init(void);
/* chen adds from old imap provider - place it in right place */
gchar *imapx_path_to_physical (const gchar *prefix, const gchar *vpath);
-gchar *imapx_concat (CamelIMAPXStore *imapx_store, const gchar *prefix, const gchar *suffix);
+gchar *imapx_concat (struct _CamelIMAPXStore *imapx_store, const gchar *prefix, const gchar *suffix);
gchar * imapx_get_temp_uid (void);
void camel_imapx_namespace_list_clear (struct _CamelIMAPXNamespaceList *nsl);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]