[evolution-patches] Patch with the improved implementation of imap_update_summary
- From: Philip Van Hoof <spam pvanhoof be>
- To: evolution-patches gnome org, Matthew Barnes <mbarnes redhat com>
- Subject: [evolution-patches] Patch with the improved implementation of imap_update_summary
- Date: Tue, 24 Oct 2006 19:35:15 +0200
Patch with the improved implementation of imap_update_summary for
Matthew to review and/or rework into Evolution's HEAD.
Tracker Bug:
http://bugzilla.gnome.org/show_bug.cgi?id=364757
--
Philip Van Hoof, software developer at x-tend
home: me at pvanhoof dot be
gnome: pvanhoof at gnome dot org
work: vanhoof at x-tend dot be
http://www.pvanhoof.be - http://www.x-tend.be
--- /home/pvanhoof/repos/gnome/cvs/evolution-data-server/camel/providers/imap/camel-imap-folder.c 2006-09-02 12:18:11.000000000 +0200
+++ camel-imap-folder.c 2006-10-24 19:28:21.000000000 +0200
@@ -191,8 +191,8 @@
imap_folder->priv = g_malloc0(sizeof(*imap_folder->priv));
#ifdef ENABLE_THREADS
- imap_folder->priv->search_lock = e_mutex_new(E_MUTEX_SIMPLE);
- imap_folder->priv->cache_lock = e_mutex_new(E_MUTEX_REC);
+ g_static_mutex_init(&imap_folder->priv->search_lock);
+ g_static_rec_mutex_init(&imap_folder->priv->cache_lock);
#endif
imap_folder->need_rescan = TRUE;
@@ -243,7 +243,7 @@
short_name = folder_name;
camel_folder_construct (folder, parent, folder_name, short_name);
- summary_file = g_strdup_printf ("%s/summary", folder_dir);
+ summary_file = g_strdup_printf ("%s/summary.mmap", folder_dir);
folder->summary = camel_imap_summary_new (folder, summary_file);
g_free (summary_file);
if (!folder->summary) {
@@ -296,8 +296,6 @@
int i, count;
char *resp;
- CAMEL_SERVICE_ASSERT_LOCKED (folder->parent_store, connect_lock);
-
count = camel_folder_summary_count (folder->summary);
for (i = 0; i < response->untagged->len; i++) {
@@ -347,9 +345,9 @@
else if (validity != imap_summary->validity) {
imap_summary->validity = validity;
camel_folder_summary_clear (folder->summary);
- CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock);
camel_imap_message_cache_clear (imap_folder->cache);
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
imap_folder->need_rescan = FALSE;
camel_imap_folder_changed (folder, exists, NULL, ex);
return;
@@ -425,8 +423,8 @@
camel_object_unref (CAMEL_OBJECT (imap_folder->cache));
#ifdef ENABLE_THREADS
- e_mutex_destroy(imap_folder->priv->search_lock);
- e_mutex_destroy(imap_folder->priv->cache_lock);
+ g_static_mutex_free(&imap_folder->priv->search_lock);
+ g_static_rec_mutex_free(&imap_folder->priv->cache_lock);
#endif
g_free(imap_folder->priv);
}
@@ -481,9 +479,9 @@
g_free (folders);
summary_path = g_strdup_printf("%s/summary", folder_dir);
- CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (folder, cache_lock);
camel_imap_message_cache_set_path(imap_folder->cache, folder_dir);
- CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (folder, cache_lock);
camel_folder_summary_set_filename(folder->summary, summary_path);
@@ -518,7 +516,7 @@
* Also, if this is the INBOX, some servers (cryus) wont tell
* us with a NOOP of new messages, so force a reselect which
* should do it. */
- CAMEL_SERVICE_LOCK (imap_store, connect_lock);
+ CAMEL_SERVICE_REC_LOCK (imap_store, connect_lock);
if (!camel_imap_store_connected(imap_store, ex))
goto done;
@@ -563,7 +561,7 @@
camel_store_summary_info_free((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary, si);
}
done:
- CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock);
camel_folder_summary_save(folder->summary);
camel_store_summary_save((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary);
@@ -597,7 +595,10 @@
}
mi->info.flags = (mi->info.flags & ~CAMEL_IMAP_MESSAGE_LABEL_MASK) | mask;
+
+#ifdef NON_TINYMAIL_FEATURES
camel_tag_set(&mi->info.user_tags, "label", label);
+#endif
}
}
@@ -620,7 +621,6 @@
gboolean ok;
CamelFolderChangeInfo *changes = NULL;
- CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock);
imap_folder->need_rescan = FALSE;
summary_len = camel_folder_summary_count (folder->summary);
@@ -834,7 +834,7 @@
}
camel_exception_init (&local_ex);
- CAMEL_SERVICE_LOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_LOCK (store, connect_lock);
/* Find a message with changed flags, find all of the other
* messages like it, sync them as a group, mark them as
@@ -902,7 +902,7 @@
g_ptr_array_free (matches, TRUE);
/* We unlock here so that other threads can have a chance to grab the connect_lock */
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
/* check for an exception */
if (camel_exception_is_set (&local_ex)) {
@@ -911,13 +911,13 @@
}
/* Re-lock the connect_lock */
- CAMEL_SERVICE_LOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_LOCK (store, connect_lock);
}
/* Save the summary */
imap_sync_offline (folder, ex);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
}
static int
@@ -970,12 +970,12 @@
int uid = 0;
char *set;
- CAMEL_SERVICE_LOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_LOCK (store, connect_lock);
if ((store->capabilities & IMAP_CAPABILITY_UIDPLUS) == 0) {
((CamelFolderClass *)CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, 0, ex);
if (camel_exception_is_set(ex)) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return;
}
}
@@ -990,7 +990,7 @@
if (response)
camel_imap_response_free (store, response);
if (camel_exception_is_set (ex)) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
g_free (set);
return;
}
@@ -1005,7 +1005,7 @@
camel_imap_response_free (store, response);
}
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
}
static void
@@ -1031,22 +1031,22 @@
* marked un-deleted.
*/
- CAMEL_SERVICE_LOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_LOCK (store, connect_lock);
((CamelFolderClass *)CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, 0, ex);
if (camel_exception_is_set(ex)) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return;
}
response = camel_imap_command (store, folder, ex, "UID SEARCH DELETED");
if (!response) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return;
}
result = camel_imap_response_extract (store, response, "SEARCH", ex);
if (!result) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return;
}
@@ -1107,7 +1107,7 @@
if (!response) {
g_ptr_array_free (keep_uids, TRUE);
g_ptr_array_free (mark_uids, TRUE);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return;
}
camel_imap_response_free (store, response);
@@ -1131,7 +1131,7 @@
if (!response) {
g_ptr_array_free (keep_uids, TRUE);
g_ptr_array_free (mark_uids, TRUE);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return;
}
camel_imap_response_free (store, response);
@@ -1171,7 +1171,7 @@
/* now we can free this, now that we're done with keep_uids */
g_free (result);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
}
static gchar *
@@ -1204,10 +1204,10 @@
uid = get_temp_uid ();
camel_imap_summary_add_offline (folder->summary, uid, message, info);
- CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (folder, cache_lock);
camel_imap_message_cache_insert_wrapper (cache, uid, "",
CAMEL_DATA_WRAPPER (message), ex);
- CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (folder, cache_lock);
changes = camel_folder_change_info_new ();
camel_folder_change_info_add_uid (changes, uid);
@@ -1292,7 +1292,7 @@
}
/* send the rest of our data - the mime message */
- response2 = camel_imap_command_continuation (store, ba->data, ba->len, ex);
+ response2 = camel_imap_command_continuation (store, (const char *) ba->data, ba->len, ex);
g_byte_array_free (ba, TRUE);
/* free it only after message is sent. This may cause more FETCHes. */
@@ -1337,11 +1337,11 @@
/* Cache first, since freeing response may trigger a
* summary update that will want this information.
*/
- CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (folder, cache_lock);
camel_imap_message_cache_insert_wrapper (
CAMEL_IMAP_FOLDER (folder)->cache, uid,
"", CAMEL_DATA_WRAPPER (message), ex);
- CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (folder, cache_lock);
if (appended_uid)
*appended_uid = uid;
else
@@ -1352,11 +1352,11 @@
camel_imap_response_free (store, response);
/* Make sure a "folder_changed" is emitted. */
- CAMEL_SERVICE_LOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_LOCK (store, connect_lock);
if (store->current_folder != folder ||
camel_folder_summary_count (folder->summary) == count)
imap_refresh_info (folder, ex);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
}
static void
@@ -1376,10 +1376,10 @@
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
const char *olduid = camel_message_info_uid (info);
- CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock);
camel_imap_message_cache_copy (imap_folder->cache, olduid,
imap_folder->cache, uid, ex);
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
if (appended_uid)
*appended_uid = uid;
@@ -1411,10 +1411,10 @@
* deadlock in the case where we're simultaneously also trying
* to copy messages in the other direction from another thread.
*/
- CAMEL_SERVICE_LOCK (store, connect_lock);
- CAMEL_IMAP_FOLDER_LOCK (source, cache_lock);
- CAMEL_IMAP_FOLDER_LOCK (dest, cache_lock);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_LOCK (store, connect_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (source, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (dest, cache_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
if (transferred_uids) {
*transferred_uids = g_ptr_array_new ();
@@ -1452,8 +1452,8 @@
camel_folder_delete_message (source, uid);
}
- CAMEL_IMAP_FOLDER_UNLOCK (dest, cache_lock);
- CAMEL_IMAP_FOLDER_UNLOCK (source, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (dest, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (source, cache_lock);
camel_object_trigger_event (CAMEL_OBJECT (dest), "folder_changed", changes);
camel_folder_change_info_free (changes);
@@ -1496,15 +1496,15 @@
* cache locks here, because we've got the store's
* command lock too, so no one else could be here.
*/
- CAMEL_IMAP_FOLDER_LOCK (source, cache_lock);
- CAMEL_IMAP_FOLDER_LOCK (destination, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (source, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (destination, cache_lock);
for (i = 0; i < src->len; i++) {
camel_imap_message_cache_copy (scache, src->pdata[i],
dcache, dest->pdata[i],
NULL);
}
- CAMEL_IMAP_FOLDER_UNLOCK (source, cache_lock);
- CAMEL_IMAP_FOLDER_UNLOCK (destination, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (source, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (destination, cache_lock);
imap_uid_array_free (src);
imap_uid_array_free (dest);
@@ -2080,7 +2080,9 @@
/* If the message is small or only 1 part, or server doesn't do 4v1 (properly) fetch it in one piece. */
if (store->server_level < IMAP_LEVEL_IMAP4REV1
|| store->braindamaged
+#ifdef NON_TINYMAIL_FEATURES
|| mi->info.size < IMAP_SMALL_BODY_SIZE
+#endif
|| (!content_info_incomplete(mi->info.content) && !mi->info.content->childs)) {
msg = get_message_simple (imap_folder, uid, NULL, ex);
} else {
@@ -2095,16 +2097,16 @@
char *body, *found_uid;
int i;
- CAMEL_SERVICE_LOCK(store, connect_lock);
+ CAMEL_SERVICE_REC_LOCK(store, connect_lock);
if (!camel_imap_store_connected(store, ex)) {
- CAMEL_SERVICE_UNLOCK(store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK(store, connect_lock);
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("This message is not currently available"));
goto fail;
}
response = camel_imap_command (store, folder, ex, "UID FETCH %s BODY", uid);
- CAMEL_SERVICE_UNLOCK(store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK(store, connect_lock);
if (response) {
for (i = 0, body = NULL; i < response->untagged->len; i++) {
@@ -2237,7 +2239,7 @@
memset ((void *) &tm, 0, sizeof (struct tm));
- tm.tm_mday = strtoul (inptr, (char **) &buf, 10);
+ tm.tm_mday = strtoul ((char *) inptr, (char **) &buf, 10);
if (buf == inptr || *buf != '-')
return (time_t) -1;
@@ -2246,7 +2248,7 @@
return (time_t) -1;
for (n = 0; n < 12; n++) {
- if (!g_ascii_strncasecmp (inptr, tm_months[n], 3))
+ if (!g_ascii_strncasecmp ((gchar *) inptr, tm_months[n], 3))
break;
}
@@ -2257,7 +2259,7 @@
inptr += 4;
- n = strtoul (inptr, (char **) &buf, 10);
+ n = strtoul ((char *) inptr, (char **) &buf, 10);
if (buf == inptr || *buf != ' ')
return (time_t) -1;
@@ -2271,7 +2273,7 @@
tm.tm_min = min;
tm.tm_sec = sec;
- n = strtol (inptr, NULL, 10);
+ n = strtol ((char *) inptr, NULL, 10);
date = e_mktime_utc (&tm);
@@ -2283,6 +2285,37 @@
return date;
}
+
+static CamelImapMessageInfo*
+message_from_data (CamelFolder *folder, GData *data)
+{
+ CamelMimeMessage *msg;
+ CamelStream *stream;
+ CamelImapMessageInfo *mi;
+ const char *idate;
+
+ stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
+ if (!stream)
+ return NULL;
+
+ msg = camel_mime_message_new ();
+ if (camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream) == -1) {
+ camel_object_unref (CAMEL_OBJECT (msg));
+ return NULL;
+ }
+
+ mi = (CamelImapMessageInfo *)camel_folder_summary_info_new_from_message (folder->summary, msg);
+ camel_object_unref (CAMEL_OBJECT (msg));
+
+ if ((idate = g_datalist_get_data (&data, "INTERNALDATE")))
+ mi->info.date_received = decode_internaldate ((const unsigned char *) idate);
+
+ if (mi->info.date_received == -1)
+ mi->info.date_received = mi->info.date_sent;
+
+ return mi;
+}
+
static void
add_message_from_data (CamelFolder *folder, GPtrArray *messages,
int first, GData *data)
@@ -2310,61 +2343,101 @@
}
mi = (CamelImapMessageInfo *)camel_folder_summary_info_new_from_message (folder->summary, msg);
+
camel_object_unref (CAMEL_OBJECT (msg));
if ((idate = g_datalist_get_data (&data, "INTERNALDATE")))
- mi->info.date_received = decode_internaldate (idate);
+ mi->info.date_received = decode_internaldate ((const unsigned char *) idate);
if (mi->info.date_received == -1)
mi->info.date_received = mi->info.date_sent;
-
+
messages->pdata[seq - first] = mi;
+
+ return;
}
+/* #define CAMEL_MESSAGE_INFO_HEADERS "DATE FROM TO CC SUBJECT REFERENCES IN-REPLY-TO MESSAGE-ID MIME-VERSION CONTENT-TYPE " */
+
+#define CAMEL_MESSAGE_INFO_HEADERS "DATE FROM TO CC SUBJECT IN-REPLY-TO MESSAGE-ID MIME-VERSION CONTENT-TYPE "
-#define CAMEL_MESSAGE_INFO_HEADERS "DATE FROM TO CC SUBJECT REFERENCES IN-REPLY-TO MESSAGE-ID MIME-VERSION CONTENT-TYPE "
/* FIXME: this needs to be kept in sync with camel-mime-utils.c's list
of mailing-list headers and so might be best if this were
auto-generated? */
#define MAILING_LIST_HEADERS "X-MAILING-LIST X-LOOP LIST-ID LIST-POST MAILING-LIST ORIGINATOR X-LIST SENDER RETURN-PATH X-BEENTHERE"
+
+static guint32
+imap_get_uids (CamelFolder *folder, CamelImapStore *store, CamelException *ex, GPtrArray *needheaders, int size, int got)
+{
+ char *resp;
+ CamelImapResponseType type;
+ guint32 cnt = 0;
+ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
+ GData *data;
+
+ while ((type = camel_imap_command_response (store, &resp, ex)) ==
+ CAMEL_IMAP_RESPONSE_UNTAGGED)
+ {
+ cnt++;
+ data = parse_fetch_response (imap_folder, resp);
+ g_free (resp);
+ if (!data)
+ continue;
+ g_ptr_array_add (needheaders, g_strdup (g_datalist_get_data (&data, "UID")));
+ if (size > 0)
+ camel_operation_progress (NULL, got * 100 / size);
+ g_datalist_clear (&data);
+ }
+ g_free (resp);
+ return cnt;
+
+}
+
static void
imap_update_summary (CamelFolder *folder, int exists,
CamelFolderChangeInfo *changes,
CamelException *ex)
{
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
- GPtrArray *fetch_data = NULL, *messages = NULL, *needheaders;
- guint32 flags, uidval;
- int i, seq, first, size, got;
- CamelImapResponseType type;
- const char *header_spec;
- CamelImapMessageInfo *mi, *info;
- CamelStream *stream;
- char *uid, *resp;
- GData *data;
-
- CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock);
- if (store->server_level >= IMAP_LEVEL_IMAP4REV1)
- header_spec = "HEADER.FIELDS (" CAMEL_MESSAGE_INFO_HEADERS MAILING_LIST_HEADERS ")";
- else
- header_spec = "0";
-
- /* Used as a way to fetch all Headers instead of the selective headers.
- Support for fetching custom headers could be done in a better way,
- using CamelURL and EPlugins. */
-
- if( g_getenv ("EVO_IMAP_FETCH_ALL_HEADERS") )
- header_spec = "HEADER";
-
- /* Figure out if any of the new messages are already cached (which
- * may be the case if we're re-syncing after disconnected operation).
- * If so, get their UIDs, FLAGS, and SIZEs. If not, get all that
- * and ask for the headers too at the same time.
- */
+ CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
+ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
+ GPtrArray *needheaders;
+ guint32 flags, uidval;
+ int i, seq, first, size, got;
+ CamelImapResponseType type;
+ const char *header_spec;
+ CamelImapMessageInfo *mi, *info;
+ CamelStream *stream;
+ char *uid, *resp;
+ GData *data;
+ gboolean more = TRUE;
+ unsigned int nextn, cnt=0, tcnt=0;
+
+ if (store->server_level >= IMAP_LEVEL_IMAP4REV1)
+ header_spec = "HEADER.FIELDS (" CAMEL_MESSAGE_INFO_HEADERS ")";
+ else
+ header_spec = "0";
+
+ if( g_getenv ("TNY_IMAP_FETCH_ALL_HEADERS") )
+ header_spec = "HEADER";
+
+ nextn = 0;
+ if (folder->summary)
+ nextn = camel_folder_summary_count (folder->summary);
+ if (nextn <= 0)
+ camel_folder_summary_load (folder->summary);
+
+ nextn = 1;
+ tcnt = 0;
+ while (more)
+ {
+ gboolean did_hack = FALSE;
+ gint hcnt = 0;
+
+ camel_folder_summary_dump_mmap (folder->summary);
seq = camel_folder_summary_count (folder->summary);
+
first = seq + 1;
if (seq > 0) {
mi = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, seq - 1);
@@ -2372,250 +2445,149 @@
camel_message_info_free(&mi->info);
} else
uidval = 0;
-
+
size = (exists - seq) * (IMAP_PRETEND_SIZEOF_FLAGS + IMAP_PRETEND_SIZEOF_SIZE + IMAP_PRETEND_SIZEOF_HEADERS);
got = 0;
+
if (!camel_imap_command_start (store, folder, ex,
- "UID FETCH %d:* (FLAGS RFC822.SIZE INTERNALDATE BODY.PEEK[%s])",
- uidval + 1, header_spec))
+ "UID FETCH %d:%d (FLAGS)", uidval + 1, uidval + 1 + nextn))
return;
+
+ more = FALSE;
+ needheaders = g_ptr_array_new ();
+
camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name);
-
- /* Parse the responses. We can't add a message to the summary
- * until we've gotten its headers, and there's no guarantee
- * the server will send the responses in a useful order...
- */
- fetch_data = g_ptr_array_new ();
- messages = g_ptr_array_new ();
- while ((type = camel_imap_command_response (store, &resp, ex)) ==
- CAMEL_IMAP_RESPONSE_UNTAGGED) {
- data = parse_fetch_response (imap_folder, resp);
- g_free (resp);
- if (!data)
- continue;
-
- seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE"));
- if (seq < first) {
- g_datalist_clear (&data);
- continue;
- }
-
- if (g_datalist_get_data (&data, "FLAGS"))
- got += IMAP_PRETEND_SIZEOF_FLAGS;
- if (g_datalist_get_data (&data, "RFC822.SIZE"))
- got += IMAP_PRETEND_SIZEOF_SIZE;
- stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
- if (stream) {
- got += IMAP_PRETEND_SIZEOF_HEADERS;
-
- /* Use the stream now so we don't tie up many
- * many fds if we're fetching many many messages.
- */
- add_message_from_data (folder, messages, first, data);
- g_datalist_set_data (&data, "BODY_PART_STREAM", NULL);
- }
-
- camel_operation_progress (NULL, got * 100 / size);
- g_ptr_array_add (fetch_data, data);
- }
+ cnt = imap_get_uids (folder, store, ex, needheaders, size, got);
camel_operation_end (NULL);
-
- if (type == CAMEL_IMAP_RESPONSE_ERROR)
- goto lose;
-
- /* Free the final tagged response */
- g_free (resp);
-
- /* Figure out which headers we still need to fetch. */
- needheaders = g_ptr_array_new ();
- size = got = 0;
- for (i = 0; i < fetch_data->len; i++) {
- data = fetch_data->pdata[i];
- if (g_datalist_get_data (&data, "BODY_PART_LEN"))
- continue;
-
- uid = g_datalist_get_data (&data, "UID");
- if (uid) {
- g_ptr_array_add (needheaders, uid);
- size += IMAP_PRETEND_SIZEOF_HEADERS;
- }
+
+ tcnt += cnt;
+
+ if (tcnt >= (exists - seq))
+ more = FALSE;
+ else
+ more = TRUE;
+
+ if (more && (((exists - seq) > nextn) && (cnt < nextn)))
+ {
+ camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name);
+ if (!camel_imap_command_start (store, folder, ex,
+ "UID FETCH %d:* FLAGS", uidval + 1 + cnt))
+ return;
+ cnt = imap_get_uids (folder, store, ex, needheaders, size, got);
+ camel_operation_end (NULL);
+ tcnt += cnt;
+ more = FALSE;
+ did_hack = TRUE;
}
-
- /* And fetch them */
- if (needheaders->len) {
+
+ if (nextn < 1000)
+ nextn += (nextn+5);
+ else
+ nextn = 1000;
+
+ if (needheaders->len)
+ {
char *uidset;
int uid = 0;
-
+
qsort (needheaders->pdata, needheaders->len,
- sizeof (void *), uid_compar);
-
+ sizeof (void *), uid_compar);
+
camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name);
-
- while (uid < needheaders->len) {
+ while (uid < needheaders->len)
+ {
uidset = imap_uid_array_to_set (folder->summary, needheaders, uid, UID_SET_LIMIT, &uid);
if (!camel_imap_command_start (store, folder, ex,
- "UID FETCH %s BODY.PEEK[%s]",
- uidset, header_spec)) {
+ "UID FETCH %s (FLAGS INTERNALDATE BODY.PEEK[%s])",
+ uidset, header_spec))
+ {
+ g_ptr_array_foreach (needheaders, (GFunc)g_free, NULL);
g_ptr_array_free (needheaders, TRUE);
camel_operation_end (NULL);
g_free (uidset);
- goto lose;
+ more = FALSE;
+ return;
}
g_free (uidset);
-
+
while ((type = camel_imap_command_response (store, &resp, ex))
- == CAMEL_IMAP_RESPONSE_UNTAGGED) {
+ == CAMEL_IMAP_RESPONSE_UNTAGGED)
+ {
+ gchar *muid;
+
data = parse_fetch_response (imap_folder, resp);
g_free (resp);
if (!data)
continue;
-
+
stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
- if (stream) {
- add_message_from_data (folder, messages, first, data);
+ if (stream)
+ {
+ mi = message_from_data (folder, data);
+
+ if (mi)
+ {
+ flags = GPOINTER_TO_INT (g_datalist_get_data (&data, "FLAGS"));
+ if (flags)
+ {
+ mi->server_flags = flags;
+ mi->info.flags |= flags;
+ flags_to_label(folder, mi);
+ }
+
+ muid = g_datalist_get_data (&data, "UID");
+ if (muid)
+ {
+ mi->info.uid = g_strdup (muid);
+ mi->info.uid_needs_free = TRUE;
+ }
+
+ info = (CamelImapMessageInfo *)camel_folder_summary_uid(folder->summary, muid);
+ if (info)
+ camel_message_info_free(&info->info);
+
+ camel_folder_summary_add (folder->summary, (CamelMessageInfo *)mi);
+ camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi));
+
+ if ((mi->info.flags & CAMEL_IMAP_MESSAGE_RECENT))
+ camel_folder_change_info_recent_uid(changes, camel_message_info_uid (mi));
+
+ }
+
+ if (did_hack)
+ {
+ hcnt++;
+ if (hcnt > 1000)
+ {
+ camel_folder_summary_dump_mmap (folder->summary);
+ hcnt = 0;
+ }
+ }
+
got += IMAP_PRETEND_SIZEOF_HEADERS;
- camel_operation_progress (NULL, got * 100 / size);
+ if (size > 0)
+ camel_operation_progress (NULL, got * 100 / size);
}
g_datalist_clear (&data);
}
if (type == CAMEL_IMAP_RESPONSE_ERROR) {
+ g_ptr_array_foreach (needheaders, (GFunc)g_free, NULL);
g_ptr_array_free (needheaders, TRUE);
camel_operation_end (NULL);
- goto lose;
+ more = FALSE;
+ return;
}
}
-
- g_ptr_array_free (needheaders, TRUE);
camel_operation_end (NULL);
}
-
- /* Now finish up summary entries (fix UIDs, set flags and size) */
- for (i = 0; i < fetch_data->len; i++) {
- data = fetch_data->pdata[i];
-
- seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE"));
- if (seq >= first + messages->len) {
- g_datalist_clear (&data);
- continue;
- }
-
- mi = messages->pdata[seq - first];
- if (mi == NULL) {
- CamelMessageInfo *pmi = NULL;
- int j;
-
- /* This is a kludge around a bug in Exchange
- * 5.5 that sometimes claims multiple messages
- * have the same UID. See bug #17694 for
- * details. The "solution" is to create a fake
- * message-info with the same details as the
- * previously valid message. Yes, the user
- * will have a clone in his/her message-list,
- * but at least we don't crash.
- */
-
- /* find the previous valid message info */
- for (j = seq - first - 1; j >= 0; j--) {
- pmi = messages->pdata[j];
- if (pmi != NULL)
- break;
- }
-
- if (pmi == NULL) {
- /* Server response is *really* fucked up,
- I guess we just pretend it never happened? */
- continue;
- }
-
- mi = (CamelImapMessageInfo *)camel_message_info_clone(pmi);
- }
-
- uid = g_datalist_get_data (&data, "UID");
- if (uid)
- mi->info.uid = g_strdup (uid);
- flags = GPOINTER_TO_INT (g_datalist_get_data (&data, "FLAGS"));
- if (flags) {
- ((CamelImapMessageInfo *)mi)->server_flags = flags;
- /* "or" them in with the existing flags that may
- * have been set by summary_info_new_from_message.
- */
- mi->info.flags |= flags;
- flags_to_label(folder, mi);
- }
- size = GPOINTER_TO_INT (g_datalist_get_data (&data, "RFC822.SIZE"));
- if (size)
- mi->info.size = size;
-
- g_datalist_clear (&data);
- }
- g_ptr_array_free (fetch_data, TRUE);
-
- /* And add the entries to the summary, etc. */
- for (i = 0; i < messages->len; i++) {
- mi = messages->pdata[i];
- if (!mi) {
- g_warning ("No information for message %d", i + first);
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Incomplete server response: no information provided for message %d"),
- i + first);
- break;
- }
- uid = (char *)camel_message_info_uid(mi);
- if (uid[0] == 0) {
- g_warning("Server provided no uid: message %d", i + first);
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Incomplete server response: no UID provided for message %d"),
- i + first);
- break;
- }
- info = (CamelImapMessageInfo *)camel_folder_summary_uid(folder->summary, uid);
- if (info) {
- for (seq = 0; seq < camel_folder_summary_count (folder->summary); seq++) {
- if (folder->summary->messages->pdata[seq] == info)
- break;
- }
-
- g_warning("Message already present? %s", camel_message_info_uid(mi));
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Unexpected server response: Identical UIDs provided for messages %d and %d"),
- seq + 1, i + first);
-
- camel_message_info_free(&info->info);
- break;
- }
-
- camel_folder_summary_add (folder->summary, (CamelMessageInfo *)mi);
- camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi));
-
- if ((mi->info.flags & CAMEL_IMAP_MESSAGE_RECENT))
- camel_folder_change_info_recent_uid(changes, camel_message_info_uid (mi));
- }
+ g_ptr_array_foreach (needheaders, (GFunc)g_free, NULL);
+ g_ptr_array_free (needheaders, TRUE);
+
+ } /* more */
+
+ camel_folder_summary_dump_mmap (folder->summary);
- for ( ; i < messages->len; i++) {
- if ((mi = messages->pdata[i]))
- camel_message_info_free(&mi->info);
- }
-
- g_ptr_array_free (messages, TRUE);
-
- return;
-
- lose:
- if (fetch_data) {
- for (i = 0; i < fetch_data->len; i++) {
- data = fetch_data->pdata[i];
- g_datalist_clear (&data);
- }
- g_ptr_array_free (fetch_data, TRUE);
- }
- if (messages) {
- for (i = 0; i < messages->len; i++) {
- if (messages->pdata[i])
- camel_message_info_free(messages->pdata[i]);
- }
- g_ptr_array_free (messages, TRUE);
- }
}
/* Called with the store's connect_lock locked */
@@ -2628,8 +2600,6 @@
CamelMessageInfo *info;
int len;
- CAMEL_SERVICE_ASSERT_LOCKED (folder->parent_store, connect_lock);
-
changes = camel_folder_change_info_new ();
if (expunged) {
int i, id;
@@ -2644,9 +2614,9 @@
}
camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info));
- CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock);
camel_imap_message_cache_remove (imap_folder->cache, camel_message_info_uid (info));
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
camel_folder_summary_remove (folder->summary, info);
camel_message_info_free(info);
}
@@ -2703,27 +2673,27 @@
* getting the same data from the cache, but that is only
* an inefficiency, and bad luck.
*/
- CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock);
stream = camel_imap_message_cache_get (imap_folder->cache, uid, section_text, ex);
if (!stream && (!strcmp (section_text, "HEADER") || !strcmp (section_text, "0"))) {
camel_exception_clear (ex);
stream = camel_imap_message_cache_get (imap_folder->cache, uid, "", ex);
}
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
if (stream || cache_only)
return stream;
camel_exception_clear(ex);
- CAMEL_SERVICE_LOCK (store, connect_lock);
- CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
+ CAMEL_SERVICE_REC_LOCK (store, connect_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock);
if (!camel_imap_store_connected(store, ex)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("This message is not currently available"));
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return NULL;
}
@@ -2738,10 +2708,10 @@
uid, section_text);
}
/* We won't need the connect_lock again after this. */
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
+ CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
if (!response) {
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
return NULL;
}
@@ -2756,7 +2726,7 @@
stream = NULL;
}
camel_imap_response_free (store, response);
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
if (!stream) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("Could not find message body in FETCH response."));
@@ -2775,7 +2745,7 @@
char *start, *part_spec = NULL, *body = NULL, *uid = NULL, *idate = NULL;
gboolean cache_header = TRUE, header = FALSE;
size_t body_len = 0;
-
+
if (*response != '(') {
long seq;
@@ -2894,11 +2864,11 @@
if (header && !cache_header) {
stream = camel_stream_mem_new_with_buffer (body, body_len);
} else {
- CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock);
stream = camel_imap_message_cache_insert (imap_folder->cache,
uid, part_spec,
body, body_len, NULL);
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
+ CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
if (stream == NULL)
stream = camel_stream_mem_new_with_buffer (body, body_len);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]