[evolution-mapi] Bug #608327 - Cannot recover after connection lost (book/cal parts)
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Bug #608327 - Cannot recover after connection lost (book/cal parts)
- Date: Tue, 17 Jul 2012 09:33:32 +0000 (UTC)
commit 467b2c3fc167c4b4eb5d73c1035211d6af68fbf7
Author: Milan Crha <mcrha redhat com>
Date: Tue Jul 17 11:32:49 2012 +0200
Bug #608327 - Cannot recover after connection lost (book/cal parts)
src/addressbook/e-book-backend-mapi-contacts.c | 112 ++++++++--
src/addressbook/e-book-backend-mapi-gal.c | 42 +++-
src/addressbook/e-book-backend-mapi.c | 113 ++++++++--
src/addressbook/e-book-backend-mapi.h | 46 +++--
src/calendar/e-cal-backend-mapi.c | 265 ++++++++++++++++++------
src/libexchangemapi/e-mapi-connection.c | 78 ++++---
6 files changed, 493 insertions(+), 163 deletions(-)
---
diff --git a/src/addressbook/e-book-backend-mapi-contacts.c b/src/addressbook/e-book-backend-mapi-contacts.c
index 8265c2e..795a146 100644
--- a/src/addressbook/e-book-backend-mapi-contacts.c
+++ b/src/addressbook/e-book-backend-mapi-contacts.c
@@ -360,25 +360,29 @@ ebbm_contacts_connection_status_changed (EBookBackendMAPI *ebma, gboolean is_onl
EMapiConnection *conn;
mapi_object_t obj_folder;
gboolean status;
+ GError *mapi_error = NULL;
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, NULL, NULL);
if (!conn) {
e_book_backend_mapi_unlock_connection (ebma);
return;
}
- status = ebbm_contacts_open_folder (E_BOOK_BACKEND_MAPI_CONTACTS (ebma), conn, &obj_folder, NULL, NULL);
+ status = ebbm_contacts_open_folder (E_BOOK_BACKEND_MAPI_CONTACTS (ebma), conn, &obj_folder, NULL, &mapi_error);
if (status) {
e_mapi_connection_enable_notifications (conn, &obj_folder,
fnevObjectCreated | fnevObjectModified | fnevObjectDeleted | fnevObjectMoved | fnevObjectCopied,
- NULL, NULL);
+ NULL, &mapi_error);
- e_mapi_connection_close_folder (conn, &obj_folder, NULL, NULL);
+ e_mapi_connection_close_folder (conn, &obj_folder, NULL, &mapi_error);
}
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
+ g_clear_error (&mapi_error);
+
g_signal_connect (conn, "server-notification", G_CALLBACK (ebbmc_server_notification_cb), ebma);
e_book_backend_mapi_unlock_connection (ebma);
@@ -411,9 +415,13 @@ ebbm_contacts_remove (EBookBackendMAPI *ebma, GCancellable *cancellable, GError
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
- g_propagate_error (error, EDB_ERROR (OFFLINE_UNAVAILABLE));
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
} else {
mapi_object_t *obj_store = NULL;
@@ -422,6 +430,7 @@ ebbm_contacts_remove (EBookBackendMAPI *ebma, GCancellable *cancellable, GError
if (mapi_error) {
mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to remove public folder"));
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
g_error_free (mapi_error);
}
}
@@ -462,10 +471,16 @@ ebbm_contacts_create_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
e_book_backend_mapi_unlock_connection (ebma);
+
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
+
return;
}
@@ -488,6 +503,7 @@ ebbm_contacts_create_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
}
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
e_book_backend_mapi_unlock_connection (ebma);
if (!mid) {
@@ -535,10 +551,16 @@ ebbm_contacts_remove_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
e_book_backend_mapi_unlock_connection (ebma);
+
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
+
return;
}
@@ -562,6 +584,7 @@ ebbm_contacts_remove_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
}
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
e_book_backend_mapi_unlock_connection (ebma);
if (mapi_error) {
@@ -607,10 +630,16 @@ ebbm_contacts_modify_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
e_book_backend_mapi_unlock_connection (ebma);
+
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
+
return;
}
@@ -638,6 +667,7 @@ ebbm_contacts_modify_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
}
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
if (!status) {
mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to modify item on a server"));
if (mapi_error)
@@ -691,10 +721,16 @@ ebbm_contacts_get_contact (EBookBackendMAPI *ebma, GCancellable *cancellable, co
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
e_book_backend_mapi_unlock_connection (ebma);
+
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
+
return;
}
@@ -722,6 +758,8 @@ ebbm_contacts_get_contact (EBookBackendMAPI *ebma, GCancellable *cancellable, co
*vcard = e_vcard_to_string (E_VCARD (tc.contact), EVC_FORMAT_VCARD_30);
g_object_unref (tc.contact);
} else {
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
+
if (!mapi_error || mapi_error->code == MAPI_E_NOT_FOUND) {
g_propagate_error (error, EDB_ERROR (CONTACT_NOT_FOUND));
} else {
@@ -772,10 +810,15 @@ ebbm_contacts_get_contact_list (EBookBackendMAPI *ebma, GCancellable *cancellabl
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
e_book_backend_mapi_unlock_connection (ebma);
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
return;
}
@@ -799,6 +842,8 @@ ebbm_contacts_get_contact_list (EBookBackendMAPI *ebma, GCancellable *cancellabl
g_slist_free_full (mids, g_free);
}
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
+
if (!status) {
mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to fetch items from a server"));
if (mapi_error)
@@ -847,10 +892,16 @@ ebbm_contacts_get_contacts_count (EBookBackendMAPI *ebma,
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
e_book_backend_mapi_unlock_connection (ebma);
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
+
return;
}
@@ -868,6 +919,8 @@ ebbm_contacts_get_contacts_count (EBookBackendMAPI *ebma,
e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
}
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
+
if (mapi_error) {
mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to count server contacts"));
g_error_free (mapi_error);
@@ -901,10 +954,16 @@ ebbm_contacts_list_known_uids (EBookBackendMAPI *ebma,
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
e_book_backend_mapi_unlock_connection (ebma);
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
+
return;
}
@@ -918,6 +977,8 @@ ebbm_contacts_list_known_uids (EBookBackendMAPI *ebma,
e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
}
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
+
if (mapi_error) {
mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to list items from a server"));
g_error_free (mapi_error);
@@ -953,10 +1014,15 @@ ebbm_contacts_transfer_contacts (EBookBackendMAPI *ebma,
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
e_book_backend_mapi_unlock_connection (ebma);
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
return;
}
@@ -992,6 +1058,8 @@ ebbm_contacts_transfer_contacts (EBookBackendMAPI *ebma,
g_slist_free_full (mids, g_free);
}
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
+
if (!status) {
mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to transfer contacts from a server"));
diff --git a/src/addressbook/e-book-backend-mapi-gal.c b/src/addressbook/e-book-backend-mapi-gal.c
index d92fab2..cf1c7dd 100644
--- a/src/addressbook/e-book-backend-mapi-gal.c
+++ b/src/addressbook/e-book-backend-mapi-gal.c
@@ -178,10 +178,16 @@ ebbm_gal_transfer_contacts (EBookBackendMAPI *ebma,
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
e_book_backend_mapi_unlock_connection (ebma);
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
+
return;
}
@@ -218,6 +224,8 @@ ebbm_gal_transfer_contacts (EBookBackendMAPI *ebma,
status = e_mapi_connection_transfer_gal_objects (conn, get_mids, NULL, NULL, transfer_gal_cb, &tg, cancellable, &mapi_error);
if (mapi_error) {
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
+
mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to fetch GAL entries"));
g_error_free (mapi_error);
} else if (!status) {
@@ -236,22 +244,35 @@ ebbm_gal_get_contacts_count (EBookBackendMAPI *ebma,
GError **error)
{
EMapiConnection *conn;
+ GError *mapi_error = NULL;
e_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (obj_total != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
e_book_backend_mapi_unlock_connection (ebma);
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
+
return;
}
- if (!e_mapi_connection_count_gal_objects (conn, obj_total, cancellable, error))
+ if (!e_mapi_connection_count_gal_objects (conn, obj_total, cancellable, &mapi_error))
*obj_total = -1;
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
+ if (mapi_error) {
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, NULL);
+ g_clear_error (&mapi_error);
+ }
+
e_book_backend_mapi_unlock_connection (ebma);
}
@@ -272,16 +293,23 @@ ebbm_gal_list_known_uids (EBookBackendMAPI *ebma,
e_book_backend_mapi_lock_connection (ebma);
- conn = e_book_backend_mapi_get_connection (ebma);
+ conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
if (!conn) {
e_book_backend_mapi_unlock_connection (ebma);
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+
+ if (!mapi_error)
+ g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
+ else
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
+ g_clear_error (&mapi_error);
+
return;
}
e_mapi_connection_list_gal_objects (conn, build_rs_cb, build_rs_cb_data, list_gal_uids_cb, lku, cancellable, &mapi_error);
if (mapi_error) {
+ e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to fetch GAL entries"));
g_error_free (mapi_error);
}
diff --git a/src/addressbook/e-book-backend-mapi.c b/src/addressbook/e-book-backend-mapi.c
index d61306f..6adab9e 100644
--- a/src/addressbook/e-book-backend-mapi.c
+++ b/src/addressbook/e-book-backend-mapi.c
@@ -51,7 +51,7 @@ struct _EBookBackendMAPIPrivate
{
EMapiOperationQueue *op_queue;
- GMutex *conn_lock;
+ GRecMutex conn_lock;
EMapiConnection *conn;
gchar *book_uid;
gboolean marked_for_offline;
@@ -69,7 +69,7 @@ struct _EBookBackendMAPIPrivate
gboolean server_dirty;
GHashTable *running_views; /* EDataBookView => GCancellable */
- GMutex *running_views_lock;
+ GMutex running_views_lock;
};
static CamelMapiSettings *
@@ -398,15 +398,16 @@ ebbm_connect_user (EBookBackendMAPI *ebma,
g_object_unref (old_conn);
if (!priv->conn || mapi_error) {
- gboolean is_network_error = g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NETWORK_ERROR);
+ gboolean is_network_error = g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NETWORK_ERROR) ||
+ (mapi_error && mapi_error->domain != E_MAPI_ERROR);
if (priv->conn) {
g_object_unref (priv->conn);
priv->conn = NULL;
}
- if (!is_network_error)
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Cannot connect"));
+ if (is_network_error)
+ mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, NULL);
e_book_backend_mapi_unlock_connection (ebma);
if (mapi_error)
@@ -429,6 +430,63 @@ ebbm_connect_user (EBookBackendMAPI *ebma,
return E_SOURCE_AUTHENTICATION_ACCEPTED;
}
+/* connection lock should be already held when calling this function */
+gboolean
+e_book_backend_mapi_ensure_connected (EBookBackendMAPI *ebma,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelMapiSettings *settings;
+ GError *local_error = NULL;
+
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), FALSE);
+
+ if (ebma->priv->conn && e_mapi_connection_connected (ebma->priv->conn))
+ return TRUE;
+
+ settings = ebbm_get_collection_settings (ebma);
+
+ if (!camel_mapi_settings_get_kerberos (settings) ||
+ ebbm_connect_user (ebma, cancellable, NULL, &local_error) != E_SOURCE_AUTHENTICATION_ACCEPTED) {
+ ESourceRegistry *registry;
+
+ registry = e_book_backend_get_registry (E_BOOK_BACKEND (ebma));
+
+ e_source_registry_authenticate_sync (
+ registry, e_backend_get_source (E_BACKEND (ebma)),
+ E_SOURCE_AUTHENTICATOR (ebma),
+ cancellable, &local_error);
+ }
+
+ if (!local_error)
+ return TRUE;
+
+ g_propagate_error (error, local_error);
+
+ return FALSE;
+}
+
+/* connection lock should be already held when calling this function */
+void
+e_book_backend_mapi_maybe_disconnect (EBookBackendMAPI *ebma,
+ const GError *mapi_error)
+{
+ g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
+
+ /* no error or already disconnected */
+ if (!mapi_error || !ebma->priv->conn)
+ return;
+
+ if (g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NETWORK_ERROR) ||
+ g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_CALL_FAILED)) {
+ e_mapi_connection_disconnect (ebma->priv->conn,
+ !g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NETWORK_ERROR),
+ NULL, NULL);
+ g_object_unref (ebma->priv->conn);
+ ebma->priv->conn = NULL;
+ }
+}
+
static void
ebbm_open (EBookBackendMAPI *ebma,
GCancellable *cancellable,
@@ -492,7 +550,7 @@ ebbm_open (EBookBackendMAPI *ebma,
e_book_backend_notify_online (E_BOOK_BACKEND (ebma), TRUE);
-
+ e_book_backend_mapi_ensure_connected (ebma, cancellable, &error);
if (!camel_mapi_settings_get_kerberos (settings) ||
ebbm_connect_user (ebma, cancellable, NULL, &error) != E_SOURCE_AUTHENTICATION_ACCEPTED) {
ESourceRegistry *registry;
@@ -1023,7 +1081,7 @@ ebbm_operation_cb (OperationBase *op, gboolean cancelled, EBookBackend *backend)
GError *err = NULL;
struct BookViewThreadData *bvtd = g_new0 (struct BookViewThreadData, 1);
- g_mutex_lock (ebma->priv->running_views_lock);
+ g_mutex_lock (&ebma->priv->running_views_lock);
bvtd->ebma = g_object_ref (ebma);
bvtd->book_view = g_object_ref (opbv->book_view);
@@ -1032,7 +1090,7 @@ ebbm_operation_cb (OperationBase *op, gboolean cancelled, EBookBackend *backend)
if (bvtd->cancellable)
g_object_ref (bvtd->cancellable);
- g_mutex_unlock (ebma->priv->running_views_lock);
+ g_mutex_unlock (&ebma->priv->running_views_lock);
g_thread_create (ebbm_book_view_thread, bvtd, FALSE, &err);
@@ -1259,9 +1317,9 @@ ebbm_op_start_book_view (EBookBackend *backend, EDataBookView *book_view)
op->base.opid = 0;
op->book_view = g_object_ref (book_view);
- g_mutex_lock (priv->running_views_lock);
+ g_mutex_lock (&priv->running_views_lock);
g_hash_table_insert (priv->running_views, book_view, g_cancellable_new ());
- g_mutex_unlock (priv->running_views_lock);
+ g_mutex_unlock (&priv->running_views_lock);
e_mapi_operation_queue_push (priv->op_queue, op);
}
@@ -1290,12 +1348,12 @@ ebbm_op_stop_book_view (EBookBackend *backend, EDataBookView *book_view)
op->base.opid = 0;
op->book_view = g_object_ref (book_view);
- g_mutex_lock (priv->running_views_lock);
+ g_mutex_lock (&priv->running_views_lock);
cancellable = g_hash_table_lookup (priv->running_views, book_view);
if (cancellable)
g_cancellable_cancel (cancellable);
g_hash_table_remove (priv->running_views, book_view);
- g_mutex_unlock (priv->running_views_lock);
+ g_mutex_unlock (&priv->running_views_lock);
e_mapi_operation_queue_push (priv->op_queue, op);
}
@@ -1307,8 +1365,8 @@ e_book_backend_mapi_init (EBookBackendMAPI *ebma)
ebma->priv->op_queue = e_mapi_operation_queue_new ((EMapiOperationQueueFunc) ebbm_operation_cb, ebma);
ebma->priv->running_views = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
- ebma->priv->running_views_lock = g_mutex_new ();
- ebma->priv->conn_lock = g_mutex_new ();
+ g_mutex_init (&ebma->priv->running_views_lock);
+ g_rec_mutex_init (&ebma->priv->conn_lock);
ebma->priv->update_cache = g_cancellable_new ();
ebma->priv->update_cache_thread = NULL;
@@ -1349,8 +1407,8 @@ ebbm_dispose (GObject *object)
FREE (priv->book_uid);
g_hash_table_destroy (priv->running_views);
- g_mutex_free (priv->running_views_lock);
- g_mutex_free (priv->conn_lock);
+ g_mutex_clear (&priv->running_views_lock);
+ g_rec_mutex_clear (&priv->conn_lock);
#undef UNREF
#undef FREE
@@ -1416,9 +1474,8 @@ e_book_backend_mapi_lock_connection (EBookBackendMAPI *ebma)
{
g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
g_return_if_fail (ebma->priv != NULL);
- g_return_if_fail (ebma->priv->conn_lock != NULL);
- g_mutex_lock (ebma->priv->conn_lock);
+ g_rec_mutex_lock (&ebma->priv->conn_lock);
}
void
@@ -1426,17 +1483,27 @@ e_book_backend_mapi_unlock_connection (EBookBackendMAPI *ebma)
{
g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
g_return_if_fail (ebma->priv != NULL);
- g_return_if_fail (ebma->priv->conn_lock != NULL);
- g_mutex_unlock (ebma->priv->conn_lock);
+ g_rec_mutex_unlock (&ebma->priv->conn_lock);
}
EMapiConnection *
-e_book_backend_mapi_get_connection (EBookBackendMAPI *ebma)
+e_book_backend_mapi_get_connection (EBookBackendMAPI *ebma,
+ GCancellable *cancellable,
+ GError **perror)
{
g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), NULL);
g_return_val_if_fail (ebma->priv != NULL, NULL);
+ if (ebma->priv->conn)
+ return ebma->priv->conn;
+
+ if (!e_backend_get_online (E_BACKEND (ebma)))
+ return NULL;
+
+ if (!e_book_backend_mapi_ensure_connected (ebma, cancellable, perror))
+ return NULL;
+
return ebma->priv->conn;
}
@@ -1458,9 +1525,9 @@ e_book_backend_mapi_book_view_is_running (EBookBackendMAPI *ebma, EDataBookView
g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), FALSE);
g_return_val_if_fail (ebma->priv != NULL, FALSE);
- g_mutex_lock (ebma->priv->running_views_lock);
+ g_mutex_lock (&ebma->priv->running_views_lock);
res = g_hash_table_lookup (ebma->priv->running_views, book_view) != NULL;
- g_mutex_unlock (ebma->priv->running_views_lock);
+ g_mutex_unlock (&ebma->priv->running_views_lock);
return res;
}
diff --git a/src/addressbook/e-book-backend-mapi.h b/src/addressbook/e-book-backend-mapi.h
index 97e6429..358ed2a 100644
--- a/src/addressbook/e-book-backend-mapi.h
+++ b/src/addressbook/e-book-backend-mapi.h
@@ -97,19 +97,39 @@ typedef struct
GType e_book_backend_mapi_get_type (void);
-const gchar *e_book_backend_mapi_get_book_uid (EBookBackendMAPI *ebma);
-void e_book_backend_mapi_lock_connection (EBookBackendMAPI *ebma);
-void e_book_backend_mapi_unlock_connection (EBookBackendMAPI *ebma);
-EMapiConnection *e_book_backend_mapi_get_connection (EBookBackendMAPI *ebma);
-void e_book_backend_mapi_get_db (EBookBackendMAPI *ebma, EBookBackendSqliteDB **db);
-gboolean e_book_backend_mapi_book_view_is_running (EBookBackendMAPI *ebma, EDataBookView *book_view);
-void e_book_backend_mapi_update_view_by_cache (EBookBackendMAPI *ebma, EDataBookView *book_view, GError **error);
-gboolean e_book_backend_mapi_is_marked_for_offline (EBookBackendMAPI *ebma);
-gboolean e_book_backend_mapi_notify_contact_update (EBookBackendMAPI *ebma, EDataBookView *book_view, EContact *contact, gint index, gint total, gpointer notify_contact_data);
-void e_book_backend_mapi_notify_contact_removed (EBookBackendMAPI *ebma, const gchar *uid);
-void e_book_backend_mapi_cache_set (EBookBackendMAPI *ebma, const gchar *key, const gchar *value);
-gchar *e_book_backend_mapi_cache_get (EBookBackendMAPI *ebma, const gchar *key);
-void e_book_backend_mapi_refresh_cache (EBookBackendMAPI *ebma);
+const gchar * e_book_backend_mapi_get_book_uid (EBookBackendMAPI *ebma);
+void e_book_backend_mapi_lock_connection (EBookBackendMAPI *ebma);
+void e_book_backend_mapi_unlock_connection (EBookBackendMAPI *ebma);
+EMapiConnection * e_book_backend_mapi_get_connection (EBookBackendMAPI *ebma,
+ GCancellable *cancellable,
+ GError **perror);
+gboolean e_book_backend_mapi_ensure_connected (EBookBackendMAPI *ebma,
+ GCancellable *cancellable,
+ GError **error);
+void e_book_backend_mapi_maybe_disconnect (EBookBackendMAPI *ebma,
+ const GError *mapi_error);
+void e_book_backend_mapi_get_db (EBookBackendMAPI *ebma,
+ EBookBackendSqliteDB **db);
+gboolean e_book_backend_mapi_book_view_is_running (EBookBackendMAPI *ebma,
+ EDataBookView *book_view);
+void e_book_backend_mapi_update_view_by_cache (EBookBackendMAPI *ebma,
+ EDataBookView *book_view,
+ GError **error);
+gboolean e_book_backend_mapi_is_marked_for_offline (EBookBackendMAPI *ebma);
+gboolean e_book_backend_mapi_notify_contact_update (EBookBackendMAPI *ebma,
+ EDataBookView *book_view,
+ EContact *contact,
+ gint index,
+ gint total,
+ gpointer notify_contact_data);
+void e_book_backend_mapi_notify_contact_removed (EBookBackendMAPI *ebma,
+ const gchar *uid);
+void e_book_backend_mapi_cache_set (EBookBackendMAPI *ebma,
+ const gchar *key,
+ const gchar *value);
+gchar * e_book_backend_mapi_cache_get (EBookBackendMAPI *ebma,
+ const gchar *key);
+void e_book_backend_mapi_refresh_cache (EBookBackendMAPI *ebma);
/* utility functions/macros */
diff --git a/src/calendar/e-cal-backend-mapi.c b/src/calendar/e-cal-backend-mapi.c
index 776a43e..79f0a7a 100644
--- a/src/calendar/e-cal-backend-mapi.c
+++ b/src/calendar/e-cal-backend-mapi.c
@@ -152,6 +152,9 @@ ecbm_open_folder (ECalBackendMAPI *ecbm,
return res;
}
+static EMapiConnection *e_cal_backend_mapi_get_connection (ECalBackendMAPI *cbma, GCancellable *cancellable, GError **perror);
+static void e_cal_backend_mapi_maybe_disconnect (ECalBackendMAPI *cbma, const GError *mapi_error);
+
#define CACHE_REFRESH_INTERVAL 600000
static GStaticMutex auth_mutex = G_STATIC_MUTEX_INIT;
@@ -385,16 +388,26 @@ ecbm_remove (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, GEr
cbmapi = E_CAL_BACKEND_MAPI (backend);
priv = cbmapi->priv;
- if (!e_backend_get_online (E_BACKEND (backend)) || !priv->conn || !e_mapi_connection_connected (priv->conn)) {
+ if (!e_backend_get_online (E_BACKEND (backend))) {
g_propagate_error (perror, EDC_ERROR (RepositoryOffline));
return;
}
+
if (!priv->is_public_folder && !priv->foreign_username) {
+ EMapiConnection *conn;
GError *mapi_error = NULL;
mapi_object_t *obj_store = NULL;
- if (!e_mapi_connection_peek_store (priv->conn, priv->foreign_username ? FALSE : priv->is_public_folder, priv->foreign_username, &obj_store, cancellable, &mapi_error) ||
- !e_mapi_connection_remove_folder (priv->conn, obj_store, priv->fid, cancellable, &mapi_error)) {
+ conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
+ if (!conn) {
+ if (!mapi_error)
+ g_propagate_error (perror, EDC_ERROR (RepositoryOffline));
+ else
+ mapi_error_to_edc_error (perror, mapi_error, RepositoryOffline, NULL);
+ e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
+ g_clear_error (&mapi_error);
+ } else if (!e_mapi_connection_peek_store (conn, priv->foreign_username ? FALSE : priv->is_public_folder, priv->foreign_username, &obj_store, cancellable, &mapi_error) ||
+ !e_mapi_connection_remove_folder (conn, obj_store, priv->fid, cancellable, &mapi_error)) {
mapi_error_to_edc_error (perror, mapi_error, OtherError, _("Failed to remove public folder"));
if (mapi_error)
g_error_free (mapi_error);
@@ -552,6 +565,8 @@ notify_error_ex (ECalBackendMAPI *mapi_backend, GError **perror, const gchar *fo
e_cal_backend_notify_error (E_CAL_BACKEND (mapi_backend), msg);
g_free (msg);
+ if (perror)
+ e_cal_backend_mapi_maybe_disconnect (mapi_backend, *perror);
g_clear_error (perror);
}
@@ -806,7 +821,13 @@ update_local_cache (ECalBackendMAPI *cbmapi, GCancellable *cancellable)
g_mutex_lock (priv->updating_mutex);
- conn = g_object_ref (priv->conn);
+ conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
+ if (!conn) {
+ g_clear_error (&mapi_error);
+ goto cleanup;
+ }
+
+ g_object_ref (conn);
success = ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &mapi_error);
if (!success) {
@@ -910,7 +931,8 @@ update_local_cache (ECalBackendMAPI *cbmapi, GCancellable *cancellable)
}
cleanup:
- g_object_unref (conn);
+ if (conn)
+ g_object_unref (conn);
g_mutex_unlock (priv->updating_mutex);
g_mutex_lock (priv->is_updating_mutex);
@@ -1237,10 +1259,11 @@ ecbm_connect_user (ECalBackend *backend,
g_signal_connect (priv->conn, "server-notification", G_CALLBACK (ecbm_server_notification_cb), cbmapi);
}
} else {
- gboolean is_network_error = g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NETWORK_ERROR);
+ gboolean is_network_error = g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NETWORK_ERROR) ||
+ (mapi_error && mapi_error->domain != E_MAPI_ERROR);
- if (!is_network_error)
- mapi_error_to_edc_error (perror, mapi_error, is_network_error ? OtherError : AuthenticationFailed, NULL);
+ if (is_network_error)
+ mapi_error_to_edc_error (perror, mapi_error, OtherError, NULL);
if (mapi_error)
g_error_free (mapi_error);
g_static_mutex_unlock (&auth_mutex);
@@ -1281,6 +1304,80 @@ ecbm_connect_user (ECalBackend *backend,
return E_SOURCE_AUTHENTICATION_ACCEPTED;
}
+static gboolean
+e_cal_backend_mapi_ensure_connected (ECalBackendMAPI *cbma,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ CamelMapiSettings *settings;
+ GError *local_error = NULL;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (cbma), FALSE);
+
+ if (cbma->priv->conn && e_mapi_connection_connected (cbma->priv->conn))
+ return TRUE;
+
+ settings = ecbm_get_collection_settings (cbma);
+
+ if (!camel_mapi_settings_get_kerberos (settings) ||
+ ecbm_connect_user (E_CAL_BACKEND (cbma), cancellable, NULL, &local_error) != E_SOURCE_AUTHENTICATION_ACCEPTED) {
+ ESourceRegistry *registry;
+
+ registry = e_cal_backend_get_registry (E_CAL_BACKEND (cbma));
+
+ e_source_registry_authenticate_sync (
+ registry, e_backend_get_source (E_BACKEND (cbma)),
+ E_SOURCE_AUTHENTICATOR (cbma),
+ cancellable, &local_error);
+ }
+
+ if (!local_error)
+ return TRUE;
+
+ g_propagate_error (perror, local_error);
+
+ return FALSE;
+}
+
+static void
+e_cal_backend_mapi_maybe_disconnect (ECalBackendMAPI *cbma,
+ const GError *mapi_error)
+{
+ g_return_if_fail (E_IS_CAL_BACKEND_MAPI (cbma));
+
+ /* no error or already disconnected */
+ if (!mapi_error || !cbma->priv->conn)
+ return;
+
+ if (g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NETWORK_ERROR) ||
+ g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_CALL_FAILED)) {
+ e_mapi_connection_disconnect (cbma->priv->conn,
+ !g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NETWORK_ERROR),
+ NULL, NULL);
+ g_object_unref (cbma->priv->conn);
+ cbma->priv->conn = NULL;
+ }
+}
+
+static EMapiConnection *
+e_cal_backend_mapi_get_connection (ECalBackendMAPI *cbma,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (cbma), NULL);
+ g_return_val_if_fail (cbma->priv != NULL, NULL);
+
+ if (cbma->priv->conn)
+ return cbma->priv->conn;
+
+ if (!e_backend_get_online (E_BACKEND (cbma)))
+ return NULL;
+
+ if (!e_cal_backend_mapi_ensure_connected (cbma, cancellable, perror))
+ return NULL;
+
+ return cbma->priv->conn;
+}
static void
ecbm_open (ECalBackend *backend,
@@ -1295,7 +1392,6 @@ ecbm_open (ECalBackend *backend,
ESourceMapiFolder *ext_mapi_folder;
guint64 fid;
const gchar *cache_dir;
- CamelMapiSettings *settings;
GError *error = NULL;
if (e_cal_backend_is_opened (backend)) {
@@ -1306,8 +1402,6 @@ ecbm_open (ECalBackend *backend,
cbmapi = E_CAL_BACKEND_MAPI (backend);
priv = cbmapi->priv;
- settings = ecbm_get_collection_settings (cbmapi);
-
esource = e_backend_get_source (E_BACKEND (cbmapi));
ext_mapi_folder = e_source_get_extension (esource, E_SOURCE_EXTENSION_MAPI_FOLDER);
fid = e_source_mapi_folder_get_id (ext_mapi_folder);
@@ -1377,17 +1471,7 @@ ecbm_open (ECalBackend *backend,
e_cal_backend_notify_online (backend, TRUE);
e_cal_backend_notify_readonly (backend, priv->read_only);
- if (!camel_mapi_settings_get_kerberos (settings) ||
- ecbm_connect_user (backend, cancellable, NULL, &error) != E_SOURCE_AUTHENTICATION_ACCEPTED) {
- ESourceRegistry *registry;
-
- registry = e_cal_backend_get_registry (backend);
-
- e_source_registry_authenticate_sync (
- registry, esource,
- E_SOURCE_AUTHENTICATOR (backend),
- cancellable, &error);
- }
+ e_cal_backend_mapi_ensure_connected (cbmapi, cancellable, &error);
if (error && perror)
g_propagate_error (perror, g_error_copy (error));
@@ -1521,37 +1605,45 @@ get_server_data (ECalBackendMAPI *cbmapi,
struct cal_cbdata *cbdata,
GCancellable *cancellable)
{
- ECalBackendMAPIPrivate *priv = cbmapi->priv;
+ EMapiConnection *conn;
icalcomponent *icalcomp;
mapi_id_t mid;
mapi_object_t obj_folder;
- GError *error = NULL;
+ GError *mapi_error = NULL;
icalcomp = e_cal_component_get_icalcomponent (comp);
get_comp_mid (icalcomp, &mid);
- if (!ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, NULL))
- return;
+ conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
+ if (!conn)
+ goto cleanup;
- if (!e_mapi_connection_transfer_object (priv->conn, &obj_folder, mid, ecbm_capture_req_props, cbdata, cancellable, &error)) {
- if (!g_error_matches (error, E_MAPI_ERROR, MAPI_E_NOT_FOUND)) {
- g_clear_error (&error);
- e_mapi_connection_close_folder (priv->conn, &obj_folder, cancellable, NULL);
- return;
+ if (!ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &mapi_error))
+ goto cleanup;
+
+ if (!e_mapi_connection_transfer_object (conn, &obj_folder, mid, ecbm_capture_req_props, cbdata, cancellable, &mapi_error)) {
+ if (!g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NOT_FOUND)) {
+ g_clear_error (&mapi_error);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
+ goto cleanup;
}
/* try to find by global-id, if not found by MID */
- g_clear_error (&error);
+ g_clear_error (&mapi_error);
}
- if (e_mapi_connection_list_objects (priv->conn, &obj_folder,
+ if (e_mapi_connection_list_objects (conn, &obj_folder,
ecbm_build_global_id_restriction, comp,
ecbm_list_for_one_mid_cb, &mid,
- cancellable, NULL)) {
- e_mapi_connection_transfer_object (priv->conn, &obj_folder, mid, ecbm_capture_req_props, cbdata, cancellable, NULL);
+ cancellable, &mapi_error)) {
+ e_mapi_connection_transfer_object (conn, &obj_folder, mid, ecbm_capture_req_props, cbdata, cancellable, &mapi_error);
}
- e_mapi_connection_close_folder (priv->conn, &obj_folder, cancellable, NULL);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
+
+ cleanup:
+ e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
+ g_clear_error (&mapi_error);
}
/* frees data members allocated in get_server_data(), not the cbdata itself */
@@ -1587,6 +1679,7 @@ ecbm_create_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
{
ECalBackendMAPI *cbmapi;
ECalBackendMAPIPrivate *priv;
+ EMapiConnection *conn;
icalcomponent_kind kind;
icalcomponent *icalcomp;
ECalComponent *comp;
@@ -1630,7 +1723,8 @@ ecbm_create_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
e_cal_component_set_last_modified (comp, ¤t);
/* Check if object exists */
- if (e_backend_get_online (E_BACKEND (backend))) {
+ conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
+ if (conn) {
struct cal_cbdata cbdata = { 0 };
gboolean status;
mapi_object_t obj_folder;
@@ -1652,18 +1746,18 @@ ecbm_create_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
cbdata.msgflags = MSGFLAG_READ;
cbdata.meeting_type = has_attendees ? MEETING_OBJECT : NOT_A_MEETING;
cbdata.resp = has_attendees ? olResponseOrganized : olResponseNone;
- cbdata.appt_id = e_mapi_cal_util_get_new_appt_id (priv->conn, priv->fid);
+ cbdata.appt_id = e_mapi_cal_util_get_new_appt_id (conn, priv->fid);
cbdata.appt_seq = 0;
cbdata.globalid = NULL;
cbdata.cleanglobalid = NULL;
- status = ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, &mapi_error);
+ status = ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &mapi_error);
if (status) {
- e_mapi_connection_create_object (priv->conn, &obj_folder, E_MAPI_CREATE_FLAG_NONE,
+ e_mapi_connection_create_object (conn, &obj_folder, E_MAPI_CREATE_FLAG_NONE,
e_mapi_cal_utils_comp_to_object, &cbdata,
&mid, cancellable, &mapi_error);
- e_mapi_connection_close_folder (priv->conn, &obj_folder, cancellable, &mapi_error);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
}
g_free (cbdata.username);
@@ -1674,6 +1768,7 @@ ecbm_create_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
if (!mid) {
g_object_unref (comp);
mapi_error_to_edc_error (error, mapi_error, OtherError, _("Failed to create item on a server"));
+ e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
if (mapi_error)
g_error_free (mapi_error);
return;
@@ -1691,7 +1786,12 @@ ecbm_create_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
*new_ecalcomp = e_cal_component_clone (comp);
e_cal_backend_notify_component_created (E_CAL_BACKEND (cbmapi), *new_ecalcomp);
} else {
- g_propagate_error (error, EDC_ERROR (UnsupportedMethod));
+ e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
+ if (!mapi_error)
+ g_propagate_error (error, EDC_ERROR (RepositoryOffline));
+ else
+ mapi_error_to_edc_error (error, mapi_error, RepositoryOffline, NULL);
+ g_clear_error (&mapi_error);
g_object_unref (comp);
return;
}
@@ -1760,6 +1860,7 @@ ecbm_modify_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
{
ECalBackendMAPI *cbmapi;
ECalBackendMAPIPrivate *priv;
+ EMapiConnection *conn;
icalcomponent_kind kind;
icalcomponent *icalcomp;
ECalComponent *comp, *cache_comp = NULL;
@@ -1821,7 +1922,9 @@ ecbm_modify_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
cbdata.get_timezone = (icaltimezone * (*)(gpointer data, const gchar *tzid)) ecbm_internal_get_timezone;
cbdata.get_tz_data = cbmapi;
- if (e_backend_get_online (E_BACKEND (backend))) {
+ conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
+
+ if (conn) {
gboolean has_attendees = e_cal_component_has_attendees (comp);
mapi_object_t obj_folder;
@@ -1863,13 +1966,13 @@ ecbm_modify_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
cbdata.meeting_type = has_attendees ? MEETING_OBJECT_RCVD : NOT_A_MEETING;
}
- status = ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, &mapi_error);
+ status = ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &mapi_error);
if (status) {
- status = e_mapi_connection_modify_object (priv->conn, &obj_folder, mid,
+ status = e_mapi_connection_modify_object (conn, &obj_folder, mid,
e_mapi_cal_utils_comp_to_object, &cbdata,
cancellable, &mapi_error);
- status = e_mapi_connection_close_folder (priv->conn, &obj_folder, cancellable, &mapi_error) && status;
+ status = e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error) && status;
}
free_server_data (&cbdata);
@@ -1878,6 +1981,7 @@ ecbm_modify_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
g_object_unref (cache_comp);
mapi_error_to_edc_error (error, mapi_error, OtherError, _("Failed to modify item on a server"));
+ e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
if (mapi_error)
g_error_free (mapi_error);
return;
@@ -1885,7 +1989,12 @@ ecbm_modify_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
} else {
g_object_unref (comp);
g_object_unref (cache_comp);
- g_propagate_error (error, EDC_ERROR (UnsupportedMethod));
+ e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
+ if (!mapi_error)
+ g_propagate_error (error, EDC_ERROR (RepositoryOffline));
+ else
+ mapi_error_to_edc_error (error, mapi_error, RepositoryOffline, NULL);
+ g_clear_error (&mapi_error);
return;
}
@@ -1906,10 +2015,11 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
{
ECalBackendMAPI *cbmapi;
ECalBackendMAPIPrivate *priv;
+ EMapiConnection *conn;
icalcomponent *icalcomp;
gchar *calobj = NULL;
mapi_id_t mid;
- GError *err = NULL;
+ GError *err = NULL, *mapi_error = NULL;
*old_ecalcomp = *new_ecalcomp = NULL;
cbmapi = E_CAL_BACKEND_MAPI (backend);
@@ -1941,6 +2051,8 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
get_comp_mid (icalcomp, &mid);
+ conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
+
if (mod == CALOBJ_MOD_THIS && rid && *rid) {
gchar *new_calobj = NULL;
struct icaltimetype time_rid;
@@ -1951,7 +2063,7 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
new_calobj = icalcomponent_as_ical_string_r (icalcomp);
ecbm_modify_object (backend, cal, cancellable, new_calobj, CALOBJ_MOD_ALL, old_ecalcomp, new_ecalcomp, &err);
g_free (new_calobj);
- } else {
+ } else if (conn) {
mapi_object_t obj_folder;
GSList *list=NULL, *l, *comp_list = e_cal_backend_store_get_components_by_uid (priv->store, uid);
GError *ri_error = NULL;
@@ -1960,8 +2072,8 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
*pmid = mid;
list = g_slist_prepend (list, pmid);
- if (ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, &ri_error)) {
- if (e_mapi_connection_remove_items (priv->conn, &obj_folder, list, cancellable, &ri_error)) {
+ if (ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &ri_error)) {
+ if (e_mapi_connection_remove_items (conn, &obj_folder, list, cancellable, &ri_error)) {
for (l = comp_list; l; l = l->next) {
ECalComponent *comp = E_CAL_COMPONENT (l->data);
ECalComponentId *id = e_cal_component_get_id (comp);
@@ -1974,17 +2086,27 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
}
}
- e_mapi_connection_close_folder (priv->conn, &obj_folder, cancellable, &ri_error);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &ri_error);
*old_ecalcomp = e_cal_component_new_from_icalcomponent (icalparser_parse_string (calobj));
*new_ecalcomp = NULL;
err = NULL; /* Success */
- } else
- mapi_error_to_edc_error (&err, ri_error, OtherError, "Cannot remove items from a server");
+ } else {
+ e_cal_backend_mapi_maybe_disconnect (cbmapi, ri_error);
+ mapi_error_to_edc_error (&err, ri_error, OtherError, _("Cannot remove items from a server"));
+ }
g_slist_free_full (list, g_free);
g_slist_free (comp_list);
+ } else {
+ e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
+ if (!mapi_error)
+ g_propagate_error (&err, EDC_ERROR (RepositoryOffline));
+ else
+ mapi_error_to_edc_error (&err, mapi_error, RepositoryOffline, NULL);
+ g_clear_error (&mapi_error);
}
+
g_free (calobj);
if (err)
@@ -2001,21 +2123,25 @@ static void
ecbm_send_objects (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj, GSList **users, gchar **modified_calobj, GError **error)
{
ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
+ EMapiConnection *conn;
icalcomponent_kind kind;
icalcomponent *icalcomp;
GError *mapi_error = NULL;
cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), InvalidArg);
e_return_data_cal_error_if_fail (calobj != NULL, InvalidArg);
- if (!e_backend_get_online (E_BACKEND (backend))) {
- g_propagate_error (error, EDC_ERROR (RepositoryOffline));
+ conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
+ if (!conn) {
+ if (!mapi_error)
+ g_propagate_error (error, EDC_ERROR (RepositoryOffline));
+ else
+ mapi_error_to_edc_error (error, mapi_error, RepositoryOffline, NULL);
+ g_clear_error (&mapi_error);
return;
}
@@ -2136,12 +2262,12 @@ ecbm_send_objects (ECalBackend *backend, EDataCal *cal, GCancellable *cancellabl
cbdata.cleanglobalid = &cleanglobalid;
mid = 0;
- if (e_mapi_connection_open_default_folder (priv->conn, olFolderSentMail, &obj_folder, cancellable, &mapi_error)) {
- e_mapi_connection_create_object (priv->conn, &obj_folder, E_MAPI_CREATE_FLAG_SUBMIT,
+ if (e_mapi_connection_open_default_folder (conn, olFolderSentMail, &obj_folder, cancellable, &mapi_error)) {
+ e_mapi_connection_create_object (conn, &obj_folder, E_MAPI_CREATE_FLAG_SUBMIT,
e_mapi_cal_utils_comp_to_object, &cbdata,
&mid, cancellable, &mapi_error);
- e_mapi_connection_close_folder (priv->conn, &obj_folder, cancellable, &mapi_error);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
}
cbdata.globalid = NULL;
@@ -2153,6 +2279,7 @@ ecbm_send_objects (ECalBackend *backend, EDataCal *cal, GCancellable *cancellabl
if (!mid) {
g_object_unref (comp);
mapi_error_to_edc_error (error, mapi_error, OtherError, _("Failed to create item on a server"));
+ e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
if (mapi_error)
g_error_free (mapi_error);
return;
@@ -2386,19 +2513,25 @@ static void
ecbm_get_free_busy (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const GSList *users, time_t start, time_t end, GSList **freebusy, GError **perror)
{
ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
+ EMapiConnection *conn;
GError *mapi_error = NULL;
cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- if (!priv->conn) {
- g_propagate_error (perror, EDC_ERROR (RepositoryOffline));
+ conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
+
+ if (!conn) {
+ if (!mapi_error)
+ g_propagate_error (perror, EDC_ERROR (RepositoryOffline));
+ else
+ mapi_error_to_edc_error (perror, mapi_error, RepositoryOffline, NULL);
+ g_clear_error (&mapi_error);
return;
}
- if (!e_mapi_cal_utils_get_free_busy_data (priv->conn, users, start, end, freebusy, cancellable, &mapi_error)) {
+ if (!e_mapi_cal_utils_get_free_busy_data (conn, users, start, end, freebusy, cancellable, &mapi_error)) {
mapi_error_to_edc_error (perror, mapi_error, OtherError, _("Failed to get Free/Busy data"));
+ e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
if (mapi_error)
g_error_free (mapi_error);
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index 9143077..70fb211 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -407,13 +407,15 @@ e_mapi_connection_dispose (GObject *object)
static void
e_mapi_connection_finalize (GObject *object)
{
+ EMapiConnection *conn;
EMapiConnectionPrivate *priv;
- priv = E_MAPI_CONNECTION (object)->priv;
+ conn = E_MAPI_CONNECTION (object);
+ priv = conn->priv;
if (priv) {
LOCK_VOID (NULL, NULL);
- disconnect (priv, TRUE);
+ disconnect (priv, TRUE && e_mapi_connection_connected (conn));
g_free (priv->profile);
priv->profile = NULL;
@@ -553,7 +555,8 @@ e_mapi_connection_find (const gchar *profile)
EMapiConnection *conn = E_MAPI_CONNECTION (l->data);
EMapiConnectionPrivate *priv = conn->priv;
- if (priv && priv->profile && g_str_equal (profile, priv->profile))
+ if (priv && priv->profile && g_str_equal (profile, priv->profile) &&
+ e_mapi_connection_connected (conn))
res = conn;
}
@@ -658,7 +661,7 @@ e_mapi_connection_disconnect (EMapiConnection *conn,
LOCK (cancellable, perror, FALSE);
res = priv->session != NULL;
- disconnect (priv, clean);
+ disconnect (priv, clean && e_mapi_connection_connected (conn));
UNLOCK ();
@@ -716,15 +719,53 @@ e_mapi_connection_reconnect (EMapiConnection *conn,
return priv->session != NULL;
}
+static gboolean
+can_reach_mapi_server (const gchar *server_address,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ GNetworkMonitor *network_monitor;
+ GSocketConnectable *connectable;
+ GError *local_error = NULL;
+ gboolean reachable;
+
+ g_return_val_if_fail (server_address != NULL, FALSE);
+
+ network_monitor = g_network_monitor_get_default ();
+ connectable = g_network_address_new (server_address, 135);
+ reachable = g_network_monitor_can_reach (network_monitor, connectable, cancellable, &local_error);
+ g_object_unref (connectable);
+
+ if (!reachable) {
+ if (local_error)
+ g_propagate_error (perror, local_error);
+ else
+ g_set_error (perror, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE, _("Server '%s' cannot be reached"), server_address);
+ }
+
+ return reachable;
+}
+
gboolean
e_mapi_connection_connected (EMapiConnection *conn)
{
/* to have this used in the below macros */
GError **perror = NULL;
+ gboolean res;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- return priv->session != NULL;
+ res = priv->session != NULL;
+ if (res) {
+ struct mapi_profile profile = { 0 };
+
+ if (MAPI_E_SUCCESS == OpenProfile (priv->mapi_ctx, &profile, priv->profile, NULL)) {
+ res = can_reach_mapi_server (profile.server, NULL, perror);
+ ShutDown (&profile);
+ }
+ }
+
+ return res;
}
static gboolean
@@ -6686,33 +6727,6 @@ try_create_profile (ESourceRegistry *registry,
return data.has_profile;
}
-static gboolean
-can_reach_mapi_server (const gchar *server_address,
- GCancellable *cancellable,
- GError **perror)
-{
- GNetworkMonitor *network_monitor;
- GSocketConnectable *connectable;
- GError *local_error = NULL;
- gboolean reachable;
-
- g_return_val_if_fail (server_address != NULL, FALSE);
-
- network_monitor = g_network_monitor_get_default ();
- connectable = g_network_address_new (server_address, 135);
- reachable = g_network_monitor_can_reach (network_monitor, connectable, cancellable, &local_error);
- g_object_unref (connectable);
-
- if (!reachable) {
- if (local_error)
- g_propagate_error (perror, local_error);
- else
- g_set_error (perror, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE, _("Server '%s' cannot be reached"), server_address);
- }
-
- return reachable;
-}
-
static struct mapi_session *
mapi_profile_load (ESourceRegistry *registry,
struct mapi_context *mapi_ctx,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]