+#include "threads.h"
+#include "config.h"
+#include "control.h"
+
+#include "ctdl_module.h"
+
+
+static DB *dbp[MAXCDB]; /* One DB handle for each Citadel database */
+static DB_ENV *dbenv; /* The DB environment (global) */
+
+
+void cdb_abort(void) {
+ syslog(LOG_DEBUG,
+ "citserver is stopping in order to prevent data loss. uid=%d gid=%d euid=%d egid=%d",
+ getuid(),
+ getgid(),
+ geteuid(),
+ getegid()
+ );
+ exit(CTDLEXIT_DB);
+}
+
+
+/* Verbose logging callback */
+void cdb_verbose_log(const DB_ENV *dbenv, const char *msg)
+{
+ if (!IsEmptyStr(msg)) {
+ syslog(LOG_DEBUG, "DB: %s", msg);
+ }
+}
+
+
+/* Verbose logging callback */
+void cdb_verbose_err(const DB_ENV *dbenv, const char *errpfx, const char *msg)
+{
+ syslog(LOG_ALERT, "DB: %s", msg);
+}
+
+
+/* just a little helper function */
+static void txabort(DB_TXN * tid)
+{
+ int ret;
+
+ ret = tid->abort(tid);
+
+ if (ret) {
+ syslog(LOG_EMERG, "bdb(): txn_abort: %s", db_strerror(ret));
+ cdb_abort();
+ }
+}
+
+/* this one is even more helpful than the last. */
+static void txcommit(DB_TXN * tid)
+{
+ int ret;
+
+ ret = tid->commit(tid, 0);
+
+ if (ret) {
+ syslog(LOG_EMERG, "bdb(): txn_commit: %s", db_strerror(ret));
+ cdb_abort();
+ }
+}
+
+/* are you sensing a pattern yet? */
+static void txbegin(DB_TXN ** tid)
+{
+ int ret;
+
+ ret = dbenv->txn_begin(dbenv, NULL, tid, 0);
+
+ if (ret) {
+ syslog(LOG_EMERG, "bdb(): txn_begin: %s", db_strerror(ret));
+ cdb_abort();
+ }
+}
+
+static void dbpanic(DB_ENV * env, int errval)
+{
+ syslog(LOG_EMERG, "bdb(): PANIC: %s", db_strerror(errval));
+}
+
+static void cclose(DBC * cursor)
+{
+ int ret;
+
+ if ((ret = cursor->c_close(cursor))) {
+ syslog(LOG_EMERG, "bdb(): c_close: %s", db_strerror(ret));
+ cdb_abort();
+ }
+}
+
+static void bailIfCursor(DBC ** cursors, const char *msg)
+{
+ int i;
+
+ for (i = 0; i < MAXCDB; i++)
+ if (cursors[i] != NULL) {
+ syslog(LOG_EMERG, "bdb(): cursor still in progress on cdb %02x: %s", i, msg);
+ cdb_abort();
+ }
+}
+
+
+void cdb_check_handles(void)
+{
+ bailIfCursor(TSD->cursors, "in check_handles");
+
+ if (TSD->tid != NULL) {
+ syslog(LOG_EMERG, "bdb(): transaction still in progress!");
+ cdb_abort();
+ }
+}