[evolution-patches] Fix for calendar loading and some missing items in calendar [exchange calendar]



Hi,
   The patch fixes the GUI locking issue while loading the exchange calendar. The changed events are received from the server in a separate thread. It also fixes the issue of some calendar items missing. Connects a signal handler to get the notification for the changed events in calendar. The GUI still will lock if we have multiple calendars for an account until all the calendars are authenticated, this should be fixed in evolution side as of now since the exchange backend is synchronous.

thanks, Chenthill.
? 327305.diff
? 330663.diff
? a
? aaa
? bak
? cal_loading.diff
? cal_loading1.diff
? core.10695
? core.14292
? core.14760
? core.17665
? core.6673
? depcomp
? evolution-exchange-zip
? patch
? patch_bak
? patch_cal.diff
? temp
? tmp
? calendar/a
? calendar/aa
? calendar/patch_backup
? calendar/temp
? calendar/zz
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-exchange/ChangeLog,v
retrieving revision 1.468
diff -u -p -r1.468 ChangeLog
--- ChangeLog	21 Feb 2006 05:04:35 -0000	1.468
+++ ChangeLog	21 Feb 2006 11:03:17 -0000
@@ -1,3 +1,21 @@
+2006-02-20  Chenthill Palanisamy  <pchenthill novell com>
+
+	* calendar/e-cal-backend-exchange-calendar.c: 
+	(add_ical): Notify the client the if a new object gets created.
+	(get_changed_events): Make it thread safe.
+	(notify_changes): get the change notifications. Do not get notifications 
+	for generated instances.
+	(open_calendar): Check if the client is already loaded, if so return 
+	immediately.
+	(ECalBackendExchangeCalendarPrivate): Added a mutex and a is_loaded variable.
+	(init): Intialiazed mutex and is_loaded variables.
+	* calendar/e-cal-backend-exchange-tasks.c: (get_changed_tasks),
+	(notify_changes), (open_task), (init)
+	(struct _ECalBackendExchangeTasksPrivate): Same as calendar.
+	* calendar/e-cal-backend-exchange.c: 
+	(open_calendar): Check if the calendar is loaded and dont reload again.
+	(init): Intialize cache unseen.
+
 2006-02-21  Sushma Rai  <rsushma novell com>
 
 	* storage/exchange-config-listener.c (exchange_camel_urls_is_equal):
Index: calendar/e-cal-backend-exchange-calendar.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/calendar/e-cal-backend-exchange-calendar.c,v
retrieving revision 1.50
diff -u -p -r1.50 e-cal-backend-exchange-calendar.c
--- calendar/e-cal-backend-exchange-calendar.c	10 Feb 2006 10:10:29 -0000	1.50
+++ calendar/e-cal-backend-exchange-calendar.c	21 Feb 2006 11:03:18 -0000
@@ -39,6 +39,8 @@
 
 struct ECalBackendExchangeCalendarPrivate {
 	int dummy;
+	GMutex *mutex;
+	gboolean is_loaded;
 };
 
 enum {
@@ -171,6 +173,7 @@ add_vevent (ECalBackendExchange *cbex,
 	return (status == GNOME_Evolution_Calendar_Success);
 }
 
+/* Add the event to the cache, Notify the backend if it is sucessfully added */
 static gboolean
 add_ical (ECalBackendExchange *cbex, const char *href, const char *lastmod, 
 	  const char *uid, const char *body, int len, int receipts)
@@ -183,6 +186,7 @@ add_ical (ECalBackendExchange *cbex, con
 	ECalComponent *ecomp;
 	GSList *attachment_list = NULL;
 	gboolean status;
+	ECalBackend *backend = E_CAL_BACKEND (cbex);
 
 	/* Check for attachments */
 	if (uid)
@@ -218,6 +222,11 @@ add_ical (ECalBackendExchange *cbex, con
 			g_object_unref (ecomp);
 		}
 		status = add_vevent (cbex, href, lastmod, icalcomp);
+
+		if (status) {
+			e_cal_backend_notify_object_created (backend, icalcomponent_as_ical_string (icalcomp));
+		}
+
 		icalcomponent_free (icalcomp);
 		return status;
 	} else if (kind != ICAL_VCALENDAR_COMPONENT) {
@@ -241,11 +250,16 @@ add_ical (ECalBackendExchange *cbex, con
 		}
 
 		if (new_comp) {
-			add_vevent (cbex, href, lastmod, new_comp);
+			status = add_vevent (cbex, href, lastmod, new_comp);
+			
+			if (status) {
+				e_cal_backend_notify_object_created (backend, icalcomponent_as_ical_string (new_comp));
+			}
+
 			icalcomponent_free (new_comp);
 		}
 		subcomp = icalcomponent_get_next_component (
-			icalcomp, ICAL_VEVENT_COMPONENT);
+				icalcomp, ICAL_VEVENT_COMPONENT);
 	}
 	icalcomponent_free (icalcomp);
 
