1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) The Exim Maintainers 2020 - 2022 */
6 /* Copyright (c) University of Cambridge 2016 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-only */
16 typedef struct lmdbstrct
23 /*************************************************
25 *************************************************/
28 lmdb_open(const uschar * filename, uschar ** errmsg)
30 MDB_env * db_env = NULL;
33 const uschar * errstr;
35 lmdb_p = store_get(sizeof(Lmdbstrct), GET_UNTAINTED);
38 if ((ret = mdb_env_create(&db_env)))
40 errstr = US"create environment";
44 if ((ret = mdb_env_open(db_env, CS filename, MDB_NOSUBDIR|MDB_RDONLY, 0660)))
46 errstr = string_sprintf("open environment with %s", filename);
50 if ((ret = mdb_txn_begin(db_env, NULL, MDB_RDONLY, &lmdb_p->txn)))
52 errstr = US"start transaction";
56 if ((ret = mdb_open(lmdb_p->txn, NULL, 0, &lmdb_p->db_dbi)))
58 errstr = US"open database";
66 if (lmdb_p->txn) mdb_txn_abort(lmdb_p->txn);
67 if (db_env) mdb_env_close(db_env);
68 *errmsg = string_sprintf("LMDB: Unable to %s: %s", errstr, mdb_strerror(ret));
74 /*************************************************
76 *************************************************/
79 lmdb_find(void * handle, const uschar * filename,
80 const uschar * keystring, int length, uschar ** result, uschar ** errmsg,
81 uint * do_cache, const uschar * opts)
85 Lmdbstrct * lmdb_p = handle;
87 dbkey.mv_data = CS keystring;
88 dbkey.mv_size = length;
90 DEBUG(D_lookup) debug_printf_indent("LMDB: lookup key: %s\n", CS keystring);
92 if ((ret = mdb_get(lmdb_p->txn, lmdb_p->db_dbi, &dbkey, &data)) == 0)
94 *result = string_copyn(US data.mv_data, data.mv_size);
95 DEBUG(D_lookup) debug_printf_indent("LMDB: lookup result: %s\n", *result);
98 else if (ret == MDB_NOTFOUND)
100 *errmsg = US"LMDB: lookup, no data found";
101 DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg);
106 *errmsg = string_sprintf("LMDB: lookup error: %s", mdb_strerror(ret));
107 DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg);
113 /*************************************************
114 * Close entry point *
115 *************************************************/
118 lmdb_close(void * handle)
120 Lmdbstrct * lmdb_p = handle;
121 MDB_env * db_env = mdb_txn_env(lmdb_p->txn);
122 mdb_txn_abort(lmdb_p->txn);
123 mdb_env_close(db_env);
127 /*************************************************
128 * Version reporting entry point *
129 *************************************************/
131 #include "../version.h"
134 lmdb_version_report(gstring * g)
136 g = string_fmt_append(g, "Library version: LMDB: Compile: %d.%d.%d\n",
137 MDB_VERSION_MAJOR, MDB_VERSION_MINOR, MDB_VERSION_PATCH);
139 g = string_fmt_append(g, " Exim version %s\n", EXIM_VERSION_STR);
144 static lookup_info lmdb_lookup_info = {
145 .name = US"lmdb", /* lookup name */
146 .type = lookup_absfile, /* query-style lookup */
147 .open = lmdb_open, /* open function */
148 .check = NULL, /* no check function */
149 .find = lmdb_find, /* find function */
150 .close = lmdb_close, /* close function */
151 .tidy = NULL, /* tidy function */
152 .quote = NULL, /* quoting function */
153 .version_report = lmdb_version_report /* version reporting */
157 # define lmdb_lookup_module_info _lookup_module_info
158 #endif /* DYNLOOKUP */
160 static lookup_info *_lookup_list[] = { &lmdb_lookup_info };
161 lookup_module_info lmdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
163 #endif /* LOOKUP_LMDB */