aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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