[evolution-data-server] Bug 699529 - Store remote folder changes more often



commit 385c2b36a98def5b5ca4e22fd6de7181b6ef5a22
Author: Milan Crha <mcrha redhat com>
Date:   Tue Aug 18 19:55:03 2015 +0200

    Bug 699529 - Store remote folder changes more often

 camel/camel-offline-folder.c            |  167 +++++++++++++++++++++++++++++++
 camel/camel-offline-settings.c          |   76 ++++++++++++++-
 camel/camel-offline-settings.h          |    5 +
 docs/reference/camel/camel-sections.txt |    2 +
 4 files changed, 249 insertions(+), 1 deletions(-)
---
diff --git a/camel/camel-offline-folder.c b/camel/camel-offline-folder.c
index 8b1528b..1e885f1 100644
--- a/camel/camel-offline-folder.c
+++ b/camel/camel-offline-folder.c
@@ -39,6 +39,10 @@ typedef struct _OfflineDownsyncData OfflineDownsyncData;
 
 struct _CamelOfflineFolderPrivate {
        gboolean offline_sync;
+
+       GMutex store_changes_lock;
+       guint store_changes_id;
+       gboolean store_changes_after_frozen;
 };
 
 struct _AsyncContext {
@@ -118,6 +122,106 @@ offline_folder_downsync_background (CamelSession *session,
 }
 
 static void
+offline_folder_store_changes_job_cb (CamelSession *session,
+                                    GCancellable *cancellable,
+                                    gpointer user_data,
+                                    GError **error)
+{
+       CamelFolder *folder = user_data;
+
+       g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder));
+
+       camel_folder_synchronize_sync (folder, FALSE, cancellable, error);
+}
+
+static gboolean
+offline_folder_schedule_store_changes_job (gpointer user_data)
+{
+       CamelOfflineFolder *offline_folder = user_data;
+       GSource *source;
+
+       source = g_main_current_source ();
+
+       if (g_source_is_destroyed (source))
+               return FALSE;
+
+       g_return_val_if_fail (CAMEL_IS_OFFLINE_FOLDER (offline_folder), FALSE);
+
+       g_mutex_lock (&offline_folder->priv->store_changes_lock);
+       if (offline_folder->priv->store_changes_id == g_source_get_id (source)) {
+               CamelSession *session;
+
+               offline_folder->priv->store_changes_id = 0;
+
+               session = camel_service_ref_session (CAMEL_SERVICE (camel_folder_get_parent_store 
(CAMEL_FOLDER (offline_folder))));
+               if (session) {
+                       gchar *description;
+
+                       description = g_strdup_printf (_("Storing changes in folder '%s'"),
+                               camel_folder_get_full_name (CAMEL_FOLDER (offline_folder)));
+
+                       camel_session_submit_job (session, description,
+                               offline_folder_store_changes_job_cb,
+                               g_object_ref (offline_folder), g_object_unref);
+
+                       g_free (description);
+               }
+
+               g_clear_object (&session);
+       }
+       g_mutex_unlock (&offline_folder->priv->store_changes_lock);
+
+       return FALSE;
+}
+
+static void
+offline_folder_maybe_schedule_folder_change_store (CamelOfflineFolder *offline_folder)
+{
+       CamelSession *session;
+       CamelStore *store;
+
+       g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (offline_folder));
+
+       g_mutex_lock (&offline_folder->priv->store_changes_lock);
+
+       if (offline_folder->priv->store_changes_id)
+               g_source_remove (offline_folder->priv->store_changes_id);
+       offline_folder->priv->store_changes_id = 0;
+       offline_folder->priv->store_changes_after_frozen = FALSE;
+
+       if (camel_folder_is_frozen (CAMEL_FOLDER (offline_folder))) {
+               offline_folder->priv->store_changes_after_frozen = TRUE;
+               g_mutex_unlock (&offline_folder->priv->store_changes_lock);
+
+               return;
+       }
+
+       store = camel_folder_get_parent_store (CAMEL_FOLDER (offline_folder));
+       session = camel_service_ref_session (CAMEL_SERVICE (store));
+
+       if (session && camel_session_get_online (session) && CAMEL_IS_OFFLINE_STORE (store) &&
+           camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store))) {
+               CamelSettings *settings;
+               gint interval = -1;
+
+               settings = camel_service_ref_settings (CAMEL_SERVICE (store));
+               if (settings && CAMEL_IS_OFFLINE_SETTINGS (settings))
+                       interval = camel_offline_settings_get_store_changes_interval (CAMEL_OFFLINE_SETTINGS 
(settings));
+               g_clear_object (&settings);
+
+               if (interval == 0)
+                       offline_folder_schedule_store_changes_job (offline_folder);
+               else if (interval > 0)
+                       offline_folder->priv->store_changes_id = g_timeout_add_seconds (interval,
+                               offline_folder_schedule_store_changes_job, offline_folder);
+       }
+
+       g_clear_object (&session);
+
+       g_mutex_unlock (&offline_folder->priv->store_changes_lock);
+}
+
+static void
 offline_folder_changed (CamelFolder *folder,
                         CamelFolderChangeInfo *changes)
 {
@@ -163,6 +267,9 @@ offline_folder_changed (CamelFolder *folder,
        }
 
        g_object_unref (session);
+
+       if (changes && changes->uid_changed && changes->uid_changed->len > 0)
+               offline_folder_maybe_schedule_folder_change_store (CAMEL_OFFLINE_FOLDER (folder));
 }
 
 static void
