[evolution-kolab/ek-wip-porting] KolabMailAccess: made API thread-safe



commit f19ea09eed7e39faa1543dabb07ce6cb1656b264
Author: Christian Hilberg <hilberg kernelconcepts de>
Date:   Tue Mar 20 17:39:36 2012 +0100

    KolabMailAccess: made API thread-safe
    
    * we have one E<Cal|Book>BackendKolab instance per ESource
    * there is only one KolabMailAccess instance per Kolab
      account in each of the backend processes
    * if there are multiple Cal|Book backends configured for
      the same Kolab account (though using different folders),
      they will concurrently access the same KolabMailAccess
      instance
    * --> added a sentinel lock to the KolabMailAccess public
      API functions. There may be issues with KolabMailHandle
      references handed out by KolabMailAccess, need to keep
      an eye on that

 src/libekolab/kolab-mail-access.c |  527 +++++++++++++++++++++----------------
 1 files changed, 304 insertions(+), 223 deletions(-)
---
diff --git a/src/libekolab/kolab-mail-access.c b/src/libekolab/kolab-mail-access.c
index 76af5d2..fc4de9f 100644
--- a/src/libekolab/kolab-mail-access.c
+++ b/src/libekolab/kolab-mail-access.c
@@ -65,6 +65,7 @@ struct _KolabMailAccessPrivate
 	GHashTable *stranstbl;
 
 	GHashTable *handles; /* foldername:uid:handle */
+	GMutex *big_lock;
 };
 
 #define KOLAB_MAIL_ACCESS_PRIVATE(obj)  (G_TYPE_INSTANCE_GET_PRIVATE ((obj), KOLAB_TYPE_MAIL_ACCESS, KolabMailAccessPrivate))
@@ -119,6 +120,7 @@ kolab_mail_access_init (KolabMailAccess *object)
 	priv->stranstbl = kolab_mail_access_new_strans_table ();
 
 	priv->handles = NULL;
+	priv->big_lock = g_mutex_new ();
 }
 
 static void
@@ -175,6 +177,11 @@ kolab_mail_access_finalize (GObject *object)
 		g_hash_table_destroy (priv->handles);
 	if (priv->stranstbl)
 		g_hash_table_destroy (priv->stranstbl);
+
+	g_mutex_lock (priv->big_lock);
+	g_mutex_unlock (priv->big_lock);
+	g_mutex_free (priv->big_lock);
+
 	G_OBJECT_CLASS (kolab_mail_access_parent_class)->finalize (object);
 }
 
