File bogofilter-kyotocabinet.patch of Package bogofilter.30272
commit 490717dabe58fca268add95e367e0954477c9599
Author: Denny Lin <dennylin93@hs.ntnu.edu.tw>
Date: Mon Sep 21 15:21:03 2015 +0200
Add Kyoto Cabinet backend.
diff --git a/configure.ac b/configure.ac
index 933b365..c085e05 100644
--- a/configure.ac
+++ b/configure.ac
@@ -464,7 +464,7 @@ AC_CACHE_SAVE
WITH_DB_ENGINE=db
AC_ARG_WITH(database,
AS_HELP_STRING([--with-database=ENGINE],
- [choose database engine {db|qdbm|sqlite3|tokyocabinet} [[db]]]),
+ [choose database engine {db|qdbm|sqlite3|tokyocabinet|kyotocabinet} [[db]]]),
[ WITH_DB_ENGINE=$withval ]
)
@@ -503,6 +503,21 @@ case "x$WITH_DB_ENGINE" in
])],,AC_MSG_ERROR(Cannot link to tokyocabinet library.))
LIBS="$saveLIBS"
;;
+ xkyotocabinet)
+ AC_DEFINE(ENABLE_KYOTOCABINET_DATASTORE,1, [Enable kyotocabinet datastore])
+ DB_TYPE=kyotocabinet
+ DB_EXT=.kct
+ AC_LIB_LINKFLAGS([kyotocabinet])
+ LIBDB="$LIBKYOTOCABINET"
+ saveLIBS="$LIBS"
+ LIBS="$LIBS $LIBDB"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([
+#include <kclangc.h>
+ ], [
+ KCDB *db = kcdbnew();
+ ])],,AC_MSG_ERROR(Cannot link to kyotocabinet library.))
+ LIBS="$saveLIBS"
+ ;;
xqdbm)
AC_DEFINE(ENABLE_QDBM_DATASTORE,1, [Enable qdbm datastore])
DB_TYPE=qdbm
@@ -653,7 +668,7 @@ shared environments, you can use --disable-dbshared-test.])],true)
LIBS="$saveLIBS"
;;
*)
- AC_MSG_ERROR([Invalid --with-database argument. Supported engines are db, qdbm, sqlite3, tokyocabinet.])
+ AC_MSG_ERROR([Invalid --with-database argument. Supported engines are db, qdbm, sqlite3, tokyocabinet, kyotocabinet.])
;;
esac
@@ -679,6 +694,7 @@ AC_SUBST(STATIC_DB)
AM_CONDITIONAL(ENABLE_QDBM_DATASTORE, test "x$WITH_DB_ENGINE" = "xqdbm")
AM_CONDITIONAL(ENABLE_SQLITE_DATASTORE, test "x$WITH_DB_ENGINE" = "xsqlite3")
AM_CONDITIONAL(ENABLE_TOKYOCABINET_DATASTORE, test "x$WITH_DB_ENGINE" = "xtokyocabinet")
+AM_CONDITIONAL(ENABLE_KYOTOCABINET_DATASTORE, test "x$WITH_DB_ENGINE" = "xkyotocabinet")
dnl Use TRIO to replace missing snprintf/vsnprintf.
needtrio=0
diff --git a/src/Makefile.am b/src/Makefile.am
index 0b2f064..fbce226 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -190,6 +190,11 @@ datastore_SOURCE = datastore_tc.c \
datastore_opthelp_dummies.c \
datastore_dummies.c
else
+if ENABLE_KYOTOCABINET_DATASTORE
+datastore_SOURCE = datastore_kc.c \
+ datastore_opthelp_dummies.c \
+ datastore_dummies.c
+else
if ENABLE_TRANSACTIONS
datastore_SOURCE = datastore_db.c datastore_db_trans.c
else
@@ -203,6 +208,7 @@ endif
endif
endif
endif
+endif
datastore_OBJECT = $(datastore_SOURCE:.c=.o)
diff --git a/src/datastore_kc.c b/src/datastore_kc.c
new file mode 100644
index 0000000..66a8f5e
--- /dev/null
+++ b/src/datastore_kc.c
@@ -0,0 +1,315 @@
+/* $Id$ */
+
+/*****************************************************************************
+
+NAME:
+datastore_kc.c -- implements the datastore, using kyotocabinet.
+
+AUTHORS:
+Gyepi Sam <gyepi@praxis-sw.com> 2003
+Matthias Andree <matthias.andree@gmx.de> 2003
+Stefan Bellon <sbellon@sbellon.de> 2003-2004
+Pierre Habouzit <madcoder@debian.org> 2007
+Denny Lin <dennylin93@hs.ntnu.edu.tw> 2015
+
+******************************************************************************/
+
+#include "common.h"
+
+#include <kclangc.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "datastore.h"
+#include "datastore_db.h"
+#include "error.h"
+#include "paths.h"
+#include "xmalloc.h"
+#include "xstrdup.h"
+
+#define UNUSED(x) ((void)(x))
+
+typedef struct {
+ char *name;
+ bool created;
+ bool writable;
+ KCDB *dbp;
+} dbh_t;
+
+static int kc_txn_begin(void *vhandle) {
+ dbh_t *dbh = vhandle;
+ if (!dbh->writable || kcdbbegintran(dbh->dbp, false))
+ return DST_OK;
+ print_error(__FILE__, __LINE__, "kcdbbegintran(%p), err: %d, %s",
+ dbh->dbp,
+ kcdbecode(dbh->dbp), kcdbemsg(dbh->dbp));
+ return DST_FAILURE;
+}
+
+static int kc_txn_abort(void *vhandle) {
+ dbh_t *dbh = vhandle;
+ if (!dbh->writable || kcdbendtran(dbh->dbp, false))
+ return DST_OK;
+ print_error(__FILE__, __LINE__, "kcdbendtran(%p, false), err: %d, %s",
+ dbh->dbp,
+ kcdbecode(dbh->dbp), kcdbemsg(dbh->dbp));
+ return DST_FAILURE;
+}
+
+static int kc_txn_commit(void *vhandle) {
+ dbh_t *dbh = vhandle;
+ if (!dbh->writable || kcdbendtran(dbh->dbp, true))
+ return DST_OK;
+ print_error(__FILE__, __LINE__, "kc_txn_commit(%p, true), err: %d, %s",
+ dbh->dbp,
+ kcdbecode(dbh->dbp), kcdbemsg(dbh->dbp));
+ return DST_FAILURE;
+}
+
+static dsm_t dsm_kc = {
+ /* public -- used in datastore.c */
+ &kc_txn_begin,
+ &kc_txn_abort,
+ &kc_txn_commit,
+ /* private -- used in datastore_db_*.c */
+ NULL, /* dsm_env_init */
+ NULL, /* dsm_cleanup */
+ NULL, /* dsm_cleanup_lite */
+ NULL, /* dsm_get_env_dbe */
+ NULL, /* dsm_database_name */
+ NULL, /* dsm_recover_open */
+ NULL, /* dsm_auto_commit_flags */
+ NULL, /* dsm_get_rmw_flag */
+ NULL, /* dsm_lock */
+ NULL, /* dsm_common_close */
+ NULL, /* dsm_sync */
+ NULL, /* dsm_log_flush */
+ NULL, /* dsm_pagesize */
+ NULL, /* dsm_purgelogs */
+ NULL, /* dsm_checkpoint */
+ NULL, /* dsm_recover */
+ NULL, /* dsm_remove */
+ NULL, /* dsm_verify */
+ NULL, /* dsm_list_logfiles */
+ NULL /* dsm_leafpages */
+};
+
+dsm_t *dsm = &dsm_kc;
+
+const char *db_version_str(void)
+{
+ static char v[80];
+ if (v[0] == '\0')
+ snprintf(v, sizeof(v) - 1, "Kyoto Cabinet %s (TreeDB)", KCVERSION);
+ return v;
+}
+
+
+static dbh_t *dbh_init(bfpath *bfp)
+{
+ dbh_t *handle;
+
+ handle = xmalloc(sizeof(dbh_t));
+ memset(handle, 0, sizeof(dbh_t));
+
+ handle->name = xstrdup(bfp->filepath);
+ handle->created = false;
+ handle->writable = false;
+ handle->dbp = kcdbnew();
+
+ return handle;
+}
+
+
+static void dbh_free(dbh_t *handle)
+{
+ if (handle != NULL) {
+ xfree(handle->name);
+ kcdbdel(handle->dbp);
+ xfree(handle);
+ }
+}
+
+
+bool db_is_swapped(void *vhandle)
+{
+ UNUSED(vhandle);
+
+ return false;
+}
+
+
+bool db_created(void *vhandle)
+{
+ dbh_t *handle = vhandle;
+
+ return handle->created;
+}
+
+
+void *db_open(void *env, bfpath *bfp, dbmode_t open_mode)
+{
+ dbh_t *handle;
+ uint32_t mode;
+ bool ret;
+
+ UNUSED(env);
+
+ handle = dbh_init(bfp);
+
+ handle->writable = open_mode & DS_WRITE;
+ mode = handle->writable ? KCOWRITER : KCOREADER;
+ ret = kcdbopen(handle->dbp, handle->name, mode);
+ if (!ret && handle->writable) {
+ ret = kcdbopen(handle->dbp, handle->name, mode | KCOCREATE);
+ handle->created = ret;
+ }
+
+ if (!ret)
+ goto open_err;
+
+ if (DEBUG_DATABASE(1))
+ fprintf(dbgout, "kcdbopen(%s, %u)\n", handle->name, mode);
+
+ return handle;
+
+open_err:
+ print_error(__FILE__, __LINE__, "kcdbopen(%s, %u), err: %d, %s",
+ handle->name, mode,
+ kcdbecode(handle->dbp), kcdbemsg(handle->dbp));
+ dbh_free(handle);
+
+ return NULL;
+}
+
+
+int db_delete(void *vhandle, const dbv_t *token)
+{
+ dbh_t *handle = vhandle;
+ bool ret;
+
+ ret = kcdbremove(handle->dbp, token->data, token->leng);
+ if (!ret) {
+ print_error(__FILE__, __LINE__, "kcdbremove(\"%.*s\"), err: %d, %s",
+ CLAMP_INT_MAX(token->leng), (char *)token->data,
+ kcdbecode(handle->dbp), kcdbemsg(handle->dbp));
+ exit(EX_ERROR);
+ }
+
+ return 0;
+}
+
+
+int db_get_dbvalue(void *vhandle, const dbv_t *token, dbv_t *val)
+{
+ dbh_t *handle = vhandle;
+ char *data;
+ size_t dsiz;
+
+ data = kcdbget(handle->dbp, token->data, token->leng, &dsiz);
+ if (data == NULL)
+ return DS_NOTFOUND;
+
+ val->leng = min(val->leng, dsiz);
+ memcpy(val->data, data, val->leng);
+ kcfree(data);
+
+ return 0;
+}
+
+int db_set_dbvalue(void *vhandle, const dbv_t *token, const dbv_t *val)
+{
+ dbh_t *handle = vhandle;
+ bool ret;
+
+ ret = kcdbset(handle->dbp, token->data, token->leng, val->data, val->leng);
+ if (!ret) {
+ print_error(__FILE__, __LINE__,
+ "kcdbset: (%.*s, %.*s), err: %d, %s",
+ CLAMP_INT_MAX(token->leng), (char *)token->data,
+ CLAMP_INT_MAX(val->leng), (char *)val->data,
+ kcdbecode(handle->dbp), kcdbemsg(handle->dbp));
+ exit(EX_ERROR);
+ }
+
+ return 0;
+}
+
+
+void db_close(void *vhandle)
+{
+ dbh_t *handle = vhandle;
+
+ if (handle == NULL)
+ return;
+
+ if (DEBUG_DATABASE(1))
+ fprintf(dbgout, "kcdbclose: %s\n", handle->name);
+
+ if (!kcdbclose(handle->dbp))
+ print_error(__FILE__, __LINE__, "kcdbclose: %s, err: %d, %s",
+ handle->name,
+ kcdbecode(handle->dbp), kcdbemsg(handle->dbp));
+
+ dbh_free(handle);
+}
+
+
+void db_flush(void *vhandle)
+{
+ dbh_t *handle = vhandle;
+
+ if (!kcdbsync(handle->dbp, false, NULL, NULL))
+ print_error(__FILE__, __LINE__, "kcdbsync(), err: %d, %s",
+ kcdbecode(handle->dbp), kcdbemsg(handle->dbp));
+}
+
+ex_t db_foreach(void *vhandle, db_foreach_t hook, void *userdata)
+{
+ dbh_t *handle = vhandle;
+ KCCUR *cursor;
+ dbv_t dbv_key, dbv_data;
+ size_t ksiz, dsiz;
+ int ret;
+ ex_t retval = EX_OK;
+ char *key;
+ const char *data;
+
+ cursor = kcdbcursor(handle->dbp);
+ if (!kccurjump(cursor)) {
+ print_error(__FILE__, __LINE__, "kccurjump(), err: %d, %s",
+ kcdbecode(handle->dbp), kcdbemsg(handle->dbp));
+ retval = EX_ERROR;
+ goto done;
+ }
+
+ while ((key = kccurget(cursor, &ksiz, &data, &dsiz, true)) != NULL) {
+ /* Copy to dbv_key and dbv_data */
+ dbv_key.data = xstrdup(key);
+ dbv_key.leng = ksiz;
+ dbv_data.data = xstrdup(data);
+ dbv_data.leng = dsiz;
+
+ /* Call function */
+ ret = hook(&dbv_key, &dbv_data, userdata);
+
+ xfree(dbv_key.data);
+ xfree(dbv_data.data);
+ kcfree(key);
+
+ if (ret != 0)
+ break;
+ }
+
+done:
+ kccurdel(cursor);
+
+ return retval;
+}
+
+const char *db_str_err(int e)
+{
+ UNUSED(e);
+ return "unknown error";
+}
diff --git a/src/tests/t.frame b/src/tests/t.frame
index 355f6f2..7eaa221 100755
--- a/src/tests/t.frame
+++ b/src/tests/t.frame
@@ -48,6 +48,7 @@ case $DB_NAME in
esac ;;
*QDBM*) DB_TXN=false ;;
*Tokyo*) DB_TXN=true ;;
+ *Kyoto*) DB_TXN=true ;;
*SQLite*) DB_TXN=true ;;
*TrivialDB*) DB_TXN=false ;;
*) echo >&2 "Unknown data base type in bogofilter -V: $DB_NAME"