+/**
+ * cleanupdb - De-initialize the key database.
+ *
+ * This function should be called upon program exit to allow the DB to
+ * cleanup after itself.
+ */
+static void db4_cleanupdb(void)
+{
+ int i = 0;
+
+ if (dbenv != NULL) {
+ dbenv->txn_checkpoint(dbenv, 0, 0, 0);
+ if (skshashdb != NULL) {
+ skshashdb->close(skshashdb, 0);
+ skshashdb = NULL;
+ }
+ if (id32db != NULL) {
+ id32db->close(id32db, 0);
+ id32db = NULL;
+ }
+ if (worddb != NULL) {
+ worddb->close(worddb, 0);
+ worddb = NULL;
+ }
+ for (i = 0; i < numdbs; i++) {
+ if (dbconns[i] != NULL) {
+ dbconns[i]->close(dbconns[i], 0);
+ dbconns[i] = NULL;
+ }
+ }
+ free(dbconns);
+ dbconns = NULL;
+ dbenv->close(dbenv, 0);
+ dbenv = NULL;
+ }
+}
+
+/**
+ * db4_upgradedb - Upgrade a DB4 database
+ *
+ * Called if we discover we need to upgrade our DB4 database; ie if
+ * we're running with a newer version of db4 than the database was
+ * created with.
+ */
+static int db4_upgradedb(int numdb)
+{
+ DB *curdb = NULL;
+ int ret;
+ int i;
+ char buf[1024];
+ int lockfile_fd;
+ struct stat statbuf;
+
+ snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir,
+ DB4_UPGRADE_FILE);
+ lockfile_fd = open(buf, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (lockfile_fd < 0) {
+ if (errno == EEXIST) {
+ while (stat(buf, &statbuf) == 0) ;
+ return 0;
+ } else {
+ logthing(LOGTHING_CRITICAL, "Couldn't open database "
+ "update lock file: %s", strerror(errno));
+ return -1;
+ }
+ }
+ snprintf(buf, sizeof(buf) - 1, "%d", getpid());
+ write(lockfile_fd, buf, strlen(buf));
+ close(lockfile_fd);
+
+ logthing(LOGTHING_NOTICE, "Upgrading DB4 database");
+ ret = db_env_create(&dbenv, 0);
+ dbenv->set_errcall(dbenv, &db4_errfunc);
+ dbenv->remove(dbenv, config.db_dir, 0);
+ dbenv = NULL;
+ for (i = 0; i < numdb; i++) {
+ ret = db_create(&curdb, NULL, 0);
+ if (ret == 0) {
+ snprintf(buf, sizeof(buf) - 1, "%s/keydb.%d.db",
+ config.db_dir, i);
+ logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
+ ret = curdb->upgrade(curdb, buf, 0);
+ curdb->close(curdb, 0);
+ } else {
+ logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
+ buf,
+ db_strerror(ret));
+ }
+ }
+
+ ret = db_create(&curdb, NULL, 0);
+ if (ret == 0) {
+ snprintf(buf, sizeof(buf) - 1, "%s/worddb", config.db_dir);
+ logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
+ ret = curdb->upgrade(curdb, buf, 0);
+ curdb->close(curdb, 0);
+ } else {
+ logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
+ buf,
+ db_strerror(ret));
+ }
+
+ ret = db_create(&curdb, NULL, 0);
+ if (ret == 0) {
+ snprintf(buf, sizeof(buf) - 1, "%s/id32db", config.db_dir);
+ logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
+ ret = curdb->upgrade(curdb, buf, 0);
+ curdb->close(curdb, 0);
+ } else {
+ logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
+ buf,
+ db_strerror(ret));
+ }
+
+ ret = db_create(&curdb, NULL, 0);
+ if (ret == 0) {
+ snprintf(buf, sizeof(buf) - 1, "%s/skshashdb", config.db_dir);
+ logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
+ ret = curdb->upgrade(curdb, buf, 0);
+ curdb->close(curdb, 0);
+ } else {
+ logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
+ buf,
+ db_strerror(ret));
+ }
+
+ snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir,
+ DB4_UPGRADE_FILE);
+ unlink(buf);
+
+ return ret;
+}
+