/*
* This is a data store backend for the Citadel server which uses Berkeley DB.
*
- * Copyright (c) 1987-2011 by the citadel.org team
+ * Copyright (c) 1987-2012 by the citadel.org team
*
* This program is open source software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
+ * modify it under the terms of the GNU General Public License version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
/*****************************************************************************
#include <sys/stat.h>
#include <dirent.h>
#include <syslog.h>
+#include <zlib.h>
#ifdef HAVE_DB_H
#include <db.h>
static DB_ENV *dbenv; /* The DB environment (global) */
-#ifdef HAVE_ZLIB
-#include <zlib.h>
-#endif
+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 */
if (ret) {
syslog(LOG_EMERG, "bdb(): txn_abort: %s", db_strerror(ret));
- abort();
+ cdb_abort();
}
}
if (ret) {
syslog(LOG_EMERG, "bdb(): txn_commit: %s", db_strerror(ret));
- abort();
+ cdb_abort();
}
}
if (ret) {
syslog(LOG_EMERG, "bdb(): txn_begin: %s", db_strerror(ret));
- abort();
+ cdb_abort();
}
}
if ((ret = cursor->c_close(cursor))) {
syslog(LOG_EMERG, "bdb(): c_close: %s", db_strerror(ret));
- abort();
+ cdb_abort();
}
}
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();
}
}
if (TSD->tid != NULL) {
syslog(LOG_EMERG, "bdb(): transaction still in progress!");
- abort();
+ cdb_abort();
}
}
void cmd_cull(char *argbuf) {
if (CtdlAccessCheck(ac_internal)) return;
cdb_cull_logs();
- cprintf("%d Database log file cull completed.", CIT_OK);
+ cprintf("%d Database log file cull completed.\n", CIT_OK);
}
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 */
CitControl.MMdbversion = current_dbversion;
put_control();
-#ifdef HAVE_ZLIB
syslog(LOG_INFO, "Linked zlib: %s\n", zlibVersion());
-#endif
/*
* Silently try to create the database subdirectory. If it's
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);
/*
- * Compression functions only used if we have zlib
+ * Decompress a database item if it was compressed on disk
*/
void cdb_decompress_if_necessary(struct cdbdata *cdb)
{
(memcmp(cdb->ptr, &magic, sizeof(magic))))
return;
-#ifdef HAVE_ZLIB
/* At this point we know we're looking at a compressed item. */
struct CtdlCompressHeader zheader;
(const Bytef *) compressed_data,
(uLong) sourceLen) != Z_OK) {
syslog(LOG_EMERG, "uncompress() error\n");
- abort();
+ cdb_abort();
}
free(cdb->ptr);
cdb->len = (size_t) destLen;
cdb->ptr = uncompressed_data;
-#else /* HAVE_ZLIB */
- syslog(LOG_EMERG, "Database contains compressed data, but this citserver was built without compression support.");
- exit(CTDLEXIT_DB);
-#endif /* HAVE_ZLIB */
}
DB_TXN *tid;
int ret = 0;
-#ifdef HAVE_ZLIB
struct CtdlCompressHeader zheader;
char *compressed_data = NULL;
int compressing = 0;
size_t buffer_len = 0;
uLongf destLen = 0;
-#endif
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;
-#ifdef HAVE_ZLIB
/* Only compress Visit records. Everything else is uncompressed. */
if (cdb == CDB_VISIT) {
compressing = 1;
&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));
ddata.size = (size_t) (sizeof(struct CtdlCompressHeader) + zheader.compressed_len);
ddata.data = compressed_data;
}
-#endif
if (TSD->tid != NULL) {
ret = dbp[cdb]->put(dbp[cdb], /* db */
0); /* flags */
if (ret) {
syslog(LOG_EMERG, "cdb_store(%d): %s", cdb, db_strerror(ret));
- abort();
+ cdb_abort();
}
-#ifdef HAVE_ZLIB
if (compressing)
free(compressed_data);
-#endif
return ret;
} else {
goto retry;
} else {
syslog(LOG_EMERG, "cdb_store(%d): %s", cdb, db_strerror(ret));
- abort();
+ cdb_abort();
}
} else {
txcommit(tid);
-#ifdef HAVE_ZLIB
if (compressing) {
free(compressed_data);
}
-#endif
return ret;
}
}
+ return ret;
}
if (ret) {
syslog(LOG_EMERG, "cdb_delete(%d): %s\n", cdb, db_strerror(ret));
if (ret != DB_NOTFOUND) {
- abort();
+ cdb_abort();
}
}
} else {
} else {
syslog(LOG_EMERG, "cdb_delete(%d): %s\n",
cdb, db_strerror(ret));
- abort();
+ cdb_abort();
}
} else {
txcommit(tid);
if (ret) {
syslog(LOG_EMERG, "localcursor: %s\n", db_strerror(ret));
- abort();
+ cdb_abort();
}
return curs;
*/
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) {
if ((ret != 0) && (ret != DB_NOTFOUND)) {
syslog(LOG_EMERG, "cdb_fetch(%d): %s\n", cdb, db_strerror(ret));
- abort();
+ cdb_abort();
}
if (ret != 0)
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);
}
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]); */
}
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();
}
}
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 */
if (TSD->tid != NULL) {
syslog(LOG_EMERG, "cdb_begin_transaction: ERROR: nested transaction\n");
- abort();
+ cdb_abort();
}
txbegin(&TSD->tid);
if (TSD->tid == NULL) {
syslog(LOG_EMERG,
"cdb_end_transaction: ERROR: txcommit(NULL) !!\n");
- abort();
+ cdb_abort();
} else {
txcommit(TSD->tid);
}
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");
} 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);
}