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