[evolution-ews/gnome-3-4] Bug #670458 - Unable to accept meeting request



commit 8efa4ea56c3985b9788aa45a121a4eec4f85b4de
Author: Milan Crha <mcrha redhat com>
Date:   Tue Aug 7 15:21:25 2012 +0200

    Bug #670458 - Unable to accept meeting request

 src/calendar/e-cal-backend-ews.c |  121 ++++++++++++++++++++++++++++++--------
 1 files changed, 96 insertions(+), 25 deletions(-)
---
diff --git a/src/calendar/e-cal-backend-ews.c b/src/calendar/e-cal-backend-ews.c
index 357c148..572aa96 100644
--- a/src/calendar/e-cal-backend-ews.c
+++ b/src/calendar/e-cal-backend-ews.c
@@ -31,6 +31,7 @@
 #include <glib/gi18n-lib.h>
 #include "libedataserver/e-xml-hash-utils.h"
 #include "libedataserver/e-url.h"
+#include "libedataserver/e-flag.h"
 #include <libedata-cal/e-cal-backend-cache.h>
 #include <libedata-cal/e-cal-backend-file-store.h>
 #include <libedata-cal/e-cal-backend-util.h>
@@ -84,7 +85,8 @@ struct _ECalBackendEwsPrivate {
 	GStaticRecMutex rec_mutex;
 	icaltimezone *default_zone;
 	guint refresh_timeout;
-	gboolean refreshing;
+	guint refreshing;
+	EFlag *refreshing_done;
 	GHashTable *item_id_hash;
 
 	ECredentials *credentials;
@@ -670,10 +672,12 @@ e_cal_backend_ews_open_compat (ECalBackend *backend,
 	ret = e_cal_backend_ews_open (backend, cal, opid, cancellable, only_if_exists, user_name,
 				password, &error);
 
-	if (!priv->credentials)
+	if (ret && priv->credentials) {
+		e_cal_backend_notify_readonly (backend, FALSE);
+		e_cal_backend_notify_opened (backend, NULL);
+	} else
 		e_cal_backend_notify_auth_required (backend, TRUE, priv->credentials);
 
-	e_cal_backend_notify_opened (backend, NULL);
 	convert_error_to_edc_error (&error);
 	e_data_cal_respond_open (cal, opid, error);
 }
@@ -707,6 +711,9 @@ e_cal_backend_ews_authenticate_user (ECalBackend *backend,
 	connect_to_server (cbews, e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_USERNAME),
 			   e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_PASSWORD), &error);
 
+	if (!error)
+		e_cal_backend_notify_readonly (backend, FALSE);
+
 	PRIV_UNLOCK (priv);
 
 	convert_error_to_edc_error (&error);
