From 0515ef5e4d5d138f1f7e9956b7a643cc01d7cf19 Mon Sep 17 00:00:00 2001 From: 9 Date: Fri, 19 Oct 2001 05:33:21 +0000 Subject: Lock the right lock for unmatched subfolder list stuff. If the sub folder 2001-10-19 * 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). * 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. svn path=/trunk/; revision=13786 --- camel/ChangeLog | 19 +++++++++++++ camel/camel-store.c | 34 ++++++++++++++++++++++ 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 + + * 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 * camel-mime-part-utils.c @@ -9,6 +24,10 @@ 2001-10-18 + * 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 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;isummary, 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;isummary, 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 -- cgit v1.2.3