experimental QDBM TXN patch

Matthias Andree matthias.andree at gmx.de
Tue Nov 9 00:07:11 CET 2004


Stefan Bellon <sbellon at sbellon.de> writes:

> Matthias Andree wrote:
>> OK, here's the second try of transactions for QDBM. Turns out QDBM
>> allows transactions only for writer database handles.
>
> This patch never sets handle->writer. So either, the transaction code
> always returns DST_OK without vltran* really being used (as
> !handle->writer is always true) or your patch isn't complete.

Something's jinxed... next version enclosed:

--- src/datastore_qdbm.c	1 Nov 2004 01:04:25 -0000	1.33
+++ src/datastore_qdbm.c	8 Nov 2004 23:04:41 -0000
@@ -7,7 +7,7 @@
 
 AUTHORS:
 Gyepi Sam <gyepi at praxis-sw.com>          2003
-Matthias Andree <matthias.andree at gmx.de> 2003
+Matthias Andree <matthias.andree at gmx.de> 2003-2004
 Stefan Bellon <sbellon at sbellon.de>       2003-2004
 
 ******************************************************************************/
@@ -18,6 +18,7 @@
 #include <cabin.h>
 #include <villa.h>
 #include <stdlib.h>
+#include <assert.h>
 
 #include "datastore.h"
 #include "datastore_db.h"
@@ -34,6 +35,7 @@
     char *name;
     bool locked;
     bool created;
+    bool writer;
     VILLA *dbp;
 } dbh_t;
 
@@ -41,6 +43,7 @@
  * or transactional initialization/shutdown */
 
 static bool init = false;
+static bool txn = false;
 
 /* Function definitions */
 
@@ -59,7 +62,6 @@
     size_t len = strlen(path) + strlen(name) + 2;
 
     handle = xmalloc(sizeof(dbh_t));
-    memset(handle, 0, sizeof(dbh_t));	/* valgrind */
 
     handle->path = xstrdup(path);
 
@@ -68,6 +70,9 @@
 
     handle->locked = false;
     handle->created = false;
+    handle->writer = false;
+
+    handle->dbp = NULL;
 
     return handle;
 }
@@ -123,6 +128,7 @@
 
     dbp = handle->dbp = vlopen(handle->name, open_flags, cmpkey);
 
+    /* retry if a writer */
     if ((dbp == NULL) && (open_mode & DS_WRITE)) {
 	dbp = handle->dbp = vlopen(handle->name, open_flags|VL_OCREAT, cmpkey);
 	if (dbp != NULL)
@@ -132,6 +138,9 @@
     if (dbp == NULL)
 	goto open_err;
 
+    if (open_flags == VL_OWRITER)
+	handle->writer = true;
+
     if (DEBUG_DATABASE(1))
 	fprintf(dbgout, "(qdbm) vlopen( %s, %d )\n", handle->name, open_mode);
 
@@ -203,14 +212,10 @@
 */
 static inline void db_optimize(VILLA *dbp, char *name)
 {
-    UNUSED(dbp);
     UNUSED(name);
 
-    /* The Villa API doesn't need optimizing like the formerly used
-       Depot API because Villa uses B+ trees and Depot uses hash tables.
-       Database size may grow larger and could get compacted with
-       vloptimize() however as the database size with Villa is smaller
-       anyway, I don't think it is worth it. */
+    assert(!txn);
+    vloptimize(dbp);
 }
 
 
@@ -230,7 +235,16 @@
 	exit(EX_ERROR);
     }
 
+#if 0
+    /* The Villa API doesn't need optimizing like the formerly used
+       Depot API because Villa uses B+ trees and Depot uses hash tables.
+       Database size may grow larger and could get compacted with
+       vloptimize() however as the database size with Villa is smaller
+       anyway, I don't think it is worth it. -- Stefan Bellon */
+
+    /* NOTE: db_optimize must not be called with a transaction open! */
     db_optimize(dbp, handle->name);
+#endif
 
     return 0;
 }
@@ -271,6 +285,7 @@
     dbh_t *handle = vhandle;
     VILLA * dbp = handle->dbp;
 
+    assert(!txn);
     if (!vlsync(dbp))
 	print_error(__FILE__, __LINE__, "(qdbm) vlsync failed: %s",
 		    dperrmsg(dpecode));
@@ -342,25 +357,61 @@
 }
 
 /** begin transaction. Returns 0 for success. */
-int db_txn_begin(void *d)
+int db_txn_begin(void *vhandle)
 {
-    UNUSED(d);
+    dbh_t *handle = vhandle;
+    VILLA *dbp = handle->dbp;
 
-    return 0;
+    assert(!txn);
+    if (!handle->writer) return DST_OK;
+
+    if (vltranbegin(dbp)) {
+	if (DEBUG_DATABASE(2))
+	    fprintf(dbgout, "(qdbm) vltranbegin(%p) success\n", (void *)dbp);
+	txn = true;
+	return DST_OK;
+    }
+    print_error(__FILE__, __LINE__, "(qdbm) vltranbegin(%s) failed: %s",
+		handle->name, dperrmsg(dpecode));
+    return DST_FAILURE;
 }
 
-int db_txn_abort(void *d)
+int db_txn_abort(void *vhandle)
 {
-    UNUSED(d);
+    dbh_t *handle = vhandle;
+    VILLA *dbp = handle->dbp;
 
-    return 0;
+    if (!handle->writer) return DST_OK;
+    assert(txn);
+
+    txn = false;
+    if (vltranabort(dbp)) {
+	if (DEBUG_DATABASE(2))
+	    fprintf(dbgout, "(qdbm) vltranabort(%p) success\n", (void *)dbp);
+	return DST_OK;
+    }
+    print_error(__FILE__, __LINE__, "(qdbm) vltranabort(%s) failed: %s",
+		handle->name, dperrmsg(dpecode));
+    return DST_FAILURE;
 }
 
-int db_txn_commit(void *d)
+int db_txn_commit(void *vhandle)
 {
-    UNUSED(d);
+    dbh_t *handle = vhandle;
+    VILLA *dbp = handle->dbp;
 
-    return 0;
+    if (!handle->writer) return DST_OK;
+    assert(txn);
+
+    txn = false;
+    if (vltrancommit(dbp)) {
+	if (DEBUG_DATABASE(2))
+	    fprintf(dbgout, "(qdbm) vltrancommit(%p) success\n", (void *)dbp);
+	return DST_OK;
+    }
+    print_error(__FILE__, __LINE__, "(qdbm) vltrancommit(%s) failed: %s",
+		handle->name, dperrmsg(dpecode));
+    return DST_FAILURE;
 }
 
 int db_recover(int a, int b)


-- 
Matthias Andree



More information about the bogofilter-dev mailing list