[evolution-data-server] I#208 - Avoid race condition when refreshing collection backend
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] I#208 - Avoid race condition when refreshing collection backend
- Date: Fri, 28 Aug 2020 12:22:08 +0000 (UTC)
commit 0714fdcbef7a03d1f15890d2f77537fd5c52467a
Author: Milan Crha <mcrha redhat com>
Date: Fri Aug 28 14:21:05 2020 +0200
I#208 - Avoid race condition when refreshing collection backend
Closes https://gitlab.gnome.org/GNOME/evolution-data-server/-/issues/208
src/libebackend/e-collection-backend.c | 63 ++++++++++++++++++++++
src/libebackend/e-collection-backend.h | 6 +++
src/libebackend/e-webdav-collection-backend.c | 11 ++++
src/modules/google-backend/module-google-backend.c | 5 +-
4 files changed, 84 insertions(+), 1 deletion(-)
---
diff --git a/src/libebackend/e-collection-backend.c b/src/libebackend/e-collection-backend.c
index d1b899fcee..7be6b8f184 100644
--- a/src/libebackend/e-collection-backend.c
+++ b/src/libebackend/e-collection-backend.c
@@ -75,6 +75,8 @@ struct _ECollectionBackendPrivate {
gint64 last_populate_call;
guint scheduled_populate_idle_id;
+
+ volatile gint populate_freeze_count;
};
enum {
@@ -625,6 +627,9 @@ collection_backend_populate_idle_cb (gpointer user_data)
backend->priv->scheduled_populate_idle_id = 0;
+ if (e_collection_backend_get_populate_frozen (backend))
+ return FALSE;
+
class = E_COLLECTION_BACKEND_GET_CLASS (backend);
g_return_val_if_fail (class != NULL, FALSE);
g_return_val_if_fail (class->populate != NULL, FALSE);
@@ -646,6 +651,9 @@ collection_backend_schedule_populate_idle (ECollectionBackend *backend,
{
g_return_if_fail (E_IS_COLLECTION_BACKEND (backend));
+ if (e_collection_backend_get_populate_frozen (backend))
+ return;
+
if (!force) {
/* Let automatically check for new child sources only once per day.
Users can still force this manually using e_source_registry_refresh_backend(). */
@@ -2020,3 +2028,58 @@ e_collection_backend_schedule_populate (ECollectionBackend *backend)
if (e_backend_get_online (E_BACKEND (backend)))
collection_backend_schedule_populate_idle (backend, TRUE);
}
+
+/**
+ * e_collection_backend_get_populate_frozen:
+ * @backend: an #ECollectionBackend
+ *
+ * Returns: Whether the backend has currently frozen (disabled) populate of its content.
+ *
+ * Since: 3.38
+ **/
+gboolean
+e_collection_backend_get_populate_frozen (ECollectionBackend *backend)
+{
+ g_return_val_if_fail (E_IS_COLLECTION_BACKEND (backend), FALSE);
+
+ return g_atomic_int_get (&backend->priv->populate_freeze_count) > 0;
+}
+
+/**
+ * e_collection_backend_freeze_populate:
+ * @backend: an #ECollectionBackend
+ *
+ * Freezes populate of the backend's content. This is used to avoid calling
+ * populate multiple times in parallel.
+ * Every call to this function should be followed by the call
+ * of e_collection_backend_thaw_populate() to reverse the effect of this function,
+ * regardless of the return value of this function.
+ *
+ * Returns: %TRUE, when this is the first freeze call
+ *
+ * Since: 3.38
+ **/
+gboolean
+e_collection_backend_freeze_populate (ECollectionBackend *backend)
+{
+ g_return_val_if_fail (E_IS_COLLECTION_BACKEND (backend), FALSE);
+
+ return !g_atomic_int_add (&backend->priv->populate_freeze_count, 1);
+}
+
+/**
+ * e_collection_backend_thaw_populate:
+ * @backend: an #ECollectionBackend
+ *
+ * Thaws populate of the backend's content. This is a pair function
+ * for e_collection_backend_freeze_populate().
+ *
+ * Since: 3.38
+ **/
+void
+e_collection_backend_thaw_populate (ECollectionBackend *backend)
+{
+ g_return_if_fail (E_IS_COLLECTION_BACKEND (backend));
+
+ g_atomic_int_add (&backend->priv->populate_freeze_count, -1);
+}
diff --git a/src/libebackend/e-collection-backend.h b/src/libebackend/e-collection-backend.h
index 695358d51e..f96a7099f1 100644
--- a/src/libebackend/e-collection-backend.h
+++ b/src/libebackend/e-collection-backend.h
@@ -171,6 +171,12 @@ void e_collection_backend_authenticate_children
const ENamedParameters *credentials);
void e_collection_backend_schedule_populate
(ECollectionBackend *backend);
+gboolean e_collection_backend_get_populate_frozen
+ (ECollectionBackend *backend);
+gboolean e_collection_backend_freeze_populate
+ (ECollectionBackend *backend);
+void e_collection_backend_thaw_populate
+ (ECollectionBackend *backend);
G_END_DECLS
diff --git a/src/libebackend/e-webdav-collection-backend.c b/src/libebackend/e-webdav-collection-backend.c
index b63c687b09..7f9880f2fb 100644
--- a/src/libebackend/e-webdav-collection-backend.c
+++ b/src/libebackend/e-webdav-collection-backend.c
@@ -303,6 +303,11 @@ webdav_collection_backend_populate (ECollectionBackend *collection)
ESource *source;
GList *list, *liter;
+ if (!e_collection_backend_freeze_populate (collection)) {
+ e_collection_backend_thaw_populate (collection);
+ return;
+ }
+
/* Chain up to parent's method. */
E_COLLECTION_BACKEND_CLASS (e_webdav_collection_backend_parent_class)->populate (collection);
@@ -359,6 +364,8 @@ webdav_collection_backend_populate (ECollectionBackend *collection)
}
g_object_unref (server);
+
+ e_collection_backend_thaw_populate (collection);
}
static void
@@ -532,6 +539,8 @@ e_webdav_collection_backend_discover_sync (EWebDAVCollectionBackend *webdav_back
(!e_source_collection_get_contacts_enabled (collection_extension) || !contacts_url))
return E_SOURCE_AUTHENTICATION_ACCEPTED;
+ e_collection_backend_freeze_populate (collection);
+
credentials_empty = !credentials || !e_named_parameters_count (credentials) ||
(e_named_parameters_count (credentials) == 1 && e_named_parameters_exists (credentials,
E_SOURCE_CREDENTIAL_SSL_TRUST));
@@ -638,5 +647,7 @@ e_webdav_collection_backend_discover_sync (EWebDAVCollectionBackend *webdav_back
g_hash_table_destroy (known_sources);
e_named_parameters_free (credentials_copy);
+ e_collection_backend_thaw_populate (collection);
+
return result;
}
diff --git a/src/modules/google-backend/module-google-backend.c
b/src/modules/google-backend/module-google-backend.c
index 2d1091225c..2b1fcf4736 100644
--- a/src/modules/google-backend/module-google-backend.c
+++ b/src/modules/google-backend/module-google-backend.c
@@ -502,6 +502,8 @@ google_backend_authenticate_sync (EBackend *backend,
g_return_val_if_fail (e_source_collection_get_calendar_enabled (collection_extension) ||
e_source_collection_get_contacts_enabled (collection_extension),
E_SOURCE_AUTHENTICATION_ERROR);
+ e_collection_backend_freeze_populate (collection);
+
if (credentials && !e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_USERNAME)) {
credentials_copy = e_named_parameters_new_clone (credentials);
e_named_parameters_set (credentials_copy, E_SOURCE_CREDENTIAL_USERNAME,
e_source_collection_get_identity (collection_extension));
@@ -609,6 +611,8 @@ google_backend_authenticate_sync (EBackend *backend,
g_hash_table_destroy (known_sources);
e_named_parameters_free (credentials_copy);
+ e_collection_backend_thaw_populate (collection);
+
return result;
}
@@ -721,7 +725,6 @@ google_backend_populate (ECollectionBackend *backend)
google_backend_add_contacts (backend);
g_list_free_full (list, (GDestroyNotify) g_object_unref);
}
-
}
static gchar *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]