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 VOLK_rc rc = mdb_txn_begin (env, p, f, tp);
237 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);
246txn_commit (MDB_txn *t) {
248 return mdb_txn_commit (t);
263mdbstore_setup (
const char *
id,
bool clear)
267 const char *path = mdbstore_path_from_id (
id);
271 if (clear)
rm_r (path);
278 RCCK (mdb_env_create (&env));
280 RCCK (mdb_env_set_maxdbs (env,
N_DB));
282 log_debug (
"Environment opened at %s.", path);
285 RCCK (txn_begin (env, NULL, 0, &txn));
287 for (
int i = 0; i <
N_DB; i++) {
288 log_trace (
"Creating DB %s", db_labels[i]);
290 mdb_dbi_open (txn, db_labels[i], db_flags[i] | MDB_CREATE, &dbi)
296 CHECK (mdb_dbi_open (
297 txn, db_labels[IDX_T_ST], db_flags[IDX_T_ST], &dbi), fail);
298 CHECK (mdb_stat (txn, dbi, &stat), fail);
300 if (stat.ms_entries == 0) {
301 log_debug (
"Loading initial data into %s", path);
304 CHECK (mdb_cursor_open (txn, dbi, &cur), fail);
308 key.mv_size =
sizeof (k);
313 VOLK_rc db_rc = mdb_cursor_put (cur, &key, &data, 0);
317 CHECK (txn_commit (txn), fail);
340mdbstore_new (
const char *
id,
size_t _unused)
348 const char *path = mdbstore_path_from_id (
id);
349 if (!path)
return NULL;
354 RCNL (mdb_env_create (&store->
env));
359 char *env_mapsize = getenv (
"VOLK_MDB_MAPSIZE");
361 else sscanf (env_mapsize,
"%zu", &mapsize);
363 "Setting environment map size at %s to %zu Mb.",
364 path, mapsize / 1024 / 1024);
365 CHECK (mdb_env_set_mapsize (store->
env, mapsize), fail);
370 CHECK (txn_begin (store->
env, NULL, 0, &txn), fail);
371 for (
int i = 0; i <
N_DB; i++)
372 CHECK (mdb_dbi_open (
373 txn, db_labels[i], db_flags[i], store->
dbi + i), fail);
376 CHECK (txn_commit(txn), fail);
379 log_info (
"Created MDB environment at %s", path);
384 if (txn) mdb_txn_abort (txn);
385 mdb_env_close (store->
env);
392mdbstore_free (
void *h)
397 mdb_env_get_path (store->
env, &path);
398 log_info (
"Closing MDB environment at %s.", path);
399 mdb_env_close (store->
env);
407mdbstore_stat (
const MDBStore *store, MDB_stat *stat)
412 RCCK (txn_begin (store->
env, NULL, MDB_RDONLY, &txn));
414 if (mdb_stat (txn, store->
dbi[IDX_SPO_C], stat) != MDB_SUCCESS)
423mdbstore_size (
const void *h)
429 if (mdbstore_stat (store, &stat) !=
VOLK_OK)
return 0;
431 return stat.ms_entries;
441 RCNL (mdb_env_get_path (store->
env, &path));
443 char *
id = malloc (strlen (path) + 8);
444 sprintf (
id,
"file://%s", path);
456 RCCK (txn_begin (store->
env, NULL, flags, (MDB_txn **) th));
463mdbstore_txn_commit (
void *th)
465 RCCK (txn_commit (th));
472mdbstore_txn_abort (
void *th)
473{ mdb_txn_abort (th); }
492mdbstore_add_init (
void *h,
const VOLK_Buffer *sc,
void *th)
504 CHECK (txn_begin (store->
env, th, 0, &it->
txn), fail);
512 it->
key.mv_data = &it->
luc;
517 int db_rc = mdb_put (
519 &it->
key, &it->
data, MDB_NOOVERWRITE);
520 if (db_rc != MDB_SUCCESS && db_rc != MDB_KEYEXIST) {
522 mdb_txn_abort (it->
txn);
526 log_debug (
"No context passed to iterator, using default.");
555 for (
int i = 0; i < 3; i++) {
560 it->
key.mv_data = spok + i;
567 &it->
key, &it->
data, MDB_NOOVERWRITE);
568 if (db_rc != MDB_SUCCESS && db_rc != MDB_KEYEXIST) {
574 log_trace (
"Inserting spok: {%x, %x, %x}", spok[0], spok[1], spok[2]);
578 it->
key.mv_data = spok;
587 &it->
key, &it->
data, MDB_NODUPDATA);
590 if (db_rc != MDB_SUCCESS) {
592 "MDB error while inserting triple: %s",
VOLK_strerror(db_rc));
605mdbstore_add_done (
void *h)
609 log_debug (
"Committing add transaction.");
611 if (txn_commit (it->
txn) != MDB_SUCCESS) {
612 mdb_txn_abort (it->
txn);
624mdbstore_add_abort (
void *h)
627 mdb_txn_abort (it->
txn);
640 MDB_val key_v, data_v;
641 key_v.mv_data = (
void*)&key;
642 key_v.mv_size =
KLEN;
644 db_rc = mdb_get (txn, store->
dbi[IDX_T_ST], &key_v, &data_v);
647 if (db_rc == MDB_SUCCESS) {
648 sterm->
addr = data_v.mv_data;
649 sterm->
size = data_v.mv_size;
651 }
else if (db_rc == MDB_NOTFOUND) {
682 if (th) it->
txn = th;
686 log_trace (
"Opening new lookup transaction @%p", it->
txn);
691 RCNL (mdb_cursor_open (
699 it->
luk[0] = spok[0];
700 it->
luk[1] = spok[1];
701 it->
luk[2] = spok[2];
702 PRCNL (lookup_3bound (it, ct));
705 it->
luk[0] = spok[0];
710 it->
luk[1] = spok[1];
712 PRCNL (lookup_2bound (idx0, idx1, it, ct));
716 it->
luk[1] = spok[2];
718 PRCNL (lookup_2bound (idx0, idx1, it, ct));
721 }
else PRCNL (lookup_1bound (idx0, it, ct));
724 it->
luk[0] = spok[1];
729 it->
luk[1] = spok[2];
731 PRCNL (lookup_2bound (idx0, idx1, it, ct));
734 }
else PRCNL (lookup_1bound (idx0, it, ct));
738 it->
luk[0] = spok[2];
740 PRCNL (lookup_1bound (idx0, it, ct));
743 }
else PRCNL (lookup_0bound (it, ct));
770 data.mv_data = &it->
luc;
785 "Found spok: {%x, %x, %x}",
788 key.mv_data = it->
spok;
789 db_rc = mdb_cursor_get (it->
ctx_cur, &key, &data, MDB_GET_BOTH);
791 if (db_rc == MDB_NOTFOUND) {
807 "Found spok in any context: {%x, %x, %x}",
813 key.mv_data = it->
spok;
814 db_rc = mdb_cursor_get (it->
ctx_cur, &key, &data, MDB_SET_KEY);
815 if (db_rc != MDB_SUCCESS) {
816 log_error (
"No context found for triple!");
821 db_rc = mdb_cursor_count (it->
ctx_cur, &ct);
824 VOLK_Key *tmp_ck = realloc (it->
ck, sizeof (*it->
ck) * (ct + 1));
831 memcpy (it->
ck + i++, data.mv_data, sizeof (*it->
ck));
833 mdb_cursor_get (it->
ctx_cur, &key, &data, MDB_NEXT_DUP)
847 VOLK_rc rc = mdbiter_next_key (it);
862 log_trace (
"Allocating %lu context buffers + sentinel.", i - 1);
863 ctx = malloc(i *
sizeof (*ctx));
866 for (i = 0; it->
ck[i]; i++)
868 memset (ctx + i, 0,
sizeof (*ctx));
881mdbiter_free (
void *h)
886 if (it->
cur) mdb_cursor_close (it->
cur);
901 unsigned char *trp_data = NULL;
911 CHECK (rc = txn_begin (store->
env, p_txn, 0, &txn),
finally);
913 MDB_cursor *i_cur, *d_cur;
915 rc = mdb_cursor_open (txn, store->
dbi[IDX_C_SPO], &i_cur),
921 key.mv_data = &new_ck;
923 rc = mdb_cursor_get (i_cur, &key, &data, MDB_SET);
924 if (rc == MDB_SUCCESS) {
926 "Context key %lu already exists. Not replacing old graph.",
930 }
else if (rc != MDB_NOTFOUND)
CHECK (rc, close_i);
933 CHECK (rc = mdbstore_add_term (store, new_c, txn), close_i);
935 key.mv_data = &old_ck;
937 rc = mdb_cursor_get (i_cur, &key, &data, MDB_SET);
938 if (rc == MDB_NOTFOUND) {
939 log_info (
"No triples found associated with old context.");
942 }
else CHECK (rc, close_i);
947 CHECK (rc = mdb_cursor_count (i_cur, &trp_ct), close_i);
948 trp_data = malloc (trp_ct *
TRP_KLEN);
956 rc = mdb_cursor_get (i_cur, &key, &data, MDB_GET_MULTIPLE);
957 if (rc != MDB_SUCCESS) {
963 memcpy (trp_data + loc_cur, data.mv_data, data.mv_size);
964 loc_cur += data.mv_size;
965 }
while (mdb_cursor_get (
966 i_cur, &key, &data, MDB_NEXT_MULTIPLE) == MDB_SUCCESS);
969 key.mv_data = &old_ck;
972 CHECK (rc = mdb_cursor_get (i_cur, &key, NULL, MDB_SET), close_i);
973 CHECK (rc = mdb_cursor_del (i_cur, MDB_NODUPDATA), close_i);
976 key.mv_data = &new_ck;
977 for (
size_t i = 0; i < trp_ct; i++) {
978 data.mv_data = trp_data + i * data.mv_size;
980 rc = mdb_cursor_put (i_cur, &key, &data, MDB_APPENDDUP),
995 CHECK (rc = mdb_cursor_open (txn, store->
dbi[IDX_SPO_C], &d_cur), close_i);
998 for (
size_t i = 0; i < trp_ct; i++) {
999 key.mv_data = trp_data + i * key.mv_size;
1000 data.mv_data = &old_ck;
1002 rc = mdb_cursor_get (d_cur, &key, &data, MDB_GET_BOTH),
1004 CHECK (rc = mdb_cursor_del (d_cur, 0), close_d);
1005 data.mv_data = &new_ck;
1007 rc = mdb_cursor_put (d_cur, &key, &data, MDB_NOOVERWRITE),
1012 mdb_cursor_close (d_cur);
1014 mdb_cursor_close (i_cur);
1017 else mdb_txn_abort (txn);
1019 if (trp_data) free (trp_data);
1035 RCCK (txn_begin (store->
env, th, 0, &txn));
1037 mdb_cursor_open (txn, store->
dbi[IDX_SPO_C], &cur);
1041 MDB_val spok_v, ck_v;
1043 ck_v.mv_size =
KLEN;
1047 size_t *ct = ct_p ? ct_p : malloc (
sizeof (*ct));
1049 MDBIterator *it = mdbstore_lookup (store, ss, sp, so, sc, txn, ct);
1051 log_debug (
"Found %lu triples to remove.", *ct);
1055 while (mdbiter_next_key (it) ==
VOLK_OK) {
1056 log_trace (
"Adding triple #%zu to remove list.", i);
1062 for (i = 0; i < *ct; i++) {
1063 spok_v.mv_data = keys + i * 3;
1066 "Removing triple #%zu: %x {%x %x %x}",
1073 rc = mdb_cursor_get (cur, &spok_v, &ck_v, MDB_GET_BOTH);
1074 if (rc == MDB_NOTFOUND) {
1075 log_warn (
"No key found in spo:c DB.");
1077 }
else CHECK (rc, fail);
1080 CHECK (rc = mdb_cursor_del (cur, 0), fail);
1081 CHECK (rc = index_triple (
1086 CHECK (txn_commit (txn), fail);
1091 mdb_txn_abort (txn);
1110mdbstore_add_term (
void *h,
const VOLK_Buffer *sterm,
void *th)
1121 else RCCK (txn_begin (store->
env, th, 0, &txn));
1124 CHECK (mdb_cursor_open (txn, store->
dbi[IDX_T_ST], &cur), fail);
1128 key.mv_size =
sizeof (k);
1130 data.mv_data = sterm->
addr;
1131 data.mv_size = sterm->
size;
1133 db_rc = mdb_cursor_put (cur, &key, &data, MDB_NOOVERWRITE);
1134 if (db_rc != MDB_KEYEXIST)
CHECK (db_rc, fail);
1136 if (txn != th)
CHECK (db_rc = txn_commit (txn), fail);
1141 if (txn != th) mdb_txn_abort (txn);
1142 log_trace (
"Aborted txn for adding term.");
1155 else CHECK (txn_begin (store->
env, NULL, MDB_RDONLY, &txn), fail);
1159 CHECK (mdb_cursor_open (txn, store->
dbi[IDX_C_SPO], &cur), fail);
1161 db_rc = mdb_cursor_get (cur, &key, &data, MDB_FIRST);
1164 while (db_rc == MDB_SUCCESS) {
1165 tdata = realloc (tdata, (i + 1) *
sizeof (*tdata));
1169 CHECK (key_to_sterm (store, txn, tkey, tdata[i]), fail);
1170 db_rc = mdb_cursor_get (cur, &key, &data, MDB_NEXT_NODUP);
1174 tdata = realloc (tdata, i *
sizeof (data));
1176 mdb_cursor_close (cur);
1177 if (txn != th) mdb_txn_abort (txn);
1182 if (txn != th) mdb_txn_abort (txn);
1183 if (tdata) free (tdata);
1189 .name =
"MDB Store",
1193 .setup_fn = mdbstore_setup,
1194 .new_fn = mdbstore_new,
1195 .free_fn = mdbstore_free,
1197 .size_fn = mdbstore_size,
1200 .txn_begin_fn = mdbstore_txn_begin,
1201 .txn_commit_fn = mdbstore_txn_commit,
1202 .txn_abort_fn = mdbstore_txn_abort,
1203 .iter_txn_fn = mdbiter_txn,
1205 .add_init_fn = mdbstore_add_init,
1206 .add_iter_fn = mdbstore_add_iter,
1207 .add_abort_fn = mdbstore_add_abort,
1208 .add_done_fn = mdbstore_add_done,
1209 .add_term_fn = mdbstore_add_term,
1211 .update_ctx_fn = mdbstore_update_ctx,
1213 .lookup_fn = mdbstore_lookup,
1214 .lu_next_fn = mdbiter_next,
1215 .lu_free_fn = mdbiter_free,
1217 .remove_fn = mdbstore_remove,
1243 log_trace (
"Indexing triple: {%x %x %x}", spok[0], spok[1], spok[2]);
1248 if (ck ==
NULL_KEY)
goto skip_remove;
1256 RCCK (mdb_cursor_open (txn, store->
dbi[IDX_C_SPO], &cur));
1257 db_rc = mdb_cursor_get (cur, &v1, &v2, MDB_GET_BOTH);
1258 if (db_rc != MDB_NOTFOUND) {
1260 RCCK (mdb_cursor_del (cur, 0));
1265 mdb_cursor_close (cur);
1268 }
else if (op ==
OP_ADD) {
1278 txn, store->
dbi[IDX_C_SPO],
1279 &v1, &v2, MDB_NODUPDATA);
1281 if (db_rc != MDB_KEYEXIST) rc =
VOLK_OK;
1296 for (
int i = 0; i < 3; i++) {
1298 db1 = store->
dbi[lookup_indices[i]],
1299 db2 = store->
dbi[lookup_indices[i + 3]];
1301 v1.mv_data = spok + i;
1302 v2.mv_data = dbl_keys[i];
1307 mdb_cursor_open(txn, store->
dbi[lookup_indices[i]], &cur1);
1308 RCCK (db_rc = mdb_cursor_get (cur1, &v1, &v2, MDB_GET_BOTH));
1309 mdb_cursor_del (cur1, 0);
1310 mdb_cursor_close (cur1);
1313 v1.mv_data = spok + i;
1314 v2.mv_data = dbl_keys[i];
1318 mdb_cursor_open(txn, store->
dbi[lookup_indices[i + 3]], &cur2);
1319 RCCK (db_rc = mdb_cursor_get (cur2, &v2, &v1, MDB_GET_BOTH));
1320 mdb_cursor_del (cur2, 0);
1321 mdb_cursor_close (cur2);
1327 log_trace (
"Indexing in %s: ", db_labels[lookup_indices[i]]);
1329 "%x: %x %x", *(
size_t*)(v1.mv_data),
1330 *(
size_t*)(v2.mv_data), *(
size_t*)(v2.mv_data) + 1);
1332 db_rc = mdb_put (txn, db1, &v1, &v2, MDB_NODUPDATA);
1334 if (db_rc == MDB_SUCCESS) rc =
VOLK_OK;
1335 else if (db_rc != MDB_KEYEXIST)
return VOLK_DB_ERR;
1338 log_trace (
"Indexing in %s: ", db_labels[lookup_indices[i + 3]]);
1340 "%x %x: %x", *(
size_t*)(v2.mv_data),
1341 *(
size_t*)(v2.mv_data) + 1, *(
size_t*)(v1.mv_data));
1343 db_rc = mdb_put (txn, db2, &v2, &v1, MDB_NODUPDATA);
1345 if (db_rc == MDB_SUCCESS) rc =
VOLK_OK;
1346 else if (db_rc != MDB_KEYEXIST)
return VOLK_DB_ERR;
1364 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_NEXT_NODUP);
1376 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_NEXT_DUP);
1396 "Composed triple: {%x %x %x}",
1410 it->
rc = mdb_cursor_get (
1411 it->
cur, &it->
key, &it->
data, MDB_NEXT_MULTIPLE);
1432 if (it->
i < it->
data.mv_size /
KLEN - 1)
1438 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_NEXT_MULTIPLE);
1451{ it->
rc = MDB_NOTFOUND; }
1459 log_debug (
"Looking up 0 bound terms.");
1464 RCCK (it->
rc = mdb_cursor_open (
1467 it->
key.mv_data = &it->
luc;
1470 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1472 if (it->
rc == MDB_NOTFOUND) *ct = 0;
1475 mdb_cursor_count (it->
cur, ct);
1484 RCCK (it->
rc = mdb_cursor_open (
1486 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_FIRST);
1488 if (it->
rc == MDB_NOTFOUND) *ct = 0;
1492 mdb_stat (it->
txn, it->
store->
dbi[IDX_S_PO], &stat);
1494 *ct = stat.ms_entries;
1500 if (it->
rc != MDB_NOTFOUND)
RCCK (it->
rc);
1507lookup_1bound (uint8_t idx0,
MDBIterator *it,
size_t *ct)
1509 it->
term_order = (
const uint8_t*)lookup_ordering_1bound[idx0];
1513 RCCK (mdb_cursor_open (
1516 it->
key.mv_data = it->
luk;
1536 ct_it->
luk[0] = it->
luk[0];
1540 PRCCK (lookup_1bound (idx0, ct_it, NULL));
1543 while (
VOLK_END != (db_rc = mdbiter_next_key (ct_it))) {
1549 if (ct_it->
cur) mdb_cursor_close (ct_it->
cur);
1554 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1555 if (it->
rc == MDB_SUCCESS) mdb_cursor_count (it->
cur, ct);
1563 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1564 if (it->
rc == MDB_SUCCESS)
1565 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_GET_MULTIPLE);
1566 if (it->
rc != MDB_NOTFOUND)
RCCK (it->
rc);
1573lookup_2bound(uint8_t idx0, uint8_t idx1,
MDBIterator *it,
size_t *ct)
1575 uint8_t luk1_offset, luk2_offset;
1579 for (
int i = 0; i < 3; i++) {
1582 idx0 == lookup_ordering_2bound[i][0] &&
1583 idx1 == lookup_ordering_2bound[i][1]
1585 idx0 == lookup_ordering_2bound[i][1] &&
1586 idx1 == lookup_ordering_2bound[i][0]
1589 it->
term_order = (
const uint8_t*)lookup_ordering_2bound[i];
1597 dbi = it->
store->
dbi[lookup_indices[i + 3]];
1599 "Looking up 2 bound in %s",
1600 db_labels[lookup_indices[i + 3]]);
1608 "Values %d and %d not found in lookup keys.",
1615 luk[luk1_offset] = it->
luk[0];
1616 luk[luk2_offset] = it->
luk[1];
1618 it->
key.mv_data = luk;
1621 mdb_cursor_open (it->
txn, dbi, &it->
cur);
1622 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1635 ct_it->
luk[0] = it->
luk[0];
1636 ct_it->
luk[1] = it->
luk[1];
1640 lookup_2bound (idx0, idx1, ct_it, NULL);
1642 while (mdbiter_next_key (ct_it) !=
VOLK_END) (*ct) ++;
1645 if (ct_it->
cur) mdb_cursor_close (ct_it->
cur);
1650 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1651 if (it->
rc == MDB_SUCCESS) mdb_cursor_count (it->
cur, ct);
1659 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_SET);
1660 if (it->
rc == MDB_SUCCESS)
1661 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_GET_MULTIPLE);
1662 if (it->
rc != MDB_NOTFOUND)
RCCK (it->
rc);
1672 "Looking up 3 bound: {%x, %x, %x}",
1675 it->
key.mv_data = it->
luk;
1678 it->
rc = mdb_cursor_open (
1689 it->
data.mv_data = it->
luk + 1;
1693 it->
rc = mdb_cursor_get (it->
cur, &it->
key, &it->
data, MDB_GET_BOTH);
1694 if (it->
rc != MDB_NOTFOUND)
RCCK (it->
rc);
1696 mdb_cursor_close (it->
cur);
1699 if (ct && it->
rc == MDB_SUCCESS) *ct = 1;
#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.
#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 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 CALLOC_GUARD(var, rc)
Allocate one pointer with calloc and return rc if it fails.
VOLK_rc rm_r(const char *path)
Remove a directory recursively (POSIX compatible).
#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.
VOLK_rc mkdir_p(const char *_path, mode_t mode)
Make recursive directories.
#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).
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.
#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.
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_env * env
Environment handle.
MDB_dbi dbi[N_DB]
DB handles. Refer to DbIdx enum.
General-purpose data buffer.