diff options
-rw-r--r-- | camel/ChangeLog | 19 | ||||
-rw-r--r-- | camel/camel-store.c | 34 | ||||
-rw-r--r-- | camel/camel-vee-folder.c | 73 |
3 files changed, 110 insertions, 16 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index acd3428658..840cbe0895 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,18 @@ +2001-10-19 <NotZed@Ximian.com> + + * camel-vee-folder.c (camel_vee_folder_remove_folder): Lock the + right lock for unmatched subfolder list stuff. If the sub folder + is deleted & part of unmatched, or the last ref to the sub folder + is gone from unmatched, blow it away completely from unmatched, + but only do it once. + (vee_folder_remove_folder): Added arg to kill unmatched + unconditionally. Also handle deleted folders, always remove + stuff. + (folder_changed_change): Lock subfolder lock for entirety of + operation, and also check to see if the subfolder is still there + before doing any fancy work (incase it got removed while we were + waiting to execute). + 2001-10-18 Jeffrey Stedfast <fejj@ximian.com> * camel-mime-part-utils.c @@ -9,6 +24,10 @@ 2001-10-18 <NotZed@Ximian.com> + * camel-store.c (camel_store_unsubscribe_folder): If we are + unsubscribing from a folder we have loaded, set the folder + deleted, as with the delete_folder case. + * providers/(imap|local|pop3|sendmail|smtp)/Makefile.am: Added CAMEL_CFLAGS so we get the right iconv stuff, patch from Yanko Kaneti <yaneti@declera.com> diff --git a/camel/camel-store.c b/camel/camel-store.c index 3cd695f1bc..df2f5bebb2 100644 --- a/camel/camel-store.c +++ b/camel/camel-store.c @@ -330,6 +330,8 @@ camel_store_delete_folder (CamelStore *store, const char *folder_name, CamelExce char *key; CAMEL_STORE_LOCK(store, folder_lock); + + /* NB: Note similarity of this code to unsubscribe_folder */ /* if we deleted a folder, force it out of the cache, and also out of the vtrash if setup */ if (store->folders) { @@ -960,13 +962,45 @@ camel_store_unsubscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex) { + CamelFolder *folder = NULL; + char *key; + g_return_if_fail (CAMEL_IS_STORE (store)); g_return_if_fail (store->flags & CAMEL_STORE_SUBSCRIPTIONS); CAMEL_STORE_LOCK(store, folder_lock); + /* NB: Note similarity of this code to delete_folder */ + + /* if we deleted a folder, force it out of the cache, and also out of the vtrash if setup */ + if (store->folders) { + CAMEL_STORE_LOCK(store, cache_lock); + folder = g_hash_table_lookup(store->folders, folder_name); + if (folder) + camel_object_ref((CamelObject *)folder); + CAMEL_STORE_UNLOCK(store, cache_lock); + + if (folder) { + if (store->vtrash) + camel_vee_folder_remove_folder((CamelVeeFolder *)store->vtrash, folder); + camel_folder_delete (folder); + } + } + CS_CLASS (store)->unsubscribe_folder (store, folder_name, ex); + if (folder) + camel_object_unref((CamelObject *)folder); + + if (store->folders) { + CAMEL_STORE_LOCK(store, cache_lock); + if (g_hash_table_lookup_extended(store->folders, folder_name, (void **)&key, (void **)&folder)) { + g_hash_table_remove (store->folders, key); + g_free (key); + } + CAMEL_STORE_UNLOCK(store, cache_lock); + } + CAMEL_STORE_UNLOCK(store, folder_lock); } diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c index 26f724ab56..2946dffbb2 100644 --- a/camel/camel-vee-folder.c +++ b/camel/camel-vee-folder.c @@ -68,7 +68,7 @@ static void camel_vee_folder_init (CamelVeeFolder *obj); static void camel_vee_folder_finalise (CamelObject *obj); static int vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex); -static void vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source); +static void vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source, int killun); static void message_changed(CamelFolder *f, const char *uid, CamelVeeFolder *vf); static void folder_changed(CamelFolder *sub, CamelFolderChangeInfo *changes, CamelVeeFolder *vf); @@ -179,7 +179,7 @@ camel_vee_folder_finalise (CamelObject *obj) camel_object_unhook_event((CamelObject *)f, "deleted", (CamelObjectEventHookFunc) subfolder_deleted, vf); /* this updates the vfolder */ if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) - vee_folder_remove_folder(vf, f); + vee_folder_remove_folder(vf, f, FALSE); } camel_object_unref((CamelObject *)f); @@ -371,6 +371,7 @@ void camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) { struct _CamelVeeFolderPrivate *p = _PRIVATE(vf), *up = _PRIVATE(folder_unmatched); + int killun = FALSE; CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); @@ -383,19 +384,34 @@ camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) return; } + camel_object_unhook_event((CamelObject *)sub, "folder_changed", (CamelObjectEventHookFunc) folder_changed, vf); + camel_object_unhook_event((CamelObject *)sub, "message_changed", (CamelObjectEventHookFunc) message_changed, vf); + camel_object_unhook_event((CamelObject *)sub, "deleted", (CamelObjectEventHookFunc) subfolder_deleted, vf); + p->folders = g_list_remove(p->folders, sub); - if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && g_list_find(p->folders, sub) != NULL) { - up->folders = g_list_remove(up->folders, sub); - camel_object_unref((CamelObject *)sub); - } CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - vee_folder_remove_folder(vf, sub); + 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); + } + } 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); + } + if (g_list_find(up->folders, sub) == NULL) { + killun = TRUE; + } + } + CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, subfolder_lock); - camel_object_unhook_event((CamelObject *)sub, "folder_changed", (CamelObjectEventHookFunc) folder_changed, vf); - camel_object_unhook_event((CamelObject *)sub, "message_changed", (CamelObjectEventHookFunc) message_changed, vf); - camel_object_unhook_event((CamelObject *)sub, "deleted", (CamelObjectEventHookFunc) subfolder_deleted, vf); + vee_folder_remove_folder(vf, sub, killun); camel_object_unref((CamelObject *)sub); } @@ -781,22 +797,22 @@ vee_folder_add_uid(CamelVeeFolder *vf, CamelFolder *f, const char *inuid, const } static void -vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) +vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source, int killun) { int i, count, n, still; char *oldkey; CamelFolder *folder = (CamelFolder *)vf; char hash[8]; - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); + /*struct _CamelVeeFolderPrivate *p = _PRIVATE(vf);*/ CamelFolderChangeInfo *vf_changes = NULL, *unmatched_changes = 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) { + if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !killun) { CAMEL_VEE_FOLDER_LOCK(folder_unmatched, subfolder_lock); - still = g_list_find(p->folders, source) != NULL; + 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 { @@ -806,6 +822,23 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) 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) { + count = camel_folder_summary_count(((CamelFolder *)folder_unmatched)->summary); + for (i=0;i<count;i++) { + CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(((CamelFolder *)folder_unmatched)->summary, i); + + if (mi) { + if (mi->folder == source) { + 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--; + } + camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); + } + } + } + count = camel_folder_summary_count(folder->summary); for (i=0;i<count;i++) { CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(folder->summary, i); @@ -833,7 +866,6 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) g_hash_table_remove(unmatched_uids, oldkey); g_free(oldkey); } - camel_folder_summary_remove_uid(((CamelFolder *)folder_unmatched)->summary, uid); } } } @@ -1188,11 +1220,18 @@ folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg) GPtrArray *matches; GHashTable *matches_hash; - camel_vee_folder_hash_folder(sub, hash); + /* Check the folder hasn't beem removed while we weren't watching */ + CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); + if (g_list_find(_PRIVATE(vf)->folders, sub) == NULL) { + CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); + return; + } CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); CAMEL_VEE_FOLDER_LOCK(folder_unmatched, summary_lock); + camel_vee_folder_hash_folder(sub, hash); + 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)); @@ -1283,6 +1322,8 @@ folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg) camel_object_trigger_event((CamelObject *)vf, "folder_changed", vf_changes); camel_folder_change_info_free(vf_changes); } + + CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); } static void |