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



commit a86de4763cc4ed4134067bca03df1e0e45049494
Author: Milan Crha <mcrha redhat com>
Date:   Fri Jul 20 18:04:31 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 cc87103..6c11f88 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
@@ -2049,6 +2090,8 @@ cfs_try_release_memory (CamelFolderSummary *summary)
 	    is_in_memory_summary (summary)) {
 		summary->priv->cache_load_time = 0;
 		summary->priv->timeout_handle = 0;
+		g_object_unref (summary);
+
 		return FALSE;
 	}
 
@@ -2084,8 +2127,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 */
@@ -3263,6 +3308,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;
@@ -4546,6 +4592,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 da8fe8f..3872f52 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -1438,6 +1438,7 @@ get_matching (CamelFolder *folder,
 
 			if (count1 != count2) {
 				g_list_free (list2);
+				camel_message_info_free ((CamelMessageInfo *) info);
 				close_range ();
 				continue;
 			}
@@ -1449,6 +1450,7 @@ get_matching (CamelFolder *folder,
 
 			if (cmp) {
 				g_list_free (list2);
+				camel_message_info_free ((CamelMessageInfo *) info);
 				close_range ();
 				continue;
 			}
@@ -1651,19 +1653,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);
@@ -1674,7 +1670,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 */
@@ -1682,12 +1678,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);
@@ -1730,6 +1720,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;
 		}
 
@@ -1799,10 +1791,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);
 
 		/* check for an exception */
@@ -1820,6 +1809,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 3cc8e97..db6422e 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -2169,6 +2169,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]