[evolution-data-server] Bug 611861 - [IMAPX] Folder list does not show up immediately. Bug 612534 - IMAPX : cann't create su
- From: Chenthill Palanisamy <pchen src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug 611861 - [IMAPX] Folder list does not show up immediately. Bug 612534 - IMAPX : cann't create su
- Date: Thu, 11 Mar 2010 09:28:39 +0000 (UTC)
commit fc39e4fde4cce6b43abb21b3fe61b9eec03d476e
Author: Chenthill Palanisamy <pchenthill novell com>
Date: Thu Mar 11 14:54:33 2010 +0530
Bug 611861 - [IMAPX] Folder list does not show up immediately.
Bug 612534 - IMAPX : cann't create sub folder
camel/providers/imapx/camel-imapx-folder.c | 2 +-
camel/providers/imapx/camel-imapx-server.c | 72 ++++++++++++++-----
camel/providers/imapx/camel-imapx-store.c | 109 +++++++++++++++++++++++++---
camel/providers/imapx/camel-imapx-store.h | 5 ++
4 files changed, 156 insertions(+), 32 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-folder.c b/camel/providers/imapx/camel-imapx-folder.c
index 2eca4b0..cc3fdd2 100644
--- a/camel/providers/imapx/camel-imapx-folder.c
+++ b/camel/providers/imapx/camel-imapx-folder.c
@@ -113,9 +113,9 @@ imapx_refresh_info (CamelFolder *folder, CamelException *ex)
if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
return;
+ camel_service_connect((CamelService *)istore, ex);
if (istore->server && camel_imapx_server_connect (istore->server, 1))
camel_imapx_server_refresh_info(istore->server, folder, ex);
-
}
static void
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 66de9e8..649236c 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -124,7 +124,7 @@ typedef void (*CamelIMAPXCommandFunc)(struct _CamelIMAPXServer *engine, struct _
struct _CamelIMAPXCommand {
struct _CamelIMAPXCommand *next, *prev;
- gchar pri;
+ gint pri;
const gchar *name; /* command name/type (e.g. FETCH) */
@@ -193,16 +193,16 @@ enum {
IMAPX_PRIORITY_CREATE_FOLDER = 200,
IMAPX_PRIORITY_DELETE_FOLDER = 200,
IMAPX_PRIORITY_MANAGE_SUBSCRIPTION = 200,
+ IMAPX_PRIORITY_SYNC_CHANGES = 150,
+ IMAPX_PRIORITY_EXPUNGE = 150,
IMAPX_PRIORITY_GET_MESSAGE = 100,
IMAPX_PRIORITY_REFRESH_INFO = 0,
IMAPX_PRIORITY_NOOP = 0,
IMAPX_PRIORITY_NEW_MESSAGES = 0,
- IMAPX_PRIORITY_SYNC_CHANGES = -50,
IMAPX_PRIORITY_APPEND_MESSAGE = -60,
IMAPX_PRIIORITY_COPY_MESSAGE = -60,
IMAPX_PRIORITY_LIST = -80,
IMAPX_PRIORITY_IDLE = -100,
- IMAPX_PRIORITY_EXPUNGE = -120,
IMAPX_PRIORITY_SYNC_MESSAGE = -120
};
@@ -224,7 +224,7 @@ struct _CamelIMAPXJob {
gint noreply:1; /* dont wait for reply */
guint32 type; /* operation type */
- guint32 pri; /* the command priority */
+ gint pri; /* the command priority */
short commands; /* counts how many commands are outstanding */
CamelFolder *folder;
@@ -293,6 +293,7 @@ static void imapx_job_fetch_new_messages_start (CamelIMAPXServer *is, CamelIMAPX
static void imapx_command_copy_messages_step_done (CamelIMAPXServer *is, CamelIMAPXCommand *ic);
static gint imapx_refresh_info_uid_cmp(gconstpointer ap, gconstpointer bp);
static gint imapx_uids_array_cmp (gconstpointer ap, gconstpointer bp);
+static void imapx_server_sync_changes(CamelIMAPXServer *is, CamelFolder *folder, gint pri, CamelException *ex);
typedef struct _CamelIMAPXIdle CamelIMAPXIdle;
struct _CamelIMAPXIdle {
@@ -812,7 +813,10 @@ imapx_command_start_next(CamelIMAPXServer *is, CamelException *ex)
c(printf("** Starting next command\n"));
if (is->literal != NULL || is->select_pending != NULL) {
- c(printf("* no, waiting for literal/pending select '%s'\n", is->select_pending->full_name));
+ c(if (is->select_pending))
+ c(printf("* no, waiting for literal/pending select '%s'\n", is->select_pending->full_name));
+
+ /* TODO prolly start the store operations which do not require any folder to be selected */
return;
}
@@ -842,7 +846,7 @@ imapx_command_start_next(CamelIMAPXServer *is, CamelException *ex)
c(printf("- we're selected on '%s', current jobs?\n", is->select));
for (ic = (CamelIMAPXCommand *)is->active.head;ic->next;ic=ic->next) {
c(printf("- %3d '%s'\n", (gint)ic->pri, ic->name));
- if (ic->pri > pri)
+ if (ic->select && ic->pri > pri)
pri = ic->pri;
count++;
if (count > MAX_COMMANDS) {
@@ -850,7 +854,7 @@ imapx_command_start_next(CamelIMAPXServer *is, CamelException *ex)
return;
}
}
-
+
c(printf("-- Checking job queue\n"));
count = 0;
ic = (CamelIMAPXCommand *)is->queue.head;
@@ -863,7 +867,7 @@ imapx_command_start_next(CamelIMAPXServer *is, CamelException *ex)
camel_dlist_remove((CamelDListNode *)ic);
imapx_command_start(is, ic);
count++;
- } else
+ } else
break;
ic = nc;
nc = nc->next;
@@ -1017,7 +1021,7 @@ found:
return job;
}
-static gboolean
+static CamelIMAPXJob *
imapx_is_job_in_queue (CamelIMAPXServer *is, const gchar *folder_name, guint32 type, const gchar *uid)
{
CamelDListNode *node;
@@ -1039,7 +1043,11 @@ imapx_is_job_in_queue (CamelIMAPXServer *is, const gchar *folder_name, guint32 t
}
QUEUE_UNLOCK (is);
- return found;
+
+ if (found)
+ return job;
+ else
+ return NULL;
}
/* handle any untagged responses */
@@ -1788,6 +1796,7 @@ imapx_job_idle_start(CamelIMAPXServer *is, CamelIMAPXJob *job)
ic = camel_imapx_command_new ("IDLE", job->folder->full_name, "IDLE");
ic->job = job;
+ ic->pri = job->pri;
ic->complete = imapx_command_idle_done;
camel_imapx_command_close(ic);
@@ -2308,7 +2317,6 @@ retry:
imapx_store->summary->namespaces = nsl;
/* FIXME needs to be identified from list response */
imapx_store->dir_sep = ns->sep;
-
}
if (!camel_exception_is_set (ex))
@@ -2447,6 +2455,7 @@ imapx_command_copy_messages_step_start (CamelIMAPXServer *is, CamelIMAPXJob *job
ic = camel_imapx_command_new ("COPY", job->folder->full_name, "UID COPY ");
ic->complete = imapx_command_copy_messages_step_done;
ic->job = job;
+ ic->pri = job->pri;
job->u.copy_messages.last_index = i;
for (;i < uids->len; i++) {
@@ -2514,7 +2523,7 @@ cleanup:
static void
imapx_job_copy_messages_start (CamelIMAPXServer *is, CamelIMAPXJob *job)
{
- camel_imapx_server_sync_changes (is, job->folder, job->ex);
+ imapx_server_sync_changes (is, job->folder, job->pri, job->ex);
if (camel_exception_is_set (job->ex))
imapx_job_done (is, job);
@@ -2916,6 +2925,7 @@ imapx_job_scan_changes_start(CamelIMAPXServer *is, CamelIMAPXJob *job)
"FETCH 1:* (UID FLAGS)");
ic->job = job;
ic->complete = imapx_job_scan_changes_done;
+ ic->pri = job->pri;
job->u.refresh_info.infos = g_array_new (0, 0, sizeof(struct _refresh_info));
imapx_command_queue (is, ic);
}
@@ -2973,10 +2983,12 @@ imapx_job_fetch_new_messages_start (CamelIMAPXServer *is, CamelIMAPXJob *job)
"FETCH %s:* (UID FLAGS)", uid);
imapx_uidset_init(&job->u.refresh_info.uidset, BATCH_FETCH_COUNT, 0);
job->u.refresh_info.infos = g_array_new (0, 0, sizeof(struct _refresh_info));
+ ic->pri = job->pri;
ic->complete = imapx_command_step_fetch_done;
} else {
ic = camel_imapx_command_new ("FETCH", job->folder->full_name,
"UID FETCH %s:* (RFC822.SIZE RFC822.HEADER FLAGS)", uid);
+ ic->pri = job->pri;
ic->complete = imapx_command_fetch_new_messages_done;
}
@@ -3012,7 +3024,7 @@ imapx_job_refresh_info_start (CamelIMAPXServer *is, CamelIMAPXJob *job)
}
/* Sync changes before fetching status, else unread count will not match. need to think about better ways for this */
- camel_imapx_server_sync_changes (is, folder, ex);
+ imapx_server_sync_changes (is, folder, job->pri, ex);
if (camel_exception_is_set (job->ex))
goto exception;
@@ -3024,6 +3036,7 @@ imapx_job_refresh_info_start (CamelIMAPXServer *is, CamelIMAPXJob *job)
ic = camel_imapx_command_new ("STATUS", folder->full_name, "STATUS %f (MESSAGES UNSEEN)", folder);
ic->job = job;
+ ic->pri = job->pri;
ic->complete = imapx_command_status_done;
imapx_command_run_sync (is, ic);
@@ -3107,11 +3120,12 @@ imapx_job_expunge_start(CamelIMAPXServer *is, CamelIMAPXJob *job)
{
CamelIMAPXCommand *ic;
- camel_imapx_server_sync_changes (is, job->folder, job->ex);
+ imapx_server_sync_changes (is, job->folder, job->pri, job->ex);
/* TODO handle UIDPLUS capability */
ic = camel_imapx_command_new("EXPUNGE", job->folder->full_name, "EXPUNGE");
ic->job = job;
+ ic->pri = job->pri;
ic->complete = imapx_command_expunge_done;
imapx_command_queue(is, ic);
}
@@ -3296,6 +3310,10 @@ imapx_job_noop_start(CamelIMAPXServer *is, CamelIMAPXJob *job)
ic->job = job;
ic->complete = imapx_command_noop_done;
+ if (job->folder)
+ ic->pri = IMAPX_PRIORITY_REFRESH_INFO;
+ else
+ ic->pri = IMAPX_PRIORITY_NOOP;
imapx_command_queue(is, ic);
}
@@ -3824,7 +3842,10 @@ imapx_server_get_message (CamelIMAPXServer *is, CamelFolder *folder, CamelOperat
QUEUE_LOCK (is);
- if (imapx_is_job_in_queue (is, folder->full_name, IMAPX_JOB_GET_MESSAGE, uid)) {
+ if ((job = imapx_is_job_in_queue (is, folder->full_name, IMAPX_JOB_GET_MESSAGE, uid))) {
+ if (pri > job->pri)
+ job->pri = pri;
+
camel_exception_set (ex, CAMEL_EXCEPTION_OPERATION_IN_PROGRESS, "Downloading message...");
QUEUE_UNLOCK (is);
return NULL;
@@ -4071,8 +4092,8 @@ imapx_sync_free_user(GArray *user_set)
g_array_free(user_set, TRUE);
}
-void
-camel_imapx_server_sync_changes(CamelIMAPXServer *is, CamelFolder *folder, CamelException *ex)
+static void
+imapx_server_sync_changes(CamelIMAPXServer *is, CamelFolder *folder, gint pri, CamelException *ex)
{
guint i, on_orset, off_orset;
GPtrArray *uids;
@@ -4186,7 +4207,10 @@ camel_imapx_server_sync_changes(CamelIMAPXServer *is, CamelFolder *folder, Camel
QUEUE_LOCK (is);
- if (imapx_is_job_in_queue (is, folder->full_name, IMAPX_JOB_SYNC_CHANGES, NULL)) {
+ if ((job = imapx_is_job_in_queue (is, folder->full_name, IMAPX_JOB_SYNC_CHANGES, NULL))) {
+ if (pri > job->pri)
+ job->pri = pri;
+
QUEUE_UNLOCK (is);
goto done;
}
@@ -4194,7 +4218,7 @@ camel_imapx_server_sync_changes(CamelIMAPXServer *is, CamelFolder *folder, Camel
job = g_malloc0(sizeof(*job));
job->type = IMAPX_JOB_SYNC_CHANGES;
job->start = imapx_job_sync_changes_start;
- job->pri = IMAPX_PRIORITY_SYNC_CHANGES;
+ job->pri = pri;
job->folder = folder;
job->ex = ex;
job->u.sync_changes.changed_uids = uids;
@@ -4219,6 +4243,12 @@ done:
camel_folder_free_uids (folder, uids);
}
+void
+camel_imapx_server_sync_changes(CamelIMAPXServer *is, CamelFolder *folder, CamelException *ex)
+{
+ imapx_server_sync_changes (is, folder, IMAPX_PRIORITY_SYNC_CHANGES, ex);
+}
+
/* expunge-uids? */
void
camel_imapx_server_expunge(CamelIMAPXServer *is, CamelFolder *folder, CamelException *ex)
@@ -4311,6 +4341,10 @@ camel_imapx_server_list(CamelIMAPXServer *is, const gchar *top, guint32 flags, C
else
sprintf(job->u.list.pattern, "%s", encoded_name);
+ /* sync operation which is triggered by user */
+ if (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST)
+ job->pri += 300;
+
if (imapx_register_job (is, job)) {
imapx_run_job (is, job);
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index d80aea9..6beb20d 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -67,6 +67,8 @@
/* Specified in RFC 2060 section 2.1 */
#define IMAP_PORT 143
+#define FINFO_REFRESH_INTERVAL 60
+
static CamelOfflineStoreClass *parent_class = NULL;
static guint
@@ -623,6 +625,9 @@ imapx_create_folder (CamelStore *store, const gchar *parent_name, const gchar *f
return NULL;
}
+ if (!(istore->server && camel_imapx_server_connect (istore->server, 1)))
+ return NULL;
+
if (!parent_name)
parent_name = "";
@@ -664,8 +669,7 @@ imapx_create_folder (CamelStore *store, const gchar *parent_name, const gchar *f
full_name = imapx_concat (istore, parent_real, real_name);
g_free(real_name);
- if (istore->server && camel_imapx_server_connect (istore->server, 1))
- camel_imapx_server_create_folder (istore->server, full_name, ex);
+ camel_imapx_server_create_folder (istore->server, full_name, ex);
if (!camel_exception_is_set (ex)) {
CamelIMAPXStoreInfo *si;
@@ -811,6 +815,9 @@ add_folders_to_summary (CamelIMAPXStore *istore, GPtrArray *folders, GHashTable
new_flags = (si->info.flags & (CAMEL_STORE_INFO_FOLDER_SUBSCRIBED | CAMEL_STORE_INFO_FOLDER_CHECK_FOR_NEW)) |
(li->flags & ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED);
+ if (!(istore->server->cinfo->capa & IMAPX_CAPABILITY_NAMESPACE))
+ istore->dir_sep = li->separator;
+
if (si->info.flags != new_flags) {
si->info.flags = new_flags;
camel_store_summary_touch ((CamelStoreSummary *) istore->summary);
@@ -907,7 +914,7 @@ get_namespaces (CamelIMAPXStore *istore)
}
static GHashTable *
-fetch_folders_for_namespaces (CamelIMAPXStore *istore, const gchar *pattern, CamelException *ex)
+fetch_folders_for_namespaces (CamelIMAPXStore *istore, const gchar *pattern, gboolean sync, CamelException *ex)
{
GHashTable *folders = NULL;
GSList *namespaces = NULL, *l;
@@ -931,6 +938,9 @@ fetch_folders_for_namespaces (CamelIMAPXStore *istore, const gchar *pattern, Cam
} else
pat = g_strdup (pattern);
+ if (sync)
+ flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST;
+
flags |= CAMEL_STORE_FOLDER_INFO_RECURSIVE;
fetch_folders_for_pattern (istore, pat, flags, folders, ex);
if (camel_exception_is_set (ex)) {
@@ -939,7 +949,6 @@ fetch_folders_for_namespaces (CamelIMAPXStore *istore, const gchar *pattern, Cam
}
flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
-
fetch_folders_for_pattern (istore, pat, flags, folders, ex);
if (camel_exception_is_set (ex)) {
g_free (pat);
@@ -963,12 +972,12 @@ exception:
}
static void
-sync_folders (CamelIMAPXStore *istore, const gchar *pattern, CamelException *ex)
+sync_folders (CamelIMAPXStore *istore, const gchar *pattern, gboolean sync, CamelException *ex)
{
GHashTable *folders_from_server;
gint i, total;
- folders_from_server = fetch_folders_for_namespaces (istore, pattern, ex);
+ folders_from_server = fetch_folders_for_namespaces (istore, pattern, sync, ex);
if (camel_exception_is_set (ex))
return;
@@ -1024,6 +1033,43 @@ sync_folders (CamelIMAPXStore *istore, const gchar *pattern, CamelException *ex)
g_hash_table_destroy (folders_from_server);
}
+struct _imapx_refresh_msg {
+ CamelSessionThreadMsg msg;
+
+ CamelStore *store;
+ CamelException ex;
+};
+
+static void
+imapx_refresh_finfo (CamelSession *session, CamelSessionThreadMsg *msg)
+{
+ struct _imapx_refresh_msg *m = (struct _imapx_refresh_msg *)msg;
+ CamelIMAPXStore *istore = (CamelIMAPXStore *)m->store;
+
+ if (CAMEL_OFFLINE_STORE(istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
+ return;
+
+ if (!camel_service_connect((CamelService *)istore, &m->ex))
+ return;
+
+ /* look in all namespaces */
+ sync_folders (istore, "", FALSE, &m->ex);
+ camel_store_summary_save ((CamelStoreSummary *)istore->summary);
+}
+
+static void
+imapx_refresh_free(CamelSession *session, CamelSessionThreadMsg *msg)
+{
+ struct _imapx_refresh_msg *m = (struct _imapx_refresh_msg *)msg;
+
+ camel_object_unref(m->store);
+ camel_exception_clear(&m->ex);
+}
+
+static CamelSessionThreadOps imapx_refresh_ops = {
+ imapx_refresh_finfo,
+ imapx_refresh_free,
+};
static void
discover_inbox (CamelStore *store, CamelException *ex)
@@ -1036,7 +1082,7 @@ discover_inbox (CamelStore *store, CamelException *ex)
imapx_subscribe_folder (store, "INBOX", FALSE, ex);
if (!camel_exception_is_set(ex) && !si)
- sync_folders (istore, "INBOX", ex);
+ sync_folders (istore, "INBOX", TRUE, ex);
if (si)
camel_store_summary_info_free((CamelStoreSummary *) istore->summary, si);
@@ -1054,17 +1100,48 @@ imapx_get_folder_info(CamelStore *store, const gchar *top, guint32 flags, CamelE
if (top == NULL)
top = "";
+ g_mutex_lock (istore->get_finfo_lock);
+
if (CAMEL_OFFLINE_STORE(store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
fi = get_folder_info_offline (store, top, flags, ex);
+
+ g_mutex_unlock (istore->get_finfo_lock);
return fi;
}
- if (!camel_service_connect((CamelService *)store, ex))
- return NULL;
-
if (camel_store_summary_count ((CamelStoreSummary *) istore->summary) == 0)
initial_setup = TRUE;
+ if (!initial_setup && flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) {
+ time_t now = time (NULL);
+
+ if (now - istore->last_refresh_time > FINFO_REFRESH_INTERVAL) {
+ struct _imapx_refresh_msg *m;
+
+ istore->last_refresh_time = time (NULL);
+ m = camel_session_thread_msg_new(((CamelService *)store)->session, &imapx_refresh_ops, sizeof(*m));
+ m->store = store;
+ camel_object_ref(store);
+ camel_exception_init(&m->ex);
+ camel_session_thread_queue(((CamelService *)store)->session, &m->msg, 0);
+ }
+
+ fi = get_folder_info_offline (store, top, flags, ex);
+ g_mutex_unlock (istore->get_finfo_lock);
+ return fi;
+ }
+
+ if (!camel_service_connect((CamelService *)store, ex)) {
+ g_mutex_unlock (istore->get_finfo_lock);
+ return NULL;
+ }
+
+ if (*top && flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST) {
+ fi = get_folder_info_offline (store, top, flags, ex);
+ g_mutex_unlock (istore->get_finfo_lock);
+ return fi;
+ }
+
if (*top) {
gchar *name;
gint i;
@@ -1082,9 +1159,11 @@ imapx_get_folder_info(CamelStore *store, const gchar *top, guint32 flags, CamelE
pattern[0] = '\0';
}
- sync_folders (istore, pattern, ex);
- if (camel_exception_is_set (ex))
+ sync_folders (istore, pattern, TRUE, ex);
+ if (camel_exception_is_set (ex)) {
+ g_mutex_unlock (istore->get_finfo_lock);
return NULL;
+ }
camel_store_summary_save((CamelStoreSummary *) istore->summary);
@@ -1093,6 +1172,7 @@ imapx_get_folder_info(CamelStore *store, const gchar *top, guint32 flags, CamelE
discover_inbox (store, ex);
fi = get_folder_info_offline (store, top, flags, ex);
+ g_mutex_unlock (istore->get_finfo_lock);
return fi;
}
@@ -1179,8 +1259,12 @@ static void
camel_imapx_store_init (gpointer object, gpointer klass)
{
CamelStore *store = (CamelStore *) object;
+ CamelIMAPXStore *istore = CAMEL_IMAPX_STORE (object);
store->flags |= CAMEL_STORE_ASYNC | CAMEL_STORE_SUBSCRIPTIONS;
+ istore->get_finfo_lock = g_mutex_new ();
+ istore->last_refresh_time = time (NULL) - (FINFO_REFRESH_INTERVAL + 10);
+ istore->dir_sep = '/';
}
static void
@@ -1192,6 +1276,7 @@ imapx_store_finalise(CamelObject *object)
/* SIGH */
camel_service_disconnect((CamelService *)imapx_store, TRUE, NULL);
+ g_mutex_free (imapx_store->get_finfo_lock);
if (imapx_store->base_url)
g_free (imapx_store->base_url);
diff --git a/camel/providers/imapx/camel-imapx-store.h b/camel/providers/imapx/camel-imapx-store.h
index b34d63c..c28eaad 100644
--- a/camel/providers/imapx/camel-imapx-store.h
+++ b/camel/providers/imapx/camel-imapx-store.h
@@ -58,6 +58,11 @@ typedef struct {
guint32 rec_options;
+ /* Used for syncronizing get_folder_info. Check for re-use of any other lock. At the
+ moment, could not find anything suitable for this */
+ GMutex *get_finfo_lock;
+ time_t last_refresh_time;
+
/* if we had a login error, what to show to user */
gchar *login_error;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]