@@ -199,6 +306,57 @@ offline_folder_get_property (GObject *object,
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 }
 
+static void
+offline_folder_dispose (GObject *object)
+{
+       CamelOfflineFolder *offline_folder = CAMEL_OFFLINE_FOLDER (object);
+
+       g_mutex_lock (&offline_folder->priv->store_changes_lock);
+       if (offline_folder->priv->store_changes_id)
+               g_source_remove (offline_folder->priv->store_changes_id);
+       offline_folder->priv->store_changes_id = 0;
+       g_mutex_unlock (&offline_folder->priv->store_changes_lock);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (camel_offline_folder_parent_class)->dispose (object);
+}
+
+static void
+offline_folder_finalize (GObject *object)
+{
+       CamelOfflineFolder *offline_folder = CAMEL_OFFLINE_FOLDER (object);
+
+       g_mutex_clear (&offline_folder->priv->store_changes_lock);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (camel_offline_folder_parent_class)->finalize (object);
+}
+
+static void
+offline_folder_thaw (CamelFolder *folder)
+{
+       /* Chain up to parent's method. */
+       CAMEL_FOLDER_CLASS (camel_offline_folder_parent_class)->thaw (folder);
+
+       if (!camel_folder_is_frozen (folder)) {
+               CamelOfflineFolder *offline_folder;
+
+               g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder));
+
+               offline_folder = CAMEL_OFFLINE_FOLDER (folder);
+
+               g_mutex_lock (&offline_folder->priv->store_changes_lock);
+               if (offline_folder->priv->store_changes_after_frozen) {
+                       offline_folder->priv->store_changes_after_frozen = FALSE;
+                       g_mutex_unlock (&offline_folder->priv->store_changes_lock);
+
+                       offline_folder_maybe_schedule_folder_change_store (offline_folder);
+               } else {
+                       g_mutex_unlock (&offline_folder->priv->store_changes_lock);
+               }
+       }
+}
+
 static gboolean
 offline_folder_downsync_sync (CamelOfflineFolder *offline,
                               const gchar *expression,
@@ -253,12 +411,18 @@ static void
 camel_offline_folder_class_init (CamelOfflineFolderClass *class)
 {
        GObjectClass *object_class;
+       CamelFolderClass *folder_class;
 
        g_type_class_add_private (class, sizeof (CamelOfflineFolderPrivate));
 
        object_class = G_OBJECT_CLASS (class);
        object_class->set_property = offline_folder_set_property;
        object_class->get_property = offline_folder_get_property;
+       object_class->dispose = offline_folder_dispose;
+       object_class->finalize = offline_folder_finalize;
+
+       folder_class = CAMEL_FOLDER_CLASS (class);
+       folder_class->thaw = offline_folder_thaw;
 
        class->downsync_sync = offline_folder_downsync_sync;
 
@@ -279,6 +443,9 @@ camel_offline_folder_init (CamelOfflineFolder *folder)
 {
        folder->priv = CAMEL_OFFLINE_FOLDER_GET_PRIVATE (folder);
 
+       g_mutex_init (&folder->priv->store_changes_lock);
+       folder->priv->store_changes_after_frozen = FALSE;
+
        g_signal_connect (
                folder, "changed",
                G_CALLBACK (offline_folder_changed), NULL);
diff --git a/camel/camel-offline-settings.c b/camel/camel-offline-settings.c
index 3d5cfad..8b4aa6e 100644
--- a/camel/camel-offline-settings.c
+++ b/camel/camel-offline-settings.c
@@ -25,11 +25,13 @@
 
 struct _CamelOfflineSettingsPrivate {
        gboolean stay_synchronized;
+       gint store_changes_interval;
 };
 
 enum {
        PROP_0,
-       PROP_STAY_SYNCHRONIZED
+       PROP_STAY_SYNCHRONIZED,
+       PROP_STORE_CHANGES_INTERVAL
 };
 
 G_DEFINE_TYPE (
@@ -49,6 +51,12 @@ offline_settings_set_property (GObject *object,
                                CAMEL_OFFLINE_SETTINGS (object),
                                g_value_get_boolean (value));
                        return;
+
+               case PROP_STORE_CHANGES_INTERVAL:
+                       camel_offline_settings_set_store_changes_interval (
+                               CAMEL_OFFLINE_SETTINGS (object),
+                               g_value_get_int (value));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -67,6 +75,13 @@ offline_settings_get_property (GObject *object,
                                camel_offline_settings_get_stay_synchronized (
                                CAMEL_OFFLINE_SETTINGS (object)));
                        return;
+
+               case PROP_STORE_CHANGES_INTERVAL:
+                       g_value_set_int (
+                               value,
+                               camel_offline_settings_get_store_changes_interval (
+                               CAMEL_OFFLINE_SETTINGS (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -94,6 +109,20 @@ camel_offline_settings_class_init (CamelOfflineSettingsClass *class)
                        G_PARAM_READWRITE |
                        G_PARAM_CONSTRUCT |
                        G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_STORE_CHANGES_INTERVAL,
+               g_param_spec_int (
+                       "store-changes-interval",
+                       "Store Changes Interval",
+                       "Interval, in seconds, to store folder changes",
+                       G_MININT,
+                       G_MAXINT,
+                       3,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -146,3 +175,48 @@ camel_offline_settings_set_stay_synchronized (CamelOfflineSettings *settings,
 
        g_object_notify (G_OBJECT (settings), "stay-synchronized");
 }
+/**
+ * camel_offline_settings_get_store_changes_interval:
+ * @settings: a #CamelOfflineSettings
+ *
+ * Returns the interval, in seconds, for the changes in the folder being
+ * saved automatically. 0 means immediately, while -1 means turning off
+ * automatic folder change saving.
+ *
+ * Returns: the interval for automatic store of folder changes
+ *
+ * Since: 3.18
+ **/
+
+gint
+camel_offline_settings_get_store_changes_interval (CamelOfflineSettings *settings)
+{
+       g_return_val_if_fail (CAMEL_IS_OFFLINE_SETTINGS (settings), -1);
+
+       return settings->priv->store_changes_interval;
+}
+
+/**
+ * camel_offline_settings_set_store_changes_interval:
+ * @settings: a #CamelOfflineSettings
+ * @interval: the interval, in seconds
+ *
+ * Sets the interval, in seconds, for the changes in the folder being
+ * saved automatically. 0 means immediately, while -1 means turning off
+ * automatic folder change saving.
+ *
+ * Since: 3.18
+ **/
+void
+camel_offline_settings_set_store_changes_interval (CamelOfflineSettings *settings,
+                                                  gint interval)
+{
+       g_return_if_fail (CAMEL_IS_OFFLINE_SETTINGS (settings));
+
+       if (settings->priv->store_changes_interval == interval)
+               return;
+
+       settings->priv->store_changes_interval = interval;
+
+       g_object_notify (G_OBJECT (settings), "store-changes-interval");
+}
diff --git a/camel/camel-offline-settings.h b/camel/camel-offline-settings.h
index 1e4dd33..b336a62 100644
--- a/camel/camel-offline-settings.h
+++ b/camel/camel-offline-settings.h
@@ -73,6 +73,11 @@ gboolean     camel_offline_settings_get_stay_synchronized
 void           camel_offline_settings_set_stay_synchronized
                                        (CamelOfflineSettings *settings,
                                         gboolean stay_synchronized);
+gint           camel_offline_settings_get_store_changes_interval
+                                       (CamelOfflineSettings *settings);
+void           camel_offline_settings_set_store_changes_interval
+                                       (CamelOfflineSettings *settings,
+                                        gint interval);
 
 G_END_DECLS
 
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index 88a11ad..8af238f 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -1572,6 +1572,8 @@ CamelOfflineFolderPrivate
 CamelOfflineSettings
 camel_offline_settings_get_stay_synchronized
 camel_offline_settings_set_stay_synchronized
+camel_offline_settings_get_store_changes_interval
+camel_offline_settings_set_store_changes_interval
 <SUBSECTION Standard>
 CAMEL_OFFLINE_SETTINGS
 CAMEL_IS_OFFLINE_SETTINGS


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