11#if (defined DEBUG || defined TESTING)
12#define DEFAULT_MAPSIZE 1<<24
13#elif !(defined __LP64__ || defined __LLP64__) || \
14 defined _WIN32 && !defined _WIN64
15#define DEFAULT_MAPSIZE 1<<31
17#define DEFAULT_MAPSIZE 1UL<<40
20#define ENV_DIR_MODE 0750
21#define ENV_FILE_MODE 0640
53typedef struct mdbstore_t {
73typedef struct mdbstore_iter_t {
101#define DUPFIXED_MASK MDB_DUPSORT | MDB_DUPFIXED
110 ENTRY( T_ST, "t:st", 0 ) \
111 ENTRY( SPO_C, "spo:c", DUPFIXED_MASK ) \
116#define LOOKUP_TABLE \
118 ENTRY( S_PO, "s:po", DUPFIXED_MASK ) \
119 ENTRY( P_SO, "p:so", DUPFIXED_MASK ) \
120 ENTRY( O_SP, "o:sp", DUPFIXED_MASK ) \
121 ENTRY( PO_S, "po:s", DUPFIXED_MASK ) \
122 ENTRY( SO_P, "so:p", DUPFIXED_MASK ) \
123 ENTRY( SP_O, "sp:o", DUPFIXED_MASK ) \
124 ENTRY( C_SPO, "c:spo", DUPFIXED_MASK ) \
129#define ENTRY(a, b, c) static const DbLabel DB_##a = b;
141#define ENTRY(a, b, c) IDX_##a,
150static const char *db_labels[
N_DB] = {
151#define ENTRY(a, b, c) DB_##a,
160static const unsigned int db_flags[
N_DB] = {
161#define ENTRY(a, b, c) c,
173static DBIdx lookup_indices[9] = {
174#define ENTRY(a, b, c) IDX_##a,
179static const uint8_t lookup_ordering_1bound[3][3] = {
185static const uint8_t lookup_ordering_2bound[3][3] = {
195static int index_triple(
201inline static VOLK_rc lookup_1bound (
203inline static VOLK_rc lookup_2bound (
204 uint8_t idx0, uint8_t idx1,
MDBIterator *it,
size_t *ct);
209mdbstore_path_from_id (
const char *
id)
212 if (!
id)
id = getenv (
"VOLK_MDB_STORE_URN");
216 "`VOLK_MDB_STORE_URN' environment variable is not "
217 "set. The default URN %s has been set as the store ID.",
id
219 }
else if (strncmp (
"file://",
id, 7) != 0) {
220 log_error (
"MDB store ID must be in the `file://<abs_path>` format.");
234txn_begin (MDB_env *env, MDB_txn *p,
unsigned int f, MDB_txn **tp) {
235 RCCK (mdb_txn_begin (env, p, f, tp));
237 RCCK (mdb_env_get_path (env, &path));
239 "BEGIN %s transaction %p child of %p in env %s",
240 f == 0 ?
"RW" :
"RO", *tp, p, path);
247txn_commit (MDB_txn *t) {
249 return mdb_txn_commit (t);
264mdbstore_setup (
const char *
id,
bool clear)
268 const char *path = mdbstore_path_from_id (
id);
272 if (clear)
rm_r (path);
279 RCCK (mdb_env_create (&env));
281 RCCK (mdb_env_set_maxdbs (env,
N_DB));
283 log_debug (
"Environment opened at %s.", path);
286 RCCK (txn_begin (env, NULL, 0, &txn));
288 for (
int i = 0; i <
N_DB; i++) {
289 log_trace (
"Creating DB %s", db_labels[i]);
291 mdb_dbi_open (txn, db_labels[i], db_flags[i] | MDB_CREATE, &dbi)
297 CHECK (mdb_dbi_open (
299 CHECK (mdb_stat (txn, dbi, &stat), fail);
301 if (stat.ms_entries == 0) {
302 log_debug (
"Loading initial data into %s", path);
305 CHECK (mdb_cursor_open (txn, dbi, &cur), fail);
309 key.mv_size =
sizeof (k);
314 VOLK_rc db_rc = mdb_cursor_put (cur, &key, &data, 0);
318 CHECK (txn_commit (txn), fail);
341mdbstore_new (
const char *
id,
size_t _unused)
349 const char *path = mdbstore_path_from_id (
id);
350 if (!path)
return NULL;
355 RCNL (mdb_env_create (&store->
env));
360 char *env_mapsize = getenv (
"VOLK_MDB_MAPSIZE");
362 else sscanf (env_mapsize,
"%zu", &mapsize);
364 "Setting environment map size at %s to %zu Mb.",
365 path, mapsize / 1024 / 1024);
366 CHECK (mdb_env_set_mapsize (store->
env, mapsize), fail);
371 CHECK (txn_begin (store->
env, NULL, 0, &txn), fail);
372 for (
int i = 0; i <
N_DB; i++)
373 CHECK (mdb_dbi_open (
374 txn, db_labels[i], db_flags[i], store->
dbi + i), fail);
377 CHECK (txn_commit(txn), fail);
380 log_info (
"Created MDB environment at %s", path);
385 if (txn) mdb_txn_abort (txn);
386 mdb_env_close (store->
env);
393mdbstore_free (
void *h)
398 mdb_env_get_path (store->
env, &path);
399 log_info (
"Closing MDB environment at %s.", path);
400 mdb_env_close (store->
env);
408mdbstore_stat (
const MDBStore *store, MDB_stat *stat)
413 RCCK (txn_begin (store->
env, NULL, MDB_RDONLY, &txn));
415 if (mdb_stat (txn, store->
dbi[
IDX_SPO_C], stat) != MDB_SUCCESS)
424mdbstore_size (
const void *h)
430 if (mdbstore_stat (store, &stat) !=
VOLK_OK)
return 0;
432 return stat.ms_entries;
442 RCNL (mdb_env_get_path (store->
env, &path));
444 char *
id = malloc (strlen (path) + 8);
445 sprintf (
id,
"file://%s", path);
457 RCCK (txn_begin (store->
env, NULL, flags, (MDB_txn **) th));
464mdbstore_txn_commit (
void *th)
466 RCCK (txn_commit (th));
473mdbstore_txn_abort (
void *th)
474{ mdb_txn_abort (th); }
492mdbstore_add_init (
void *h,
const VOLK_Buffer *sc,
void *th)
502 if (th) it->
txn = th;
504 CHECK (txn_begin (store->
env, th, 0, &it->
txn), fail);
514 it->
key.mv_data = &it->
luc;
519 int db_rc = mdb_put (
521 &it->
key, &it->
data, MDB_NOOVERWRITE);
522 if (db_rc != MDB_SUCCESS && db_rc != MDB_KEYEXIST) {
524 mdb_txn_abort (it->
txn);
528 log_debug (
"No context passed to iterator, using default.");
557 for (
int i = 0; i < 3; i++) {
562 it->
key.mv_data = spok + i;
569 &it->
key, &it->
data, MDB_NOOVERWRITE);
570 if (db_rc != MDB_SUCCESS && db_rc != MDB_KEYEXIST) {
576 log_trace (
"Inserting spok: {%x, %x, %x}", spok[0], spok[1], spok[2]);
580 it->
key.mv_data = spok;
589 &it->
key, &it->
data, MDB_NODUPDATA);
592 if (db_rc != MDB_SUCCESS) {
594 "MDB error while inserting triple: %s",
VOLK_strerror(db_rc));
607mdbstore_add_done (
void *h)
612 log_debug (
"Committing add transaction.");
615 if (txn_commit (it->
txn) != MDB_SUCCESS) {
616 log_error (
"Error committing transaction. Aborting instead.");
617 mdb_txn_abort (it->
txn);
630mdbstore_add_abort (
void *h)
646 MDB_val key_v, data_v;
647 key_v.mv_data = (
void*)&key;
648 key_v.mv_size =
KLEN;
650 db_rc = mdb_get (txn, store->
dbi[
IDX_T_ST], &key_v, &data_v);
653 if (db_rc == MDB_SUCCESS) {
654 sterm->
addr = data_v.mv_data;
655 sterm->
size = data_v.mv_size;
657 }
else if (db_rc == MDB_NOTFOUND) {
691 if (th) it->
txn = th;
694 log_trace (
"Opening new lookup transaction @%p", it->
txn);
699 RCNL (mdb_cursor_open (
707 it->
luk[0] = spok[0];
708 it->
luk[1] = spok[1];
709 it->
luk[2] = spok[2];
710 PRCNL (lookup_3bound (it, ct));
713 it->
luk[0] = spok[0];
718 it->
luk[1] = spok[1];
720 PRCNL (lookup_2bound (idx0, idx1, it, ct));
724 it->
luk[1] = spok[2];
726 PRCNL (lookup_2bound (idx0, idx1, it, ct));
729 }
else PRCNL (lookup_1bound (idx0, it, ct));
732 it->
luk[0] = spok[1];
737 it->
luk[1] = spok[2];
739 PRCNL (lookup_2bound (idx0, idx1, it, ct));
742 }
else PRCNL (lookup_1bound (idx0, it, ct));
746 it->
luk[0] = spok[2];
748 PRCNL (lookup_1bound (idx0, it, ct));
751 }
else PRCNL (lookup_0bound (it, ct));
778 data.mv_data = &it->
luc;
793 "Found spok: {%x, %x, %x}",
796 key.mv_data = it->
spok;
797 db_rc = mdb_cursor_get (it->
ctx_cur, &key, &data, MDB_GET_BOTH);
799 if (db_rc == MDB_NOTFOUND) {
815 "Found spok in any context: {%x, %x, %x}",
821 key.mv_data = it->
spok;
822 db_rc = mdb_cursor_get (it->
ctx_cur, &key, &data, MDB_SET_KEY);
823 if (db_rc != MDB_SUCCESS) {
824 log_error (
"No context found for triple!");
829 db_rc = mdb_cursor_count (it->
ctx_cur, &ct);
832 VOLK_Key *tmp_ck = realloc (it->
ck, sizeof (*it->
ck) * (ct + 1));
839 memcpy (it->
ck + i++, data.mv_data, sizeof (*it->
ck));
841 mdb_cursor_get (it->
ctx_cur, &key, &data, MDB_NEXT_DUP)
855 VOLK_rc rc = mdbiter_next_key (it);
870 log_trace (
"Allocating %lu context buffers + sentinel.", i - 1);
871 ctx = malloc(i *
sizeof (*ctx));
874 for (i = 0; it->
ck[i]; i++)
876 memset (ctx + i, 0,
sizeof (*ctx));
889mdbiter_free (
void *h)
894 if (it->
cur) mdb_cursor_close (it->
cur);
909 unsigned char *trp_data = NULL;
919 CHECK (rc = txn_begin (store->
env, p_txn, 0, &txn),
finally);
921 MDB_cursor *i_cur, *d_cur;
923 rc = mdb_cursor_open (txn, store->
dbi[
IDX_C_SPO], &i_cur),
929 key.mv_data = &new_ck;
931 rc = mdb_cursor_get (i_cur, &key, &data, MDB_SET);
932 if (rc == MDB_SUCCESS) {
934 "Context key %lu already exists. Not replacing old graph.",
938 }
else if (rc != MDB_NOTFOUND)
CHECK (rc, close_i);
941 CHECK (rc = mdbstore_add_term (store, new_c, txn), close_i);
943 key.mv_data = &old_ck;
945 rc = mdb_cursor_get (i_cur, &key, &data, MDB_SET);
946 if (rc == MDB_NOTFOUND) {
947 log_info (
"No triples found associated with old context.");
950 }
else CHECK (rc, close_i);
955 CHECK (rc = mdb_cursor_count (i_cur, &trp_ct), close_i);
956 trp_data = malloc (trp_ct *
TRP_KLEN);
964 rc = mdb_cursor_get (i_cur, &key, &data, MDB_GET_MULTIPLE);
965 if (rc != MDB_SUCCESS) {
971 memcpy (trp_data + loc_cur, data.mv_data, data.mv_size);
972 loc_cur += data.mv_size;
973 }
while (mdb_cursor_get (
974 i_cur, &key, &data, MDB_NEXT_MULTIPLE) == MDB_SUCCESS);
977 key.mv_data = &old_ck;
980 CHECK (rc = mdb_cursor_get (i_cur, &key, NULL, MDB_SET), close_i);
981 CHECK (rc = mdb_cursor_del (i_cur, MDB_NODUPDATA), close_i);
984 key.mv_data = &new_ck;
985 for (
size_t i = 0; i < trp_ct; i++) {
986 data.mv_data = trp_data + i * data.mv_size;
988 rc = mdb_cursor_put (i_cur, &key, &data, MDB_APPENDDUP),
1005 data.mv_size =
KLEN;
1006 for (
size_t i = 0; i < trp_ct; i++) {
1007 key.mv_data = trp_data + i * key.mv_size;
1008 data.mv_data = &old_ck;
1010 rc = mdb_cursor_get (d_cur, &key, &data, MDB_GET_BOTH),
1012 CHECK (rc = mdb_cursor_del (d_cur, 0), close_d);
1013 data.mv_data = &new_ck;
1015 rc = mdb_cursor_put (d_cur, &key, &data, MDB_NOOVERWRITE),
1020 mdb_cursor_close (d_cur);
1022 mdb_cursor_close (i_cur);
1025 else mdb_txn_abort (txn);
1027 if (trp_data) free (trp_data);
1043 RCCK (txn_begin (store->
env, th, 0, &txn));
1049 MDB_val spok_v, ck_v;
1051 ck_v.mv_size =
KLEN;
1055 size_t *ct = ct_p ? ct_p : malloc (
sizeof (*ct));
1057 MDBIterator *it = mdbstore_lookup (store, ss, sp, so, sc, txn, ct);
1059 log_debug (
"Found %lu triples to remove.", *ct);
1063 while (mdbiter_next_key (it) ==
VOLK_OK) {
1064 log_trace (
"Adding triple #%zu to remove list.", i);
1070 for (i = 0; i < *ct; i++) {
1071 spok_v.mv_data = keys + i * 3;
1074 "Removing triple #%zu: %x {%x %x %x}",
1081 rc = mdb_cursor_get (cur, &spok_v, &ck_v, MDB_GET_BOTH);
1082 if (rc == MDB_NOTFOUND) {
1083 log_warn (
"No key found in spo:c DB.");
1085 }
else CHECK (rc, fail);
1088 CHECK (rc = mdb_cursor_del (cur, 0), fail);
1089 CHECK (rc = index_triple (
1094 CHECK (txn_commit (txn), fail);
1099 mdb_txn_abort (txn);
1118mdbstore_add_term (
void *h,
const VOLK_Buffer *sterm,
void *th)
1129 else RCCK (txn_begin (store->
env, th, 0, &txn));
1136 key.mv_size =
sizeof (k);
1138 data.mv_data = sterm->
addr;
1139 data.mv_size = sterm->
size;
1141 db_rc = mdb_cursor_put (cur, &key, &data, MDB_NOOVERWRITE);
1142 if (db_rc != MDB_KEYEXIST)
CHECK (db_rc, fail);
1144 if (txn != th)
CHECK (db_rc = txn_commit (txn), fail);
1149 if (txn != th) mdb_txn_abort (txn);
1150 log_trace (
"Aborted txn for adding term.");
1163 else CHECK (txn_begin (store->
env, NULL, MDB_RDONLY, &txn), fail_txn);
1170 db_rc = mdb_cursor_get (cur, &key, &data, MDB_FIRST);
1172 while (db_rc == MDB_SUCCESS) {
1174 db_rc = mdb_cursor_get (cur, &key, &data, MDB_NEXT_NODUP);
1176 tdata = malloc ((i + 1) *
sizeof (*tdata));
1179 db_rc = mdb_cursor_get (cur, &key, &data, MDB_FIRST);
1181 while (db_rc == MDB_SUCCESS) {
1184 CHECK (key_to_sterm (store, txn, tkey, tdata[i++]), fail);
1185 db_rc = mdb_cursor_get (cur, &key, &data, MDB_NEXT_NODUP);
1188 mdb_cursor_close (cur);
1189 if (txn != th) mdb_txn_abort (txn);
1194 if (txn != th) mdb_txn_abort (txn);
1195 if (tdata) free (tdata);
1202 .name =
"MDB Store",
1206 .setup_fn = mdbstore_setup,
1207 .new_fn = mdbstore_new,
1208 .free_fn = mdbstore_free,
1210 .size_fn = mdbstore_size,
1213 .txn_begin_fn = mdbstore_txn_begin,
1214 .txn_commit_fn = mdbstore_txn_commit,
1215 .txn_abort_fn = mdbstore_txn_abort,
1216 .iter_txn_fn = mdbiter_txn,
1218 .add_init_fn = mdbstore_add_init,
1219 .add_iter_fn = mdbstore_add_iter,
1220 .add_abort_fn = mdbstore_add_abort,
1221 .add_done_fn = mdbstore_add_done,
1222 .add_term_fn = mdbstore_add_term,
1224 .update_ctx_fn = mdbstore_update_ctx,
1226 .lookup_fn = mdbstore_lookup,
1227 .lu_next_fn = mdbiter_next,
1228 .lu_free_fn = mdbiter_free,
1230 .remove_fn = mdbstore_remove,
1256 log_trace (
"Indexing triple: {%x %x %x}", spok[0], spok[1], spok[2]);
1261 if (ck ==
NULL_KEY)
goto skip_remove;
1270 db_rc = mdb_cursor_get (cur, &v1, &v2, MDB_GET_BOTH);
1271 if (db_rc != MDB_NOTFOUND) {
1273 RCCK (mdb_cursor_del (cur, 0));
1278 mdb_cursor_close (cur);
1281 }
else if (op ==
OP_ADD) {
1292 &v1, &v2, MDB_NODUPDATA);
1294 if (db_rc != MDB_KEYEXIST) rc =
VOLK_OK;
1309 for (
int i = 0; i < 3; i++) {
1311 db1 = store->
dbi[lookup_indices[i]],
1312 db2 = store->
dbi[lookup_indices[i + 3]];
1314 v1.mv_data = spok + i;
1315 v2.mv_data = dbl_keys[i];
1320 mdb_cursor_open(txn, store->
dbi[lookup_indices[i]], &cur1);
1321 RCCK (db_rc = mdb_cursor_get (cur1, &v1, &v2, MDB_GET_BOTH));
1322 mdb_cursor_del (cur1, 0);
1323 mdb_cursor_close (cur1);
1326 v1.mv_data = spok + i;
1327 v2.mv_data = dbl_keys[i];
1331 mdb_cursor_open(txn, store->
dbi[lookup_indices[i + 3]], &cur2);
1332 RCCK (db_rc = mdb_cursor_get (cur2, &v2, &v1, MDB_GET_BOTH));
1333 mdb_cursor_del (cur2, 0);
1334 mdb_cursor_close (cur2);
1340 log_trace (
"Indexing in %s: ", db_labels[lookup_indices[i]]);
1342 "%x: %x %x", *(
size_t*)(v1.mv_data),
1343 *(
size_t*)(v2.mv_data), *(
size_t*)(v2.mv_data) + 1);
1345 db_rc = mdb_put (txn, db1, &v1, &v2, MDB_NODUPDATA);
1347 if (db_rc == MDB_SUCCESS) rc =
VOLK_OK;
1348 else if (db_rc != MDB_KEYEXIST)
return VOLK_DB_ERR;
1351 log_trace (
"Indexing in %s: ", db_labels[lookup_indices[i + 3]]);
1353 "%x %x: %x", *(
size_t*)(v2.mv_data),
1354 *(
size_t*)(v2.mv_data) + 1, *(
size_t*)(v1.mv_data));
1356 db_rc = mdb_put (txn, db2, &v2, &v1, MDB_NODUPDATA);
1358 if (db_rc == MDB_SUCCESS) rc =
VOLK_OK;
1359 else if (db_rc != MDB_KEYEXIST)
return VOLK_DB_ERR;
1377 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_NEXT_NODUP);
1389 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_NEXT_DUP);
1409 "Composed triple: {%x %x %x}",
1423 it->
rc = mdb_cursor_get (
1424 it->
cur, &it->
key, &it->
data, MDB_NEXT_MULTIPLE);
1445 if (it->
i < it->
data.mv_size /
KLEN - 1)
1451 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_NEXT_MULTIPLE);
1464{ it->
rc = MDB_NOTFOUND; }
1472 log_debug (
"Looking up 0 bound terms.");
1477 RCCK (it->
rc = mdb_cursor_open (
1480 it->
key.mv_data = &it->
luc;
1483 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1485 if (it->
rc == MDB_NOTFOUND) *ct = 0;
1488 mdb_cursor_count (it->
cur, ct);
1497 RCCK (it->
rc = mdb_cursor_open (
1499 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_FIRST);
1501 if (it->
rc == MDB_NOTFOUND) *ct = 0;
1507 *ct = stat.ms_entries;
1513 if (it->
rc != MDB_NOTFOUND)
RCCK (it->
rc);
1520lookup_1bound (uint8_t idx0,
MDBIterator *it,
size_t *ct)
1522 it->
term_order = (
const uint8_t*)lookup_ordering_1bound[idx0];
1526 RCCK (mdb_cursor_open (
1529 it->
key.mv_data = it->
luk;
1549 ct_it->
luk[0] = it->
luk[0];
1553 PRCCK (lookup_1bound (idx0, ct_it, NULL));
1556 while (
VOLK_END != (db_rc = mdbiter_next_key (ct_it))) {
1562 if (ct_it->
cur) mdb_cursor_close (ct_it->
cur);
1567 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1568 if (it->
rc == MDB_SUCCESS) mdb_cursor_count (it->
cur, ct);
1576 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1577 if (it->
rc == MDB_SUCCESS)
1578 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_GET_MULTIPLE);
1579 if (it->
rc != MDB_NOTFOUND)
RCCK (it->
rc);
1586lookup_2bound(uint8_t idx0, uint8_t idx1,
MDBIterator *it,
size_t *ct)
1588 uint8_t luk1_offset, luk2_offset;
1592 for (
int i = 0; i < 3; i++) {
1595 idx0 == lookup_ordering_2bound[i][0] &&
1596 idx1 == lookup_ordering_2bound[i][1]
1598 idx0 == lookup_ordering_2bound[i][1] &&
1599 idx1 == lookup_ordering_2bound[i][0]
1602 it->
term_order = (
const uint8_t*)lookup_ordering_2bound[i];
1610 dbi = it->
store->
dbi[lookup_indices[i + 3]];
1612 "Looking up 2 bound in %s",
1613 db_labels[lookup_indices[i + 3]]);
1621 "Values %d and %d not found in lookup keys.",
1628 luk[luk1_offset] = it->
luk[0];
1629 luk[luk2_offset] = it->
luk[1];
1631 it->
key.mv_data = luk;
1634 mdb_cursor_open (it->
txn, dbi, &it->
cur);
1635 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1648 ct_it->
luk[0] = it->
luk[0];
1649 ct_it->
luk[1] = it->
luk[1];
1653 lookup_2bound (idx0, idx1, ct_it, NULL);
1655 while (mdbiter_next_key (ct_it) !=
VOLK_END) (*ct) ++;
1658 if (ct_it->
cur) mdb_cursor_close (ct_it->
cur);
1663 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1664 if (it->
rc == MDB_SUCCESS) mdb_cursor_count (it->
cur, ct);
1672 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1673 if (it->
rc == MDB_SUCCESS)
1674 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_GET_MULTIPLE);
1675 if (it->
rc != MDB_NOTFOUND)
RCCK (it->
rc);
1685 "Looking up 3 bound: {%x, %x, %x}",
1688 it->
key.mv_data = it->
luk;
1691 it->
rc = mdb_cursor_open (
1702 it->
data.mv_data = it->
luk + 1;
1706 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_GET_BOTH);
1707 if (it->
rc != MDB_NOTFOUND)
RCCK (it->
rc);
1709 mdb_cursor_close (it->
cur);
1712 if (ct && it->
rc == MDB_SUCCESS) *ct = 1;
#define NULL_TRP
"NULL" triple, a value that is never user-provided.
bool VOLK_env_is_init
Whether the environment is initialized.
#define MALLOC_GUARD(var, rc)
Allocate one pointer with malloc and return rc if it fails.
#define RCNL(exp)
Return NULL if exp returns a nonzero value.
#define NLCHECK(exp, marker)
Log error and jump to marker if exp is NULL.
#define PRCNL(exp)
Return NULL if exp returns a negative value (=error).
#define CHECK(exp, marker)
Jump to marker if exp does not return VOLK_OK.
#define NLNL(exp)
Log error and return NULL if exp is NULL.
#define CALLOC_GUARD(var, rc)
Allocate one pointer with calloc and return rc if it fails.
#define RCCK(exp)
Return exp return value if it is of VOLK_rc type and nonzero.
#define NLRCCK(exp, _rc)
Return rc return code if exp is NULL.
#define LOG_RC(rc)
Log an error or warning for return codes that are not VOLK_OK.
#define PRCCK(exp)
Return exp return value if it is of VOLK_rc type and negative (=error).
VOLK_rc rm_r(const char *path)
Remove a directory recursively (POSIX compatible).
VOLK_rc mkdir_p(const char *_path, mode_t mode)
Make recursive directories.
#define VOLK_VALUE_ERR
An invalid input value was provided.
#define VOLK_MEM_ERR
Memory allocation error.
#define VOLK_NORESULT
No result yielded.
#define VOLK_DB_ERR
Low-level database error.
#define VOLK_CONFLICT
Conflict warning.
#define VOLK_END
Loop end.
#define VOLK_OK
Generic success return code.
#define VOLK_NOACTION
No action taken.
#define VOLK_ENV_ERR
Error while handling environment setup; or environment not initialized.
#define VOLK_TXN_ERR
Error handling a store transaction.
const char * VOLK_strerror(VOLK_rc rc)
Return an error message for a return code.
#define NULL_KEY
"NULL" key, a value that is never user-provided.
VOLK_Key VOLK_buffer_hash(const VOLK_Buffer *buf)
Hash a buffer.
VOLK_Buffer * VOLK_btriple_pos(const VOLK_BufferTriple *trp, VOLK_TriplePos n)
Get serialized triple by term position.
VOLK_Buffer * VOLK_default_ctx_buf
Serialized default context.
#define BUF_DUMMY
Dummy buffer to be used with VOLK_buffer_init.
size_t VOLK_Key
Term key, i.e., hash of a serialized term.
VOLK_Key VOLK_TripleKey[3]
Array of three VOLK_Key values, representing a triple.
VOLK_Key VOLK_DoubleKey[2]
Array of two VOLK_Key values.
VOLK_StoreFlags
Store flags passed to various operations.
@ VOLK_STORE_TXN_RO
Start a read-only transaction.
@ VOLK_STORE_TXN
Supports transaction handling.
@ VOLK_STORE_COW
Copy on write.
@ VOLK_STORE_IDX
Store is fully SPO(C)-indexed.
VOLK_Buffer ** mdbstore_ctx_list(void *h, void *th)
StoreFlags
Store state flags.
@ LSSTORE_OPEN
Env is open.
const VOLK_StoreInt mdbstore_int
MDB store interface.
char * mdbstore_id(const void *h)
void(* iter_op_fn_t)(MDBIterator *it)
Iterator operation.
IterFlags
Iterator state flags.
@ ITER_OPEN_TXN
A transaction is open.
LMDB graph store backend.
#define VOLK_MDB_STORE_URN
Default MDB store identifier and location.
MDB_cursor * ctx_cur
MDB c:spo index cursor.
VOLK_TripleKey spok
Triple to be populated with match.
VOLK_Key luk[3]
0รท3 lookup keys.
MDB_cursor * cur
MDB cursor.
const uint8_t * term_order
Term order used in 1-2bound look-ups.
MDBStore * store
MDB store handle.
IterFlags flags
Iterator flags.
MDB_txn * txn
MDB transaction.
VOLK_Key luc
Ctx key to filter by. May be NULL_KEY.
size_t i
Internal counter for paged lookups.
iter_op_fn_t iter_op_fn
Function used to look up next match.
MDB_val key
Internal data handler.
int rc
MDB_* return code for the next result.
MDB_val data
Internal data handler.
StoreFlags flags
Store state flags.
MDB_dbi dbi[9]
DB handles. Refer to DbIdx enum.
MDB_env * env
Environment handle.
General-purpose data buffer.