|
@@ -2,16 +2,6 @@
|
|
|
|
|
|
#include "store_mdb.h"
|
|
|
|
|
|
-
|
|
|
- * TODO At the moment up to 64-bit key / hash values are allowed. Later on,
|
|
|
- * 128-bit keys should be allowed by compile options, and that will no longer
|
|
|
- * be compatible with integer keys and data. When 128-bit keys are supported,
|
|
|
- * integer keys should remain available for code compiled with 64-bit keys.
|
|
|
- */
|
|
|
-#define INT_KEY_MASK MDB_INTEGERKEY
|
|
|
-#define INT_DUP_KEY_MASK MDB_DUPSORT | MDB_DUPFIXED | MDB_INTEGERKEY
|
|
|
-#define INT_DUPDATA_MASK MDB_DUPSORT | MDB_DUPFIXED | MDB_INTEGERDUP
|
|
|
-
|
|
|
|
|
|
* Number of DBs defined.
|
|
|
*/
|
|
@@ -70,28 +60,40 @@ struct MatchArgs {
|
|
|
|
|
|
static LSUP_Buffer *default_ctx = NULL;
|
|
|
|
|
|
+
|
|
|
+ * TODO At the moment up to 64-bit key / hash values are allowed. Later on,
|
|
|
+ * 128-bit keys should be allowed by compile options, and that will no longer
|
|
|
+ * be compatible with integer keys and data. When 128-bit keys are supported,
|
|
|
+ * integer keys should remain available for code compiled with 64-bit keys.
|
|
|
+ */
|
|
|
+#define DUPSORT_MASK MDB_DUPSORT
|
|
|
+#define DUPFIXED_MASK MDB_DUPSORT | MDB_DUPFIXED
|
|
|
+#define INT_KEY_MASK MDB_INTEGERKEY
|
|
|
+#define INT_DUP_KEY_MASK MDB_DUPSORT | MDB_DUPFIXED | MDB_INTEGERKEY
|
|
|
+#define INT_DUPDATA_MASK MDB_DUPSORT | MDB_DUPFIXED | MDB_INTEGERDUP
|
|
|
+
|
|
|
|
|
|
* Main DBs. These are the master information containers.
|
|
|
*
|
|
|
* Data columns are: identifier prefix, DB label, flags.
|
|
|
*/
|
|
|
#define MAIN_TABLE \
|
|
|
- ENTRY( T_ST, "t:st", INT_KEY_MASK ) \
|
|
|
- ENTRY( SPO_C, "spo:c", INT_DUPDATA_MASK) \
|
|
|
- ENTRY( C_, "c:", INT_KEY_MASK ) \
|
|
|
+ ENTRY( T_ST, "t:st", 0 ) \
|
|
|
+ ENTRY( SPO_C, "spo:c", DUPFIXED_MASK ) \
|
|
|
+ ENTRY( C_, "c:", 0 ) \
|
|
|
ENTRY( PFX_NS, "pfx:ns", 0 ) \
|
|
|
|
|
|
|
|
|
* Lookup DBs. These are indices and may be destroyed and rebuilt.
|
|
|
*/
|
|
|
#define LOOKUP_TABLE \
|
|
|
- ENTRY( S_PO, "s:po", INT_DUP_KEY_MASK) \
|
|
|
- ENTRY( P_SO, "p:so", INT_DUP_KEY_MASK) \
|
|
|
- ENTRY( O_SP, "o:sp", INT_DUP_KEY_MASK) \
|
|
|
- ENTRY( PO_S, "po:s", INT_DUPDATA_MASK) \
|
|
|
- ENTRY( SO_P, "so:p", INT_DUPDATA_MASK) \
|
|
|
- ENTRY( SP_O, "sp:o", INT_DUPDATA_MASK) \
|
|
|
- ENTRY( C_SPO, "c:spo", INT_DUP_KEY_MASK) \
|
|
|
+ ENTRY( S_PO, "s:po", DUPFIXED_MASK ) \
|
|
|
+ ENTRY( P_SO, "p:so", DUPFIXED_MASK ) \
|
|
|
+ ENTRY( O_SP, "o:sp", DUPFIXED_MASK ) \
|
|
|
+ ENTRY( PO_S, "po:s", DUPFIXED_MASK ) \
|
|
|
+ ENTRY( SO_P, "so:p", DUPFIXED_MASK ) \
|
|
|
+ ENTRY( SP_O, "sp:o", DUPFIXED_MASK ) \
|
|
|
+ ENTRY( C_SPO, "c:spo", DUPFIXED_MASK ) \
|
|
|
ENTRY( NS_PFX, "ns:pfx", 0 ) \
|
|
|
|
|
|
|
|
@@ -178,13 +180,13 @@ static int index_triple(
|
|
|
LSUP_MDBStore *store, StoreOp op,
|
|
|
LSUP_TripleKey spok, LSUP_Key ck);
|
|
|
|
|
|
-inline static LSUP_rc match_callback_0bound(
|
|
|
+inline static LSUP_rc lookup_0bound(
|
|
|
struct MDBStore *store, struct MatchArgs *args);
|
|
|
-inline static LSUP_rc match_callback_1bound(
|
|
|
+inline static LSUP_rc lookup_1bound(
|
|
|
struct MDBStore *store, struct MatchArgs *args);
|
|
|
-inline static LSUP_rc match_callback_2bound(
|
|
|
+inline static LSUP_rc lookup_2bound(
|
|
|
struct MDBStore *store, struct MatchArgs *args);
|
|
|
-inline static LSUP_rc match_callback_3bound(
|
|
|
+inline static LSUP_rc lookup_3bound(
|
|
|
struct MDBStore *store, struct MatchArgs *args);
|
|
|
|
|
|
inline static int check_txn_open(MDB_txn *txn, bool write);
|
|
@@ -333,8 +335,21 @@ LSUP_store_size(LSUP_MDBStore *store)
|
|
|
{
|
|
|
if(!(store->state & LSSTORE_INIT)) return 0;
|
|
|
|
|
|
+ bool txn_pending = false;
|
|
|
+ if (!store->txn) {
|
|
|
+ mdb_txn_begin(store->env, NULL, 0, &store->txn);
|
|
|
+ txn_pending = true;
|
|
|
+ }
|
|
|
+
|
|
|
MDB_stat stat;
|
|
|
- mdb_stat(store->txn, store->dbi[IDX_SPO_C], &stat);
|
|
|
+ int rc = mdb_stat(store->txn, store->dbi[IDX_SPO_C], &stat);
|
|
|
+ TRACE("Stat rc: %d\n", rc);
|
|
|
+
|
|
|
+
|
|
|
+ if(txn_pending) {
|
|
|
+ mdb_txn_abort(store->txn);
|
|
|
+ store->txn = NULL;
|
|
|
+ }
|
|
|
|
|
|
return stat.ms_entries;
|
|
|
}
|
|
@@ -488,27 +503,28 @@ LSUP_store_key_to_sterm(
|
|
|
|
|
|
|
|
|
LSUP_rc
|
|
|
-LSUP_store_match_callback(
|
|
|
- LSUP_MDBStore *store, LSUP_SerTerm sspoc[], size_t *ct,
|
|
|
+LSUP_store_lookup(
|
|
|
+ LSUP_MDBStore *store, LSUP_SerTerm *sspoc[], size_t *ct,
|
|
|
mdb_store_match_fn_t callback_fn, void *ctx)
|
|
|
{
|
|
|
LSUP_TripleKey spok = {
|
|
|
- LSUP_sterm_to_key(sspoc),
|
|
|
- LSUP_sterm_to_key(sspoc + 1),
|
|
|
- LSUP_sterm_to_key(sspoc + 2),
|
|
|
+ LSUP_sterm_to_key(sspoc[0]),
|
|
|
+ LSUP_sterm_to_key(sspoc[1]),
|
|
|
+ LSUP_sterm_to_key(sspoc[2]),
|
|
|
};
|
|
|
|
|
|
- LSUP_Key ck = store->default_ctx ? LSUP_sterm_to_key(sspoc + 3) : NULL_KEY;
|
|
|
+ LSUP_Key ck = store->default_ctx ? LSUP_sterm_to_key(sspoc[3]) : NULL_KEY;
|
|
|
|
|
|
struct MatchArgs args_s;
|
|
|
struct MatchArgs *args = &args_s;
|
|
|
args->ct = ct;
|
|
|
+ *args->ct = 0;
|
|
|
args->callback_fn = callback_fn;
|
|
|
args->ctx = ctx;
|
|
|
|
|
|
|
|
|
if (spok[0] != NULL_KEY && spok[1] != NULL_KEY && spok[2] != NULL_KEY) {
|
|
|
- return match_callback_3bound(store, args);
|
|
|
+ return lookup_3bound(store, args);
|
|
|
}
|
|
|
|
|
|
else if (spok[0] != NULL_KEY) {
|
|
@@ -518,15 +534,15 @@ LSUP_store_match_callback(
|
|
|
if (spok[1] != NULL_KEY) {
|
|
|
args->luks[1] = spok[1];
|
|
|
args->idx1 = 1;
|
|
|
- return match_callback_2bound(store, args);
|
|
|
+ return lookup_2bound(store, args);
|
|
|
|
|
|
} else if (spok[2] != NULL_KEY) {
|
|
|
args->luks[1] = spok[2];
|
|
|
args->idx1 = 2;
|
|
|
- return match_callback_2bound(store, args);
|
|
|
+ return lookup_2bound(store, args);
|
|
|
|
|
|
} else {
|
|
|
- return match_callback_1bound(store, args);
|
|
|
+ return lookup_1bound(store, args);
|
|
|
}
|
|
|
|
|
|
} else if (spok[1] != NULL_KEY) {
|
|
@@ -535,20 +551,20 @@ LSUP_store_match_callback(
|
|
|
if (spok[2] != NULL_KEY) {
|
|
|
args->luks[1] = spok[2];
|
|
|
args->idx1 = 2;
|
|
|
- return match_callback_2bound(store, args);
|
|
|
+ return lookup_2bound(store, args);
|
|
|
|
|
|
} else {
|
|
|
args->idx0 = 1;
|
|
|
- return match_callback_1bound(store, args);
|
|
|
+ return lookup_1bound(store, args);
|
|
|
}
|
|
|
|
|
|
} else if (spok[2] != NULL_KEY) {
|
|
|
args->luks[0] = spok[2];
|
|
|
args->idx0 = 2;
|
|
|
- return match_callback_1bound(store, args);
|
|
|
+ return lookup_1bound(store, args);
|
|
|
|
|
|
} else {
|
|
|
- return match_callback_0bound(store, args);
|
|
|
+ return lookup_0bound(store, args);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -668,6 +684,8 @@ index_triple(
|
|
|
int rc = LSUP_NOACTION;
|
|
|
MDB_val v1, v2;
|
|
|
|
|
|
+ printf("Indexing triple: %lx %lx %lx\n", spok[0], spok[1], spok[2]);
|
|
|
+
|
|
|
|
|
|
if (op == OP_REMOVE) {
|
|
|
if (ck != NULL_KEY) {
|
|
@@ -739,16 +757,26 @@ index_triple(
|
|
|
mdb_cursor_close(cur2);
|
|
|
|
|
|
} else {
|
|
|
- CHECK(
|
|
|
- mdb_put(store->txn, db1, &v1, &v2, MDB_NODUPDATA),
|
|
|
- db_rc, _index_triple_exit);
|
|
|
- CHECK(
|
|
|
- mdb_put(store->txn, db2, &v2, &v1, MDB_NODUPDATA),
|
|
|
- db_rc, _index_triple_exit);
|
|
|
+ printf("Indexing in %s: ", db_labels[lookup_indices[i]]);
|
|
|
+ printf(
|
|
|
+ "%lx: %lx %lx\n", *(size_t*)(v1.mv_data),
|
|
|
+ *(size_t*)(v2.mv_data), *(size_t*)(v2.mv_data) + 1);
|
|
|
+
|
|
|
+ db_rc = mdb_put(store->txn, db1, &v1, &v2, MDB_NODUPDATA);
|
|
|
+ if (db_rc != MDB_SUCCESS && db_rc != MDB_KEYEXIST)
|
|
|
+ return LSUP_DB_ERR;
|
|
|
+
|
|
|
+ printf("Indexing in %s: ", db_labels[lookup_indices[i + 3]]);
|
|
|
+ printf(
|
|
|
+ "%lx %lx: %lx\n", *(size_t*)(v2.mv_data),
|
|
|
+ *(size_t*)(v2.mv_data) + 1, *(size_t*)(v1.mv_data));
|
|
|
+
|
|
|
+ db_rc = mdb_put(store->txn, db2, &v2, &v1, MDB_NODUPDATA);
|
|
|
+ if (db_rc != MDB_SUCCESS && db_rc != MDB_KEYEXIST)
|
|
|
+ return LSUP_DB_ERR;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-_index_triple_exit:
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -756,7 +784,7 @@ _index_triple_exit:
|
|
|
|
|
|
|
|
|
inline static LSUP_rc
|
|
|
-match_callback_0bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
+lookup_0bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
{
|
|
|
int rc = LSUP_NORESULT;
|
|
|
|
|
@@ -768,9 +796,11 @@ match_callback_0bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
|
|
|
if(args->ct) {
|
|
|
MDB_stat stat;
|
|
|
- mdb_stat(store->txn, store->dbi[IDX_SPO_C], &stat);
|
|
|
+ mdb_stat(txn, store->dbi[IDX_SPO_C], &stat);
|
|
|
|
|
|
*args->ct = stat.ms_entries;
|
|
|
+
|
|
|
+ if (!args->callback_fn && *args->ct > 0) rc = LSUP_OK;
|
|
|
}
|
|
|
|
|
|
MDB_cursor *cur;
|
|
@@ -795,26 +825,34 @@ _match0b_abort:
|
|
|
|
|
|
|
|
|
inline static LSUP_rc
|
|
|
-match_callback_1bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
+lookup_1bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
{
|
|
|
- int rc = LSUP_NORESULT;
|
|
|
+ int rc = LSUP_NORESULT, db_rc;
|
|
|
|
|
|
const uint8_t *term_order = lookup_ordering_1bound[args->idx0];
|
|
|
|
|
|
+ TRACE("Looking up 1 bound term: %lx\n", args->luks[0]);
|
|
|
+
|
|
|
MDB_txn *txn;
|
|
|
if(store->txn) txn = store->txn;
|
|
|
- else mdb_txn_begin(store->env, NULL, MDB_RDONLY, &txn);
|
|
|
+ else {
|
|
|
+ db_rc = mdb_txn_begin(store->env, NULL, MDB_RDONLY, &txn);
|
|
|
+ if (db_rc != MDB_SUCCESS) abort();
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
MDB_cursor *cur;
|
|
|
- mdb_cursor_open(txn, store->dbi[args->idx0], &cur);
|
|
|
+ mdb_cursor_open(txn, store->dbi[lookup_indices[args->idx0]], &cur);
|
|
|
|
|
|
MDB_val key_v, data_v;
|
|
|
- key_v.mv_data = &args->luks;
|
|
|
+ key_v.mv_data = args->luks;
|
|
|
key_v.mv_size = KLEN;
|
|
|
|
|
|
if(args->ct) {
|
|
|
- mdb_cursor_get(cur, &key_v, &data_v, MDB_SET);
|
|
|
- mdb_cursor_count(cur, args->ct);
|
|
|
+ db_rc = mdb_cursor_get(cur, &key_v, &data_v, MDB_SET);
|
|
|
+ db_rc = mdb_cursor_count(cur, args->ct);
|
|
|
+
|
|
|
+ if (!args->callback_fn && *args->ct > 0) rc = LSUP_OK;
|
|
|
}
|
|
|
|
|
|
if(args->callback_fn) {
|
|
@@ -848,7 +886,7 @@ _match1b_abort:
|
|
|
|
|
|
|
|
|
inline static LSUP_rc
|
|
|
-match_callback_2bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
+lookup_2bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
{
|
|
|
int rc = LSUP_NORESULT;
|
|
|
|
|
@@ -876,6 +914,9 @@ match_callback_2bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
luk2_offset = 0;
|
|
|
}
|
|
|
dbi = store->dbi[lookup_indices[i + 3]];
|
|
|
+ TRACE(
|
|
|
+ "Looking up 2 bound in %s\n",
|
|
|
+ db_labels[lookup_indices[i + 3]]);
|
|
|
|
|
|
break;
|
|
|
}
|
|
@@ -898,7 +939,7 @@ match_callback_2bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
else mdb_txn_begin(store->env, NULL, MDB_RDONLY, &txn);
|
|
|
|
|
|
MDB_cursor *cur;
|
|
|
- mdb_cursor_open(txn, store->dbi[dbi], &cur);
|
|
|
+ mdb_cursor_open(txn, dbi, &cur);
|
|
|
|
|
|
MDB_val key_v, data_v;
|
|
|
key_v.mv_data = luk;
|
|
@@ -907,6 +948,8 @@ match_callback_2bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
if(args->ct) {
|
|
|
mdb_cursor_get(cur, &key_v, &data_v, MDB_SET);
|
|
|
mdb_cursor_count(cur, args->ct);
|
|
|
+
|
|
|
+ if (!args->callback_fn && *args->ct > 0) rc = LSUP_OK;
|
|
|
}
|
|
|
|
|
|
if(args->callback_fn) {
|
|
@@ -940,7 +983,7 @@ _match2b_abort:
|
|
|
|
|
|
|
|
|
inline static LSUP_rc
|
|
|
-match_callback_3bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
+lookup_3bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
{
|
|
|
int rc = LSUP_NORESULT;
|
|
|
|
|
@@ -959,7 +1002,9 @@ match_callback_3bound(struct MDBStore *store, struct MatchArgs *args)
|
|
|
|
|
|
if(args->ct) {
|
|
|
if (mdb_cursor_get(cur, &key_v, NULL, MDB_SET) == MDB_SUCCESS)
|
|
|
- rc = mdb_cursor_count(cur, args->ct);
|
|
|
+ mdb_cursor_count(cur, args->ct);
|
|
|
+
|
|
|
+ if (!args->callback_fn && *args->ct > 0) rc = LSUP_OK;
|
|
|
}
|
|
|
|
|
|
if(args->callback_fn) {
|