[evolution-data-server] ECalBackendStore: Better ensure final save works.



commit 2707aa92740bb6510b6dab4a511f6bfe45adfa4f
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed Jan 9 14:12:53 2013 -0500

    ECalBackendStore: Better ensure final save works.
    
    Collect what we need from ETimezoneCache when we schedule the save
    instead of relying on ETimezoneCache when we actually do the save.

 calendar/libedata-cal/e-cal-backend-store.c |   80 +++++++++++++++++++++------
 1 files changed, 62 insertions(+), 18 deletions(-)
---
diff --git a/calendar/libedata-cal/e-cal-backend-store.c b/calendar/libedata-cal/e-cal-backend-store.c
index cd41f2b..1fa1120 100644
--- a/calendar/libedata-cal/e-cal-backend-store.c
+++ b/calendar/libedata-cal/e-cal-backend-store.c
@@ -62,6 +62,7 @@ struct _ECalBackendStorePrivate {
 
 	guint save_timeout_id;
 	GMutex save_timeout_lock;
+	GList *timezones_to_save;
 };
 
 enum {
@@ -102,6 +103,12 @@ destroy_full_object (FullCompObject *obj)
 }
 
 static void
+cal_backend_store_free_zone (icaltimezone *zone)
+{
+	icaltimezone_free (zone, 1);
+}
+
+static void
 cal_backend_store_add_timezone (ECalBackendStore *store,
                                 icalcomponent *vtzcomp)
 {
@@ -280,39 +287,32 @@ cal_backend_store_scan_vcalendar (ECalBackendStore *store,
 }
 
 static void
-cal_backend_store_save_cache_now (ECalBackendStore *store)
+cal_backend_store_save_cache_now (ECalBackendStore *store,
+                                  GList *timezones_to_save)
 {
-	ETimezoneCache *timezone_cache;
 	GHashTableIter iter;
-	GList *list, *link;
 	icalcomponent *vcalcomp;
 	gchar *data = NULL, *tmpfile;
 	gsize len, nwrote;
 	gpointer value;
 	FILE *f;
 
-	/* Since we only hold a weak reference on the ETimezoneCache,
-	 * make sure we still have it before proceeding.  If we lost
-	 * the ETimezoneCache, abort the save with a console warning
-	 * to avoid wiping out saved time zone data. */
-	timezone_cache = e_cal_backend_store_ref_timezone_cache (store);
-	g_return_if_fail (timezone_cache != NULL);
-
 	g_rw_lock_reader_lock (&store->priv->lock);
 
 	vcalcomp = e_cal_util_new_top_level ();
 
 	/* Add all timezone components. */
-	list = e_timezone_cache_list_timezones (timezone_cache);
-	for (link = list; link != NULL; link = g_list_next (link)) {
-		icaltimezone *tz = link->data;
+	while (timezones_to_save != NULL) {
+		icaltimezone *tz;
 		icalcomponent *tzcomp;
 
+		tz = timezones_to_save->data;
 		tzcomp = icaltimezone_get_component (tz);
 		tzcomp = icalcomponent_new_clone (tzcomp);
 		icalcomponent_add_component (vcalcomp, tzcomp);
+
+		timezones_to_save = g_list_next (timezones_to_save);
 	}
-	g_list_free (list);
 
 	/* Add all non-timezone components. */
 	g_hash_table_iter_init (&iter, store->priv->comp_uid_hash);
@@ -358,7 +358,6 @@ cal_backend_store_save_cache_now (ECalBackendStore *store)
 
 error:
 	g_rw_lock_reader_unlock (&store->priv->lock);
-	g_object_unref (timezone_cache);
 	g_free (tmpfile);
 	g_free (data);
 }
@@ -367,14 +366,21 @@ static gboolean
 cal_backend_store_save_cache_timeout_cb (gpointer user_data)
 {
 	ECalBackendStore *store;
+	GList *timezones_to_save;
 
 	store = E_CAL_BACKEND_STORE (user_data);
 
 	g_mutex_lock (&store->priv->save_timeout_lock);
 	store->priv->save_timeout_id = 0;
+	timezones_to_save = store->priv->timezones_to_save;
+	store->priv->timezones_to_save = NULL;
 	g_mutex_unlock (&store->priv->save_timeout_lock);
 
-	cal_backend_store_save_cache_now (store);
+	cal_backend_store_save_cache_now (store, timezones_to_save);
+
+	g_list_free_full (
+		timezones_to_save,
+		(GDestroyNotify) cal_backend_store_free_zone);
 
 	return FALSE;
 }
@@ -382,6 +388,29 @@ cal_backend_store_save_cache_timeout_cb (gpointer user_data)
 static void
 cal_backend_store_save_cache (ECalBackendStore *store)
 {
+	ETimezoneCache *timezone_cache;
+	GList *list, *link;
+
+	timezone_cache = e_cal_backend_store_ref_timezone_cache (store);
+	g_return_if_fail (timezone_cache != NULL);
+
+	/* Clone the icaltimezone structs in case
+	 * the timeout outlives the ETimezoneCache. */
+	list = e_timezone_cache_list_timezones (timezone_cache);
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		icaltimezone *tz;
+		icalcomponent *tzcomp;
+
+		tz = icaltimezone_new ();
+		tzcomp = icaltimezone_get_component (link->data);
+		tzcomp = icalcomponent_new_clone (tzcomp);
+		icaltimezone_set_component (tz, tzcomp);
+
+		link->data = tz;
+	}
+
+	g_object_unref (timezone_cache);
+
 	g_mutex_lock (&store->priv->save_timeout_lock);
 
 	if (store->priv->save_timeout_id > 0)
@@ -391,6 +420,12 @@ cal_backend_store_save_cache (ECalBackendStore *store)
 		IDLE_SAVE_TIMEOUT_SECONDS,
 		cal_backend_store_save_cache_timeout_cb, store);
 
+	g_list_free_full (
+		store->priv->timezones_to_save,
+		(GDestroyNotify) cal_backend_store_free_zone);
+
+	store->priv->timezones_to_save = list;  /* takes ownership */
+
 	g_mutex_unlock (&store->priv->save_timeout_lock);
 }
 
@@ -477,6 +512,7 @@ cal_backend_store_dispose (GObject *object)
 {
 	ECalBackendStorePrivate *priv;
 	ETimezoneCache *timezone_cache;
+	GList *timezones_to_save = NULL;
 	gboolean save_needed = FALSE;
 
 	priv = E_CAL_BACKEND_STORE_GET_PRIVATE (object);
@@ -486,12 +522,20 @@ cal_backend_store_dispose (GObject *object)
 	if (priv->save_timeout_id > 0) {
 		g_source_remove (priv->save_timeout_id);
 		priv->save_timeout_id = 0;
+		timezones_to_save = priv->timezones_to_save;
+		priv->timezones_to_save = NULL;
 		save_needed = TRUE;
 	}
 	g_mutex_unlock (&priv->save_timeout_lock);
-	if (save_needed)
+
+	if (save_needed) {
 		cal_backend_store_save_cache_now (
-			E_CAL_BACKEND_STORE (object));
+			E_CAL_BACKEND_STORE (object),
+			timezones_to_save);
+		g_list_free_full (
+			timezones_to_save,
+			(GDestroyNotify) cal_backend_store_free_zone);
+	}
 
 	timezone_cache = g_weak_ref_get (&priv->timezone_cache);
 	if (timezone_cache != NULL) {



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