+ cdbret = (struct cdbdata *) malloc(sizeof(struct cdbdata));
+ cdbret->len = data.size;
+ cdbret->ptr = data.data;
+ cdb_decompress_if_necessary(cdbret);
+
+ return (cdbret);
+}
+
+
+
+/*
+ * Transaction-based stuff. I'm writing this as I bake cookies...
+ */
+
+void cdb_begin_transaction(void)
+{
+
+ bailIfCursor(TSD->cursors, "can't begin transaction during r/o cursor");
+
+ if (TSD->tid != NULL) {
+ syslog(LOG_EMERG, "cdb_begin_transaction: ERROR: nested transaction\n");
+ cdb_abort();
+ }
+
+ txbegin(&TSD->tid);
+}
+
+void cdb_end_transaction(void)
+{
+ int i;
+
+ for (i = 0; i < MAXCDB; i++)
+ if (TSD->cursors[i] != NULL) {
+ syslog(LOG_WARNING,
+ "cdb_end_transaction: WARNING: cursor %d still open at transaction end\n",
+ i);
+ cclose(TSD->cursors[i]);
+ TSD->cursors[i] = NULL;
+ }
+
+ if (TSD->tid == NULL) {
+ syslog(LOG_EMERG,
+ "cdb_end_transaction: ERROR: txcommit(NULL) !!\n");
+ cdb_abort();
+ } else {
+ txcommit(TSD->tid);
+ }
+
+ TSD->tid = NULL;
+}
+
+/*
+ * Truncate (delete every record)
+ */
+void cdb_trunc(int cdb)
+{
+ /* DB_TXN *tid; */
+ int ret;
+ u_int32_t count;
+
+ if (TSD->tid != NULL) {
+ syslog(LOG_EMERG, "cdb_trunc must not be called in a transaction.");
+ cdb_abort();
+ } else {
+ bailIfCursor(TSD->cursors, "attempt to write during r/o cursor");
+
+ retry:
+ /* txbegin(&tid); */
+
+ if ((ret = dbp[cdb]->truncate(dbp[cdb], /* db */
+ NULL, /* transaction ID */
+ &count, /* #rows deleted */
+ 0))) { /* flags */
+ if (ret == DB_LOCK_DEADLOCK) {
+ /* txabort(tid); */
+ goto retry;
+ } else {
+ syslog(LOG_EMERG, "cdb_truncate(%d): %s\n", cdb, db_strerror(ret));
+ if (ret == ENOMEM) {
+ syslog(LOG_EMERG, "You may need to tune your database; please read http://www.citadel.org/doku.php?id=faq:troubleshooting:out_of_lock_entries for more information.");
+ }
+ exit(CTDLEXIT_DB);
+ }
+ } else {
+ /* txcommit(tid); */
+ }
+ }
+}
+
+int SeentDebugEnabled = 0;
+
+#define DBGLOG(LEVEL) if ((LEVEL != LOG_DEBUG) || (SeentDebugEnabled != 0))
+#define SEENM_syslog(LEVEL, FORMAT) \
+ DBGLOG(LEVEL) syslog(LEVEL, \
+ "IO[%ld]CC[%ld] SEEN[%s][%d] " FORMAT, \
+ ioid, ccid, Facility, cType)
+
+time_t CheckIfAlreadySeen(const char *Facility,
+ StrBuf *guid,
+ time_t now,
+ time_t antiexpire,
+ eCheckType cType,
+ long ccid,
+ long ioid)
+{
+ time_t InDBTimeStamp = 0;
+ struct UseTable ut;
+ struct cdbdata *cdbut;
+
+ if (cType != eWrite)
+ {
+ SEENM_syslog(LOG_DEBUG, "Loading");
+ cdbut = cdb_fetch(CDB_USETABLE, SKEY(guid));
+ if ((cdbut != NULL) && (cdbut->ptr != NULL)) {
+ memcpy(&ut, cdbut->ptr,
+ ((cdbut->len > sizeof(struct UseTable)) ?
+ sizeof(struct UseTable) : cdbut->len));
+ InDBTimeStamp = ut.ut_timestamp;
+
+ if (InDBTimeStamp < antiexpire)
+ {
+ SEENM_syslog(LOG_DEBUG, "Found - Not expired.");
+ cdb_free(cdbut);
+ return InDBTimeStamp;
+ }
+ else
+ {
+ SEENM_syslog(LOG_DEBUG, "Found - Expired.");
+ InDBTimeStamp = ut.ut_timestamp;
+ cdb_free(cdbut);
+ }