[evolution-mapi] Use cancellable rec mutex for connection operations
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Use cancellable rec mutex for connection operations
- Date: Thu, 12 Jul 2012 12:49:27 +0000 (UTC)
commit 4b470ed5f3c2efd43e7c11cc99bd98a601df9b3c
Author: Milan Crha <mcrha redhat com>
Date: Thu Jul 12 14:48:40 2012 +0200
Use cancellable rec mutex for connection operations
src/libexchangemapi/e-mapi-connection.c | 189 +++++++++++++++++++------------
src/libexchangemapi/e-mapi-utils.c | 152 +++++++++++++++++++++----
src/libexchangemapi/e-mapi-utils.h | 19 +++-
3 files changed, 262 insertions(+), 98 deletions(-)
---
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index 0da0030..c83954b 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -55,13 +55,38 @@ static struct mapi_session *mapi_profile_load (ESourceRegistry *registry, struct
G_DEFINE_TYPE (EMapiConnection, e_mapi_connection, G_TYPE_OBJECT)
+/* These three macros require 'priv' variable of type EMapiConnectionPrivate */
+#define LOCK(_cclb,_err,_ret) G_STMT_START { \
+ e_mapi_debug_print ("%s: %s: lock(session & global)", G_STRLOC, G_STRFUNC); \
+ if (!e_mapi_cancellable_rec_mutex_lock (&priv->session_lock, _cclb, _err)) { \
+ e_mapi_debug_print (" %s: %s: cancelled before got session lock)", G_STRLOC, G_STRFUNC); \
+ return _ret; \
+ } \
+ if (!e_mapi_utils_global_lock (_cclb, _err)) { \
+ e_mapi_cancellable_rec_mutex_unlock (&priv->session_lock); \
+ e_mapi_debug_print (" %s: %s: cancelled before got global lock)", G_STRLOC, G_STRFUNC); \
+ return _ret; \
+ } \
+ } G_STMT_END
-#define global_lock() e_mapi_utils_global_lock ()
-#define global_unlock() e_mapi_utils_global_unlock ()
+#define LOCK_VOID(_cclb,_err) G_STMT_START { \
+ e_mapi_debug_print ("%s: %s: lock(session & global)", G_STRLOC, G_STRFUNC); \
+ if (!e_mapi_cancellable_rec_mutex_lock (&priv->session_lock, _cclb, _err)) { \
+ e_mapi_debug_print (" %s: %s: cancelled before got session lock)", G_STRLOC, G_STRFUNC); \
+ return; \
+ } \
+ if (!e_mapi_utils_global_lock (_cclb, _err)) { \
+ e_mapi_cancellable_rec_mutex_unlock (&priv->session_lock); \
+ e_mapi_debug_print (" %s: %s: cancelled before got global lock)", G_STRLOC, G_STRFUNC); \
+ return; \
+ } \
+ } G_STMT_END
-/* These two macros require 'priv' variable of type EMapiConnectionPrivate */
-#define LOCK() e_mapi_debug_print ("%s: %s: lock(session & global)", G_STRLOC, G_STRFUNC); g_static_rec_mutex_lock (&priv->session_lock); global_lock ();
-#define UNLOCK() e_mapi_debug_print ("%s: %s: unlock(session & global)", G_STRLOC, G_STRFUNC); g_static_rec_mutex_unlock (&priv->session_lock); global_unlock ();
+#define UNLOCK() G_STMT_START { \
+ e_mapi_debug_print ("%s: %s: unlock(session & global)", G_STRLOC, G_STRFUNC); \
+ e_mapi_utils_global_unlock (); \
+ e_mapi_cancellable_rec_mutex_unlock (&priv->session_lock); \
+ } G_STMT_END
#define e_return_val_mapi_error_if_fail(expr, _code, _val) \
G_STMT_START { \
@@ -166,7 +191,7 @@ struct _EMapiConnectionPrivate {
struct mapi_context *mapi_ctx;
struct mapi_session *session;
- GStaticRecMutex session_lock;
+ EMapiCancellableRecMutex session_lock;
gchar *profile; /* profile name, where the session is connected to */
mapi_object_t msg_store; /* valid only when session != NULL */
@@ -207,7 +232,7 @@ stop_notification (EMapiConnectionPrivate *priv,
e_return_val_mapi_error_if_fail (priv != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
ms = Unsubscribe (priv->session, conn_id);
if (ms != MAPI_E_SUCCESS)
@@ -234,7 +259,7 @@ stop_all_notifications (EMapiConnectionPrivate *priv)
if (!priv->notification_thread)
return;
- LOCK ();
+ LOCK_VOID (NULL, NULL);
if (priv->session)
g_hash_table_foreach (priv->known_notifications, call_stop_notification, priv);
g_hash_table_remove_all (priv->known_notifications);
@@ -384,7 +409,7 @@ e_mapi_connection_finalize (GObject *object)
priv = E_MAPI_CONNECTION (object)->priv;
if (priv) {
- LOCK ();
+ LOCK_VOID (NULL, NULL);
disconnect (priv);
g_free (priv->profile);
priv->profile = NULL;
@@ -398,7 +423,7 @@ e_mapi_connection_finalize (GObject *object)
priv->foreign_stores = NULL;
UNLOCK ();
- g_static_rec_mutex_free (&priv->session_lock);
+ e_mapi_cancellable_rec_mutex_clear (&priv->session_lock);
g_static_rec_mutex_free (&priv->folders_lock);
e_mapi_utils_destroy_mapi_context (priv->mapi_ctx);
@@ -446,7 +471,7 @@ e_mapi_connection_init (EMapiConnection *conn)
conn->priv = G_TYPE_INSTANCE_GET_PRIVATE (conn, E_MAPI_TYPE_CONNECTION, EMapiConnectionPrivate);
g_return_if_fail (conn->priv != NULL);
- g_static_rec_mutex_init (&conn->priv->session_lock);
+ e_mapi_cancellable_rec_mutex_init (&conn->priv->session_lock);
g_static_rec_mutex_init (&conn->priv->folders_lock);
conn->priv->session = NULL;
@@ -582,7 +607,7 @@ e_mapi_connection_new (ESourceRegistry *registry,
priv = conn->priv;
e_return_val_mapi_error_if_fail (priv != NULL, MAPI_E_INVALID_PARAMETER, conn);
- LOCK ();
+ LOCK (cancellable, perror, NULL);
mapi_object_init (&priv->msg_store);
priv->registry = registry ? g_object_ref (registry) : NULL;
priv->mapi_ctx = mapi_ctx;
@@ -626,7 +651,7 @@ e_mapi_connection_close (EMapiConnection *conn)
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- LOCK ();
+ LOCK (NULL, NULL, FALSE);
res = priv->session != NULL;
disconnect (priv);
@@ -648,7 +673,7 @@ e_mapi_connection_reconnect (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (priv->profile != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
if (priv->session)
e_mapi_connection_close (conn);
@@ -748,7 +773,7 @@ e_mapi_connection_test_foreign_folder (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (folder_name != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (fid != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mapi_object_init (&obj_store);
mapi_object_init (&obj_folder);
@@ -832,7 +857,7 @@ e_mapi_connection_get_public_folder (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mapi_object_init (obj_folder);
@@ -862,7 +887,7 @@ e_mapi_connection_peek_store (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (!public_store, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (obj_store != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
if (public_store) {
if (!ensure_public_store (priv, perror)) {
@@ -929,7 +954,7 @@ e_mapi_connection_get_store_quotas (EMapiConnection *conn,
*receive_quota = -1;
*send_quota = -1;
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
@@ -1012,10 +1037,10 @@ e_mapi_connection_open_default_folder (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
-
mapi_object_init (obj_folder);
+ LOCK (cancellable, perror, FALSE);
+
ms = GetDefaultFolder (&priv->msg_store, &fid, olFolderIdentifier);
if (ms != MAPI_E_SUCCESS) {
make_mapi_error (perror, "GetDefaultFolder", ms);
@@ -1047,10 +1072,10 @@ e_mapi_connection_open_personal_folder (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
-
mapi_object_init (obj_folder);
+ LOCK (cancellable, perror, FALSE);
+
ms = OpenFolder (&priv->msg_store, fid, obj_folder);
if (ms != MAPI_E_SUCCESS)
make_mapi_error (perror, "OpenFolder", ms);
@@ -1072,7 +1097,9 @@ e_mapi_connection_open_public_folder (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ mapi_object_init (obj_folder);
+
+ LOCK (cancellable, perror, FALSE);
if (!ensure_public_store (priv, perror)) {
UNLOCK ();
@@ -1084,8 +1111,6 @@ e_mapi_connection_open_public_folder (EMapiConnection *conn,
return FALSE;
}
- mapi_object_init (obj_folder);
-
ms = OpenFolder (&priv->public_store, fid, obj_folder);
if (ms != MAPI_E_SUCCESS)
make_mapi_error (perror, "OpenFolder", ms);
@@ -1110,7 +1135,9 @@ e_mapi_connection_open_foreign_folder (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (username != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ mapi_object_init (obj_folder);
+
+ LOCK (cancellable, perror, FALSE);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
UNLOCK ();
@@ -1125,8 +1152,6 @@ e_mapi_connection_open_foreign_folder (EMapiConnection *conn,
ms = MAPI_E_SUCCESS;
}
- mapi_object_init (obj_folder);
-
if (ms == MAPI_E_SUCCESS) {
ms = OpenFolder (msg_store, fid, obj_folder);
if (ms == MAPI_E_NOT_FOUND)
@@ -1146,13 +1171,30 @@ e_mapi_connection_close_folder (EMapiConnection *conn,
GCancellable *cancellable,
GError **perror)
{
+ gboolean was_cancelled = FALSE;
+
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ /* kinda bad thing to do, but nothing better;
+ if the open_folder succeeded, then it's always good to free resources,
+ even when the operation on the folder was cancelled; and as it's good
+ to be cancellable, then this is better than passing NULL to LOCK().
+ */
+ if (cancellable) {
+ was_cancelled = g_cancellable_is_cancelled (cancellable);
+ if (was_cancelled)
+ g_cancellable_reset (cancellable);
+ }
+
+ LOCK (cancellable, perror, FALSE);
mapi_object_release (obj_folder);
+ /* this can invoke 'cancelled' again, but no big deal for evo-mapi */
+ if (was_cancelled)
+ g_cancellable_cancel (cancellable);
+
UNLOCK ();
return TRUE;
@@ -1255,7 +1297,7 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
if (g_cancellable_set_error_if_cancelled (cancellable, perror))
@@ -1510,7 +1552,7 @@ e_mapi_connection_get_permissions (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (entries != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
mapi_object_init (&obj_table);
@@ -1578,7 +1620,7 @@ e_mapi_connection_set_permissions (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
rows = talloc_zero (mem_ctx, struct mapi_PermissionsData);
@@ -1954,7 +1996,7 @@ e_mapi_connection_list_objects (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
mapi_object_init (&obj_table);
@@ -2813,7 +2855,7 @@ e_mapi_connection_transfer_objects (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
eap.download_offset = 0;
@@ -2962,7 +3004,7 @@ e_mapi_connection_transfer_summary (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
ms = MAPI_E_SUCCESS;
@@ -3254,7 +3296,7 @@ write_streamed_prop (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (obj_object != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (stream != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mapi_object_init (&obj_stream);
@@ -3357,7 +3399,7 @@ update_props_on_object (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
if (!convert_mapi_props_to_props (conn, obj_folder, properties, known_streams, known_streams_count, &props, &propslen, &streams, &streamslen, mem_ctx, cancellable, perror)) {
ms = MAPI_E_CALL_FAILED;
@@ -3455,7 +3497,7 @@ delete_object_recipients (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
ms = RemoveAllRecipients (obj_object);
if (ms != MAPI_E_SUCCESS)
@@ -3512,7 +3554,7 @@ add_object_recipients (EMapiConnection *conn,
if (!count)
return TRUE;
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
all_proptags = g_hash_table_new (g_direct_hash, g_direct_equal);
users = g_new0 (const gchar *, count + 1);
@@ -3682,7 +3724,7 @@ delete_object_attachments (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mapi_object_init (&obj_table);
@@ -3740,7 +3782,7 @@ add_object_attachments (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
for (attachment = attachments; attachment && ms == MAPI_E_SUCCESS; attachment = attachment->next) {
mapi_object_t obj_attach;
@@ -3889,7 +3931,7 @@ e_mapi_connection_create_object (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (write_object_cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (out_mid != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
*out_mid = 0;
@@ -4002,7 +4044,7 @@ e_mapi_connection_modify_object (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (write_object_cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (mid != 0, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
mapi_object_init (&obj_message);
@@ -4324,7 +4366,7 @@ e_mapi_connection_count_gal_objects (EMapiConnection *conn,
*obj_total = 0;
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
@@ -4365,7 +4407,7 @@ e_mapi_connection_list_gal_objects (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (priv->session->nspi->ctx != NULL, MAPI_E_UNCONFIGURED, FALSE);
e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
@@ -4600,7 +4642,7 @@ e_mapi_connection_transfer_gal_objects (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (priv->session->nspi->ctx != NULL, MAPI_E_UNCONFIGURED, FALSE);
e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
for (iter = mids; iter; iter = iter->next) {
@@ -4752,7 +4794,7 @@ e_mapi_connection_create_folder (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (new_folder_type != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (new_fid != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mapi_object_init (&obj_folder);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
@@ -4804,7 +4846,7 @@ e_mapi_connection_empty_folder (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (obj_folder, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
@@ -4879,7 +4921,7 @@ emc_open_folders (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (obj_child_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (obj_parent_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mapi_object_init (obj_child_folder);
mapi_object_init (obj_parent_folder);
@@ -4956,7 +4998,7 @@ e_mapi_connection_remove_folder (EMapiConnection *conn,
folder = NULL;
}
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mapi_object_init (&obj_folder);
mapi_object_init (&obj_parent);
@@ -5025,7 +5067,7 @@ e_mapi_connection_rename_folder (EMapiConnection *conn,
e_mapi_debug_print ("%s: Entering %s ", G_STRLOC, G_STRFUNC);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
@@ -5072,7 +5114,7 @@ e_mapi_connection_move_folder (EMapiConnection *conn,
e_return_val_mapi_error_if_fail (new_name != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_return_val_mapi_error_if_fail (strchr (new_name, '/') == NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
@@ -5114,7 +5156,7 @@ e_mapi_connection_resolve_named_props (EMapiConnection *conn,
e_mapi_debug_print ("%s: Entering %s ", G_STRLOC, G_STRFUNC);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
fid = 0;
if (obj_folder)
@@ -5427,7 +5469,7 @@ e_mapi_connection_get_default_folder_id (EMapiConnection *conn,
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
- LOCK ();
+ LOCK (cancellable, perror, 0);
ms = GetDefaultFolder (&priv->msg_store, &fid, olFolder);
if (ms != MAPI_E_SUCCESS) {
@@ -5464,7 +5506,7 @@ e_mapi_connection_set_flags (EMapiConnection *conn,
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
id_messages = talloc_array (mem_ctx, mapi_id_t, g_slist_length (mids));
@@ -5510,7 +5552,7 @@ e_mapi_connection_copymove_items (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
@@ -5570,7 +5612,7 @@ e_mapi_connection_remove_items (EMapiConnection *conn,
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
@@ -5947,7 +5989,7 @@ e_mapi_connection_get_folders_list (EMapiConnection *conn,
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
@@ -6053,7 +6095,7 @@ e_mapi_connection_get_pf_folders_list (EMapiConnection *conn,
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
if (!ensure_public_store (priv, perror))
@@ -6104,7 +6146,7 @@ e_mapi_connection_peek_folders_list (EMapiConnection *conn)
g_static_rec_mutex_lock (&priv->folders_lock);
if (!priv->folders) {
- LOCK ();
+ LOCK (NULL, NULL, NULL);
e_mapi_connection_get_folders_list (conn, &priv->folders, NULL, NULL, NULL, perror);
UNLOCK ();
}
@@ -6138,9 +6180,9 @@ e_mapi_connection_ex_to_smtp (EMapiConnection *conn,
str_array[0] = ex_address;
str_array[1] = NULL;
- mem_ctx = talloc_new (priv->session);
+ LOCK (cancellable, perror, NULL);
- LOCK ();
+ mem_ctx = talloc_new (priv->session);
SPropTagArray = set_SPropTagArray (mem_ctx, 0x2,
PR_DISPLAY_NAME_UNICODE,
@@ -6206,7 +6248,7 @@ e_mapi_connection_resolve_username (EMapiConnection *conn,
str_array[0] = to_resolve;
str_array[1] = NULL;
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
mem_ctx = talloc_new (priv->session);
@@ -6376,7 +6418,7 @@ e_mapi_connection_notification_thread (gpointer user_data)
while (g_hash_table_size (priv->known_notifications) > 0) {
GTimeVal tv;
- LOCK ();
+ LOCK (NULL, NULL, NULL);
/* this returns MAPI_E_INVALID_PARAMETER when there
is no pending notification
*/
@@ -6416,7 +6458,7 @@ e_mapi_connection_enable_notifications (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
if (event_mask == 0)
event_mask = fnevNewMail |
@@ -6482,7 +6524,7 @@ e_mapi_connection_disable_notifications (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- LOCK ();
+ LOCK (cancellable, perror, FALSE);
if (!priv->notification_thread) {
/* no notifications started, just return */
@@ -6655,7 +6697,8 @@ mapi_profile_load (ESourceRegistry *registry,
e_return_val_mapi_error_if_fail (mapi_ctx != NULL, MAPI_E_INVALID_PARAMETER, NULL);
e_return_val_mapi_error_if_fail (profname != NULL, MAPI_E_INVALID_PARAMETER, NULL);
- e_mapi_utils_global_lock ();
+ if (!e_mapi_utils_global_lock (cancellable, perror))
+ return NULL;
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
@@ -6729,8 +6772,10 @@ mapi_profile_create (struct mapi_context *mapi_ctx,
e_return_val_mapi_error_if_fail (COMPLETE_PROFILEDATA (empd) && (empd->krb_sso || (empd->password && empd->password->len)),
MAPI_E_INVALID_PARAMETER, FALSE);
- if (use_locking)
- e_mapi_utils_global_lock ();
+ if (use_locking) {
+ if (!e_mapi_utils_global_lock (cancellable, perror))
+ return FALSE;
+ }
e_mapi_debug_print ("Create profile with %s %s %s\n", empd->username,
empd->domain, empd->server);
@@ -6845,7 +6890,8 @@ e_mapi_delete_profile (struct mapi_context *mapi_ctx,
e_return_val_mapi_error_if_fail (mapi_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_mapi_utils_global_lock ();
+ if (!e_mapi_utils_global_lock (NULL, perror))
+ return FALSE;
e_mapi_debug_print ("Deleting profile %s ", profile);
@@ -6872,7 +6918,8 @@ e_mapi_rename_profile (struct mapi_context *mapi_ctx,
g_return_if_fail (new_name != NULL);
/* do not use locking here, it's called with a lock held already */
- /* e_mapi_utils_global_lock (); */
+ /* if (!e_mapi_utils_global_lock (NULL, perror))
+ return; */
RenameProfile (mapi_ctx, old_name, new_name);
diff --git a/src/libexchangemapi/e-mapi-utils.c b/src/libexchangemapi/e-mapi-utils.c
index 6ae30c8..13b452e 100644
--- a/src/libexchangemapi/e-mapi-utils.c
+++ b/src/libexchangemapi/e-mapi-utils.c
@@ -50,6 +50,128 @@
#define KRB_DBUS_PATH "/org/gnome/KrbAuthDialog"
#define KRB_DBUS_INTERFACE "org.gnome.KrbAuthDialog"
+void
+e_mapi_cancellable_rec_mutex_init (EMapiCancellableRecMutex *rec_mutex)
+{
+ g_return_if_fail (rec_mutex != NULL);
+
+ g_rec_mutex_init (&rec_mutex->rec_mutex);
+ g_mutex_init (&rec_mutex->cond_mutex);
+ g_cond_init (&rec_mutex->cond);
+}
+
+void
+e_mapi_cancellable_rec_mutex_clear (EMapiCancellableRecMutex *rec_mutex)
+{
+ g_return_if_fail (rec_mutex != NULL);
+
+ g_rec_mutex_clear (&rec_mutex->rec_mutex);
+ g_mutex_clear (&rec_mutex->cond_mutex);
+ g_cond_clear (&rec_mutex->cond);
+}
+
+static void
+cancellable_rec_mutex_cancelled_cb (GCancellable *cancellable,
+ EMapiCancellableRecMutex *rec_mutex)
+{
+ g_return_if_fail (rec_mutex != NULL);
+
+ /* wake-up any waiting threads */
+ g_mutex_lock (&rec_mutex->cond_mutex);
+ g_cond_broadcast (&rec_mutex->cond);
+ g_mutex_unlock (&rec_mutex->cond_mutex);
+}
+
+/* returns FALSE if cancelled, in which case the lock is not held */
+gboolean
+e_mapi_cancellable_rec_mutex_lock (EMapiCancellableRecMutex *rec_mutex,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gulong handler_id;
+ gboolean res = TRUE;
+
+ g_return_val_if_fail (rec_mutex != NULL, FALSE);
+
+ g_mutex_lock (&rec_mutex->cond_mutex);
+ if (!cancellable) {
+ g_mutex_unlock (&rec_mutex->cond_mutex);
+ g_rec_mutex_lock (&rec_mutex->rec_mutex);
+ return TRUE;
+ }
+
+ if (g_cancellable_is_cancelled (cancellable)) {
+ if (error && !*error)
+ g_cancellable_set_error_if_cancelled (cancellable, error);
+ g_mutex_unlock (&rec_mutex->cond_mutex);
+ return FALSE;
+ }
+
+ handler_id = g_signal_connect (cancellable, "cancelled",
+ G_CALLBACK (cancellable_rec_mutex_cancelled_cb), rec_mutex);
+
+ while (!g_rec_mutex_trylock (&rec_mutex->rec_mutex)) {
+ /* recheck once per 10 seconds, just in case */
+ g_cond_wait_until (&rec_mutex->cond, &rec_mutex->cond_mutex,
+ g_get_monotonic_time () + (10 * G_TIME_SPAN_SECOND));
+
+ if (g_cancellable_is_cancelled (cancellable)) {
+ if (error && !*error)
+ g_cancellable_set_error_if_cancelled (cancellable, error);
+ res = FALSE;
+ break;
+ }
+ }
+
+ g_signal_handler_disconnect (cancellable, handler_id);
+
+ g_mutex_unlock (&rec_mutex->cond_mutex);
+
+ return res;
+}
+
+void
+e_mapi_cancellable_rec_mutex_unlock (EMapiCancellableRecMutex *rec_mutex)
+{
+ g_return_if_fail (rec_mutex != NULL);
+
+ g_rec_mutex_unlock (&rec_mutex->rec_mutex);
+
+ g_mutex_lock (&rec_mutex->cond_mutex);
+ /* also wake-up any waiting threads */
+ g_cond_broadcast (&rec_mutex->cond);
+ g_mutex_unlock (&rec_mutex->cond_mutex);
+}
+
+static gboolean
+manage_global_lock (gboolean lock,
+ GCancellable *cancellable,
+ GError **error)
+{
+ static EMapiCancellableRecMutex global_lock;
+ gboolean res = TRUE;
+
+ if (lock)
+ res = e_mapi_cancellable_rec_mutex_lock (&global_lock, cancellable, error);
+ else
+ e_mapi_cancellable_rec_mutex_unlock (&global_lock);
+
+ return res;
+}
+
+gboolean
+e_mapi_utils_global_lock (GCancellable *cancellable,
+ GError **error)
+{
+ return manage_global_lock (TRUE, cancellable, error);
+}
+
+void
+e_mapi_utils_global_unlock (void)
+{
+ manage_global_lock (FALSE, NULL, NULL);
+}
+
inline gchar *
e_mapi_util_mapi_id_to_string (mapi_id_t id)
{
@@ -956,29 +1078,6 @@ e_mapi_utils_propagate_cancelled_error (const GError *mapi_error,
return TRUE;
}
-static void
-manage_global_lock (gboolean lock)
-{
- static GStaticRecMutex global_lock = G_STATIC_REC_MUTEX_INIT;
-
- if (lock)
- g_static_rec_mutex_lock (&global_lock);
- else
- g_static_rec_mutex_unlock (&global_lock);
-}
-
-void
-e_mapi_utils_global_lock (void)
-{
- manage_global_lock (TRUE);
-}
-
-void
-e_mapi_utils_global_unlock (void)
-{
- manage_global_lock (FALSE);
-}
-
gboolean
e_mapi_utils_create_mapi_context (struct mapi_context **mapi_ctx, GError **perror)
{
@@ -988,7 +1087,8 @@ e_mapi_utils_create_mapi_context (struct mapi_context **mapi_ctx, GError **perro
g_return_val_if_fail (mapi_ctx != NULL, FALSE);
- e_mapi_utils_global_lock ();
+ if (!e_mapi_utils_global_lock (NULL, perror))
+ return FALSE;
*mapi_ctx = NULL;
user_data_dir = e_get_user_data_dir ();
@@ -1028,7 +1128,9 @@ e_mapi_utils_destroy_mapi_context (struct mapi_context *mapi_ctx)
if (!mapi_ctx)
return;
- e_mapi_utils_global_lock ();
+ if (!e_mapi_utils_global_lock (NULL, NULL))
+ return;
+
MAPIUninitialize (mapi_ctx);
e_mapi_utils_global_unlock ();
}
diff --git a/src/libexchangemapi/e-mapi-utils.h b/src/libexchangemapi/e-mapi-utils.h
index f9577c2..8f080eb 100644
--- a/src/libexchangemapi/e-mapi-utils.h
+++ b/src/libexchangemapi/e-mapi-utils.h
@@ -30,6 +30,23 @@
#include "e-mapi-debug.h"
#include "e-mapi-connection.h"
+typedef struct _EMapiCancellableRecMutex {
+ GRecMutex rec_mutex;
+ GMutex cond_mutex;
+ GCond cond;
+} EMapiCancellableRecMutex;
+
+void e_mapi_cancellable_rec_mutex_init (EMapiCancellableRecMutex *rec_mutex);
+void e_mapi_cancellable_rec_mutex_clear (EMapiCancellableRecMutex *rec_mutex);
+gboolean e_mapi_cancellable_rec_mutex_lock (EMapiCancellableRecMutex *rec_mutex,
+ GCancellable *cancellable,
+ GError **error);
+void e_mapi_cancellable_rec_mutex_unlock (EMapiCancellableRecMutex *rec_mutex);
+
+gboolean e_mapi_utils_global_lock (GCancellable *cancellable,
+ GError **error);
+void e_mapi_utils_global_unlock (void);
+
gchar * e_mapi_util_mapi_id_to_string (mapi_id_t id);
gboolean e_mapi_util_mapi_id_from_string (const gchar *str, mapi_id_t *id);
@@ -99,8 +116,6 @@ void e_mapi_util_time_t_to_filetime (const time_t tt,
gboolean e_mapi_utils_propagate_cancelled_error (const GError *mapi_error,
GError **error);
-void e_mapi_utils_global_lock (void);
-void e_mapi_utils_global_unlock (void);
gboolean e_mapi_utils_create_mapi_context (struct mapi_context **mapi_ctx,
GError **perror);
void e_mapi_utils_destroy_mapi_context (struct mapi_context *mapi_ctx);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]