+#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) */
+
+
+#ifdef HAVE_ZLIB
+#include <zlib.h>
+#endif
+
+
+/* Verbose logging callback */
+void cdb_verbose_log(const DB_ENV *dbenv, const char *msg)
+{
+ if (!IsEmptyStr(msg)) {
+ CtdlLogPrintf(CTDL_DEBUG, "DB: %s\n", msg);
+ }
+}
+
+
+/* Verbose logging callback */
+void cdb_verbose_err(const DB_ENV *dbenv, const char *errpfx, const char *msg)
+{
+ CtdlLogPrintf(CTDL_ALERT, "DB: %s\n", msg);
+}
+
+
+/* just a little helper function */
+static void txabort(DB_TXN * tid)
+{
+ int ret;
+
+ ret = tid->abort(tid);
+
+ if (ret) {
+ CtdlLogPrintf(CTDL_EMERG, "bdb(): txn_abort: %s\n", db_strerror(ret));
+ 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) {
+ CtdlLogPrintf(CTDL_EMERG, "bdb(): txn_commit: %s\n", db_strerror(ret));
+ 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) {
+ CtdlLogPrintf(CTDL_EMERG, "bdb(): txn_begin: %s\n", db_strerror(ret));
+ abort();
+ }
+}
+
+static void dbpanic(DB_ENV * env, int errval)
+{
+ CtdlLogPrintf(CTDL_EMERG, "bdb(): PANIC: %s\n", db_strerror(errval));
+}
+
+static void cclose(DBC * cursor)
+{
+ int ret;
+
+ if ((ret = cursor->c_close(cursor))) {
+ CtdlLogPrintf(CTDL_EMERG, "bdb(): c_close: %s\n", db_strerror(ret));
+ abort();
+ }
+}
+
+static void bailIfCursor(DBC ** cursors, const char *msg)
+{
+ int i;
+
+ for (i = 0; i < MAXCDB; i++)
+ if (cursors[i] != NULL) {
+ CtdlLogPrintf(CTDL_EMERG,
+ "bdb(): cursor still in progress on cdb %02x: %s\n", i, msg);
+ abort();
+ }
+}
+
+void check_handles(void *arg)
+{
+ if (arg != NULL) {
+ ThreadTSD *tsd = (ThreadTSD *) arg;
+
+ bailIfCursor(tsd->cursors, "in check_handles");
+
+ if (tsd->tid != NULL) {
+ CtdlLogPrintf(CTDL_EMERG, "bdb(): transaction still in progress!");
+ abort();
+ }
+ }
+}
+
+void cdb_check_handles(void)
+{
+ check_handles(pthread_getspecific(ThreadKey));
+}