X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fdatabase.c;h=dbcccf5b16b1a51ce3b7c17136d08f3f849022f7;hb=30a4090b04dff1084df3789efe78afd1e2bf6d90;hp=4eb34cdd7a593fef68419b46bef176a93878d361;hpb=80598eb9c1cf339151a66e3bdf1b7756efdde1a2;p=citadel.git diff --git a/citadel/database.c b/citadel/database.c index 4eb34cdd7..dbcccf5b1 100644 --- a/citadel/database.c +++ b/citadel/database.c @@ -27,16 +27,8 @@ /*****************************************************************************/ #include "sysdep.h" -#include -#include #include -#include -#include -#include -#include -#include #include -#include #include #ifdef HAVE_DB_H @@ -54,29 +46,35 @@ #include -#include "citadel.h" -#include "server.h" -#include "citserver.h" -#include "database.h" -#include "msgbase.h" -#include "sysdep_decls.h" -#include "threads.h" -#include "config.h" -#include "control.h" #include "ctdl_module.h" +#include "control.h" +#include "citserver.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() + ); + cit_backtrace(); + 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); + cit_backtrace(); } } @@ -84,7 +82,10 @@ void cdb_verbose_log(const DB_ENV *dbenv, const char *msg) /* Verbose logging callback */ void cdb_verbose_err(const DB_ENV *dbenv, const char *errpfx, const char *msg) { + int *FOO = NULL; syslog(LOG_ALERT, "DB: %s", msg); + cit_backtrace(); + *FOO = 1; } @@ -97,7 +98,7 @@ static void txabort(DB_TXN * tid) if (ret) { syslog(LOG_EMERG, "bdb(): txn_abort: %s", db_strerror(ret)); - abort(); + cdb_abort(); } } @@ -110,7 +111,7 @@ static void txcommit(DB_TXN * tid) if (ret) { syslog(LOG_EMERG, "bdb(): txn_commit: %s", db_strerror(ret)); - abort(); + cdb_abort(); } } @@ -123,13 +124,14 @@ static void txbegin(DB_TXN ** tid) if (ret) { syslog(LOG_EMERG, "bdb(): txn_begin: %s", db_strerror(ret)); - abort(); + cdb_abort(); } } static void dbpanic(DB_ENV * env, int errval) { syslog(LOG_EMERG, "bdb(): PANIC: %s", db_strerror(errval)); + cit_backtrace(); } static void cclose(DBC * cursor) @@ -138,7 +140,7 @@ static void cclose(DBC * cursor) if ((ret = cursor->c_close(cursor))) { syslog(LOG_EMERG, "bdb(): c_close: %s", db_strerror(ret)); - abort(); + cdb_abort(); } } @@ -149,7 +151,7 @@ static void bailIfCursor(DBC ** cursors, const char *msg) for (i = 0; i < MAXCDB; i++) if (cursors[i] != NULL) { syslog(LOG_EMERG, "bdb(): cursor still in progress on cdb %02x: %s", i, msg); - abort(); + cdb_abort(); } } @@ -160,7 +162,7 @@ void cdb_check_handles(void) if (TSD->tid != NULL) { syslog(LOG_EMERG, "bdb(): transaction still in progress!"); - abort(); + cdb_abort(); } } @@ -168,7 +170,7 @@ void cdb_check_handles(void) /* * Cull the database logs */ -static void cdb_cull_logs(void) +void cdb_cull_logs(void) { u_int32_t flags; int ret; @@ -204,15 +206,6 @@ static void cdb_cull_logs(void) } } -/* - * Manually initiate log file cull. - */ -void cmd_cull(char *argbuf) { - if (CtdlAccessCheck(ac_internal)) return; - cdb_cull_logs(); - cprintf("%d Database log file cull completed.", CIT_OK); -} - /* * Request a checkpoint of the database. Called once per minute by the thread manager. @@ -226,7 +219,7 @@ void cdb_checkpoint(void) if (ret != 0) { syslog(LOG_EMERG, "cdb_checkpoint: txn_checkpoint: %s", db_strerror(ret)); - abort(); + cdb_abort(); } /* After a successful checkpoint, we can cull the unused logs */ @@ -384,7 +377,7 @@ void open_databases(void) if (ret) { syslog(LOG_EMERG, "db_open[%02x]: %s\n", i, db_strerror(ret)); if (ret == ENOMEM) { - syslog(LOG_EMERG, "You may need to tune your database; please read http://www.citadel.org/doku.php/faq:troubleshooting:out_of_lock_entries for more information.\n"); + 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."); } syslog(LOG_EMERG, "exit code %d\n", ret); exit(CTDLEXIT_DB); @@ -420,7 +413,6 @@ void cdb_chmod_data(void) { } syslog(LOG_DEBUG, "open_databases() finished\n"); - CtdlRegisterProtoHook(cmd_cull, "CULL", "Cull database logs"); } @@ -500,7 +492,7 @@ void cdb_decompress_if_necessary(struct cdbdata *cdb) (const Bytef *) compressed_data, (uLong) sourceLen) != Z_OK) { syslog(LOG_EMERG, "uncompress() error\n"); - abort(); + cdb_abort(); } free(cdb->ptr); @@ -530,7 +522,9 @@ int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen) memset(&dkey, 0, sizeof(DBT)); memset(&ddata, 0, sizeof(DBT)); dkey.size = ckeylen; + /* no, we don't care for this error. */ dkey.data = ckey; + ddata.size = cdatalen; ddata.data = cdata; @@ -547,7 +541,7 @@ int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen) &destLen, (Bytef *) cdata, (uLongf) cdatalen, 1) != Z_OK) { syslog(LOG_EMERG, "compress2() error\n"); - abort(); + cdb_abort(); } zheader.compressed_len = (size_t) destLen; memcpy(compressed_data, &zheader, sizeof(struct CtdlCompressHeader)); @@ -563,7 +557,7 @@ int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen) 0); /* flags */ if (ret) { syslog(LOG_EMERG, "cdb_store(%d): %s", cdb, db_strerror(ret)); - abort(); + cdb_abort(); } if (compressing) free(compressed_data); @@ -585,7 +579,7 @@ int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen) goto retry; } else { syslog(LOG_EMERG, "cdb_store(%d): %s", cdb, db_strerror(ret)); - abort(); + cdb_abort(); } } else { txcommit(tid); @@ -595,6 +589,7 @@ int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen) return ret; } } + return ret; } @@ -617,7 +612,7 @@ int cdb_delete(int cdb, void *key, int keylen) if (ret) { syslog(LOG_EMERG, "cdb_delete(%d): %s\n", cdb, db_strerror(ret)); if (ret != DB_NOTFOUND) { - abort(); + cdb_abort(); } } } else { @@ -634,7 +629,7 @@ int cdb_delete(int cdb, void *key, int keylen) } else { syslog(LOG_EMERG, "cdb_delete(%d): %s\n", cdb, db_strerror(ret)); - abort(); + cdb_abort(); } } else { txcommit(tid); @@ -655,7 +650,7 @@ static DBC *localcursor(int cdb) if (ret) { syslog(LOG_EMERG, "localcursor: %s\n", db_strerror(ret)); - abort(); + cdb_abort(); } return curs; @@ -669,13 +664,13 @@ static DBC *localcursor(int cdb) */ struct cdbdata *cdb_fetch(int cdb, const void *key, int keylen) { - struct cdbdata *tempcdb; DBT dkey, dret; int ret; memset(&dkey, 0, sizeof(DBT)); dkey.size = keylen; + /* no we don't care about this error. */ dkey.data = key; if (TSD->tid != NULL) { @@ -700,7 +695,7 @@ struct cdbdata *cdb_fetch(int cdb, const void *key, int keylen) if ((ret != 0) && (ret != DB_NOTFOUND)) { syslog(LOG_EMERG, "cdb_fetch(%d): %s\n", cdb, db_strerror(ret)); - abort(); + cdb_abort(); } if (ret != 0) @@ -709,13 +704,16 @@ struct cdbdata *cdb_fetch(int cdb, const void *key, int keylen) if (tempcdb == NULL) { syslog(LOG_EMERG, "cdb_fetch: Cannot allocate memory for tempcdb\n"); - abort(); + cdb_abort(); + return NULL; /* make it easier for static analysis... */ + } + else + { + tempcdb->len = dret.size; + tempcdb->ptr = dret.data; + cdb_decompress_if_necessary(tempcdb); + return (tempcdb); } - - tempcdb->len = dret.size; - tempcdb->ptr = dret.data; - cdb_decompress_if_necessary(tempcdb); - return (tempcdb); } @@ -755,8 +753,8 @@ void cdb_rewind(int cdb) if (TSD->cursors[cdb] != NULL) { syslog(LOG_EMERG, - "cdb_rewind: must close cursor on database %d before reopening.\n", cdb); - abort(); + "cdb_rewind: must close cursor on database %d before reopening.\n", cdb); + cdb_abort(); /* cclose(TSD->cursors[cdb]); */ } @@ -766,7 +764,7 @@ void cdb_rewind(int cdb) ret = dbp[cdb]->cursor(dbp[cdb], TSD->tid, &TSD->cursors[cdb], 0); if (ret) { syslog(LOG_EMERG, "cdb_rewind: db_cursor: %s\n", db_strerror(ret)); - abort(); + cdb_abort(); } } @@ -791,7 +789,7 @@ struct cdbdata *cdb_next_item(int cdb) if (ret) { if (ret != DB_NOTFOUND) { syslog(LOG_EMERG, "cdb_next_item(%d): %s\n", cdb, db_strerror(ret)); - abort(); + cdb_abort(); } cdb_close_cursor(cdb); return NULL; /* presumably, end of file */ @@ -818,7 +816,7 @@ void cdb_begin_transaction(void) if (TSD->tid != NULL) { syslog(LOG_EMERG, "cdb_begin_transaction: ERROR: nested transaction\n"); - abort(); + cdb_abort(); } txbegin(&TSD->tid); @@ -840,7 +838,7 @@ void cdb_end_transaction(void) if (TSD->tid == NULL) { syslog(LOG_EMERG, "cdb_end_transaction: ERROR: txcommit(NULL) !!\n"); - abort(); + cdb_abort(); } else { txcommit(TSD->tid); } @@ -859,7 +857,7 @@ void cdb_trunc(int cdb) if (TSD->tid != NULL) { syslog(LOG_EMERG, "cdb_trunc must not be called in a transaction."); - abort(); + cdb_abort(); } else { bailIfCursor(TSD->cursors, "attempt to write during r/o cursor"); @@ -876,7 +874,7 @@ void cdb_trunc(int cdb) } 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/faq:troubleshooting:out_of_lock_entries for more information."); + 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); } @@ -885,3 +883,141 @@ void cdb_trunc(int cdb) } } } + +int SeentDebugEnabled = 0; + +#define DBGLOG(LEVEL) if ((LEVEL != LOG_DEBUG) || (SeentDebugEnabled != 0)) +#define SEENM_syslog(LEVEL, FORMAT) \ + DBGLOG(LEVEL) syslog(LEVEL, \ + "%s[%ld]CC[%ld] SEEN[%s][%d] " FORMAT, \ + IOSTR, ioid, ccid, Facility, cType) + +#define SEEN_syslog(LEVEL, FORMAT, ...) \ + DBGLOG(LEVEL) syslog(LEVEL, \ + "%s[%ld]CC[%ld] SEEN[%s][%d] " FORMAT, \ + IOSTR, ioid, ccid, Facility, cType, \ + __VA_ARGS__) + +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) + { + SEEN_syslog(LOG_DEBUG, "Loading [%s]", ChrPtr(guid)); + 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 = now - ut.ut_timestamp; + + if (InDBTimeStamp < antiexpire) + { + SEEN_syslog(LOG_DEBUG, "Found - Not expired %ld < %ld", InDBTimeStamp, antiexpire); + cdb_free(cdbut); + return InDBTimeStamp; + } + else + { + SEEN_syslog(LOG_DEBUG, "Found - Expired. %ld >= %ld", InDBTimeStamp, antiexpire); + cdb_free(cdbut); + } + } + else + { + if (cdbut) cdb_free(cdbut); + + SEENM_syslog(LOG_DEBUG, "not Found"); + if (cType == eCheckUpdate) + return 0; + } + + if (cType == eCheckExist) + return InDBTimeStamp; + } + + memcpy(ut.ut_msgid, SKEY(guid)); + ut.ut_timestamp = now; + + SEENM_syslog(LOG_DEBUG, "Saving new Timestamp"); + /* rewrite the record anyway, to update the timestamp */ + cdb_store(CDB_USETABLE, + SKEY(guid), + &ut, sizeof(struct UseTable) ); + + SEENM_syslog(LOG_DEBUG, "Done Saving"); + return InDBTimeStamp; +} + + +void cmd_rsen(char *argbuf) { + char Token[SIZ]; + long TLen; + char Time[SIZ]; + + struct UseTable ut; + struct cdbdata *cdbut; + + if (CtdlAccessCheck(ac_aide)) return; + + TLen = extract_token(Token, argbuf, 1, '|', sizeof Token); + if (strncmp(argbuf, "GET", 3) == 0) { + cdbut = cdb_fetch(CDB_USETABLE, Token, TLen); + if (cdbut != NULL) { + memcpy(&ut, cdbut->ptr, + ((cdbut->len > sizeof(struct UseTable)) ? + sizeof(struct UseTable) : cdbut->len)); + + cprintf("%d %ld\n", CIT_OK, ut.ut_timestamp); + } + else { + cprintf("%d not found\n", ERROR + NOT_HERE); + } + + } + else if (strncmp(argbuf, "SET", 3) == 0) { + memcpy(ut.ut_msgid, Token, TLen); + extract_token(Time, argbuf, 2, '|', sizeof Time); + ut.ut_timestamp = atol(Time); + cdb_store(CDB_USETABLE, + Token, TLen, + &ut, sizeof(struct UseTable) ); + cprintf("%d token updated\n", CIT_OK); + } + else if (strncmp(argbuf, "DEL", 3) == 0) { + if (cdb_delete(CDB_USETABLE, Token, TLen)) + cprintf("%d not found\n", ERROR + NOT_HERE); + else + cprintf("%d deleted.\n", CIT_OK); + + } + else { + cprintf("%d Usage: [GET|SET|DEL]|Token|timestamp\n", ERROR); + } + +} +void LogDebugEnableSeenEnable(const int n) +{ + SeentDebugEnabled = n; +} + +CTDL_MODULE_INIT(database) +{ + if (!threading) + { + CtdlRegisterDebugFlagHook(HKEY("SeenDebug"), LogDebugEnableSeenEnable, &SeentDebugEnabled); + CtdlRegisterProtoHook(cmd_rsen, "RSEN", "manipulate Aggregators seen database"); + } + + /* return our module id for the log */ + return "database"; +}