|
@@ -22,12 +22,15 @@ typedef struct ht_store_t {
|
|
|
|
|
|
typedef struct ht_iterator_t {
|
|
typedef struct ht_iterator_t {
|
|
HTStore * store; // Store being iterated.
|
|
HTStore * store; // Store being iterated.
|
|
- size_t i; // Number of records found at any point of
|
|
|
|
|
|
+ size_t cur; // Internal has table cursor.
|
|
|
|
+ size_t ct; // Number of records found at any point of
|
|
// a lookup iteration, or number of records
|
|
// a lookup iteration, or number of records
|
|
// added at any point of an add loop.
|
|
// added at any point of an add loop.
|
|
LSUP_Key luk[3]; // 0÷3 lookup keys.
|
|
LSUP_Key luk[3]; // 0÷3 lookup keys.
|
|
LSUP_key_eq_fn_t eq_fn; // Equality function to test triples.
|
|
LSUP_key_eq_fn_t eq_fn; // Equality function to test triples.
|
|
int rc; // Return code for *next* result.
|
|
int rc; // Return code for *next* result.
|
|
|
|
+ // When the end of results is reached, this
|
|
|
|
+ // is set to LSUP_END.
|
|
LSUP_TripleKey * entry; // Retrieved SPO key.
|
|
LSUP_TripleKey * entry; // Retrieved SPO key.
|
|
} HTIterator;
|
|
} HTIterator;
|
|
|
|
|
|
@@ -149,12 +152,16 @@ static void htstore_idx_free_fn (void *item)
|
|
|
|
|
|
/* * * Other prototypes. * * */
|
|
/* * * Other prototypes. * * */
|
|
|
|
|
|
-inline static LSUP_rc tkey_to_strp (
|
|
|
|
|
|
+inline static LSUP_rc
|
|
|
|
+tkey_to_strp (
|
|
const HTStore *store, const LSUP_Key *spok, LSUP_BufferTriple *sspo);
|
|
const HTStore *store, const LSUP_Key *spok, LSUP_BufferTriple *sspo);
|
|
|
|
|
|
static LSUP_rc
|
|
static LSUP_rc
|
|
htstore_add_key_iter (HTIterator *it, const LSUP_TripleKey spok);
|
|
htstore_add_key_iter (HTIterator *it, const LSUP_TripleKey spok);
|
|
|
|
|
|
|
|
+static LSUP_rc
|
|
|
|
+htiter_next_key (HTIterator *it, LSUP_TripleKey *spok);
|
|
|
|
+
|
|
|
|
|
|
/* * * API * * */
|
|
/* * * API * * */
|
|
|
|
|
|
@@ -287,6 +294,7 @@ LSUP_htstore_add_term (HTStore *store, const LSUP_Buffer *sterm)
|
|
hashmap_set (
|
|
hashmap_set (
|
|
store->idx, &(IndexEntry){
|
|
store->idx, &(IndexEntry){
|
|
.key = tk,
|
|
.key = tk,
|
|
|
|
+ // This shall be freed with the index hashmap.
|
|
.sterm = LSUP_buffer_new (sterm->size, sterm->addr)
|
|
.sterm = LSUP_buffer_new (sterm->size, sterm->addr)
|
|
});
|
|
});
|
|
|
|
|
|
@@ -301,7 +309,7 @@ LSUP_htstore_add_init (HTStore *store)
|
|
MALLOC_GUARD (it, NULL);
|
|
MALLOC_GUARD (it, NULL);
|
|
|
|
|
|
it->store = store;
|
|
it->store = store;
|
|
- it->i = 0;
|
|
|
|
|
|
+ it->ct = 0;
|
|
|
|
|
|
return it;
|
|
return it;
|
|
}
|
|
}
|
|
@@ -316,7 +324,17 @@ LSUP_htstore_add_iter (HTIterator *it, const LSUP_BufferTriple *sspo)
|
|
LSUP_buffer_hash (sspo->o),
|
|
LSUP_buffer_hash (sspo->o),
|
|
};
|
|
};
|
|
|
|
|
|
- return htstore_add_key_iter (it, spok);
|
|
|
|
|
|
+ LSUP_rc rc = htstore_add_key_iter (it, spok);
|
|
|
|
+
|
|
|
|
+ if (rc != LSUP_OK) return rc;
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < 3; i++) {
|
|
|
|
+ rc = LSUP_htstore_add_term (it->store, LSUP_btriple_pos (sspo, i));
|
|
|
|
+ if (rc != LSUP_OK) return rc;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
void
|
|
void
|
|
@@ -329,33 +347,22 @@ LSUP_htstore_remove(
|
|
LSUP_HTStore *store, const LSUP_Buffer *ss, const LSUP_Buffer *sp,
|
|
LSUP_HTStore *store, const LSUP_Buffer *ss, const LSUP_Buffer *sp,
|
|
const LSUP_Buffer *so, size_t *ct)
|
|
const LSUP_Buffer *so, size_t *ct)
|
|
{
|
|
{
|
|
|
|
+ LSUP_rc rc = LSUP_NOACTION;
|
|
|
|
+
|
|
LSUP_HTIterator *it = LSUP_htstore_lookup (store, ss, sp, so);
|
|
LSUP_HTIterator *it = LSUP_htstore_lookup (store, ss, sp, so);
|
|
if (UNLIKELY (!it)) return LSUP_DB_ERR;
|
|
if (UNLIKELY (!it)) return LSUP_DB_ERR;
|
|
|
|
|
|
- if (ct) *ct = 0;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- void **entry;
|
|
|
|
- size_t i = 0;
|
|
|
|
- while (hashmap_iter (store->keys, &i, entry)) {
|
|
|
|
- hashmap_delete (store->keys, *entry);
|
|
|
|
- }
|
|
|
|
- if (ct) *ct = i;
|
|
|
|
- */
|
|
|
|
LSUP_TripleKey *tmp;
|
|
LSUP_TripleKey *tmp;
|
|
- HASH_ITER (hh, store->keys, it->entry, tmp) {
|
|
|
|
- if (it->eq_fn (it->entry->key, it->luk)) {
|
|
|
|
- HASH_DEL (store->keys, it->entry);
|
|
|
|
- free (it->entry);
|
|
|
|
-
|
|
|
|
- if (ct) (*ct)++;
|
|
|
|
|
|
+ while (htiter_next_key (it, tmp)) {
|
|
|
|
+ if (it->rc == LSUP_OK) {
|
|
|
|
+ tmp = hashmap_delete (store->keys, tmp);
|
|
|
|
+ free (tmp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ if (ct) *ct = it->ct;
|
|
|
|
|
|
LSUP_htiter_free (it);
|
|
LSUP_htiter_free (it);
|
|
|
|
|
|
- // TODO clean up orphan indices in separate (async, scheduled) function.
|
|
|
|
-
|
|
|
|
return LSUP_OK;
|
|
return LSUP_OK;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -368,10 +375,11 @@ LSUP_htstore_lookup (HTStore *store, const LSUP_Buffer *ss,
|
|
MALLOC_GUARD (it, NULL);
|
|
MALLOC_GUARD (it, NULL);
|
|
|
|
|
|
it->store = store;
|
|
it->store = store;
|
|
- //it->cur = 0;
|
|
|
|
|
|
+ it->cur = 0;
|
|
|
|
+ it->ct = 0;
|
|
it->rc = LSUP_END;
|
|
it->rc = LSUP_END;
|
|
|
|
|
|
- if (HASH_COUNT (store->keys) == 0) return it;
|
|
|
|
|
|
+ if (hashmap_count (store->keys) == 0) return it;
|
|
|
|
|
|
LSUP_TripleKey spok = {
|
|
LSUP_TripleKey spok = {
|
|
LSUP_buffer_hash (ss),
|
|
LSUP_buffer_hash (ss),
|
|
@@ -401,7 +409,6 @@ LSUP_htstore_lookup (HTStore *store, const LSUP_Buffer *ss,
|
|
} else {
|
|
} else {
|
|
it->eq_fn = lookup_sk_eq_fn;
|
|
it->eq_fn = lookup_sk_eq_fn;
|
|
}
|
|
}
|
|
- //it->cur = 0;
|
|
|
|
|
|
|
|
} else if (spok[1] != NULL_KEY) {
|
|
} else if (spok[1] != NULL_KEY) {
|
|
it->luk[0] = spok[1];
|
|
it->luk[0] = spok[1];
|
|
@@ -422,9 +429,9 @@ LSUP_htstore_lookup (HTStore *store, const LSUP_Buffer *ss,
|
|
// ? ? ?
|
|
// ? ? ?
|
|
} else it->eq_fn = lookup_none_eq_fn;
|
|
} else it->eq_fn = lookup_none_eq_fn;
|
|
|
|
|
|
- it->entry = it->store->keys; // First record in hash table.
|
|
|
|
- it->rc = it->entry == NULL ? LSUP_END : LSUP_OK;
|
|
|
|
- it->i = 0;
|
|
|
|
|
|
+ // Position cursor at first record in hash table.
|
|
|
|
+ if (hashmap_iter (it->store->keys, &it->cur, (void **) it->entry))
|
|
|
|
+ it->rc = LSUP_OK; // Else it's LSUP_END already.
|
|
|
|
|
|
return it;
|
|
return it;
|
|
}
|
|
}
|
|
@@ -436,8 +443,8 @@ LSUP_htiter_free (LSUP_HTIterator *it)
|
|
|
|
|
|
|
|
|
|
size_t
|
|
size_t
|
|
-LSUP_htiter_cur (const LSUP_HTIterator *it)
|
|
|
|
-{ return it->i; }
|
|
|
|
|
|
+LSUP_htiter_count (const LSUP_HTIterator *it)
|
|
|
|
+{ return it->cur; }
|
|
|
|
|
|
|
|
|
|
LSUP_rc
|
|
LSUP_rc
|
|
@@ -448,6 +455,7 @@ htiter_next_key (HTIterator *it, LSUP_TripleKey *spok)
|
|
// If the previous iteration hit the end, return.
|
|
// If the previous iteration hit the end, return.
|
|
if (it->rc != LSUP_OK) return it->rc;
|
|
if (it->rc != LSUP_OK) return it->rc;
|
|
|
|
|
|
|
|
+ // This value is for internal looping only. It shall never be returned.
|
|
it->rc = LSUP_NORESULT;
|
|
it->rc = LSUP_NORESULT;
|
|
/*
|
|
/*
|
|
#ifdef DEBUG
|
|
#ifdef DEBUG
|
|
@@ -462,33 +470,34 @@ htiter_next_key (HTIterator *it, LSUP_TripleKey *spok)
|
|
#endif
|
|
#endif
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
+ // Iteration resumes from lookup where first hashmap_iter was called.
|
|
do {
|
|
do {
|
|
- if (!it->entry) it->rc = LSUP_END;
|
|
|
|
-
|
|
|
|
- else {
|
|
|
|
- if (it->eq_fn (*it->entry, it->luk)) {
|
|
|
|
- log_trace (
|
|
|
|
- "Found spok: {%lx, %lx, %lx}",
|
|
|
|
- it->entry[0], it->entry[1], it->entry[2]
|
|
|
|
- );
|
|
|
|
- /*
|
|
|
|
|
|
+ if (!it->entry) return LSUP_END;
|
|
|
|
+
|
|
|
|
+ // Loop through all triples until a match is found, or end is reached.
|
|
|
|
+ if (it->eq_fn (*it->entry, it->luk)) {
|
|
|
|
+ log_trace (
|
|
|
|
+ "Found spok: {%lx, %lx, %lx}",
|
|
|
|
+ it->entry[0], it->entry[1], it->entry[2]
|
|
|
|
+ );
|
|
|
|
+ /*
|
|
#ifdef DEBUG
|
|
#ifdef DEBUG
|
|
- IndexEntry *tmp = NULL;
|
|
|
|
- HASH_FIND (hh, it->store->idx, it->entry->key + 0, KLEN, tmp);
|
|
|
|
- LSUP_buffer_print(tmp->sterm);
|
|
|
|
- HASH_FIND (hh, it->store->idx, it->entry->key + 1, KLEN, tmp);
|
|
|
|
- LSUP_buffer_print(tmp->sterm);
|
|
|
|
- HASH_FIND (hh, it->store->idx, it->entry->key + 2, KLEN, tmp);
|
|
|
|
- LSUP_buffer_print(tmp->sterm);
|
|
|
|
|
|
+ IndexEntry *tmp = NULL;
|
|
|
|
+ HASH_FIND (hh, it->store->idx, it->entry->key + 0, KLEN, tmp);
|
|
|
|
+ LSUP_buffer_print(tmp->sterm);
|
|
|
|
+ HASH_FIND (hh, it->store->idx, it->entry->key + 1, KLEN, tmp);
|
|
|
|
+ LSUP_buffer_print(tmp->sterm);
|
|
|
|
+ HASH_FIND (hh, it->store->idx, it->entry->key + 2, KLEN, tmp);
|
|
|
|
+ LSUP_buffer_print(tmp->sterm);
|
|
#endif
|
|
#endif
|
|
- */
|
|
|
|
-
|
|
|
|
- it->rc = LSUP_OK;
|
|
|
|
- it->i++;
|
|
|
|
- }
|
|
|
|
|
|
+ */
|
|
|
|
|
|
- it->entry = it->entry->hh.next;
|
|
|
|
|
|
+ it->rc = LSUP_OK;
|
|
|
|
+ it->ct++;
|
|
}
|
|
}
|
|
|
|
+ if (hashmap_iter (it->store->keys, &it->cur, (void **) it->entry))
|
|
|
|
+ it->rc = LSUP_OK;
|
|
|
|
+
|
|
} while (it->rc == LSUP_NORESULT);
|
|
} while (it->rc == LSUP_NORESULT);
|
|
|
|
|
|
return it->rc;
|
|
return it->rc;
|
|
@@ -499,17 +508,16 @@ LSUP_rc
|
|
LSUP_htiter_next (HTIterator *it, LSUP_BufferTriple *sspo)
|
|
LSUP_htiter_next (HTIterator *it, LSUP_BufferTriple *sspo)
|
|
{
|
|
{
|
|
LSUP_TripleKey *cur;
|
|
LSUP_TripleKey *cur;
|
|
- while (htiter_next_key (it, cur) {
|
|
|
|
- tkey_to_strp (it->store, it->entry->key, sspo);
|
|
|
|
- if (!sspo->s || !sspo->p || !sspo->o) return LSUP_DB_ERR;
|
|
|
|
- }
|
|
|
|
|
|
+ LSUP_rc rc = htiter_next_key (it, cur);
|
|
|
|
+ if (rc != LSUP_OK) return rc;
|
|
|
|
|
|
|
|
+ return tkey_to_strp (it->store, *it->entry, sspo);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/* * * Statics * * */
|
|
/* * * Statics * * */
|
|
|
|
|
|
-static inline LSUP_rc
|
|
|
|
|
|
+inline static LSUP_rc
|
|
tkey_to_strp (
|
|
tkey_to_strp (
|
|
const HTStore *store, const LSUP_Key *spok, LSUP_BufferTriple *sspo)
|
|
const HTStore *store, const LSUP_Key *spok, LSUP_BufferTriple *sspo)
|
|
{
|
|
{
|
|
@@ -517,15 +525,15 @@ tkey_to_strp (
|
|
IndexEntry *tmp;
|
|
IndexEntry *tmp;
|
|
|
|
|
|
tmp = hashmap_get (store->idx, spok + 0);
|
|
tmp = hashmap_get (store->idx, spok + 0);
|
|
- if (UNLIKELY (!tmp)) return LSUP_ERROR;
|
|
|
|
|
|
+ if (UNLIKELY (!tmp)) return LSUP_DB_ERR;
|
|
sspo->s = tmp->sterm;
|
|
sspo->s = tmp->sterm;
|
|
|
|
|
|
tmp = hashmap_get (store->idx, spok + 1);
|
|
tmp = hashmap_get (store->idx, spok + 1);
|
|
- if (UNLIKELY (!tmp)) return LSUP_ERROR;
|
|
|
|
|
|
+ if (UNLIKELY (!tmp)) return LSUP_DB_ERR;
|
|
sspo->p = tmp->sterm;
|
|
sspo->p = tmp->sterm;
|
|
|
|
|
|
tmp = hashmap_get (store->idx, spok + 2);
|
|
tmp = hashmap_get (store->idx, spok + 2);
|
|
- if (UNLIKELY (!tmp)) return LSUP_ERROR;
|
|
|
|
|
|
+ if (UNLIKELY (!tmp)) return LSUP_DB_ERR;
|
|
sspo->o = tmp->sterm;
|
|
sspo->o = tmp->sterm;
|
|
|
|
|
|
return LSUP_OK;
|
|
return LSUP_OK;
|
|
@@ -538,34 +546,17 @@ htstore_add_key_iter (HTIterator *it, const LSUP_TripleKey spok)
|
|
// Add triple.
|
|
// Add triple.
|
|
log_trace ("Inserting spok: {%lx, %lx, %lx}", spok[0], spok[1], spok[2]);
|
|
log_trace ("Inserting spok: {%lx, %lx, %lx}", spok[0], spok[1], spok[2]);
|
|
|
|
|
|
- TripleEntry *k_ins = NULL;
|
|
|
|
- HASH_FIND (hh, it->store->keys, spok, TRP_KLEN, k_ins);
|
|
|
|
- if (k_ins == NULL) {
|
|
|
|
- log_trace ("Triple not found, inserting.");
|
|
|
|
- MALLOC_GUARD (k_ins, LSUP_MEM_ERR);
|
|
|
|
-
|
|
|
|
- memcpy (k_ins->key, spok, TRP_KLEN);
|
|
|
|
- HASH_ADD (hh, it->store->keys, key, TRP_KLEN, k_ins);
|
|
|
|
-
|
|
|
|
- it->i++;
|
|
|
|
- } else {
|
|
|
|
- log_trace ("Triple found. Skipping.");
|
|
|
|
|
|
+ if (hashmap_get (it->store->keys, &spok)) {
|
|
|
|
+ log_trace ("Triple found. Not adding.");
|
|
return LSUP_NOACTION;
|
|
return LSUP_NOACTION;
|
|
}
|
|
}
|
|
|
|
|
|
- // Add terms to index. Terms are copied.
|
|
|
|
- for (int i = 0; i < 3; i++) {
|
|
|
|
- IndexEntry *ins = NULL;
|
|
|
|
- HASH_FIND (hh, it->store->idx, spok + i, KLEN, ins);
|
|
|
|
- if (ins == NULL) {
|
|
|
|
- MALLOC_GUARD (ins, LSUP_MEM_ERR);
|
|
|
|
- ins->key = spok[i];
|
|
|
|
- ins->sterm = LSUP_buffer_new (
|
|
|
|
- (LSUP_btriple_pos (sspo, i))->size,
|
|
|
|
- (LSUP_btriple_pos (sspo, i))->addr);
|
|
|
|
- HASH_ADD (hh, it->store->idx, key, KLEN, ins);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ log_trace ("Triple not found, inserting.");
|
|
|
|
+
|
|
|
|
+ hashmap_set (it->store->keys, &spok);
|
|
|
|
+ if (hashmap_oom(it->store->keys)) return LSUP_MEM_ERR;
|
|
|
|
+
|
|
|
|
+ it->ct++;
|
|
|
|
|
|
return LSUP_OK;
|
|
return LSUP_OK;
|
|
}
|
|
}
|