[evolution-data-server/gnome-3-4] Bug #680211 - Memory usage increases on each folder select



commit 6cfd76b0b2545306662b669b0535253a30a24304
Author: Milan Crha <mcrha redhat com>
Date:   Fri Jul 20 18:05:05 2012 +0200

    Bug #680211 - Memory usage increases on each folder select

 camel/camel-folder-summary.c             |   51 ++++++++++++++++++++++++++++-
 camel/providers/imap/camel-imap-folder.c |   29 ++++++----------
 camel/providers/imap/camel-imap-store.c  |    2 +
 3 files changed, 62 insertions(+), 20 deletions(-)
---
diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c
index 024b3d4..75213b9 100644
--- a/camel/camel-folder-summary.c
+++ b/camel/camel-folder-summary.c
@@ -167,6 +167,37 @@ enum {
 
 G_DEFINE_TYPE (CamelFolderSummary, camel_folder_summary, CAMEL_TYPE_OBJECT)
 
+static gboolean
+remove_each_item (gpointer uid,
+		  gpointer mi,
+		  gpointer user_data)
+{
+	GSList **to_remove_infos = user_data;
+
+	*to_remove_infos = g_slist_prepend (*to_remove_infos, mi);
+
+	return TRUE;
+}
+
+static void
+remove_all_loaded (CamelFolderSummary *summary)
+{
+	GSList *to_remove_infos = NULL;
+
+	g_return_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary));
+
+	camel_folder_summary_lock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+
+	camel_folder_summary_lock (summary, CAMEL_FOLDER_SUMMARY_REF_LOCK);
+	g_hash_table_foreach_remove (summary->priv->loaded_infos, remove_each_item, &to_remove_infos);
+	camel_folder_summary_unlock (summary, CAMEL_FOLDER_SUMMARY_REF_LOCK);
+
+	g_slist_foreach (to_remove_infos, (GFunc) camel_message_info_free, NULL);
+	g_slist_free (to_remove_infos);
+
+	camel_folder_summary_unlock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+}
+
 static void
 free_o_name (gpointer key,
              gpointer value,
@@ -184,6 +215,8 @@ folder_summary_dispose (GObject *object)
 	priv = CAMEL_FOLDER_SUMMARY_GET_PRIVATE (object);
 
 	if (priv->timeout_handle) {
+		/* this should not happen, because the release timer
+		   holds a reference on object */
 		g_source_remove (priv->timeout_handle);
 		priv->timeout_handle = 0;
 	}
@@ -228,6 +261,11 @@ folder_summary_dispose (GObject *object)
 		priv->index = NULL;
 	}
 
+	if (priv->folder) {
+		g_object_weak_unref (G_OBJECT (priv->folder), (GWeakNotify) g_nullify_pointer, &priv->folder);
+		priv->folder = NULL;
+	}
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (camel_folder_summary_parent_class)->dispose (object);
 }
@@ -239,6 +277,7 @@ folder_summary_finalize (GObject *object)
 	CamelFolderSummaryPrivate *priv = summary->priv;
 
 	g_hash_table_destroy (priv->uids);
+	remove_all_loaded (summary);
 	g_hash_table_destroy (priv->loaded_infos);
 
 	g_hash_table_foreach (priv->filter_charset, free_o_name, NULL);
@@ -265,6 +304,8 @@ folder_summary_set_folder (CamelFolderSummary *summary,
 	/* folder can be NULL in certain cases, see maildir-store */
 
 	summary->priv->folder = folder;
+	if (folder)
+		g_object_weak_ref (G_OBJECT (folder), (GWeakNotify) g_nullify_pointer, &summary->priv->folder);
 }
 
 static void
@@ -1961,6 +2002,8 @@ cfs_try_release_memory (CamelFolderSummary *summary)
 	if (!summary->priv->folder || !g_hash_table_size (summary->priv->loaded_infos)) {
 		summary->priv->cache_load_time = 0;
 		summary->priv->timeout_handle = 0;
+		g_object_unref (summary);
+
 		return FALSE;
 	}
 
@@ -1993,8 +2036,10 @@ cfs_schedule_info_release_timer (CamelFolderSummary *summary)
 		}
 
 		/* FIXME[disk-summary] LRU please and not timeouts */
-		if (can_do)
-			summary->priv->timeout_handle = g_timeout_add_seconds (SUMMARY_CACHE_DROP, (GSourceFunc) cfs_try_release_memory, summary);
+		if (can_do) {
+			summary->priv->timeout_handle = g_timeout_add_seconds (SUMMARY_CACHE_DROP,
+				(GSourceFunc) cfs_try_release_memory, g_object_ref (summary));
+		}
 	}
 
 	/* update also cache load time to the actual, to not release something just loaded */
@@ -3151,6 +3196,7 @@ camel_folder_summary_clear (CamelFolderSummary *summary,
 	}
 
 	g_hash_table_remove_all (summary->priv->uids);
