[evolution] Make the mail folder cache a proper GObject



commit 65705e4f55560889ac6de638aa8f3245c06349c0
Author: Jonathon Jongsma <jonathon quotidian org>
Date:   Wed Dec 9 14:29:49 2009 -0600

    Make the mail folder cache a proper GObject
    
    mail-folder-cache previously was a bit of a pseudo object (sort of a singleton)
    that operated on some file static data.  This commit re-factors things so that
    it is a proper class named MailFolderCache.  At the moment, this doesn't gain us
    much, but in the future, it will allow us to add signals, etc so that we can
    de-couple a lot of the interdependencies in here.  This is essentially a
    pre-requisite to splitting up a lot of the mail backend stuff.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=604627

 mail/e-mail-store.c                     |   10 +-
 mail/em-folder-tree-model.c             |    3 +-
 mail/em-folder-utils.c                  |    2 +-
 mail/mail-folder-cache.c                |  382 +++++++++++++++++++------------
 mail/mail-folder-cache.h                |   57 ++++-
 mail/mail-send-recv.c                   |    2 +-
 mail/mail-tools.c                       |    2 +-
 mail/mail-vfolder.c                     |    7 +-
 plugins/itip-formatter/itip-formatter.c |    3 +-
 9 files changed, 304 insertions(+), 164 deletions(-)
