[evolution] Move folder URI caching to MailFolderCache.



commit e3b8f3fbb3f1cbd981e8a6382365cd699a95c149
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed Dec 7 23:47:40 2011 -0500

    Move folder URI caching to MailFolderCache.

 mail/mail-folder-cache.c         |  222 ++++++++++++++++++++++++++++++++++++++
 mail/mail-folder-cache.h         |    7 +-
 mail/mail-vfolder.c              |  112 ++++++--------------
 mail/mail-vfolder.h              |    3 -
 modules/mail/e-mail-shell-view.c |   28 ++----
 5 files changed, 270 insertions(+), 102 deletions(-)
---
diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c
index 0baaa0e..cab15c5 100644
--- a/mail/mail-folder-cache.c
+++ b/mail/mail-folder-cache.c
@@ -76,6 +76,9 @@ struct _MailFolderCachePrivate {
 	/* hack for people who LIKE to have unsent count */
 	gint count_sent;
 	gint count_trash;
+
+	GQueue local_folder_uris;
+	GQueue remote_folder_uris;
 };
 
 enum {
@@ -887,6 +890,22 @@ store_go_online_cb (CamelStore *store,
 	g_mutex_unlock (ud->cache->priv->stores_mutex);
 }
 
+static GList *
+find_folder_uri (GQueue *queue,
+                 CamelSession *session,
+                 const gchar *folder_uri)
+{
+	GList *head, *link;
+
+	head = g_queue_peek_head_link (queue);
+
+	for (link = head; link != NULL; link = g_list_next (link))
+		if (e_mail_folder_uri_equal (session, link->data, folder_uri))
+			break;
+
+	return link;
+}
+
 struct _find_info {
 	const gchar *folder_uri;
 	struct _folder_info *fi;
@@ -931,11 +950,167 @@ mail_folder_cache_finalize (GObject *object)
 		cache->priv->update_id = 0;
 	}
 
+	while (!g_queue_is_empty (&cache->priv->local_folder_uris))
+		g_free (g_queue_pop_head (&cache->priv->local_folder_uris));
+
+	while (!g_queue_is_empty (&cache->priv->remote_folder_uris))
+		g_free (g_queue_pop_head (&cache->priv->remote_folder_uris));
+
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (mail_folder_cache_parent_class)->finalize (object);
 }
 
 static void
