[evolution-data-server] addressbook file backend: libdb must be initialized for concurrent read/write



commit faada76f22cd192252b9f052183e9f1544a6da04
Author: Patrick Ohly <patrick ohly intel com>
Date:   Mon May 16 11:21:04 2011 +0200

    addressbook file backend: libdb must be initialized for concurrent read/write
    
    Very bad performance (100% CPU load, several minutes run time) were
    seen for multiple concurrent writes. gdb shows that libdb is
    apparently busy polling while writing.
    
    The libdb API docs for DB_ENV->open() imply that either DB_INIT_CDB or
    DB_INIT_LOCK must be used in apps which are not read-only, like
    EDS. This patch adds DB_INIT_CDB because it is simple and fixes the
    performance problem.
    
    In some rare cases, DB_INIT_LOCK might provide better performance by
    allowing concurrent writes of independent data, but that seems too
    complicated for not enough gain right now (must check for deadlocks).

 addressbook/backends/file/e-book-backend-file.c |   13 ++++++++++++-
 1 files changed, 12 insertions(+), 1 deletions(-)
---
diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index 7f8f465..6f33d8d 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -1143,7 +1143,18 @@ e_book_backend_file_load_source (EBookBackend           *backend,
 				(gpointer (*)(gpointer , gsize)) g_try_realloc,
 				g_free);
 
-		db_error = (*env->open) (env, NULL, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_THREAD, 0);
+		/*
+		 * We need either DB_INIT_CDB or DB_INIT_LOCK, because we will have
+		 * multiple threads reading and writing concurrently without
+		 * any locking above libdb.
+		 *
+		 * DB_INIT_CDB enforces multiple reader/single writer by locking inside
+		 * the database. It is used instead of DB_INIT_LOCK because DB_INIT_LOCK
+		 * may deadlock, which would have to be called in a separate thread.
+		 * Considered too complicated for not enough gain (= concurrent writes)
+		 * at this point.
+		 */
+		db_error = (*env->open) (env, NULL, DB_INIT_CDB | DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_THREAD, 0);
 		if (db_error != 0) {
 			env->close (env, 0);
 			g_warning ("db_env_open failed with %s", db_strerror (db_error));



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