Group messages into sets with the same flags and use the IMAP message set
* providers/imap/camel-imap-folder.c (imap_sync): Group messages into sets with the same flags and use the IMAP message set notation rather than doing a separate STORE FLAGS for each one. This cuts the network traffic down to just a handful of commands per sync rather than one per changed message. Removed the progress notification stuff since it's no longer meaningful and should hopefully be unnecessary. (imap_copy_message_to): move the former sync_message function into here, since it's no longer shared with imap_sync. svn path=/trunk/; revision=8396
This commit is contained in:
@ -1,3 +1,15 @@
|
||||
2001-02-26 Dan Winship <danw@ximian.com>
|
||||
|
||||
* providers/imap/camel-imap-folder.c (imap_sync): Group messages
|
||||
into sets with the same flags and use the IMAP message set
|
||||
notation rather than doing a separate STORE FLAGS for each one.
|
||||
This cuts the network traffic down to just a handful of commands
|
||||
per sync rather than one per changed message. Removed the progress
|
||||
notification stuff since it's no longer meaningful and should
|
||||
hopefully be unnecessary.
|
||||
(imap_copy_message_to): move the former sync_message function
|
||||
into here, since it's no longer shared with imap_sync.
|
||||
|
||||
2001-02-26 Jeffrey Stedfast <fejj@ximian.com>
|
||||
|
||||
* camel-mime-utils.c: Made thread-safe and moved to above the test
|
||||
|
||||
@ -424,27 +424,62 @@ imap_rescan (CamelFolder *folder, int exists, CamelException *ex)
|
||||
camel_operation_end(NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
sync_message (CamelImapStore *store, CamelFolder *folder,
|
||||
CamelMessageInfo *mi, CamelException *ex)
|
||||
/* Find all messages in @folder with flags matching @flags and @mask.
|
||||
* If no messages match, returns %NULL. Otherwise, returns an array of
|
||||
* CamelMessageInfo and sets *@set to a message set corresponding the
|
||||
* UIDs of the matched messages. The caller must free the infos, the
|
||||
* array, and the set string.
|
||||
*/
|
||||
static GPtrArray *
|
||||
get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set)
|
||||
{
|
||||
CamelImapResponse *response;
|
||||
char *flags;
|
||||
GPtrArray *matches;
|
||||
CamelMessageInfo *info;
|
||||
int i, max, range;
|
||||
GString *gset;
|
||||
|
||||
flags = imap_create_flag_list (mi->flags);
|
||||
CAMEL_IMAP_STORE_LOCK (store, command_lock);
|
||||
response = camel_imap_command (store, folder, ex,
|
||||
"UID STORE %s FLAGS.SILENT %s",
|
||||
camel_message_info_uid (mi), flags);
|
||||
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
|
||||
g_free (flags);
|
||||
if (camel_exception_is_set (ex))
|
||||
return;
|
||||
camel_imap_response_free (response);
|
||||
matches = g_ptr_array_new ();
|
||||
gset = g_string_new ("");
|
||||
max = camel_folder_summary_count (folder->summary);
|
||||
range = -1;
|
||||
for (i = 0; i < max; i++) {
|
||||
info = camel_folder_summary_index (folder->summary, i);
|
||||
if (!info)
|
||||
continue;
|
||||
if ((info->flags & mask) != flags) {
|
||||
camel_folder_summary_info_free (folder->summary, info);
|
||||
if (range != -1) {
|
||||
if (range != i - 1) {
|
||||
info = matches->pdata[matches->len - 1];
|
||||
g_string_sprintfa (gset, ":%s", camel_message_info_uid (info));
|
||||
}
|
||||
range = -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
mi->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
|
||||
((CamelImapMessageInfo *)mi)->server_flags =
|
||||
mi->flags & CAMEL_IMAP_SERVER_FLAGS;
|
||||
g_ptr_array_add (matches, info);
|
||||
if (range != -1)
|
||||
continue;
|
||||
range = i;
|
||||
if (gset->len)
|
||||
g_string_append_c (gset, ',');
|
||||
g_string_sprintfa (gset, "%s", camel_message_info_uid (info));
|
||||
}
|
||||
if (range != -1 && range != max - 1) {
|
||||
info = matches->pdata[matches->len - 1];
|
||||
g_string_sprintfa (gset, ":%s", camel_message_info_uid (info));
|
||||
}
|
||||
|
||||
if (matches->len) {
|
||||
*set = gset->str;
|
||||
g_string_free (gset, FALSE);
|
||||
return matches;
|
||||
} else {
|
||||
g_string_free (gset, TRUE);
|
||||
g_ptr_array_free (matches, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -452,26 +487,83 @@ imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
|
||||
{
|
||||
CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
|
||||
CamelImapResponse *response;
|
||||
int i, max;
|
||||
CamelMessageInfo *info;
|
||||
GPtrArray *matches;
|
||||
char *set, *flaglist;
|
||||
int i, j, max;
|
||||
|
||||
camel_operation_start(NULL, _("Synchronising IMAP folder"));
|
||||
|
||||
/* Set the flags on any messages that have changed this session */
|
||||
max = camel_folder_summary_count (folder->summary);
|
||||
for (i = 0; i < max; i++) {
|
||||
CamelMessageInfo *info;
|
||||
|
||||
info = camel_folder_summary_index (folder->summary, i);
|
||||
if (info && (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED))
|
||||
sync_message (store, folder, info, ex);
|
||||
camel_folder_summary_info_free(folder->summary, info);
|
||||
|
||||
camel_operation_progress(NULL, (i+1)*100/max);
|
||||
|
||||
if (camel_exception_is_set (ex)) {
|
||||
camel_operation_end(NULL);
|
||||
return;
|
||||
/* If we're expunging then we don't need to be precise about the
|
||||
* flags of deleted messages. Just add \Deleted to anything that
|
||||
* should have it.
|
||||
*/
|
||||
if (expunge && (matches = get_matching (folder, CAMEL_MESSAGE_DELETED,
|
||||
CAMEL_MESSAGE_DELETED, &set))) {
|
||||
for (i = 0; i < matches->len; i++) {
|
||||
info = matches->pdata[i];
|
||||
info->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
|
||||
camel_folder_summary_info_free (folder->summary, info);
|
||||
}
|
||||
g_ptr_array_free (matches, TRUE);
|
||||
camel_folder_summary_touch (folder->summary);
|
||||
|
||||
CAMEL_IMAP_STORE_LOCK (store, command_lock);
|
||||
response = camel_imap_command (store, folder, ex,
|
||||
"UID STORE %s +FLAGS.SILENT \\Deleted",
|
||||
set);
|
||||
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
|
||||
g_free (set);
|
||||
if (response)
|
||||
camel_imap_response_free (response);
|
||||
if (camel_exception_is_set (ex))
|
||||
return;
|
||||
}
|
||||
|
||||
/* OK, now, 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.
|
||||
*/
|
||||
for (i = 0; i < max; i++) {
|
||||
info = camel_folder_summary_index (folder->summary, i);
|
||||
if (!info)
|
||||
continue;
|
||||
if (!(info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
|
||||
camel_folder_summary_info_free (folder->summary, info);
|
||||
continue;
|
||||
}
|
||||
|
||||
flaglist = imap_create_flag_list (info->flags);
|
||||
matches = get_matching (folder, info->flags & (CAMEL_IMAP_SERVER_FLAGS | CAMEL_MESSAGE_FOLDER_FLAGGED),
|
||||
CAMEL_IMAP_SERVER_FLAGS | CAMEL_MESSAGE_FOLDER_FLAGGED, &set);
|
||||
camel_folder_summary_info_free (folder->summary, info);
|
||||
|
||||
CAMEL_IMAP_STORE_LOCK (store, command_lock);
|
||||
response = camel_imap_command (store, folder, ex,
|
||||
"UID STORE %s FLAGS.SILENT %s",
|
||||
set, flaglist);
|
||||
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
|
||||
g_free (set);
|
||||
g_free (flaglist);
|
||||
if (response)
|
||||
camel_imap_response_free (response);
|
||||
if (!camel_exception_is_set (ex)) {
|
||||
for (j = 0; j < matches->len; j++) {
|
||||
info = matches->pdata[j];
|
||||
info->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
|
||||
((CamelImapMessageInfo*)info)->server_flags =
|
||||
info->flags & CAMEL_IMAP_SERVER_FLAGS;
|
||||
}
|
||||
camel_folder_summary_touch (folder->summary);
|
||||
}
|
||||
for (j = 0; j < matches->len; j++) {
|
||||
info = matches->pdata[j];
|
||||
camel_folder_summary_info_free (folder->summary, info);
|
||||
}
|
||||
g_ptr_array_free (matches, TRUE);
|
||||
|
||||
if (camel_exception_is_set (ex))
|
||||
return;
|
||||
}
|
||||
|
||||
if (expunge) {
|
||||
@ -582,8 +674,27 @@ imap_copy_message_to (CamelFolder *source, const char *uid,
|
||||
g_return_if_fail (mi != NULL);
|
||||
|
||||
/* Sync message flags if needed. */
|
||||
if (mi->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)
|
||||
sync_message (store, source, mi, ex);
|
||||
if (mi->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) {
|
||||
char *flaglist;
|
||||
|
||||
flaglist = imap_create_flag_list (mi->flags);
|
||||
CAMEL_IMAP_STORE_LOCK (store, command_lock);
|
||||
response = camel_imap_command (store, source, ex,
|
||||
"UID STORE %s FLAGS.SILENT %s",
|
||||
camel_message_info_uid (mi),
|
||||
flaglist);
|
||||
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
|
||||
g_free (flaglist);
|
||||
if (camel_exception_is_set (ex)) {
|
||||
camel_folder_summary_info_free (source->summary, mi);
|
||||
return;
|
||||
}
|
||||
camel_imap_response_free (response);
|
||||
|
||||
mi->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
|
||||
((CamelImapMessageInfo *)mi)->server_flags =
|
||||
mi->flags & CAMEL_IMAP_SERVER_FLAGS;
|
||||
}
|
||||
camel_folder_summary_info_free (source->summary, mi);
|
||||
|
||||
if (camel_exception_is_set (ex))
|
||||
|
||||
Reference in New Issue
Block a user