[evolution-patches] Fix for calendar loading and some missing items in calendar [exchange calendar]
- From: pchenthill <pchenthill novell com>
- To: patches <evolution-patches gnome org>
- Subject: [evolution-patches] Fix for calendar loading and some missing items in calendar [exchange calendar]
- Date: Tue, 21 Feb 2006 16:48:36 +0530
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]