Lookups: per-searchtype options framework
[exim.git] / src / src / lookups / lmdb.c
CommitLineData
5bde3efa
ACK
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
f9ba5e22 5/* Copyright (c) University of Cambridge 2016 - 2018*/
5bde3efa
ACK
6/* See the file NOTICE for conditions of use and distribution. */
7
8#include "../exim.h"
9
10#ifdef EXPERIMENTAL_LMDB
11
12#include <lmdb.h>
13
14typedef struct lmdbstrct
15{
16MDB_txn *txn;
17MDB_dbi db_dbi;
18} Lmdbstrct;
19
20
21/*************************************************
22* Open entry point *
23*************************************************/
24
25static void *
d447dbd1 26lmdb_open(const uschar * filename, uschar ** errmsg)
5bde3efa
ACK
27{
28MDB_env * db_env = NULL;
29Lmdbstrct * lmdb_p;
30int ret, save_errno;
31const uschar * errstr;
32
f3ebb786 33lmdb_p = store_get(sizeof(Lmdbstrct), FALSE);
5bde3efa
ACK
34lmdb_p->txn = NULL;
35
36if ((ret = mdb_env_create(&db_env)))
37 {
38 errstr = US"create environment";
39 goto bad;
40 }
41
42if ((ret = mdb_env_open(db_env, CS filename, MDB_NOSUBDIR|MDB_RDONLY, 0660)))
43 {
a3382e87 44 errstr = string_sprintf("open environment with %s", filename);
5bde3efa
ACK
45 goto bad;
46 }
47
48if ((ret = mdb_txn_begin(db_env, NULL, MDB_RDONLY, &lmdb_p->txn)))
49 {
50 errstr = US"start transaction";
51 goto bad;
52 }
53
54if ((ret = mdb_open(lmdb_p->txn, NULL, 0, &lmdb_p->db_dbi)))
55 {
56 errstr = US"open database";
57 goto bad;
58 }
59
60return lmdb_p;
61
62bad:
63 save_errno = errno;
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));
67 errno = save_errno;
68 return NULL;
69}
70
71
72/*************************************************
73* Find entry point *
74*************************************************/
75
76static int
d447dbd1 77lmdb_find(void * handle, const uschar * filename,
5bde3efa 78 const uschar * keystring, int length, uschar ** result, uschar ** errmsg,
67a57a5a 79 uint * do_cache, const uschar * opts)
5bde3efa
ACK
80{
81int ret;
82MDB_val dbkey, data;
83Lmdbstrct * lmdb_p = handle;
84
85dbkey.mv_data = CS keystring;
86dbkey.mv_size = length;
87
42c7f0b4 88DEBUG(D_lookup) debug_printf_indent("LMDB: lookup key: %s\n", CS keystring);
5bde3efa
ACK
89
90if ((ret = mdb_get(lmdb_p->txn, lmdb_p->db_dbi, &dbkey, &data)) == 0)
91 {
92 *result = string_copyn(US data.mv_data, data.mv_size);
42c7f0b4 93 DEBUG(D_lookup) debug_printf_indent("LMDB: lookup result: %s\n", *result);
5bde3efa
ACK
94 return OK;
95 }
96else if (ret == MDB_NOTFOUND)
97 {
98 *errmsg = US"LMDB: lookup, no data found";
42c7f0b4 99 DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg);
5bde3efa
ACK
100 return FAIL;
101 }
102else
103 {
104 *errmsg = string_sprintf("LMDB: lookup error: %s", mdb_strerror(ret));
42c7f0b4 105 DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg);
5bde3efa
ACK
106 return DEFER;
107 }
108}
109
110
111/*************************************************
112* Close entry point *
113*************************************************/
114
115static void
116lmdb_close(void * handle)
117{
118Lmdbstrct * lmdb_p = handle;
119MDB_env * db_env = mdb_txn_env(lmdb_p->txn);
120mdb_txn_abort(lmdb_p->txn);
121mdb_env_close(db_env);
122}
123
124
125/*************************************************
126* Version reporting entry point *
127*************************************************/
128
129#include "../version.h"
130
131void
132lmdb_version_report(FILE * f)
133{
134fprintf(f, "Library version: LMDB: Compile: %d.%d.%d\n",
135 MDB_VERSION_MAJOR, MDB_VERSION_MINOR, MDB_VERSION_PATCH);
136#ifdef DYNLOOKUP
137fprintf(f, " Exim version %s\n", EXIM_VERSION_STR);
138#endif
139}
140
141static lookup_info lmdb_lookup_info = {
142 US"lmdb", /* lookup name */
143 lookup_absfile, /* query-style lookup */
144 lmdb_open, /* open function */
145 NULL, /* no check function */
146 lmdb_find, /* find function */
147 lmdb_close, /* close function */
148 NULL, /* tidy function */
149 NULL, /* quoting function */
150 lmdb_version_report /* version reporting */
151};
152
153#ifdef DYNLOOKUP
154# define lmdb_lookup_module_info _lookup_module_info
155#endif /* DYNLOOKUP */
156
157static lookup_info *_lookup_list[] = { &lmdb_lookup_info };
158lookup_module_info lmdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
159
160#endif /* EXPERIMENTAL_LMDB */