|
@@ -1,3 +1,4 @@
|
|
|
+#include "htable.h"
|
|
|
#include "graph.h"
|
|
|
|
|
|
// Initial size of lookup graph. It will double each time capacity is reached.
|
|
@@ -15,57 +16,32 @@ typedef enum KSetFlag {
|
|
|
LSUP_KS_CHECK_DUP = 1 << 1,
|
|
|
} KSetFlag;
|
|
|
|
|
|
-enum {
|
|
|
- HS_ERROR = -1,
|
|
|
- HS_PRESENT = 0,
|
|
|
- HS_EMPTY = 1,
|
|
|
- HS_TOMBSTONE = 2,
|
|
|
-};
|
|
|
-
|
|
|
/**
|
|
|
- * Index (identity) hashing function.
|
|
|
+ * Identity hashing function.
|
|
|
*
|
|
|
* Since the key is already a strong hash, reuse it for bucket allocation.
|
|
|
*/
|
|
|
-static inline khint64_t idx_key_hash_fn(LSUP_Key key)
|
|
|
-{ return key; }
|
|
|
+static inline uint64_t id_hash_fn(const void *key, ksize_t size, uint64_t seed)
|
|
|
+{ return *(uint64_t*)key; }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
- * Triple Key hash.
|
|
|
- *
|
|
|
- * Since triple keys are already hashes, interlace the first bytes of each
|
|
|
- * key element to preserve the individual identities.
|
|
|
+ * General XX64 hash. Strong (non-crypto) and extremely fast.
|
|
|
*/
|
|
|
-static inline khint64_t tkey_hash_fn(LSUP_TripleKey spok)
|
|
|
-{
|
|
|
- khint64_t rc = (khint64_t)XXH64(spok, sizeof(LSUP_TripleKey), SEED);
|
|
|
- TRACE("Key hash: 0x%lx\n", rc);
|
|
|
- return rc;
|
|
|
-}
|
|
|
+static inline uint64_t xx64_hash_fn(
|
|
|
+ const void *key, ksize_t size, uint64_t seed)
|
|
|
+{ return XXH64(key, size, seed); }
|
|
|
|
|
|
-static inline int tkey_eq_fn(LSUP_Key *a, LSUP_Key *b)
|
|
|
-{
|
|
|
- TRACE("a addr: %p", a);
|
|
|
- TRACE("b addr: %p", b);
|
|
|
- TRACE("Comparing a: {%lx, %lx, %lx}", a[0], a[1], a[2]);
|
|
|
- TRACE("Wtih b: {%lx, %lx, %lx}", b[0], b[1], b[2]);
|
|
|
- // Evaluate from the least to the most probable to match.
|
|
|
- return (
|
|
|
- a[2] == b[2] &&
|
|
|
- a[0] == b[0] &&
|
|
|
- a[1] == b[1]);
|
|
|
-}
|
|
|
|
|
|
-KHASH_INIT(Keys, LSUP_Key *, char, 0, tkey_hash_fn, tkey_eq_fn)
|
|
|
+static inline bool buffer_eq_fn(const void *a, const void *b, ksize_t size)
|
|
|
+{ return memcmp(a, b, size) == 0; }
|
|
|
|
|
|
-KHASH_INIT(
|
|
|
- Index, LSUP_Key, LSUP_Buffer, 1, idx_key_hash_fn, kh_int_hash_equal)
|
|
|
|
|
|
typedef struct Graph {
|
|
|
LSUP_store_type store_type; // In-memory or MDB-backed
|
|
|
LSUP_Term *uri; // Graph "name" (URI)
|
|
|
- khash_t(Keys) *keys;
|
|
|
- khash_t(Index) *idx; // Dictionary of keys to serialized terms
|
|
|
+ LSUP_HTable *keys;
|
|
|
+ LSUP_HTable *idx; // Dictionary of keys to serialized terms
|
|
|
} Graph;
|
|
|
|
|
|
/**
|
|
@@ -83,47 +59,67 @@ typedef bool (*LSUP_key_cmp_fn_t)(
|
|
|
const LSUP_TripleKey* spok, const LSUP_Key k1, const LSUP_Key k2);
|
|
|
|
|
|
|
|
|
-// Dummy callback for queries with all parameters unbound. Returns true.
|
|
|
+/**
|
|
|
+ * Dummy callback for queries with all parameters unbound. Returns true.
|
|
|
static bool lookup_none_cmp_fn(
|
|
|
const LSUP_TripleKey* spok, const LSUP_Key k1, const LSUP_Key k2)
|
|
|
{ return true; }
|
|
|
+*/
|
|
|
|
|
|
-// Keyset lookup for S key.
|
|
|
+/**
|
|
|
+ * Keyset lookup for S key.
|
|
|
+ */
|
|
|
static bool lookup_sk_cmp_fn(
|
|
|
const LSUP_TripleKey* spok, const LSUP_Key k1, const LSUP_Key k2)
|
|
|
{ return spok[0][0] == k1; }
|
|
|
|
|
|
-// Keyset lookup for P key.
|
|
|
+/**
|
|
|
+ * Keyset lookup for P key.
|
|
|
+ */
|
|
|
static bool lookup_pk_cmp_fn(
|
|
|
const LSUP_TripleKey* spok, const LSUP_Key k1, const LSUP_Key k2)
|
|
|
{ return spok[0][1] == k1; }
|
|
|
|
|
|
-// Keyset lookup for O key.
|
|
|
+/**
|
|
|
+ * Keyset lookup for O key.
|
|
|
+ */
|
|
|
static bool lookup_ok_cmp_fn(
|
|
|
const LSUP_TripleKey* spok, const LSUP_Key k1, const LSUP_Key k2)
|
|
|
{ return spok[0][2] == k1; }
|
|
|
|
|
|
-// Keyset lookup for S and P keys.
|
|
|
+/**
|
|
|
+ * Keyset lookup for S and P keys.
|
|
|
+ */
|
|
|
static bool lookup_skpk_cmp_fn(
|
|
|
const LSUP_TripleKey* spok, const LSUP_Key k1, const LSUP_Key k2)
|
|
|
{ return spok[0][0] == k1 && spok[0][1] == k2; }
|
|
|
|
|
|
-// Keyset lookup for S and O keys.
|
|
|
+/**
|
|
|
+ * Keyset lookup for S and O keys.
|
|
|
+ */
|
|
|
static bool lookup_skok_cmp_fn(
|
|
|
const LSUP_TripleKey* spok, const LSUP_Key k1, const LSUP_Key k2)
|
|
|
{ return spok[0][0] == k1 && spok[0][2] == k2; }
|
|
|
|
|
|
-// Keyset lookup for P and O keys.
|
|
|
+/**
|
|
|
+ * Keyset lookup for P and O keys.
|
|
|
+ */
|
|
|
static bool lookup_pkok_cmp_fn(
|
|
|
const LSUP_TripleKey* spok, const LSUP_Key k1, const LSUP_Key k2)
|
|
|
{ return spok[0][1] == k1 && spok[0][2] == k2; }
|
|
|
|
|
|
|
|
|
-/* * * Post-lookup callbacks * * */
|
|
|
+/* * * Post-lookup callback prototypes * * */
|
|
|
|
|
|
-int match_add_fn(LSUP_Graph *src, LSUP_Graph *dest, khiter_t cur, void *ctx);
|
|
|
+int match_add_fn(
|
|
|
+ LSUP_Graph *src, LSUP_Graph *dest, const LSUP_TripleKey *spok,
|
|
|
+ void *ctx);
|
|
|
+
|
|
|
+
|
|
|
+int match_rm_fn(
|
|
|
+ LSUP_Graph *src, LSUP_Graph *dest, const LSUP_TripleKey *spok,
|
|
|
+ void *ctx);
|
|
|
|
|
|
-int match_rm_fn(LSUP_Graph *src, LSUP_Graph *dest, khiter_t cur, void *ctx);
|
|
|
|
|
|
|
|
|
/* * * KEYSETS * * */
|
|
@@ -151,13 +147,14 @@ LSUP_graph_init(
|
|
|
gr->uri = LSUP_term_new(LSUP_TERM_URI, uri_str, NULL, NULL);
|
|
|
}
|
|
|
|
|
|
- gr->keys = kh_init_Keys();
|
|
|
- kh_resize_Keys(gr->keys, capacity);
|
|
|
+ gr->keys = LSUP_htable_new(
|
|
|
+ capacity, TRP_KLEN, 0, xx64_hash_fn, buffer_eq_fn, 0);
|
|
|
|
|
|
switch (store_type ) {
|
|
|
case LSUP_STORE_MEM:
|
|
|
- gr->idx = kh_init_Index();
|
|
|
- kh_resize_Index(gr->idx, capacity * IDX_SIZE_RATIO);
|
|
|
+ gr->idx = LSUP_htable_new(
|
|
|
+ capacity * IDX_SIZE_RATIO, sizeof(uint64_t), sizeof(uintptr_t),
|
|
|
+ xx64_hash_fn, buffer_eq_fn, 0);
|
|
|
break;
|
|
|
|
|
|
case LSUP_STORE_MDB:
|
|
@@ -196,7 +193,7 @@ static int graph_copy_contents(LSUP_Graph *src, LSUP_Graph *dest)
|
|
|
trp.o = NULL;
|
|
|
|
|
|
return LSUP_graph_match_callback(
|
|
|
- src, dest, &trp, match_add_fn, true, NULL);
|
|
|
+ src, dest, &trp, &match_add_fn, true, NULL);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -212,15 +209,15 @@ LSUP_graph_copy(LSUP_Graph *dest, LSUP_Graph *src)
|
|
|
int
|
|
|
LSUP_graph_resize(LSUP_Graph *gr, size_t size)
|
|
|
{
|
|
|
- kh_resize_Keys(gr->keys, size);
|
|
|
- kh_resize_Index(gr->idx, size * IDX_SIZE_RATIO);
|
|
|
+ LSUP_htable_resize(gr->keys, size);
|
|
|
+ LSUP_htable_resize(gr->idx, size * IDX_SIZE_RATIO);
|
|
|
|
|
|
return LSUP_OK;
|
|
|
}
|
|
|
|
|
|
|
|
|
size_t
|
|
|
-LSUP_graph_capacity(LSUP_Graph *gr) { return kh_end(gr->keys); }
|
|
|
+LSUP_graph_capacity(LSUP_Graph *gr) { return LSUP_htable_capacity(gr->keys); }
|
|
|
|
|
|
|
|
|
char *
|
|
@@ -228,13 +225,14 @@ LSUP_graph_uri(LSUP_Graph *gr) { return gr->uri->data; }
|
|
|
|
|
|
|
|
|
size_t
|
|
|
-LSUP_graph_size(LSUP_Graph *gr) { return kh_size(gr->keys); }
|
|
|
+LSUP_graph_size(LSUP_Graph *gr) { return LSUP_htable_size(gr->keys); }
|
|
|
|
|
|
|
|
|
int
|
|
|
LSUP_graph_add_triple(LSUP_Graph *gr, const LSUP_Triple *spo)
|
|
|
{
|
|
|
LSUP_SerTerm sspo[3];
|
|
|
+ LSUP_SerTerm *sterm;
|
|
|
|
|
|
LSUP_term_serialize(spo->s, sspo);
|
|
|
LSUP_term_serialize(spo->p, sspo + 1);
|
|
@@ -243,31 +241,26 @@ LSUP_graph_add_triple(LSUP_Graph *gr, const LSUP_Triple *spo)
|
|
|
LSUP_TripleKey spok = NULL_TRP;
|
|
|
|
|
|
// Add term to index.
|
|
|
- int status;
|
|
|
- khiter_t cur;
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
spok[i] = LSUP_sterm_to_key(sspo + i);
|
|
|
-
|
|
|
- cur = kh_put_Index(gr->idx, spok[i], &status);
|
|
|
- if (status == HS_EMPTY || status == HS_TOMBSTONE) {
|
|
|
- // If term is not indexed, store the struct in the index.
|
|
|
- kh_value(gr->idx, cur) = sspo[i];
|
|
|
+ TRACE("Indexing term key %lu\n", spok[i]);
|
|
|
+
|
|
|
+ // If term is already in the index, discard and free it.
|
|
|
+ if (LSUP_htable_get(gr->idx, spok + i, NULL) == LSUP_OK) {
|
|
|
+ CRITICAL(sterm = malloc(sizeof(LSUP_Buffer)));
|
|
|
+ //*sterm = sspo[i];
|
|
|
+ sterm = sspo + i;
|
|
|
+ LSUP_htable_put(gr->idx, spok + i, sterm);
|
|
|
} else {
|
|
|
- // If term is already in the index, discard and free it.
|
|
|
+ TRACE("%s", "Term is already indexed.");
|
|
|
LSUP_buffer_done(sspo + i);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Add triple.
|
|
|
TRACE("Inserting spok: {%lx, %lx, %lx}", spok[0], spok[1], spok[2]);
|
|
|
- cur = kh_put_Keys(gr->keys, spok, &status);
|
|
|
- //if (status == HS_EMPTY || status == HS_TOMBSTONE)
|
|
|
- // kh_key(gr->keys, cur) = spok;
|
|
|
- TRACE("cur: %d\n", cur);
|
|
|
- TRACE("Keyset size: %d\n", kh_size(gr->keys));
|
|
|
- TRACE("Insert status: %d\n", status);
|
|
|
-
|
|
|
- return status == HS_PRESENT ? LSUP_NOACTION : LSUP_OK;
|
|
|
+
|
|
|
+ return LSUP_htable_put(gr->keys, spok, NULL);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -294,13 +287,13 @@ LSUP_graph_add(LSUP_Graph *gr, const LSUP_Triple data[], size_t data_size)
|
|
|
bool
|
|
|
LSUP_graph_contains(const LSUP_Graph *gr, const LSUP_Triple *spo)
|
|
|
{
|
|
|
- LSUP_Key sk = LSUP_term_to_key(spo->s);
|
|
|
- LSUP_Key pk = LSUP_term_to_key(spo->p);
|
|
|
- LSUP_Key ok = LSUP_term_to_key(spo->o);
|
|
|
-
|
|
|
- LSUP_TripleKey spok = {sk, pk, ok};
|
|
|
+ LSUP_TripleKey spok = {
|
|
|
+ LSUP_term_to_key(spo->s),
|
|
|
+ LSUP_term_to_key(spo->p),
|
|
|
+ LSUP_term_to_key(spo->o),
|
|
|
+ };
|
|
|
|
|
|
- return kh_get_Keys(gr->keys, spok) != kh_end(gr->keys);
|
|
|
+ return LSUP_htable_get(gr->keys, spok, NULL) == LSUP_OK;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -308,25 +301,27 @@ int LSUP_graph_match_callback(
|
|
|
LSUP_Graph *gr, LSUP_Graph *res, const LSUP_Triple *spo,
|
|
|
keyset_match_fn_t callback_fn, bool match_cond, void *ctx)
|
|
|
{
|
|
|
- if (kh_size(gr->keys) == 0)
|
|
|
+ if (LSUP_htable_size(gr->keys) == 0)
|
|
|
return LSUP_NOACTION;
|
|
|
|
|
|
+ htsize_t cur = 0;
|
|
|
LSUP_Key k1, k2;
|
|
|
LSUP_key_cmp_fn_t cmp_fn;
|
|
|
+ LSUP_TripleKey i_spok;
|
|
|
|
|
|
- LSUP_Key sk = LSUP_term_to_key(spo->s);
|
|
|
- LSUP_Key pk = LSUP_term_to_key(spo->p);
|
|
|
- LSUP_Key ok = LSUP_term_to_key(spo->o);
|
|
|
-
|
|
|
- if (sk != NULL_KEY && pk != NULL_KEY && ok != NULL_KEY) {
|
|
|
- LSUP_TripleKey spok = {sk, pk, ok};
|
|
|
+ LSUP_TripleKey spok = {
|
|
|
+ LSUP_term_to_key(spo->s),
|
|
|
+ LSUP_term_to_key(spo->p),
|
|
|
+ LSUP_term_to_key(spo->o),
|
|
|
+ };
|
|
|
|
|
|
+ if (spok[0] != NULL_KEY && spok[1] != NULL_KEY && spok[2] != NULL_KEY) {
|
|
|
if (match_cond == true) {
|
|
|
// Shortcut for 3-term match—only if match_cond is true.
|
|
|
LSUP_graph_init(res, 1, NULL, LSUP_STORE_MEM);
|
|
|
- khint_t cur = kh_get_Keys(gr->keys, spok);
|
|
|
- if(cur != kh_end(gr->keys)) {
|
|
|
- callback_fn(gr, res, cur, ctx);
|
|
|
+ int rc = LSUP_htable_get(gr->keys, spok, NULL);
|
|
|
+ if(rc == LSUP_OK) {
|
|
|
+ callback_fn(gr, res, &spok, ctx);
|
|
|
return LSUP_OK;
|
|
|
} else {
|
|
|
return LSUP_NOACTION;
|
|
@@ -335,30 +330,29 @@ int LSUP_graph_match_callback(
|
|
|
// For negative condition (i.e. "apply this function to all triples
|
|
|
// except the matching one")
|
|
|
int rc = LSUP_NOACTION;
|
|
|
- for (khiter_t i = kh_begin(gr->keys); i != kh_end(gr->keys); i++) {
|
|
|
- LSUP_Key *cur = kh_key(gr->keys, i);
|
|
|
- if (
|
|
|
- cur[0] != spok[0] ||
|
|
|
- cur[1] != spok[1] ||
|
|
|
- cur[2] != spok[2]
|
|
|
- ) {
|
|
|
- callback_fn(gr, res, i, ctx);
|
|
|
- rc = LSUP_OK;
|
|
|
+ while (LSUP_htable_iter(
|
|
|
+ gr->keys, &cur, (void**)&i_spok, NULL) == LSUP_OK) {
|
|
|
+ if (LIKELY(
|
|
|
+ i_spok[2] != spok[2] ||
|
|
|
+ i_spok[0] != spok[0] ||
|
|
|
+ i_spok[1] != spok[1]
|
|
|
+ )) {
|
|
|
+ rc = callback_fn(gr, res, &i_spok, ctx);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
- } else if (sk != NULL_KEY) {
|
|
|
- k1 = sk;
|
|
|
+ } else if (spok[0] != NULL_KEY) {
|
|
|
+ k1 = spok[0];
|
|
|
|
|
|
- if (pk != NULL_KEY) { // s p ?
|
|
|
- k2 = pk;
|
|
|
+ if (spok[1] != NULL_KEY) { // s p ?
|
|
|
+ k2 = spok[1];
|
|
|
cmp_fn = lookup_skpk_cmp_fn;
|
|
|
|
|
|
- } else if (ok != NULL_KEY) { // s ? o
|
|
|
- k2 = ok;
|
|
|
+ } else if (spok[2] != NULL_KEY) { // s ? o
|
|
|
+ k2 = spok[2];
|
|
|
cmp_fn = lookup_skok_cmp_fn;
|
|
|
|
|
|
} else { // s ? ?
|
|
@@ -366,19 +360,19 @@ int LSUP_graph_match_callback(
|
|
|
|
|
|
}
|
|
|
|
|
|
- } else if (pk != NULL_KEY) {
|
|
|
- k1 = pk;
|
|
|
+ } else if (spok[1] != NULL_KEY) {
|
|
|
+ k1 = spok[1];
|
|
|
|
|
|
- if (ok != NULL_KEY) { // ? p o
|
|
|
- k2 = ok;
|
|
|
+ if (spok[2] != NULL_KEY) { // ? p o
|
|
|
+ k2 = spok[2];
|
|
|
cmp_fn = lookup_pkok_cmp_fn;
|
|
|
|
|
|
} else { // ? p ?
|
|
|
cmp_fn = lookup_pk_cmp_fn;
|
|
|
}
|
|
|
|
|
|
- } else if (ok != NULL_KEY) { // ? ? o
|
|
|
- k1 = ok;
|
|
|
+ } else if (spok[2] != NULL_KEY) { // ? ? o
|
|
|
+ k1 = spok[2];
|
|
|
cmp_fn = lookup_ok_cmp_fn;
|
|
|
|
|
|
} else {
|
|
@@ -386,10 +380,9 @@ int LSUP_graph_match_callback(
|
|
|
return LSUP_graph_copy(res, gr);
|
|
|
}
|
|
|
|
|
|
- for(khiter_t i = kh_begin(gr->keys); i != kh_end(gr->keys); i++) {
|
|
|
- LSUP_TripleKey *spok = (LSUP_TripleKey*)&kh_key(gr->keys, i);
|
|
|
- if (cmp_fn(spok, k1, k2) == match_cond)
|
|
|
- callback_fn(gr, res, i, ctx);
|
|
|
+ while (LSUP_htable_iter(gr->keys, &cur, (void**)&i_spok, NULL) == LSUP_OK) {
|
|
|
+ if (cmp_fn(&i_spok, k1, k2) == match_cond)
|
|
|
+ callback_fn(gr, res, &i_spok, ctx);
|
|
|
}
|
|
|
|
|
|
return LSUP_OK;
|
|
@@ -400,9 +393,7 @@ int LSUP_graph_lookup(LSUP_Graph *gr, LSUP_Graph *res, const LSUP_Triple *spo)
|
|
|
{
|
|
|
LSUP_graph_init(res, LOOKUP_GR_INIT_SIZE, NULL, LSUP_STORE_MEM);
|
|
|
|
|
|
- LSUP_graph_match_callback(gr, res, spo, &match_add_fn, true, NULL);
|
|
|
-
|
|
|
- return LSUP_OK;
|
|
|
+ return LSUP_graph_match_callback(gr, res, spo, &match_add_fn, true, NULL);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -416,19 +407,18 @@ int LSUP_graph_join(LSUP_Graph *gr1, LSUP_Graph *gr2, LSUP_Graph *res)
|
|
|
|
|
|
int LSUP_graph_subtract(LSUP_Graph *gr1, LSUP_Graph *gr2, LSUP_Graph *res)
|
|
|
{
|
|
|
- if (kh_size(gr2->keys) == 0) return LSUP_graph_copy(gr1, res);
|
|
|
+ if (LSUP_htable_size(gr2->keys) == 0) return LSUP_graph_copy(gr1, res);
|
|
|
|
|
|
LSUP_graph_init(res, LSUP_graph_capacity(gr1), NULL, LSUP_STORE_MEM);
|
|
|
|
|
|
- if (kh_size(gr1->keys) == 0) return LSUP_OK;
|
|
|
+ if (LSUP_htable_size(gr1->keys) == 0) return LSUP_OK;
|
|
|
|
|
|
- for(khiter_t i = kh_begin(gr1->keys); i != kh_end(gr1->keys); i++) {
|
|
|
- LSUP_TripleKey *spok = (LSUP_TripleKey*)&kh_key(gr1->keys, i);
|
|
|
+ htsize_t cur = 0;
|
|
|
+ LSUP_TripleKey spok;
|
|
|
|
|
|
- khiter_t cur = kh_get_Keys(gr2->keys, *spok);
|
|
|
- if (cur == kh_end(gr2->keys)) {
|
|
|
- match_add_fn(res, gr1, cur, NULL);
|
|
|
- }
|
|
|
+ while(LSUP_htable_iter(gr1->keys, &cur, (void**)&spok, NULL) == LSUP_OK) {
|
|
|
+ if (LSUP_htable_get(gr2->keys, (void**)&spok, NULL) == LSUP_NORESULT)
|
|
|
+ match_add_fn(res, gr1, &spok, NULL);
|
|
|
}
|
|
|
|
|
|
return LSUP_OK;
|
|
@@ -439,16 +429,15 @@ int LSUP_graph_intersect(LSUP_Graph *gr1, LSUP_Graph *gr2, LSUP_Graph *res)
|
|
|
{
|
|
|
LSUP_graph_init(res, LSUP_graph_capacity(gr1), NULL, LSUP_STORE_MEM);
|
|
|
|
|
|
- if (kh_size(gr1->keys) == 0 || kh_size(gr2->keys) == 0)
|
|
|
+ if (LSUP_htable_size(gr1->keys) == 0 || LSUP_htable_size(gr2->keys) == 0)
|
|
|
return LSUP_OK;
|
|
|
|
|
|
- for(khiter_t i = kh_begin(gr1->keys); i != kh_end(gr1->keys); i++) {
|
|
|
- LSUP_TripleKey *spok = (LSUP_TripleKey*)&kh_key(gr1->keys, i);
|
|
|
+ htsize_t cur = 0;
|
|
|
+ LSUP_TripleKey spok;
|
|
|
|
|
|
- khiter_t cur = kh_get_Keys(gr2->keys, *spok);
|
|
|
- if (cur != kh_end(gr2->keys)) {
|
|
|
- match_add_fn(res, gr1, cur, NULL);
|
|
|
- }
|
|
|
+ while(LSUP_htable_iter(gr1->keys, &cur, (void**)&spok, NULL) == LSUP_OK) {
|
|
|
+ if (LSUP_htable_get(gr2->keys, (void**)&spok, NULL) == LSUP_OK)
|
|
|
+ match_add_fn(res, gr1, &spok, NULL);
|
|
|
}
|
|
|
|
|
|
return LSUP_OK;
|
|
@@ -457,29 +446,26 @@ int LSUP_graph_intersect(LSUP_Graph *gr1, LSUP_Graph *gr2, LSUP_Graph *res)
|
|
|
|
|
|
int LSUP_graph_xor(LSUP_Graph *gr1, LSUP_Graph *gr2, LSUP_Graph *res)
|
|
|
{
|
|
|
- if (kh_size(gr1->keys) == 0) return LSUP_graph_copy(gr2, res);
|
|
|
- if (kh_size(gr2->keys) == 0) return LSUP_graph_copy(gr1, res);
|
|
|
+ if (LSUP_htable_size(gr1->keys) == 0) return LSUP_graph_copy(gr2, res);
|
|
|
+ if (LSUP_htable_size(gr2->keys) == 0) return LSUP_graph_copy(gr1, res);
|
|
|
|
|
|
LSUP_graph_init(
|
|
|
res, min(LSUP_graph_capacity(gr1), LSUP_graph_capacity(gr2)),
|
|
|
NULL, LSUP_STORE_MEM);
|
|
|
|
|
|
- for(khiter_t i = kh_begin(gr1->keys); i != kh_end(gr1->keys); i++) {
|
|
|
- LSUP_TripleKey *spok = (LSUP_TripleKey*)&kh_key(gr1->keys, i);
|
|
|
+ htsize_t cur = 0;
|
|
|
+ LSUP_TripleKey spok;
|
|
|
|
|
|
- khiter_t cur = kh_get_Keys(gr2->keys, *spok);
|
|
|
- if (cur == kh_end(gr2->keys)) {
|
|
|
- match_add_fn(res, gr1, cur, NULL);
|
|
|
- }
|
|
|
+ while(LSUP_htable_iter(gr1->keys, &cur, (void**)&spok, NULL) == LSUP_OK) {
|
|
|
+ if (LSUP_htable_get(gr2->keys, (void**)&spok, NULL) == LSUP_NORESULT)
|
|
|
+ match_add_fn(res, gr1, &spok, NULL);
|
|
|
}
|
|
|
|
|
|
- for(khiter_t i = kh_begin(gr2->keys); i != kh_end(gr2->keys); i++) {
|
|
|
- LSUP_TripleKey *spok = (LSUP_TripleKey*)&kh_key(gr2->keys, i);
|
|
|
+ cur = 0;
|
|
|
|
|
|
- khiter_t cur = kh_get_Keys(gr1->keys, *spok);
|
|
|
- if (cur == kh_end(gr1->keys)) {
|
|
|
- match_add_fn(res, gr2, cur, NULL);
|
|
|
- }
|
|
|
+ while(LSUP_htable_iter(gr2->keys, &cur, (void**)&spok, NULL) == LSUP_OK) {
|
|
|
+ if (LSUP_htable_get(gr1->keys, (void**)&spok, NULL) == LSUP_NORESULT)
|
|
|
+ match_add_fn(res, gr2, &spok, NULL);
|
|
|
}
|
|
|
|
|
|
return LSUP_OK;
|
|
@@ -493,20 +479,19 @@ LSUP_graph_free(LSUP_Graph *gr)
|
|
|
LSUP_term_free(gr->uri);
|
|
|
|
|
|
// Free up triples.
|
|
|
- /*
|
|
|
- for(khiter_t i = kh_begin(gr->keys); i != kh_end(gr->keys); ++i) {
|
|
|
- if(kh_exist(gr->keys, i))
|
|
|
- free(&kh_value(gr->keys, i));
|
|
|
- }
|
|
|
- */
|
|
|
- kh_destroy_Keys(gr->keys);
|
|
|
+ LSUP_htable_free(gr->keys);
|
|
|
|
|
|
// Free up index entries and index.
|
|
|
- for(khiter_t i = kh_begin(gr->idx); i != kh_end(gr->idx); ++i) {
|
|
|
- if(kh_exist(gr->idx, i))
|
|
|
- LSUP_buffer_done(&kh_value(gr->idx, i));
|
|
|
+ htsize_t cur = 0;
|
|
|
+ LSUP_TripleKey spok;
|
|
|
+ LSUP_Buffer *sterm;
|
|
|
+ while(LSUP_htable_iter(
|
|
|
+ gr->idx, &cur, (void**)&spok, (void**)&sterm) == LSUP_OK) {
|
|
|
+ TRACE("Freeing indexed term buffer #%d at %p", cur, sterm);
|
|
|
+ LSUP_buffer_done(sterm);
|
|
|
}
|
|
|
- kh_destroy_Index(gr->idx);
|
|
|
+
|
|
|
+ LSUP_htable_free(gr->idx);
|
|
|
|
|
|
free(gr);
|
|
|
}
|
|
@@ -522,35 +507,31 @@ LSUP_graph_free(LSUP_Graph *gr)
|
|
|
*
|
|
|
* The source graph cursor must be set to the triple to be copied.
|
|
|
*/
|
|
|
-int match_add_fn(LSUP_Graph *src, LSUP_Graph *dest, khiter_t cur, void *ctx)
|
|
|
+int match_add_fn(
|
|
|
+ LSUP_Graph *src, LSUP_Graph *dest, const LSUP_TripleKey *spok,
|
|
|
+ void *ctx)
|
|
|
{
|
|
|
- LSUP_TripleKey *spok = (LSUP_TripleKey*)&kh_key(src->keys, cur);
|
|
|
// Add term to index.
|
|
|
- int status;
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
- khiter_t dest_cur = kh_put_Index(dest->idx, *spok[i], &status);
|
|
|
- if (
|
|
|
- kh_exist(src->idx, *spok[i] &&
|
|
|
- (status == HS_EMPTY || status == HS_TOMBSTONE))) {
|
|
|
- // If term is not indexed, store the struct in the index.
|
|
|
- LSUP_buffer_copy(
|
|
|
- &kh_value(dest->idx, dest_cur), &kh_value(src->idx, cur));
|
|
|
+ // Index terms if not yet presents in destination.
|
|
|
+ void *src_val, *dest_val;
|
|
|
+
|
|
|
+ if(LSUP_htable_get(src->idx, *spok + i, &src_val) == LSUP_OK) {
|
|
|
+ CRITICAL(dest_val = malloc(sizeof(LSUP_Buffer)));
|
|
|
+ LSUP_buffer_copy(dest_val, src_val);
|
|
|
+ LSUP_htable_put(dest->idx, *spok + i, dest_val);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Add triple.
|
|
|
- kh_put_Keys(src->keys, *spok, &status);
|
|
|
-
|
|
|
- return LSUP_OK;
|
|
|
+ return LSUP_htable_put(dest->keys, spok, NULL);
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Callback for removing a matched triple.
|
|
|
*/
|
|
|
-int match_rm_fn(LSUP_Graph *src, LSUP_Graph *dest, khint_t cur, void *ctx)
|
|
|
-{
|
|
|
- kh_del_Keys(dest->keys, cur);
|
|
|
-
|
|
|
- return LSUP_OK;
|
|
|
-}
|
|
|
+int match_rm_fn(
|
|
|
+ LSUP_Graph *src, LSUP_Graph *dest, const LSUP_TripleKey *spok,
|
|
|
+ void *ctx)
|
|
|
+{ return LSUP_htable_del(dest->keys, spok); }
|