+mail_folder_cache_folder_available (MailFolderCache *cache,
+                                    CamelStore *store,
+                                    const gchar *folder_name)
+{
+	CamelService *service;
+	CamelSession *session;
+	CamelProvider *provider;
+	GQueue *queue;
+	gchar *folder_uri;
+
+	/* Disregard virtual stores. */
+	if (CAMEL_IS_VEE_STORE (store))
+		return;
+
+	/* Disregard virtual Junk folders. */
+	if (store->flags & CAMEL_STORE_VJUNK)
+		if (g_strcmp0 (folder_name, CAMEL_VJUNK_NAME) == 0)
+			return;
+
+	/* Disregard virtual Trash folders. */
+	if (store->flags & CAMEL_STORE_VTRASH)
+		if (g_strcmp0 (folder_name, CAMEL_VTRASH_NAME) == 0)
+			return;
+
+	service = CAMEL_SERVICE (store);
+	session = camel_service_get_session (service);
+	provider = camel_service_get_provider (service);
+
+	/* Reuse the stores mutex just because it's handy. */
+	g_mutex_lock (cache->priv->stores_mutex);
+
+	folder_uri = e_mail_folder_uri_build (store, folder_name);
+
+	if (provider->flags & CAMEL_PROVIDER_IS_REMOTE)
+		queue = &cache->priv->remote_folder_uris;
+	else
+		queue = &cache->priv->local_folder_uris;
+
+	if (find_folder_uri (queue, session, folder_uri) == NULL)
+		g_queue_push_tail (queue, folder_uri);
+	else
+		g_free (folder_uri);
+
+	g_mutex_unlock (cache->priv->stores_mutex);
+}
+
+static void
+mail_folder_cache_folder_unavailable (MailFolderCache *cache,
+                                      CamelStore *store,
+                                      const gchar *folder_name)
+{
+	CamelService *service;
+	CamelSession *session;
+	CamelProvider *provider;
+	GQueue *queue;
+	GList *link;
+	gchar *folder_uri;
+
+	/* Disregard virtual stores. */
+	if (CAMEL_IS_VEE_STORE (store))
+		return;
+
+	/* Disregard virtual Junk folders. */
+	if (store->flags & CAMEL_STORE_VJUNK)
+		if (g_strcmp0 (folder_name, CAMEL_VJUNK_NAME) == 0)
+			return;
+
+	/* Disregard virtual Trash folders. */
+	if (store->flags & CAMEL_STORE_VTRASH)
+		if (g_strcmp0 (folder_name, CAMEL_VTRASH_NAME) == 0)
+			return;
+
+	service = CAMEL_SERVICE (store);
+	session = camel_service_get_session (service);
+	provider = camel_service_get_provider (service);
+
+	/* Reuse the stores mutex just because it's handy. */
+	g_mutex_lock (cache->priv->stores_mutex);
+
+	folder_uri = e_mail_folder_uri_build (store, folder_name);
+
+	if (provider->flags & CAMEL_PROVIDER_IS_REMOTE)
+		queue = &cache->priv->remote_folder_uris;
+	else
+		queue = &cache->priv->local_folder_uris;
+
+	link = find_folder_uri (queue, session, folder_uri);
+	if (link != NULL) {
+		g_free (link->data);
+		g_queue_delete_link (queue, link);
+	}
+
+	g_free (folder_uri);
+
+	g_mutex_unlock (cache->priv->stores_mutex);
+}
+
+static void
+mail_folder_cache_folder_deleted (MailFolderCache *cache,
+                                  CamelStore *store,
+                                  const gchar *folder_name)
+{
+	CamelService *service;
+	CamelSession *session;
+	GQueue *queue;
+	GList *link;
+	gchar *folder_uri;
+
+	/* Disregard virtual stores. */
+	if (CAMEL_IS_VEE_STORE (store))
+		return;
+
+	/* Disregard virtual Junk folders. */
+	if (store->flags & CAMEL_STORE_VJUNK)
+		if (g_strcmp0 (folder_name, CAMEL_VJUNK_NAME) == 0)
+			return;
+
+	/* Disregard virtual Trash folders. */
+	if (store->flags & CAMEL_STORE_VTRASH)
+		if (g_strcmp0 (folder_name, CAMEL_VTRASH_NAME) == 0)
+			return;
+
+	service = CAMEL_SERVICE (store);
+	session = camel_service_get_session (service);
+
+	/* Reuse the stores mutex just because it's handy. */
+	g_mutex_lock (cache->priv->stores_mutex);
+
+	folder_uri = e_mail_folder_uri_build (store, folder_name);
+
+	queue = &cache->priv->local_folder_uris;
+	link = find_folder_uri (queue, session, folder_uri);
+	if (link != NULL) {
+		g_free (link->data);
+		g_queue_delete_link (queue, link);
+	}
+
+	queue = &cache->priv->remote_folder_uris;
+	link = find_folder_uri (queue, session, folder_uri);
+	if (link != NULL) {
+		g_free (link->data);
+		g_queue_delete_link (queue, link);
+	}
+
+	g_free (folder_uri);
+
+	g_mutex_unlock (cache->priv->stores_mutex);
+}
+
+static void
 mail_folder_cache_class_init (MailFolderCacheClass *class)
 {
 	GObjectClass *object_class;
@@ -945,6 +1120,10 @@ mail_folder_cache_class_init (MailFolderCacheClass *class)
 	object_class = G_OBJECT_CLASS (class);
 	object_class->finalize = mail_folder_cache_finalize;
 
+	class->folder_available = mail_folder_cache_folder_available;
+	class->folder_unavailable = mail_folder_cache_folder_unavailable;
+	class->folder_deleted = mail_folder_cache_folder_deleted;
+
 	/**
 	 * MailFolderCache::folder-available
 	 * @store: the #CamelStore containing the folder
@@ -1089,6 +1268,9 @@ mail_folder_cache_init (MailFolderCache *cache)
 	timeout = buf ? strtoul (buf, NULL, 10) : 600;
 	cache->priv->ping_id = g_timeout_add_seconds (
 		timeout, (GSourceFunc) ping_cb, cache);
+
+	g_queue_init (&cache->priv->local_folder_uris);
+	g_queue_init (&cache->priv->remote_folder_uris);
 }
 
 MailFolderCache *
@@ -1397,3 +1579,43 @@ mail_folder_cache_get_folder_has_children (MailFolderCache *cache,
 
 	return fi.fi != NULL && fi.fi->has_children;
 }
+
+void
+mail_folder_cache_get_local_folder_uris (MailFolderCache *self,
+                                         GQueue *out_queue)
+{
+	GList *head, *link;
+
+	g_return_if_fail (MAIL_IS_FOLDER_CACHE (self));
+	g_return_if_fail (out_queue != NULL);
+
+	/* Reuse the stores mutex just because it's handy. */
+	g_mutex_lock (self->priv->stores_mutex);
+
+	head = g_queue_peek_head_link (&self->priv->local_folder_uris);
+
+	for (link = head; link != NULL; link = g_list_next (link))
+		g_queue_push_tail (out_queue, g_strdup (link->data));
+
+	g_mutex_unlock (self->priv->stores_mutex);
+}
+
+void
+mail_folder_cache_get_remote_folder_uris (MailFolderCache *self,
+                                          GQueue *out_queue)
+{
+	GList *head, *link;
+
+	g_return_if_fail (MAIL_IS_FOLDER_CACHE (self));
+	g_return_if_fail (out_queue != NULL);
+
+	/* Reuse the stores mutex just because it's handy. */
+	g_mutex_lock (self->priv->stores_mutex);
+
+	head = g_queue_peek_head_link (&self->priv->remote_folder_uris);
+
+	for (link = head; link != NULL; link = g_list_next (link))
+		g_queue_push_tail (out_queue, g_strdup (link->data));
+
+	g_mutex_unlock (self->priv->stores_mutex);
+}
diff --git a/mail/mail-folder-cache.h b/mail/mail-folder-cache.h
index 8253461..146ead5 100644
--- a/mail/mail-folder-cache.h
+++ b/mail/mail-folder-cache.h
@@ -126,11 +126,16 @@ gboolean	mail_folder_cache_get_folder_info_flags
 						(MailFolderCache *self,
 						 CamelFolder *folder,
 						 CamelFolderInfoFlags *flags);
