[evolution-data-server] Bug #580198 - IMAP offline mode improvement



commit 7aaf3c8b7f66c7221c2d18cab4911a3a2c6e63d7
Author: Milan Crha <mcrha redhat com>
Date:   Tue Jun 9 12:56:12 2009 +0200

    Bug #580198 - IMAP offline mode improvement
---
 camel/camel-folder.c                       |    2 +
 camel/providers/imap/camel-imap-folder.c   |   81 ++++++++++++++++++++-------
 camel/providers/imap/camel-imap-journal.c  |    4 ++
 camel/providers/imap/camel-imap-journal.h  |    2 +-
 camel/providers/local/camel-local-folder.c |    9 ---
 5 files changed, 67 insertions(+), 31 deletions(-)

diff --git a/camel/camel-folder.c b/camel/camel-folder.c
index 84d0537..2575084 100644
--- a/camel/camel-folder.c
+++ b/camel/camel-folder.c
@@ -346,7 +346,9 @@ camel_folder_refresh_info (CamelFolder *folder, CamelException *ex)
 {
 	g_return_if_fail (CAMEL_IS_FOLDER (folder));
 
+	CAMEL_FOLDER_REC_LOCK (folder, lock);
 	CF_CLASS (folder)->refresh_info (folder, ex);
+	CAMEL_FOLDER_REC_UNLOCK (folder, lock);
 }
 
 static gint
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index b2395d2..1a3ac21 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -233,6 +233,35 @@ camel_imap_folder_get_type (void)
 	return camel_imap_folder_type;
 }
 
+static void
+replay_offline_journal (CamelImapStore *imap_store, CamelImapFolder *imap_folder, CamelException *ex)
+{
+	CamelIMAPJournal *imap_journal;
+
+	g_return_if_fail (imap_store != NULL);
+	g_return_if_fail (imap_folder != NULL);
+	g_return_if_fail (imap_folder->journal != NULL);
+
+	imap_journal = CAMEL_IMAP_JOURNAL (imap_folder->journal);
+	g_return_if_fail (imap_journal != NULL);
+
+	/* do not replay when still in offline */
+	if (CAMEL_OFFLINE_STORE (imap_store)->state != CAMEL_OFFLINE_STORE_NETWORK_AVAIL || !camel_imap_store_connected (imap_store, ex))
+		return;
+
+	/* Check if the replay is already in progress as imap_sync would be called while expunge resync */
+	if (!imap_journal->rp_in_progress) {
+		imap_journal->rp_in_progress++;
+
+		camel_offline_journal_replay (imap_folder->journal, ex);
+		camel_imap_journal_close_folders (imap_journal);
+		camel_offline_journal_write (imap_folder->journal, ex);
+
+		imap_journal->rp_in_progress--;
+		g_return_if_fail (imap_journal->rp_in_progress >= 0);
+	}
+}
+
 CamelFolder *
 camel_imap_folder_new (CamelStore *parent, const gchar *folder_name,
 		       const gchar *folder_dir, CamelException *ex)
@@ -298,9 +327,8 @@ camel_imap_folder_new (CamelStore *parent, const gchar *folder_name,
 
 	imap_folder->search = camel_imap_search_new(folder_dir);
 
-	camel_offline_journal_replay (imap_folder->journal, ex);
-	camel_imap_journal_close_folders ((CamelIMAPJournal *)imap_folder->journal);
-	camel_offline_journal_write (CAMEL_IMAP_FOLDER (folder)->journal, ex);
+	/* do not do that here, as other folders for 'transfer' might not be opened yet
+	replay_offline_journal (imap_store, imap_folder, ex);*/
 
 	return folder;
 }
@@ -706,6 +734,9 @@ imap_refresh_info (CamelFolder *folder, CamelException *ex)
 	if (camel_application_is_exiting  || !camel_imap_store_connected(imap_store, ex))
 		goto done;
 
+	/* try to store local changes first, as the summary contains new local messages */
+	replay_offline_journal (imap_store, imap_folder, ex);
+
 	if (imap_store->current_folder != folder
 	    || g_ascii_strcasecmp(folder->full_name, "INBOX") == 0) {
 		response = camel_imap_command (imap_store, folder, ex, NULL);
@@ -770,10 +801,6 @@ imap_refresh_info (CamelFolder *folder, CamelException *ex)
 done:
 	CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock);
 
-	camel_offline_journal_replay (CAMEL_IMAP_FOLDER (folder)->journal, ex);
-	camel_imap_journal_close_folders ((CamelIMAPJournal *) CAMEL_IMAP_FOLDER (folder)->journal);
-	camel_offline_journal_write (CAMEL_IMAP_FOLDER (folder)->journal, ex);
-
 	camel_folder_summary_save_to_db (folder->summary, ex);
 	camel_store_summary_save ((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary);
 }
@@ -1167,6 +1194,25 @@ imap_rescan (CamelFolder *folder, gint exists, CamelException *ex)
 	g_array_free (removed, TRUE);
 }
 
+static const gchar *
+get_message_uid (CamelFolder *folder, CamelImapMessageInfo *info)
+{
+	const gchar *uid;
+
+	g_return_val_if_fail (folder != NULL, NULL);
+	g_return_val_if_fail (info != NULL, NULL);
+
+	uid = camel_message_info_uid (info);
+	g_return_val_if_fail (uid != NULL, NULL);
+
+	if (!isdigit ((unsigned char)*uid)) {
+		uid = camel_imap_journal_uidmap_lookup ((CamelIMAPJournal *) CAMEL_IMAP_FOLDER (folder)->journal, uid);
+		g_return_val_if_fail (uid != NULL, NULL);
+	}
+
+	return uid;
+}
+
 /* the max number of chars that an unsigned 32-bit gint can be is 10 chars plus 1 for a possible : */
 #define UID_SET_FULL(setlen, maxlen) (maxlen > 0 ? setlen + 11 >= maxlen : FALSE)
 
