diff --git a/lib/cyrusdb.h b/lib/cyrusdb.h index 3d1ded3..b4bc813 100644 --- a/lib/cyrusdb.h +++ b/lib/cyrusdb.h @@ -69,7 +69,8 @@ enum cyrusdb_dbflags { enum cyrusdb_openflags { CYRUSDB_CREATE = 0x01, /* Create the database if not existant */ - CYRUSDB_MBOXSORT = 0x02 /* Use mailbox sort order ('.' sorts 1st) */ + CYRUSDB_MBOXSORT = 0x02, /* Use mailbox sort order ('.' sorts 1st) */ + CYRUSDB_UPGRADE = 0x04 /* Do in place upgrade of Berkeley DB */ }; typedef int foreach_p(void *rock, diff --git a/lib/cyrusdb_berkeley.c b/lib/cyrusdb_berkeley.c index ee4816a..dacdba0 100644 --- a/lib/cyrusdb_berkeley.c +++ b/lib/cyrusdb_berkeley.c @@ -228,6 +228,11 @@ static int init(const char *dbdir, int myflags) r = (dbenv->open)(dbenv, dbdir, NULL, flags, 0644); #endif if (r) { + if ((myflags & CYRUSDB_UPGRADE) && do_retry && (r == DB_VERSION_MISMATCH)) { + flags |= DB_PRIVATE; + do_retry = 0; + goto retry; + } if (do_retry && (r == ENOENT)) { /* Per sleepycat Support Request #3838 reporting a performance problem: @@ -404,11 +409,35 @@ static int myopen(const char *fname, DBTYPE type, int flags, struct db **ret) *ret = NULL; + if (flags & CYRUS_UPGRADE) { + r = db_create(&db, dbenv, 0); + if (r != 0) { + syslog(LOG_ERR, "DBERROR: upgrading %s (creating database handle): %s", fname, db_strerror(r)); + return CYRUSDB_IOERROR; + } + + /* should we care for upgrades from db 3.0? */ + r = db->upgrade(db, fname, 0); + + if (r != 0) { + syslog(LOG_ERR, "DBERROR: upgrading %s (upgrading from the old format, possible corruption): %s", fname, db_strerror(r)); + return CYRUSDB_IOERROR; + } + + r = db-close(db, 0); + + if (r != 0) { + syslog(LOG_ERR, "DBERROR: upgrading %s (closing file after upgrade): %s", fname, db_strerror(r)); + return CYRUSDB_IOERROR; + } + } + r = db_create(&db, dbenv, 0); if (r != 0) { syslog(LOG_ERR, "DBERROR: opening %s (creating database handle): %s", fname, db_strerror(r)); return CYRUSDB_IOERROR; } /* xxx set comparator! */ if (flags & CYRUSDB_MBOXSORT) db->set_bt_compare(db, mbox_compar);