[evolution-data-server] Bug 640054 - CamelDB: do not read the db while a trasaction is in progress. Fix the dead-lock cause



commit c5348d470881ed5da94462f23e354c70c5b2f4cb
Author: Chenthill Palanisamy <pchenthill novell com>
Date:   Thu May 26 15:56:07 2011 +0530

    Bug 640054 - CamelDB: do not read the db while a trasaction is in progress.
     Fix the dead-lock caused due to transaction (DB WRITE_LOCK) and summary lock.

 camel/camel-db.c             |   33 ++++++++++++++++++++++++++++-----
 camel/camel-folder-summary.c |   27 +++++++++++++--------------
 2 files changed, 41 insertions(+), 19 deletions(-)
---
diff --git a/camel/camel-db.c b/camel/camel-db.c
index 35edacb..968cc27 100644
--- a/camel/camel-db.c
+++ b/camel/camel-db.c
@@ -1573,21 +1573,44 @@ camel_db_prepare_message_info_table (CamelDB *cdb,
                                      GError **error)
 {
 	gint ret, current_version;
+	GError *err = NULL;
 
 	/* Make sure we have the table already */
-	ret = camel_db_create_message_info_table (cdb, folder_name, error);
+	camel_db_begin_transaction (cdb, &err);
+	ret = camel_db_create_message_info_table (cdb, folder_name, &err);
+	if (err)
+		goto exit;
+
+	camel_db_end_transaction (cdb, &err);
 
 	/* Migration stage zero: version fetch */
-	current_version = camel_db_get_folder_version (cdb, folder_name, error);
+	current_version = camel_db_get_folder_version (cdb, folder_name, &err);
 
+	camel_db_begin_transaction (cdb, &err);
+	
 	/* Migration stage one: storing the old data if necessary */
-	ret = camel_db_migrate_folder_prepare (cdb, folder_name, current_version, error);
+	ret = camel_db_migrate_folder_prepare (cdb, folder_name, current_version, &err);
+	if (err)
+		goto exit;
 
 	/* Migration stage two: rewriting the old data if necessary */
-	ret = camel_db_migrate_folder_recreate (cdb, folder_name, current_version, error);
+	ret = camel_db_migrate_folder_recreate (cdb, folder_name, current_version, &err);
+	if (err)
+		goto exit;
 
 	/* Final step: (over)write the current version label */
-	ret = camel_db_write_folder_version (cdb, folder_name, current_version, error);
+	ret = camel_db_write_folder_version (cdb, folder_name, current_version, &err);
+	if (err)
+		goto exit;
+	
+	camel_db_end_transaction (cdb, &err);
+
+exit:
+	if (err && cdb->priv->transaction_is_on)
+		camel_db_abort_transaction (cdb, NULL);
+	
+	if (err)
+		g_propagate_error (error, err);
 
 	return ret;
 }
diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c
index 6b701ce..563dcd9 100644
--- a/camel/camel-folder-summary.c
+++ b/camel/camel-folder-summary.c
@@ -2146,11 +2146,15 @@ save_message_infos_to_db (CamelFolderSummary *s,
 		return -1;
 
 	camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+	
 	/* Push MessageInfo-es */
+	camel_db_begin_transaction (cdb, NULL);
 	g_hash_table_foreach (s->loaded_infos, save_to_db_cb, &args);
+	camel_db_end_transaction (cdb, NULL);
+	
 	camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
-/* FIXME[disk-summary] make sure we free the message infos that are loaded
- * are freed if not used anymore or should we leave that to the timer? */
+	/* FIXME[disk-summary] make sure we free the message infos that are loaded
+	 * are freed if not used anymore or should we leave that to the timer? */
 
 	return 0;
 }
@@ -2190,12 +2194,14 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s,
 
 	d(printf ("\ncamel_folder_summary_save_to_db called \n"));
 	if (s->priv->need_preview && g_hash_table_size (s->priv->preview_updates)) {
-		camel_db_begin_transaction (parent_store->cdb_w, NULL);
 		camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
+		
+		camel_db_begin_transaction (parent_store->cdb_w, NULL);
 		g_hash_table_foreach (s->priv->preview_updates, (GHFunc) msg_save_preview, s->folder);
 		g_hash_table_remove_all (s->priv->preview_updates);
-		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 		camel_db_end_transaction (parent_store->cdb_w, NULL);
+		
+		camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 	}
 
 	s->flags &= ~CAMEL_SUMMARY_DIRTY;
@@ -2204,11 +2210,8 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s,
 	if (!count)
 		return camel_folder_summary_header_save_to_db (s, error);
 
-	camel_db_begin_transaction (cdb, NULL);
-
 	ret = save_message_infos_to_db (s, FALSE, error);
 	if (ret != 0) {
-		camel_db_abort_transaction (cdb, NULL);
 		/* Failed, so lets reset the flag */
 		s->flags |= CAMEL_SUMMARY_DIRTY;
 		return -1;
@@ -2220,25 +2223,21 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s,
 		strstr ((*error)->message, "26 columns but 28 values") != NULL) {
 		const gchar *full_name;
 
-		/* This is an error is previous migration. Let remigrate this folder alone. */
-		camel_db_abort_transaction (cdb, NULL);
 		full_name = camel_folder_get_full_name (s->folder);
-		camel_db_reset_folder_version (cdb, full_name, 0, NULL);
 		g_warning ("Fixing up a broken summary migration on %s\n", full_name);
+		
 		/* Begin everything again. */
 		camel_db_begin_transaction (cdb, NULL);
+		camel_db_reset_folder_version (cdb, full_name, 0, NULL);
+		camel_db_end_transaction (cdb, NULL);
 
 		ret = save_message_infos_to_db (s, FALSE, error);
 		if (ret != 0) {
-			camel_db_abort_transaction (cdb, NULL);
-			/* Failed, so lets reset the flag */
 			s->flags |= CAMEL_SUMMARY_DIRTY;
 			return -1;
 		}
 	}
 
-	camel_db_end_transaction (cdb, NULL);
-
 	record = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->summary_header_to_db (s, error);
 	if (!record) {
 		s->flags |= CAMEL_SUMMARY_DIRTY;



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