@@ -1193,7 +1239,7 @@ get_matching (CamelFolder *folder, guint32 flags, guint32 mask, CamelMessageInfo
 			if (range != i - 1) {								\
 				CamelImapMessageInfo *rinfo = matches->pdata[matches->len - 1];		\
 													\
-				g_string_append_printf (gset, ":%s", camel_message_info_uid (rinfo));	\
+				g_string_append_printf (gset, ":%s", get_message_uid (folder, rinfo));	\
 			}										\
 			range = -1;									\
 			last_range_uid = -1;								\
@@ -1289,12 +1335,12 @@ get_matching (CamelFolder *folder, guint32 flags, guint32 mask, CamelMessageInfo
 		last_range_uid = uid_num;
 		if (gset->len)
 			g_string_append_c (gset, ',');
-		g_string_append_printf (gset, "%s", camel_message_info_uid (info));
+		g_string_append_printf (gset, "%s", get_message_uid (folder, info));
 	}
 
 	if (range != -1 && range != max - 1) {
 		info = matches->pdata[matches->len - 1];
-		g_string_append_printf (gset, ":%s", camel_message_info_uid (info));
+		g_string_append_printf (gset, ":%s", get_message_uid (folder, info));
 	}
 
 	if (list1)
@@ -1362,6 +1408,9 @@ imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
 	camel_exception_init (&local_ex);
 	CAMEL_SERVICE_REC_LOCK (store, connect_lock);
 
+	/* write local changes first */
+	replay_offline_journal (store, imap_folder, ex);
+
 	/* Find a message with changed flags, find all of the other
 	 * messages like it, sync them as a group, mark them as
 	 * updated, and continue.
@@ -1484,17 +1533,6 @@ imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
 	if (expunge)
 		imap_expunge (folder, ex);
 
-	/* Check if the replay is already in progress as imap_sync would be called while expunge resync */
-	if (!CAMEL_IMAP_JOURNAL (imap_folder->journal)->rp_in_progress) {
-		CAMEL_IMAP_JOURNAL (imap_folder->journal)->rp_in_progress = TRUE;
-
-		camel_offline_journal_replay (imap_folder->journal, ex);
-		camel_imap_journal_close_folders ((CamelIMAPJournal *)imap_folder->journal);
-		camel_offline_journal_write (CAMEL_IMAP_FOLDER (folder)->journal, ex);
-
-		CAMEL_IMAP_JOURNAL (imap_folder->journal)->rp_in_progress = FALSE;
-	}
-
 	g_ptr_array_foreach (summary, (GFunc) camel_pstring_free, NULL);
 	g_ptr_array_free (summary, TRUE);
 
@@ -2434,6 +2472,7 @@ imap_transfer_resyncing (CamelFolder *source, GPtrArray *uids,
 			message = camel_folder_get_message (source, uid, NULL);
 			if (!message) {
 				/* Message must have been expunged */
+				i++;
 				continue;
 			}
 			info = camel_folder_get_message_info (source, uid);
diff --git a/camel/providers/imap/camel-imap-journal.c b/camel/providers/imap/camel-imap-journal.c
index d82c07f..b8008ed 100644
--- a/camel/providers/imap/camel-imap-journal.c
+++ b/camel/providers/imap/camel-imap-journal.c
@@ -303,8 +303,12 @@ static CamelFolder *
 journal_decode_folder (CamelIMAPJournal *journal, const gchar *name)
 {
 	CamelFolder *folder;
+	CamelOfflineJournal *offline = CAMEL_OFFLINE_JOURNAL (journal);
 
 	folder = g_hash_table_lookup (journal->folders, name);
+	if (!folder && offline->folder && g_str_equal (offline->folder->full_name, name)) {
+		folder = offline->folder;
+	}
 	if (!folder) {
 		CamelException ex;
 		gchar *msg;
diff --git a/camel/providers/imap/camel-imap-journal.h b/camel/providers/imap/camel-imap-journal.h
index 8419859..ea5e7f0 100644
--- a/camel/providers/imap/camel-imap-journal.h
+++ b/camel/providers/imap/camel-imap-journal.h
@@ -70,7 +70,7 @@ struct _CamelIMAPJournal {
 
 	GHashTable *folders;
 	GHashTable *uidmap;
-	gboolean rp_in_progress;
+	gint rp_in_progress;
 };
 
 struct _CamelIMAPJournalClass {
diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c
index e05a4f7..1ce89fc 100644
--- a/camel/providers/local/camel-local-folder.c
+++ b/camel/providers/local/camel-local-folder.c
@@ -484,19 +484,10 @@ local_refresh_info(CamelFolder *folder, CamelException *ex)
 {
 	CamelLocalFolder *lf = (CamelLocalFolder *)folder;
 
-	/*
-	 * Banner: This is a very very ugly hack to get over the summary mismatch. This needs to
-	 * be done better. Im postponing this post-disk summary.
-	 * */
-
-	CAMEL_FOLDER_REC_LOCK(folder, lock);
-
 	if (camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex) == -1) {
-		CAMEL_FOLDER_REC_UNLOCK(folder, lock);
 		return;
 	}
 
-	CAMEL_FOLDER_REC_UNLOCK(folder, lock);
 	if (camel_folder_change_info_changed(lf->changes)) {
 		camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes);
 		camel_folder_change_info_clear(lf->changes);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]