+	remove_all_loaded (summary);
 	g_hash_table_remove_all (summary->priv->loaded_infos);
 
 	summary->priv->saved_count = 0;
@@ -4426,6 +4472,7 @@ camel_message_info_free (gpointer o)
 		if (mi->summary->priv->build_content
 		    && ((CamelMessageInfoBase *) mi)->content) {
 			camel_folder_summary_content_info_free (mi->summary, ((CamelMessageInfoBase *) mi)->content);
+			((CamelMessageInfoBase *) mi)->content = NULL;
 		}
 
 		CAMEL_FOLDER_SUMMARY_GET_CLASS (mi->summary)->message_info_free (mi->summary, mi);
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index e771152..1a172c9 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -1442,6 +1442,7 @@ get_matching (CamelFolder *folder,
 
 			if (count1 != count2) {
 				g_list_free (list2);
+				camel_message_info_free ((CamelMessageInfo *) info);
 				close_range ();
 				continue;
 			}
@@ -1453,6 +1454,7 @@ get_matching (CamelFolder *folder,
 
 			if (cmp) {
 				g_list_free (list2);
+				camel_message_info_free ((CamelMessageInfo *) info);
 				close_range ();
 				continue;
 			}
@@ -1657,19 +1659,13 @@ imap_synchronize_sync (CamelFolder *folder,
 	/* deleted_uids is NULL when not using real trash */
 	folder_path = camel_imap_settings_dup_real_trash_path (
 		CAMEL_IMAP_SETTINGS (settings));
-	if (folder_path != NULL) {
+	if (folder_path != NULL && *folder_path) {
 		if ((folder->folder_flags & CAMEL_FOLDER_IS_TRASH) != 0) {
 			/* syncing the trash, expunge deleted when found any */
 			real_trash = g_object_ref (folder);
 		} else {
 			real_trash = camel_store_get_trash_folder_sync (
 				parent_store, cancellable, NULL);
-
-			if (folder_path == NULL && real_trash) {
-				/* failed to open real trash */
-				g_object_unref (real_trash);
-				real_trash = NULL;
-			}
 		}
 	}
 	g_free (folder_path);
@@ -1680,7 +1676,7 @@ imap_synchronize_sync (CamelFolder *folder,
 	/* junked_uids is NULL when not using real junk */
 	folder_path = camel_imap_settings_dup_real_junk_path (
 		CAMEL_IMAP_SETTINGS (settings));
-	if (folder_path != NULL) {
+	if (folder_path != NULL && *folder_path) {
 		if ((folder->folder_flags & CAMEL_FOLDER_IS_JUNK) != 0) {
 			/* syncing the junk, but cannot move
 			 * messages to itself, thus do nothing */
@@ -1688,12 +1684,6 @@ imap_synchronize_sync (CamelFolder *folder,
 		} else {
 			real_junk = camel_store_get_junk_folder_sync (
 				parent_store, cancellable, NULL);
-
-			if (folder_path == NULL && real_junk) {
-				/* failed to open real junk */
-				g_object_unref (real_junk);
-				real_junk = NULL;
-			}
 		}
 	}
 	g_free (folder_path);
@@ -1736,6 +1726,8 @@ imap_synchronize_sync (CamelFolder *folder,
 		if (!camel_imap_store_connected (store, NULL)) {
 			g_free (set);
 			camel_message_info_free (info);
+			g_ptr_array_foreach (matches, (GFunc) camel_message_info_free, NULL);
+			g_ptr_array_free (matches, TRUE);
 			break;
 		}
 
@@ -1805,10 +1797,7 @@ imap_synchronize_sync (CamelFolder *folder,
 			camel_folder_summary_touch (folder->summary);
 		}
 
-		for (j = 0; j < matches->len; j++) {
-			info = matches->pdata[j];
-			camel_message_info_free (&info->info);
-		}
+		g_ptr_array_foreach (matches, (GFunc) camel_message_info_free, NULL);
 		g_ptr_array_free (matches, TRUE);
 
 		/* We unlock here so that other threads can have a chance to grab the connect_lock */
@@ -1829,6 +1818,10 @@ imap_synchronize_sync (CamelFolder *folder,
 				g_object_unref (real_trash);
 			if (real_junk)
 				g_object_unref (real_junk);
+
+			g_ptr_array_foreach (summary, (GFunc) camel_pstring_free, NULL);
+			g_ptr_array_free (summary, TRUE);
+
 			return FALSE;
 		}
 
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 25c789a..f9badb1 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -2209,6 +2209,8 @@ imap_store_get_folder_sync (CamelStore *store,
 	new_folder = camel_imap_folder_new (store, folder_name, folder_dir, error);
 	g_free (folder_dir);
 	if (new_folder) {
+		if (imap_store->current_folder)
+			g_object_unref (imap_store->current_folder);
 		imap_store->current_folder = g_object_ref (new_folder);
 		if (!camel_imap_folder_selected (
 			new_folder, response, cancellable, error)) {



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