---
diff --git a/mail/e-mail-store.c b/mail/e-mail-store.c
index 749459d..2cc03ad 100644
--- a/mail/e-mail-store.c
+++ b/mail/e-mail-store.c
@@ -147,9 +147,9 @@ mail_store_note_store_cb (CamelStore *store,
 	if (!store_info->removed) {
 		/* This keeps message counters up-to-date. */
 		if (store_info->vtrash != NULL)
-			mail_note_folder (store_info->vtrash);
+			mail_folder_cache_note_folder (mail_folder_cache_get_default (), store_info->vtrash);
 		if (store_info->vjunk != NULL)
-			mail_note_folder (store_info->vjunk);
+			mail_folder_cache_note_folder (mail_folder_cache_get_default (), store_info->vjunk);
 	}
 
 	store_info_unref (store_info);
@@ -177,7 +177,7 @@ mail_store_add (CamelStore *store,
 	em_folder_tree_model_add_store (
 		default_model, store, store_info->display_name);
 
-	mail_note_store (
+	mail_folder_cache_note_store (mail_folder_cache_get_default (),
 		store, NULL,
 		mail_store_note_store_cb,
 		store_info_ref (store_info));
@@ -194,7 +194,7 @@ mail_store_add_local_done_cb (CamelStore *store,
 	for (ii = 0; ii < E_MAIL_NUM_LOCAL_FOLDERS; ii++) {
 		folder = e_mail_local_get_folder (ii);
 		if (folder != NULL)
-			mail_note_folder (folder);
+			mail_folder_cache_note_folder (mail_folder_cache_get_default (), folder);
 	}
 }
 
@@ -367,7 +367,7 @@ e_mail_store_remove (CamelStore *store)
 	camel_object_ref (store);
 
 	g_hash_table_remove (store_table, store);
-	mail_note_store_remove (store);
+	mail_folder_cache_note_store_remove (mail_folder_cache_get_default (), store);
 
 	default_model = em_folder_tree_model_get_default ();
 	em_folder_tree_model_remove_store (default_model, store);
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c
index b753cd7..4833277 100644
--- a/mail/em-folder-tree-model.c
+++ b/mail/em-folder-tree-model.c
@@ -550,7 +550,8 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
 	/* HACK2: We do the same to the draft folder */
 	/* This is duplicated in mail-folder-cache too, should perhaps be functionised */
 	unread = fi->unread;
-	if (mail_note_get_folder_from_uri(fi->uri, &folder) && folder) {
+	if (mail_folder_cache_get_folder_from_uri(mail_folder_cache_get_default (),
+						fi->uri, &folder) && folder) {
 		is_drafts = em_utils_folder_is_drafts (folder, fi->uri);
 
 		if (is_drafts || em_utils_folder_is_outbox (folder, fi->uri)) {
diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c
index cf805f3..2838e82 100644
--- a/mail/em-folder-utils.c
+++ b/mail/em-folder-utils.c
@@ -448,7 +448,7 @@ em_folder_utils_delete_folder (CamelFolder *folder)
 		return;
 	}
 
-	if (mail_folder_cache_get_folder_info_flags (folder, &flags) && (flags & CAMEL_FOLDER_SYSTEM))
+	if (mail_folder_cache_get_folder_info_flags (mail_folder_cache_get_default (), folder, &flags) && (flags & CAMEL_FOLDER_SYSTEM))
 	{
 		e_alert_run_dialog_for_args (parent,"mail:no-delete-special-folder", folder->name, NULL);
 		return;
diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c
index 59f823f..2bba248 100644
--- a/mail/mail-folder-cache.c
+++ b/mail/mail-folder-cache.c
@@ -14,10 +14,12 @@
  *
  *
  * Authors:
- *		Peter Williams <peterw ximian com>
- *	    Michael Zucchi <notzed ximian com>
+ *   Peter Williams <peterw ximian com>
+ *   Michael Zucchi <notzed ximian com>
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2009 Intel Corporation
  *
  */
 
@@ -71,9 +73,24 @@
 
 /* This code is a mess, there is no reason it should be so complicated. */
 
-/* note that many things are effectively serialised by having them run in
-   the main loop thread which they need to do because of corba/gtk calls */
-G_LOCK_DEFINE_STATIC (stores);
+G_DEFINE_TYPE (MailFolderCache, mail_folder_cache, G_TYPE_OBJECT)
+
+#define FOLDER_CACHE_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), MAIL_TYPE_FOLDER_CACHE, MailFolderCachePrivate))
+
+struct _MailFolderCachePrivate
+{
+	guint ping_id;
+	/* Store to storeinfo table, active stores */
+	GHashTable *stores;
+	GMutex *stores_mutex;
+	/* List of folder changes to be executed in gui thread */
+	GQueue updates;
+	gint update_id;
+	/* hack for people who LIKE to have unsent count */
+	gint count_sent;
+	gint count_trash;
+};
 
 struct _folder_info {
 	struct _store_info *store_info;	/* 'parent' link */
@@ -118,24 +135,13 @@ struct _store_info {
 	GQueue folderinfo_updates;
 };
 
+
 static void folder_changed(CamelObject *o, gpointer event_data, gpointer user_data);
 static void folder_renamed(CamelObject *o, gpointer event_data, gpointer user_data);
 static void folder_finalised(CamelObject *o, gpointer event_data, gpointer user_data);
 
-static guint ping_id = 0;
 static gboolean ping_cb (gpointer user_data);
 
-/* Store to storeinfo table, active stores */
-static GHashTable *stores = NULL;
-
-/* List of folder changes to be executed in gui thread */
-static GQueue updates = G_QUEUE_INIT;
-static gint update_id = -1;
-
-/* hack for people who LIKE to have unsent count */
-static gint count_sent = FALSE;
-static gint count_trash = FALSE;
-
 static void
 free_update(struct _folder_update *up)
 {
@@ -152,18 +158,19 @@ free_update(struct _folder_update *up)
 }
 
 static void
-real_flush_updates (void)
+real_flush_updates (gpointer o, gpointer event_data, gpointer data)
 {
 	EShell *shell;
 	EMFolderTreeModel *default_model;
 	struct _folder_update *up;
+	MailFolderCache *self = (MailFolderCache*) o;
 
 	shell = e_shell_get_default ();
 	default_model = em_folder_tree_model_get_default ();
 
-	G_LOCK (stores);
-	while ((up = g_queue_pop_head (&updates)) != NULL) {
-		G_UNLOCK (stores);
+	g_mutex_lock (self->priv->stores_mutex);
+	while ((up = g_queue_pop_head (&self->priv->updates)) != NULL) {
+		g_mutex_unlock (self->priv->stores_mutex);
 
 		if (up->remove) {
 			if (up->delete) {
@@ -223,31 +230,31 @@ real_flush_updates (void)
 			CamelFolder *folder = camel_store_get_folder (up->store, up->full_name, 0, NULL);
 
 			if (folder) {
-				mail_note_folder (folder);
+				mail_folder_cache_note_folder (self, folder);
 				camel_object_unref (folder);
 			}
 		}
 
 		free_update(up);
 
-		G_LOCK (stores);
+		g_mutex_lock (self->priv->stores_mutex);
 	}
-	update_id = -1;
-	G_UNLOCK (stores);
+	self->priv->update_id = -1;
+	g_mutex_unlock (self->priv->stores_mutex);
 }
 
 static void
-flush_updates (void)
+flush_updates (MailFolderCache *self)
 {
-	if (update_id == -1 && !g_queue_is_empty (&updates))
-		update_id = mail_async_event_emit (
+	if (self->priv->update_id == -1 && !g_queue_is_empty (&self->priv->updates))
+		self->priv->update_id = mail_async_event_emit (
 			mail_async_event, MAIL_ASYNC_GUI,
 			(MailAsyncFunc) real_flush_updates,
-			NULL, NULL, NULL);
+			self, NULL, NULL);
 }
 
 static void
-unset_folder_info(struct _folder_info *mfi, gint delete, gint unsub)
+unset_folder_info(MailFolderCache *self, struct _folder_info *mfi, gint delete, gint unsub)
 {
 	struct _folder_update *up;
 
@@ -256,9 +263,9 @@ unset_folder_info(struct _folder_info *mfi, gint delete, gint unsub)
 	if (mfi->folder) {
 		CamelFolder *folder = mfi->folder;
 
-		camel_object_unhook_event(folder, "folder_changed", folder_changed, NULL);
-		camel_object_unhook_event(folder, "renamed", folder_renamed, NULL);
-		camel_object_unhook_event(folder, "finalize", folder_finalised, NULL);
+		camel_object_unhook_event(folder, "folder_changed", folder_changed, self);
+		camel_object_unhook_event(folder, "renamed", folder_renamed, self);
+		camel_object_unhook_event(folder, "finalize", folder_finalised, self);
 	}
 
 	if ((mfi->flags & CAMEL_FOLDER_NOSELECT) == 0) {
@@ -272,8 +279,8 @@ unset_folder_info(struct _folder_info *mfi, gint delete, gint unsub)
 		camel_object_ref(up->store);
 		up->uri = g_strdup(mfi->uri);
 
-		g_queue_push_head (&updates, up);
-		flush_updates();
+		g_queue_push_head (&self->priv->updates, up);
+		flush_updates(self);
 	}
 }
 
@@ -308,7 +315,7 @@ free_folder_info(struct _folder_info *mfi)
  * it's correct.  */
 
 static void
-update_1folder(struct _folder_info *mfi, gint new, const gchar *msg_uid, const gchar *msg_sender, const gchar *msg_subject, CamelFolderInfo *info)
+update_1folder(MailFolderCache *self, struct _folder_info *mfi, gint new, const gchar *msg_uid, const gchar *msg_sender, const gchar *msg_subject, CamelFolderInfo *info)
 {
 	struct _folder_update *up;
 	CamelFolder *folder;
@@ -320,10 +327,10 @@ update_1folder(struct _folder_info *mfi, gint new, const gchar *msg_uid, const g
 		gboolean is_drafts = FALSE, is_outbox = FALSE;
 
 		d(printf("update 1 folder '%s'\n", folder->full_name));
-		if ((count_trash && (CAMEL_IS_VTRASH_FOLDER (folder)))
+		if ((self->priv->count_trash && (CAMEL_IS_VTRASH_FOLDER (folder)))
 		    || (is_drafts = em_utils_folder_is_drafts (folder, info ? info->uri : NULL))
 		    || (is_outbox = em_utils_folder_is_outbox (folder, info ? info->uri : NULL))
-		    || (count_sent && em_utils_folder_is_sent (folder, info ? info->uri : NULL))) {
+		    || (self->priv->count_sent && em_utils_folder_is_sent (folder, info ? info->uri : NULL))) {
 			d(printf(" total count\n"));
 			unread = camel_folder_get_message_count (folder);
 			if (is_drafts || is_outbox) {
@@ -362,19 +369,19 @@ update_1folder(struct _folder_info *mfi, gint new, const gchar *msg_uid, const g
 	up->msg_sender = g_strdup (msg_sender);
 	up->msg_subject = g_strdup (msg_subject);
 	camel_object_ref(up->store);
-	g_queue_push_head (&updates, up);
-	flush_updates();
+	g_queue_push_head (&self->priv->updates, up);
+	flush_updates(self);
 }
 
 static void
-setup_folder(CamelFolderInfo *fi, struct _store_info *si)
+setup_folder(MailFolderCache *self, CamelFolderInfo *fi, struct _store_info *si)
 {
 	struct _folder_info *mfi;
 	struct _folder_update *up;
 
 	mfi = g_hash_table_lookup(si->folders, fi->full_name);
 	if (mfi) {
-		update_1folder (mfi, 0, NULL, NULL, NULL, fi);
+		update_1folder (self, mfi, 0, NULL, NULL, NULL, fi);
 	} else {
 		d(printf("Adding new folder: %s (%s)\n", fi->full_name, fi->uri));
 		mfi = g_malloc0(sizeof(*mfi));
@@ -396,21 +403,21 @@ setup_folder(CamelFolderInfo *fi, struct _store_info *si)
 		if ((fi->flags & CAMEL_FOLDER_NOSELECT) == 0)
 			up->add = TRUE;
 
-		g_queue_push_head (&updates, up);
-		flush_updates();
+		g_queue_push_head (&self->priv->updates, up);
+		flush_updates(self);
 	}
 }
 
 static void
-create_folders(CamelFolderInfo *fi, struct _store_info *si)
+create_folders(MailFolderCache *self, CamelFolderInfo *fi, struct _store_info *si)
 {
 	d(printf("Setup new folder: %s\n  %s\n", fi->uri, fi->full_name));
 
 	while (fi) {
-		setup_folder(fi, si);
+		setup_folder(self, fi, si);
 
 		if (fi->child)
-			create_folders(fi->child, si);
+			create_folders(self, fi->child, si);
 
 		fi = fi->next;
 	}
@@ -433,6 +440,7 @@ folder_changed (CamelObject *o, gpointer event_data, gpointer user_data)
 	gint i;
 	guint32 flags;
 	gchar *uid = NULL, *sender = NULL, *subject = NULL;
+	MailFolderCache *self = (MailFolderCache*) user_data;
 
 	d(printf("folder '%s' changed\n", folder->full_name));
 
@@ -478,14 +486,14 @@ folder_changed (CamelObject *o, gpointer event_data, gpointer user_data)
 	if (new > 0 || !last_newmail)
 		time (&last_newmail);
 
-	G_LOCK (stores);
-	if (stores != NULL
-	    && (si = g_hash_table_lookup(stores, store)) != NULL
+	g_mutex_lock (self->priv->stores_mutex);
+	if (self->priv->stores != NULL
+	    && (si = g_hash_table_lookup(self->priv->stores, store)) != NULL
 	    && (mfi = g_hash_table_lookup(si->folders, folder->full_name)) != NULL
 	    && mfi->folder == folder) {
-		update_1folder (mfi, new, uid, sender, subject, NULL);
+		update_1folder (self, mfi, new, uid, sender, subject, NULL);
 	}
-	G_UNLOCK (stores);
+	g_mutex_unlock (self->priv->stores_mutex);
 
 	g_free (uid);
 	g_free (sender);
@@ -499,16 +507,17 @@ folder_finalised(CamelObject *o, gpointer event_data, gpointer user_data)
 	CamelStore *store = folder->parent_store;
 	struct _store_info *si;
 	struct _folder_info *mfi;
+	MailFolderCache *self = (MailFolderCache*) user_data;
 
 	d(printf("Folder finalised '%s'!\n", ((CamelFolder *)o)->full_name));
-	G_LOCK (stores);
-	if (stores != NULL
-	    && (si = g_hash_table_lookup(stores, store)) != NULL
+	g_mutex_lock (self->priv->stores_mutex);
+	if (self->priv->stores != NULL
+	    && (si = g_hash_table_lookup(self->priv->stores, store)) != NULL
 	    && (mfi = g_hash_table_lookup(si->folders, folder->full_name)) != NULL
 	    && mfi->folder == folder) {
 		mfi->folder = NULL;
 	}
-	G_UNLOCK (stores);
+	g_mutex_unlock (self->priv->stores_mutex);
 }
 
 static void
@@ -524,7 +533,7 @@ folder_renamed(CamelObject *o, gpointer event_data, gpointer user_data)
 	/* Dont do anything, do it from the store rename event? */
 }
 
-void mail_note_folder(CamelFolder *folder)
+void mail_folder_cache_note_folder(MailFolderCache *self, CamelFolder *folder)
 {
 	CamelStore *store = folder->parent_store;
 	struct _store_info *si;
@@ -532,30 +541,30 @@ void mail_note_folder(CamelFolder *folder)
 
 	d(printf("noting folder '%s'\n", folder->full_name));
 
-	G_LOCK (stores);
-	if (stores == NULL
-	    || (si = g_hash_table_lookup(stores, store)) == NULL
+	g_mutex_lock (self->priv->stores_mutex);
+	if (self->priv->stores == NULL
+	    || (si = g_hash_table_lookup(self->priv->stores, store)) == NULL
 	    || (mfi = g_hash_table_lookup(si->folders, folder->full_name)) == NULL) {
 		w(g_warning("Noting folder before store initialised"));
-		G_UNLOCK (stores);
+		g_mutex_unlock (self->priv->stores_mutex);
 		return;
 	}
 
 	/* dont do anything if we already have this */
 	if (mfi->folder == folder) {
-		G_UNLOCK (stores);
+		g_mutex_unlock (self->priv->stores_mutex);
 		return;
 	}
 
 	mfi->folder = folder;
 
-	update_1folder (mfi, 0, NULL, NULL, NULL, NULL);
+	update_1folder (self, mfi, 0, NULL, NULL, NULL, NULL);
 
-	G_UNLOCK (stores);
+	g_mutex_unlock (self->priv->stores_mutex);
 
-	camel_object_hook_event(folder, "folder_changed", folder_changed, NULL);
-	camel_object_hook_event(folder, "renamed", folder_renamed, NULL);
-	camel_object_hook_event(folder, "finalize", folder_finalised, NULL);
+	camel_object_hook_event(folder, "folder_changed", folder_changed, self);
+	camel_object_hook_event(folder, "renamed", folder_renamed, self);
+	camel_object_hook_event(folder, "finalize", folder_finalised, self);
 }
 
 static void
@@ -563,14 +572,15 @@ store_folder_subscribed(CamelObject *o, gpointer event_data, gpointer data)
 {
 	struct _store_info *si;
 	CamelFolderInfo *fi = event_data;
+	MailFolderCache *self = (MailFolderCache*) data;
 
 	d(printf("Store folder subscribed '%s' store '%s' \n", fi->full_name, camel_url_to_string(((CamelService *)o)->url, 0)));
 
-	G_LOCK (stores);
-	si = g_hash_table_lookup(stores, o);
+	g_mutex_lock (self->priv->stores_mutex);
+	si = g_hash_table_lookup(self->priv->stores, o);
 	if (si)
-		setup_folder(fi, si);
-	G_UNLOCK (stores);
+		setup_folder(self, fi, si);
+	g_mutex_unlock (self->priv->stores_mutex);
 }
 
 static void
@@ -585,8 +595,9 @@ static void
 store_folder_opened(CamelObject *o, gpointer event_data, gpointer data)
 {
 	CamelFolder *folder = event_data;
+	MailFolderCache *self = (MailFolderCache*) data;
 
-	mail_note_folder(folder);
+	mail_folder_cache_note_folder(self, folder);
 }
 
 static void
@@ -596,21 +607,22 @@ store_folder_unsubscribed(CamelObject *o, gpointer event_data, gpointer data)
 	CamelFolderInfo *fi = event_data;
 	struct _folder_info *mfi;
 	CamelStore *store = (CamelStore *)o;
+	MailFolderCache *self = (MailFolderCache*) data;
 
 	d(printf("Store Folder deleted: %s\n", fi->full_name));
 
-	G_LOCK (stores);
-	si = g_hash_table_lookup(stores, store);
+	g_mutex_lock (self->priv->stores_mutex);
+	si = g_hash_table_lookup(self->priv->stores, store);
 	if (si) {
 		mfi = g_hash_table_lookup(si->folders, fi->full_name);
 		if (mfi) {
 			g_hash_table_remove(si->folders, mfi->full_name);
 			g_hash_table_remove(si->folders_uri, mfi->uri);
-			unset_folder_info(mfi, TRUE, TRUE);
+			unset_folder_info(self, mfi, TRUE, TRUE);
 			free_folder_info(mfi);
 		}
 	}
-	G_UNLOCK (stores);
+	g_mutex_unlock (self->priv->stores_mutex);
 }
 
 static void
@@ -644,7 +656,7 @@ folder_to_url(CamelStore *store, const gchar *full_name)
 }
 
 static void
-rename_folders(struct _store_info *si, const gchar *oldbase, const gchar *newbase, CamelFolderInfo *fi)
+rename_folders(MailFolderCache *self, struct _store_info *si, const gchar *oldbase, const gchar *newbase, CamelFolderInfo *fi)
 {
 	gchar *old, *olduri, *oldfile, *newuri, *newfile;
 	struct _folder_info *mfi;
@@ -695,13 +707,13 @@ rename_folders(struct _store_info *si, const gchar *oldbase, const gchar *newbas
 	if ((fi->flags & CAMEL_FOLDER_NOSELECT) == 0)
 		up->add = TRUE;
 
-	g_queue_push_tail (&updates, up);
-	flush_updates();
+	g_queue_push_tail (&self->priv->updates, up);
+	flush_updates(self);
 #if 0
 	if (fi->sibling)
-		rename_folders(si, oldbase, newbase, fi->sibling, folders);
+		rename_folders(self, si, oldbase, newbase, fi->sibling, folders);
 	if (fi->child)
-		rename_folders(si, oldbase, newbase, fi->child, folders);
+		rename_folders(self, si, oldbase, newbase, fi->child, folders);
 #endif
 
 	/* rename the meta-data we maintain ourselves */
@@ -754,11 +766,12 @@ store_folder_renamed(CamelObject *o, gpointer event_data, gpointer data)
 	CamelStore *store = (CamelStore *)o;
 	CamelRenameInfo *info = event_data;
 	struct _store_info *si;
+	MailFolderCache *self = (MailFolderCache*) data;
 
 	d(printf("Folder renamed: oldbase = '%s' new->full = '%s'\n", info->old_base, info->new->full_name));
 
-	G_LOCK (stores);
-	si = g_hash_table_lookup(stores, store);
+	g_mutex_lock (self->priv->stores_mutex);
+	si = g_hash_table_lookup(self->priv->stores, store);
 	if (si) {
 		GPtrArray *folders = g_ptr_array_new();
 		CamelFolderInfo *top;
@@ -771,13 +784,13 @@ store_folder_renamed(CamelObject *o, gpointer event_data, gpointer data)
 
 		top = folders->pdata[0];
 		for (i=0;i<folders->len;i++) {
-			rename_folders(si, info->old_base, top->full_name, folders->pdata[i]);
+			rename_folders(self, si, info->old_base, top->full_name, folders->pdata[i]);
 		}
 
 		g_ptr_array_free(folders, TRUE);
 
 	}
-	G_UNLOCK (stores);
+	g_mutex_unlock (self->priv->stores_mutex);
 }
 
 struct _update_data {
@@ -786,12 +799,14 @@ struct _update_data {
 
 	gboolean (*done)(CamelStore *store, CamelFolderInfo *info, gpointer data);
 	gpointer data;
+	MailFolderCache *cache;
 };
 
 static void
 unset_folder_info_hash(gchar *path, struct _folder_info *mfi, gpointer data)
 {
-	unset_folder_info(mfi, FALSE, FALSE);
+	MailFolderCache *self = (MailFolderCache*) data;
+	unset_folder_info(self, mfi, FALSE, FALSE);
 }
 
 static void
@@ -801,29 +816,29 @@ free_folder_info_hash(gchar *path, struct _folder_info *mfi, gpointer data)
 }
 
 void
-mail_note_store_remove(CamelStore *store)
+mail_folder_cache_note_store_remove(MailFolderCache *self, CamelStore *store)
 {
 	struct _store_info *si;
 
 	g_return_if_fail (CAMEL_IS_STORE(store));
 
-	if (stores == NULL)
+	if (self->priv->stores == NULL)
 		return;
 
 	d(printf("store removed!!\n"));
-	G_LOCK (stores);
-	si = g_hash_table_lookup(stores, store);
+	g_mutex_lock (self->priv->stores_mutex);
+	si = g_hash_table_lookup(self->priv->stores, store);
 	if (si) {
 		GList *link;
-		g_hash_table_remove(stores, store);
+		g_hash_table_remove(self->priv->stores, store);
 
-		camel_object_unhook_event(store, "folder_opened", store_folder_opened, NULL);
-		camel_object_unhook_event(store, "folder_created", store_folder_created, NULL);
-		camel_object_unhook_event(store, "folder_deleted", store_folder_deleted, NULL);
-		camel_object_unhook_event(store, "folder_renamed", store_folder_renamed, NULL);
-		camel_object_unhook_event(store, "folder_subscribed", store_folder_subscribed, NULL);
-		camel_object_unhook_event(store, "folder_unsubscribed", store_folder_unsubscribed, NULL);
-		g_hash_table_foreach(si->folders, (GHFunc)unset_folder_info_hash, NULL);
+		camel_object_unhook_event(store, "folder_opened", store_folder_opened, self);
+		camel_object_unhook_event(store, "folder_created", store_folder_created, self);
+		camel_object_unhook_event(store, "folder_deleted", store_folder_deleted, self);
+		camel_object_unhook_event(store, "folder_renamed", store_folder_renamed, self);
+		camel_object_unhook_event(store, "folder_subscribed", store_folder_subscribed, self);
+		camel_object_unhook_event(store, "folder_unsubscribed", store_folder_unsubscribed, self);
+		g_hash_table_foreach(si->folders, (GHFunc)unset_folder_info_hash, self);
 
 		link = g_queue_peek_head_link (&si->folderinfo_updates);
 
@@ -844,7 +859,7 @@ mail_note_store_remove(CamelStore *store)
 		g_free(si);
 	}
 
-	G_UNLOCK (stores);
+	g_mutex_unlock (self->priv->stores_mutex);
 }
 
 static gboolean
@@ -856,17 +871,17 @@ update_folders(CamelStore *store, CamelFolderInfo *fi, gpointer data)
 
 	d(printf("Got folderinfo for store %s\n", store->parent_object.provider->protocol));
 
-	G_LOCK (stores);
-	si = g_hash_table_lookup(stores, store);
+	g_mutex_lock (ud->cache->priv->stores_mutex);
+	si = g_hash_table_lookup(ud->cache->priv->stores, store);
 	if (si && !ud->cancel) {
 		/* the 'si' is still there, so we can remove ourselves from its list */
 		/* otherwise its not, and we're on our own and free anyway */
 		g_queue_remove (&si->folderinfo_updates, ud);
 
 		if (fi)
-			create_folders(fi, si);
+			create_folders(ud->cache, fi, si);
 	}
-	G_UNLOCK (stores);
+	g_mutex_unlock (ud->cache->priv->stores_mutex);
 
 	if (ud->done)
 		res = ud->done (store, fi, ud->data);
@@ -943,11 +958,12 @@ ping_store (gpointer key, gpointer val, gpointer user_data)
 static gboolean
 ping_cb (gpointer user_data)
 {
-	G_LOCK (stores);
+	MailFolderCache *self = (MailFolderCache*) user_data;
+	g_mutex_lock (self->priv->stores_mutex);
 
-	g_hash_table_foreach (stores, ping_store, NULL);
+	g_hash_table_foreach (self->priv->stores, ping_store, NULL);
 
-	G_UNLOCK (stores);
+	g_mutex_unlock (self->priv->stores_mutex);
 
 	return TRUE;
 }
@@ -957,9 +973,9 @@ store_online_cb (CamelStore *store, gpointer data)
 {
 	struct _update_data *ud = data;
 
-	G_LOCK (stores);
+	g_mutex_lock (ud->cache->priv->stores_mutex);
 
-	if (g_hash_table_lookup(stores, store) != NULL && !ud->cancel) {
+	if (g_hash_table_lookup(ud->cache->priv->stores, store) != NULL && !ud->cancel) {
 		/* re-use the cancel id.  we're already in the store update list too */
 		ud->id = mail_get_folderinfo(store, NULL, update_folders, ud);
 	} else {
@@ -968,34 +984,23 @@ store_online_cb (CamelStore *store, gpointer data)
 		g_free(ud);
 	}
 
-	G_UNLOCK (stores);
+	g_mutex_unlock (ud->cache->priv->stores_mutex);
 }
 
 void
-mail_note_store(CamelStore *store, CamelOperation *op,
-		gboolean (*done)(CamelStore *store, CamelFolderInfo *info, gpointer data), gpointer data)
+mail_folder_cache_note_store(MailFolderCache *self, CamelStore *store, CamelOperation *op,
+		NoteDoneFunc done, gpointer data)
 {
 	struct _store_info *si;
 	struct _update_data *ud;
-	const gchar *buf;
-	guint timeout;
 	gint hook = 0;
 
 	g_return_if_fail (CAMEL_IS_STORE(store));
 	g_return_if_fail (mail_in_main_thread());
 
-	G_LOCK (stores);
+	g_mutex_lock (self->priv->stores_mutex);
 
-	if (stores == NULL) {
-		stores = g_hash_table_new(NULL, NULL);
-		count_sent = getenv("EVOLUTION_COUNT_SENT") != NULL;
-		count_trash = getenv("EVOLUTION_COUNT_TRASH") != NULL;
-		buf = getenv ("EVOLUTION_PING_TIMEOUT");
-		timeout = buf ? strtoul (buf, NULL, 10) : 600;
-		ping_id = g_timeout_add_seconds (timeout, ping_cb, NULL);
-	}
-
-	si = g_hash_table_lookup(stores, store);
+	si = g_hash_table_lookup(self->priv->stores, store);
 	if (si == NULL) {
 		d(printf("Noting a new store: %p: %s\n", store, camel_url_to_string(((CamelService *)store)->url, 0)));
 
@@ -1005,7 +1010,7 @@ mail_note_store(CamelStore *store, CamelOperation *op,
 						   CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(store))->compare_folder_name);
 		si->store = store;
 		camel_object_ref((CamelObject *)store);
-		g_hash_table_insert(stores, store, si);
+		g_hash_table_insert(self->priv->stores, store, si);
 		g_queue_init (&si->folderinfo_updates);
 		hook = TRUE;
 	}
@@ -1014,6 +1019,7 @@ mail_note_store(CamelStore *store, CamelOperation *op,
 	ud->done = done;
 	ud->data = data;
 	ud->cancel = 0;
+	ud->cache = self;
 
 	/* We might get a race when setting up a store, such that it is still left in offline mode,
 	   after we've gone online.  This catches and fixes it up when the shell opens us */
@@ -1039,16 +1045,16 @@ mail_note_store(CamelStore *store, CamelOperation *op,
 
 	g_queue_push_tail (&si->folderinfo_updates, ud);
 
-	G_UNLOCK (stores);
+	g_mutex_unlock (self->priv->stores_mutex);
 
 	/* there is potential for race here, but it is safe as we check for the store anyway */
 	if (hook) {
-		camel_object_hook_event(store, "folder_opened", store_folder_opened, NULL);
-		camel_object_hook_event(store, "folder_created", store_folder_created, NULL);
-		camel_object_hook_event(store, "folder_deleted", store_folder_deleted, NULL);
-		camel_object_hook_event(store, "folder_renamed", store_folder_renamed, NULL);
-		camel_object_hook_event(store, "folder_subscribed", store_folder_subscribed, NULL);
-		camel_object_hook_event(store, "folder_unsubscribed", store_folder_unsubscribed, NULL);
+		camel_object_hook_event(store, "folder_opened", store_folder_opened, self);
+		camel_object_hook_event(store, "folder_created", store_folder_created, self);
+		camel_object_hook_event(store, "folder_deleted", store_folder_deleted, self);
+		camel_object_hook_event(store, "folder_renamed", store_folder_renamed, self);
+		camel_object_hook_event(store, "folder_subscribed", store_folder_subscribed, self);
+		camel_object_hook_event(store, "folder_unsubscribed", store_folder_unsubscribed, self);
 	}
 }
 
@@ -1074,17 +1080,18 @@ static void storeinfo_find_folder_info(CamelStore *store, struct _store_info *si
 
 /* returns TRUE if the uri is available, folderp is set to a
    reffed folder if the folder has also already been opened */
-gint mail_note_get_folder_from_uri(const gchar *uri, CamelFolder **folderp)
+gboolean
+mail_folder_cache_get_folder_from_uri(MailFolderCache *self, const gchar *uri, CamelFolder **folderp)
 {
 	struct _find_info fi = { uri, NULL, NULL };
 
-	if (stores == NULL)
+	if (self->priv->stores == NULL)
 		return FALSE;
 
 	fi.url = camel_url_new(uri, NULL);
 
-	G_LOCK (stores);
-	g_hash_table_foreach(stores, (GHFunc)storeinfo_find_folder_info, &fi);
+	g_mutex_lock (self->priv->stores_mutex);
+	g_hash_table_foreach(self->priv->stores, (GHFunc)storeinfo_find_folder_info, &fi);
 	if (folderp) {
 		if (fi.fi && fi.fi->folder) {
 			*folderp = fi.fi->folder;
@@ -1093,7 +1100,7 @@ gint mail_note_get_folder_from_uri(const gchar *uri, CamelFolder **folderp)
 			*folderp = NULL;
 		}
 	}
-	G_UNLOCK (stores);
+	g_mutex_unlock (self->priv->stores_mutex);
 
 	camel_url_free(fi.url);
 
@@ -1101,27 +1108,118 @@ gint mail_note_get_folder_from_uri(const gchar *uri, CamelFolder **folderp)
 }
 
 gboolean
-mail_folder_cache_get_folder_info_flags (CamelFolder *folder, gint *flags)
+mail_folder_cache_get_folder_info_flags (MailFolderCache *self, CamelFolder *folder, gint *flags)
 {
 	gchar *uri = mail_tools_folder_to_url (folder);
 	struct _find_info fi = { uri, NULL, NULL };
 
-	if (stores == NULL)
+	if (self->priv->stores == NULL)
 		return FALSE;
 
 	fi.url = camel_url_new (uri, NULL);
 
-	G_LOCK (stores);
-	g_hash_table_foreach(stores, (GHFunc)storeinfo_find_folder_info, &fi);
+	g_mutex_lock (self->priv->stores_mutex);
+	g_hash_table_foreach(self->priv->stores, (GHFunc)storeinfo_find_folder_info, &fi);
 	if (flags) {
 		if (fi.fi) {
 			*flags = fi.fi->flags;
 		}
 	}
-	G_UNLOCK (stores);
+	g_mutex_unlock (self->priv->stores_mutex);
 
 	camel_url_free(fi.url);
 	g_free (uri);
 
 	return fi.fi != NULL;
 }
+
+
+static void
+mail_folder_cache_dispose (GObject *object)
+{
+	G_OBJECT_CLASS (mail_folder_cache_parent_class)->dispose (object);
+}
+
+static void
+mail_folder_cache_finalize (GObject *object)
+{
+	MailFolderCache *cache = (MailFolderCache*) object;
+	g_hash_table_destroy (cache->priv->stores);
+	g_mutex_free (cache->priv->stores_mutex);
+
+	if (cache->priv->ping_id > 0) {
+		g_source_remove (cache->priv->ping_id);
+		cache->priv->ping_id = 0;
+	}
+
+	if (cache->priv->update_id > 0) {
+		g_source_remove (cache->priv->update_id);
+		cache->priv->update_id = 0;
+	}
+
+	G_OBJECT_CLASS (mail_folder_cache_parent_class)->finalize (object);
+}
+
+static void
+mail_folder_cache_class_init (MailFolderCacheClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (MailFolderCachePrivate));
+
+	object_class->dispose = mail_folder_cache_dispose;
+	object_class->finalize = mail_folder_cache_finalize;
+}
+
+static void
+mail_folder_cache_init (MailFolderCache *self)
+{
+	const gchar *buf;
+	guint timeout;
+
+	self->priv = FOLDER_CACHE_PRIVATE (self);
+
+	/* initialize values */
+	self->priv->stores = g_hash_table_new(NULL, NULL);
+	self->priv->stores_mutex = g_mutex_new ();
+
+	g_queue_init (&self->priv->updates);
+	self->priv->update_id = -1;
+	self->priv->count_sent = getenv("EVOLUTION_COUNT_SENT") != NULL;
+	self->priv->count_trash = getenv("EVOLUTION_COUNT_TRASH") != NULL;
+
+	buf = getenv ("EVOLUTION_PING_TIMEOUT");
+	timeout = buf ? strtoul (buf, NULL, 10) : 600;
+	self->priv->ping_id = g_timeout_add_seconds (timeout, ping_cb, self);
+}
+
+/**
+ * mail_folder_cache_new:
+ *
+ * You probably don't want to use this. Use mail_folder_cache_get_default()
+ * instead
+ */
+MailFolderCache *
+mail_folder_cache_new (void)
+{
+	return g_object_new (MAIL_TYPE_FOLDER_CACHE, NULL);
+}
+
+static MailFolderCache *default_cache = NULL;
+G_LOCK_DEFINE_STATIC (default_cache);
+
+/**
+ * mail_folder_cache_get_default:
+ *
+ * Get the default folder cache object
+ */
+MailFolderCache *
+mail_folder_cache_get_default (void)
+{
+	G_LOCK (default_cache);
+	if (!default_cache)
+		default_cache = g_object_new (MAIL_TYPE_FOLDER_CACHE, NULL);
+	G_UNLOCK (default_cache);
+
+	return default_cache;
+}
diff --git a/mail/mail-folder-cache.h b/mail/mail-folder-cache.h
index 41f36ac..762152f 100644
--- a/mail/mail-folder-cache.h
+++ b/mail/mail-folder-cache.h
@@ -14,10 +14,12 @@
  *
  *
  * Authors:
- *		Peter Williams <peterw ximian com>
- *	    Michael Zucchi <notzed ximian com>
+ *   Peter Williams <peterw ximian com>
+ *   Michael Zucchi <notzed ximian com>
+ *   Jonathon Jongsma <jonathon jongsma collabora co uk>
  *
  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2009 Intel Corporation
  *
  */
 
@@ -26,29 +28,64 @@
 #ifndef _MAIL_FOLDER_CACHE_H
 #define _MAIL_FOLDER_CACHE_H
 
+#include <glib-object.h>
 #include <camel/camel-store.h>
 
+G_BEGIN_DECLS
+
+/* Stores information about open folders */
+
+#define MAIL_TYPE_FOLDER_CACHE            mail_folder_cache_get_type()
+#define MAIL_FOLDER_CACHE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAIL_TYPE_FOLDER_CACHE, MailFolderCache))
+#define MAIL_FOLDER_CACHE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), MAIL_TYPE_FOLDER_CACHE, MailFolderCacheClass))
+#define MAIL_IS_FOLDER_CACHE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAIL_TYPE_FOLDER_CACHE))
+#define MAIL_IS_FOLDER_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAIL_TYPE_FOLDER_CACHE))
+#define MAIL_FOLDER_CACHE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), MAIL_TYPE_FOLDER_CACHE, MailFolderCacheClass))
+
+typedef struct _MailFolderCache MailFolderCache;
+typedef struct _MailFolderCacheClass MailFolderCacheClass;
+typedef struct _MailFolderCachePrivate MailFolderCachePrivate;
+
+struct _MailFolderCache
+{
+	GObject parent;
+
+	MailFolderCachePrivate *priv;
+};
+
+struct _MailFolderCacheClass
+{
+	GObjectClass parent_class;
+};
+
+GType mail_folder_cache_get_type (void) G_GNUC_CONST;
+
+MailFolderCache *mail_folder_cache_new (void);
+
+MailFolderCache *mail_folder_cache_get_default (void);
+
+typedef gboolean (*NoteDoneFunc)(CamelStore *store, CamelFolderInfo *info, gpointer data);
 /* Add a store whose folders should appear in the shell
    The folders are scanned from the store, and/or added at
    runtime via the folder_created event.
    The 'done' function returns if we can free folder info. */
-void
-mail_note_store (CamelStore *store, CamelOperation *op,
-		 gboolean (*done) (CamelStore *store, CamelFolderInfo *info, gpointer data),
-		 gpointer data);
+void mail_folder_cache_note_store (MailFolderCache *self,
+				 CamelStore *store, CamelOperation *op,
+				 NoteDoneFunc func, gpointer data);
 
 /* de-note a store */
-void mail_note_store_remove (CamelStore *store);
+void mail_folder_cache_note_store_remove (MailFolderCache *self, CamelStore *store);
 
 /* When a folder has been opened, notify it for watching.
    The folder must have already been created on the store (which has already been noted)
    before the folder can be opened
  */
-void mail_note_folder (CamelFolder *folder);
+void mail_folder_cache_note_folder (MailFolderCache *self, CamelFolder *folder);
 
 /* Returns true if a folder is available (yet), and also sets *folderp (if supplied)
    to a (referenced) copy of the folder if it has already been opened */
-gint mail_note_get_folder_from_uri (const gchar *uri, CamelFolder **folderp);
-gboolean mail_folder_cache_get_folder_info_flags (CamelFolder *folder, gint *flags);
+gboolean mail_folder_cache_get_folder_from_uri (MailFolderCache *self, const gchar *uri, CamelFolder **folderp);
+gboolean mail_folder_cache_get_folder_info_flags (MailFolderCache *self, CamelFolder *folder, gint *flags);
 
+G_END_DECLS
 #endif
diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c
index b5e135c..be806ef 100644
--- a/mail/mail-send-recv.c
+++ b/mail/mail-send-recv.c
@@ -960,7 +960,7 @@ receive_update_got_store (gchar *uri, CamelStore *store, gpointer data)
 	struct _send_info *info = data;
 
 	if (store) {
-		mail_note_store(
+		mail_folder_cache_note_store(mail_folder_cache_get_default (),
 			store, info->cancel,
 			receive_update_got_folderinfo, info);
 	} else {
diff --git a/mail/mail-tools.c b/mail/mail-tools.c
index 1403605..45f502e 100644
--- a/mail/mail-tools.c
+++ b/mail/mail-tools.c
@@ -349,7 +349,7 @@ mail_tool_uri_to_folder (const gchar *uri, guint32 flags, CamelException *ex)
 	}
 
 	if (folder)
-		mail_note_folder (folder);
+		mail_folder_cache_note_folder (mail_folder_cache_get_default (), folder);
 
 	camel_url_free (url);
 	g_free(curi);
diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c
index d95ee2b..f58886b 100644
--- a/mail/mail-vfolder.c
+++ b/mail/mail-vfolder.c
@@ -255,7 +255,9 @@ vfolder_adduri_exec (struct _adduri_msg *m)
 
 	/* we dont try lookup the cache if we are removing it, its no longer there */
 
-	if (!m->remove && !mail_note_get_folder_from_uri(m->uri, &folder)) {
+	if (!m->remove &&
+	    !mail_folder_cache_get_folder_from_uri(mail_folder_cache_get_default (),
+						   m->uri, &folder)) {
 		g_warning("Folder '%s' disappeared while I was adding/remove it to/from my vfolder", m->uri);
 		return;
 	}
@@ -707,7 +709,8 @@ rule_add_sources(GList *l, GList **sources_folderp, GList **sources_urip)
 	while (l) {
 		gchar *curi = em_uri_to_camel(l->data);
 
-		if (mail_note_get_folder_from_uri(curi, &newfolder)) {
+		if (mail_folder_cache_get_folder_from_uri
+		    (mail_folder_cache_get_default (), curi, &newfolder)) {
 			if (newfolder)
 				sources_folder = g_list_append(sources_folder, newfolder);
 			else
diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c
index 57e9bc2..4ce4b43 100644
--- a/plugins/itip-formatter/itip-formatter.c
+++ b/plugins/itip-formatter/itip-formatter.c
@@ -2117,7 +2117,8 @@ in_proper_folder (CamelFolder *folder)
 
 	uri = mail_tools_folder_to_url (folder);
 
-	if (mail_folder_cache_get_folder_info_flags (folder, &flags)) {
+	if (mail_folder_cache_get_folder_info_flags (mail_folder_cache_get_default (),
+						     folder, &flags)) {
 		/* it should be neither trash nor junk folder, */
 		res = ((flags & CAMEL_FOLDER_TYPE_TRASH) !=  CAMEL_FOLDER_TYPE_TRASH &&
 		       (flags & CAMEL_FOLDER_TYPE_JUNK) != CAMEL_FOLDER_TYPE_JUNK &&



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]