[evolution-patches] patch for #59904 (calendar)



This makes ECal use a cache of queries, so that we don't have to run
them over and over again. I've seen a lot of speed improvements in the
local calendars, not that much in the DVD movies file (mentioned in the
bug), so I'm still looking at fixing that, but this should make things
much quicker for most users
-- 
Rodrigo Moya <rodrigo novell com>
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/ChangeLog,v
retrieving revision 1.305
diff -u -p -r1.305 ChangeLog
--- ChangeLog	3 Aug 2004 06:25:57 -0000	1.305
+++ ChangeLog	3 Aug 2004 12:45:56 -0000
@@ -1,3 +1,23 @@
+2004-08-03  Rodrigo Moya <rodrigo novell com>
+
+	Fixes #59904
+
+	* libecal/e-cal-view.c (e_cal_view_init): create a hash table to
+	store the matched objects.
+	(e_cal_view_finalize): destroy the new hash table.
+	(objects_added_cb, objects_modified_cb, objects_removed_cb): update
+	the internal list of objects.
+	(view_done_cb): keep track of whether the view has been done yet.
+	(e_cal_view_start): if the query was already started, notify of the
+	matched objects.
+
+	* libecal/e-cal.c: keep a list of live queries, to easily re-use them.
+	(e_cal_init): create the live queries hash table.
+	(e_cal_finalize): destroy the live queries hash table.
+	(free_live_query): new function.
+	(e_cal_get_query): try to reuse queries when available. Fixed return
+	values in g_return_val_if_fail() calls.
+
 2004-08-03  Harish Krishnaswamy  <kharish novell com>
 
 	* backends/groupwise/e-cal-backend-groupwise-utils.c:
