[evolution-data-server/gnome-3-32] I#130 - [CamelOfflineFolder] Multiple downsync operations can run simultaneously
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/gnome-3-32] I#130 - [CamelOfflineFolder] Multiple downsync operations can run simultaneously
- Date: Fri, 21 Jun 2019 16:34:14 +0000 (UTC)
commit a4d2f496e62fc07d8da94ad786f4cac6105a5f6a
Author: Milan Crha <mcrha redhat com>
Date: Fri Jun 21 18:35:14 2019 +0200
I#130 - [CamelOfflineFolder] Multiple downsync operations can run simultaneously
Closes https://gitlab.gnome.org/GNOME/evolution-data-server/issues/130
src/camel/camel-offline-folder.c | 71 ++++++++++++++++++++++++++++++++++++----
1 file changed, 65 insertions(+), 6 deletions(-)
---
diff --git a/src/camel/camel-offline-folder.c b/src/camel/camel-offline-folder.c
index 5d0d809b2..b0c95c6a6 100644
--- a/src/camel/camel-offline-folder.c
+++ b/src/camel/camel-offline-folder.c
@@ -28,6 +28,7 @@
#include "camel-offline-store.h"
#include "camel-operation.h"
#include "camel-session.h"
+#include "camel-string-utils.h"
#include "camel-utils.h"
#define CAMEL_OFFLINE_FOLDER_GET_PRIVATE(obj) \
@@ -43,6 +44,9 @@ struct _CamelOfflineFolderPrivate {
GMutex store_changes_lock;
guint store_changes_id;
gboolean store_changes_after_frozen;
+
+ GMutex ongoing_downloads_lock;
+ GHashTable *ongoing_downloads; /* gchar * UID ~> g_thread_self() */
};
struct _AsyncContext {
@@ -71,6 +75,60 @@ async_context_free (AsyncContext *async_context)
g_slice_free (AsyncContext, async_context);
}
+static gboolean
+offline_folder_synchronize_message_wrapper_sync (CamelFolder *folder,
+ const gchar *uid,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelOfflineFolder *offline_folder;
+ gboolean success;
+
+ g_return_val_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder), FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+
+ offline_folder = CAMEL_OFFLINE_FOLDER (folder);
+
+ g_mutex_lock (&offline_folder->priv->ongoing_downloads_lock);
+ /* Another thread is downloading this message already, do not wait for it,
+ just move on to the next one. In case the previous/ongoing download
+ fails the message won't be downloaded. */
+ if (g_hash_table_contains (offline_folder->priv->ongoing_downloads, uid)) {
+ if (camel_debug ("downsync")) {
+ printf ("[downsync] %p: (%s : %s): skipping uid '%s', because it is already
downloading by thread %p (this thread is %p)\n", camel_folder_get_parent_store (folder),
+ camel_service_get_display_name (CAMEL_SERVICE (camel_folder_get_parent_store
(folder))), camel_folder_get_full_name (folder),
+ uid, g_hash_table_lookup (offline_folder->priv->ongoing_downloads, uid),
g_thread_self ());
+ }
+ g_mutex_unlock (&offline_folder->priv->ongoing_downloads_lock);
+ return TRUE;
+ } else {
+ g_hash_table_insert (offline_folder->priv->ongoing_downloads, (gpointer) camel_pstring_strdup
(uid), g_thread_self ());
+ }
+
+ if (camel_debug ("downsync")) {
+ printf ("[downsync] %p: (%s : %s): going to download uid '%s' in thread %p\n",
camel_folder_get_parent_store (folder),
+ camel_service_get_display_name (CAMEL_SERVICE (camel_folder_get_parent_store
(folder))), camel_folder_get_full_name (folder),
+ uid, g_thread_self ());
+ }
+
+ g_mutex_unlock (&offline_folder->priv->ongoing_downloads_lock);
+
+ success = camel_folder_synchronize_message_sync (folder, uid, cancellable, error);
+
+ g_mutex_lock (&offline_folder->priv->ongoing_downloads_lock);
+ g_warn_if_fail (g_hash_table_remove (offline_folder->priv->ongoing_downloads, uid));
+
+ if (camel_debug ("downsync")) {
+ printf ("[downsync] %p: (%s : %s): finished download of uid '%s' in thread %p,
%s\n", camel_folder_get_parent_store (folder),
+ camel_service_get_display_name (CAMEL_SERVICE (camel_folder_get_parent_store
(folder))), camel_folder_get_full_name (folder),
+ uid, g_thread_self (), success ? "success" : "failure");
+ }
+
+ g_mutex_unlock (&offline_folder->priv->ongoing_downloads_lock);
+
+ return success;
+}
+
static void
offline_downsync_data_free (OfflineDownsyncData *data)
{
@@ -160,7 +218,7 @@ offline_folder_downsync_background (CamelSession *session,
continue;
}
- success = camel_folder_synchronize_message_sync (
+ success = offline_folder_synchronize_message_wrapper_sync (
data->folder, uid, cancellable, error);
}
} else {
@@ -386,6 +444,9 @@ offline_folder_finalize (GObject *object)
CamelOfflineFolder *offline_folder = CAMEL_OFFLINE_FOLDER (object);
g_mutex_clear (&offline_folder->priv->store_changes_lock);
+ g_mutex_clear (&offline_folder->priv->ongoing_downloads_lock);
+
+ g_hash_table_destroy (offline_folder->priv->ongoing_downloads);
/* Chain up to parent's method. */
G_OBJECT_CLASS (camel_offline_folder_parent_class)->finalize (object);
@@ -530,7 +591,7 @@ offline_folder_downsync_sync (CamelOfflineFolder *offline,
camel_folder_get_full_name (folder));
/* Stop on failure */
- if (!camel_folder_synchronize_message_sync (folder, uid, cancellable, &local_error)) {
+ if (!offline_folder_synchronize_message_wrapper_sync (folder, uid, cancellable,
&local_error)) {
if (camel_debug ("downsync")) {
printf ("[downsync] %p: (%s : %s): aborting, failed to
download uid:%s error:%s\n", camel_folder_get_parent_store (folder),
camel_service_get_display_name (CAMEL_SERVICE
(camel_folder_get_parent_store (folder))), camel_folder_get_full_name (folder),
@@ -539,10 +600,6 @@ offline_folder_downsync_sync (CamelOfflineFolder *offline,
g_clear_error (&local_error);
camel_operation_pop_message (cancellable);
break;
- } else if (camel_debug ("downsync")) {
- printf ("[downsync] %p: (%s : %s): uid '%s' downloaded\n",
camel_folder_get_parent_store (folder),
- camel_service_get_display_name (CAMEL_SERVICE
(camel_folder_get_parent_store (folder))), camel_folder_get_full_name (folder),
- uid);
}
camel_operation_pop_message (cancellable);
@@ -603,8 +660,10 @@ camel_offline_folder_init (CamelOfflineFolder *folder)
folder->priv = CAMEL_OFFLINE_FOLDER_GET_PRIVATE (folder);
g_mutex_init (&folder->priv->store_changes_lock);
+ g_mutex_init (&folder->priv->ongoing_downloads_lock);
folder->priv->store_changes_after_frozen = FALSE;
folder->priv->offline_sync = CAMEL_THREE_STATE_INCONSISTENT;
+ folder->priv->ongoing_downloads = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)
camel_pstring_free, NULL);
g_signal_connect (
folder, "changed",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]