#ifdef HAVE_DB_H
#include <db.h>
+#elif defined(HAVE_DB4_DB_H)
+#include <db4/db.h>
#elif defined(HAVE_DB3_DB_H)
#include <db3/db.h>
#else
#include "dynloader.h"
#include "citserver.h"
#include "database.h"
+#include "msgbase.h"
#include "sysdep_decls.h"
static DB *dbp[MAXCDB]; /* One DB handle for each Citadel database */
u_int32_t flags;
int ret;
char **file, **list;
+ char errmsg[SIZ];
lprintf(5, "Database log file cull started.\n");
if (list != NULL) {
for (file = list; *file != NULL; ++file) {
lprintf(9, "Deleting log: %s\n", *file);
- unlink(*file);
+ ret = unlink(*file);
+ if (ret != 0) {
+ snprintf(errmsg, sizeof(errmsg),
+ " ** ERROR **\n \n \n "
+ "Citadel was unable to delete the "
+ "database log file '%s' because of the "
+ "following error:\n \n %s\n \n"
+ " This log file is no longer in use "
+ "and may be safely deleted.\n",
+ *file,
+ strerror(errno));
+ aide_message(errmsg);
+ }
}
free(list);
}
/* Arbitrary names for our tables -- we reference them by
* number, so we don't have string names for them.
*/
- sprintf(dbfilename, "cdb.%02x", i);
+ snprintf(dbfilename, sizeof dbfilename, "cdb.%02x", i);
ret = dbp[i]->open(dbp[i],
dbfilename,
}
+
/*
* Transaction-based stuff. I'm writing this as I bake cookies...
*/
MYTID = NULL;
}
+/*
+ * Truncate (delete every record)
+ */
+void cdb_trunc(int cdb)
+{
+ DB_TXN *tid;
+ int ret;
+#if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR > 2
+ u_int32_t count;
+#endif
+
+ if (MYTID != NULL)
+ {
+ lprintf(1, "cdb_trunc must not be called in a transaction.\n");
+ abort();
+ }
+ else
+ {
+ bailIfCursor(MYCURSORS, "attempt to write during r/o cursor");
+
+#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 3
+ for (;;)
+ {
+ DBT key, data;
+
+ /* Initialize the key/data pair so the flags aren't set. */
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ txbegin(&tid);
+
+ ret = dbp[cdb]->cursor(dbp[cdb], tid, &MYCURSORS[cdb], 0);
+ if (ret)
+ {
+ lprintf(1, "cdb_trunc: db_cursor: %s\n", db_strerror(ret));
+ abort();
+ }
+
+ ret = MYCURSORS[cdb]->c_get(MYCURSORS[cdb],
+ &key, &data, DB_NEXT);
+ if (ret)
+ {
+ cclose(MYCURSORS[cdb]);
+ txabort(tid);
+ if (ret == DB_LOCK_DEADLOCK)
+ continue;
+
+ if (ret == DB_NOTFOUND)
+ break;
+
+ lprintf(1, "cdb_trunc: c_get: %s\n", db_strerror(ret));
+ abort();
+ }
+
+ ret = MYCURSORS[cdb]->c_del(MYCURSORS[cdb], 0);
+ if (ret)
+ {
+ cclose(MYCURSORS[cdb]);
+ txabort(tid);
+ if (ret == DB_LOCK_DEADLOCK)
+ continue;
+
+ lprintf(1, "cdb_trunc: c_del: %s\n", db_strerror(ret));
+ abort();
+ }
+
+ cclose(MYCURSORS[cdb]);
+ txcommit(tid);
+ }
+#else
+ retry:
+ txbegin(&tid);
+
+ if ((ret = dbp[cdb]->truncate(dbp[cdb], /* db */
+ tid, /* transaction ID */
+ &count, /* #rows deleted */
+ 0))) /* flags */
+ {
+ if (ret == DB_LOCK_DEADLOCK)
+ {
+ txabort(tid);
+ goto retry;
+ }
+ else
+ {
+ lprintf(1, "cdb_truncate(%d): %s\n", cdb,
+ db_strerror(ret));
+ abort();
+ }
+ }
+ else
+ {
+ txcommit(tid);
+ }
+#endif
+ }
+}