From d5e090651bbd30ee761624187db6ad7920162aa8 Mon Sep 17 00:00:00 2001 From: 9 Date: Tue, 9 Oct 2001 22:26:01 +0000 Subject: Implement. 2001-10-09 * providers/local/camel-spool-folder.c (spool_search_by_uids): Implement. * providers/imap/camel-imap-search.c (imap_body_contains): If searching a sub-set of the total message count, then use a UID range to search only specific messages. * camel-vee-folder.c (vee_folder_change_match): Removed. (folder_changed_add_uid): Helper func for changed code. (folder_changed_remove_uid): " (folder_changed_change_uid): " (folder_changed): Rewritten. Supports proper auto-updating of changes, but not removals till a sync occurs. (vee_search_by_uids): Implement. (folder_changed): Changed to call an async threaded function to do the actual folder updating. * camel-folder-summary.c (camel_flag_list_copy): New func to copy a whole list of flags. (camel_tag_list_copy): New func to copy a whole list of flags. * providers/imap/camel-imap-folder.c (imap_search_by_uids): Implement. * providers/local/camel-local-folder.c (local_search_by_uids): Implement. * camel-folder.c (camel_folder_search_by_uids): New function, search a subset of uid's. (search_by_uids): Default impl, return error. svn path=/trunk/; revision=13532 --- camel/providers/imap/camel-imap-command.c | 2 +- camel/providers/imap/camel-imap-folder.c | 46 ++++++++++++++++++++++++++++++ camel/providers/imap/camel-imap-search.c | 45 ++++++++++++++++++++++++++--- camel/providers/local/camel-local-folder.c | 44 ++++++++++++++++++++++++++++ camel/providers/local/camel-spool-folder.c | 43 ++++++++++++++++++++++++++++ 5 files changed, 175 insertions(+), 5 deletions(-) (limited to 'camel/providers') diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c index 64095b320d..141ae19ae5 100644 --- a/camel/providers/imap/camel-imap-command.c +++ b/camel/providers/imap/camel-imap-command.c @@ -678,7 +678,7 @@ imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt, len += arglen * 2; start = p + 1; break; - + case '%': start = p; break; diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index b17ffb55cd..5fe517f4ef 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -97,6 +97,7 @@ static void imap_move_messages_to (CamelFolder *source, GPtrArray *uids, /* searching */ static GPtrArray *imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex); +static GPtrArray *imap_search_by_uids (CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex); static void imap_search_free (CamelFolder *folder, GPtrArray *uids); static void imap_thaw (CamelFolder *folder); @@ -115,6 +116,7 @@ camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class) camel_folder_class->get_message = imap_get_message; camel_folder_class->move_messages_to = imap_move_messages_to; camel_folder_class->search_by_expression = imap_search_by_expression; + camel_folder_class->search_by_uids = imap_search_by_uids; camel_folder_class->search_free = imap_search_free; camel_folder_class->thaw = imap_thaw; @@ -1301,6 +1303,50 @@ imap_search_by_expression (CamelFolder *folder, const char *expression, CamelExc return matches; } +static GPtrArray * +imap_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) +{ + CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER(folder); + GPtrArray *summary, *matches; + int i; + + if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (folder->parent_store), ex)) + return NULL; + + /* NOTE: could get away without the search lock by creating a new + search object each time */ + + summary = g_ptr_array_new(); + for (i=0;ilen;i++) { + CamelMessageInfo *info; + + info = camel_folder_get_message_info(folder, uids->pdata[i]); + if (info) + g_ptr_array_add(summary, info); + } + + if (summary->len == 0) + return summary; + + CAMEL_IMAP_FOLDER_LOCK(folder, search_lock); + + if (imap_folder->search == NULL) + imap_folder->search = camel_imap_search_new(); + + camel_folder_search_set_folder(imap_folder->search, folder); + camel_folder_search_set_summary(imap_folder->search, summary); + + matches = camel_folder_search_execute_expression(imap_folder->search, expression, ex); + + CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock); + + for (i=0;ilen;i++) + camel_folder_free_message_info(folder, summary->pdata[i]); + g_ptr_array_free(summary, TRUE); + + return matches; +} + static void imap_search_free (CamelFolder *folder, GPtrArray *uids) { diff --git a/camel/providers/imap/camel-imap-search.c b/camel/providers/imap/camel-imap-search.c index 3c96449963..0418a34617 100644 --- a/camel/providers/imap/camel-imap-search.c +++ b/camel/providers/imap/camel-imap-search.c @@ -34,6 +34,7 @@ #include "camel-imap-store.h" #include "camel-imap-search.h" #include "camel-imap-private.h" +#include "camel-imap-utils.h" static ESExpResult * imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, @@ -67,6 +68,21 @@ camel_imap_search_get_type (void) return camel_imap_search_type; } +static int +cmp_uid(const void *ap, const void *bp) +{ + unsigned int a, b; + + a = strtoul(((char **)ap)[0], NULL, 10); + b = strtoul(((char **)bp)[0], NULL, 10); + if (ab) + return 1; + + return 0; +} + static ESExpResult * imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s) @@ -79,6 +95,9 @@ imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, ESExpResult *r; CamelMessageInfo *info; GHashTable *uid_hash = NULL; + char *set; + GPtrArray *sorted; + int i; if (s->current) { uid = camel_message_info_uid (s->current); @@ -100,11 +119,29 @@ imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, g_ptr_array_add (r->value.ptrarray, (char *)camel_message_info_uid (info)); } } else { - /* FIXME: danw: what if we have multiple string args? */ + /* If searching a (reasonably small) subset of + the real folder size, then use a + message-set to optimise it */ + /* TODO: This peeks a bunch of 'private'ish data */ + if (s->summary->len < camel_folder_get_message_count(s->folder)/2) { + sorted = g_ptr_array_new(); + g_ptr_array_set_size(sorted, s->summary->len); + for (i=0;isummary->len;i++) + sorted->pdata[i] = (void *)camel_message_info_uid((CamelMessageInfo *)s->summary->pdata[i]); + qsort(sorted->pdata, sorted->len, sizeof(sorted->pdata[0]), cmp_uid); + set = imap_uid_array_to_set(s->folder->summary, sorted); + response = camel_imap_command (store, s->folder, NULL, + "UID SEARCH UID %s BODY \"%s\"", + set, value); + g_free(set); + g_ptr_array_free(sorted, TRUE); + } else { + response = camel_imap_command (store, s->folder, NULL, + "UID SEARCH BODY \"%s\"", + value); + } + r->value.ptrarray = g_ptr_array_new (); - response = camel_imap_command (store, s->folder, NULL, - "UID SEARCH BODY \"%s\"", - value); } } diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c index 43622eb23a..27b49a5c70 100644 --- a/camel/providers/local/camel-local-folder.c +++ b/camel/providers/local/camel-local-folder.c @@ -62,6 +62,7 @@ static void local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex static void local_expunge(CamelFolder *folder, CamelException *ex); static GPtrArray *local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex); +static GPtrArray *local_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex); static void local_search_free(CamelFolder *folder, GPtrArray * result); static void local_finalize(CamelObject * object); @@ -80,6 +81,7 @@ camel_local_folder_class_init(CamelLocalFolderClass * camel_local_folder_class) camel_folder_class->expunge = local_expunge; camel_folder_class->search_by_expression = local_search_by_expression; + camel_folder_class->search_by_uids = local_search_by_uids; camel_folder_class->search_free = local_search_free; camel_local_folder_class->lock = local_lock; @@ -334,6 +336,48 @@ local_search_by_expression(CamelFolder *folder, const char *expression, CamelExc return matches; } +static GPtrArray * +local_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) +{ + CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); + GPtrArray *summary, *matches; + int i; + + /* NOTE: could get away without the search lock by creating a new + search object each time */ + + summary = g_ptr_array_new(); + for (i=0;ilen;i++) { + CamelMessageInfo *info; + + info = camel_folder_get_message_info(folder, uids->pdata[i]); + if (info) + g_ptr_array_add(summary, info); + } + + if (summary->len == 0) + return summary; + + CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); + + if (local_folder->search == NULL) + local_folder->search = camel_folder_search_new(); + + camel_folder_search_set_folder(local_folder->search, folder); + camel_folder_search_set_body_index(local_folder->search, local_folder->index); + camel_folder_search_set_summary(local_folder->search, summary); + + matches = camel_folder_search_execute_expression(local_folder->search, expression, ex); + + CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); + + for (i=0;ilen;i++) + camel_folder_free_message_info(folder, summary->pdata[i]); + g_ptr_array_free(summary, TRUE); + + return matches; +} + static void local_search_free(CamelFolder *folder, GPtrArray * result) { diff --git a/camel/providers/local/camel-spool-folder.c b/camel/providers/local/camel-spool-folder.c index bc715e46bc..9e487dfa89 100644 --- a/camel/providers/local/camel-spool-folder.c +++ b/camel/providers/local/camel-spool-folder.c @@ -64,6 +64,7 @@ static void spool_sync(CamelFolder *folder, gboolean expunge, CamelException *ex static void spool_expunge(CamelFolder *folder, CamelException *ex); static GPtrArray *spool_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex); +static GPtrArray *spool_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex); static void spool_search_free(CamelFolder *folder, GPtrArray * result); static void spool_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, CamelException *ex); @@ -87,6 +88,7 @@ camel_spool_folder_class_init(CamelSpoolFolderClass * camel_spool_folder_class) camel_folder_class->expunge = spool_expunge; camel_folder_class->search_by_expression = spool_search_by_expression; + camel_folder_class->search_by_uids = spool_search_by_uids; camel_folder_class->search_free = spool_search_free; /* virtual method overload */ @@ -363,6 +365,47 @@ spool_search_by_expression(CamelFolder *folder, const char *expression, CamelExc return matches; } +static GPtrArray * +spool_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) +{ + CamelSpoolFolder *spool_folder = CAMEL_SPOOL_FOLDER(folder); + GPtrArray *summary, *matches; + int i; + + /* NOTE: could get away without the search lock by creating a new + search object each time */ + + summary = g_ptr_array_new(); + for (i=0;ilen;i++) { + CamelMessageInfo *info; + + info = camel_folder_get_message_info(folder, uids->pdata[i]); + if (info) + g_ptr_array_add(summary, info); + } + + if (summary->len == 0) + return summary; + + CAMEL_SPOOL_FOLDER_LOCK(folder, search_lock); + + if (spool_folder->search == NULL) + spool_folder->search = camel_folder_search_new(); + + camel_folder_search_set_folder(spool_folder->search, folder); + camel_folder_search_set_summary(spool_folder->search, summary); + + matches = camel_folder_search_execute_expression(spool_folder->search, expression, ex); + + CAMEL_SPOOL_FOLDER_UNLOCK(folder, search_lock); + + for (i=0;ilen;i++) + camel_folder_free_message_info(folder, summary->pdata[i]); + g_ptr_array_free(summary, TRUE); + + return matches; +} + static void spool_search_free(CamelFolder *folder, GPtrArray * result) { -- cgit v1.2.3