--- evolution-data-server-2.32.1/camel/camel-db.c	2010-09-21 07:21:00.000000000 +0100
+++ /usr/src/packages/BUILD/evolution-data-server-2.32.1/camel/camel-db.c	2011-04-06 10:55:55.457163269 +0100
@@ -41,6 +41,148 @@
 /* how long to wait before invoking sync on the file */
 #define SYNC_TIMEOUT_SECONDS 5
 
+#define READER_LOCK(cdb) e_static_rw_lock_reader_lock (&cdb->priv->rwlock)
+#define READER_UNLOCK(cdb) e_static_rw_lock_reader_unlock (&cdb->priv->rwlock)
+#define WRITER_LOCK(cdb) e_static_rw_lock_writer_lock (&cdb->priv->rwlock)
+#define WRITER_UNLOCK(cdb) e_static_rw_lock_writer_unlock (&cdb->priv->rwlock)
+
+
+/* ARGH ...
+ *   We want a RW lock that is recursive, and whomever owns the write
+ *   lock, implicitly can take a read lock too. FIXME: quite possibly
+ *   we want the write lock to be recursive too - that needs adding,
+ *   with a 'write_counter' as well.
+ */
+typedef struct _EStaticRWLock EStaticRWLock;
+struct _EStaticRWLock
+{
+  /*< private >*/
+  GStaticMutex mutex;
+  GCond *read_cond;
+  GCond *write_cond;
+  guint read_counter;
+  GThread *write_owner;
+  guint want_to_read;
+  guint want_to_write;
+};
+
+#define E_STATIC_RW_LOCK_INIT { G_STATIC_MUTEX_INIT, NULL, NULL, 0, FALSE, 0, 0 }
+
+void      e_static_rw_lock_init           (EStaticRWLock* lock);
+void      e_static_rw_lock_reader_lock    (EStaticRWLock* lock);
+void      e_static_rw_lock_reader_unlock  (EStaticRWLock* lock);
+void      e_static_rw_lock_writer_lock    (EStaticRWLock* lock);
+void      e_static_rw_lock_writer_unlock  (EStaticRWLock* lock);
+void      e_static_rw_lock_free           (EStaticRWLock* lock);
+
+void
+e_static_rw_lock_init (EStaticRWLock* lock)
+{
+  static const EStaticRWLock init_lock = E_STATIC_RW_LOCK_INIT;
+
+  g_return_if_fail (lock);
+
+  *lock = init_lock;
+}
+
+inline static void
+e_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
+{
+  if (!*cond)
+      *cond = g_cond_new ();
+  g_cond_wait (*cond, g_static_mutex_get_mutex (mutex));
+}
+
+inline static void
+e_static_rw_lock_signal (EStaticRWLock* lock)
+{
+  if (lock->want_to_write && lock->write_cond)
+    g_cond_signal (lock->write_cond);
+  else if (lock->want_to_read && lock->read_cond)
+    g_cond_broadcast (lock->read_cond);
+}
+void
+e_static_rw_lock_reader_lock (EStaticRWLock* lock)
+{
+  g_return_if_fail (lock);
+
+  if (!g_threads_got_initialized)
+    return;
+
+  g_static_mutex_lock (&lock->mutex);
+  lock->want_to_read++;
+  if (!lock->write_owner || lock->write_owner != g_thread_self())
+    while (lock->write_owner || lock->want_to_write)
+      e_static_rw_lock_wait (&lock->read_cond, &lock->mutex);
+  lock->want_to_read--;
+  lock->read_counter++;
+  g_static_mutex_unlock (&lock->mutex);
+}
+void
+e_static_rw_lock_reader_unlock  (EStaticRWLock* lock)
+{
+  g_return_if_fail (lock);
+
+  if (!g_threads_got_initialized)
+    return;
+
+  g_static_mutex_lock (&lock->mutex);
+  lock->read_counter--;
+  if (lock->read_counter == 0)
+    e_static_rw_lock_signal (lock);
+  g_static_mutex_unlock (&lock->mutex);
+}
+void
+e_static_rw_lock_writer_lock (EStaticRWLock* lock)
+{
+  g_return_if_fail (lock);
+
+  if (!g_threads_got_initialized)
+    return;
+
+  g_static_mutex_lock (&lock->mutex);
+  lock->want_to_write++;
+  while (lock->write_owner || lock->read_counter)
+    e_static_rw_lock_wait (&lock->write_cond, &lock->mutex);
+  lock->want_to_write--;
+  lock->write_owner = g_thread_self();
+  g_static_mutex_unlock (&lock->mutex);
+}
+void
+e_static_rw_lock_writer_unlock (EStaticRWLock* lock)
+{
+  g_return_if_fail (lock);
+
+  if (!g_threads_got_initialized)
+    return;
+
+  g_static_mutex_lock (&lock->mutex);
+  /* anything else would be bad style - right ? */
+  g_assert (lock->write_owner == g_thread_self());
+  lock->write_owner = NULL;
+  e_static_rw_lock_signal (lock);
+  g_static_mutex_unlock (&lock->mutex);
+}
+void
+e_static_rw_lock_free (EStaticRWLock* lock)
+{
+  g_return_if_fail (lock);
+
+  if (lock->read_cond)
+    {
+      g_cond_free (lock->read_cond);
+      lock->read_cond = NULL;
+    }
+  if (lock->write_cond)
+    {
+      g_cond_free (lock->write_cond);
+      lock->write_cond = NULL;
+    }
+  g_static_mutex_free (&lock->mutex);
+}
+
+
+
 static sqlite3_vfs *old_vfs = NULL;
 
 typedef struct {
@@ -353,14 +495,23 @@
 
 struct _CamelDBPrivate {
 	GTimer *timer;
+	EStaticRWLock rwlock;
 	gchar *file_name;
 };
 
-static GStaticRecMutex trans_lock = G_STATIC_REC_MUTEX_INIT;
-
+/**
+ * cdb_sql_exec 
+ * @db: 
+ * @stmt: 
+ * @error: 
+ * 
+ * Callers should hold the lock
+ **/
 static gint
 cdb_sql_exec (sqlite3 *db,
               const gchar *stmt,
+	      gint (*callback)(void*,gint,gchar**,gchar**),
+	      gpointer data,
               GError **error)
 {
 	gchar *errmsg = NULL;
@@ -368,7 +519,7 @@
 
 	d(g_print("Camel SQL Exec:\n%s\n", stmt));
 
-	ret = sqlite3_exec(db, stmt, 0, 0, &errmsg);
+	ret = sqlite3_exec (db, stmt, callback, data, &errmsg);
 	while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED || ret == -1) {
 		if (errmsg) {
 			sqlite3_free (errmsg);
@@ -476,9 +627,9 @@
 
 	cdb = g_new (CamelDB, 1);
 	cdb->db = db;
-	cdb->lock = g_mutex_new ();
 	cdb->priv = g_new(CamelDBPrivate, 1);
 	cdb->priv->file_name = g_strdup(path);
+	e_static_rw_lock_init (&cdb->priv->rwlock);
 	cdb->priv->timer = NULL;
 	d(g_print ("\nDatabase succesfully opened  \n"));
 
@@ -528,7 +679,9 @@
 {
 	if (cdb) {
 		sqlite3_close (cdb->db);
-		g_mutex_free (cdb->lock);
+		e_static_rw_lock_free (&cdb->priv->rwlock);
+		g_free (cdb->priv->file_name);
+		g_free (cdb->priv);
 		g_free (cdb);
 		d(g_print ("\nDatabase succesfully closed \n"));
 	}
@@ -547,11 +700,11 @@
 		if (!cdb)
 			return 0;
 
-		g_mutex_lock (cdb->lock);
+		WRITER_LOCK (cdb);
 		d(g_print("Creating Collation %s on %s with %p\n", collate, col, (gpointer) func));
 		if (collate && func)
 			ret = sqlite3_create_collation(cdb->db, collate, SQLITE_UTF8,  NULL, func);
-		g_mutex_unlock (cdb->lock);
+		WRITER_UNLOCK (cdb);
 
 		return ret;
 }
@@ -570,12 +723,15 @@
 
 	if (!cdb)
 		return TRUE;
-	g_mutex_lock (cdb->lock);
+	
+	WRITER_LOCK (cdb);
 
 	START(stmt);
-	ret = cdb_sql_exec (cdb->db, stmt, error);
+	ret = cdb_sql_exec (cdb->db, stmt, NULL, NULL, error);
 	END;
-	g_mutex_unlock (cdb->lock);
+	
+	WRITER_UNLOCK (cdb);
+
 
 	return ret;
 }
@@ -591,13 +747,11 @@
 {
 	if (!cdb)
 		return -1;
-	if (g_getenv("SQLITE_TRANSLOCK"))
-		g_static_rec_mutex_lock (&trans_lock);
 
-	g_mutex_lock (cdb->lock);
+	WRITER_LOCK (cdb);
 	STARTTS("BEGIN");
 
-	return (cdb_sql_exec (cdb->db, "BEGIN", error));
+	return (cdb_sql_exec (cdb->db, "BEGIN", NULL, NULL, error));
 }
 
 /**
@@ -613,12 +767,10 @@
 	if (!cdb)
 		return -1;
 
-	ret = cdb_sql_exec (cdb->db, "COMMIT", error);
+	ret = cdb_sql_exec (cdb->db, "COMMIT", NULL, NULL, error);
+	
 	ENDTS;
-	g_mutex_unlock (cdb->lock);
-	if (g_getenv("SQLITE_TRANSLOCK"))
-		g_static_rec_mutex_unlock (&trans_lock);
-
+	WRITER_UNLOCK (cdb);
 	CAMEL_DB_RELEASE_SQLITE_MEMORY;
 
 	return ret;
@@ -635,10 +787,9 @@
 {
 	gint ret;
 
-	ret = cdb_sql_exec (cdb->db, "ROLLBACK", error);
-	g_mutex_unlock (cdb->lock);
-	if (g_getenv("SQLITE_TRANSLOCK"))
-		g_static_rec_mutex_unlock (&trans_lock);
+	ret = cdb_sql_exec (cdb->db, "ROLLBACK", NULL, NULL, error);
+
+	WRITER_UNLOCK (cdb);
 	CAMEL_DB_RELEASE_SQLITE_MEMORY;
 
 	return ret;
@@ -657,7 +808,7 @@
 	if (!cdb)
 		return -1;
 
-	return (cdb_sql_exec (cdb->db, stmt, error));
+	return (cdb_sql_exec (cdb->db, stmt, NULL, NULL, error));
 }
 
 /**
@@ -676,24 +827,25 @@
 	if (!cdb)
 		return -1;
 
-	g_mutex_lock (cdb->lock);
+	WRITER_LOCK (cdb);
+
 	STARTTS("BEGIN");
-	ret = cdb_sql_exec (cdb->db, "BEGIN", error);
+	ret = cdb_sql_exec (cdb->db, "BEGIN", NULL, NULL, error);
 	if (ret)
 		goto end;
 
 	while (qry_list) {
 		query = qry_list->data;
-		ret = cdb_sql_exec (cdb->db, query, error);
+		ret = cdb_sql_exec (cdb->db, query, NULL, NULL, error);
 		if (ret)
 			goto end;
 		qry_list = g_slist_next (qry_list);
 	}
 
-	ret = cdb_sql_exec (cdb->db, "COMMIT", error);
+	ret = cdb_sql_exec (cdb->db, "COMMIT", NULL, NULL, error);
 	ENDTS;
 end:
-	g_mutex_unlock (cdb->lock);
+	WRITER_UNLOCK (cdb);
 	return ret;
 }
 
@@ -723,41 +875,18 @@
                              GError **error)
 {
 	gint ret = -1;
-	gchar *errmsg = NULL;
 
-	g_mutex_lock (cdb->lock);
 
+	READER_LOCK (cdb);
+	
 	START(query);
-	ret = sqlite3_exec(cdb->db, query, count_cb, count, &errmsg);
-	while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED) {
-		if (errmsg) {
-			sqlite3_free (errmsg);
-			errmsg = NULL;
-		}
-
-		ret = sqlite3_exec (cdb->db, query, count_cb, count, &errmsg);
-	}
-
+	ret = cdb_sql_exec (cdb->db, query, count_cb, count, error);
 	END;
 
-	g_mutex_unlock (cdb->lock);
+	READER_UNLOCK (cdb);
 
 	CAMEL_DB_RELEASE_SQLITE_MEMORY;
 
-	if (ret != SQLITE_OK) {
-		d(g_print ("Error in SQL SELECT statement: %s [%s]\n", query, errmsg));
-		g_set_error (
-			error, CAMEL_ERROR,
-			CAMEL_ERROR_GENERIC, "%s", errmsg);
-		sqlite3_free (errmsg);
-		errmsg = NULL;
-	}
-
-	if (errmsg) {
-		sqlite3_free (errmsg);
-		errmsg = NULL;
-	}
-
 	return ret;
 }
 
@@ -949,46 +1078,22 @@
                  gpointer data,
                  GError **error)
 {
-	gchar *errmsg = NULL;
-	/*int nrecs = 0;*/
 	gint ret = -1;
 
 	if (!cdb)
 		return ret;
 
 	d(g_print ("\n%s:\n%s \n", G_STRFUNC, stmt));
-	g_mutex_lock (cdb->lock);
+	READER_LOCK (cdb);
 
 	START(stmt);
-	ret = sqlite3_exec(cdb->db, stmt, callback, data, &errmsg);
-	while (ret == SQLITE_BUSY || ret == SQLITE_LOCKED) {
-		if (errmsg) {
-			sqlite3_free (errmsg);
-			errmsg = NULL;
-		}
-
-		ret = sqlite3_exec (cdb->db, stmt, callback, data, &errmsg);
-	}
-
+	ret = cdb_sql_exec (cdb->db, stmt, callback, data, error);
 	END;
 
-	g_mutex_unlock (cdb->lock);
+	READER_UNLOCK (cdb);
+	
 	CAMEL_DB_RELEASE_SQLITE_MEMORY;
 
-	if (ret != SQLITE_OK) {
-		d(g_warning ("Error in select statement '%s' [%s].\n", stmt, errmsg));
-		g_set_error (
-			error, CAMEL_ERROR,
-			CAMEL_ERROR_GENERIC, "%s", errmsg);
-		sqlite3_free (errmsg);
-		errmsg = NULL;
-	}
-
-	if (errmsg) {
-		sqlite3_free (errmsg);
-		errmsg = NULL;
-	}
-
 	return ret;
 }
 
