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,