[evolution-ews] CamelEwsStore: Make connection usage thread-safe.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] CamelEwsStore: Make connection usage thread-safe.
- Date: Tue, 31 Jul 2012 17:31:58 +0000 (UTC)
commit 68333f7c1784782783554b0cf1c9f2d39ab8bc67
Author: Matthew Barnes <mbarnes redhat com>
Date: Tue Jul 31 11:46:46 2012 -0400
CamelEwsStore: Make connection usage thread-safe.
Always obtain the connection_lock before changing the EEwsConnection
pointer, and always obtain a reference to the EEwsConnection when using
it to issue requests.
src/camel/camel-ews-store.c | 141 ++++++++++++++++++++++++++++++-------------
1 files changed, 98 insertions(+), 43 deletions(-)
---
diff --git a/src/camel/camel-ews-store.c b/src/camel/camel-ews-store.c
index 7e4ec25..2731df0 100644
--- a/src/camel/camel-ews-store.c
+++ b/src/camel/camel-ews-store.c
@@ -62,7 +62,8 @@
struct _CamelEwsStorePrivate {
time_t last_refresh_time;
GMutex *get_finfo_lock;
- EEwsConnection *cnc;
+ EEwsConnection *connection;
+ GMutex *connection_lock;
};
static gboolean ews_store_construct (CamelService *service, CamelSession *session,
@@ -218,6 +219,7 @@ ews_connect_sync (CamelService *service,
GCancellable *cancellable,
GError **error)
{
+ EEwsConnection *connection;
CamelEwsStore *ews_store;
CamelSession *session;
gboolean success;
@@ -228,8 +230,11 @@ ews_connect_sync (CamelService *service,
if (camel_service_get_connection_status (service) == CAMEL_SERVICE_DISCONNECTED)
return FALSE;
- if (ews_store->priv->cnc != NULL)
+ connection = camel_ews_store_ref_connection (ews_store);
+ if (connection != NULL) {
+ g_object_unref (connection);
return TRUE;
+ }
/* Try running an operation that requires authentication
* to make sure we have a valid password available. */
@@ -253,14 +258,19 @@ ews_disconnect_sync (CamelService *service,
CamelEwsStore *ews_store = (CamelEwsStore *) service;
CamelServiceClass *service_class;
+ g_mutex_lock (ews_store->priv->connection_lock);
+
/* TODO cancel all operations in the connection */
- if (ews_store->priv->cnc) {
- g_signal_handlers_disconnect_by_data (camel_service_get_settings (service), service);
- e_ews_connection_forget_password (ews_store->priv->cnc);
- g_object_unref (ews_store->priv->cnc);
- ews_store->priv->cnc = NULL;
+ if (ews_store->priv->connection != NULL) {
+ g_signal_handlers_disconnect_by_data (
+ camel_service_get_settings (service), service);
+ e_ews_connection_forget_password (ews_store->priv->connection);
+ g_object_unref (ews_store->priv->connection);
+ ews_store->priv->connection = NULL;
}
+ g_mutex_unlock (ews_store->priv->connection_lock);
+
service_class = CAMEL_SERVICE_CLASS (camel_ews_store_parent_class);
return service_class->disconnect_sync (service, clean, cancellable, error);
}
@@ -372,20 +382,23 @@ ews_authenticate_sync (CamelService *service,
cancellable, &local_error);
if (local_error == NULL) {
- /* FIXME Protect this with a mutex. */
- if (ews_store->priv->cnc != NULL)
- g_object_unref (ews_store->priv->cnc);
- ews_store->priv->cnc = g_object_ref (connection);
+ g_mutex_lock (ews_store->priv->connection_lock);
+ if (ews_store->priv->connection != NULL)
+ g_object_unref (ews_store->priv->connection);
+ ews_store->priv->connection = g_object_ref (connection);
+ g_mutex_unlock (ews_store->priv->connection_lock);
/* This consumes all allocated result data. */
ews_update_folder_hierarchy (
ews_store, sync_state, includes_last_folder,
folders_created, folders_deleted, folders_updated);
} else {
- /* FIXME Protect this with a mutex. */
- if (ews_store->priv->cnc != NULL)
- g_object_unref (ews_store->priv->cnc);
- ews_store->priv->cnc = NULL;
+ g_mutex_lock (ews_store->priv->connection_lock);
+ if (ews_store->priv->connection != NULL) {
+ g_object_unref (ews_store->priv->connection);
+ ews_store->priv->connection = NULL;
+ }
+ g_mutex_unlock (ews_store->priv->connection_lock);
g_free (sync_state);
@@ -599,6 +612,7 @@ exit:
static gboolean
ews_refresh_finfo (CamelEwsStore *ews_store)
{
+ EEwsConnection *connection;
gchar *sync_state;
if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (ews_store)))
@@ -609,11 +623,17 @@ ews_refresh_finfo (CamelEwsStore *ews_store)
sync_state = camel_ews_store_summary_get_string_val (ews_store->summary, "sync_state", NULL);
+ connection = camel_ews_store_ref_connection (ews_store);
+
e_ews_connection_sync_folder_hierarchy (
- ews_store->priv->cnc, EWS_PRIORITY_MEDIUM,
+ connection, EWS_PRIORITY_MEDIUM,
sync_state, NULL, ews_folder_hierarchy_ready_cb,
g_object_ref (ews_store));
+
+ g_object_unref (connection);
+
g_free (sync_state);
+
return TRUE;
}
@@ -627,11 +647,13 @@ ews_get_folder_info_sync (CamelStore *store,
CamelEwsStore *ews_store;
CamelEwsStorePrivate *priv;
CamelFolderInfo *fi = NULL;
+ EEwsConnection *connection;
gchar *sync_state;
gboolean initial_setup = FALSE;
GSList *folders_created = NULL, *folders_updated = NULL;
GSList *folders_deleted = NULL;
gboolean includes_last_folder;
+ gboolean success;
GError *local_error = NULL;
ews_store = (CamelEwsStore *) store;
@@ -659,11 +681,17 @@ ews_get_folder_info_sync (CamelStore *store,
goto offline;
}
- if (!e_ews_connection_sync_folder_hierarchy_sync (
- ews_store->priv->cnc, EWS_PRIORITY_MEDIUM,
- &sync_state, &includes_last_folder,
- &folders_created, &folders_updated,
- &folders_deleted, cancellable, &local_error)) {
+ connection = camel_ews_store_ref_connection (ews_store);
+
+ success = e_ews_connection_sync_folder_hierarchy_sync (
+ connection, EWS_PRIORITY_MEDIUM,
+ &sync_state, &includes_last_folder,
+ &folders_created, &folders_updated,
+ &folders_deleted, cancellable, &local_error);
+
+ g_object_unref (connection);
+
+ if (!success) {
if (local_error)
g_warning ("Unable to fetch the folder hierarchy: %s :%d \n",
local_error->message, local_error->code);
@@ -697,7 +725,9 @@ ews_create_folder_sync (CamelStore *store,
gchar *fid = NULL;
gchar *full_name;
EwsFolderId *folder_id;
+ EEwsConnection *connection;
CamelFolderInfo *fi = NULL;
+ gboolean success;
GError *local_error = NULL;
/* Get Parent folder ID */
@@ -716,12 +746,17 @@ ews_create_folder_sync (CamelStore *store,
return NULL;
}
- /* Make the call */
- if (!e_ews_connection_create_folder_sync (
- ews_store->priv->cnc,
- EWS_PRIORITY_MEDIUM, fid,
- FALSE, folder_name, &folder_id,
- cancellable, &local_error)) {
+ connection = camel_ews_store_ref_connection (ews_store);
+
+ success = e_ews_connection_create_folder_sync (
+ connection,
+ EWS_PRIORITY_MEDIUM, fid,
+ FALSE, folder_name, &folder_id,
+ cancellable, &local_error);
+
+ g_object_unref (connection);
+
+ if (!success) {
camel_ews_store_maybe_disconnect (ews_store, local_error);
g_propagate_error (error, local_error);
g_free (fid);
@@ -759,6 +794,8 @@ ews_delete_folder_sync (CamelStore *store,
CamelEwsStoreSummary *ews_summary = ews_store->summary;
gchar *fid;
CamelFolderInfo *fi = NULL;
+ EEwsConnection *connection;
+ gboolean success;
GError *local_error = NULL;
fid = camel_ews_store_summary_get_folder_id_from_name (ews_summary,
@@ -774,11 +811,17 @@ ews_delete_folder_sync (CamelStore *store,
return FALSE;
}
- if (!e_ews_connection_delete_folder_sync (
- ews_store->priv->cnc,
- EWS_PRIORITY_MEDIUM,
- fid, FALSE, "HardDelete",
- cancellable, &local_error)) {
+ connection = camel_ews_store_ref_connection (ews_store);
+
+ success = e_ews_connection_delete_folder_sync (
+ connection,
+ EWS_PRIORITY_MEDIUM,
+ fid, FALSE, "HardDelete",
+ cancellable, &local_error);
+
+ g_object_unref (connection);
+
+ if (!success) {
camel_ews_store_maybe_disconnect (ews_store, local_error);
g_propagate_error (error, local_error);
g_free (fid);
@@ -832,6 +875,7 @@ ews_rename_folder_sync (CamelStore *store,
{
CamelEwsStore *ews_store = CAMEL_EWS_STORE (store);
CamelEwsStoreSummary *ews_summary = ews_store->summary;
+ EEwsConnection *connection;
const gchar *old_slash, *new_slash;
gchar *fid;
gchar *changekey;
@@ -862,6 +906,8 @@ ews_rename_folder_sync (CamelStore *store,
return FALSE;
}
+ connection = camel_ews_store_ref_connection (ews_store);
+
old_slash = g_strrstr (old_name, "/");
new_slash = g_strrstr (new_name, "/");
@@ -907,9 +953,12 @@ ews_rename_folder_sync (CamelStore *store,
rename_data->folder_id = fid;
rename_data->change_key = changekey;
- if (!e_ews_connection_update_folder_sync (
- ews_store->priv->cnc, EWS_PRIORITY_MEDIUM,
- rename_folder_cb, rename_data, cancellable, &local_error)) {
+ res = e_ews_connection_update_folder_sync (
+ connection, EWS_PRIORITY_MEDIUM,
+ rename_folder_cb, rename_data,
+ cancellable, &local_error);
+
+ if (!res) {
g_free (rename_data);
goto out;
}
@@ -934,9 +983,12 @@ ews_rename_folder_sync (CamelStore *store,
goto out;
}
}
- if (!e_ews_connection_move_folder_sync (
- ews_store->priv->cnc, EWS_PRIORITY_MEDIUM,
- pfid, fid, cancellable, &local_error)) {
+
+ res = e_ews_connection_move_folder_sync (
+ connection, EWS_PRIORITY_MEDIUM,
+ pfid, fid, cancellable, &local_error);
+
+ if (!res) {
g_free (pfid);
goto out;
}
@@ -951,6 +1003,8 @@ ews_rename_folder_sync (CamelStore *store,
g_propagate_error (error, local_error);
}
+ g_object_unref (connection);
+
g_free (changekey);
g_free (fid);
return res;
@@ -983,7 +1037,7 @@ camel_ews_store_ref_connection (CamelEwsStore *ews_store)
{
g_return_val_if_fail (CAMEL_IS_EWS_STORE (ews_store), NULL);
- return g_object_ref (ews_store->priv->cnc);
+ return g_object_ref (ews_store->priv->connection);
}
static CamelFolder *
@@ -1096,9 +1150,9 @@ ews_store_dispose (GObject *object)
ews_store->summary = NULL;
}
- if (ews_store->priv->cnc != NULL) {
- g_object_unref (ews_store->priv->cnc);
- ews_store->priv->cnc = NULL;
+ if (ews_store->priv->connection != NULL) {
+ g_object_unref (ews_store->priv->connection);
+ ews_store->priv->connection = NULL;
}
/* Chain up to parent's dispose() method. */
@@ -1114,6 +1168,7 @@ ews_store_finalize (GObject *object)
g_free (ews_store->storage_path);
g_mutex_free (ews_store->priv->get_finfo_lock);
+ g_mutex_free (ews_store->priv->connection_lock);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (camel_ews_store_parent_class)->finalize (object);
@@ -1159,7 +1214,7 @@ camel_ews_store_init (CamelEwsStore *ews_store)
ews_store->priv =
CAMEL_EWS_STORE_GET_PRIVATE (ews_store);
- ews_store->priv->cnc = NULL;
ews_store->priv->last_refresh_time = time (NULL) - (FINFO_REFRESH_INTERVAL + 10);
ews_store->priv->get_finfo_lock = g_mutex_new ();
+ ews_store->priv->connection_lock = g_mutex_new ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]