summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Colin Kissa <andrew@topdog.za.net>2016-08-14 13:45:08 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2016-08-14 13:45:40 +0100
commit5bde3efabfec675b323501cae5e3a99784afcc31 (patch)
treebdb8686393521becc0c7552d066afa0646028eff /src
parenteea0defeafb2d80a0ce656518523c0e928df4933 (diff)
LMDB: introduce as Experimental. Bug 1856
Diffstat (limited to 'src')
-rwxr-xr-xsrc/scripts/MakeLinks2
-rwxr-xr-xsrc/scripts/lookups-Makefile5
-rw-r--r--src/src/EDITME7
-rw-r--r--src/src/config.h.defaults1
-rw-r--r--src/src/drtables.c7
-rw-r--r--src/src/exim.c6
-rw-r--r--src/src/lookups/Makefile2
-rw-r--r--src/src/lookups/lmdb.c160
8 files changed, 189 insertions, 1 deletions
diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks
index 7a5649ef8..86f748c15 100755
--- a/src/scripts/MakeLinks
+++ b/src/scripts/MakeLinks
@@ -31,7 +31,7 @@ mkdir lookups
cd lookups
# Makefile is generated
for f in README cdb.c dbmdb.c dnsdb.c dsearch.c ibase.c ldap.h ldap.c \
- lsearch.c mysql.c redis.c nis.c nisplus.c oracle.c passwd.c \
+ lmdb.c lsearch.c mysql.c redis.c nis.c nisplus.c oracle.c passwd.c \
pgsql.c spf.c sqlite.c testdb.c whoson.c \
lf_functions.h lf_check_file.c lf_quote.c lf_sqlperform.c
do
diff --git a/src/scripts/lookups-Makefile b/src/scripts/lookups-Makefile
index 4e69a9a77..db2d184a7 100755
--- a/src/scripts/lookups-Makefile
+++ b/src/scripts/lookups-Makefile
@@ -177,6 +177,11 @@ fi
OBJ="${OBJ} spf.o"
+if want_experimental LMDB
+then
+ OBJ="${OBJ} lmdb.o"
+fi
+
echo "MODS = $MODS"
echo "OBJ = $OBJ"
diff --git a/src/src/EDITME b/src/src/EDITME
index ac8c642bc..10e5ccacb 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -488,6 +488,13 @@ EXIM_MONITOR=eximon.bin
# Uncomment the following to include extra information in fail DSN message (bounces)
# EXPERIMENTAL_DSN_INFO=yes
+# Uncomment the following to add LMDB lookup support
+# You need to have LMDB installed on your system (https://github.com/LMDB/lmdb)
+# Depending on where it is installed you may have to edit the CFLAGS and LDFLAGS lines.
+# EXPERIMENTAL_LMDB=yes
+# CFLAGS += -I/usr/local/include
+# LDFLAGS += -llmdb
+
###############################################################################
# THESE ARE THINGS YOU MIGHT WANT TO SPECIFY #
###############################################################################
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index 9d5f4c402..fe5878aaf 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -177,6 +177,7 @@ it's a default value. */
#define EXPERIMENTAL_DCC
#define EXPERIMENTAL_DSN_INFO
#define EXPERIMENTAL_DMARC
+#define EXPERIMENTAL_LMDB
#define EXPERIMENTAL_SPF
#define EXPERIMENTAL_SRS
diff --git a/src/src/drtables.c b/src/src/drtables.c
index c83012944..c807d86c7 100644
--- a/src/src/drtables.c
+++ b/src/src/drtables.c
@@ -500,6 +500,9 @@ extern lookup_module_info pgsql_lookup_module_info;
#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
extern lookup_module_info redis_lookup_module_info;
#endif
+#if defined(EXPERIMENTAL_LMDB)
+extern lookup_module_info lmdb_lookup_module_info;
+#endif
#if defined(EXPERIMENTAL_SPF)
extern lookup_module_info spf_lookup_module_info;
#endif
@@ -585,6 +588,10 @@ init_lookup_list(void)
addlookupmodule(NULL, &redis_lookup_module_info);
#endif
+#ifdef EXPERIMENTAL_LMDB
+ addlookupmodule(NULL, &lmdb_lookup_module_info);
+#endif
+
#ifdef EXPERIMENTAL_SPF
addlookupmodule(NULL, &spf_lookup_module_info);
#endif
diff --git a/src/src/exim.c b/src/src/exim.c
index 14e0b9d67..1ad76dea2 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -842,6 +842,9 @@ fprintf(f, "Support for:");
#ifdef SUPPORT_SOCKS
fprintf(f, " SOCKS");
#endif
+#ifdef EXPERIMENTAL_LMDB
+ fprintf(f, " Experimental_LMDB");
+#endif
#ifdef EXPERIMENTAL_SPF
fprintf(f, " Experimental_SPF");
#endif
@@ -887,6 +890,9 @@ fprintf(f, "Lookups (built-in):");
#if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
fprintf(f, " ldap ldapdn ldapm");
#endif
+#ifdef EXPERIMENTAL_LMDB
+ fprintf(f, " lmdb");
+#endif
#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
fprintf(f, " mysql");
#endif
diff --git a/src/src/lookups/Makefile b/src/src/lookups/Makefile
index 6ba0cb169..7c9700690 100644
--- a/src/src/lookups/Makefile
+++ b/src/src/lookups/Makefile
@@ -34,6 +34,7 @@ dnsdb.o: $(PHDRS) dnsdb.c
dsearch.o: $(PHDRS) dsearch.c
ibase.o: $(PHDRS) ibase.c
ldap.o: $(PHDRS) ldap.c
+lmdb.o: $(PHDRS) lmdb.c
lsearch.o: $(PHDRS) lsearch.c
mysql.o: $(PHDRS) mysql.c
nis.o: $(PHDRS) nis.c
@@ -53,6 +54,7 @@ dnsdb.so: $(PHDRS) dnsdb.c
dsearch.so: $(PHDRS) dsearch.c
ibase.so: $(PHDRS) ibase.c
ldap.so: $(PHDRS) ldap.c
+lmdb.so: $(PHDRS) lmdb.c
lsearch.so: $(PHDRS) lsearch.c
mysql.so: $(PHDRS) mysql.c
nis.so: $(PHDRS) nis.c
diff --git a/src/src/lookups/lmdb.c b/src/src/lookups/lmdb.c
new file mode 100644
index 000000000..8b0ffd2dd
--- /dev/null
+++ b/src/src/lookups/lmdb.c
@@ -0,0 +1,160 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) University of Cambridge 2016 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+#include "../exim.h"
+
+#ifdef EXPERIMENTAL_LMDB
+
+#include <lmdb.h>
+
+typedef struct lmdbstrct
+{
+MDB_txn *txn;
+MDB_dbi db_dbi;
+} Lmdbstrct;
+
+
+/*************************************************
+* Open entry point *
+*************************************************/
+
+static void *
+lmdb_open(uschar * filename, uschar ** errmsg)
+{
+MDB_env * db_env = NULL;
+Lmdbstrct * lmdb_p;
+int ret, save_errno;
+const uschar * errstr;
+
+lmdb_p = store_get(sizeof(Lmdbstrct));
+lmdb_p->txn = NULL;
+
+if ((ret = mdb_env_create(&db_env)))
+ {
+ errstr = US"create environment";
+ goto bad;
+ }
+
+if ((ret = mdb_env_open(db_env, CS filename, MDB_NOSUBDIR|MDB_RDONLY, 0660)))
+ {
+ errstr = US"open environment";
+ goto bad;
+ }
+
+if ((ret = mdb_txn_begin(db_env, NULL, MDB_RDONLY, &lmdb_p->txn)))
+ {
+ errstr = US"start transaction";
+ goto bad;
+ }
+
+if ((ret = mdb_open(lmdb_p->txn, NULL, 0, &lmdb_p->db_dbi)))
+ {
+ errstr = US"open database";
+ goto bad;
+ }
+
+return lmdb_p;
+
+bad:
+ save_errno = errno;
+ if (lmdb_p->txn) mdb_txn_abort(lmdb_p->txn);
+ if (db_env) mdb_env_close(db_env);
+ *errmsg = string_sprintf("LMDB: Unable to %s: %s", errstr, mdb_strerror(ret));
+ errno = save_errno;
+ return NULL;
+}
+
+
+/*************************************************
+* Find entry point *
+*************************************************/
+
+static int
+lmdb_find(void * handle, uschar * filename,
+ const uschar * keystring, int length, uschar ** result, uschar ** errmsg,
+ uint * do_cache)
+{
+int ret;
+MDB_val dbkey, data;
+Lmdbstrct * lmdb_p = handle;
+
+dbkey.mv_data = CS keystring;
+dbkey.mv_size = length;
+
+DEBUG(D_lookup) debug_printf("LMDB: lookup key: %s\n", (char *)keystring);
+
+if ((ret = mdb_get(lmdb_p->txn, lmdb_p->db_dbi, &dbkey, &data)) == 0)
+ {
+ *result = string_copyn(US data.mv_data, data.mv_size);
+ DEBUG(D_lookup) debug_printf("LMDB: lookup result: %s\n", *result);
+ return OK;
+ }
+else if (ret == MDB_NOTFOUND)
+ {
+ *errmsg = US"LMDB: lookup, no data found";
+ DEBUG(D_lookup) debug_printf("%s\n", *errmsg);
+ return FAIL;
+ }
+else
+ {
+ *errmsg = string_sprintf("LMDB: lookup error: %s", mdb_strerror(ret));
+ DEBUG(D_lookup) debug_printf("%s\n", *errmsg);
+ return DEFER;
+ }
+}
+
+
+/*************************************************
+* Close entry point *
+*************************************************/
+
+static void
+lmdb_close(void * handle)
+{
+Lmdbstrct * lmdb_p = handle;
+MDB_env * db_env = mdb_txn_env(lmdb_p->txn);
+mdb_txn_abort(lmdb_p->txn);
+mdb_env_close(db_env);
+}
+
+
+/*************************************************
+* Version reporting entry point *
+*************************************************/
+
+#include "../version.h"
+
+void
+lmdb_version_report(FILE * f)
+{
+fprintf(f, "Library version: LMDB: Compile: %d.%d.%d\n",
+ MDB_VERSION_MAJOR, MDB_VERSION_MINOR, MDB_VERSION_PATCH);
+#ifdef DYNLOOKUP
+fprintf(f, " Exim version %s\n", EXIM_VERSION_STR);
+#endif
+}
+
+static lookup_info lmdb_lookup_info = {
+ US"lmdb", /* lookup name */
+ lookup_absfile, /* query-style lookup */
+ lmdb_open, /* open function */
+ NULL, /* no check function */
+ lmdb_find, /* find function */
+ lmdb_close, /* close function */
+ NULL, /* tidy function */
+ NULL, /* quoting function */
+ lmdb_version_report /* version reporting */
+};
+
+#ifdef DYNLOOKUP
+# define lmdb_lookup_module_info _lookup_module_info
+#endif /* DYNLOOKUP */
+
+static lookup_info *_lookup_list[] = { &lmdb_lookup_info };
+lookup_module_info lmdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
+
+#endif /* EXPERIMENTAL_LMDB */