|
@@ -28,11 +28,13 @@ typedef struct ht_store_t {
|
|
|
|
|
|
typedef struct ht_iterator_t {
|
|
|
HTStore * store; // Store being iterated.
|
|
|
- size_t i; // Lookup cursor.
|
|
|
+ size_t i; // Number of records found at any point of
|
|
|
+ // a lookup iteration, or number of records
|
|
|
+ // added at any point of an add loop.
|
|
|
LSUP_Key luk[3]; // 0÷3 lookup keys.
|
|
|
LSUP_key_eq_fn_t eq_fn; // Equality function to test triples.
|
|
|
int rc; // Return code for *next* result.
|
|
|
- TripleEntry * spok; // Retrieved SPO key.
|
|
|
+ TripleEntry * bucket; // Retrieved SPO key bucket.
|
|
|
} HTIterator;
|
|
|
|
|
|
|
|
@@ -97,7 +99,6 @@ static bool lookup_pok_eq_fn(
|
|
|
|
|
|
/* * * Other prototypes. * * */
|
|
|
|
|
|
-static inline LSUP_rc htiter_next_key (HTIterator *it);
|
|
|
static inline LSUP_rc tkey_to_strp (
|
|
|
const HTStore *store, const LSUP_Key spok[], LSUP_SerTriple *sspo);
|
|
|
|
|
@@ -285,7 +286,11 @@ LSUP_htstore_add_init (HTStore *store)
|
|
|
LSUP_rc
|
|
|
LSUP_htstore_add_iter (HTIterator *it, const LSUP_SerTriple *sspo)
|
|
|
{
|
|
|
- LSUP_TripleKey spok = NULL_TRP;
|
|
|
+ LSUP_TripleKey spok = {
|
|
|
+ LSUP_buffer_hash (sspo->s),
|
|
|
+ LSUP_buffer_hash (sspo->p),
|
|
|
+ LSUP_buffer_hash (sspo->o),
|
|
|
+ };
|
|
|
|
|
|
// Add triple.
|
|
|
TRACE ("Inserting spok: {%lx, %lx, %lx}", spok[0], spok[1], spok[2]);
|
|
@@ -335,17 +340,21 @@ LSUP_rc
|
|
|
LSUP_htstore_remove(
|
|
|
LSUP_HTStore *store, const LSUP_SerTriple *sspo, size_t *ct)
|
|
|
{
|
|
|
- LSUP_HTIterator *it = LSUP_htstore_lookup (store, sspo, ct);
|
|
|
+ LSUP_HTIterator *it = LSUP_htstore_lookup (store, sspo);
|
|
|
if (UNLIKELY (!it)) return LSUP_DB_ERR;
|
|
|
|
|
|
*ct = 0;
|
|
|
- while (htiter_next_key (it)) {
|
|
|
- HASH_DEL (store->keys, it->spok);
|
|
|
- free (it->spok);
|
|
|
- //if (UNLIKELY (rc < 0)) return rc;
|
|
|
|
|
|
- (*ct) ++;
|
|
|
+ TripleEntry *tmp = malloc (sizeof (*tmp));
|
|
|
+ HASH_ITER (hh, store->keys, it->bucket, tmp) {
|
|
|
+ if (it->eq_fn (it->bucket->key, it->luk)) {
|
|
|
+ HASH_DEL (store->keys, it->bucket);
|
|
|
+ free (it->bucket);
|
|
|
+
|
|
|
+ (*ct)++;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
// TODO clean up orphan indices in separate (async, scheduled) function.
|
|
|
|
|
|
return LSUP_OK;
|
|
@@ -353,7 +362,7 @@ LSUP_htstore_remove(
|
|
|
|
|
|
|
|
|
HTIterator *
|
|
|
-LSUP_htstore_lookup (HTStore *store, const LSUP_SerTriple *sspo, size_t *ct)
|
|
|
+LSUP_htstore_lookup (HTStore *store, const LSUP_SerTriple *sspo)
|
|
|
{
|
|
|
HTIterator *it = malloc (sizeof (*it));
|
|
|
if (UNLIKELY (!it)) return NULL;
|
|
@@ -413,8 +422,9 @@ LSUP_htstore_lookup (HTStore *store, const LSUP_SerTriple *sspo, size_t *ct)
|
|
|
// ? ? ?
|
|
|
} else it->eq_fn = lookup_none_eq_fn;
|
|
|
|
|
|
- it->spok = it->store->keys->hh.next;
|
|
|
- it->rc = it->spok == NULL ? LSUP_END : LSUP_OK;
|
|
|
+ it->bucket = it->store->keys; // First record in hash table.
|
|
|
+ it->rc = it->bucket == NULL ? LSUP_END : LSUP_OK;
|
|
|
+ it->i = 0;
|
|
|
|
|
|
return it;
|
|
|
}
|
|
@@ -433,47 +443,37 @@ LSUP_htiter_cur (LSUP_HTIterator *it)
|
|
|
LSUP_rc
|
|
|
LSUP_htiter_next (HTIterator *it, LSUP_SerTriple *sspo)
|
|
|
{
|
|
|
- LSUP_rc rc = htiter_next_key (it);
|
|
|
- if (UNLIKELY (rc != LSUP_OK)) return rc;
|
|
|
+ // If the previous iteration hit the end, return.
|
|
|
+ if (it->rc != LSUP_OK) return it->rc;
|
|
|
|
|
|
- IndexEntry *cur;
|
|
|
+ it->rc = LSUP_NORESULT;
|
|
|
|
|
|
- HASH_FIND (hh, it->store->idx, it->spok + 0, KLEN, cur);
|
|
|
- sspo->s = cur->sterm;
|
|
|
- HASH_FIND (hh, it->store->idx, it->spok + 1, KLEN, cur);
|
|
|
- sspo->p = cur->sterm;
|
|
|
- HASH_FIND (hh, it->store->idx, it->spok + 2, KLEN, cur);
|
|
|
- sspo->o = cur->sterm;
|
|
|
+ while (it->rc == LSUP_NORESULT) {
|
|
|
+ if (!it->bucket) it->rc = LSUP_END;
|
|
|
|
|
|
- if (!sspo->s || !sspo->p || !sspo->o) {
|
|
|
- sspo = NULL;
|
|
|
- return LSUP_DB_ERR;
|
|
|
- }
|
|
|
-
|
|
|
- return LSUP_OK;
|
|
|
-}
|
|
|
+ else {
|
|
|
+ if (it->eq_fn (it->bucket->key, it->luk)) {
|
|
|
+ tkey_to_strp (it->store, it->bucket->key, sspo);
|
|
|
+ if (!sspo->s || !sspo->p || !sspo->o) return LSUP_DB_ERR;
|
|
|
|
|
|
+ TRACE (
|
|
|
+ "Found spok: {%lx, %lx, %lx}",
|
|
|
+ it->bucket->key[0], it->bucket->key[1], it->bucket->key[2]
|
|
|
+ );
|
|
|
|
|
|
-/* * * Statics * * */
|
|
|
+ it->rc = LSUP_OK;
|
|
|
+ it->i++;
|
|
|
+ }
|
|
|
|
|
|
-static inline LSUP_rc
|
|
|
-htiter_next_key (HTIterator *it)
|
|
|
-{
|
|
|
- // Loop as long as there are entries, and until a match is found.
|
|
|
- for (;;) {
|
|
|
- if (it->rc != LSUP_OK) return it->rc;
|
|
|
- if (it->eq_fn (it->spok->key, it->luk)) return LSUP_OK;
|
|
|
-
|
|
|
- TripleEntry *cur = NULL, *tmp = NULL;
|
|
|
- HASH_ITER (hh, it->store->keys, cur, tmp);
|
|
|
- if (cur != NULL) {
|
|
|
- it->spok = cur;
|
|
|
- it->rc = LSUP_OK;
|
|
|
- } else it->rc = LSUP_NORESULT;
|
|
|
+ it->bucket = it->bucket->hh.next;
|
|
|
+ }
|
|
|
}
|
|
|
+ return it->rc;
|
|
|
}
|
|
|
|
|
|
|
|
|
+/* * * Statics * * */
|
|
|
+
|
|
|
inline static LSUP_rc
|
|
|
tkey_to_strp (
|
|
|
const HTStore *store, const LSUP_Key spok[], LSUP_SerTriple *sspo)
|