@@ -756,10 +763,28 @@ e_cal_backend_ews_get_object (ECalBackend *backend,
 
 	PRIV_LOCK (priv);
 
+	/* make sure any pending refreshing is done */
+	while (priv->refreshing) {
+		PRIV_UNLOCK (priv);
+		e_flag_wait (priv->refreshing_done);
+		PRIV_LOCK (priv);
+	}
+
 	/* search the object in the cache */
 	comp = e_cal_backend_store_get_component (priv->store, uid, rid);
-	if (comp) {
+	if (!comp) {
+		/* maybe a meeting invitation, for which the calendar item is not downloaded yet,
+		   thus synchronize local cache first */
+		ews_start_sync (cbews);
+
 		PRIV_UNLOCK (priv);
+		e_flag_wait (priv->refreshing_done);
+		PRIV_LOCK (priv);
+
+		comp = e_cal_backend_store_get_component (priv->store, uid, rid);
+	}
+
+	if (comp) {
 		if (e_cal_backend_get_kind (backend) ==
 		    icalcomponent_isa (e_cal_component_get_icalcomponent (comp)))
 			object = e_cal_component_get_as_string (comp);
@@ -770,15 +795,13 @@ e_cal_backend_ews_get_object (ECalBackend *backend,
 
 		if (!object)
 			g_propagate_error (&error, EDC_ERROR (ObjectNotFound));
-		goto exit;
+	} else {
+		g_propagate_error (&error, EDC_ERROR (ObjectNotFound));
 	}
 
 	PRIV_UNLOCK (priv);
 
-	/* callers will never have a uuid that is in server but not in cache */
-	g_propagate_error (&error, EDC_ERROR (ObjectNotFound));
-
-exit:
+ exit:
 	convert_error_to_edc_error (&error);
 	e_data_cal_respond_get_object (cal, context, error, object);
 	g_free (object);
@@ -3256,6 +3279,34 @@ add_item_to_cache (ECalBackendEws *cbews,
 	icalcomponent_free (vcomp);
 }
 
+static void
+ews_refreshing_inc (ECalBackendEws *cbews)
+{
+	PRIV_LOCK (cbews->priv);
+	if (!cbews->priv->refreshing)
+		e_flag_clear (cbews->priv->refreshing_done);
+	cbews->priv->refreshing++;
+	PRIV_UNLOCK (cbews->priv);
+}
+
+static void
+ews_refreshing_dec (ECalBackendEws *cbews)
+{
+	PRIV_LOCK (cbews->priv);
+	if (!cbews->priv->refreshing) {
+		e_flag_set (cbews->priv->refreshing_done);
+		PRIV_UNLOCK (cbews->priv);
+
+		g_warning ("%s: Invalid call, currently not refreshing", G_STRFUNC);
+		return;
+	}
+	cbews->priv->refreshing--;
+	if (!cbews->priv->refreshing) {
+		e_flag_set (cbews->priv->refreshing_done);
+	}
+	PRIV_UNLOCK (cbews->priv);
+}
+
 struct _ews_sync_data {
 	ECalBackendEws *cbews;
 	gchar *sync_state;
@@ -3284,10 +3335,6 @@ ews_cal_get_items_ready_cb (GObject *obj,
 	if (error != NULL) {
 		g_warning ("Unable to get items %s \n", error->message);
 
-		PRIV_LOCK (priv);
-		priv->refreshing = FALSE;
-		PRIV_UNLOCK (priv);
-
 		g_clear_error (&error);
 		goto exit;
 	}
@@ -3308,6 +3355,8 @@ ews_cal_get_items_ready_cb (GObject *obj,
 			sub_sync_data->cbews = g_object_ref (sync_data->cbews);
 			sub_sync_data->master_uid = g_strdup (item_id->id);
 
+			ews_refreshing_inc (cbews);
+
 			e_ews_connection_get_items_start (g_object_ref (cnc), EWS_PRIORITY_MEDIUM,
 					modified_occurrences,
 					"IdOnly", "item:Attachments item:HasAttachments item:MimeContent calendar:TimeZone calendar:UID calendar:Resources calendar:ModifiedOccurrences calendar:RequiredAttendees calendar:OptionalAttendees",
@@ -3332,7 +3381,8 @@ ews_cal_get_items_ready_cb (GObject *obj,
 
 	if (sync_data->sync_state)
 		e_cal_backend_store_put_key_value (priv->store, SYNC_KEY, sync_data->sync_state);
-	if (sync_data->sync_pending)
+	if (sync_data->sync_pending) {
+		ews_refreshing_inc (cbews);
 		e_ews_connection_sync_folder_items_start
 						(g_object_ref (priv->cnc), EWS_PRIORITY_MEDIUM,
 						 sync_data->sync_state, priv->folder_id,
@@ -3340,8 +3390,11 @@ ews_cal_get_items_ready_cb (GObject *obj,
 						 EWS_MAX_FETCH_COUNT,
 						 ews_cal_sync_items_ready_cb,
 						 NULL, g_object_ref (cbews));
+	}
+
+ exit:
+	ews_refreshing_dec (cbews);
 
-exit:
 	g_object_unref (sync_data->cbews);
 	g_free (sync_data->master_uid);
 	g_free (sync_data->sync_state);
@@ -3379,9 +3432,7 @@ ews_cal_sync_items_ready_cb (GObject *obj,
 	if (error != NULL) {
 		g_warning ("Unable to Sync changes %s \n", error->message);
 
-		PRIV_LOCK (priv);
-		priv->refreshing = FALSE;
-		PRIV_UNLOCK (priv);
+		ews_refreshing_dec (cbews);
 
 		g_clear_error (&error);
 		g_object_unref (cbews);
@@ -3424,6 +3475,7 @@ ews_cal_sync_items_ready_cb (GObject *obj,
 
 	if (!cal_item_ids && !task_item_ids && !includes_last_item) {
 		e_cal_backend_store_put_key_value (priv->store, SYNC_KEY, sync_state);
+		ews_refreshing_inc (cbews);
 		e_ews_connection_sync_folder_items_start
 						(g_object_ref (priv->cnc), EWS_PRIORITY_MEDIUM,
 						 sync_state, priv->folder_id,
@@ -3442,7 +3494,8 @@ ews_cal_sync_items_ready_cb (GObject *obj,
 		sync_data->sync_pending = !includes_last_item;
 	}
 
-	if (cal_item_ids)
+	if (cal_item_ids) {
+		ews_refreshing_inc (cbews);
 		e_ews_connection_get_items_start (cnc,
 						  EWS_PRIORITY_MEDIUM,
 						  cal_item_ids,
@@ -3452,8 +3505,10 @@ ews_cal_sync_items_ready_cb (GObject *obj,
 						  ews_cal_get_items_ready_cb,
 						  NULL, NULL, NULL,
 						  (gpointer) sync_data);
+	}
 
-	if (task_item_ids)
+	if (task_item_ids) {
+		ews_refreshing_inc (cbews);
 		e_ews_connection_get_items_start (cnc, EWS_PRIORITY_MEDIUM,
 						  task_item_ids,
 						  "AllProperties",
@@ -3463,6 +3518,7 @@ ews_cal_sync_items_ready_cb (GObject *obj,
 						  ews_cal_get_items_ready_cb,
 						  NULL, NULL, NULL,
 						  (gpointer) sync_data);
+	}
 
 exit:
 	if (cal_item_ids) {
@@ -3481,6 +3537,8 @@ exit:
 	if (items_deleted)
 		g_slist_free (items_deleted);
 
+	ews_refreshing_dec (cbews);
+
 	g_object_unref (cbews);
 }
 
@@ -3494,10 +3552,7 @@ ews_start_sync_thread (gpointer data)
 	cbews = (ECalBackendEws *) data;
 	priv = cbews->priv;
 
-	PRIV_LOCK (priv);
-	priv->refreshing = TRUE;
-	PRIV_UNLOCK (priv);
-
+	/* ews_refreshing_inc() is called within ews_start_sync() */
 	sync_state = e_cal_backend_store_get_key_value (priv->store, SYNC_KEY);
 	e_ews_connection_sync_folder_items_start
 						(priv->cnc, EWS_PRIORITY_MEDIUM,
@@ -3515,11 +3570,21 @@ ews_start_sync_thread (gpointer data)
 static gboolean
 ews_start_sync (gpointer data)
 {
+	ECalBackendEws *cbews = data;
 	GThread *thread;
 
+	PRIV_LOCK (cbews->priv);
+	if (cbews->priv->refreshing) {
+		PRIV_UNLOCK (cbews->priv);
+		return TRUE;
+	}
+
+	ews_refreshing_inc (cbews);
+	PRIV_UNLOCK (cbews->priv);
+
 	/* run the actual operation in thread,
 	   to not block main thread of the factory */
-	thread = g_thread_new (NULL, ews_start_sync_thread, g_object_ref (data));
+	thread = g_thread_new (NULL, ews_start_sync_thread, g_object_ref (cbews));
 	g_thread_unref (thread);
 
 	return TRUE;
@@ -3940,6 +4005,11 @@ e_cal_backend_ews_finalize (GObject *object)
 	e_credentials_free (priv->credentials);
 	priv->credentials = NULL;
 
+	if (priv->refreshing_done) {
+		e_flag_free (priv->refreshing_done);
+		priv->refreshing_done = NULL;
+	}
+
 	g_free (priv);
 	cbews->priv = NULL;
 
@@ -3957,6 +4027,7 @@ e_cal_backend_ews_init (ECalBackendEws *cbews)
 
 	/* create the mutex for thread safety */
 	g_static_rec_mutex_init (&priv->rec_mutex);
+	priv->refreshing_done = e_flag_new ();
 	priv->item_id_hash = g_hash_table_new_full
 						(g_str_hash, g_str_equal,
 						 (GDestroyNotify) g_free,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]