Attached is a patch that begins to implement a db3_rpc cyrusdb
back-end. I worked-around my previous question (for now) by just
implementing an open) that fakes the database name from the basename
of the full path of the filename.

I've only tested this with the mailboxes.db so far, the others that
live in "configdirectory" will be tested tomorrow.  I'm not sure what
to do about: the per-user databases that could be db3, ctl_cyrusdb --
and I'm sure there's other stuff too...

Comments please!

Regards,

-- 
Stephen L. Ulmer                              [EMAIL PROTECTED]
Senior Systems Programmer                         http://www.ulmer.org/
Northeast Regional Data Center                      VOX: (352) 392-2061
University of Florida                               FAX: (352) 392-9440

diff -ruN cyrus-imapd-2.1.11/configure.in cyrus-imapd-2.1.11-db3_rpc+openhack/configure.in
--- cyrus-imapd-2.1.11/configure.in	Sat Nov 16 11:31:54 2002
+++ cyrus-imapd-2.1.11-db3_rpc+openhack/configure.in	Mon Jan  6 16:56:14 2003
@@ -155,6 +155,7 @@
 	AC_MSG_CHECKING([$1 database backend])
 	if test "$3" != "db3" -a \
 		"$3" != "db3_nosync" -a \
+		"$3" != "db3_rpc" -a \
 	 	"$3" != "flat" -a \
 		"$3" != "skiplist"; then
 	   AC_ERROR([invalid $1 value])
@@ -170,6 +171,7 @@
 	fi
 	if test "$3" != "db3" -a \
 		"$3" != "db3_nosync" -a \
+		"$3" != "db3_rpc" -a \
 		"$3" != "skiplist"; then
 	   AC_ERROR([invalid $1 value])
 	fi
diff -ruN cyrus-imapd-2.1.11/lib/cyrusdb.c cyrus-imapd-2.1.11-db3_rpc+openhack/lib/cyrusdb.c
--- cyrus-imapd-2.1.11/lib/cyrusdb.c	Sat Feb 23 23:42:17 2002
+++ cyrus-imapd-2.1.11-db3_rpc+openhack/lib/cyrusdb.c	Mon Jan  6 16:56:14 2003
@@ -61,6 +61,7 @@
 struct cyrusdb_backend *cyrusdb_backends[] = {
     &cyrusdb_db3,
     &cyrusdb_db3_nosync,
+    &cyrusdb_db3_rpc,
     &cyrusdb_flat,
     &cyrusdb_skiplist,
     NULL };
diff -ruN cyrus-imapd-2.1.11/lib/cyrusdb.h cyrus-imapd-2.1.11-db3_rpc+openhack/lib/cyrusdb.h
--- cyrus-imapd-2.1.11/lib/cyrusdb.h	Wed Jul 24 14:05:18 2002
+++ cyrus-imapd-2.1.11-db3_rpc+openhack/lib/cyrusdb.h	Mon Jan  6 16:56:14 2003
@@ -166,6 +166,7 @@
 
 extern struct cyrusdb_backend cyrusdb_db3;
 extern struct cyrusdb_backend cyrusdb_db3_nosync;
+extern struct cyrusdb_backend cyrusdb_db3_rpc;
 extern struct cyrusdb_backend cyrusdb_flat;
 extern struct cyrusdb_backend cyrusdb_skiplist;
 
diff -ruN cyrus-imapd-2.1.11/lib/cyrusdb_db3.c cyrus-imapd-2.1.11-db3_rpc+openhack/lib/cyrusdb_db3.c
--- cyrus-imapd-2.1.11/lib/cyrusdb_db3.c	Mon Nov  4 12:32:07 2002
+++ cyrus-imapd-2.1.11-db3_rpc+openhack/lib/cyrusdb_db3.c	Mon Jan  6 22:21:21 2003
@@ -50,6 +50,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <libgen.h>
 
 #include "cyrusdb.h"
 #include "exitcodes.h"
@@ -913,6 +914,106 @@
     return 0;
 }
 