-
 gboolean	mail_folder_cache_get_folder_has_children
 						(MailFolderCache *self,
 						 CamelFolder *folder,
 						 gboolean *found);
+void		mail_folder_cache_get_local_folder_uris
+						(MailFolderCache *self,
+						 GQueue *out_queue);
+void		mail_folder_cache_get_remote_folder_uris
+						(MailFolderCache *self,
+						 GQueue *out_queue);
 
 G_END_DECLS
 
diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c
index b93122a..b37d042 100644
--- a/mail/mail-vfolder.c
+++ b/mail/mail-vfolder.c
@@ -61,12 +61,6 @@ static EMVFolderContext *context;	/* context remains open all time */
 /* lock for accessing shared resources (below) */
 G_LOCK_DEFINE_STATIC (vfolder);
 
-/* list of source folder uri's - remote ones */
-static GQueue source_folders_remote = G_QUEUE_INIT;
-
-/* list of source folder uri's - local ones */
-static GQueue source_folders_local = G_QUEUE_INIT;
-
 static GHashTable *vfolder_hash;
 /* This is a slightly hacky solution to shutting down, we poll this variable in various
  * loops, and just quit processing if it is set. */
@@ -329,24 +323,6 @@ vfolder_adduri (EMailBackend *backend,
 
 /* ********************************************************************** */
 
-static GList *
-mv_find_folder (GQueue *queue,
-                EMailSession *session,
-                const gchar *uri)
-{
-	CamelSession *camel_session = CAMEL_SESSION (session);
-	GList *head, *link;
-
-	head = g_queue_peek_head_link (queue);
-
-	for (link = head; link != NULL; link = g_list_next (link)) {
-		if (e_mail_folder_uri_equal (camel_session, link->data, uri))
-			break;
-	}
-
-	return link;
-}
-
 /* so special we never use it */
 static gint
 folder_is_spethal (CamelStore *store,
@@ -395,17 +371,14 @@ mail_vfolder_add_folder (EMailBackend *backend,
 	const gchar *source;
 	CamelVeeFolder *vf;
 	CamelProvider *provider;
-	GList *folders = NULL, *link;
-	GQueue *queue;
+	GList *folders = NULL;
 	gint remote;
-	gint is_ignore = FALSE;
 	gchar *uri;
 
 	session = e_mail_backend_get_session (backend);
 
 	provider = camel_service_get_provider (CAMEL_SERVICE (store));
 	remote = (provider->flags & CAMEL_PROVIDER_IS_REMOTE) != 0;
-	queue = remote ? &source_folders_remote : &source_folders_local;
 
 	if (folder_is_spethal (store, folder_name))
 		return;
@@ -416,21 +389,6 @@ mail_vfolder_add_folder (EMailBackend *backend,
 
 	G_LOCK (vfolder);
 
-	/* maintain the source folders lists for changed rules later on */
-	if (CAMEL_IS_VEE_STORE (store)) {
-		is_ignore = TRUE;
-	} else if (remove) {
-		link = mv_find_folder (queue, session, uri);
-		if (link != NULL) {
-			g_free (link->data);
-			g_queue_delete_link (queue, link);
-		}
-	} else if (!is_ignore) {
-		/* we ignore drafts/sent/outbox here */
-		if (mv_find_folder (queue, session, uri) == NULL)
-			g_queue_push_tail (queue, g_strdup (uri));
-	}
-
 	if (context == NULL)
 		goto done;
 
@@ -445,7 +403,7 @@ mail_vfolder_add_folder (EMailBackend *backend,
 		/* Don't auto-add any sent/drafts folders etc,
 		 * they must be explictly listed as a source. */
 		if (rule->source
-		    && !is_ignore
+		    && !CAMEL_IS_VEE_STORE (store)
 		    && ((((EMVFolderRule *) rule)->with ==
 				EM_VFOLDER_RULE_WITH_LOCAL && !remote)
 			|| (((EMVFolderRule *) rule)->with ==
@@ -510,10 +468,8 @@ mail_vfolder_delete_folder (EMailBackend *backend,
 	const gchar *source;
 	CamelVeeFolder *vf;
 	GString *changed;
-	GQueue *queue;
 	guint changed_count;
 	gchar *uri;
-	GList *link;
 
 	g_return_if_fail (E_IS_MAIL_BACKEND (backend));
 	g_return_if_fail (CAMEL_IS_STORE (store));
@@ -590,20 +546,6 @@ mail_vfolder_delete_folder (EMailBackend *backend,
 	}
 
 done:
-	queue = &source_folders_remote;
-	link = mv_find_folder (queue, session, uri);
-	if (link != NULL) {
-		g_free (link->data);
-		g_queue_delete_link (queue, link);
-	}
-
-	queue = &source_folders_local;
-	link = mv_find_folder (queue, session, uri);
-	if (link != NULL) {
-		g_free (link->data);
-		g_queue_delete_link (queue, link);
-	}
-
 	G_UNLOCK (vfolder);
 
 	if (changed_count > 0) {
@@ -724,18 +666,6 @@ mail_vfolder_rename_folder (CamelStore *store,
 	g_free (new_uri);
 }
 
-GList *
-mail_vfolder_get_sources_local (void)
-{
-	return g_queue_peek_head_link (&source_folders_local);
-}
-
-GList *
-mail_vfolder_get_sources_remote (void)
-{
-	return g_queue_peek_head_link (&source_folders_remote);
-}
-
 /* ********************************************************************** */
 
 static void context_rule_added (ERuleContext *ctx, EFilterRule *rule);
@@ -780,7 +710,8 @@ rule_changed (EFilterRule *rule,
 	EMailBackend *backend;
 	EMailSession *session;
 	CamelService *service;
-	GList *sources_uri = NULL, *sources_folder = NULL;
+	GList *sources_uri = NULL;
+	GList *sources_folder = NULL;
 	GString *query;
 	const gchar *full_name;
 
@@ -827,20 +758,43 @@ rule_changed (EFilterRule *rule,
 		&sources_folder, &sources_uri);
 
 	G_LOCK (vfolder);
+
 	if (((EMVFolderRule *) rule)->with ==
 			EM_VFOLDER_RULE_WITH_LOCAL ||
 			((EMVFolderRule *) rule)->with ==
-			EM_VFOLDER_RULE_WITH_LOCAL_REMOTE_ACTIVE)
+			EM_VFOLDER_RULE_WITH_LOCAL_REMOTE_ACTIVE) {
+
+		MailFolderCache *cache;
+		GQueue queue = G_QUEUE_INIT;
+
+		cache = e_mail_session_get_folder_cache (session);
+		mail_folder_cache_get_local_folder_uris (cache, &queue);
+
 		rule_add_sources (
-			session, &source_folders_local,
-			&sources_folder, &sources_uri);
+			session, &queue, &sources_folder, &sources_uri);
+
+		while (!g_queue_is_empty (&queue))
+			g_free (g_queue_pop_head (&queue));
+	}
+
 	if (((EMVFolderRule *) rule)->with ==
 			EM_VFOLDER_RULE_WITH_REMOTE_ACTIVE ||
 			((EMVFolderRule *) rule)->with ==
-			EM_VFOLDER_RULE_WITH_LOCAL_REMOTE_ACTIVE)
+			EM_VFOLDER_RULE_WITH_LOCAL_REMOTE_ACTIVE) {
+
+		MailFolderCache *cache;
+		GQueue queue = G_QUEUE_INIT;
+
+		cache = e_mail_session_get_folder_cache (session);
+		mail_folder_cache_get_remote_folder_uris (cache, &queue);
+
 		rule_add_sources (
-			session, &source_folders_remote,
-			&sources_folder, &sources_uri);
+			session, &queue, &sources_folder, &sources_uri);
+
+		while (!g_queue_is_empty (&queue))
+			g_free (g_queue_pop_head (&queue));
+	}
+
 	G_UNLOCK (vfolder);
 
 	query = g_string_new("");
diff --git a/mail/mail-vfolder.h b/mail/mail-vfolder.h
index 7ef5956..c180106 100644
--- a/mail/mail-vfolder.h
+++ b/mail/mail-vfolder.h
@@ -46,9 +46,6 @@ void		vfolder_gui_add_from_address	(EMailSession *session,
 						 gint flags,
 						 CamelFolder *folder);
 
-GList *		mail_vfolder_get_sources_local	(void);
-GList *		mail_vfolder_get_sources_remote	(void);
-
 /* close up, clean up */
 void		mail_vfolder_shutdown		(void);
 
diff --git a/modules/mail/e-mail-shell-view.c b/modules/mail/e-mail-shell-view.c
index 74a69a9..02a31c2 100644
--- a/modules/mail/e-mail-shell-view.c
+++ b/modules/mail/e-mail-shell-view.c
@@ -224,6 +224,7 @@ mail_shell_view_execute_search (EShellView *shell_view)
 	EActionComboBox *combo_box;
 	EMailBackend *backend;
 	EMailSession *session;
+	MailFolderCache *cache;
 	EMFolderTree *folder_tree;
 	GtkWidget *message_list;
 	EFilterRule *rule;
@@ -240,6 +241,7 @@ mail_shell_view_execute_search (EShellView *shell_view)
 	GString *string;
 	GList *list, *iter;
 	GSList *search_strings = NULL;
+	GQueue queue = G_QUEUE_INIT;
 	const gchar *text;
 	gboolean valid;
 	gchar *query;
@@ -564,26 +566,14 @@ all_accounts:
 		CAMEL_STORE_VEE_FOLDER_AUTO);
 	priv->search_account_all = search_folder;
 
-	/* Add local folders. */
-	iter = mail_vfolder_get_sources_local ();
-	while (iter != NULL) {
-		const gchar *folder_uri = iter->data;
-		/* FIXME Not passing a GCancellable or GError here. */
-		folder = e_mail_session_uri_to_folder_sync (
-			E_MAIL_SESSION (session), folder_uri, 0, NULL, NULL);
+	cache = e_mail_session_get_folder_cache (session);
+	mail_folder_cache_get_local_folder_uris (cache, &queue);
+	mail_folder_cache_get_remote_folder_uris (cache, &queue);
 
-		if (folder != NULL)
-			list = g_list_append (list, folder);
-		else
-			g_warning ("Could not open vfolder source: %s", folder_uri);
-
-		iter = g_list_next (iter);
-	}
+	/* Add all available local and remote folders. */
+	while (!g_queue_is_empty (&queue)) {
+		gchar *folder_uri = g_queue_pop_head (&queue);
 
-	/* Add remote folders. */
-	iter = mail_vfolder_get_sources_remote ();
-	while (iter != NULL) {
-		const gchar *folder_uri = iter->data;
 		/* FIXME Not passing a GCancellable or GError here. */
 		folder = e_mail_session_uri_to_folder_sync (
 			E_MAIL_SESSION (session), folder_uri, 0, NULL, NULL);
@@ -593,7 +583,7 @@ all_accounts:
 		else
 			g_warning ("Could not open vfolder source: %s", folder_uri);
 
-		iter = g_list_next (iter);
+		g_free (folder_uri);
 	}
 
 	camel_vee_folder_set_expression (search_folder, query);



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