dovecot-2.2: dict: Added support for cdb backend.

dovecot at dovecot.org dovecot at dovecot.org
Mon Jan 21 18:31:20 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/2c249941f9c2
changeset: 15665:2c249941f9c2
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jan 21 18:31:08 2013 +0200
description:
dict: Added support for cdb backend.
Based on patch by Hleb Valoshka.

diffstat:

 configure.ac                |   23 +++++++
 src/dict/main.c             |    3 +
 src/lib-dict/Makefile.am    |    1 +
 src/lib-dict/dict-cdb.c     |  138 ++++++++++++++++++++++++++++++++++++++++++++
 src/lib-dict/dict-private.h |    1 +
 5 files changed, 166 insertions(+), 0 deletions(-)

diffs (223 lines):

diff -r 9aba8584e5eb -r 2c249941f9c2 configure.ac
--- a/configure.ac	Mon Jan 21 18:12:41 2013 +0200
+++ b/configure.ac	Mon Jan 21 18:31:08 2013 +0200
@@ -126,6 +126,11 @@
 #  want_db=no)
 want_db=no
 
+AC_ARG_WITH(cdb,
+AS_HELP_STRING([--with-cdb], [Build with CDB support]),
+  TEST_WITH(cdb, $withval),
+  want_cdb=no)
+
 dnl The --with-sql is useful only if Dovecot is being built with all the SQL
 dnl drivers as modules. If any SQL driver is built-in, this option is ignored.
 AC_ARG_WITH(sql,
@@ -2113,6 +2118,23 @@
   fi
 fi
 
+if test $want_cdb != no; then
+  AC_CHECK_LIB(cdb, cdb_init, [
+    AC_CHECK_HEADER(cdb.h, [
+      DICT_LIBS="$DICT_LIBS -lcdb"
+      AC_DEFINE(BUILD_CDB,, Build with CDB support)
+    ], [
+      if test $want_cdb = yes; then
+        AC_ERROR([Can't build with CDB support: cdb.h not found])
+      fi
+    ])
+  ], [
+    if test $want_cdb = yes; then
+      AC_ERROR([Can't build with CDB support: libcdb not found])
+    fi
+  ])
+fi
+
 if test $want_pgsql != no; then
   AC_CHECK_PROG(PG_CONFIG, pg_config, pg_config, NO)
   if test $PG_CONFIG = NO; then
@@ -2397,6 +2419,7 @@
 AC_SUBST(SQLITE_LIBS)
 
 AC_SUBST(DICT_LIBS)
+AC_SUBST(CDB_LIBS)
 AC_SUBST(dict_drivers)
 
 dnl **
diff -r 9aba8584e5eb -r 2c249941f9c2 src/dict/main.c
--- a/src/dict/main.c	Mon Jan 21 18:12:41 2013 +0200
+++ b/src/dict/main.c	Mon Jan 21 18:31:08 2013 +0200
@@ -35,6 +35,9 @@
 	/* Load built-in SQL drivers (if any) */
 	sql_drivers_init();
 	sql_drivers_register_all();
+#ifdef HAVE_CDB
+	dict_driver_register(&dict_driver_cdb);
+#endif
 
 	restrict_access_by_env(NULL, FALSE);
 	restrict_access_allow_coredumps(TRUE);
diff -r 9aba8584e5eb -r 2c249941f9c2 src/lib-dict/Makefile.am
--- a/src/lib-dict/Makefile.am	Mon Jan 21 18:12:41 2013 +0200
+++ b/src/lib-dict/Makefile.am	Mon Jan 21 18:31:08 2013 +0200
@@ -14,6 +14,7 @@
 	dict.c \
 	dict-client.c \
 	dict-file.c \
+	dict-cdb.c \
 	dict-memcached.c \
 	dict-memcached-ascii.c \
 	dict-redis.c \
diff -r 9aba8584e5eb -r 2c249941f9c2 src/lib-dict/dict-cdb.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-dict/dict-cdb.c	Mon Jan 21 18:31:08 2013 +0200
@@ -0,0 +1,138 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+
+#ifdef BUILD_CDB
+#include "dict-private.h"
+
+#include <string.h>
+#include <cdb.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define CDB_WITH_NULL 1
+#define CDB_WITHOUT_NULL 2
+
+struct cdb_dict {
+	struct dict dict;
+	struct cdb cdb;
+	char *path;
+	int fd, flag;
+};
+
+static void cdb_dict_deinit(struct dict *_dict);
+
+static int
+cdb_dict_init(struct dict *driver, const char *uri,
+	      enum dict_data_type value_type ATTR_UNUSED,
+	      const char *username ATTR_UNUSED,
+	      const char *base_dir ATTR_UNUSED,
+	      struct dict **dict_r, const char **error_r)
+{
+	struct cdb_dict *dict;
+
+	dict = i_new(struct cdb_dict, 1);
+	dict->dict = *driver;
+	dict->path = i_strdup(uri);
+	dict->flag = CDB_WITH_NULL | CDB_WITHOUT_NULL;
+
+	/* initialize cdb to 0 (unallocated) */
+	memset(&dict->cdb, 0, sizeof(struct cdb));
+
+	dict->fd = open(dict->path, O_RDONLY);
+	if (dict->fd == -1) {
+		*error_r = t_strdup_printf("open(%s) failed: %m", dict->path);
+		cdb_dict_deinit(&dict->dict);
+		return -1;
+	}
+
+#ifdef TINYCDB_VERSION
+	if (cdb_init(&dict->cdb, dict->fd) < 0) {
+		*error_r = t_strdup_printf("cdb_init(%s) failed: %m", dict->path);
+		cdb_dict_deinit(&dict->dict);
+		return -1;
+	}
+#else
+	cdb_init(&dict->cdb, dict->fd);
+#endif
+
+	*dict_r = &dict->dict;
+	return 0;
+}
+
+static void cdb_dict_deinit(struct dict *_dict)
+{
+	struct cdb_dict *dict = (struct cdb_dict *)_dict;
+
+	/* we can safely deinit unallocated cdb */
+	cdb_free(&dict->cdb);
+
+	if (dict->fd != -1) {
+		if (close(dict->fd) < 0)
+			i_error("close(%s) failed: %m", dict->path);
+	}
+
+	i_free(dict->path);
+	i_free(dict);
+}
+
+static int cdb_dict_lookup(struct dict *_dict, pool_t pool,
+			   const char *key, const char **value_r)
+{
+	struct cdb_dict *dict = (struct cdb_dict *)_dict;
+	unsigned datalen;
+	int ret = 0;
+	char *data;
+
+	/* keys and values may be null terminated... */
+	if ((dict->flag & CDB_WITH_NULL) != 0) {
+		ret = cdb_find(&dict->cdb, key, (unsigned)strlen(key)+1);
+		if (ret > 0)
+			dict->flag &= ~CDB_WITHOUT_NULL;
+	}
+
+	/* ...or not */
+	if (ret == 0 && (dict->flag & CDB_WITHOUT_NULL) != 0) {
+		ret = cdb_find(&dict->cdb, key, (unsigned)strlen(key));
+		if (ret > 0)
+			dict->flag &= ~CDB_WITH_NULL;
+	}
+
+	if (ret <= 0) {
+		*value_r = NULL;
+		/* something bad with db */
+		if (ret < 0) {
+			i_error("cdb_lookup(%s) failed: %m", dict->path);
+			return -1;
+		}
+		/* found nothing */
+		return 0;
+	}
+
+	datalen = cdb_datalen(&dict->cdb);
+	data = p_new(pool, char, datalen + 1);
+	cdb_read(&dict->cdb, data, datalen, cdb_datapos(&dict->cdb));
+	*value_r = data;
+	return 1;
+}
+
+struct dict dict_driver_cdb = {
+	.name = "cdb",
+	{
+		cdb_dict_init,
+		cdb_dict_deinit,
+		NULL,
+		cdb_dict_lookup,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL
+	}
+};
+#endif
diff -r 9aba8584e5eb -r 2c249941f9c2 src/lib-dict/dict-private.h
--- a/src/lib-dict/dict-private.h	Mon Jan 21 18:12:41 2013 +0200
+++ b/src/lib-dict/dict-private.h	Mon Jan 21 18:31:08 2013 +0200
@@ -59,5 +59,6 @@
 extern struct dict dict_driver_memcached;
 extern struct dict dict_driver_memcached_ascii;
 extern struct dict dict_driver_redis;
+extern struct dict dict_driver_cdb;
 
 #endif


More information about the dovecot-cvs mailing list