+static int init_rpc(const char *dbdir, int myflags)
+{
+    int r, do_retry = 1;
+    int flags = 0;
+    int maj, min, patch;
+    char *vstr, *rpc_server, *dbhome;
+    static char errpfx[10]; /* needs to be static; bdb doesn't copy */
+
+    if (dbinit++) return 0;
+
+    vstr = db_version(&maj, &min, &patch);
+    if (maj != DB_VERSION_MAJOR || min != DB_VERSION_MINOR ||
+	DB_VERSION_PATCH > patch) {
+	syslog(LOG_CRIT, "incorrect version of Berkeley db: "
+	       "compiled against %d.%d.%d, linked against %d.%d.%d",
+	       DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
+	       maj, min, patch);
+	fatal("wrong db version", EC_SOFTWARE);
+    }
+
+    if (myflags & CYRUSDB_RECOVER) {
+      flags |= DB_RECOVER | DB_CREATE;
+    }
+
+    if ((r = db_env_create(&dbenv, DB_CLIENT)) != 0) {
+	syslog(LOG_ERR, "DBERROR: db_appinit failed: %s", db_strerror(r));
+	return CYRUSDB_IOERROR;
+    }
+    dbenv->set_paniccall(dbenv, (void (*)(DB_ENV *, int)) &db_panic);
+    if (CONFIG_DB_VERBOSE) {
+	dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, 1);
+	dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR, 1);
+    }
+    if (CONFIG_DB_VERBOSE > 1) {
+	dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT, 1);
+    }
+    dbenv->set_lk_detect(dbenv, CONFIG_DEADLOCK_DETECTION);
+
+    dbenv->set_errcall(dbenv, db_err);
+    snprintf(errpfx, sizeof(errpfx), "db%d", DB_VERSION_MAJOR);
+    dbenv->set_errpfx(dbenv, errpfx);
+
+    /* Setup RPC server */
+    rpc_server = config_getstring("db3_rpc_server", NULL);
+
+    if ((r = dbenv->set_rpc_server(dbenv, NULL, rpc_server, 0, 0, 0)) != 0 ) {
+	syslog(LOG_ERR, "DBERROR: db_set_rpc_server failed: %s", db_strerror(r));
+	return CYRUSDB_IOERROR;
+    }
+
+    /* Setup DB "home" */
+    dbhome = config_getstring("db3_rpc_home", NULL);
+
+    /* what directory are we in? */
+ retry:
+    flags |= DB_INIT_LOCK | DB_INIT_MPOOL | 
+	     DB_INIT_LOG | DB_INIT_TXN;
+#if (DB_VERSION_MAJOR > 3) || ((DB_VERSION_MAJOR == 3) && (DB_VERSION_MINOR > 0))
+    r = dbenv->open(dbenv, dbhome, flags, 0644); 
+#else
+    r = dbenv->open(dbenv, dbhome, NULL, flags, 0644); 
+#endif
+    if (r) {
+        if (do_retry && (r == ENOENT)) {
+	  /* Per sleepycat Support Request #3838 reporting a performance problem: 
+
+	        Berkeley DB only transactionally protects the open if you're
+	        doing a DB_CREATE.  Even if the Cyrus application is opening
+  	        the file read/write, we don't need a transaction.  I see
+	        from their source that they are always specifying DB_CREATE.
+	        I bet if they changed it to not specifying CREATE and only
+	        creating if necessary, the problem would probably go away.
+
+	     Given that in general the file should exist, we optimize the most 
+	     often case: the file exists.  So, we add DB_CREATE only if we fail 
+	     to open the file and thereby avoid doing a stat(2) needlessly. Sure, it 
+	     should be cached by why waste the cycles anyway?
+	  */
+	  flags |= DB_CREATE;
+	  do_retry = 0;
+	  goto retry;
+        }
+	
+	syslog(LOG_ERR, "DBERROR: dbenv->open '%s' failed: %s", dbdir,
+	       db_strerror(r));
+	return CYRUSDB_IOERROR;
+    }
+
+    dbinit = 1;
+
+    return 0;
+}
+
+static int open_rpc(const char *fname, struct db **ret)
+{
+    char dbname[1024];
+    (void) strncpy(dbname, basename(fname), 1024);
+    return myopen(dbname, ret);
+}
+
 struct cyrusdb_backend cyrusdb_db3 = 
 {
     "db3",			/* name */
@@ -959,6 +1060,32 @@
     &delete_nosync,
 
     &commit_nosync,
+    &abort_txn,
+
+    NULL,
+    NULL
+};
+
+struct cyrusdb_backend cyrusdb_db3_rpc = 
+{
+    "db3-rpc",		       /* name */
+
+    &init_rpc,
+    &done,
+    &mysync,
+    &myarchive,
+
+    &open_rpc,
+    &myclose,
+
+    &fetch,
+    &fetchlock,
+    &foreach,
+    &create,
+    &store,
+    &delete,
+
+    &commit_txn,
     &abort_txn,
 
     NULL,

Reply via email to