|
@@ -1,13 +1,12 @@
|
|
#include <ftw.h>
|
|
#include <ftw.h>
|
|
|
|
|
|
-#include "uthash.h"
|
|
|
|
-
|
|
|
|
#include "store_mdb.h"
|
|
#include "store_mdb.h"
|
|
|
|
+#include "data/bootstrap.h"
|
|
|
|
|
|
/**
|
|
/**
|
|
* Number of DBs defined.
|
|
* Number of DBs defined.
|
|
*/
|
|
*/
|
|
-#define N_DB 12
|
|
|
|
|
|
+#define N_DB 13
|
|
|
|
|
|
/**
|
|
/**
|
|
* Memory map size.
|
|
* Memory map size.
|
|
@@ -106,12 +105,6 @@ typedef struct ctx_triple_map_t {
|
|
* Static variables.
|
|
* Static variables.
|
|
*/
|
|
*/
|
|
|
|
|
|
-/*
|
|
|
|
- * 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 DUPSORT_MASK MDB_DUPSORT
|
|
#define DUPFIXED_MASK MDB_DUPSORT | MDB_DUPFIXED
|
|
#define DUPFIXED_MASK MDB_DUPSORT | MDB_DUPFIXED
|
|
|
|
|
|
@@ -119,12 +112,15 @@ typedef struct ctx_triple_map_t {
|
|
* Main DBs. These are the master information containers.
|
|
* Main DBs. These are the master information containers.
|
|
*
|
|
*
|
|
* Data columns are: identifier prefix, DB label, flags.
|
|
* Data columns are: identifier prefix, DB label, flags.
|
|
|
|
+ *
|
|
|
|
+ * The number of entries must match the N_DB constant defined above.
|
|
*/
|
|
*/
|
|
#define MAIN_TABLE \
|
|
#define MAIN_TABLE \
|
|
ENTRY( T_ST, "t:st", 0 ) /* Key to ser. term */ \
|
|
ENTRY( T_ST, "t:st", 0 ) /* Key to ser. term */ \
|
|
ENTRY( SPO_C, "spo:c", DUPFIXED_MASK ) /* Triple to context */ \
|
|
ENTRY( SPO_C, "spo:c", DUPFIXED_MASK ) /* Triple to context */ \
|
|
ENTRY( C_, "c:", 0 ) /* Track empty ctx */ \
|
|
ENTRY( C_, "c:", 0 ) /* Track empty ctx */ \
|
|
ENTRY( PFX_NS, "pfx:ns", 0 ) /* Prefix to NS */ \
|
|
ENTRY( PFX_NS, "pfx:ns", 0 ) /* Prefix to NS */ \
|
|
|
|
+ ENTRY( IDK_ID, "idk:id", 0 ) /* ID key to ID */ \
|
|
|
|
|
|
/**
|
|
/**
|
|
* Lookup DBs. These are indices and may be destroyed and rebuilt.
|
|
* Lookup DBs. These are indices and may be destroyed and rebuilt.
|
|
@@ -267,7 +263,7 @@ LSUP_mdbstore_new (const char *path, const LSUP_Buffer *default_ctx)
|
|
LSUP_MDBStore *store;
|
|
LSUP_MDBStore *store;
|
|
MALLOC_GUARD (store, NULL);
|
|
MALLOC_GUARD (store, NULL);
|
|
store->features = LSUP_STORE_CTX;
|
|
store->features = LSUP_STORE_CTX;
|
|
- if (strcmp (path, MDB_RAMDISK_PATH) != 0)
|
|
|
|
|
|
+ if (strcmp (path, LSUP_MDB_RAMDISK_PATH) != 0)
|
|
store->features |= LSUP_STORE_PERM;
|
|
store->features |= LSUP_STORE_PERM;
|
|
|
|
|
|
db_rc = mdb_env_create (&store->env);
|
|
db_rc = mdb_env_create (&store->env);
|
|
@@ -283,8 +279,8 @@ LSUP_mdbstore_new (const char *path, const LSUP_Buffer *default_ctx)
|
|
if (env_mapsize == NULL) mapsize = DEFAULT_MAPSIZE;
|
|
if (env_mapsize == NULL) mapsize = DEFAULT_MAPSIZE;
|
|
else sscanf (env_mapsize, "%lu", &mapsize);
|
|
else sscanf (env_mapsize, "%lu", &mapsize);
|
|
log_info (
|
|
log_info (
|
|
- "Setting environment map size at %s to %lu bytes.",
|
|
|
|
- path, mapsize);
|
|
|
|
|
|
+ "Setting environment map size at %s to %lu Mb.",
|
|
|
|
+ path, mapsize / 1024 / 1024);
|
|
db_rc = mdb_env_set_mapsize (store->env, mapsize);
|
|
db_rc = mdb_env_set_mapsize (store->env, mapsize);
|
|
|
|
|
|
db_rc = mdb_env_set_maxdbs (store->env, N_DB);
|
|
db_rc = mdb_env_set_maxdbs (store->env, N_DB);
|
|
@@ -294,22 +290,50 @@ LSUP_mdbstore_new (const char *path, const LSUP_Buffer *default_ctx)
|
|
if (UNLIKELY (db_rc != MDB_SUCCESS)) return NULL;
|
|
if (UNLIKELY (db_rc != MDB_SUCCESS)) return NULL;
|
|
|
|
|
|
// Assign DB handles to store->dbi.
|
|
// Assign DB handles to store->dbi.
|
|
- MDB_txn *txn;
|
|
|
|
- mdb_txn_begin (store->env, NULL, 0, &txn);
|
|
|
|
|
|
+ mdb_txn_begin (store->env, NULL, 0, &store->txn);
|
|
for (int i = 0; i < N_DB; i++) {
|
|
for (int i = 0; i < N_DB; i++) {
|
|
- db_rc = mdb_dbi_open (txn, db_labels[i], db_flags[i], store->dbi + i);
|
|
|
|
- if (UNLIKELY (db_rc != MDB_SUCCESS)) {
|
|
|
|
- mdb_txn_abort (txn);
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
|
|
+ db_rc = mdb_dbi_open (
|
|
|
|
+ store->txn, db_labels[i], db_flags[i], store->dbi + i);
|
|
|
|
+ if (UNLIKELY (db_rc != MDB_SUCCESS)) goto fail;
|
|
}
|
|
}
|
|
|
|
|
|
- mdb_txn_commit (txn);
|
|
|
|
|
|
+ if (store->features & LSUP_STORE_PERM) {
|
|
|
|
+ // Bootstrap the permanent store with initial data.
|
|
|
|
+ MDB_stat stat;
|
|
|
|
+ mdb_stat (store->txn, store->dbi[IDX_PFX_NS], &stat);
|
|
|
|
+
|
|
|
|
+ if (stat.ms_entries == 0) {
|
|
|
|
+ log_debug ("Loading initial data into %s", path);
|
|
|
|
+
|
|
|
|
+ // Load initial NS map.
|
|
|
|
+ LSUP_NSMap *nsm = LSUP_nsmap_new();
|
|
|
|
+
|
|
|
|
+ for (int i = 0; init_nsmap[i][0] != NULL; i++)
|
|
|
|
+ LSUP_nsmap_add (nsm, init_nsmap[i][0], init_nsmap[i][1]);
|
|
|
|
+
|
|
|
|
+ LSUP_mdbstore_nsm_store (store, nsm);
|
|
|
|
+
|
|
|
|
+ // Load initial IDs.
|
|
|
|
+ for (int i = 0; init_datatypes[i] != NULL; i++) {
|
|
|
|
+ char *fq_uri;
|
|
|
|
+ LSUP_nsmap_normalize_uri (nsm, init_datatypes[i], &fq_uri);
|
|
|
|
+ db_rc = LSUP_mdbstore_idcache_store (store, fq_uri);
|
|
|
|
+ free (fq_uri);
|
|
|
|
+ if (UNLIKELY (db_rc < 0)) goto fail;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
store->state |= LSSTORE_OPEN;
|
|
store->state |= LSSTORE_OPEN;
|
|
|
|
+ mdb_txn_commit (store->txn);
|
|
store->txn = NULL;
|
|
store->txn = NULL;
|
|
|
|
|
|
return store;
|
|
return store;
|
|
|
|
+
|
|
|
|
+fail:
|
|
|
|
+ log_error (LSUP_strerror (db_rc));
|
|
|
|
+ if (store->txn) mdb_txn_abort (store->txn);
|
|
|
|
+ return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -373,6 +397,10 @@ LSUP_mdbstore_add_init (LSUP_MDBStore *store, const LSUP_Buffer *sc)
|
|
it->i = 0;
|
|
it->i = 0;
|
|
|
|
|
|
// No other write transaction may be open.
|
|
// No other write transaction may be open.
|
|
|
|
+ if (UNLIKELY (it->store->txn)) {
|
|
|
|
+ log_error ("A write transaction is already open.");
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
mdb_txn_begin (store->env, NULL, 0, &it->store->txn);
|
|
mdb_txn_begin (store->env, NULL, 0, &it->store->txn);
|
|
|
|
|
|
// Take care of context first.
|
|
// Take care of context first.
|
|
@@ -786,7 +814,7 @@ LSUP_mdbstore_remove(
|
|
LSUP_MDBStore *store, const LSUP_Buffer *ss, const LSUP_Buffer *sp,
|
|
LSUP_MDBStore *store, const LSUP_Buffer *ss, const LSUP_Buffer *sp,
|
|
const LSUP_Buffer *so, const LSUP_Buffer *sc, size_t *ct)
|
|
const LSUP_Buffer *so, const LSUP_Buffer *sc, size_t *ct)
|
|
{
|
|
{
|
|
- LSUP_rc rc = LSUP_NOACTION;
|
|
|
|
|
|
+ LSUP_rc rc = LSUP_NOACTION, db_rc;
|
|
|
|
|
|
LSUP_Key ck = NULL_KEY;
|
|
LSUP_Key ck = NULL_KEY;
|
|
|
|
|
|
@@ -795,13 +823,13 @@ LSUP_mdbstore_remove(
|
|
ck = LSUP_buffer_hash (sc);
|
|
ck = LSUP_buffer_hash (sc);
|
|
}
|
|
}
|
|
|
|
|
|
- MDB_txn *txn;
|
|
|
|
-
|
|
|
|
- mdb_txn_begin (store->env, NULL, 0, &txn);
|
|
|
|
|
|
+ // No other write transaction may be open.
|
|
|
|
+ if (UNLIKELY (store->txn)) return LSUP_TXN_ERR;
|
|
|
|
+ mdb_txn_begin (store->env, NULL, 0, &store->txn);
|
|
|
|
|
|
MDB_cursor *dcur, *icur;
|
|
MDB_cursor *dcur, *icur;
|
|
- mdb_cursor_open (txn, store->dbi[IDX_SPO_C], &dcur);
|
|
|
|
- mdb_cursor_open (txn, store->dbi[IDX_C_SPO], &icur);
|
|
|
|
|
|
+ mdb_cursor_open (store->txn, store->dbi[IDX_SPO_C], &dcur);
|
|
|
|
+ mdb_cursor_open (store->txn, store->dbi[IDX_C_SPO], &icur);
|
|
|
|
|
|
MDB_val spok_v, ck_v;
|
|
MDB_val spok_v, ck_v;
|
|
|
|
|
|
@@ -816,56 +844,59 @@ LSUP_mdbstore_remove(
|
|
while (mdbiter_next_key (it, NULL) == LSUP_OK) {
|
|
while (mdbiter_next_key (it, NULL) == LSUP_OK) {
|
|
spok_v.mv_data = it->spok;
|
|
spok_v.mv_data = it->spok;
|
|
|
|
|
|
- rc = mdb_cursor_get (dcur, &spok_v, &ck_v, MDB_GET_BOTH);
|
|
|
|
- if (rc == MDB_NOTFOUND) continue;
|
|
|
|
- if (UNLIKELY (rc != MDB_SUCCESS)) goto _remove_abort;
|
|
|
|
|
|
+ db_rc = mdb_cursor_get (dcur, &spok_v, &ck_v, MDB_GET_BOTH);
|
|
|
|
+ if (db_rc == MDB_NOTFOUND) continue;
|
|
|
|
+ if (UNLIKELY (db_rc != MDB_SUCCESS)) goto fail;
|
|
|
|
|
|
log_trace (
|
|
log_trace (
|
|
"Removing {%lx, %lx, %lx}",
|
|
"Removing {%lx, %lx, %lx}",
|
|
it->spok[0], it->spok[1], it->spok[2]);
|
|
it->spok[0], it->spok[1], it->spok[2]);
|
|
|
|
|
|
// Delete spo:c entry.
|
|
// Delete spo:c entry.
|
|
- rc = mdb_cursor_del (dcur, 0);
|
|
|
|
- if (UNLIKELY (rc != MDB_SUCCESS)) goto _remove_abort;
|
|
|
|
|
|
+ db_rc = mdb_cursor_del (dcur, 0);
|
|
|
|
+ if (UNLIKELY (db_rc != MDB_SUCCESS)) goto fail;
|
|
|
|
|
|
// Restore ck address after each delete.
|
|
// Restore ck address after each delete.
|
|
spok_v.mv_data = it->spok;
|
|
spok_v.mv_data = it->spok;
|
|
ck_v.mv_data = &ck;
|
|
ck_v.mv_data = &ck;
|
|
|
|
|
|
// Delete c:spo entry.
|
|
// Delete c:spo entry.
|
|
- rc = mdb_cursor_get (icur, &ck_v, &spok_v, MDB_GET_BOTH);
|
|
|
|
- if (rc == MDB_NOTFOUND) continue;
|
|
|
|
- if (UNLIKELY (rc != MDB_SUCCESS)) goto _remove_abort;
|
|
|
|
|
|
+ db_rc = mdb_cursor_get (icur, &ck_v, &spok_v, MDB_GET_BOTH);
|
|
|
|
+ if (db_rc == MDB_NOTFOUND) continue;
|
|
|
|
+ if (UNLIKELY (db_rc != MDB_SUCCESS)) goto fail;
|
|
|
|
|
|
- rc = mdb_cursor_del (icur, 0);
|
|
|
|
- if (UNLIKELY (rc != MDB_SUCCESS)) goto _remove_abort;
|
|
|
|
|
|
+ db_rc = mdb_cursor_del (icur, 0);
|
|
|
|
+ if (UNLIKELY (db_rc != MDB_SUCCESS)) goto fail;
|
|
|
|
|
|
spok_v.mv_data = it->spok;
|
|
spok_v.mv_data = it->spok;
|
|
ck_v.mv_data = &ck;
|
|
ck_v.mv_data = &ck;
|
|
|
|
|
|
// 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.
|
|
- rc = mdb_cursor_get (dcur, &spok_v, NULL, MDB_SET);
|
|
|
|
- if (rc == MDB_SUCCESS) continue;
|
|
|
|
- if (UNLIKELY (rc != MDB_NOTFOUND)) goto _remove_abort;
|
|
|
|
|
|
+ db_rc = mdb_cursor_get (dcur, &spok_v, NULL, MDB_SET);
|
|
|
|
+ if (db_rc == MDB_SUCCESS) continue;
|
|
|
|
+ if (UNLIKELY (db_rc != MDB_NOTFOUND)) goto fail;
|
|
|
|
|
|
- index_triple (store, OP_REMOVE, it->spok, ck);
|
|
|
|
|
|
+ rc = index_triple (store, OP_REMOVE, it->spok, ck);
|
|
}
|
|
}
|
|
|
|
|
|
LSUP_mdbiter_free (it);
|
|
LSUP_mdbiter_free (it);
|
|
|
|
|
|
- if (UNLIKELY (mdb_txn_commit (txn) != MDB_SUCCESS)) {
|
|
|
|
|
|
+ if (UNLIKELY (mdb_txn_commit (store->txn) != MDB_SUCCESS)) {
|
|
rc = LSUP_TXN_ERR;
|
|
rc = LSUP_TXN_ERR;
|
|
- goto _remove_abort;
|
|
|
|
|
|
+ goto fail;
|
|
}
|
|
}
|
|
|
|
+ store->txn = NULL;
|
|
|
|
|
|
return rc;
|
|
return rc;
|
|
|
|
|
|
-_remove_abort:
|
|
|
|
- mdb_txn_abort (txn);
|
|
|
|
- log_error ("Database error: %s", LSUP_strerror (rc));
|
|
|
|
|
|
+fail:
|
|
|
|
+ mdb_txn_abort (store->txn);
|
|
|
|
+ store->txn = NULL;
|
|
|
|
|
|
- return rc;
|
|
|
|
|
|
+ log_error ("Database error: %s", LSUP_strerror (db_rc));
|
|
|
|
+
|
|
|
|
+ return rc == LSUP_TXN_ERR ? rc : LSUP_DB_ERR;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -917,7 +948,7 @@ LSUP_mdbstore_nsm_get (LSUP_MDBStore *store, LSUP_NSMap **nsm_p)
|
|
}
|
|
}
|
|
|
|
|
|
MDB_val ns_v, pfx_v;
|
|
MDB_val ns_v, pfx_v;
|
|
- if (mdb_cursor_get (cur, &ns_v, &pfx_v, MDB_FIRST) != MDB_SUCCESS)
|
|
|
|
|
|
+ if (mdb_cursor_get (cur, &pfx_v, &ns_v, MDB_FIRST) != MDB_SUCCESS)
|
|
goto finally;
|
|
goto finally;
|
|
|
|
|
|
do {
|
|
do {
|
|
@@ -930,7 +961,7 @@ LSUP_mdbstore_nsm_get (LSUP_MDBStore *store, LSUP_NSMap **nsm_p)
|
|
|
|
|
|
free (ns);
|
|
free (ns);
|
|
} while (mdb_cursor_get (
|
|
} while (mdb_cursor_get (
|
|
- cur, &ns_v, &pfx_v, MDB_NEXT_NODUP) == MDB_SUCCESS);
|
|
|
|
|
|
+ cur, &pfx_v, &ns_v, MDB_NEXT_NODUP) == MDB_SUCCESS);
|
|
|
|
|
|
finally:
|
|
finally:
|
|
mdb_cursor_close (cur);
|
|
mdb_cursor_close (cur);
|
|
@@ -944,10 +975,7 @@ LSUP_rc
|
|
LSUP_mdbstore_nsm_store (LSUP_MDBStore *store, const LSUP_NSMap *nsm)
|
|
LSUP_mdbstore_nsm_store (LSUP_MDBStore *store, const LSUP_NSMap *nsm)
|
|
{
|
|
{
|
|
MDB_txn *txn;
|
|
MDB_txn *txn;
|
|
- if (!store->txn) {
|
|
|
|
- RCCK (mdb_txn_begin (store->env, NULL, 0, &txn));
|
|
|
|
- }
|
|
|
|
- else txn = store->txn;
|
|
|
|
|
|
+ RCCK (mdb_txn_begin (store->env, store->txn, 0, &txn));
|
|
|
|
|
|
LSUP_rc rc = LSUP_NOACTION;
|
|
LSUP_rc rc = LSUP_NOACTION;
|
|
int db_rc;
|
|
int db_rc;
|
|
@@ -958,8 +986,8 @@ LSUP_mdbstore_nsm_store (LSUP_MDBStore *store, const LSUP_NSMap *nsm)
|
|
||
|
|
||
|
|
mdb_cursor_open (txn, store->dbi[IDX_NS_PFX], &icur) != MDB_SUCCESS
|
|
mdb_cursor_open (txn, store->dbi[IDX_NS_PFX], &icur) != MDB_SUCCESS
|
|
) {
|
|
) {
|
|
- rc = LSUP_DB_ERR;
|
|
|
|
- goto finally;
|
|
|
|
|
|
+ mdb_txn_abort (txn);
|
|
|
|
+ return LSUP_DB_ERR;
|
|
}
|
|
}
|
|
|
|
|
|
MDB_val pfx_v, ns_v;
|
|
MDB_val pfx_v, ns_v;
|
|
@@ -969,34 +997,115 @@ LSUP_mdbstore_nsm_store (LSUP_MDBStore *store, const LSUP_NSMap *nsm)
|
|
// At least 1 action. If not OK, it will change during the iteration.
|
|
// At least 1 action. If not OK, it will change during the iteration.
|
|
if (i == 0) rc = LSUP_OK;
|
|
if (i == 0) rc = LSUP_OK;
|
|
|
|
|
|
- pfx_v.mv_data = (void *)nsm_data[i][0];
|
|
|
|
|
|
+ pfx_v.mv_data = (void *) nsm_data[i];
|
|
pfx_v.mv_size = strlen (nsm_data[i][0]) + 1;
|
|
pfx_v.mv_size = strlen (nsm_data[i][0]) + 1;
|
|
- ns_v.mv_data = (void *)nsm_data[i][1];
|
|
|
|
|
|
+ ns_v.mv_data = (void *) nsm_data[i] + 1;
|
|
ns_v.mv_size = strlen (nsm_data[i][1]) + 1;
|
|
ns_v.mv_size = strlen (nsm_data[i][1]) + 1;
|
|
|
|
|
|
- // If either ns or pfx exist, quit.
|
|
|
|
|
|
+ // If either ns or pfx exist, skip.
|
|
if (
|
|
if (
|
|
mdb_cursor_get (dcur, &pfx_v, &ns_v, MDB_SET) != MDB_NOTFOUND
|
|
mdb_cursor_get (dcur, &pfx_v, &ns_v, MDB_SET) != MDB_NOTFOUND
|
|
||
|
|
||
|
|
mdb_cursor_get (icur, &ns_v, &pfx_v, MDB_SET) != MDB_NOTFOUND
|
|
mdb_cursor_get (icur, &ns_v, &pfx_v, MDB_SET) != MDB_NOTFOUND
|
|
) {
|
|
) {
|
|
rc = LSUP_CONFLICT;
|
|
rc = LSUP_CONFLICT;
|
|
- goto finally;
|
|
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
|
|
|
|
db_rc = mdb_cursor_put (dcur, &pfx_v, &ns_v, 0);
|
|
db_rc = mdb_cursor_put (dcur, &pfx_v, &ns_v, 0);
|
|
|
|
+ db_rc |= mdb_cursor_put (icur, &ns_v, &pfx_v, 0);
|
|
if (db_rc != MDB_SUCCESS) {
|
|
if (db_rc != MDB_SUCCESS) {
|
|
log_error ("DB error: %s", LSUP_strerror (db_rc));
|
|
log_error ("DB error: %s", LSUP_strerror (db_rc));
|
|
- rc = LSUP_DB_ERR;
|
|
|
|
- goto finally;
|
|
|
|
|
|
+ free (nsm_data);
|
|
|
|
+ return LSUP_DB_ERR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ free (nsm_data);
|
|
|
|
+
|
|
|
|
+ if (UNLIKELY (mdb_txn_commit (txn) != MDB_SUCCESS)) {
|
|
|
|
+ mdb_txn_abort (txn);
|
|
|
|
+ return LSUP_TXN_ERR;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+LSUP_rc
|
|
|
|
+LSUP_mdbstore_idcache_store (LSUP_MDBStore *store, const char *id)
|
|
|
|
+{
|
|
|
|
+ int db_rc;
|
|
|
|
+ MDB_val key, data;
|
|
|
|
+
|
|
|
|
+ MDB_txn *txn;
|
|
|
|
+ // If store->txn exists, open a child txn, otherwise parent should be NULL.
|
|
|
|
+ RCCK (mdb_txn_begin (store->env, store->txn, 0, &txn));
|
|
|
|
+
|
|
|
|
+ MDB_cursor *cur;
|
|
|
|
+ db_rc = mdb_cursor_open (txn, store->dbi[IDX_IDK_ID], &cur);
|
|
|
|
+ if (UNLIKELY (db_rc != MDB_SUCCESS)) goto fail;
|
|
|
|
+
|
|
|
|
+ uint32_t k = XXH32 (id, strlen (id) + 1, HASH_SEED);
|
|
|
|
+ key.mv_data = &k;
|
|
|
|
+ key.mv_size = sizeof (k);
|
|
|
|
+
|
|
|
|
+ data.mv_data = (void *) id;
|
|
|
|
+ data.mv_size = strlen (id) + 1;
|
|
|
|
+
|
|
|
|
+ db_rc = mdb_cursor_put (cur, &key, &data, MDB_NOOVERWRITE);
|
|
|
|
+ if (db_rc != MDB_SUCCESS && db_rc != MDB_KEYEXIST) goto fail;
|
|
|
|
+
|
|
|
|
+ if (txn != store->txn) {
|
|
|
|
+ db_rc = mdb_txn_commit (txn);
|
|
|
|
+ txn = NULL;
|
|
|
|
+ if (UNLIKELY (db_rc != MDB_SUCCESS)) goto fail;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return LSUP_OK;
|
|
|
|
+
|
|
|
|
+fail:
|
|
|
|
+ log_error (mdb_strerror (db_rc));
|
|
|
|
+ if (txn) mdb_txn_abort (txn);
|
|
|
|
+ return LSUP_DB_ERR;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+LSUP_rc
|
|
|
|
+LSUP_mdbstore_idcache_get (LSUP_MDBStore *store)
|
|
|
|
+{
|
|
|
|
+ int db_rc, rc = LSUP_NOACTION;
|
|
|
|
+ MDB_txn *txn = NULL;
|
|
|
|
+ MDB_cursor *cur = NULL;
|
|
|
|
+
|
|
|
|
+ RCCK (mdb_txn_begin (store->env, NULL, MDB_RDONLY, &txn));
|
|
|
|
+
|
|
|
|
+ db_rc = mdb_cursor_open (txn, store->dbi[IDX_IDK_ID], &cur);
|
|
|
|
+ if (UNLIKELY (db_rc != MDB_SUCCESS)) {
|
|
|
|
+ log_error ("Database error: %s", LSUP_strerror (db_rc));
|
|
|
|
+ rc = LSUP_DB_ERR;
|
|
|
|
+ goto finally;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ MDB_val key, data;
|
|
|
|
+ db_rc = mdb_cursor_get (cur, &key, &data, MDB_FIRST);
|
|
|
|
+ if (db_rc != MDB_NOTFOUND) rc = LSUP_OK;
|
|
|
|
+
|
|
|
|
+ while (db_rc == MDB_SUCCESS) {
|
|
|
|
+ rc = LSUP_tcache_add_id (
|
|
|
|
+ *(uint32_t *) key.mv_data, (char *) data.mv_data);
|
|
|
|
+ if (UNLIKELY (rc != LSUP_OK)) goto finally;
|
|
|
|
+
|
|
|
|
+ db_rc = mdb_cursor_get (cur, &key, &data, MDB_NEXT_NODUP);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (db_rc != MDB_NOTFOUND) {
|
|
|
|
+ log_error ("Database error: %s", LSUP_strerror (db_rc));
|
|
|
|
+ rc = LSUP_DB_ERR;
|
|
|
|
+ }
|
|
|
|
|
|
finally:
|
|
finally:
|
|
- if (icur) mdb_cursor_close (icur);
|
|
|
|
- if (dcur) mdb_cursor_close (dcur);
|
|
|
|
- free (nsm_data);
|
|
|
|
- if (txn != store->txn) mdb_txn_commit (txn);
|
|
|
|
|
|
+ if (cur) mdb_cursor_close (cur);
|
|
|
|
+ mdb_txn_abort (txn);
|
|
|
|
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|