From a34a4b15b8e5ab5f0a145c17ef0969da9666d8d0 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Tue, 21 Nov 2000 13:38:53 +0000 Subject: Shite, -1 on error, >=0 on success. So i've just been truncating all the 2000-11-21 Not Zed * providers/local/camel-mh-summary.c (mh_summary_sync_message): Shite, -1 on error, >=0 on success. So i've just been truncating all the messages I touched, good one zed. (mh_summary_sync_message): Sigh, and write to the right damn fd as well. (mh_summary_sync_message): Argh, and we need to compare the length of the old xev -1 to the new xev, to check if we can optimise it. * camel-folder.c (camel_folder_change_info_new): Init the pool. (camel_folder_change_info_add_source): Allocate string in the pool. (camel_folder_change_info_add_source_list): (camel_folder_change_info_add_update): No longer free the key, as it cannot be yet. (change_info_add_uid): Add a new arg, copy, telling it whether to copy the uid argument or not, and copy using mempool_strdup. (change_info_cat): Tell add_uid to copy the string. (camel_folder_change_info_add_update): Call add_uid directly. (change_info_remove): Call add_uid directly, with no copy, and dont free the key. (change_info_free_update): No longer required since we dont malloc the keys. (camel_folder_change_info_add_uid): Fix for add_uid change. (camel_folder_change_info_remove_uid): (camel_folder_change_info_change_uid): (change_info_clear): No longer needed, just set the size to 0 on the array directly. (camel_folder_change_info_clear): Empty the arrays directly, and flush the mempool too, and also clear uid_source, incase anyone was silly enough to call us in the wrong order. (camel_folder_change_info_free): Dont bother clearing the array's contents, just free the pool and throw away all the indexes. * camel-folder.h: Added a mempool to CamelFolderChangeInfo to store the uid's we get. * camel-folder-search.c (search_match_all): If we are only matching a single info, just use that/do the search. (camel_folder_search_match_expression): New function. Matches a single message info against an expression. (camel_folder_search_init): Init a hash table used to map the returned gptrarrays' to mempools. (camel_folder_search_execute_expression): Store all of the string data in a mempool, slightly faster, less wasted space (usually),. (camel_folder_search_free_result): Check for the mempool that stores the data for the list, and free that if we have it, otherwise assume we need to use g_free() (which should only happen if the list is empty at the moment). : commented out the debugging prints. Got sick of 'executing header search' crap. * providers/vee/camel-vee-folder.c (camel_vee_folder_init): Init changes. (camel_vee_folder_finalise): Free changes. (vfolder_add_match): Simple helper to add a new matching info record. (camel_vee_folder_add_folder): Only trigger a changed event if we have changes. (vfolder_change_match): New function, changes our local vfolder info to match the source. (vfolder_add_match): Add a new info to the vfolder list. (vfolder_remove_match): Remove a no-longer matching info from the vfolder summary. (message_changed): check if the message still matches, and remove/etc as required. (camel_vee_folder_finalise, init): init/free search object. (vee_folder_build_folder): Build the changes to the folder into the changes data, as we go. (folder_changed): If the folder gave us an explicit list of changes, then process each one separately (unless there's a lot added/changed). * providers/vee/camel-vee-folder.h: Added a changes field to the folder. svn path=/trunk/; revision=6628 --- camel/providers/vee/camel-vee-folder.c | 228 +++++++++++++++++++++++++++++---- 1 file changed, 201 insertions(+), 27 deletions(-) (limited to 'camel/providers/vee/camel-vee-folder.c') diff --git a/camel/providers/vee/camel-vee-folder.c b/camel/providers/vee/camel-vee-folder.c index da47761754..77c3017179 100644 --- a/camel/providers/vee/camel-vee-folder.c +++ b/camel/providers/vee/camel-vee-folder.c @@ -24,6 +24,9 @@ #include "camel-vee-folder.h" #include "camel-folder-summary.h" #include "camel-mime-message.h" +#ifdef DYNAMIC +#include "camel-folder-search.h" +#endif #include @@ -128,6 +131,11 @@ camel_vee_folder_init (CamelVeeFolder *obj) CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN; + + obj->changes = camel_folder_change_info_new(); +#ifdef DYNAMIC + obj->search = camel_folder_search_new(); +#endif } static void @@ -137,12 +145,19 @@ camel_vee_folder_finalise (CamelObject *obj) struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); GList *node; + /* FIXME: some leaks here, summary etc */ + node = p->folders; while (node) { CamelFolder *f = node->data; camel_object_unref((CamelObject *)f); node = g_list_next(node); } + + camel_folder_change_info_free(vf->changes); +#ifdef DYNAMIC + camel_object_unref((CamelObject *)vf->search); +#endif } /** @@ -156,8 +171,7 @@ camel_vee_folder_finalise (CamelObject *obj) * Return value: A new CamelVeeFolder widget. **/ CamelFolder * -camel_vee_folder_new (CamelStore *parent_store, const char *name, - CamelException *ex) +camel_vee_folder_new (CamelStore *parent_store, const char *name, CamelException *ex) { CamelFolder *folder; CamelVeeFolder *vf; @@ -192,16 +206,136 @@ camel_vee_folder_new (CamelStore *parent_store, const char *name, return folder; } +#ifdef DYNAMIC +static void +vfolder_remove_match(CamelVeeFolder *vf, CamelVeeMessageInfo *vinfo) +{ + printf("removing match %s\n", vinfo->info.uid); + + g_hash_table_remove(vf->messages_uid, vinfo->info.uid); + g_ptr_array_remove_fast(vf->messages, vinfo); + camel_folder_change_info_remove_uid(vf->changes, vinfo->info.uid); + camel_message_info_free((CamelMessageInfo *)vinfo); +} + +static CamelVeeMessageInfo * +vfolder_add_match(CamelVeeFolder *vf, CamelFolder *f, const CamelMessageInfo *info) +{ + CamelVeeMessageInfo *mi; + + mi = g_malloc0(sizeof(*mi)); + camel_message_info_dup_to(info, (CamelMessageInfo*)mi); + g_free (mi->info.uid); + mi->info.uid = g_strdup_printf("%p:%s", f, info->uid); + mi->folder = f; + g_ptr_array_add(vf->messages, mi); + g_hash_table_insert(vf->messages_uid, mi->info.uid, mi); + + printf("adding match %s\n", mi->info.uid); + + camel_folder_change_info_add_uid(vf->changes, mi->info.uid); + return mi; +} +#endif + +static void +vfolder_change_match(CamelVeeFolder *vf, CamelVeeMessageInfo *vinfo, const CamelMessageInfo *info) +{ + CamelFlag *flag; + CamelTag *tag; + + printf("changing match %s\n", vinfo->info.uid); + + vinfo->info.flags = info->flags; + camel_flag_list_free(&vinfo->info.user_flags); + flag = info->user_flags; + while (flag) { + camel_flag_set(&vinfo->info.user_flags, flag->name, TRUE); + flag = flag->next; + } + camel_tag_list_free(&vinfo->info.user_tags); + tag = info->user_tags; + while (tag) { + camel_tag_set(&vinfo->info.user_tags, tag->name, tag->value); + tag = tag->next; + } + camel_folder_change_info_change_uid(vf->changes, vinfo->info.uid); +} + static void folder_changed(CamelFolder *sub, gpointer type, CamelVeeFolder *vf) { CamelException *ex; - ex = camel_exception_new(); - vee_folder_build_folder(vf, sub, ex); - camel_exception_free(ex); - /* FIXME: should only raise follow-on event if the result changed */ - camel_object_trigger_event( CAMEL_OBJECT(vf), "folder_changed", GINT_TO_POINTER(0)); +#ifdef DYNAMIC + CamelFolderChangeInfo *changes = type; + + /* assume its faster to search a long list in whole, than by part */ + if (changes && (changes->uid_added->len + changes->uid_changed->len) < 500) { + int i; + char *vuid; + CamelVeeMessageInfo *vinfo; + gboolean match; + const CamelMessageInfo *info; + + ex = camel_exception_new(); + + /* see if added ones now match us */ + for (i=0;iuid_added->len;i++) { + info = camel_folder_get_message_info(sub, changes->uid_added->pdata[i]); + if (info) { + camel_folder_search_set_folder(vf->search, sub); + match = camel_folder_search_match_expression(vf->search, vf->expression, info, ex); + if (match) + vinfo = vfolder_add_match(vf, sub, info); + } + } + + /* check if changed ones still match */ + for (i=0;iuid_changed->len;i++) { + info = camel_folder_get_message_info(sub, changes->uid_changed->pdata[i]); + vuid = g_strdup_printf("%p:%s", sub, (char *)changes->uid_changed->pdata[i]); + vinfo = (CamelVeeMessageInfo *)vee_get_message_info((CamelFolder *)vf, vuid); + if (info) { + camel_folder_search_set_folder(vf->search, sub); + match = camel_folder_search_match_expression(vf->search, vf->expression, info, ex); + if (vinfo) { + if (match) + vfolder_change_match(vf, vinfo, info); + else + vfolder_remove_match(vf, vinfo); + } else if (match) + vfolder_add_match(vf, sub, info); + } else if (vinfo) + vfolder_remove_match(vf, vinfo); + + g_free(vuid); + } + + camel_exception_free(ex); + + /* mirror removes directly, if they used to match */ + for (i=0;iuid_removed->len;i++) { + vuid = g_strdup_printf("%p:%s", sub, (char *)changes->uid_removed->pdata[i]); + vinfo = (CamelVeeMessageInfo *)vee_get_message_info((CamelFolder *)vf, vuid); + if (vinfo) + vfolder_remove_match(vf, vinfo); + g_free(vuid); + } + } else { +#endif + ex = camel_exception_new(); + vee_folder_build_folder(vf, sub, ex); + camel_exception_free(ex); +#ifdef DYNAMIC + } +#endif + + /* cascade up, if we need to */ + if (camel_folder_change_info_changed(vf->changes)) { + camel_object_trigger_event( CAMEL_OBJECT(vf), "folder_changed", vf->changes); + camel_folder_change_info_clear(vf->changes); + } } /* track flag changes in the summary */ @@ -209,24 +343,49 @@ static void message_changed(CamelFolder *f, const char *uid, CamelVeeFolder *mf) { const CamelMessageInfo *info; - CamelMessageInfo *vinfo; - CamelFlag *flag; + CamelVeeMessageInfo *vinfo; char *vuid; +#ifdef DYNAMIC + gboolean match; + CamelException *ex; +#endif info = camel_folder_get_message_info(f, uid); - vuid = g_strdup_printf("%p:%s", f, uid); - vinfo = (CamelMessageInfo *)vee_get_message_info((CamelFolder *)mf, vuid); - if (info && vinfo) { - vinfo->flags = info->flags; - camel_flag_list_free(&vinfo->user_flags); - flag = info->user_flags; - while (flag) { - camel_flag_set(&vinfo->user_flags, flag->name, TRUE); - flag = flag->next; - } - camel_object_trigger_event( CAMEL_OBJECT(mf), "message_changed", vinfo->uid); + vinfo = (CamelVeeMessageInfo *)vee_get_message_info((CamelFolder *)mf, vuid); + + /* see if this message now matches/doesn't match anymore */ + + /* Hmm, this might not work if the folder uses some weird search thing, + and/or can be slow since it wont use any index index, hmmm. */ + +#ifdef DYNAMIC + camel_folder_search_set_folder(mf->search, f); + ex = camel_exception_new(); + match = camel_folder_search_match_expression(mf->search, mf->expression, info, ex); + camel_exception_free(ex); + if (info) { + if (vinfo) { + if (match) + vfolder_change_match(mf, vinfo, info); + else + vfolder_remove_match(mf, vinfo); + } else if (match) + vfolder_add_match(mf, f, info); + } else if (vinfo) + vfolder_remove_match(mf, vinfo); +#else + if (info && vinfo) + vfolder_change_match(mf, vinfo, info); +#endif + + /* cascade up, if required. This could probably be delayed, + but doesn't matter really, that is what freeze is for. */ + if (camel_folder_change_info_changed(mf->changes)) { + camel_object_trigger_event( CAMEL_OBJECT(mf), "folder_changed", mf->changes); + camel_folder_change_info_clear(mf->changes); } + g_free(vuid); } @@ -245,8 +404,18 @@ camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub) ex = camel_exception_new(); vee_folder_build_folder(vf, sub, ex); camel_exception_free(ex); - /* FIXME: should only raise follow-on event if the result changed */ - camel_object_trigger_event( CAMEL_OBJECT(vf), "folder_changed", GINT_TO_POINTER(0)); + + /* we'll assume the caller is going to update the whole list after they do this + this may or may not be the right thing to do, but it should be close enough */ +#if 0 + if (camel_folder_change_info_changed(vf->changes)) { + camel_object_trigger_event( CAMEL_OBJECT(vf), "folder_changed", vf->changes); + camel_folder_change_info_clear(vf->changes); + } +#else + camel_folder_change_info_clear(vf->changes); +#endif + } @@ -441,6 +610,11 @@ vee_folder_build(CamelVeeFolder *vf, CamelException *ex) messages = g_ptr_array_new(); messages_uid = g_hash_table_new(g_str_hash, g_str_equal); + g_ptr_array_free(vf->messages, TRUE); + vf->messages = messages; + g_hash_table_destroy(vf->messages_uid); + vf->messages_uid = messages_uid; + node = p->folders; while (node) { GPtrArray *matches; @@ -465,11 +639,6 @@ vee_folder_build(CamelVeeFolder *vf, CamelException *ex) camel_folder_search_free(f, matches); node = g_list_next(node); } - - g_ptr_array_free(vf->messages, TRUE); - vf->messages = messages; - g_hash_table_destroy(vf->messages_uid); - vf->messages_uid = messages_uid; } @@ -489,6 +658,7 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException for (i=0;imessages->len;i++) { CamelVeeMessageInfo *mi = g_ptr_array_index(vf->messages, i); if (mi->folder == source) { + camel_folder_change_info_add_source(vf->changes, mi->info.uid); g_hash_table_remove(vf->messages_uid, mi->info.uid); g_ptr_array_remove_index_fast(vf->messages, i); @@ -511,9 +681,13 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException mi->folder = f; g_ptr_array_add(messages, mi); g_hash_table_insert(messages_uid, mi->info.uid, mi); + + camel_folder_change_info_add_update(vf->changes, mi->info.uid); } } camel_folder_search_free(f, matches); + + camel_folder_change_info_build_diff(vf->changes); } -- cgit v1.2.3