@@ -269,7 +283,7 @@ static const char *new_event_properties[
 static const int n_new_event_properties = G_N_ELEMENTS (new_event_properties);
 
 static guint
-get_changed_events (ECalBackendExchange *cbex, const char *since)
+get_changed_events (ECalBackendExchange *cbex)
 {
 	GPtrArray *hrefs;
 	GHashTable *modtimes;
@@ -282,9 +296,13 @@ get_changed_events (ECalBackendExchange 
 	guint status;
 	E2kContext *ctx;
 	int i, status_tracking = EX_NO_RECEIPTS;
+	const char *since = NULL;
+	ECalBackendExchangeCalendar *cbexc = E_CAL_BACKEND_EXCHANGE_CALENDAR (cbex);
 
 	g_return_val_if_fail (E_IS_CAL_BACKEND_EXCHANGE (cbex), SOUP_STATUS_CANCELLED);
 
+	g_mutex_lock (cbexc->priv->mutex);
+
 	rn = e2k_restriction_andv (
 		e2k_restriction_prop_string (E2K_PR_DAV_CONTENT_CLASS,
 					     E2K_RELOP_EQ,
@@ -295,8 +313,6 @@ get_changed_events (ECalBackendExchange 
 			e2k_restriction_prop_int (E2K_PR_CALENDAR_INSTANCE_TYPE,
 						  E2K_RELOP_EQ, cdoMaster),
 			e2k_restriction_prop_int (E2K_PR_CALENDAR_INSTANCE_TYPE,
-						  E2K_RELOP_EQ, cdoInstance),
-			e2k_restriction_prop_int (E2K_PR_CALENDAR_INSTANCE_TYPE,
 						  E2K_RELOP_EQ, cdoException),
 			NULL),
 		NULL);
@@ -367,6 +383,7 @@ get_changed_events (ECalBackendExchange 
 		g_ptr_array_free (hrefs, TRUE);
 		g_hash_table_destroy (modtimes);
 		g_hash_table_destroy (attachments);
+		g_mutex_unlock (cbexc->priv->mutex);
 		return status;
 	}
 
@@ -377,6 +394,8 @@ get_changed_events (ECalBackendExchange 
 		g_ptr_array_free (hrefs, TRUE);
 		g_hash_table_destroy (modtimes);
 		g_hash_table_destroy (attachments);
+		cbexc->priv->is_loaded = TRUE;
+		g_mutex_unlock (cbexc->priv->mutex);
 		return SOUP_STATUS_OK;
 	}
 
@@ -429,17 +448,21 @@ get_changed_events (ECalBackendExchange 
 	if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
 		g_ptr_array_free (hrefs, TRUE);
 		g_hash_table_destroy (modtimes);
+		g_mutex_unlock (cbexc->priv->mutex);
 		return status;
 	}
 	if (!hrefs->len) {
 		g_ptr_array_free (hrefs, TRUE);
 		g_hash_table_destroy (modtimes);
+		cbexc->priv->is_loaded = TRUE;
+		g_mutex_unlock (cbexc->priv->mutex);
 		return SOUP_STATUS_OK;
 	}
 
 	/* Get the remaining ones the hard way */
 	ctx = exchange_account_get_context (cbex->account);
 	if (!ctx) {
+		g_mutex_unlock (cbexc->priv->mutex);
 		/* This either means we lost connection or we are in offline mode */
 		return SOUP_STATUS_CANT_CONNECT;
 	}
@@ -463,15 +486,38 @@ get_changed_events (ECalBackendExchange 
 	g_ptr_array_free (hrefs, TRUE);
 	g_hash_table_destroy (modtimes);
 	g_hash_table_destroy (attachments);
+
+	if (status == SOUP_STATUS_OK)
+		cbexc->priv->is_loaded = TRUE;
+
+	g_mutex_unlock (cbexc->priv->mutex);
 	return status;
 }
 
+/* folder subscription notify callback */
+static void
+notify_changes (E2kContext *ctx, const char *uri,
+                     E2kContextChangeType type, gpointer user_data)
+{
+
+	ECalBackendExchange *ecalbex = E_CAL_BACKEND_EXCHANGE (user_data);
+	
+	g_return_if_fail (E_IS_CAL_BACKEND_EXCHANGE (ecalbex));
+	g_return_if_fail (uri != NULL);
+
+	get_changed_events (ecalbex);
+	
+}
+
 static ECalBackendSyncStatus
 open_calendar (ECalBackendSync *backend, EDataCal *cal,
 	       gboolean only_if_exists,
 	       const char *username, const char *password)
 {
 	ECalBackendSyncStatus status;
+	GThread *thread = NULL;
+	GError *error = NULL;
+	ECalBackendExchangeCalendar *cbexc = E_CAL_BACKEND_EXCHANGE_CALENDAR (backend);
 
 	/* Do the generic part */
 	status = E_CAL_BACKEND_SYNC_CLASS (parent_class)->open_sync (
@@ -483,12 +529,21 @@ open_calendar (ECalBackendSync *backend,
 		return GNOME_Evolution_Calendar_Success;
 	}
 
-	/* Now load the rest of the calendar items */
-	status = get_changed_events (E_CAL_BACKEND_EXCHANGE (backend), NULL);
-	if (status == E2K_HTTP_OK)
+	if (cbexc->priv->is_loaded)
 		return GNOME_Evolution_Calendar_Success;
-	else
-		return GNOME_Evolution_Calendar_OtherError; /* FIXME */
+
+	e_folder_exchange_subscribe (E_CAL_BACKEND_EXCHANGE (backend)->folder,
+                                        E2K_CONTEXT_OBJECT_CHANGED, 30,
+                                        notify_changes, backend);
+
+	thread = g_thread_create ((GThreadFunc) get_changed_events, E_CAL_BACKEND_EXCHANGE (backend), FALSE, &error);
+	if (!thread) {
+		g_warning (G_STRLOC ": %s", error->message);
+		g_error_free (error);
+		
+		return GNOME_Evolution_Calendar_OtherError;
+	}
+	return GNOME_Evolution_Calendar_Success;
 }
 
 struct _cb_data {
@@ -2067,6 +2122,8 @@ static void
 init (ECalBackendExchangeCalendar *cbexc)
 {
 	cbexc->priv = g_new0 (ECalBackendExchangeCalendarPrivate, 1);
+	cbexc->priv->is_loaded = FALSE;
+	cbexc->priv->mutex = g_mutex_new ();
 }
 
 static void
@@ -2080,6 +2137,11 @@ finalize (GObject *object)
 {
 	ECalBackendExchangeCalendar *cbexc =
 		E_CAL_BACKEND_EXCHANGE_CALENDAR (object);
+
+	if (cbexc->priv->mutex) {
+		g_mutex_free (cbexc->priv->mutex);
+		cbexc->priv->mutex = NULL;
+	}
 
 	g_free (cbexc->priv);
 
Index: calendar/e-cal-backend-exchange-tasks.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/calendar/e-cal-backend-exchange-tasks.c,v
retrieving revision 1.20
diff -u -p -r1.20 e-cal-backend-exchange-tasks.c
--- calendar/e-cal-backend-exchange-tasks.c	23 Aug 2005 08:28:24 -0000	1.20
+++ calendar/e-cal-backend-exchange-tasks.c	21 Feb 2006 11:03:18 -0000
@@ -60,6 +60,10 @@ struct _ECalBackendExchangeTasksPrivate 
 	
 	GList *comp;
 
+	GMutex *mutex;
+
+	gboolean is_loaded;
+
 	int dummy;
 };
 
@@ -554,7 +558,7 @@ static const char *task_props[] = {
 static const int n_task_props = sizeof (task_props) / sizeof (task_props[0]);
 
 static guint
-get_changed_tasks (ECalBackendExchange *cbex, const char *since)
+get_changed_tasks (ECalBackendExchange *cbex)
 {
 	ECalBackendExchangeComponent *ecalbexcomp;
 	E2kRestriction *rn;
@@ -574,9 +578,13 @@ get_changed_tasks (ECalBackendExchange *
 	const icaltimezone *itzone;
 	ECalComponentDateTime ecdatetime;
 	icalcomponent *icalcomp;
+	const char *since = NULL;
+	ECalBackendExchangeTasks *cbext = E_CAL_BACKEND_EXCHANGE_TASKS (cbex);
 
         g_return_val_if_fail (E_IS_CAL_BACKEND_EXCHANGE (cbex), SOUP_STATUS_CANCELLED);
 
+	g_mutex_lock (cbext->priv->mutex);
+
 	rn = e2k_restriction_prop_string (E2K_PR_DAV_CONTENT_CLASS,
 					  E2K_RELOP_EQ,
 					  "urn:content-classes:task");
@@ -804,9 +812,17 @@ get_changed_tasks (ECalBackendExchange *
 		}
 		e_cal_component_commit_sequence (ecal);
 		icalcomp = e_cal_component_get_icalcomponent (ecal);
-		if (icalcomp)
-			e_cal_backend_exchange_add_object (cbex, result->href, 
+		if (icalcomp) {
+			gboolean status = FALSE;
+			icalcomponent_kind kind = icalcomponent_isa (icalcomp);
+			
+			status = e_cal_backend_exchange_add_object (cbex, result->href, 
 						modtime, icalcomp);
+
+			if (status && kind == ICAL_VTODO_COMPONENT)
+				e_cal_backend_notify_object_created (E_CAL_BACKEND (cbex), icalcomponent_as_ical_string (icalcomp));
+			
+		}
 	} /* End while */
 	status = e2k_result_iter_free (iter);
 
@@ -814,6 +830,7 @@ get_changed_tasks (ECalBackendExchange *
 		g_ptr_array_free (hrefs, TRUE);
 		g_hash_table_destroy (modtimes);
 		g_hash_table_destroy (attachments);
+		g_mutex_unlock (cbext->priv->mutex);
 		return status;
 	}
 
@@ -824,6 +841,8 @@ get_changed_tasks (ECalBackendExchange *
 		g_ptr_array_free (hrefs, TRUE);
 		g_hash_table_destroy (modtimes);
 		g_hash_table_destroy (attachments);
+		cbext->priv->is_loaded = TRUE;
+		g_mutex_unlock (cbext->priv->mutex);
 		return SOUP_STATUS_OK;
 	}
 	
@@ -861,17 +880,21 @@ get_changed_tasks (ECalBackendExchange *
 	if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
 		g_ptr_array_free (hrefs, TRUE);
 		g_hash_table_destroy (attachments);
+		g_mutex_unlock (cbext->priv->mutex);
 		return status;
 	}
 
 	if (!hrefs->len) {
 		g_ptr_array_free (hrefs, TRUE);
 		g_hash_table_destroy (attachments);
+		cbext->priv->is_loaded = TRUE;
+		g_mutex_unlock (cbext->priv->mutex);
 		return SOUP_STATUS_OK;
 	}
 
 	ctx = exchange_account_get_context (cbex->account);
 	if (!ctx) {
+		g_mutex_unlock (cbext->priv->mutex);
 		/* This either means we lost connection or we are in offline mode */
 		return SOUP_STATUS_CANT_CONNECT;
 	}
@@ -903,6 +926,11 @@ get_changed_tasks (ECalBackendExchange *
 	g_ptr_array_free (hrefs, TRUE);
 	g_hash_table_destroy (modtimes);
 	g_hash_table_destroy (attachments);
+
+	if (status == SOUP_STATUS_OK)
+		cbext->priv->is_loaded = TRUE;
+
+	g_mutex_unlock (cbext->priv->mutex);
 	return status;
 }
 
@@ -917,7 +945,7 @@ notify_changes (E2kContext *ctx, const c
 	g_return_if_fail (E_IS_CAL_BACKEND_EXCHANGE (ecalbex));
 	g_return_if_fail (uri != NULL);
 
-	get_changed_tasks (ecalbex, NULL);
+	get_changed_tasks (ecalbex);
 	
 }
 
@@ -927,6 +955,9 @@ open_task (ECalBackendSync *backend, EDa
 	   const char *username, const char *password)
 {
 	ECalBackendSyncStatus status;
+	GThread *thread = NULL;
+	GError *error = NULL;
+	ECalBackendExchangeTasks *cbext = E_CAL_BACKEND_EXCHANGE_TASKS (backend);
 
 	status = E_CAL_BACKEND_SYNC_CLASS (parent_class)->open_sync (backend,
 				     cal, only_if_exits, username, password);
@@ -937,16 +968,24 @@ open_task (ECalBackendSync *backend, EDa
 		d(printf ("ECBEC : calendar is offline\n"));
 		return GNOME_Evolution_Calendar_Success;
 	}
-
-	status = get_changed_tasks (E_CAL_BACKEND_EXCHANGE (backend), NULL);
-	if (status != E2K_HTTP_OK)
-		return GNOME_Evolution_Calendar_OtherError;
 	
+	if (cbext->priv->is_loaded)
+		return GNOME_Evolution_Calendar_Success;
+
 	/* Subscribe to the folder to notice changes */
         e_folder_exchange_subscribe (E_CAL_BACKEND_EXCHANGE (backend)->folder,
                                         E2K_CONTEXT_OBJECT_CHANGED, 30,
                                         notify_changes, backend);
 
+	thread = g_thread_create ((GThreadFunc) get_changed_tasks, E_CAL_BACKEND_EXCHANGE (backend), FALSE, &error);
+	if (!thread) {
+		g_warning (G_STRLOC ": %s", error->message);
+		g_error_free (error);
+
+		return GNOME_Evolution_Calendar_OtherError;
+	}
+
+
 	return GNOME_Evolution_Calendar_Success;
 }
 
@@ -1312,6 +1351,9 @@ static void
 init (ECalBackendExchangeTasks *cbext)
 {
 	cbext->priv = g_new0 (ECalBackendExchangeTasksPrivate, 1);
+
+	cbext->priv->mutex = g_mutex_new ();
+	cbext->priv->is_loaded = FALSE;
 }
 
 static void
@@ -1325,6 +1367,11 @@ finalize (GObject *object)
 {
 	ECalBackendExchangeTasks *cbext =
 		E_CAL_BACKEND_EXCHANGE_TASKS (object);
+
+	if (cbext->priv->mutex) {
+		g_mutex_free (cbext->priv->mutex);
+		cbext->priv->mutex = NULL;
+	}
 
 	g_free (cbext->priv);
 
Index: calendar/e-cal-backend-exchange.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/calendar/e-cal-backend-exchange.c,v
retrieving revision 1.60
diff -u -p -r1.60 e-cal-backend-exchange.c
--- calendar/e-cal-backend-exchange.c	13 Feb 2006 13:20:18 -0000	1.60
+++ calendar/e-cal-backend-exchange.c	21 Feb 2006 11:03:18 -0000
@@ -322,6 +322,7 @@ open_calendar (ECalBackendSync *backend,
 
 		d(printf ("ECBE : cal is offline .. load cache\n"));
 
+		
 		cbex->priv->read_only = TRUE;
 		source = e_cal_backend_get_source (E_CAL_BACKEND (cbex));
 		display_contents = e_source_get_property (source, "offline_sync");
@@ -340,6 +341,11 @@ open_calendar (ECalBackendSync *backend,
 				cbex->folder = exchange_account_get_folder (cbex->account, uristr);
 			}
 		}
+		
+		if (cbex->priv->is_loaded) {
+			g_mutex_unlock (cbex->priv->open_lock);
+			return GNOME_Evolution_Calendar_Success;
+		}
 
 		euri = e2k_uri_new (uristr);
 		load_status = load_cache (cbex, euri);
@@ -351,6 +357,12 @@ open_calendar (ECalBackendSync *backend,
 		return load_status;
 	}
 		
+	/* What else to check */
+	if (cbex->priv->is_loaded && cbex->account && exchange_account_get_context (cbex->account)) {
+		g_mutex_unlock (cbex->priv->open_lock);
+		return GNOME_Evolution_Calendar_Success;
+	}
+		
 	/* Make sure we have an open connection */
 	/* This steals the ExchangeAccount from ExchangeComponent */
 	cbex->account = exchange_component_get_account_for_uri (global_exchange_component, uristr);
@@ -492,8 +504,23 @@ static void
 uncache (gpointer key, gpointer value, gpointer data)
 {
 	ECalBackendExchange *cbex = data;
+	ECalBackend *backend = E_CAL_BACKEND (cbex);
+	ECalComponentId *id = g_new0 (ECalComponentId, 1);
+	ECalBackendExchangeComponent *ecomp;
 
+	ecomp = (ECalBackendExchangeComponent *)value;
+	
+	/* FIXME Need get the recurrence id here */
+	id->uid = g_strdup (key);
+	id->rid = NULL;
+	if (ecomp->icomp) {
+		/* FIXME somehow the query does not match with the component in some cases, so user needs to press a
+		   clear to get rid of the component from the view in that case*/
+		e_cal_backend_notify_object_removed (backend, id, icalcomponent_as_ical_string (ecomp->icomp)
+				, NULL);
+	}
 	g_hash_table_remove (cbex->priv->objects, key);
+	e_cal_component_free_id (id);
 }
 
 void
@@ -1809,6 +1836,7 @@ init (ECalBackendExchange *cbex)
 
 	cbex->priv->set_lock = g_mutex_new ();
 	cbex->priv->open_lock = g_mutex_new ();
+	cbex->priv->cache_unseen = NULL;
 
 	e_cal_backend_sync_set_lock (E_CAL_BACKEND_SYNC (cbex), TRUE);
 }


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