|
@@ -29,6 +29,7 @@ typedef char DbLabel[8];
|
|
typedef enum {
|
|
typedef enum {
|
|
LSSTORE_INIT = 1, // Is the store environment set up on disk?
|
|
LSSTORE_INIT = 1, // Is the store environment set up on disk?
|
|
LSSTORE_OPEN = 3, // Is the environment open? Assumes init is set.
|
|
LSSTORE_OPEN = 3, // Is the environment open? Assumes init is set.
|
|
|
|
+ LSSTORE_DIRTY_TXN = 4, // Main txn was opened in a subroutine.
|
|
} StoreState;
|
|
} StoreState;
|
|
|
|
|
|
|
|
|
|
@@ -38,13 +39,13 @@ typedef enum {
|
|
} StoreOp;
|
|
} StoreOp;
|
|
|
|
|
|
|
|
|
|
-struct MDBStore {
|
|
|
|
|
|
+typedef struct MDBStore {
|
|
MDB_env * env; // Environment handle.
|
|
MDB_env * env; // Environment handle.
|
|
MDB_txn * txn; // Current transaction.
|
|
MDB_txn * txn; // Current transaction.
|
|
MDB_dbi dbi[N_DB]; // DB handles. Refer to DbIdx enum.
|
|
MDB_dbi dbi[N_DB]; // DB handles. Refer to DbIdx enum.
|
|
- LSUP_Buffer * default_ctx;// Default context as a serialized URI.
|
|
|
|
- StoreState state; // Store state (initialized, open etc.)
|
|
|
|
-};
|
|
|
|
|
|
+ LSUP_Buffer * default_ctx;// Default ctx as a serialized URI.
|
|
|
|
+ StoreState state; // Store state.
|
|
|
|
+} MDBStore;
|
|
|
|
|
|
|
|
|
|
/** @brief Iterator operation.
|
|
/** @brief Iterator operation.
|
|
@@ -62,19 +63,20 @@ typedef void (*iter_op_fn_t)(struct MDBIterator *it);
|
|
|
|
|
|
/** @brief Triple iterator.
|
|
/** @brief Triple iterator.
|
|
*/
|
|
*/
|
|
-struct MDBIterator {
|
|
|
|
- struct MDBStore *store; // MDB store pointer.
|
|
|
|
- MDB_txn *txn; // MDB transaction.
|
|
|
|
- MDB_cursor *cur; // MDB cursor.
|
|
|
|
- MDB_val key, data; // Internal data handlers.
|
|
|
|
- LSUP_TripleKey *spok; // Triple to be populated with match.
|
|
|
|
- LSUP_Key ck; // Context key to filter by. May be NULL_TRP.
|
|
|
|
- iter_op_fn_t iter_op_fn; // Function used to look up next match.
|
|
|
|
- const uint8_t *term_order; // Term order used in 1-2bound look-ups.
|
|
|
|
- LSUP_Key luk[3]; // 0÷3 lookup keys.
|
|
|
|
- size_t i; // Internal counter for paged lookups.
|
|
|
|
- int rc; // MDB_* return code for the next result.
|
|
|
|
-};
|
|
|
|
|
|
+typedef struct MDBIterator {
|
|
|
|
+ MDBStore * store; // MDB store pointer.
|
|
|
|
+ MDB_txn * txn; // MDB transaction.
|
|
|
|
+ MDB_cursor * cur; // MDB cursor.
|
|
|
|
+ MDB_val key, data; // Internal data handlers.
|
|
|
|
+ LSUP_TripleKey spok; // Triple to be populated with match.
|
|
|
|
+ LSUP_Key ck; // Ctx key to filter by. May be NULL_TRP.
|
|
|
|
+ iter_op_fn_t iter_op_fn; // Function used to look up next match.
|
|
|
|
+ const uint8_t * term_order; // Term order used in 1-2bound look-ups.
|
|
|
|
+ LSUP_Key luk[3]; // 0÷3 lookup keys.
|
|
|
|
+ size_t i; // Internal counter for paged lookups.
|
|
|
|
+ int rc; // MDB_* return code for the next result.
|
|
|
|
+ StoreState state; // State flags.
|
|
|
|
+} MDBIterator;
|
|
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -200,15 +202,14 @@ static int index_triple(
|
|
LSUP_TripleKey spok, LSUP_Key ck);
|
|
LSUP_TripleKey spok, LSUP_Key ck);
|
|
|
|
|
|
inline static LSUP_rc lookup_0bound(
|
|
inline static LSUP_rc lookup_0bound(
|
|
- struct MDBStore *store, struct MDBIterator *it, size_t *ct);
|
|
|
|
|
|
+ MDBStore *store, MDBIterator *it, size_t *ct);
|
|
inline static LSUP_rc lookup_1bound(
|
|
inline static LSUP_rc lookup_1bound(
|
|
- struct MDBStore *store, uint8_t idx0,
|
|
|
|
- struct MDBIterator *it, size_t *ct);
|
|
|
|
|
|
+ MDBStore *store, uint8_t idx0, MDBIterator *it, size_t *ct);
|
|
inline static LSUP_rc lookup_2bound(
|
|
inline static LSUP_rc lookup_2bound(
|
|
- struct MDBStore *store, uint8_t idx0, uint8_t idx1,
|
|
|
|
- struct MDBIterator *it, size_t *ct);
|
|
|
|
|
|
+ MDBStore *store, uint8_t idx0, uint8_t idx1,
|
|
|
|
+ MDBIterator *it, size_t *ct);
|
|
inline static LSUP_rc lookup_3bound(
|
|
inline static LSUP_rc lookup_3bound(
|
|
- struct MDBStore *store, struct MDBIterator *it, size_t *ct);
|
|
|
|
|
|
+ MDBStore *store, MDBIterator *it, size_t *ct);
|
|
/* TODO
|
|
/* TODO
|
|
inline static int check_txn_open(MDB_txn *txn, bool write);
|
|
inline static int check_txn_open(MDB_txn *txn, bool write);
|
|
*/
|
|
*/
|
|
@@ -224,7 +225,7 @@ static int rmrf(char *path);
|
|
*/
|
|
*/
|
|
|
|
|
|
LSUP_rc
|
|
LSUP_rc
|
|
-LSUP_store_setup(char **path/*, bool clear*/) // TODO clear
|
|
|
|
|
|
+LSUP_mdbstore_setup(char **path/*, bool clear*/) // TODO clear
|
|
{
|
|
{
|
|
int rc;
|
|
int rc;
|
|
|
|
|
|
@@ -276,12 +277,15 @@ LSUP_store_setup(char **path/*, bool clear*/) // TODO clear
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-LSUP_MDBStore *
|
|
|
|
-LSUP_store_new(const char *path, const LSUP_Buffer *default_ctx)
|
|
|
|
|
|
+LSUP_rc
|
|
|
|
+LSUP_mdbstore_new(
|
|
|
|
+ const char *path, const LSUP_Buffer *default_ctx,
|
|
|
|
+ LSUP_MDBStore **store_p)
|
|
{
|
|
{
|
|
int rc;
|
|
int rc;
|
|
LSUP_MDBStore *store;
|
|
LSUP_MDBStore *store;
|
|
CRITICAL(store = malloc(sizeof(LSUP_MDBStore)));
|
|
CRITICAL(store = malloc(sizeof(LSUP_MDBStore)));
|
|
|
|
+ *store_p = NULL;
|
|
|
|
|
|
rc = mdb_env_create(&store->env);
|
|
rc = mdb_env_create(&store->env);
|
|
TRACE("create rc: %d", rc);
|
|
TRACE("create rc: %d", rc);
|
|
@@ -299,10 +303,10 @@ LSUP_store_new(const char *path, const LSUP_Buffer *default_ctx)
|
|
else sscanf(env_mapsize, "%lu", &mapsize);
|
|
else sscanf(env_mapsize, "%lu", &mapsize);
|
|
|
|
|
|
rc = mdb_env_set_maxdbs(store->env, N_DB);
|
|
rc = mdb_env_set_maxdbs(store->env, N_DB);
|
|
- if(rc != MDB_SUCCESS) return NULL;
|
|
|
|
|
|
+ if(rc != MDB_SUCCESS) return LSUP_DB_ERR;
|
|
|
|
|
|
rc = mdb_env_open(store->env, path, 0, ENV_FILE_MODE);
|
|
rc = mdb_env_open(store->env, path, 0, ENV_FILE_MODE);
|
|
- if (rc != MDB_SUCCESS) return NULL;
|
|
|
|
|
|
+ if (rc != MDB_SUCCESS) return LSUP_DB_ERR;
|
|
|
|
|
|
// Assign DB handles to store->dbi.
|
|
// Assign DB handles to store->dbi.
|
|
MDB_txn *txn;
|
|
MDB_txn *txn;
|
|
@@ -312,7 +316,7 @@ LSUP_store_new(const char *path, const LSUP_Buffer *default_ctx)
|
|
txn, db_labels[i], db_flags[i], store->dbi + i);
|
|
txn, db_labels[i], db_flags[i], store->dbi + i);
|
|
if (rc != MDB_SUCCESS) {
|
|
if (rc != MDB_SUCCESS) {
|
|
mdb_txn_abort(txn);
|
|
mdb_txn_abort(txn);
|
|
- return NULL;
|
|
|
|
|
|
+ return LSUP_DB_ERR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -321,12 +325,14 @@ LSUP_store_new(const char *path, const LSUP_Buffer *default_ctx)
|
|
store->state |= LSSTORE_OPEN;
|
|
store->state |= LSSTORE_OPEN;
|
|
store->txn = NULL;
|
|
store->txn = NULL;
|
|
|
|
|
|
- return store;
|
|
|
|
|
|
+ *store_p = store;
|
|
|
|
+
|
|
|
|
+ return LSUP_OK;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
void
|
|
-LSUP_store_free(LSUP_MDBStore *store)
|
|
|
|
|
|
+LSUP_mdbstore_free(LSUP_MDBStore *store)
|
|
{
|
|
{
|
|
if (store->state & LSSTORE_OPEN) {
|
|
if (store->state & LSSTORE_OPEN) {
|
|
TRACE(STR, "Closing MDB env.\n");
|
|
TRACE(STR, "Closing MDB env.\n");
|
|
@@ -343,7 +349,7 @@ LSUP_store_free(LSUP_MDBStore *store)
|
|
|
|
|
|
|
|
|
|
LSUP_rc
|
|
LSUP_rc
|
|
-LSUP_store_stats(LSUP_MDBStore *store)
|
|
|
|
|
|
+LSUP_mdbstore_stats(LSUP_MDBStore *store)
|
|
{
|
|
{
|
|
// TODO
|
|
// TODO
|
|
// MDB_stat env_stat, db_stats[N_DB];
|
|
// MDB_stat env_stat, db_stats[N_DB];
|
|
@@ -352,7 +358,7 @@ LSUP_store_stats(LSUP_MDBStore *store)
|
|
|
|
|
|
|
|
|
|
size_t
|
|
size_t
|
|
-LSUP_store_size(LSUP_MDBStore *store)
|
|
|
|
|
|
+LSUP_mdbstore_size(LSUP_MDBStore *store)
|
|
{
|
|
{
|
|
if(!(store->state & LSSTORE_INIT)) return 0;
|
|
if(!(store->state & LSSTORE_INIT)) return 0;
|
|
|
|
|
|
@@ -376,109 +382,146 @@ LSUP_store_size(LSUP_MDBStore *store)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-LSUP_rc
|
|
|
|
-LSUP_store_add(
|
|
|
|
- LSUP_MDBStore *store, const LSUP_Buffer *sc,
|
|
|
|
- const LSUP_SerTriple *data, const size_t data_size)
|
|
|
|
|
|
+void
|
|
|
|
+LSUP_mdbstore_add_init(
|
|
|
|
+ LSUP_MDBStore *store, const LSUP_Buffer *sc, MDBIterator **it_p)
|
|
{
|
|
{
|
|
- MDB_val key_v, data_v;
|
|
|
|
|
|
+ /* An iterator is used here. Some members are a bit misused but it does
|
|
|
|
+ * its job without having to define a very similar struct.
|
|
|
|
+ */
|
|
|
|
+ MDBIterator *it;
|
|
|
|
+ CRITICAL(it= malloc(sizeof(MDBIterator)));
|
|
|
|
+ it->i = 0;
|
|
|
|
|
|
- bool txn_pending = false;
|
|
|
|
if (!store->txn) {
|
|
if (!store->txn) {
|
|
mdb_txn_begin(store->env, NULL, 0, &store->txn);
|
|
mdb_txn_begin(store->env, NULL, 0, &store->txn);
|
|
- txn_pending = true;
|
|
|
|
|
|
+ // We are starting the main DB txn and we need to close it afterwards.
|
|
|
|
+ it->state = LSSTORE_DIRTY_TXN;
|
|
}
|
|
}
|
|
|
|
|
|
// Take care of context first.
|
|
// Take care of context first.
|
|
// Serialize and hash.
|
|
// Serialize and hash.
|
|
- LSUP_Key ck = NULL_KEY;
|
|
|
|
|
|
+ it->ck = NULL_KEY;
|
|
|
|
|
|
if (store->default_ctx != NULL) {
|
|
if (store->default_ctx != NULL) {
|
|
if (sc == NULL) sc = store->default_ctx;
|
|
if (sc == NULL) sc = store->default_ctx;
|
|
|
|
|
|
- ck = LSUP_sterm_to_key(sc);
|
|
|
|
|
|
+ it->ck = LSUP_sterm_to_key(sc);
|
|
|
|
|
|
// Insert t:st for context.
|
|
// Insert t:st for context.
|
|
//TRACE("Adding context: %s", sc);
|
|
//TRACE("Adding context: %s", sc);
|
|
- key_v.mv_data = &ck;
|
|
|
|
- key_v.mv_size = KLEN;
|
|
|
|
- data_v.mv_data = sc->addr;
|
|
|
|
- data_v.mv_size = sc->size;
|
|
|
|
|
|
+ it->key.mv_data = &it->ck;
|
|
|
|
+ it->key.mv_size = KLEN;
|
|
|
|
+ it->data.mv_data = sc->addr;
|
|
|
|
+ it->data.mv_size = sc->size;
|
|
|
|
|
|
- mdb_put(
|
|
|
|
|
|
+ if (mdb_put(
|
|
store->txn, store->dbi[IDX_T_ST],
|
|
store->txn, store->dbi[IDX_T_ST],
|
|
- &key_v, &data_v, MDB_NOOVERWRITE);
|
|
|
|
|
|
+ &it->key, &it->data, MDB_NOOVERWRITE) != MDB_SUCCESS)
|
|
|
|
+ it->rc = LSUP_DB_ERR;
|
|
}
|
|
}
|
|
|
|
|
|
- LSUP_rc rc = LSUP_NOACTION;
|
|
|
|
|
|
+ *it_p = it;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+LSUP_rc
|
|
|
|
+LSUP_mdbstore_add_iter(MDBIterator *it, const LSUP_SerTriple *sspo)
|
|
|
|
+{
|
|
int db_rc;
|
|
int db_rc;
|
|
- for (size_t i = 0; i < data_size; i++) {
|
|
|
|
- const LSUP_SerTriple *sspo = data + i;
|
|
|
|
- LSUP_TripleKey spok = NULL_TRP;
|
|
|
|
-
|
|
|
|
- // Add triple.
|
|
|
|
- for (int j = 0; j < 3; j++) {
|
|
|
|
- LSUP_SerTerm *st = LSUP_ser_triple_term_by_pos(sspo, j);
|
|
|
|
-
|
|
|
|
- printf("Inserting term: ");
|
|
|
|
- LSUP_buffer_print(st);
|
|
|
|
- printf("\n");
|
|
|
|
-
|
|
|
|
- spok[j] = LSUP_sterm_to_key(st);
|
|
|
|
-
|
|
|
|
- key_v.mv_data = spok + j;
|
|
|
|
- key_v.mv_size = KLEN;
|
|
|
|
- data_v.mv_data = st->addr;
|
|
|
|
- data_v.mv_size = st->size;
|
|
|
|
-
|
|
|
|
- db_rc = mdb_put(
|
|
|
|
- store->txn, store->dbi[IDX_T_ST],
|
|
|
|
- &key_v, &data_v, MDB_NOOVERWRITE);
|
|
|
|
- if (db_rc == MDB_SUCCESS) rc = LSUP_OK;
|
|
|
|
- else if (db_rc != MDB_KEYEXIST) goto _add_close_txn;
|
|
|
|
- }
|
|
|
|
|
|
+ LSUP_TripleKey spok = NULL_TRP;
|
|
|
|
|
|
- TRACE("Inserting spok: {%lx, %lx, %lx}", spok[0], spok[1], spok[2]);
|
|
|
|
|
|
+ // Add triple.
|
|
|
|
+ for (int j = 0; j < 3; j++) {
|
|
|
|
+ LSUP_Buffer *st = LSUP_striple_pos(sspo, j);
|
|
|
|
|
|
- // Insert spo:c.
|
|
|
|
- key_v.mv_data = spok;
|
|
|
|
- key_v.mv_size = TRP_KLEN;
|
|
|
|
|
|
+ printf("Inserting term: ");
|
|
|
|
+ LSUP_buffer_print(st);
|
|
|
|
+ printf("\n");
|
|
|
|
|
|
- // In triple mode, data is empty (= NULL_KEY).
|
|
|
|
- data_v.mv_data = &ck;
|
|
|
|
- data_v.mv_size = ck == NULL_KEY ? 0 : KLEN;
|
|
|
|
|
|
+ spok[j] = LSUP_sterm_to_key(st);
|
|
|
|
|
|
|
|
+ it->key.mv_data = spok + j;
|
|
|
|
+ it->key.mv_size = KLEN;
|
|
|
|
+ it->data.mv_data = st->addr;
|
|
|
|
+ it->data.mv_size = st->size;
|
|
|
|
|
|
db_rc = mdb_put(
|
|
db_rc = mdb_put(
|
|
- store->txn, store->dbi[IDX_SPO_C],
|
|
|
|
- &key_v, &data_v, MDB_NODUPDATA);
|
|
|
|
- if (db_rc == MDB_SUCCESS) rc = LSUP_OK;
|
|
|
|
- else if (db_rc != MDB_KEYEXIST) goto _add_close_txn;
|
|
|
|
|
|
+ it->store->txn, it->store->dbi[IDX_T_ST],
|
|
|
|
+ &it->key, &it->data, MDB_NOOVERWRITE);
|
|
|
|
+ if (db_rc == MDB_SUCCESS) it->rc = LSUP_OK;
|
|
|
|
+ else if (db_rc != MDB_KEYEXIST) {
|
|
|
|
+ it->rc = LSUP_DB_ERR;
|
|
|
|
+ return it->rc;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ TRACE("Inserting spok: {%lx, %lx, %lx}", spok[0], spok[1], spok[2]);
|
|
|
|
+
|
|
|
|
+ // Insert spo:c.
|
|
|
|
+ it->key.mv_data = spok;
|
|
|
|
+ it->key.mv_size = TRP_KLEN;
|
|
|
|
+
|
|
|
|
+ // In triple mode, data is empty (= NULL_KEY).
|
|
|
|
+ it->data.mv_data = &it->ck;
|
|
|
|
+ it->data.mv_size = it->ck == NULL_KEY ? 0 : KLEN;
|
|
|
|
|
|
- // Index.
|
|
|
|
- PCHECK(index_triple(store, OP_ADD, spok, ck), db_rc, _add_close_txn);
|
|
|
|
|
|
+ db_rc = mdb_put(
|
|
|
|
+ it->store->txn, it->store->dbi[IDX_SPO_C],
|
|
|
|
+ &it->key, &it->data, MDB_NODUPDATA);
|
|
|
|
+ if (db_rc == MDB_SUCCESS) it->rc = LSUP_OK;
|
|
|
|
+ else if (db_rc != MDB_KEYEXIST) {
|
|
|
|
+ it->rc = LSUP_DB_ERR;
|
|
|
|
+ return it->rc;
|
|
}
|
|
}
|
|
|
|
|
|
-_add_close_txn:
|
|
|
|
|
|
+ // Index.
|
|
|
|
+ it->rc = index_triple(it->store, OP_ADD, spok, it->ck);
|
|
|
|
+
|
|
|
|
+ if(it->rc == LSUP_OK) it->i++;
|
|
|
|
+
|
|
|
|
+ return it->rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+LSUP_rc
|
|
|
|
+LSUP_mdbstore_add_done(MDBIterator *it, size_t *inserted)
|
|
|
|
+{
|
|
// Only return commit rc if it fails.
|
|
// Only return commit rc if it fails.
|
|
- if (txn_pending) {
|
|
|
|
- if (rc == LSUP_OK) {
|
|
|
|
- if((db_rc = mdb_txn_commit(store->txn)) != MDB_SUCCESS) {
|
|
|
|
- mdb_txn_abort(store->txn);
|
|
|
|
- rc = db_rc;
|
|
|
|
|
|
+ if (it->state & LSSTORE_DIRTY_TXN) {
|
|
|
|
+ if (it->rc == LSUP_OK) {
|
|
|
|
+ if(mdb_txn_commit(it->store->txn) != MDB_SUCCESS) {
|
|
|
|
+ mdb_txn_abort(it->store->txn);
|
|
|
|
+ it->rc = LSUP_DB_ERR;
|
|
}
|
|
}
|
|
- } else mdb_txn_abort(store->txn);
|
|
|
|
|
|
+ } else mdb_txn_abort(it->store->txn);
|
|
|
|
|
|
- store->txn = NULL;
|
|
|
|
|
|
+ it->store->txn = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
- return rc;
|
|
|
|
|
|
+ return it->rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+LSUP_rc
|
|
|
|
+LSUP_mdbstore_add(
|
|
|
|
+ LSUP_MDBStore *store, const LSUP_Buffer *sc,
|
|
|
|
+ const LSUP_SerTriple strp[], const size_t ct, size_t *inserted)
|
|
|
|
+{
|
|
|
|
+ MDBIterator *it;
|
|
|
|
+ LSUP_mdbstore_add_init(store, sc, &it);
|
|
|
|
+ if (it->rc < 0) {
|
|
|
|
+ for (size_t i = 0; i < ct; i++)
|
|
|
|
+ if (LSUP_mdbstore_add_iter(it, strp + i) < 0) break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return LSUP_mdbstore_add_done(it, inserted);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
LSUP_Key
|
|
LSUP_Key
|
|
-LSUP_store_sterm_to_key(
|
|
|
|
- LSUP_MDBStore *store, const LSUP_SerTerm *sterm)
|
|
|
|
|
|
+LSUP_mdbstore_sterm_to_key(
|
|
|
|
+ LSUP_MDBStore *store, const LSUP_Buffer *sterm)
|
|
{
|
|
{
|
|
// TODO this will be replaced by a lookup when 128-bit hash is introduced.
|
|
// TODO this will be replaced by a lookup when 128-bit hash is introduced.
|
|
return LSUP_sterm_to_key(sterm);
|
|
return LSUP_sterm_to_key(sterm);
|
|
@@ -486,8 +529,8 @@ LSUP_store_sterm_to_key(
|
|
|
|
|
|
|
|
|
|
LSUP_rc
|
|
LSUP_rc
|
|
-LSUP_store_key_to_sterm(
|
|
|
|
- LSUP_MDBStore *store, const LSUP_Key key, LSUP_SerTerm *sterm)
|
|
|
|
|
|
+LSUP_mdbstore_key_to_sterm(
|
|
|
|
+ LSUP_MDBStore *store, const LSUP_Key key, LSUP_Buffer *sterm)
|
|
{
|
|
{
|
|
LSUP_rc rc = LSUP_NORESULT;
|
|
LSUP_rc rc = LSUP_NORESULT;
|
|
|
|
|
|
@@ -515,22 +558,22 @@ LSUP_store_key_to_sterm(
|
|
|
|
|
|
|
|
|
|
LSUP_rc
|
|
LSUP_rc
|
|
-LSUP_store_lookup(
|
|
|
|
- LSUP_MDBStore *store, LSUP_SerTerm *sspoc[],
|
|
|
|
- struct MDBIterator **itp, size_t *ct)
|
|
|
|
|
|
+LSUP_mdbstore_lookup(
|
|
|
|
+ LSUP_MDBStore *store, const LSUP_SerTriple *sspo,
|
|
|
|
+ const LSUP_Buffer *sc, MDBIterator **it_p, size_t *ct)
|
|
{
|
|
{
|
|
LSUP_TripleKey spok = {
|
|
LSUP_TripleKey spok = {
|
|
- LSUP_sterm_to_key(sspoc[0]),
|
|
|
|
- LSUP_sterm_to_key(sspoc[1]),
|
|
|
|
- LSUP_sterm_to_key(sspoc[2]),
|
|
|
|
|
|
+ LSUP_sterm_to_key(sspo->s),
|
|
|
|
+ LSUP_sterm_to_key(sspo->p),
|
|
|
|
+ LSUP_sterm_to_key(sspo->o),
|
|
};
|
|
};
|
|
|
|
|
|
LSUP_MDBIterator *it;
|
|
LSUP_MDBIterator *it;
|
|
- CRITICAL(it = malloc(sizeof(struct MDBIterator)));
|
|
|
|
- *itp = it;
|
|
|
|
|
|
+ CRITICAL(it = malloc(sizeof(MDBIterator)));
|
|
|
|
+ *it_p = it;
|
|
|
|
|
|
it->store = store;
|
|
it->store = store;
|
|
- it->ck = store->default_ctx ? LSUP_sterm_to_key(sspoc[3]) : NULL_KEY;
|
|
|
|
|
|
+ it->ck = store->default_ctx ? LSUP_sterm_to_key(sc) : NULL_KEY;
|
|
|
|
|
|
if(ct) *ct = 0;
|
|
if(ct) *ct = 0;
|
|
|
|
|
|
@@ -587,7 +630,7 @@ LSUP_store_lookup(
|
|
|
|
|
|
|
|
|
|
LSUP_rc
|
|
LSUP_rc
|
|
-LSUP_store_it_next(LSUP_MDBIterator *it, LSUP_SerTerm **sspo)
|
|
|
|
|
|
+mdbiter_next_key(LSUP_MDBIterator *it)
|
|
{
|
|
{
|
|
// Only advance if the previous it->rc wasn't already at the end.
|
|
// Only advance if the previous it->rc wasn't already at the end.
|
|
if(it->rc == MDB_NOTFOUND) return LSUP_END;
|
|
if(it->rc == MDB_NOTFOUND) return LSUP_END;
|
|
@@ -646,14 +689,21 @@ LSUP_store_it_next(LSUP_MDBIterator *it, LSUP_SerTerm **sspo)
|
|
|
|
|
|
} else rc = LSUP_OK;
|
|
} else rc = LSUP_OK;
|
|
|
|
|
|
- if (sspo) {
|
|
|
|
- if (rc == LSUP_OK) {
|
|
|
|
- LSUP_store_key_to_sterm(it->store, *it->spok[0], *sspo);
|
|
|
|
- LSUP_store_key_to_sterm(it->store, *it->spok[1], *sspo + 1);
|
|
|
|
- LSUP_store_key_to_sterm(it->store, *it->spok[2], *sspo + 2);
|
|
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+LSUP_rc
|
|
|
|
+LSUP_mdbiter_next(LSUP_MDBIterator *it, LSUP_SerTriple *sspo)
|
|
|
|
+{
|
|
|
|
+ LSUP_rc rc = mdbiter_next_key(it);
|
|
|
|
+
|
|
|
|
+ if (sspo && rc == LSUP_OK) {
|
|
|
|
+ LSUP_mdbstore_key_to_sterm(it->store, it->spok[0], sspo->s);
|
|
|
|
+ LSUP_mdbstore_key_to_sterm(it->store, it->spok[1], sspo->p);
|
|
|
|
+ LSUP_mdbstore_key_to_sterm(it->store, it->spok[2], sspo->o);
|
|
|
|
|
|
// TODO error handling.
|
|
// TODO error handling.
|
|
- } else *sspo = NULL;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
return rc;
|
|
return rc;
|
|
@@ -661,7 +711,7 @@ LSUP_store_it_next(LSUP_MDBIterator *it, LSUP_SerTerm **sspo)
|
|
|
|
|
|
|
|
|
|
void
|
|
void
|
|
-LSUP_store_it_free(struct MDBIterator *it)
|
|
|
|
|
|
+LSUP_mdbiter_free(MDBIterator *it)
|
|
{
|
|
{
|
|
if (it) {
|
|
if (it) {
|
|
mdb_cursor_close(it->cur);
|
|
mdb_cursor_close(it->cur);
|
|
@@ -674,9 +724,9 @@ LSUP_store_it_free(struct MDBIterator *it)
|
|
|
|
|
|
|
|
|
|
LSUP_rc
|
|
LSUP_rc
|
|
-LSUP_store_remove(
|
|
|
|
- LSUP_MDBStore *store, const LSUP_Buffer *sc,
|
|
|
|
- LSUP_TripleKey data[], size_t data_size)
|
|
|
|
|
|
+LSUP_mdbstore_remove(
|
|
|
|
+ MDBStore *store, const LSUP_SerTriple *sspo,
|
|
|
|
+ const LSUP_Buffer *sc, size_t *ct)
|
|
{
|
|
{
|
|
LSUP_rc rc = LSUP_NOACTION;
|
|
LSUP_rc rc = LSUP_NOACTION;
|
|
|
|
|
|
@@ -700,8 +750,11 @@ LSUP_store_remove(
|
|
spok_v.mv_size = TRP_KLEN;
|
|
spok_v.mv_size = TRP_KLEN;
|
|
ck_v.mv_size = KLEN;
|
|
ck_v.mv_size = KLEN;
|
|
|
|
|
|
- for(size_t i = 0; i < data_size; i++) {
|
|
|
|
- spok_v.mv_data = data + i;
|
|
|
|
|
|
+ LSUP_MDBIterator *it;
|
|
|
|
+ LSUP_mdbstore_lookup(store, sspo, sc, &it, ct);
|
|
|
|
+
|
|
|
|
+ while (mdbiter_next_key(it)) {
|
|
|
|
+ spok_v.mv_data = it->spok;
|
|
|
|
|
|
rc = mdb_cursor_get(dcur, &spok_v, &ck_v, MDB_GET_BOTH);
|
|
rc = mdb_cursor_get(dcur, &spok_v, &ck_v, MDB_GET_BOTH);
|
|
if (rc == MDB_NOTFOUND) continue;
|
|
if (rc == MDB_NOTFOUND) continue;
|
|
@@ -719,7 +772,7 @@ LSUP_store_remove(
|
|
if (UNLIKELY(rc != MDB_SUCCESS)) goto _remove_abort;
|
|
if (UNLIKELY(rc != MDB_SUCCESS)) goto _remove_abort;
|
|
|
|
|
|
mdb_cursor_del(icur, 0);
|
|
mdb_cursor_del(icur, 0);
|
|
- spok_v.mv_data = data + i;
|
|
|
|
|
|
+ spok_v.mv_data = it->spok;
|
|
|
|
|
|
// If there are no more contexts associated with this triple,
|
|
// If there are no more contexts associated with this triple,
|
|
// remove from indices.
|
|
// remove from indices.
|
|
@@ -727,7 +780,7 @@ LSUP_store_remove(
|
|
if (rc == MDB_SUCCESS) continue;
|
|
if (rc == MDB_SUCCESS) continue;
|
|
if (UNLIKELY(rc != MDB_NOTFOUND)) goto _remove_abort;
|
|
if (UNLIKELY(rc != MDB_NOTFOUND)) goto _remove_abort;
|
|
|
|
|
|
- index_triple(store, OP_REMOVE, data[i], ck);
|
|
|
|
|
|
+ index_triple(store, OP_REMOVE, it->spok, ck);
|
|
}
|
|
}
|
|
|
|
|
|
if(UNLIKELY(mdb_txn_commit(txn) != MDB_SUCCESS)) {
|
|
if(UNLIKELY(mdb_txn_commit(txn) != MDB_SUCCESS)) {
|
|
@@ -765,20 +818,6 @@ static int rmrf(char *path)
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
|
|
-/* TODO
|
|
|
|
-inline static int
|
|
|
|
-check_txn_open(MDB_txn *txn, bool write)
|
|
|
|
-{
|
|
|
|
- if (txn == NULL) {
|
|
|
|
- mdb_txn_begin(LSUP_mdbenv, NULL, write ? 0 : MDB_RDONLY, &txn);
|
|
|
|
-
|
|
|
|
- return LSUP_OK;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return LSUP_NOACTION;
|
|
|
|
-}
|
|
|
|
-*/
|
|
|
|
-
|
|
|
|
static LSUP_rc
|
|
static LSUP_rc
|
|
index_triple(
|
|
index_triple(
|
|
LSUP_MDBStore *store, StoreOp op,
|
|
LSUP_MDBStore *store, StoreOp op,
|
|
@@ -891,9 +930,9 @@ index_triple(
|
|
* Cursor: spo:c
|
|
* Cursor: spo:c
|
|
*/
|
|
*/
|
|
inline static void
|
|
inline static void
|
|
-it_next_0bound(struct MDBIterator *it)
|
|
|
|
|
|
+it_next_0bound(MDBIterator *it)
|
|
{
|
|
{
|
|
- it->spok = (LSUP_TripleKey*)&it->data.mv_data;
|
|
|
|
|
|
+ memcpy(it->spok, it->data.mv_data, sizeof(LSUP_TripleKey));
|
|
|
|
|
|
it->rc = mdb_cursor_get(it->cur, &it->key, NULL, MDB_NEXT);
|
|
it->rc = mdb_cursor_get(it->cur, &it->key, NULL, MDB_NEXT);
|
|
}
|
|
}
|
|
@@ -906,17 +945,17 @@ it_next_0bound(struct MDBIterator *it)
|
|
* Cursor: s:po, p:so, or o:sp.
|
|
* Cursor: s:po, p:so, or o:sp.
|
|
*/
|
|
*/
|
|
inline static void
|
|
inline static void
|
|
-it_next_1bound(struct MDBIterator *it)
|
|
|
|
|
|
+it_next_1bound(MDBIterator *it)
|
|
{
|
|
{
|
|
LSUP_DoubleKey *lu_dset = it->data.mv_data;
|
|
LSUP_DoubleKey *lu_dset = it->data.mv_data;
|
|
|
|
|
|
- it->spok[0][it->term_order[0]] = it->luk[0];
|
|
|
|
- it->spok[0][it->term_order[1]] = lu_dset[it->i][0];
|
|
|
|
- it->spok[0][it->term_order[2]] = lu_dset[it->i][1];
|
|
|
|
|
|
+ it->spok[it->term_order[0]] = it->luk[0];
|
|
|
|
+ it->spok[it->term_order[1]] = lu_dset[it->i][0];
|
|
|
|
+ it->spok[it->term_order[2]] = lu_dset[it->i][1];
|
|
|
|
|
|
TRACE(
|
|
TRACE(
|
|
"Composed triple: {%lu %lu %lu}",
|
|
"Composed triple: {%lu %lu %lu}",
|
|
- it->spok[0][0], it->spok[0][1], it->spok[0][2]);
|
|
|
|
|
|
+ it->spok[0], it->spok[1], it->spok[2]);
|
|
|
|
|
|
// Ensure next block within the same page is not beyond the last.
|
|
// Ensure next block within the same page is not beyond the last.
|
|
if(it->i < it->data.mv_size / DBL_KLEN - 1) {
|
|
if(it->i < it->data.mv_size / DBL_KLEN - 1) {
|
|
@@ -942,13 +981,13 @@ it_next_1bound(struct MDBIterator *it)
|
|
* Cursor: po:s, so:p, or sp:o.
|
|
* Cursor: po:s, so:p, or sp:o.
|
|
*/
|
|
*/
|
|
inline static void
|
|
inline static void
|
|
-it_next_2bound(struct MDBIterator *it)
|
|
|
|
|
|
+it_next_2bound(MDBIterator *it)
|
|
{
|
|
{
|
|
LSUP_Key *lu_dset = it->data.mv_data;
|
|
LSUP_Key *lu_dset = it->data.mv_data;
|
|
|
|
|
|
- it->spok[0][it->term_order[0]] = it->luk[0];
|
|
|
|
- it->spok[0][it->term_order[1]] = it->luk[1];
|
|
|
|
- it->spok[0][it->term_order[2]] = lu_dset[it->i];
|
|
|
|
|
|
+ it->spok[it->term_order[0]] = it->luk[0];
|
|
|
|
+ it->spok[it->term_order[1]] = it->luk[1];
|
|
|
|
+ it->spok[it->term_order[2]] = lu_dset[it->i];
|
|
|
|
|
|
// Ensure next block within the same page is not beyond the last.
|
|
// Ensure next block within the same page is not beyond the last.
|
|
if(it->i < it->data.mv_size / KLEN - 1)
|
|
if(it->i < it->data.mv_size / KLEN - 1)
|
|
@@ -969,7 +1008,7 @@ it_next_2bound(struct MDBIterator *it)
|
|
* already MDB_NOTFOUND and this function will not be called.
|
|
* already MDB_NOTFOUND and this function will not be called.
|
|
*/
|
|
*/
|
|
inline static void
|
|
inline static void
|
|
-it_next_3bound(struct MDBIterator *it)
|
|
|
|
|
|
+it_next_3bound(MDBIterator *it)
|
|
{
|
|
{
|
|
it->rc = MDB_NOTFOUND;
|
|
it->rc = MDB_NOTFOUND;
|
|
}
|
|
}
|
|
@@ -978,7 +1017,7 @@ it_next_3bound(struct MDBIterator *it)
|
|
/* * * Term-specific lookups. * * */
|
|
/* * * Term-specific lookups. * * */
|
|
|
|
|
|
inline static LSUP_rc
|
|
inline static LSUP_rc
|
|
-lookup_0bound(struct MDBStore *store, struct MDBIterator *it, size_t *ct)
|
|
|
|
|
|
+lookup_0bound(MDBStore *store, MDBIterator *it, size_t *ct)
|
|
{
|
|
{
|
|
if(store->txn) it->txn = store->txn;
|
|
if(store->txn) it->txn = store->txn;
|
|
else {
|
|
else {
|
|
@@ -1023,9 +1062,7 @@ lookup_0bound(struct MDBStore *store, struct MDBIterator *it, size_t *ct)
|
|
|
|
|
|
|
|
|
|
inline static LSUP_rc
|
|
inline static LSUP_rc
|
|
-lookup_1bound(
|
|
|
|
- struct MDBStore *store, uint8_t idx0,
|
|
|
|
- struct MDBIterator *it, size_t *ct)
|
|
|
|
|
|
+lookup_1bound(MDBStore *store, uint8_t idx0, MDBIterator *it, size_t *ct)
|
|
{
|
|
{
|
|
it->term_order = (const uint8_t*)lookup_ordering_1bound[idx0];
|
|
it->term_order = (const uint8_t*)lookup_ordering_1bound[idx0];
|
|
|
|
|
|
@@ -1048,12 +1085,12 @@ lookup_1bound(
|
|
// If a context is specified, the only way to count triples matching
|
|
// If a context is specified, the only way to count triples matching
|
|
// the context is to loop over them.
|
|
// the context is to loop over them.
|
|
if (it->ck != NULL_KEY) {
|
|
if (it->ck != NULL_KEY) {
|
|
- struct MDBIterator *ct_it;
|
|
|
|
- CRITICAL(ct_it = malloc(sizeof(struct MDBIterator)));
|
|
|
|
|
|
+ MDBIterator *ct_it;
|
|
|
|
+ CRITICAL(ct_it = malloc(sizeof(MDBIterator)));
|
|
|
|
|
|
ct_it->luk[0] = it->luk[0];
|
|
ct_it->luk[0] = it->luk[0];
|
|
LSUP_TripleKey ct_spok;
|
|
LSUP_TripleKey ct_spok;
|
|
- ct_it->spok = &ct_spok;
|
|
|
|
|
|
+ memcpy(ct_it->spok, ct_spok, sizeof(LSUP_TripleKey));
|
|
ct_it->ck = it->ck;
|
|
ct_it->ck = it->ck;
|
|
ct_it->store = it->store;
|
|
ct_it->store = it->store;
|
|
ct_it->txn = it->txn;
|
|
ct_it->txn = it->txn;
|
|
@@ -1062,7 +1099,7 @@ lookup_1bound(
|
|
ct_it->i = 0;
|
|
ct_it->i = 0;
|
|
lookup_1bound(store, idx0, ct_it, NULL);
|
|
lookup_1bound(store, idx0, ct_it, NULL);
|
|
|
|
|
|
- while (LSUP_store_it_next(ct_it, NULL) != LSUP_END) {
|
|
|
|
|
|
+ while (LSUP_mdbiter_next(ct_it, NULL) != LSUP_END) {
|
|
ct[0] ++;
|
|
ct[0] ++;
|
|
TRACE("Counter increased to %lu.", *ct);
|
|
TRACE("Counter increased to %lu.", *ct);
|
|
}
|
|
}
|
|
@@ -1094,8 +1131,8 @@ lookup_1bound(
|
|
|
|
|
|
inline static LSUP_rc
|
|
inline static LSUP_rc
|
|
lookup_2bound(
|
|
lookup_2bound(
|
|
- struct MDBStore *store, uint8_t idx0, uint8_t idx1,
|
|
|
|
- struct MDBIterator *it, size_t *ct)
|
|
|
|
|
|
+ MDBStore *store, uint8_t idx0, uint8_t idx1,
|
|
|
|
+ MDBIterator *it, size_t *ct)
|
|
{
|
|
{
|
|
uint8_t luk1_offset, luk2_offset;
|
|
uint8_t luk1_offset, luk2_offset;
|
|
MDB_dbi dbi = 0;
|
|
MDB_dbi dbi = 0;
|
|
@@ -1158,19 +1195,19 @@ lookup_2bound(
|
|
// If a context is specified, the only way to count triples matching
|
|
// If a context is specified, the only way to count triples matching
|
|
// the context is to loop over them.
|
|
// the context is to loop over them.
|
|
if (it->ck != NULL_KEY) {
|
|
if (it->ck != NULL_KEY) {
|
|
- struct MDBIterator *ct_it;
|
|
|
|
- CRITICAL(ct_it = malloc(sizeof(struct MDBIterator)));
|
|
|
|
|
|
+ MDBIterator *ct_it;
|
|
|
|
+ CRITICAL(ct_it = malloc(sizeof(MDBIterator)));
|
|
|
|
|
|
ct_it->luk[0] = it->luk[0];
|
|
ct_it->luk[0] = it->luk[0];
|
|
ct_it->luk[1] = it->luk[1];
|
|
ct_it->luk[1] = it->luk[1];
|
|
LSUP_TripleKey ct_spok;
|
|
LSUP_TripleKey ct_spok;
|
|
- ct_it->spok = &ct_spok;
|
|
|
|
|
|
+ memcpy(ct_it->spok, ct_spok, sizeof(LSUP_TripleKey));
|
|
ct_it->ck = it->ck;
|
|
ct_it->ck = it->ck;
|
|
ct_it->store = it->store;
|
|
ct_it->store = it->store;
|
|
ct_it->txn = it->txn;
|
|
ct_it->txn = it->txn;
|
|
lookup_2bound(store, idx0, idx1, ct_it, NULL);
|
|
lookup_2bound(store, idx0, idx1, ct_it, NULL);
|
|
|
|
|
|
- while (LSUP_store_it_next(ct_it, NULL) != LSUP_END) {
|
|
|
|
|
|
+ while (LSUP_mdbiter_next(ct_it, NULL) != LSUP_END) {
|
|
ct[0] ++;
|
|
ct[0] ++;
|
|
}
|
|
}
|
|
if (ct_it->cur) mdb_cursor_close(ct_it->cur);
|
|
if (ct_it->cur) mdb_cursor_close(ct_it->cur);
|
|
@@ -1199,7 +1236,7 @@ lookup_2bound(
|
|
|
|
|
|
|
|
|
|
inline static LSUP_rc
|
|
inline static LSUP_rc
|
|
-lookup_3bound(struct MDBStore *store, struct MDBIterator *it, size_t *ct)
|
|
|
|
|
|
+lookup_3bound(MDBStore *store, MDBIterator *it, size_t *ct)
|
|
{
|
|
{
|
|
TRACE(
|
|
TRACE(
|
|
"Looking up 3 bound: {%lx, %lx, %lx}",
|
|
"Looking up 3 bound: {%lx, %lx, %lx}",
|
|
@@ -1232,7 +1269,7 @@ lookup_3bound(struct MDBStore *store, struct MDBIterator *it, size_t *ct)
|
|
if(ct && it->rc == MDB_SUCCESS) *ct = 1;
|
|
if(ct && it->rc == MDB_SUCCESS) *ct = 1;
|
|
|
|
|
|
it->iter_op_fn = it_next_3bound;
|
|
it->iter_op_fn = it_next_3bound;
|
|
- it->spok = &it->luk;
|
|
|
|
|
|
+ memcpy(it->spok, it->luk, sizeof(LSUP_TripleKey));
|
|
|
|
|
|
if (it->rc != MDB_SUCCESS && it->rc != MDB_NOTFOUND) {
|
|
if (it->rc != MDB_SUCCESS && it->rc != MDB_NOTFOUND) {
|
|
fprintf(stderr, "Database error: %s", mdb_strerror(it->rc));
|
|
fprintf(stderr, "Database error: %s", mdb_strerror(it->rc));
|