@@ -1595,7 +1602,7 @@ kolab_mail_access_configure (KolabMailAccess *self,
 	 */
 
 	KolabMailAccessPrivate *priv = NULL;
-	gboolean ok = FALSE;
+	gboolean ok = TRUE;
 	GError *tmp_err = NULL;
 
 	g_assert (KOLAB_IS_MAIL_ACCESS (self));
@@ -1604,17 +1611,20 @@ kolab_mail_access_configure (KolabMailAccess *self,
 
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 
+	g_mutex_lock (priv->big_lock);
+
 	if (priv->state->opmode == KOLAB_MAIL_ACCESS_OPMODE_SHUTDOWN) {
-		g_set_error (err,
+		g_set_error (&tmp_err,
 		             KOLAB_BACKEND_ERROR,
 		             KOLAB_BACKEND_ERROR_STATE_WRONG_FOR_OP,
 		             _("Backend is shutting down"));
-		return FALSE;
+		ok = FALSE;
+		goto exit;
 	}
 
 	/* cannot reconfigure a KolabMailAccess, create a new object instead */
 	if (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_NEW)
-		return TRUE;
+		goto exit;
 
 	if (priv->ksettings == NULL) {
 		g_object_ref (ksettings); /* unref'd in dispose() */
@@ -1624,36 +1634,28 @@ kolab_mail_access_configure (KolabMailAccess *self,
 	ok = kolab_mail_info_db_configure (priv->infodb,
 	                                   priv->ksettings,
 	                                   &tmp_err);
-	if (! ok) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (! ok)
+		goto exit;
 
 	ok = kolab_mail_mime_builder_configure (priv->mimebuilder,
 	                                        priv->ksettings,
 	                                        &tmp_err);
-	if (! ok) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (! ok)
+		goto exit;
 
 	ok = kolab_mail_imap_client_configure (priv->client,
 	                                       priv->ksettings,
 	                                       priv->mimebuilder,
 	                                       &tmp_err);
-	if (! ok) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (! ok)
+		goto exit;
 
 	ok = kolab_mail_side_cache_configure (priv->sidecache,
 	                                      priv->ksettings,
 	                                      priv->mimebuilder,
 	                                      &tmp_err);
-	if (! ok) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (! ok)
+		goto exit;
 
 	ok = kolab_mail_synchronizer_configure (priv->synchronizer,
 	                                        priv->ksettings,
@@ -1662,13 +1664,20 @@ kolab_mail_access_configure (KolabMailAccess *self,
 	                                        priv->sidecache,
 	                                        priv->mimebuilder,
 	                                        &tmp_err);
-	if (! ok) {
+	if (! ok)
+		goto exit;
+
+	priv->state->opmode = KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED;
+
+ exit:
+	if (tmp_err != NULL) {
 		g_propagate_error (err, tmp_err);
-		return FALSE;
+		ok = FALSE;
 	}
 
-	priv->state->opmode = KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED;
-	return TRUE;
+	g_mutex_unlock (priv->big_lock);
+
+	return ok;
 }
 
 
@@ -1732,7 +1741,7 @@ kolab_mail_access_bringup (KolabMailAccess *self,
                            GCancellable *cancellable,
                            GError **err)
 {
-	gboolean ok = FALSE;
+	gboolean ok = TRUE;
 	GError *tmp_err = NULL;
 
 	g_assert (KOLAB_IS_MAIL_ACCESS (self));
@@ -1743,12 +1752,10 @@ kolab_mail_access_bringup (KolabMailAccess *self,
 	                                   KOLAB_MAIL_ACCESS_OPMODE_OFFLINE,
 	                                   cancellable,
 	                                   &tmp_err);
-	if (! ok) {
+	if (tmp_err != NULL)
 		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
 
-	return TRUE;
+	return ok;
 }
 
 /**
@@ -1778,7 +1785,7 @@ kolab_mail_access_shutdown (KolabMailAccess *self,
                             GCancellable *cancellable,
                             GError **err)
 {
-	gboolean ok = FALSE;
+	gboolean ok = TRUE;
 	GError *tmp_err = NULL;
 
 	g_assert (KOLAB_IS_MAIL_ACCESS (self));
@@ -1788,12 +1795,10 @@ kolab_mail_access_shutdown (KolabMailAccess *self,
 	                                   KOLAB_MAIL_ACCESS_OPMODE_SHUTDOWN,
 	                                   cancellable,
 	                                   &tmp_err);
-	if (! ok) {
+	if (tmp_err != NULL)
 		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
 
-	return TRUE;
+	return ok;
 }
 
 /*----------------------------------------------------------------------------*/
@@ -1839,7 +1844,7 @@ kolab_mail_access_set_opmode (KolabMailAccess *self,
 {
 	KolabMailAccessPrivate *priv = NULL;
 	KolabMailAccessStateTransitionFunc strans_fn = NULL;
-	gboolean strans_ok = FALSE;
+	gboolean strans_ok = TRUE;
 	GError *tmp_err = NULL;
 
 	g_assert (KOLAB_IS_MAIL_ACCESS (self));
@@ -1850,25 +1855,25 @@ kolab_mail_access_set_opmode (KolabMailAccess *self,
 
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 
+	g_mutex_lock (priv->big_lock);
+
 	/* check whether we are in required opmode already */
 	if (opmode == priv->state->opmode)
-		return TRUE;
+		goto exit;
 
 	/* get transition function for (current opmode) -> (opmode) */
 	strans_fn = kolab_mail_access_get_strans_func (self, opmode, &tmp_err);
 	if (strans_fn == NULL) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
+		strans_ok = FALSE;
+		goto exit;
 	}
 
 	/* call opmode state transition function */
 	strans_ok = strans_fn (self,
 	                       cancellable,
 	                       &tmp_err);
-	if (! strans_ok) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (! strans_ok)
+		goto exit;
 
 	/* TODO implement me
 	 *
@@ -1890,7 +1895,15 @@ kolab_mail_access_set_opmode (KolabMailAccess *self,
 	 *   CamelKolabSession and CamelKolabIMAPXStore
 	 */
 
-	return TRUE;
+ exit:
+	if (tmp_err != NULL) {
+		g_propagate_error (err, tmp_err);
+		strans_ok = FALSE;
+	}
+
+	g_mutex_unlock (priv->big_lock);
+
+	return strans_ok;
 }
 
 /**
@@ -1909,23 +1922,20 @@ kolab_mail_access_get_opmode (KolabMailAccess *self,
                               GError **err)
 {
 	KolabMailAccessPrivate *priv = NULL;
+	KolabMailAccessOpmodeID opmode = KOLAB_MAIL_ACCESS_OPMODE_INVAL;
 
 	g_assert (KOLAB_IS_MAIL_ACCESS (self));
 	g_return_val_if_fail (err == NULL || *err == NULL, KOLAB_MAIL_ACCESS_OPMODE_INVAL);
 
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 
-	/* TODO
-	 *
-	 * how to remember backend state?
-	 * - store explicitly as private KolabMailAccess property
-	 *   (i.e. quick-check)
-	 * - deduce from CamelKolabSession / CamelKolabIMAPXStore objects
-	 *   (i.e. full-check within KolabMailImapClient)
-	 * - combine both
-	 */
+	g_mutex_lock (priv->big_lock);
+
+	opmode =  priv->state->opmode;
+
+	g_mutex_unlock (priv->big_lock);
 
-	return priv->state->opmode;
+	return opmode;
 }
 
 
@@ -1976,13 +1986,13 @@ kolab_mail_access_query_uids (KolabMailAccess *self,
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 	g_assert (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED);
 
+	g_mutex_lock (priv->big_lock);
+
 	foldername = kolab_mail_access_foldername_new_from_sourcename (self,
 	                                                               sourcename,
 	                                                               &tmp_err);
-	if (foldername == NULL) {
-		g_propagate_error (err, tmp_err);
-		return NULL;
-	}
+	if (foldername == NULL)
+		goto exit;
 
 	/* query KolabMailInfoDb for UIDs */
 	uids = kolab_mail_info_db_query_uids (priv->infodb,
@@ -1991,12 +2001,20 @@ kolab_mail_access_query_uids (KolabMailAccess *self,
 	                                      FALSE,
 	                                      FALSE,
 	                                      &tmp_err);
-	g_free (foldername);
+ exit:
+	if (foldername != NULL)
+		g_free (foldername);
+
 	if (tmp_err != NULL) {
 		g_propagate_error (err, tmp_err);
-		return NULL;
+		if (uids != NULL) {
+			kolab_util_glib_glist_free (uids);
+			uids = NULL;
+		}
 	}
 
+	g_mutex_unlock (priv->big_lock);
+
 	return uids;
 }
 
@@ -2036,7 +2054,7 @@ kolab_mail_access_query_changed_uids (KolabMailAccess *self,
 	KolabMailAccessPrivate *priv = NULL;
 	GList *changed_uids_lst = NULL;
 	gchar *foldername = NULL;
-	gboolean ok = FALSE;
+	gboolean ok = TRUE;
 	GError *tmp_err = NULL;
 
 	g_assert (KOLAB_IS_MAIL_ACCESS (self));
@@ -2048,13 +2066,13 @@ kolab_mail_access_query_changed_uids (KolabMailAccess *self,
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 	g_assert (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED);
 
+	g_mutex_lock (priv->big_lock);
+
 	foldername = kolab_mail_access_foldername_new_from_sourcename (self,
 	                                                               sourcename,
 	                                                               &tmp_err);
-	if (tmp_err != NULL) {
-		g_propagate_error (err, tmp_err);
-		return NULL;
-	}
+	if (tmp_err != NULL)
+		goto exit;
 
 	if (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_OFFLINE) {
 		ok = kolab_mail_synchronizer_info_sync (priv->synchronizer,
@@ -2062,18 +2080,15 @@ kolab_mail_access_query_changed_uids (KolabMailAccess *self,
 		                                        foldername,
 		                                        cancellable,
 		                                        &tmp_err);
-		if (! ok) {
-			g_propagate_error (err, tmp_err);
-			return NULL;
-		}
+		if (! ok)
+			goto exit;
+
 		ok = kolab_mail_access_update_handles_from_infodb (self,
 		                                                   foldername,
 		                                                   sexp,
 		                                                   &tmp_err);
-		if (! ok) {
-			g_propagate_error (err, tmp_err);
-			return NULL;
-		}
+		if (! ok)
+			goto exit;
 	}
 
 	changed_uids_lst = kolab_mail_info_db_query_changed_uids (priv->infodb,
@@ -2081,11 +2096,20 @@ kolab_mail_access_query_changed_uids (KolabMailAccess *self,
 	                                                          sexp,
 	                                                          TRUE,
 	                                                          &tmp_err);
+ exit:
+	if (foldername != NULL)
+		g_free (foldername);
+
 	if (tmp_err != NULL) {
 		g_propagate_error (err, tmp_err);
-		return NULL;
+		if (changed_uids_lst != NULL) {
+			kolab_util_glib_glist_free (changed_uids_lst);
+			changed_uids_lst = NULL;
+		}
 	}
 
+	g_mutex_unlock (priv->big_lock);
+
 	return changed_uids_lst;
 }
 
@@ -2139,14 +2163,14 @@ kolab_mail_access_get_handle (KolabMailAccess *self,
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 	g_assert (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED);
 
+	g_mutex_lock (priv->big_lock);
+
 	/* map Evo calendar name to Kolab folder name */
 	foldername = kolab_mail_access_foldername_new_from_sourcename (self,
 	                                                               sourcename,
 	                                                               &tmp_err);
-	if (tmp_err != NULL) {
-		g_propagate_error (err, tmp_err);
-		return NULL;
-	}
+	if (tmp_err != NULL)
+		goto exit;
 
 	handles_tbl = g_hash_table_lookup (priv->handles, foldername);
 	if (handles_tbl == NULL) {
@@ -2166,17 +2190,16 @@ kolab_mail_access_get_handle (KolabMailAccess *self,
 		                                                         uid,
 		                                                         foldername,
 		                                                         &tmp_err);
-		if (tmp_err != NULL) {
-			g_propagate_error (err, tmp_err);
-			return NULL;
-		}
+		if (tmp_err != NULL)
+			goto exit;
+
 		handle_is_new = TRUE;
 	}
 
 	if (handle == NULL) {
 		g_debug ("%s: UID (%s) Folder (%s) unknown",
 		         __func__, uid, foldername);
-		return NULL;
+		goto exit;
 	}
 
 	if (handle_is_new) {
@@ -2191,11 +2214,20 @@ kolab_mail_access_get_handle (KolabMailAccess *self,
 	/* check whether foldernames match, if handle has one set */
 	if (s_fn != NULL) {
 		if (g_strcmp0 (foldername, s_fn) != 0) {
-			g_free (foldername);
-			return NULL;
+			handle = NULL;
 		}
 	}
-	g_free (foldername);
+
+ exit:
+	if (foldername != NULL)
+		g_free (foldername);
+
+	if (tmp_err != NULL) {
+		g_propagate_error (err, tmp_err);
+		handle = NULL;
+	}
+
+	g_mutex_unlock (priv->big_lock);
 
 	return handle;
 }
@@ -2280,16 +2312,16 @@ kolab_mail_access_store_handle (KolabMailAccess *self,
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 	g_assert (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED);
 
+	g_mutex_lock (priv->big_lock);
+
 	/* folder check */
 
 	/* sourcename data */
 	sourcename_fn = kolab_mail_access_foldername_new_from_sourcename (self,
 	                                                                  sourcename,
 	                                                                  &tmp_err);
-	if (sourcename_fn == NULL) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (sourcename_fn == NULL)
+		goto exit;
 
 	/* handle data */
 	handle_fn = kolab_mail_handle_get_foldername (kmailhandle);
@@ -2305,26 +2337,21 @@ kolab_mail_access_store_handle (KolabMailAccess *self,
 	folder_summary = kolab_mail_info_db_query_folder_summary (priv->infodb,
 	                                                          sourcename_fn,
 	                                                          &tmp_err);
-	if (folder_summary == NULL) {
-		g_free (sourcename_fn);
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (folder_summary == NULL)
+		goto exit;
+
 	sourcename_ft = kolab_folder_summary_get_uint_field (folder_summary,
 	                                                     KOLAB_FOLDER_SUMMARY_UINT_FIELD_FOLDER_TYPE);
-	kolab_folder_summary_free (folder_summary);
-
 	/* folder type check */
 	if ((sourcename_ft < handle_ft) || (sourcename_ft > (handle_ft + 1))) {
-		g_free (sourcename_fn);
-		g_set_error (err,
+		g_set_error (&tmp_err,
 		             KOLAB_BACKEND_ERROR,
 		             KOLAB_BACKEND_ERROR_INTERNAL,
 		             _("PIM Object handle, UID '%s', which has PIM type %i, cannot be stored in folder of mismatching PIM type %i"),
 		             kolab_mail_handle_get_uid (kmailhandle),
 		             handle_ft,
 		             sourcename_ft);
-		return FALSE;
+		goto exit;
 	}
 
 	/* store operation */
@@ -2333,11 +2360,8 @@ kolab_mail_access_store_handle (KolabMailAccess *self,
 	                                    sourcename_fn,
 	                                    cancellable,
 	                                    &tmp_err);
-	g_free (sourcename_fn);
-	if (! ok) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (! ok)
+		goto exit;
 
 	/* handle is now no longer 'complete', Kolab_conv_mail part
 	 * and summary have been ripped out and stored in SideCache/ImapClient
@@ -2353,7 +2377,19 @@ kolab_mail_access_store_handle (KolabMailAccess *self,
 		g_hash_table_remove (handles_tbl, uid);
 	g_free (uid);
 
-	return TRUE;
+ exit:
+	if (sourcename_fn != NULL)
+		g_free (sourcename_fn);
+	if (folder_summary != NULL)
+		kolab_folder_summary_free (folder_summary);
+	if (tmp_err != NULL) {
+		g_propagate_error (err, tmp_err);
+		ok = FALSE;
+	}
+
+	g_mutex_unlock (priv->big_lock);
+
+	return ok;
 }
 
 /**
@@ -2409,30 +2445,29 @@ kolab_mail_access_retrieve_handle (KolabMailAccess *self,
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 	g_assert (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED);
 
+	g_mutex_lock (priv->big_lock);
+
 	/* lookup mail handle in local databases */
 	local_handle = kolab_mail_access_local_handle_get (self,
 	                                                   kmailhandle,
 	                                                   &tmp_err);
-	if (tmp_err != NULL) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (tmp_err != NULL)
+		goto exit;
+
 	if (local_handle == NULL) {
-		g_set_error (err,
+		g_set_error (&tmp_err,
 		             KOLAB_BACKEND_ERROR,
 		             KOLAB_BACKEND_ERROR_INTERNAL,
 		             _("Internal inconsistency detected: Cannot get local PIM Object handle"));
-		return FALSE;
+		goto exit;
 	}
 
 	/* check whether we have a summary for the mail handle */
 	ok = kolab_mail_access_local_handle_attach_summary (self,
 	                                                    local_handle,
 	                                                    &tmp_err);
-	if (! ok) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (! ok)
+		goto exit;
 
 	uid = kolab_mail_handle_get_uid (local_handle);
 
@@ -2444,8 +2479,10 @@ kolab_mail_access_retrieve_handle (KolabMailAccess *self,
 	 * and we're done
 	 */
 	if ((location == KOLAB_OBJECT_CACHE_LOCATION_NONE) &&
-	    kolab_mail_handle_is_complete (local_handle))
-		return TRUE;
+	    kolab_mail_handle_is_complete (local_handle)) {
+		ok = TRUE;
+		goto exit;
+	}
 
 	/* if the handle is cached in the SideCache, we'll retrieve
 	 * this local data (no ImapClient lookup in this case, though
@@ -2456,19 +2493,18 @@ kolab_mail_access_retrieve_handle (KolabMailAccess *self,
 		ok = kolab_mail_side_cache_retrieve (priv->sidecache,
 		                                     local_handle,
 		                                     &tmp_err);
-		if (! ok) {
-			g_propagate_error (err, tmp_err);
-			return FALSE;
-		}
+		if (! ok)
+			goto exit;
+
 		ok = kolab_mail_handle_convert_kconvmail_to_eds (local_handle,
 		                                                 &tmp_err);
-		if (! ok) {
-			g_propagate_error (err, tmp_err);
-			return FALSE;
-		}
+		if (! ok)
+			goto exit;
+
 		g_debug ("%s: UID (%s) data retrieved from side cache",
 		         __func__, uid);
-		return TRUE;
+
+		goto exit;
 	}
 
 	/* if the handle is in the ImapClient cache only, we use this data.
@@ -2483,28 +2519,36 @@ kolab_mail_access_retrieve_handle (KolabMailAccess *self,
 		                                      update,
 		                                      cancellable,
 		                                      &tmp_err);
-		if (! ok) {
-			g_propagate_error (err, tmp_err);
-			return FALSE;
-		}
+		if (! ok)
+			goto exit;
+
 		/* FIXME update InfoDb, we may have a changed folder type
 		 *       (default vs. non-default)
 		 */
 		ok = kolab_mail_handle_convert_kconvmail_to_eds (local_handle,
 		                                                 &tmp_err);
-		if (! ok) {
-			g_propagate_error (err, tmp_err);
-			return FALSE;
-		}
+		if (! ok)
+			goto exit;
+
 		g_debug ("%s: UID (%s) data retrieved from imap client",
 		         __func__, uid);
-		return TRUE;
+
+		goto exit;
 	}
 
 	/* more cache location bit checks could go here */
 
 	g_assert_not_reached (); /* TODO better handling of location bits here */
-	return TRUE;
+
+ exit:
+	if (tmp_err != NULL) {
+		g_propagate_error (err, tmp_err);
+		ok = FALSE;
+	}
+
+	g_mutex_unlock (priv->big_lock);
+
+	return ok;
 }
 
 /**
@@ -2559,20 +2603,21 @@ kolab_mail_access_delete_handle (KolabMailAccess *self,
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 	g_assert (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED);
 
+	g_mutex_lock (priv->big_lock);
+
 	/* lookup mail handle in local databases */
 	local_handle = kolab_mail_access_local_handle_get (self,
 	                                                   kmailhandle,
 	                                                   &tmp_err);
-	if (tmp_err != NULL) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (tmp_err != NULL)
+		goto exit;
+
 	if (local_handle == NULL) {
-		g_set_error (err,
+		g_set_error (&tmp_err,
 		             KOLAB_BACKEND_ERROR,
 		             KOLAB_BACKEND_ERROR_INTERNAL,
 		             _("Internal inconsistency detected: Cannot get local PIM Object handle"));
-		return FALSE;
+		goto exit;
 	}
 
 	uid = g_strdup (kolab_mail_handle_get_uid (local_handle));
@@ -2587,10 +2632,7 @@ kolab_mail_access_delete_handle (KolabMailAccess *self,
 	if (! ok) {
 		g_warning ("%s: UID (%s) Folder (%s) error destroying: %s",
 		           __func__, uid, foldername, tmp_err->message);
-		g_free (uid);
-		g_free (foldername);
-		g_propagate_error (err, tmp_err);
-		return FALSE;
+		goto exit;
 	}
 
 	handles_tbl = g_hash_table_lookup (priv->handles, foldername);
@@ -2599,10 +2641,19 @@ kolab_mail_access_delete_handle (KolabMailAccess *self,
 
 	/* TODO should the deleted UID be recorded in changed_uids_lst? */
 
-	g_free (uid);
-	g_free (foldername);
+ exit:
+	if (uid != NULL)
+		g_free (uid);
+	if (foldername != NULL)
+		g_free (foldername);
+	if (tmp_err != NULL) {
+		g_propagate_error (err, tmp_err);
+		ok = FALSE;
+	}
 
-	return TRUE;
+	g_mutex_unlock (priv->big_lock);
+
+	return ok;
 }
 
 /**
@@ -2636,7 +2687,6 @@ kolab_mail_access_delete_by_uid (KolabMailAccess *self,
 	KolabMailAccessPrivate *priv = NULL;
 	GHashTable *handles_tbl = NULL;
 	KolabMailHandle *local_handle = NULL;
-	gchar *local_uid = NULL;
 	gchar *foldername = NULL;
 	gboolean ok = FALSE;
 	GError *tmp_err = NULL;
@@ -2650,13 +2700,13 @@ kolab_mail_access_delete_by_uid (KolabMailAccess *self,
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 	g_assert (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED);
 
+	g_mutex_lock (priv->big_lock);
+
 	foldername = kolab_mail_access_foldername_new_from_sourcename (self,
 	                                                               sourcename,
 	                                                               &tmp_err);
-	if (tmp_err != NULL) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (tmp_err != NULL)
+		goto exit;
 
 	/* lookup mail handle in local databases */
 	local_handle = kolab_mail_access_local_handle_get_by_uid (self,
@@ -2664,40 +2714,41 @@ kolab_mail_access_delete_by_uid (KolabMailAccess *self,
 	                                                          foldername,
 	                                                          FALSE,
 	                                                          &tmp_err);
-	if (tmp_err != NULL) {
-		g_free (foldername);
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (tmp_err != NULL)
+		goto exit;
+
 	if (local_handle == NULL) {
-		g_free (foldername);
 		g_debug ("%s: UID (%s) no longer exists", __func__, uid);
-		return TRUE;
+		ok = TRUE;
+		goto exit;
 	}
 
-	local_uid = g_strdup (uid);
-
 	/* delete local handle */
 	ok = kolab_mail_access_local_delete (self,
 	                                     local_handle,
 	                                     foldername,
 	                                     cancellable,
 	                                     &tmp_err);
-	if (! ok) {
-		g_free (foldername);
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (! ok)
+		goto exit;
 
 	handles_tbl = g_hash_table_lookup (priv->handles, foldername);
 	if (handles_tbl != NULL)
-		g_hash_table_remove (handles_tbl, local_uid);
-	g_free (local_uid);
-	g_free (foldername);
+		g_hash_table_remove (handles_tbl, uid);
 
 	/* TODO should the deleted UID be recorded in changed_uids_lst? */
 
-	return TRUE;
+ exit:
+	if (foldername != NULL)
+		g_free (foldername);
+	if (tmp_err != NULL) {
+		g_propagate_error (err, tmp_err);
+		ok = FALSE;
+	}
+
+	g_mutex_unlock (priv->big_lock);
+
+	return ok;
 }
 
 /*----------------------------------------------------------------------------*/
@@ -2745,14 +2796,13 @@ kolab_mail_access_query_sources (KolabMailAccess *self,
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 	g_assert (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED);
 
+	g_mutex_lock (priv->big_lock);
+
 	/* query KolabMailInfoDb for existing foldernames in current context */
 	folders = kolab_mail_info_db_query_foldernames (priv->infodb,
 	                                                &tmp_err);
-	if (tmp_err != NULL) {
-		kolab_util_glib_glist_free (folders);
-		g_propagate_error (err, tmp_err);
-		return NULL;
-	}
+	if (tmp_err != NULL)
+		goto exit;
 
 	folders_ptr = folders;
 	while (folders_ptr != NULL) {
@@ -2782,7 +2832,20 @@ kolab_mail_access_query_sources (KolabMailAccess *self,
 		folders_ptr = g_list_next (folders_ptr);
 	}
 
-	kolab_util_glib_glist_free (folders);
+ exit:
+
+	if (folders != NULL)
+		kolab_util_glib_glist_free (folders);
+
+	if (tmp_err != NULL) {
+		g_propagate_error (err, tmp_err);
+		if (sources != NULL) {
+			kolab_util_glib_glist_free (sources);
+			sources = NULL;
+		}
+	}
+
+	g_mutex_unlock (priv->big_lock);
 
 	return sources;
 }
@@ -2818,7 +2881,7 @@ kolab_mail_access_create_source (KolabMailAccess *self,
 	KolabMailAccessPrivate *priv = NULL;
 	gchar *foldername = NULL;
 	gboolean exists = FALSE;
-	gboolean ok = FALSE;
+	gboolean ok = TRUE;
 	GError *tmp_err = NULL;
 
 	g_assert (KOLAB_IS_MAIL_ACCESS (self));
@@ -2829,28 +2892,25 @@ kolab_mail_access_create_source (KolabMailAccess *self,
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 	g_assert (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED);
 
+	g_mutex_lock (priv->big_lock);
+
 	/* map Evo sourcename to Kolab foldername */
 	foldername = kolab_util_backend_foldername_new_from_sourcename (sourcename,
 	                                                                &tmp_err);
-	if (foldername == NULL) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (foldername == NULL)
+		goto exit;
 
 	/* check whether folder exists */
 	exists = kolab_mail_info_db_exists_foldername (priv->infodb,
 	                                               foldername,
 	                                               &tmp_err);
 	if (tmp_err != NULL) {
-		g_free (foldername);
-		g_propagate_error (err, tmp_err);
-		return FALSE;
+		ok = FALSE;
+		goto exit;
 	}
 
-	if (exists) {
-		g_free (foldername);
-		return TRUE;
-	}
+	if (exists)
+		goto exit;
 
 	/* create folder */
 	ok = kolab_mail_access_local_store (self,
@@ -2858,13 +2918,18 @@ kolab_mail_access_create_source (KolabMailAccess *self,
 	                                    foldername,
 	                                    cancellable,
 	                                    &tmp_err);
-	g_free (foldername);
-	if (! ok) {
+ exit:
+	if (foldername != NULL)
+		g_free (foldername);
+
+	if (tmp_err != NULL) {
 		g_propagate_error (err, tmp_err);
-		return FALSE;
+		ok = FALSE;
 	}
 
-	return TRUE;
+	g_mutex_unlock (priv->big_lock);
+
+	return ok;
 }
 
 /**
@@ -2904,7 +2969,7 @@ kolab_mail_access_delete_source (KolabMailAccess *self,
 	KolabMailAccessPrivate *priv = NULL;
 	gchar *foldername = NULL;
 	gboolean exists = FALSE;
-	gboolean ok = FALSE;
+	gboolean ok = TRUE;
 	GError *tmp_err = NULL;
 
 	g_assert (KOLAB_IS_MAIL_ACCESS (self));
@@ -2915,12 +2980,14 @@ kolab_mail_access_delete_source (KolabMailAccess *self,
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 	g_assert (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED);
 
+	g_mutex_lock (priv->big_lock);
+
 	/* map Evo sourcename to Kolab foldername */
 	foldername = kolab_util_backend_foldername_new_from_sourcename (sourcename,
 	                                                                &tmp_err);
 	if (foldername == NULL) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
+		ok = FALSE;
+		goto exit;
 	}
 
 	/* check whether folder exists */
@@ -2928,15 +2995,12 @@ kolab_mail_access_delete_source (KolabMailAccess *self,
 	                                               foldername,
 	                                               &tmp_err);
 	if (tmp_err != NULL) {
-		g_free (foldername);
-		g_propagate_error (err, tmp_err);
-		return FALSE;
+		ok = FALSE;
+		goto exit;
 	}
 
-	if (! exists) {
-		g_free (foldername);
-		return TRUE;
-	}
+	if (! exists)
+		goto exit;
 
 	/* delete folder */
 	ok = kolab_mail_access_local_delete (self,
@@ -2944,13 +3008,18 @@ kolab_mail_access_delete_source (KolabMailAccess *self,
 	                                     foldername,
 	                                     cancellable,
 	                                     &tmp_err);
-	g_free (foldername);
-	if (! ok) {
+ exit:
+	if (foldername != NULL)
+		g_free (foldername);
+
+	if (tmp_err != NULL) {
 		g_propagate_error (err, tmp_err);
-		return FALSE;
+		ok = FALSE;
 	}
 
-	return TRUE;
+	g_mutex_unlock (priv->big_lock);
+
+	return ok;
 }
 
 /**
@@ -2980,6 +3049,7 @@ kolab_mail_access_source_fbtrigger_needed (KolabMailAccess *self,
 	KolabFolderSummary *summary = NULL;
 	KolabFolderTypeID folder_type = KOLAB_FOLDER_TYPE_INVAL;
 	gchar *foldername = NULL;
+	gboolean trigger_needed = FALSE;
 	GError *tmp_err = NULL;
 
 	g_assert (KOLAB_IS_MAIL_ACCESS (self));
@@ -2989,43 +3059,54 @@ kolab_mail_access_source_fbtrigger_needed (KolabMailAccess *self,
 	priv = KOLAB_MAIL_ACCESS_PRIVATE (self);
 	g_assert (priv->state->opmode > KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED);
 
+	g_mutex_lock (priv->big_lock);
+
 	/* do not try to trigger if in offline mode */
 	if (priv->state->opmode <= KOLAB_MAIL_ACCESS_OPMODE_OFFLINE)
-		return FALSE;
+		goto exit;
 
 	/* map Evo sourcename to Kolab foldername */
 	foldername = kolab_util_backend_foldername_new_from_sourcename (sourcename,
 	                                                                &tmp_err);
-	if (foldername == NULL) {
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (foldername == NULL)
+		goto exit;
 
 	/* get folder type */
 	summary = kolab_mail_info_db_query_folder_summary (priv->infodb,
 	                                                   foldername,
 	                                                   &tmp_err);
-	if (summary == NULL) {
-		g_free (foldername);
-		g_propagate_error (err, tmp_err);
-		return FALSE;
-	}
+	if (summary == NULL)
+		goto exit;
+
 	folder_type = kolab_folder_summary_get_uint_field (summary,
 	                                                   KOLAB_FOLDER_SUMMARY_UINT_FIELD_FOLDER_TYPE);
-	kolab_folder_summary_free (summary);
-	g_free (foldername);
-
 	/* F/B triggers only needed for event folders */
 	if (! ((folder_type == KOLAB_FOLDER_TYPE_EVENT) ||
 	       (folder_type == KOLAB_FOLDER_TYPE_EVENT_DEFAULT)))
-		return FALSE;
+		goto exit;
 
 	/* TODO check whether the folder had offline objects which
 	 *      have been synced onto the server (i.e. a trigger
 	 *      does not need to be sent if this is not the case)
 	 */
 
-	return TRUE;
+	trigger_needed = TRUE;
+
+ exit:
+	if (foldername != NULL)
+		g_free (foldername);
+
+	if (summary != NULL)
+		kolab_folder_summary_free (summary);
+
+	if (tmp_err != NULL) {
+		g_propagate_error (err, tmp_err);
+		trigger_needed = FALSE;
+	}
+
+	g_mutex_unlock (priv->big_lock);
+
+	return trigger_needed;
 }
 
 /*----------------------------------------------------------------------------*/



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