summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2011-05-16 11:21:04 +0200
committerPatrick Ohly <patrick.ohly@intel.com>2011-05-16 17:46:11 +0200
commit5388a319326fa5db8b137bbce225a5cc2a445d4a (patch)
tree731cfa0487b21e64ba4a26445c1e9d38f4595819
parent26ff15a20e4ffd3f6e02777431a2d86db406f86d (diff)
downloadevolution-data-server-5388a319326fa5db8b137bbce225a5cc2a445d4a.tar.gz
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). (cherry picked from commit faada76f22cd192252b9f052183e9f1544a6da04)
-rw-r--r--addressbook/backends/file/e-book-backend-file.c13
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 dc6a70391..cbd51c4a3 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));