1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) University of Cambridge 2016 - 2018*/
6 /* See the file NOTICE for conditions of use and distribution. */
10 #ifdef EXPERIMENTAL_LMDB
14 typedef struct lmdbstrct
21 /*************************************************
23 *************************************************/
26 lmdb_open(const uschar * filename, uschar ** errmsg)
28 MDB_env * db_env = NULL;
31 const uschar * errstr;
33 lmdb_p = store_get(sizeof(Lmdbstrct), FALSE);
36 if ((ret = mdb_env_create(&db_env)))
38 errstr = US"create environment";
42 if ((ret = mdb_env_open(db_env, CS filename, MDB_NOSUBDIR|MDB_RDONLY, 0660)))
44 errstr = string_sprintf("open environment with %s", filename);
48 if ((ret = mdb_txn_begin(db_env, NULL, MDB_RDONLY, &lmdb_p->txn)))
50 errstr = US"start transaction";
54 if ((ret = mdb_open(lmdb_p->txn, NULL, 0, &lmdb_p->db_dbi)))
56 errstr = US"open database";
64 if (lmdb_p->txn) mdb_txn_abort(lmdb_p->txn);
65 if (db_env) mdb_env_close(db_env);
66 *errmsg = string_sprintf("LMDB: Unable to %s: %s", errstr, mdb_strerror(ret));
72 /*************************************************
74 *************************************************/
77 lmdb_find(void * handle, const uschar * filename,
78 const uschar * keystring, int length, uschar ** result, uschar ** errmsg,
79 uint * do_cache, const uschar * opts)
83 Lmdbstrct * lmdb_p = handle;
85 dbkey.mv_data = CS keystring;
86 dbkey.mv_size = length;
88 DEBUG(D_lookup) debug_printf_indent("LMDB: lookup key: %s\n", CS keystring);
90 if ((ret = mdb_get(lmdb_p->txn, lmdb_p->db_dbi, &dbkey, &data)) == 0)
92 *result = string_copyn(US data.mv_data, data.mv_size);
93 DEBUG(D_lookup) debug_printf_indent("LMDB: lookup result: %s\n", *result);
96 else if (ret == MDB_NOTFOUND)
98 *errmsg = US"LMDB: lookup, no data found";
99 DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg);
104 *errmsg = string_sprintf("LMDB: lookup error: %s", mdb_strerror(ret));
105 DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg);
111 /*************************************************
112 * Close entry point *
113 *************************************************/
116 lmdb_close(void * handle)
118 Lmdbstrct * lmdb_p = handle;
119 MDB_env * db_env = mdb_txn_env(lmdb_p->txn);
120 mdb_txn_abort(lmdb_p->txn);
121 mdb_env_close(db_env);
125 /*************************************************
126 * Version reporting entry point *
127 *************************************************/
129 #include "../version.h"
132 lmdb_version_report(FILE * f)
134 fprintf(f, "Library version: LMDB: Compile: %d.%d.%d\n",
135 MDB_VERSION_MAJOR, MDB_VERSION_MINOR, MDB_VERSION_PATCH);
137 fprintf(f, " Exim version %s\n", EXIM_VERSION_STR);
141 static lookup_info lmdb_lookup_info = {
142 .name = US"lmdb", /* lookup name */
143 .type = lookup_absfile, /* query-style lookup */
144 .open = lmdb_open, /* open function */
145 .check = NULL, /* no check function */
146 .find = lmdb_find, /* find function */
147 .close = lmdb_close, /* close function */
148 .tidy = NULL, /* tidy function */
149 .quote = NULL, /* quoting function */
150 .version_report = lmdb_version_report /* version reporting */
154 # define lmdb_lookup_module_info _lookup_module_info
155 #endif /* DYNLOOKUP */
157 static lookup_info *_lookup_list[] = { &lmdb_lookup_info };
158 lookup_module_info lmdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
160 #endif /* EXPERIMENTAL_LMDB */