From 665df59a88360115e410d46f50ebe61dead6b151 Mon Sep 17 00:00:00 2001 From: Not Zed Date: Tue, 28 Sep 2004 04:53:28 +0000 Subject: free the unmatched uid values as well. 2004-09-24 Not Zed * camel-vee-store.c (camel_vee_store_finalise): free the unmatched uid values as well. * camel-vee-folder.c (vee_folder_remove_folder): lock main folder summary lock before doing the unmatched stuff, so the order is right. 2004-08-25 Ed Catmur ** See bug #63881. * camel-vee-store.c: * camel-vee-folder.c: move the unmatched folder onto the camel-vee-store object. Removede the global unmatched folder and associated locks/etc, fixed all the code up to work with the new unmatched folder, if present. svn path=/trunk/; revision=27408 --- camel/ChangeLog | 19 +++ camel/camel-vee-folder.c | 334 ++++++++++++++++++++++++----------------------- camel/camel-vee-folder.h | 4 + camel/camel-vee-store.c | 17 ++- camel/camel-vee-store.h | 3 + 5 files changed, 211 insertions(+), 166 deletions(-) diff --git a/camel/ChangeLog b/camel/ChangeLog index 9d1c574e72..3aadea280d 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,22 @@ +2004-09-24 Not Zed + + * camel-vee-store.c (camel_vee_store_finalise): free the unmatched + uid values as well. + + * camel-vee-folder.c (vee_folder_remove_folder): lock main folder + summary lock before doing the unmatched stuff, so the order is + right. + +2004-08-25 Ed Catmur + + ** See bug #63881. + + * camel-vee-store.c: + * camel-vee-folder.c: move the unmatched + folder onto the camel-vee-store object. Removede the global + unmatched folder and associated locks/etc, fixed all the code up + to work with the new unmatched folder, if present. + 2004-09-27 Not Zed * providers/local/camel-spool-folder.c (camel_spool_folder_new): diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c index 1475c1da25..34211a48aa 100644 --- a/camel/camel-vee-folder.c +++ b/camel/camel-vee-folder.c @@ -86,16 +86,6 @@ static void folder_changed_remove_uid(CamelFolder *sub, const char *uid, const c static CamelFolderClass *camel_vee_folder_parent; -/* a vfolder for unmatched messages */ -/* use folder_unmatched->summary_lock for access to unmatched_uids or appropriate internals, for consistency */ -static CamelVeeFolder *folder_unmatched; -static GHashTable *unmatched_uids; /* a refcount of uid's that are matched by any rules */ -static pthread_mutex_t unmatched_lock = PTHREAD_MUTEX_INITIALIZER; -/* only used to initialise folder_unmatched */ -#define UNMATCHED_LOCK() pthread_mutex_lock(&unmatched_lock) -#define UNMATCHED_UNLOCK() pthread_mutex_unlock(&unmatched_lock) - - CamelType camel_vee_folder_get_type (void) { @@ -174,6 +164,7 @@ camel_vee_folder_finalise (CamelObject *obj) CamelVeeFolder *vf = (CamelVeeFolder *)obj; struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); GList *node; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; /* FIXME: check leaks */ node = p->folders; @@ -209,8 +200,8 @@ camel_vee_folder_finalise (CamelObject *obj) g_free(p); } -static void -vee_folder_construct (CamelVeeFolder *vf, CamelStore *parent_store, const char *name, guint32 flags) +void +camel_vee_folder_construct (CamelVeeFolder *vf, CamelStore *parent_store, const char *name, guint32 flags) { CamelFolder *folder = (CamelFolder *)vf; char *tmp; @@ -227,25 +218,9 @@ vee_folder_construct (CamelVeeFolder *vf, CamelStore *parent_store, const char * /* should CamelVeeMessageInfo be subclassable ..? */ folder->summary = camel_folder_summary_new(); folder->summary->message_info_size = sizeof(CamelVeeMessageInfo); -} -void -camel_vee_folder_construct(CamelVeeFolder *vf, CamelStore *parent_store, const char *name, guint32 flags) -{ - UNMATCHED_LOCK(); - - /* setup unmatched folder if we haven't yet */ - if (folder_unmatched == NULL) { - unmatched_uids = g_hash_table_new (g_str_hash, g_str_equal); - folder_unmatched = (CamelVeeFolder *)camel_object_new (camel_vee_folder_get_type ()); - d(printf("created foldeer unmatched %p\n", folder_unmatched)); - - vee_folder_construct (folder_unmatched, parent_store, CAMEL_UNMATCHED_NAME, CAMEL_STORE_FOLDER_PRIVATE); - } - - UNMATCHED_UNLOCK(); - - vee_folder_construct (vf, parent_store, name, flags); + if (CAMEL_IS_VEE_STORE(parent_store)) + vf->parent_vee_store = (CamelVeeStore *)parent_store; } /** @@ -263,25 +238,13 @@ camel_vee_folder_new(CamelStore *parent_store, const char *name, guint32 flags) { CamelVeeFolder *vf; char *tmp; - - UNMATCHED_LOCK(); - - /* setup unmatched folder if we haven't yet */ - if (folder_unmatched == NULL) { - unmatched_uids = g_hash_table_new(g_str_hash, g_str_equal); - folder_unmatched = vf = (CamelVeeFolder *)camel_object_new(camel_vee_folder_get_type()); - d(printf("created foldeer unmatched %p\n", folder_unmatched)); - vee_folder_construct (vf, parent_store, CAMEL_UNMATCHED_NAME, CAMEL_STORE_FOLDER_PRIVATE); - } - - UNMATCHED_UNLOCK(); - - if (strcmp(name, CAMEL_UNMATCHED_NAME) == 0) { - vf = folder_unmatched; + + if (CAMEL_IS_VEE_STORE(parent_store) && strcmp(name, CAMEL_UNMATCHED_NAME) == 0) { + vf = ((CamelVeeStore *)parent_store)->folder_unmatched; camel_object_ref(vf); } else { vf = (CamelVeeFolder *)camel_object_new(camel_vee_folder_get_type()); - vee_folder_construct(vf, parent_store, name, flags); + camel_vee_folder_construct(vf, parent_store, name, flags); } d(printf("returning folder %s %p, count = %d\n", name, vf, camel_folder_get_message_count((CamelFolder *)vf))); @@ -343,8 +306,9 @@ camel_vee_folder_set_expression(CamelVeeFolder *vf, const char *query) void camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub) { - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf), *up = _PRIVATE(folder_unmatched); + struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); int i; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; if (vf == (CamelVeeFolder *)sub) { g_warning("Adding a virtual folder to itself as source, ignored"); @@ -366,7 +330,8 @@ camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub) CAMEL_FOLDER_UNLOCK(vf, change_lock); } - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub)) { + if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub) && folder_unmatched != NULL) { + struct _CamelVeeFolderPrivate *up = _PRIVATE(folder_unmatched); camel_object_ref((CamelObject *)sub); up->folders = g_list_append(up->folders, sub); @@ -400,9 +365,10 @@ camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub) void camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) { - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf), *up = _PRIVATE(folder_unmatched); + struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); int killun = FALSE; int i; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); @@ -429,36 +395,40 @@ camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - CAMEL_VEE_FOLDER_LOCK(folder_unmatched, subfolder_lock); - /* if folder deleted, then blow it away from unmatched always, and remove all refs to it */ - if (sub->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED) { - while (g_list_find(up->folders, sub)) { - killun = TRUE; - up->folders = g_list_remove(up->folders, sub); - camel_object_unref((CamelObject *)sub); - - /* undo the freeze state that Unmatched has imposed on this source folder */ - CAMEL_FOLDER_LOCK(folder_unmatched, change_lock); - for (i = 0; i < ((CamelFolder *)folder_unmatched)->priv->frozen; i++) - camel_folder_thaw(sub); - CAMEL_FOLDER_UNLOCK(folder_unmatched, change_lock); - } - } else if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) { - if (g_list_find(up->folders, sub) != NULL) { - up->folders = g_list_remove(up->folders, sub); - camel_object_unref((CamelObject *)sub); - - /* undo the freeze state that Unmatched has imposed on this source folder */ - CAMEL_FOLDER_LOCK(folder_unmatched, change_lock); - for (i = 0; i < ((CamelFolder *)folder_unmatched)->priv->frozen; i++) - camel_folder_thaw(sub); - CAMEL_FOLDER_UNLOCK(folder_unmatched, change_lock); - } - if (g_list_find(up->folders, sub) == NULL) { - killun = TRUE; + if (folder_unmatched != NULL) { + struct _CamelVeeFolderPrivate *up = _PRIVATE(folder_unmatched); + + CAMEL_VEE_FOLDER_LOCK(folder_unmatched, subfolder_lock); + /* if folder deleted, then blow it away from unmatched always, and remove all refs to it */ + if (sub->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED) { + while (g_list_find(up->folders, sub)) { + killun = TRUE; + up->folders = g_list_remove(up->folders, sub); + camel_object_unref((CamelObject *)sub); + + /* undo the freeze state that Unmatched has imposed on this source folder */ + CAMEL_FOLDER_LOCK(folder_unmatched, change_lock); + for (i = 0; i < ((CamelFolder *)folder_unmatched)->priv->frozen; i++) + camel_folder_thaw(sub); + CAMEL_FOLDER_UNLOCK(folder_unmatched, change_lock); + } + } else if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) { + if (g_list_find(up->folders, sub) != NULL) { + up->folders = g_list_remove(up->folders, sub); + camel_object_unref((CamelObject *)sub); + + /* undo the freeze state that Unmatched has imposed on this source folder */ + CAMEL_FOLDER_LOCK(folder_unmatched, change_lock); + for (i = 0; i < ((CamelFolder *)folder_unmatched)->priv->frozen; i++) + camel_folder_thaw(sub); + CAMEL_FOLDER_UNLOCK(folder_unmatched, change_lock); + } + if (g_list_find(up->folders, sub) == NULL) { + killun = TRUE; + } } + CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, subfolder_lock); } - CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, subfolder_lock); vee_folder_remove_folder(vf, sub, killun); @@ -689,6 +659,7 @@ vee_search_by_expression(CamelFolder *folder, const char *expression, CamelExcep CamelVeeFolder *vf = (CamelVeeFolder *)folder; struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); GHashTable *searched = g_hash_table_new(NULL, NULL); + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); @@ -919,56 +890,59 @@ vee_folder_add_uid(CamelVeeFolder *vf, CamelFolder *f, const char *inuid, const static void vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source, int killun) { - int i, count, n, still, start, last; + int i, count, n, still = FALSE, start, last; char *oldkey; CamelFolder *folder = (CamelFolder *)vf; char hash[8]; /*struct _CamelVeeFolderPrivate *p = _PRIVATE(vf);*/ CamelFolderChangeInfo *vf_changes = NULL, *unmatched_changes = NULL; void *oldval; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; + GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL; if (vf == folder_unmatched) return; - /* check if this folder is still to be part of unmatched */ - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !killun) { - CAMEL_VEE_FOLDER_LOCK(folder_unmatched, subfolder_lock); - still = g_list_find(_PRIVATE(folder_unmatched)->folders, source) != NULL; - CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, subfolder_lock); - camel_vee_folder_hash_folder(source, hash); - } else { - still = FALSE; - } - CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); - CAMEL_VEE_FOLDER_LOCK(folder_unmatched, summary_lock); - /* See if we just blow all uid's from this folder away from unmatched, regardless */ - if (killun) { - start = -1; - last = -1; - count = camel_folder_summary_count(((CamelFolder *)folder_unmatched)->summary); - for (i=0;isummary, i); - - if (mi) { - if (mi->folder == source) { - camel_folder_change_info_remove_uid(folder_unmatched->changes, camel_message_info_uid(mi)); - if (last == -1) { - last = start = i; - } else if (last+1 == i) { - last = i; - } else { - camel_folder_summary_remove_range(((CamelFolder *)folder_unmatched)->summary, start, last); - i -= (last-start)+1; - start = last = i; + if (folder_unmatched != NULL) { + /* check if this folder is still to be part of unmatched */ + if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !killun) { + CAMEL_VEE_FOLDER_LOCK(folder_unmatched, subfolder_lock); + still = g_list_find(_PRIVATE(folder_unmatched)->folders, source) != NULL; + CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, subfolder_lock); + camel_vee_folder_hash_folder(source, hash); + } + + CAMEL_VEE_FOLDER_LOCK(folder_unmatched, summary_lock); + + /* See if we just blow all uid's from this folder away from unmatched, regardless */ + if (killun) { + start = -1; + last = -1; + count = camel_folder_summary_count(((CamelFolder *)folder_unmatched)->summary); + for (i=0;isummary, i); + + if (mi) { + if (mi->folder == source) { + camel_folder_change_info_remove_uid(folder_unmatched->changes, camel_message_info_uid(mi)); + if (last == -1) { + last = start = i; + } else if (last+1 == i) { + last = i; + } else { + camel_folder_summary_remove_range(((CamelFolder *)folder_unmatched)->summary, start, last); + i -= (last-start)+1; + start = last = i; + } } + camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); } - camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); } + if (last != -1) + camel_folder_summary_remove_range(((CamelFolder *)folder_unmatched)->summary, start, last); } - if (last != -1) - camel_folder_summary_remove_range(((CamelFolder *)folder_unmatched)->summary, start, last); } start = -1; @@ -991,7 +965,7 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source, int killun) i -= (last-start)+1; start = last = i; } - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) { + if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && folder_unmatched != NULL) { if (still) { if (g_hash_table_lookup_extended(unmatched_uids, uid, (void **)&oldkey, &oldval)) { n = GPOINTER_TO_INT (oldval); @@ -1019,9 +993,13 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source, int killun) if (last != -1) camel_folder_summary_remove_range(folder->summary, start, last); - if (camel_folder_change_info_changed(folder_unmatched->changes)) { - unmatched_changes = folder_unmatched->changes; - folder_unmatched->changes = camel_folder_change_info_new(); + if (folder_unmatched) { + if (camel_folder_change_info_changed(folder_unmatched->changes)) { + unmatched_changes = folder_unmatched->changes; + folder_unmatched->changes = camel_folder_change_info_new(); + } + + CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); } if (camel_folder_change_info_changed(vf->changes)) { @@ -1029,7 +1007,6 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source, int killun) vf->changes = camel_folder_change_info_new(); } - CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); if (unmatched_changes) { @@ -1047,6 +1024,8 @@ struct _update_data { CamelFolder *source; CamelVeeFolder *vf; char hash[8]; + CamelVeeFolder *folder_unmatched; + GHashTable *unmatched_uids; }; static void @@ -1058,16 +1037,16 @@ unmatched_check_uid(char *uidin, void *value, struct _update_data *u) uid = alloca(strlen(uidin)+9); memcpy(uid, u->hash, 8); strcpy(uid+8, uidin); - n = GPOINTER_TO_INT(g_hash_table_lookup(unmatched_uids, uid)); + n = GPOINTER_TO_INT(g_hash_table_lookup(u->unmatched_uids, uid)); if (n == 0) { - if (vee_folder_add_uid(folder_unmatched, u->source, uidin, u->hash)) - camel_folder_change_info_add_uid(folder_unmatched->changes, uid); + if (vee_folder_add_uid(u->folder_unmatched, u->source, uidin, u->hash)) + camel_folder_change_info_add_uid(u->folder_unmatched->changes, uid); } else { - CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(((CamelFolder *)folder_unmatched)->summary, uid); + CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(((CamelFolder *)u->folder_unmatched)->summary, uid); if (mi) { - camel_folder_summary_remove(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); - camel_folder_change_info_remove_uid(folder_unmatched->changes, uid); - camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); + camel_folder_summary_remove(((CamelFolder *)u->folder_unmatched)->summary, (CamelMessageInfo *)mi); + camel_folder_change_info_remove_uid(u->folder_unmatched->changes, uid); + camel_folder_summary_info_free(((CamelFolder *)u->folder_unmatched)->summary, (CamelMessageInfo *)mi); } } } @@ -1083,12 +1062,12 @@ folder_added_uid(char *uidin, void *value, struct _update_data *u) if ( (mi = vee_folder_add_uid(u->vf, u->source, uidin, u->hash)) ) { camel_folder_change_info_add_uid(u->vf->changes, camel_message_info_uid(mi)); - if (!CAMEL_IS_VEE_FOLDER(u->source)) { - if (g_hash_table_lookup_extended(unmatched_uids, camel_message_info_uid(mi), (void **)&oldkey, &oldval)) { + if (!CAMEL_IS_VEE_FOLDER(u->source) && u->unmatched_uids != NULL) { + if (g_hash_table_lookup_extended(u->unmatched_uids, camel_message_info_uid(mi), (void **)&oldkey, &oldval)) { n = GPOINTER_TO_INT (oldval); - g_hash_table_insert(unmatched_uids, oldkey, GINT_TO_POINTER(n+1)); + g_hash_table_insert(u->unmatched_uids, oldkey, GINT_TO_POINTER(n+1)); } else { - g_hash_table_insert(unmatched_uids, g_strdup(camel_message_info_uid(mi)), GINT_TO_POINTER(1)); + g_hash_table_insert(u->unmatched_uids, g_strdup(camel_message_info_uid(mi)), GINT_TO_POINTER(1)); } } } @@ -1105,6 +1084,8 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException int i, n, count, start, last; struct _update_data u; CamelFolderChangeInfo *vf_changes = NULL, *unmatched_changes = NULL; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; + GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL; if (vf == folder_unmatched) return 0; @@ -1120,6 +1101,8 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException u.source = source; u.vf = vf; + u.folder_unmatched = folder_unmatched; + u.unmatched_uids = unmatched_uids; camel_vee_folder_hash_folder(source, u.hash); CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); @@ -1136,7 +1119,8 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException if (g_hash_table_lookup(matchhash, all->pdata[i]) == NULL) g_hash_table_insert(allhash, all->pdata[i], GINT_TO_POINTER (1)); - CAMEL_VEE_FOLDER_LOCK(folder_unmatched, summary_lock); + if (folder_unmatched != NULL) + CAMEL_VEE_FOLDER_LOCK(folder_unmatched, summary_lock); /* scan, looking for "old" uid's to be removed */ start = -1; @@ -1162,6 +1146,7 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException } camel_folder_change_info_remove_uid(vf->changes, camel_message_info_uid(mi)); if (!CAMEL_IS_VEE_FOLDER(source) + && unmatched_uids != NULL && g_hash_table_lookup_extended(unmatched_uids, uid, (void **)&oldkey, &oldval)) { n = GPOINTER_TO_INT (oldval); if (n == 1) { @@ -1184,36 +1169,40 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException /* now matchhash contains any new uid's, add them, etc */ g_hash_table_foreach(matchhash, (GHFunc)folder_added_uid, &u); - /* scan unmatched, remove any that have vanished, etc */ - count = camel_folder_summary_count(((CamelFolder *)folder_unmatched)->summary); - for (i=0;isummary, i); + if (folder_unmatched != NULL) { + /* scan unmatched, remove any that have vanished, etc */ + count = camel_folder_summary_count(((CamelFolder *)folder_unmatched)->summary); + for (i=0;isummary, i); - if (mi) { - if (mi->folder == source) { - char *uid = (char *)camel_message_info_uid(mi); + if (mi) { + if (mi->folder == source) { + char *uid = (char *)camel_message_info_uid(mi); - if (g_hash_table_lookup(allhash, uid+8) == NULL) { - /* no longer exists at all, just remove it entirely */ - camel_folder_summary_remove_index(((CamelFolder *)folder_unmatched)->summary, i); - camel_folder_change_info_remove_uid(folder_unmatched->changes, camel_message_info_uid(mi)); - i--; - } else { - g_hash_table_remove(allhash, uid+8); + if (g_hash_table_lookup(allhash, uid+8) == NULL) { + /* no longer exists at all, just remove it entirely */ + camel_folder_summary_remove_index(((CamelFolder *)folder_unmatched)->summary, i); + camel_folder_change_info_remove_uid(folder_unmatched->changes, camel_message_info_uid(mi)); + i--; + } else { + g_hash_table_remove(allhash, uid+8); + } } + camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); } - camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); } - } - /* now allhash contains all potentially new uid's for the unmatched folder, process */ - if (!CAMEL_IS_VEE_FOLDER(source)) - g_hash_table_foreach(allhash, (GHFunc)unmatched_check_uid, &u); + /* now allhash contains all potentially new uid's for the unmatched folder, process */ + if (!CAMEL_IS_VEE_FOLDER(source)) + g_hash_table_foreach(allhash, (GHFunc)unmatched_check_uid, &u); - /* copy any changes so we can raise them outside the lock */ - if (camel_folder_change_info_changed(folder_unmatched->changes)) { - unmatched_changes = folder_unmatched->changes; - folder_unmatched->changes = camel_folder_change_info_new(); + /* copy any changes so we can raise them outside the lock */ + if (camel_folder_change_info_changed(folder_unmatched->changes)) { + unmatched_changes = folder_unmatched->changes; + folder_unmatched->changes = camel_folder_change_info_new(); + } + + CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); } if (camel_folder_change_info_changed(vf->changes)) { @@ -1221,7 +1210,6 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException vf->changes = camel_folder_change_info_new(); } - CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); g_hash_table_destroy(matchhash); @@ -1262,6 +1250,8 @@ folder_changed_add_uid(CamelFolder *sub, const char *uid, const char hash[8], Ca char *oldkey; void *oldval; int n; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; + GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL; vinfo = vee_folder_add_uid(vf, sub, uid, hash); if (vinfo == NULL) @@ -1270,7 +1260,7 @@ folder_changed_add_uid(CamelFolder *sub, const char *uid, const char hash[8], Ca vuid = camel_message_info_uid(vinfo); camel_folder_change_info_add_uid(vf->changes, vuid); - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub)) { + if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub) && folder_unmatched != NULL) { if (g_hash_table_lookup_extended(unmatched_uids, vuid, (void **)&oldkey, &oldval)) { n = GPOINTER_TO_INT (oldval); g_hash_table_insert(unmatched_uids, oldkey, GINT_TO_POINTER(n+1)); @@ -1294,6 +1284,8 @@ folder_changed_remove_uid(CamelFolder *sub, const char *uid, const char hash[8], void *oldval; int n; CamelVeeMessageInfo *vinfo; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; + GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL; vuid = alloca(strlen(uid)+9); memcpy(vuid, hash, 8); @@ -1306,7 +1298,7 @@ folder_changed_remove_uid(CamelFolder *sub, const char *uid, const char hash[8], camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); } - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub)) { + if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub) && folder_unmatched != NULL) { if (keep) { if (g_hash_table_lookup_extended(unmatched_uids, vuid, (void **)&oldkey, &oldval)) { n = GPOINTER_TO_INT (oldval); @@ -1342,16 +1334,18 @@ static void folder_changed_change_uid(CamelFolder *sub, const char *uid, const char hash[8], CamelVeeFolder *vf) { char *vuid; - CamelVeeMessageInfo *vinfo, *uinfo; + CamelVeeMessageInfo *vinfo, *uinfo = NULL; CamelMessageInfo *info; CamelFolder *folder = (CamelFolder *)vf; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; vuid = alloca(strlen(uid)+9); memcpy(vuid, hash, 8); strcpy(vuid+8, uid); vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, vuid); - uinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(((CamelFolder *)folder_unmatched)->summary, vuid); + if (folder_unmatched != NULL) + uinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(((CamelFolder *)folder_unmatched)->summary, vuid); if (vinfo || uinfo) { info = camel_folder_get_message_info(sub, uid); if (info) { @@ -1425,6 +1419,8 @@ folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg) *changed; GPtrArray *always_changed = NULL; GHashTable *matches_hash; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; + GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL; /* Check the folder hasn't beem removed while we weren't watching */ CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); @@ -1479,7 +1475,8 @@ folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg) } CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); - CAMEL_VEE_FOLDER_LOCK(folder_unmatched, summary_lock); + if (folder_unmatched != NULL) + CAMEL_VEE_FOLDER_LOCK(folder_unmatched, summary_lock); dd(printf("Vfolder '%s' subfolder changed '%s'\n", folder->full_name, sub->full_name)); dd(printf(" changed %d added %d removed %d\n", changes->uid_changed->len, changes->uid_added->len, changes->uid_removed->len)); @@ -1510,7 +1507,7 @@ folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg) memcpy(vuid, hash, 8); strcpy(vuid+8, uid); - if (!CAMEL_IS_VEE_FOLDER(sub) && g_hash_table_lookup(unmatched_uids, vuid) == NULL) { + if (!CAMEL_IS_VEE_FOLDER(sub) && folder_unmatched != NULL && g_hash_table_lookup(unmatched_uids, vuid) == NULL) { dd(printf(" adding uid '%s' to Unmatched [newly unmatched]\n", (char *)uid)); vinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info((CamelFolder *)folder_unmatched, vuid); if (vinfo == NULL) { @@ -1581,17 +1578,20 @@ folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg) folder_changed_change_uid(sub, changed->pdata[i], hash, vf); } - if (camel_folder_change_info_changed(folder_unmatched->changes)) { - unmatched_changes = folder_unmatched->changes; - folder_unmatched->changes = camel_folder_change_info_new(); - } + if (folder_unmatched != NULL) { + if (camel_folder_change_info_changed(folder_unmatched->changes)) { + unmatched_changes = folder_unmatched->changes; + folder_unmatched->changes = camel_folder_change_info_new(); + } + CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); + } + if (camel_folder_change_info_changed(vf->changes)) { vf_changes = vf->changes; vf->changes = camel_folder_change_info_new(); } - CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock); CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock); /* Cleanup stuff on our folder */ @@ -1608,7 +1608,7 @@ folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg) g_ptr_array_free(newchanged, TRUE); g_free(vuid); - + if (unmatched_changes) { camel_object_trigger_event((CamelObject *)folder_unmatched, "folder_changed", unmatched_changes); camel_folder_change_info_free(unmatched_changes); @@ -1671,6 +1671,8 @@ subfolder_renamed_update(CamelVeeFolder *vf, CamelFolder *sub, char hash[8]) { int count, i; CamelFolderChangeInfo *changes = NULL; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; + GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL; CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); @@ -1727,6 +1729,7 @@ static void subfolder_renamed(CamelFolder *f, void *event_data, CamelVeeFolder *vf) { char hash[8]; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; /* TODO: This could probably be done in another thread, tho it is pretty quick/memory bound */ @@ -1736,7 +1739,8 @@ subfolder_renamed(CamelFolder *f, void *event_data, CamelVeeFolder *vf) camel_vee_folder_hash_folder(f, hash); subfolder_renamed_update(vf, f, hash); - subfolder_renamed_update(folder_unmatched, f, hash); + if (folder_unmatched != NULL) + subfolder_renamed_update(folder_unmatched, f, hash); } static void diff --git a/camel/camel-vee-folder.h b/camel/camel-vee-folder.h index 3339b3a1d9..79f13a7280 100644 --- a/camel/camel-vee-folder.h +++ b/camel/camel-vee-folder.h @@ -56,6 +56,10 @@ struct _CamelVeeFolder { CamelFolderChangeInfo *changes; CamelFolderSearch *search; + + /* only set-up if our parent is a vee-store, used also as a flag to + * say that this folder is part of the unmatched folder */ + struct _CamelVeeStore *parent_vee_store; }; struct _CamelVeeFolderClass { diff --git a/camel/camel-vee-store.c b/camel/camel-vee-store.c index 770a0239c1..90c6ee1f95 100644 --- a/camel/camel-vee-store.c +++ b/camel/camel-vee-store.c @@ -93,12 +93,27 @@ camel_vee_store_init (CamelVeeStore *obj) /* we dont want a vtrash/vjunk on this one */ store->flags &= ~(CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK); + + /* Set up unmatched folder */ + obj->unmatched_uids = g_hash_table_new (g_str_hash, g_str_equal); + obj->folder_unmatched = (CamelVeeFolder *)camel_object_new (camel_vee_folder_get_type ()); + camel_vee_folder_construct (obj->folder_unmatched, store, CAMEL_UNMATCHED_NAME, CAMEL_STORE_FOLDER_PRIVATE); +} + +static void +cvs_free_unmatched(void *key, void *value, void *data) +{ + g_free(key); } static void camel_vee_store_finalise (CamelObject *obj) { - ; + CamelVeeStore *vstore = (CamelVeeStore *)obj; + + g_hash_table_foreach(vstore->unmatched_uids, cvs_free_unmatched, NULL); + g_hash_table_destroy(vstore->unmatched_uids); + camel_object_unref(vstore->folder_unmatched); } /** diff --git a/camel/camel-vee-store.h b/camel/camel-vee-store.h index d0352046be..a5a9864a56 100644 --- a/camel/camel-vee-store.h +++ b/camel/camel-vee-store.h @@ -44,6 +44,9 @@ typedef struct _CamelVeeStoreClass CamelVeeStoreClass; struct _CamelVeeStore { CamelStore parent; + /* Unmatched folder, set up in camel_vee_store_init */ + struct _CamelVeeFolder *folder_unmatched; + GHashTable *unmatched_uids; }; struct _CamelVeeStoreClass { -- cgit v1.2.3