[evolution-data-server] Bug 785212 - Quit with a large vFolder causes load of each message info



commit 666be62ac02049116dc9169b2d2d9fdca221ee42
Author: Milan Crha <mcrha redhat com>
Date:   Mon Jul 24 19:26:18 2017 +0200

    Bug 785212 - Quit with a large vFolder causes load of each message info

 src/camel/camel-folder-summary.c   |   26 ++++++++++++++++++++++
 src/camel/camel-folder-summary.h   |    5 +++-
 src/camel/camel-vee-folder.c       |    5 ++++
 src/camel/camel-vee-message-info.c |   41 +++++++++++++++++++++++++++++++++++-
 src/camel/camel-vee-store.c        |   14 ++++++++---
 src/camel/camel-vee-summary.c      |   31 +++++++++++++++++++++++++++
 6 files changed, 116 insertions(+), 6 deletions(-)
---
diff --git a/src/camel/camel-folder-summary.c b/src/camel/camel-folder-summary.c
index 4286bda..3194538 100644
--- a/src/camel/camel-folder-summary.c
+++ b/src/camel/camel-folder-summary.c
@@ -143,6 +143,13 @@ enum {
        PROP_VISIBLE_COUNT
 };
 
+enum {
+       PREPARE_FETCH_ALL,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
 G_DEFINE_TYPE (CamelFolderSummary, camel_folder_summary, G_TYPE_OBJECT)
 
 /* Private function */
@@ -737,6 +744,23 @@ camel_folder_summary_class_init (CamelFolderSummaryClass *class)
                        "How many visible (not deleted and not junk) infos is saved in a summary",
                        0,  G_MAXUINT32,
                        0, G_PARAM_READABLE));
+
+       /**
+        * CamelFolderSummary::prepare-fetch-all
+        * @summary: the #CamelFolderSummary which emitted the signal
+        *
+        * Emitted on call to camel_folder_summary_prepare_fetch_all().
+        *
+        * Since: 3.26
+        **/
+       signals[PREPARE_FETCH_ALL] = g_signal_new (
+               "changed",
+               G_OBJECT_CLASS_TYPE (class),
+               G_SIGNAL_RUN_FIRST,
+               G_STRUCT_OFFSET (CamelFolderSummaryClass, prepare_fetch_all),
+               NULL, NULL, NULL,
+               G_TYPE_NONE, 0,
+               G_TYPE_NONE);
 }
 
 static void
