aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
author9 <NotZed@Ximian.com>2001-10-19 13:33:21 +0800
committerMichael Zucci <zucchi@src.gnome.org>2001-10-19 13:33:21 +0800
commit0515ef5e4d5d138f1f7e9956b7a643cc01d7cf19 (patch)
tree81be21ec9add33d807bd7150887da30db713e5af /camel
parentec619f7bfaf14ee913f565664459103507adb34f (diff)
downloadgsoc2013-evolution-0515ef5e4d5d138f1f7e9956b7a643cc01d7cf19.tar.gz
gsoc2013-evolution-0515ef5e4d5d138f1f7e9956b7a643cc01d7cf19.tar.zst
gsoc2013-evolution-0515ef5e4d5d138f1f7e9956b7a643cc01d7cf19.zip
Lock the right lock for unmatched subfolder list stuff. If the sub folder
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). * 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
Diffstat (limited to 'camel')
-rw-r--r--camel/ChangeLog19
-rw-r--r--camel/camel-store.c34
-rw-r--r--camel/camel-vee-folder.c73
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