[evolution-data-server/wip/offline-cache] Added ECalMetaBackend::requires_reconnect() virtual method and some other fixes
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/wip/offline-cache] Added ECalMetaBackend::requires_reconnect() virtual method and some other fixes
- Date: Thu, 16 Mar 2017 14:32:56 +0000 (UTC)
commit 157cfb1310260c9003e68a5eebfda008685075a3
Author: Milan Crha <mcrha redhat com>
Date: Thu Mar 16 15:29:58 2017 +0100
Added ECalMetaBackend::requires_reconnect() virtual method and some other fixes
src/calendar/libedata-cal/e-cal-meta-backend.c | 202 ++++++++++++++++++++++-
src/calendar/libedata-cal/e-cal-meta-backend.h | 3 +
2 files changed, 196 insertions(+), 9 deletions(-)
---
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.c b/src/calendar/libedata-cal/e-cal-meta-backend.c
index 5558de2..7ee31aa 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.c
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.c
@@ -62,6 +62,17 @@ struct _ECalMetaBackendPrivate {
gulong source_changed_id;
gulong notify_online_id;
guint refresh_timeout_id;
+
+ gboolean refresh_after_authenticate;
+
+ /* Last successful connect data, for some extensions */
+ guint16 authentication_port;
+ gchar *authentication_host;
+ gchar *authentication_user;
+ gchar *authentication_method;
+ gchar *authentication_proxy_uid;
+ gchar *authentication_credential_name;
+ SoupURI *webdav_soup_uri;
};
enum {
@@ -213,6 +224,49 @@ ecmb_steal_view_cancellable (ECalMetaBackend *meta_backend,
return cancellable;
}
+static void
+ecmb_update_connection_values (ECalMetaBackend *meta_backend)
+{
+ ESource *source;
+
+ g_return_if_fail (E_IS_CAL_META_BACKEND (meta_backend));
+
+ source = e_backend_get_source (E_BACKEND (meta_backend));
+
+ g_mutex_lock (&meta_backend->priv->property_lock);
+
+ meta_backend->priv->authentication_port = 0;
+ g_clear_pointer (&meta_backend->priv->authentication_host, g_free);
+ g_clear_pointer (&meta_backend->priv->authentication_user, g_free);
+ g_clear_pointer (&meta_backend->priv->authentication_method, g_free);
+ g_clear_pointer (&meta_backend->priv->authentication_proxy_uid, g_free);
+ g_clear_pointer (&meta_backend->priv->authentication_credential_name, g_free);
+ g_clear_pointer (&meta_backend->priv->webdav_soup_uri, (GDestroyNotify) soup_uri_free);
+
+ if (source && e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION)) {
+ ESourceAuthentication *auth_extension;
+
+ auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+ meta_backend->priv->authentication_port = e_source_authentication_get_port (auth_extension);
+ meta_backend->priv->authentication_host = e_source_authentication_dup_host (auth_extension);
+ meta_backend->priv->authentication_user = e_source_authentication_dup_user (auth_extension);
+ meta_backend->priv->authentication_method = e_source_authentication_dup_method
(auth_extension);
+ meta_backend->priv->authentication_proxy_uid = e_source_authentication_dup_proxy_uid
(auth_extension);
+ meta_backend->priv->authentication_credential_name =
e_source_authentication_dup_credential_name (auth_extension);
+ }
+
+ if (source && e_source_has_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND)) {
+ ESourceWebdav *webdav_extension;
+
+ webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+
+ meta_backend->priv->webdav_soup_uri = e_source_webdav_dup_soup_uri (webdav_extension);
+ }
+
+ g_mutex_unlock (&meta_backend->priv->property_lock);
+}
+
static gboolean
ecmb_connect_wrapper_sync (ECalMetaBackend *meta_backend,
GCancellable *cancellable,
@@ -240,7 +294,9 @@ ecmb_connect_wrapper_sync (ECalMetaBackend *meta_backend,
if (e_cal_meta_backend_connect_sync (meta_backend, credentials, &auth_result, &certificate_pem,
&certificate_errors,
cancellable, &local_error)) {
+ ecmb_update_connection_values (meta_backend);
e_named_parameters_free (credentials);
+
return TRUE;
}
@@ -416,6 +472,56 @@ ecmb_get_changes_sync (ECalMetaBackend *meta_backend,
return TRUE;
}
+static gboolean
+ecmb_requires_reconnect (ECalMetaBackend *meta_backend)
+{
+ ESource *source;
+ gboolean requires = FALSE;
+
+ g_return_val_if_fail (E_IS_CAL_META_BACKEND (meta_backend), FALSE);
+
+ source = e_backend_get_source (E_BACKEND (meta_backend));
+ g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+
+ g_mutex_lock (&meta_backend->priv->property_lock);
+
+ if (e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION)) {
+ ESourceAuthentication *auth_extension;
+
+ auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+ e_source_extension_property_lock (E_SOURCE_EXTENSION (auth_extension));
+
+ requires = meta_backend->priv->authentication_port != e_source_authentication_get_port
(auth_extension) ||
+ g_strcmp0 (meta_backend->priv->authentication_host, e_source_authentication_get_host
(auth_extension)) != 0 ||
+ g_strcmp0 (meta_backend->priv->authentication_user, e_source_authentication_get_user
(auth_extension)) != 0 ||
+ g_strcmp0 (meta_backend->priv->authentication_method,
e_source_authentication_get_method (auth_extension)) != 0 ||
+ g_strcmp0 (meta_backend->priv->authentication_proxy_uid,
e_source_authentication_get_proxy_uid (auth_extension)) != 0 ||
+ g_strcmp0 (meta_backend->priv->authentication_credential_name,
e_source_authentication_get_credential_name (auth_extension)) != 0;
+
+ e_source_extension_property_unlock (E_SOURCE_EXTENSION (auth_extension));
+ }
+
+ if (!requires && e_source_has_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND)) {
+ ESourceWebdav *webdav_extension;
+ SoupURI *soup_uri;
+
+ webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+ soup_uri = e_source_webdav_dup_soup_uri (webdav_extension);
+
+ requires = (!meta_backend->priv->webdav_soup_uri && soup_uri) ||
+ (soup_uri && meta_backend->priv->webdav_soup_uri &&
+ !soup_uri_equal (meta_backend->priv->webdav_soup_uri, soup_uri));
+
+ if (soup_uri)
+ soup_uri_free (soup_uri);
+ }
+
+ g_mutex_unlock (&meta_backend->priv->property_lock);
+
+ return requires;
+}
+
static void
ecmb_start_view_thread_func (ECalBackend *cal_backend,
gpointer user_data,
@@ -550,9 +656,16 @@ ecmb_refresh_thread_func (ECalBackend *cal_backend,
if (!e_backend_get_online (E_BACKEND (meta_backend)) ||
!ecmb_connect_wrapper_sync (meta_backend, cancellable, NULL)) {
/* Ignore connection errors here */
+ g_mutex_lock (&meta_backend->priv->property_lock);
+ meta_backend->priv->refresh_after_authenticate = TRUE;
+ g_mutex_unlock (&meta_backend->priv->property_lock);
goto done;
}
+ g_mutex_lock (&meta_backend->priv->property_lock);
+ meta_backend->priv->refresh_after_authenticate = FALSE;
+ g_mutex_unlock (&meta_backend->priv->property_lock);
+
cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
if (!cal_cache) {
g_warn_if_reached ();
@@ -634,9 +747,8 @@ ecmb_refresh_thread_func (ECalBackend *cal_backend,
g_hash_table_destroy (covered_uids);
}
- if (success) {
- e_cache_set_key (E_CACHE (cal_cache), ECMB_KEY_SYNC_TAG, new_sync_tag ? new_sync_tag
: "", NULL);
- }
+ if (success && new_sync_tag)
+ e_cache_set_key (E_CACHE (cal_cache), ECMB_KEY_SYNC_TAG, new_sync_tag, NULL);
g_slist_free_full (created_objects, e_cal_meta_backend_info_free);
g_slist_free_full (modified_objects, e_cal_meta_backend_info_free);
@@ -703,9 +815,17 @@ ecmb_source_changed_thread_func (ECalBackend *cal_backend,
g_signal_emit (meta_backend, signals[SOURCE_CHANGED], 0, NULL);
if (e_backend_get_online (E_BACKEND (meta_backend)) &&
+ e_cal_meta_backend_requires_reconnect (meta_backend) &&
e_cal_meta_backend_disconnect_sync (meta_backend, cancellable, error)) {
ecmb_schedule_refresh (meta_backend);
}
+
+ g_mutex_lock (&meta_backend->priv->property_lock);
+
+ if (meta_backend->priv->source_changed_cancellable == cancellable)
+ g_clear_object (&meta_backend->priv->source_changed_cancellable);
+
+ g_mutex_unlock (&meta_backend->priv->property_lock);
}
static void
@@ -714,12 +834,23 @@ ecmb_go_offline_thread_func (ECalBackend *cal_backend,
GCancellable *cancellable,
GError **error)
{
+ ECalMetaBackend *meta_backend;
+
g_return_if_fail (E_IS_CAL_META_BACKEND (cal_backend));
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return;
- e_cal_meta_backend_disconnect_sync (E_CAL_META_BACKEND (cal_backend), cancellable, error);
+ meta_backend = E_CAL_META_BACKEND (cal_backend);
+
+ e_cal_meta_backend_disconnect_sync (meta_backend, cancellable, error);
+
+ g_mutex_lock (&meta_backend->priv->property_lock);
+
+ if (meta_backend->priv->go_offline_cancellable == cancellable)
+ g_clear_object (&meta_backend->priv->go_offline_cancellable);
+
+ g_mutex_unlock (&meta_backend->priv->property_lock);
}
static ECalComponent *
@@ -2576,7 +2707,7 @@ ecmb_authenticate_sync (EBackend *backend,
{
ECalMetaBackend *meta_backend;
ESourceAuthenticationResult auth_result = E_SOURCE_AUTHENTICATION_UNKNOWN;
- gboolean success;
+ gboolean success, refresh_after_authenticate = FALSE;
g_return_val_if_fail (E_IS_CAL_META_BACKEND (backend), E_SOURCE_AUTHENTICATION_ERROR);
@@ -2593,6 +2724,7 @@ ecmb_authenticate_sync (EBackend *backend,
out_certificate_pem, out_certificate_errors, cancellable, error);
if (success) {
+ ecmb_update_connection_values (meta_backend);
auth_result = E_SOURCE_AUTHENTICATION_ACCEPTED;
} else {
if (auth_result == E_SOURCE_AUTHENTICATION_UNKNOWN)
@@ -2602,13 +2734,20 @@ ecmb_authenticate_sync (EBackend *backend,
g_mutex_lock (&meta_backend->priv->property_lock);
e_named_parameters_free (meta_backend->priv->last_credentials);
- if (success)
+ if (success) {
meta_backend->priv->last_credentials = e_named_parameters_new_clone (credentials);
- else
+
+ refresh_after_authenticate = meta_backend->priv->refresh_after_authenticate;
+ meta_backend->priv->refresh_after_authenticate = FALSE;
+ } else {
meta_backend->priv->last_credentials = NULL;
+ }
g_mutex_unlock (&meta_backend->priv->property_lock);
+ if (refresh_after_authenticate)
+ ecmb_schedule_refresh (meta_backend);
+
return auth_result;
}
@@ -2674,11 +2813,15 @@ ecmb_schedule_go_offline (ECalMetaBackend *meta_backend)
g_mutex_lock (&meta_backend->priv->property_lock);
/* Cancel anything ongoing now, but disconnect in a dedicated thread */
- if (meta_backend->priv->refresh_cancellable)
+ if (meta_backend->priv->refresh_cancellable) {
g_cancellable_cancel (meta_backend->priv->refresh_cancellable);
+ g_clear_object (&meta_backend->priv->refresh_cancellable);
+ }
- if (meta_backend->priv->source_changed_cancellable)
+ if (meta_backend->priv->source_changed_cancellable) {
g_cancellable_cancel (meta_backend->priv->source_changed_cancellable);
+ g_clear_object (&meta_backend->priv->source_changed_cancellable);
+ }
if (meta_backend->priv->go_offline_cancellable) {
/* Already going offline */
@@ -2857,6 +3000,12 @@ e_cal_meta_backend_finalize (GObject *object)
g_clear_object (&meta_backend->priv->source_changed_cancellable);
g_clear_object (&meta_backend->priv->go_offline_cancellable);
g_clear_error (&meta_backend->priv->create_cache_error);
+ g_clear_pointer (&meta_backend->priv->authentication_host, g_free);
+ g_clear_pointer (&meta_backend->priv->authentication_user, g_free);
+ g_clear_pointer (&meta_backend->priv->authentication_method, g_free);
+ g_clear_pointer (&meta_backend->priv->authentication_proxy_uid, g_free);
+ g_clear_pointer (&meta_backend->priv->authentication_credential_name, g_free);
+ g_clear_pointer (&meta_backend->priv->webdav_soup_uri, (GDestroyNotify) soup_uri_free);
g_mutex_clear (&meta_backend->priv->property_lock);
g_hash_table_destroy (meta_backend->priv->view_cancellables);
@@ -2876,6 +3025,7 @@ e_cal_meta_backend_class_init (ECalMetaBackendClass *klass)
g_type_class_add_private (klass, sizeof (ECalMetaBackendPrivate));
klass->get_changes_sync = ecmb_get_changes_sync;
+ klass->requires_reconnect = ecmb_requires_reconnect;
cal_backend_sync_class = E_CAL_BACKEND_SYNC_CLASS (klass);
cal_backend_sync_class->open_sync = ecmb_open_sync;
@@ -2961,6 +3111,7 @@ e_cal_meta_backend_init (ECalMetaBackend *meta_backend)
meta_backend->priv->view_cancellables = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
g_object_unref);
meta_backend->priv->current_online_state = FALSE;
+ meta_backend->priv->refresh_after_authenticate = FALSE;
}
/**
@@ -3013,6 +3164,8 @@ e_cal_meta_backend_set_cache (ECalMetaBackend *meta_backend,
return;
}
+ g_clear_error (&meta_backend->priv->create_cache_error);
+
g_clear_object (&meta_backend->priv->cache);
meta_backend->priv->cache = g_object_ref (cache);
@@ -3869,3 +4022,34 @@ e_cal_meta_backend_remove_component_sync (ECalMetaBackend *meta_backend,
return klass->remove_component_sync (meta_backend, conflict_resolution, uid, extra, cancellable,
error);
}
+
+/**
+ * e_cal_meta_backend_requires_reconnect:
+ * @meta_backend: an #ECalMetaBackend
+ *
+ * Determines, whether current source content requires reconnect of the backend.
+ *
+ * It is optional to implement this virtual method by the descendant. The default
+ * implementation compares %E_SOURCE_EXTENSION_AUTHENTICATION and
+ * %E_SOURCE_EXTENSION_WEBDAV_BACKEND, if existing in the source,
+ * with the values after the last successful connect and returns
+ * %TRUE when they changed. It always return %TRUE when there was
+ * no successful connect done yet.
+ *
+ * Returns: %TRUE, when reconnect is required, %FALSE otherwise.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_cal_meta_backend_requires_reconnect (ECalMetaBackend *meta_backend)
+{
+ ECalMetaBackendClass *klass;
+
+ g_return_val_if_fail (E_IS_CAL_META_BACKEND (meta_backend), FALSE);
+
+ klass = E_CAL_META_BACKEND_GET_CLASS (meta_backend);
+ g_return_val_if_fail (klass != NULL, FALSE);
+ g_return_val_if_fail (klass->requires_reconnect != NULL, FALSE);
+
+ return klass->requires_reconnect (meta_backend);
+}
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.h b/src/calendar/libedata-cal/e-cal-meta-backend.h
index 7079a91..d135b14 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.h
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.h
@@ -142,6 +142,7 @@ struct _ECalMetaBackendClass {
const gchar *extra,
GCancellable *cancellable,
GError **error);
+ gboolean (* requires_reconnect) (ECalMetaBackend *meta_backend);
/* Signals */
void (* source_changed) (ECalMetaBackend *meta_backend);
@@ -231,6 +232,8 @@ gboolean e_cal_meta_backend_remove_component_sync
const gchar *extra,
GCancellable *cancellable,
GError **error);
+gboolean e_cal_meta_backend_requires_reconnect
+ (ECalMetaBackend *meta_backend);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]