@@ -1743,6 +1767,8 @@ camel_folder_summary_prepare_fetch_all (CamelFolderSummary *summary,
        loaded = cfs_cache_size (summary);
        known = camel_folder_summary_count (summary);
 
+       g_signal_emit (summary, signals[PREPARE_FETCH_ALL], 0);
+
        if (known - loaded > 50) {
                camel_folder_summary_lock (summary);
                cfs_reload_from_db (summary, error);
diff --git a/src/camel/camel-folder-summary.h b/src/camel/camel-folder-summary.h
index 8fb53bb..bb0cea7 100644
--- a/src/camel/camel-folder-summary.h
+++ b/src/camel/camel-folder-summary.h
@@ -120,8 +120,11 @@ struct _CamelFolderSummaryClass {
        gchar *         (*next_uid_string)
                                        (CamelFolderSummary *summary);
 
+       void            (* prepare_fetch_all)
+                                       (CamelFolderSummary *summary);
+
        /* Padding for future expansion */
-       gpointer reserved[20];
+       gpointer reserved[19];
 };
 
 GType          camel_folder_summary_get_type   (void);
diff --git a/src/camel/camel-vee-folder.c b/src/camel/camel-vee-folder.c
index 2555b14..47c8ca2 100644
--- a/src/camel/camel-vee-folder.c
+++ b/src/camel/camel-vee-folder.c
@@ -39,6 +39,8 @@
 #define d(x)
 #define dd(x) (camel_debug ("vfolder")?(x):0)
 
+extern gint camel_application_is_exiting;
+
 typedef struct _FolderChangedData FolderChangedData;
 
 #define CAMEL_VEE_FOLDER_GET_PRIVATE(obj) \
@@ -1092,6 +1094,9 @@ vee_folder_remove_folder (CamelVeeFolder *vfolder,
        CamelFolder *v_folder;
        GHashTable *uids;
 
+       if (camel_application_is_exiting)
+               return;
+
        v_folder = CAMEL_FOLDER (vfolder);
        changes = camel_folder_change_info_new ();
 
diff --git a/src/camel/camel-vee-message-info.c b/src/camel/camel-vee-message-info.c
index 4ec2aea..d932cfa 100644
--- a/src/camel/camel-vee-message-info.c
+++ b/src/camel/camel-vee-message-info.c
@@ -136,10 +136,49 @@ vee_message_info_notify_mi_changed (CamelFolder *folder,
                return result;                                                                  \
        } G_STMT_END
 
+static gboolean
+vee_message_info_read_flags_from_orig_summary (const CamelMessageInfo *mi,
+                                              guint32 *out_flags)
+{
+       CamelVeeMessageInfo *vmi;
+       const gchar *uid;
+
+       g_return_val_if_fail (CAMEL_IS_VEE_MESSAGE_INFO (mi), FALSE);
+       g_return_val_if_fail (out_flags != NULL, FALSE);
+
+       vmi = CAMEL_VEE_MESSAGE_INFO (mi);
+       g_return_val_if_fail (vmi->priv->orig_summary != NULL, FALSE);
+
+       uid = camel_message_info_pooldup_uid (mi);
+       g_return_val_if_fail (uid != NULL, FALSE);
+
+       if (!uid[0] || !uid[1] || !uid[2] || !uid[3] || !uid[4] ||
+           !uid[5] || !uid[6] || !uid[7] || !uid[8]) {
+               camel_pstring_free (uid);
+               g_warn_if_reached ();
+               return FALSE;
+       }
+
+       /* Flags can be read from summary, without a need to load the message info and
+          it is also required when adding to the summary, thus this should help when
+          populating summary of any vFolder. */
+       *out_flags = camel_folder_summary_get_info_flags (vmi->priv->orig_summary, uid + 8);
+
+       camel_pstring_free (uid);
+
+       return *out_flags != (~0);
+}
+
 static guint32
 vee_message_info_get_flags (const CamelMessageInfo *mi)
 {
-       vee_call_from_parent_mi (0, guint32, camel_message_info_get_flags, (orig_mi), FALSE);
+       guint32 flags = 0;
+
+       if (vee_message_info_read_flags_from_orig_summary (mi, &flags)) {
+               return flags;
+       } else {
+               vee_call_from_parent_mi (0, guint32, camel_message_info_get_flags, (orig_mi), FALSE);
+       }
 }
 
 static gboolean
diff --git a/src/camel/camel-vee-store.c b/src/camel/camel-vee-store.c
index 2b72e86..3b47ce8 100644
--- a/src/camel/camel-vee-store.c
+++ b/src/camel/camel-vee-store.c
@@ -47,6 +47,8 @@
 #define CHANGE_DELETE (1)
 #define CHANGE_NOSELECT (2)
 
+extern gint camel_application_is_exiting;
+
 /* The custom property ID is a CamelArg artifact.
  * It still identifies the property in state files. */
 enum {
@@ -711,7 +713,8 @@ camel_vee_store_note_subfolder_used (CamelVeeStore *vstore,
 
        /* only real folders can be part of the unmatched folder */
        if (CAMEL_IS_VEE_FOLDER (subfolder) ||
-           used_by == vstore->priv->unmatched_folder)
+           used_by == vstore->priv->unmatched_folder ||
+           camel_application_is_exiting)
                return;
 
        g_mutex_lock (&vstore->priv->sf_counts_mutex);
@@ -795,7 +798,8 @@ camel_vee_store_note_subfolder_unused (CamelVeeStore *vstore,
 
        /* only real folders can be part of the unmatched folder */
        if (CAMEL_IS_VEE_FOLDER (subfolder) ||
-           unused_by == vstore->priv->unmatched_folder)
+           unused_by == vstore->priv->unmatched_folder ||
+           camel_application_is_exiting)
                return;
 
        g_mutex_lock (&vstore->priv->sf_counts_mutex);
@@ -850,7 +854,8 @@ camel_vee_store_note_vuid_used (CamelVeeStore *vstore,
        g_return_if_fail (mi_data != NULL);
 
        /* these notifications are ignored from Unmatched folder */
-       if (used_by == vstore->priv->unmatched_folder)
+       if (used_by == vstore->priv->unmatched_folder ||
+           camel_application_is_exiting)
                return;
 
        /* unmatched folder holds only real folders */
@@ -912,7 +917,8 @@ camel_vee_store_note_vuid_unused (CamelVeeStore *vstore,
        g_return_if_fail (mi_data != NULL);
 
        /* these notifications are ignored from Unmatched folder */
-       if (unused_by == vstore->priv->unmatched_folder)
+       if (unused_by == vstore->priv->unmatched_folder ||
+           camel_application_is_exiting)
                return;
 
        /* unmatched folder holds only real folders */
diff --git a/src/camel/camel-vee-summary.c b/src/camel/camel-vee-summary.c
index 2b51c26..e89ee48 100644
--- a/src/camel/camel-vee-summary.c
+++ b/src/camel/camel-vee-summary.c
@@ -88,6 +88,36 @@ message_info_from_uid (CamelFolderSummary *s,
 }
 
 static void
+vee_summary_prepare_fetch_all (CamelFolderSummary *summary)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+       CamelVeeSummary *vee_summary;
+
+       g_return_if_fail (CAMEL_IS_VEE_SUMMARY (summary));
+
+       camel_folder_summary_lock (summary);
+
+       vee_summary = CAMEL_VEE_SUMMARY (summary);
+
+       g_hash_table_iter_init (&iter, vee_summary->priv->vuids_by_subfolder);
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               CamelFolder *subfolder = key;
+               GHashTable *vuids = value;
+
+               if (subfolder && vuids && g_hash_table_size (vuids) > 50) {
+                       CamelFolderSummary *subsummary;
+
+                       subsummary = camel_folder_get_folder_summary (subfolder);
+                       if (subsummary)
+                               camel_folder_summary_prepare_fetch_all (subsummary, NULL);
+               }
+       }
+
+       camel_folder_summary_unlock (summary);
+}
+
+static void
 vee_summary_finalize (GObject *object)
 {
        CamelVeeSummaryPrivate *priv;
@@ -114,6 +144,7 @@ camel_vee_summary_class_init (CamelVeeSummaryClass *class)
        folder_summary_class = CAMEL_FOLDER_SUMMARY_CLASS (class);
        folder_summary_class->message_info_type = CAMEL_TYPE_VEE_MESSAGE_INFO;
        folder_summary_class->message_info_from_uid = message_info_from_uid;
+       folder_summary_class->prepare_fetch_all = vee_summary_prepare_fetch_all;
 }
 
 static void


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