Index: libecal/e-cal.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/libecal/e-cal.c,v
retrieving revision 1.69
diff -u -p -r1.69 e-cal.c
--- libecal/e-cal.c	30 Jul 2004 12:30:43 -0000	1.69
+++ libecal/e-cal.c	3 Aug 2004 12:45:57 -0000
@@ -96,6 +96,9 @@ struct _ECalPrivate {
 	   them repeatedly for each get_object() call. */
 	GHashTable *timezones;
 
+	/* A list of all the live queries we have around, to be able to reuse them */
+	GHashTable *live_queries;
+
 	/* The default timezone to use to resolve DATE and floating DATE-TIME
 	   values. */
 	icaltimezone *default_zone;
@@ -1075,6 +1078,7 @@ e_cal_init (ECal *ecal, ECalClass *klass
 	priv->capabilities = FALSE;
 	priv->factories = NULL;
 	priv->timezones = g_hash_table_new (g_str_hash, g_str_equal);
+	priv->live_queries = g_hash_table_new (g_str_hash, g_str_equal);
 	priv->default_zone = icaltimezone_get_utc_timezone ();
 	priv->comp_listener = NULL;
 
@@ -1104,6 +1108,14 @@ e_cal_init (ECal *ecal, ECalClass *klass
 	g_signal_connect (G_OBJECT (priv->listener), "backend_error", G_CALLBACK (backend_error_cb), ecal);
 }
 
+/* Callback function from g_hash_table_foreach to free individual live queries */
+static void
+free_live_query (gpointer key, gpointer value, gpointer user_data)
+{
+	g_free (key);
+	g_object_unref (value);
+}
+
 /* Finalize handler for the calendar ecal */
 static void
 e_cal_finalize (GObject *object)
@@ -1173,6 +1185,10 @@ e_cal_finalize (GObject *object)
 	g_hash_table_destroy (priv->timezones);
 	priv->timezones = NULL;
 
+	g_hash_table_foreach (priv->live_queries, free_live_query, NULL);
+	g_hash_table_destroy (priv->live_queries);
+	priv->live_queries = NULL;
+
 	g_free (priv);
 	ecal->priv = NULL;
 
@@ -4081,9 +4097,17 @@ e_cal_get_query (ECal *ecal, const char 
 	ECalendarOp *our_op;
 	ECalendarStatus status;
 
-	e_return_error_if_fail (ecal && E_IS_CAL (ecal), E_CALENDAR_STATUS_INVALID_ARG);
-	e_return_error_if_fail (query, E_CALENDAR_STATUS_INVALID_ARG);
+	e_return_error_if_fail (ecal && E_IS_CAL (ecal), FALSE);
+	e_return_error_if_fail (query, FALSE);
+
+	/* Search the live queries hash table */
+	*query = g_hash_table_lookup (ecal->priv->live_queries, sexp);
+	if (*query) {
+		g_object_ref (*query);
+		return TRUE;
+	}
 
+	/* Query not available, so create a new one */
 	g_mutex_lock (ecal->priv->mutex);
 
 	if (ecal->priv->load_state != E_CAL_LOAD_LOADED) {
@@ -4127,9 +4151,13 @@ e_cal_get_query (ECal *ecal, const char 
 
 	status = our_op->status;
 	*query = our_op->query;
+	if (status == E_CALENDAR_STATUS_OK) {
+		/* add the query to our cache */
+		g_hash_table_insert (ecal->priv->live_queries, g_strdup (sexp), g_object_ref (*query));
+	}
 
 	bonobo_object_unref (BONOBO_OBJECT (our_op->listener));
-	
+
 	e_calendar_remove_op (ecal, our_op);
 	g_mutex_unlock (our_op->mutex);
 	e_calendar_free_op (our_op);
Index: libecal/e-cal-view.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/libecal/e-cal-view.c,v
retrieving revision 1.2
diff -u -p -r1.2 e-cal-view.c
--- libecal/e-cal-view.c	11 Nov 2003 01:34:46 -0000	1.2
+++ libecal/e-cal-view.c	3 Aug 2004 12:45:57 -0000
@@ -41,6 +41,11 @@ struct _ECalViewPrivate {
 
 	/* The CalClient associated with this view */
 	ECal *client;
+
+	gboolean already_started;
+	gboolean already_done;
+	ECalendarStatus done_status;
+	GHashTable *matched_objects;
 };
 
 /* Property IDs */
@@ -71,9 +76,17 @@ static void
 objects_added_cb (ECalViewListener *listener, GList *objects, gpointer data)
 {
 	ECalView *view;
+	GList *l;
 
 	view = E_CAL_VIEW (data);
 
+	/* update the list of objects */
+	for (l = objects; l != NULL; l = l->next) {
+		g_hash_table_insert (view->priv->matched_objects,
+				     g_strdup (icalcomponent_get_uid (l->data)),
+				     icalcomponent_new_clone (l->data));
+	}
+
 	g_signal_emit (G_OBJECT (view), signals[OBJECTS_ADDED], 0, objects);
 }
 
@@ -81,9 +94,25 @@ static void
 objects_modified_cb (ECalViewListener *listener, GList *objects, gpointer data)
 {
 	ECalView *view;
+	GList *l;
 
 	view = E_CAL_VIEW (data);
 
+	for (l = objects; l != NULL; l = l->next) {
+		gpointer orig_key, orig_value;
+
+		if (g_hash_table_lookup_extended (view->priv->matched_objects, icalcomponent_get_uid (l->data),
+						  &orig_key, &orig_value)) {
+			g_hash_table_remove (view->priv->matched_objects, orig_key);
+			g_free (orig_key);
+			icalcomponent_free (orig_value);
+		}
+
+		g_hash_table_insert (view->priv->matched_objects,
+				     g_strdup (icalcomponent_get_uid (l->data)),
+				     icalcomponent_new_clone (l->data));
+	}
+
 	g_signal_emit (G_OBJECT (view), signals[OBJECTS_MODIFIED], 0, objects);
 }
 
@@ -91,9 +120,21 @@ static void
 objects_removed_cb (ECalViewListener *listener, GList *uids, gpointer data)
 {
 	ECalView *view;
+	GList *l;
 
 	view = E_CAL_VIEW (data);
 
+	for (l = uids; l != NULL; l = l->next) {
+		gpointer orig_key, orig_value;
+
+		if (g_hash_table_lookup_extended (view->priv->matched_objects, l->data,
+						  &orig_key, &orig_value)) {
+			g_hash_table_remove (view->priv->matched_objects, orig_key);
+			g_free (orig_key);
+			icalcomponent_free (orig_value);
+		}
+	}
+
 	g_signal_emit (G_OBJECT (view), signals[OBJECTS_REMOVED], 0, uids);
 }
 
@@ -113,6 +154,8 @@ view_done_cb (ECalViewListener *listener
 	ECalView *view;
 
 	view = E_CAL_VIEW (data);
+	view->priv->already_done = TRUE;
+	view->priv->done_status = status;
 
 	g_signal_emit (G_OBJECT (view), signals[VIEW_DONE], 0, status);
 }
@@ -128,6 +171,10 @@ e_cal_view_init (ECalView *view, ECalVie
 
 	priv->listener = NULL;
 	priv->view = CORBA_OBJECT_NIL;
+
+	priv->already_started = FALSE;
+	priv->already_done = FALSE;
+	priv->matched_objects = g_hash_table_new (g_str_hash, g_str_equal);
 }
 
 static void
@@ -191,6 +238,12 @@ e_cal_view_get_property (GObject *object
 	}
 }
 
+static void
+free_matched_object (gpointer key, gpointer value, gpointer user_data)
+{
+	g_free (key);
+	icalcomponent_free (value);
+}
 
 /* Finalize handler for the calendar view */
 static void
@@ -212,6 +265,10 @@ e_cal_view_finalize (GObject *object)
 	if (priv->view != CORBA_OBJECT_NIL)
 		bonobo_object_release_unref (priv->view, NULL);
 
+	g_hash_table_foreach (priv->matched_objects, free_matched_object, NULL);
+	g_hash_table_destroy (priv->matched_objects);
+	priv->matched_objects = NULL;
+
 	g_free (priv);
 
 	if (G_OBJECT_CLASS (parent_class)->finalize)
@@ -354,6 +411,14 @@ e_cal_view_get_client (ECalView *view)
 	return view->priv->client;
 }
 
+static void
+add_matched_object (gpointer key, gpointer value, gpointer user_data)
+{
+	GList **objects = user_data;
+
+	*objects = g_list_append (*objects, value);
+}
+
 void
 e_cal_view_start (ECalView *view)
 {
@@ -364,12 +429,27 @@ e_cal_view_start (ECalView *view)
 	g_return_if_fail (E_IS_CAL_VIEW (view));
 	
 	priv = view->priv;
-	
-	CORBA_exception_init (&ev);
 
-	GNOME_Evolution_Calendar_CalView_start (priv->view, &ev);
-	if (BONOBO_EX (&ev)) 
-		g_warning (G_STRLOC ": Unable to start view");
+	/* if the query was already started, notify of the matched objects */
+	if (priv->already_started) {
+		GList *objects = NULL;
+
+		g_hash_table_foreach (priv->matched_objects, (GHFunc) add_matched_object, &objects);
+		g_signal_emit (G_OBJECT (view), signals[OBJECTS_ADDED], 0, objects);
+
+		/* if the query was done, notify that also */
+		if (priv->already_done)
+			g_signal_emit (G_OBJECT (view), signals[VIEW_DONE], 0, priv->done_status);
+
+		g_list_free (objects);
+	} else {
+		priv->already_started = TRUE;
+		CORBA_exception_init (&ev);
+
+		GNOME_Evolution_Calendar_CalView_start (priv->view, &ev);
+		if (BONOBO_EX (&ev)) 
+			g_warning (G_STRLOC ": Unable to start view");
 
-	CORBA_exception_free (&ev);
+		CORBA_exception_free (&ev);
+	}
 }


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