|
@@ -1,10 +1,14 @@
|
|
|
-#include "khash.h"
|
|
|
-
|
|
|
#include "graph.h"
|
|
|
|
|
|
// Initial size of lookup graph. It will double each time capacity is reached.
|
|
|
#define LOOKUP_GR_INIT_SIZE 64
|
|
|
|
|
|
+// Assume VERY coarsly that the number of unique terms will be in general
|
|
|
+// 1.7 times the number of triples. This is conservative to maintain load
|
|
|
+// factor low.
|
|
|
+#define IDX_SIZE_RATIO 1.7
|
|
|
+
|
|
|
+
|
|
|
typedef enum KSetFlag {
|
|
|
LSUP_KS_NONE = 0,
|
|
|
LSUP_KS_CHECK_CAP = 1 << 0,
|
|
@@ -18,36 +22,52 @@ enum {
|
|
|
HS_TOMBSTONE = 2,
|
|
|
};
|
|
|
|
|
|
-typedef struct Keyset {
|
|
|
- LSUP_TripleKey *data;
|
|
|
- size_t capacity;
|
|
|
- size_t cur;
|
|
|
- size_t free_i;
|
|
|
-} Keyset;
|
|
|
-
|
|
|
/**
|
|
|
* Index (identity) hashing function.
|
|
|
*
|
|
|
* Since the key is already a strong hash, reuse it for bucket allocation.
|
|
|
*/
|
|
|
-static inline LSUP_Key idx_key_hash_fn(LSUP_Key key)
|
|
|
+static inline khint64_t idx_key_hash_fn(LSUP_Key key)
|
|
|
{ return key; }
|
|
|
|
|
|
+/**
|
|
|
+ * Triple Key hash.
|
|
|
+ *
|
|
|
+ * Since triple keys are already hashes, interlace the first bytes of each
|
|
|
+ * key element to preserve the individual identities.
|
|
|
+ */
|
|
|
+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 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)
|
|
|
+
|
|
|
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
|
|
|
- Keyset *keys; // Key arrangements in triples
|
|
|
LSUP_Term *uri; // Graph "name" (URI)
|
|
|
+ khash_t(Keys) *keys;
|
|
|
khash_t(Index) *idx; // Dictionary of keys to serialized terms
|
|
|
} Graph;
|
|
|
|
|
|
-
|
|
|
-// "NULL" triple, a value that is never user-provided. Used to fill deleted
|
|
|
-// triples in a keyset.
|
|
|
-LSUP_TripleKey NULL_TRP = {NULL_KEY, NULL_KEY, NULL_KEY};
|
|
|
-
|
|
|
/**
|
|
|
* Extern inline functions.
|
|
|
*/
|
|
@@ -63,6 +83,11 @@ 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.
|
|
|
+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.
|
|
|
static bool lookup_sk_cmp_fn(
|
|
|
const LSUP_TripleKey* spok, const LSUP_Key k1, const LSUP_Key k2)
|
|
@@ -93,17 +118,12 @@ 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; }
|
|
|
|
|
|
-// 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; }
|
|
|
-
|
|
|
|
|
|
/* * * Post-lookup callbacks * * */
|
|
|
|
|
|
-int match_add_fn(LSUP_Graph *src, LSUP_Graph *dest, void *ctx);
|
|
|
+int match_add_fn(LSUP_Graph *src, LSUP_Graph *dest, khiter_t cur, void *ctx);
|
|
|
|
|
|
-int match_rm_fn(LSUP_Graph *src, LSUP_Graph *dest, void *ctx);
|
|
|
+int match_rm_fn(LSUP_Graph *src, LSUP_Graph *dest, khiter_t cur, void *ctx);
|
|
|
|
|
|
|
|
|
/* * * KEYSETS * * */
|
|
@@ -111,153 +131,9 @@ int match_rm_fn(LSUP_Graph *src, LSUP_Graph *dest, void *ctx);
|
|
|
static inline bool is_null_trp(const LSUP_TripleKey *trp)
|
|
|
{
|
|
|
return (
|
|
|
- (*trp)[0] == NULL_TRP[0]
|
|
|
- && (*trp)[1] == NULL_TRP[1]
|
|
|
- && (*trp)[2] == NULL_TRP[2]);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int keyset_init(Keyset *ks, size_t capacity)
|
|
|
-{
|
|
|
- CRITICAL (ks->data = malloc(capacity * TRP_KLEN));
|
|
|
- ks->capacity = capacity;
|
|
|
- ks->cur = 0;
|
|
|
- ks->free_i = 0;
|
|
|
-
|
|
|
- return LSUP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/**
|
|
|
- * Move cursor to a non-empty position.
|
|
|
- */
|
|
|
-static inline bool keyset_seek(Keyset* ks, size_t idx)
|
|
|
-{
|
|
|
- if (idx >= ks->free_i) return false;
|
|
|
-
|
|
|
- ks->cur = idx;
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static inline LSUP_TripleKey *keyset_peek(Keyset *ks) {
|
|
|
- return ks->data + ks->cur;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static inline bool keyset_contains(
|
|
|
- const Keyset *ks, const LSUP_TripleKey *val) {
|
|
|
-
|
|
|
- for (size_t i = 0; i < ks->free_i; i++) {
|
|
|
- // scan from the least to the most probable to match.
|
|
|
- if (
|
|
|
- (*val)[2] == ks->data[i][2] &&
|
|
|
- (*val)[0] == ks->data[i][0] &&
|
|
|
- (*val)[1] == ks->data[i][1]) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static inline bool keyset_next(Keyset *ks)
|
|
|
-{
|
|
|
- if (ks->free_i > 0 && ks->cur < ks->free_i - 1) {
|
|
|
- ks->cur ++;
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int keyset_resize(Keyset *ks, size_t new_size) {
|
|
|
- new_size = max(new_size, ks->free_i);
|
|
|
-
|
|
|
- CRITICAL (ks->data = realloc(
|
|
|
- ks->data, max(new_size, ks->free_i) * TRP_KLEN))
|
|
|
-
|
|
|
- return LSUP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int keyset_add(
|
|
|
- Keyset *ks, const LSUP_TripleKey *val, const KSetFlag flags)
|
|
|
-{
|
|
|
- if((flags & LSUP_KS_CHECK_DUP) && keyset_contains(ks, val))
|
|
|
- return LSUP_NOACTION;
|
|
|
-
|
|
|
- if((flags & LSUP_KS_CHECK_CAP) && ks->free_i >= ks->capacity)
|
|
|
- keyset_resize(ks, ks->capacity * 2);
|
|
|
-
|
|
|
- memcpy(ks->data + ks->free_i, val, TRP_KLEN);
|
|
|
-
|
|
|
- ks->cur = ks->free_i;
|
|
|
- ks->free_i ++;
|
|
|
-
|
|
|
- return LSUP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int keyset_remove(Keyset *ks, const LSUP_TripleKey *val) {
|
|
|
-
|
|
|
- keyset_seek(ks, 0);
|
|
|
-
|
|
|
- while (keyset_next(ks)) {
|
|
|
- if (memcmp(val, ks->data + ks->cur, TRP_KLEN) == 0) {
|
|
|
- memcpy(ks->data + ks->cur, &NULL_TRP, TRP_KLEN);
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return LSUP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int keyset_copy(const Keyset *src, Keyset *dest) {
|
|
|
-
|
|
|
- keyset_init(dest, src->capacity);
|
|
|
-
|
|
|
- memcpy(dest->data, src->data, src->capacity * TRP_KLEN);
|
|
|
-
|
|
|
- keyset_seek(dest, 0);
|
|
|
- dest->free_i = src->free_i;
|
|
|
-
|
|
|
- return LSUP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int keyset_sparse_copy(Keyset *src, Keyset *dest) {
|
|
|
-
|
|
|
- keyset_init(dest, src->capacity);
|
|
|
-
|
|
|
- if (keyset_seek(src, 0)) {
|
|
|
- do {
|
|
|
- if (LIKELY(memcmp(
|
|
|
- keyset_peek(src),
|
|
|
- &NULL_TRP, TRP_KLEN) != 0)) {
|
|
|
- keyset_add(dest, keyset_peek(src), 0);
|
|
|
- }
|
|
|
- } while (keyset_next(src));
|
|
|
-
|
|
|
- keyset_seek(dest, 0);
|
|
|
- }
|
|
|
-
|
|
|
- return LSUP_OK;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static void keyset_free(Keyset *ks)
|
|
|
-{
|
|
|
- if(LIKELY(ks != NULL)) {
|
|
|
- if(LIKELY(ks->data != NULL))
|
|
|
- free(ks->data);
|
|
|
-
|
|
|
- free(ks);
|
|
|
- }
|
|
|
+ *trp[0] == NULL_KEY &&
|
|
|
+ *trp[1] == NULL_KEY &&
|
|
|
+ *trp[2] == NULL_KEY);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -275,13 +151,13 @@ LSUP_graph_init(
|
|
|
gr->uri = LSUP_term_new(LSUP_TERM_URI, uri_str, NULL, NULL);
|
|
|
}
|
|
|
|
|
|
- gr->keys = malloc(sizeof(Keyset));
|
|
|
- keyset_init(gr->keys, capacity);
|
|
|
+ gr->keys = kh_init_Keys();
|
|
|
+ kh_resize_Keys(gr->keys, capacity);
|
|
|
|
|
|
switch (store_type ) {
|
|
|
case LSUP_STORE_MEM:
|
|
|
-
|
|
|
gr->idx = kh_init_Index();
|
|
|
+ kh_resize_Index(gr->idx, capacity * IDX_SIZE_RATIO);
|
|
|
break;
|
|
|
|
|
|
case LSUP_STORE_MDB:
|
|
@@ -327,14 +203,24 @@ static int graph_copy_contents(LSUP_Graph *src, LSUP_Graph *dest)
|
|
|
int
|
|
|
LSUP_graph_copy(LSUP_Graph *dest, LSUP_Graph *src)
|
|
|
{
|
|
|
- LSUP_graph_init(dest, src->keys->capacity, NULL, src->store_type);
|
|
|
+ LSUP_graph_init(dest, LSUP_graph_size(src), NULL, src->store_type);
|
|
|
|
|
|
return graph_copy_contents(src, dest);
|
|
|
}
|
|
|
|
|
|
|
|
|
+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);
|
|
|
+
|
|
|
+ return LSUP_OK;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
size_t
|
|
|
-LSUP_graph_capacity(LSUP_Graph *gr) { return gr->keys->capacity; }
|
|
|
+LSUP_graph_capacity(LSUP_Graph *gr) { return kh_end(gr->keys); }
|
|
|
|
|
|
|
|
|
char *
|
|
@@ -342,7 +228,7 @@ LSUP_graph_uri(LSUP_Graph *gr) { return gr->uri->data; }
|
|
|
|
|
|
|
|
|
size_t
|
|
|
-LSUP_graph_size(LSUP_Graph *gr) { return gr->keys->free_i; }
|
|
|
+LSUP_graph_size(LSUP_Graph *gr) { return kh_size(gr->keys); }
|
|
|
|
|
|
|
|
|
int
|
|
@@ -354,7 +240,7 @@ LSUP_graph_add_triple(LSUP_Graph *gr, const LSUP_Triple *spo)
|
|
|
LSUP_term_serialize(spo->p, sspo + 1);
|
|
|
LSUP_term_serialize(spo->o, sspo + 2);
|
|
|
|
|
|
- LSUP_TripleKey spok = {0, 0, 0};
|
|
|
+ LSUP_TripleKey spok = NULL_TRP;
|
|
|
|
|
|
// Add term to index.
|
|
|
int status;
|
|
@@ -373,9 +259,15 @@ LSUP_graph_add_triple(LSUP_Graph *gr, const LSUP_Triple *spo)
|
|
|
}
|
|
|
|
|
|
// Add triple.
|
|
|
- keyset_add(gr->keys, &spok, LSUP_KS_CHECK_DUP);
|
|
|
-
|
|
|
- return LSUP_OK;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -385,14 +277,17 @@ LSUP_graph_add(LSUP_Graph *gr, const LSUP_Triple data[], size_t data_size)
|
|
|
// TODO Decouple this and build interface for memory and MDB integration.
|
|
|
|
|
|
// Resize all at once if needed.
|
|
|
- if (gr->keys->capacity < gr->keys->free_i + data_size)
|
|
|
- keyset_resize(gr->keys, gr->keys->free_i + data_size);
|
|
|
+ if (LSUP_graph_capacity(gr) < LSUP_graph_size(gr) + data_size)
|
|
|
+ LSUP_graph_resize(gr, LSUP_graph_size(gr) + data_size);
|
|
|
|
|
|
+ int rc = LSUP_NOACTION;
|
|
|
for (size_t i = 0; i < data_size; i++) {
|
|
|
- LSUP_graph_add_triple(gr, data + i);
|
|
|
+ TRACE("Inserting triple #%lu\n", i);
|
|
|
+ if (LIKELY(LSUP_graph_add_triple(gr, data + i) == LSUP_OK))
|
|
|
+ rc = LSUP_OK;
|
|
|
}
|
|
|
|
|
|
- return LSUP_OK;
|
|
|
+ return rc;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -405,7 +300,7 @@ LSUP_graph_contains(const LSUP_Graph *gr, const LSUP_Triple *spo)
|
|
|
|
|
|
LSUP_TripleKey spok = {sk, pk, ok};
|
|
|
|
|
|
- return keyset_contains(gr->keys, &spok);
|
|
|
+ return kh_get_Keys(gr->keys, spok) != kh_end(gr->keys);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -413,7 +308,7 @@ 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 (!keyset_seek(gr->keys, 0))
|
|
|
+ if (kh_size(gr->keys) == 0)
|
|
|
return LSUP_NOACTION;
|
|
|
|
|
|
LSUP_Key k1, k2;
|
|
@@ -428,28 +323,29 @@ int LSUP_graph_match_callback(
|
|
|
|
|
|
if (match_cond == true) {
|
|
|
// Shortcut for 3-term match—only if match_cond is true.
|
|
|
- keyset_init(res->keys, 1);
|
|
|
- if(keyset_contains(gr->keys, &spok)) {
|
|
|
- callback_fn(gr, res, ctx);
|
|
|
+ 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);
|
|
|
return LSUP_OK;
|
|
|
} else {
|
|
|
return LSUP_NOACTION;
|
|
|
}
|
|
|
} else {
|
|
|
// For negative condition (i.e. "apply this function to all triples
|
|
|
- // except the matching one"), the whole set is scanned.
|
|
|
- const LSUP_TripleKey *cur = keyset_peek(gr->keys);
|
|
|
+ // except the matching one")
|
|
|
int rc = LSUP_NOACTION;
|
|
|
- do {
|
|
|
+ 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]
|
|
|
+ cur[0] != spok[0] ||
|
|
|
+ cur[1] != spok[1] ||
|
|
|
+ cur[2] != spok[2]
|
|
|
) {
|
|
|
- callback_fn(gr, res, ctx);
|
|
|
+ callback_fn(gr, res, i, ctx);
|
|
|
rc = LSUP_OK;
|
|
|
}
|
|
|
- } while (keyset_next(gr->keys));
|
|
|
+ }
|
|
|
|
|
|
return rc;
|
|
|
}
|
|
@@ -490,11 +386,11 @@ int LSUP_graph_match_callback(
|
|
|
return LSUP_graph_copy(res, gr);
|
|
|
}
|
|
|
|
|
|
- do {
|
|
|
- if (cmp_fn(keyset_peek(gr->keys), k1, k2) == match_cond) {
|
|
|
- callback_fn(gr, res, ctx);
|
|
|
- }
|
|
|
- } while (keyset_next(gr->keys));
|
|
|
+ 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);
|
|
|
+ }
|
|
|
|
|
|
return LSUP_OK;
|
|
|
}
|
|
@@ -520,17 +416,20 @@ 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)
|
|
|
{
|
|
|
- LSUP_graph_init(res, gr1->keys->capacity, NULL, LSUP_STORE_MEM);
|
|
|
+ if (kh_size(gr2->keys) == 0) return LSUP_graph_copy(gr1, res);
|
|
|
|
|
|
- if (!keyset_seek(gr1->keys, 0))
|
|
|
- return LSUP_OK;
|
|
|
+ LSUP_graph_init(res, LSUP_graph_capacity(gr1), NULL, LSUP_STORE_MEM);
|
|
|
+
|
|
|
+ if (kh_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);
|
|
|
|
|
|
- do {
|
|
|
- const LSUP_TripleKey *spok = keyset_peek(gr1->keys);
|
|
|
- if (!is_null_trp(spok) && !keyset_contains(gr2->keys, spok)) {
|
|
|
- match_add_fn(res, gr1, NULL);
|
|
|
+ khiter_t cur = kh_get_Keys(gr2->keys, *spok);
|
|
|
+ if (cur == kh_end(gr2->keys)) {
|
|
|
+ match_add_fn(res, gr1, cur, NULL);
|
|
|
}
|
|
|
- } while (keyset_next(gr1->keys));
|
|
|
+ }
|
|
|
|
|
|
return LSUP_OK;
|
|
|
}
|
|
@@ -538,17 +437,19 @@ int LSUP_graph_subtract(LSUP_Graph *gr1, LSUP_Graph *gr2, LSUP_Graph *res)
|
|
|
|
|
|
int LSUP_graph_intersect(LSUP_Graph *gr1, LSUP_Graph *gr2, LSUP_Graph *res)
|
|
|
{
|
|
|
- LSUP_graph_init(res, gr1->keys->capacity, NULL, LSUP_STORE_MEM);
|
|
|
+ LSUP_graph_init(res, LSUP_graph_capacity(gr1), NULL, LSUP_STORE_MEM);
|
|
|
|
|
|
- if (!keyset_seek(gr1->keys, 0) || gr2->keys->free_i == 0)
|
|
|
+ if (kh_size(gr1->keys) == 0 || kh_size(gr2->keys) == 0)
|
|
|
return LSUP_OK;
|
|
|
|
|
|
- do {
|
|
|
- const LSUP_TripleKey *spok = keyset_peek(gr1->keys);
|
|
|
- if (!is_null_trp(spok) && keyset_contains(gr2->keys, spok)) {
|
|
|
- match_add_fn(res, gr1, NULL);
|
|
|
+ for(khiter_t i = kh_begin(gr1->keys); i != kh_end(gr1->keys); i++) {
|
|
|
+ LSUP_TripleKey *spok = (LSUP_TripleKey*)&kh_key(gr1->keys, i);
|
|
|
+
|
|
|
+ khiter_t cur = kh_get_Keys(gr2->keys, *spok);
|
|
|
+ if (cur != kh_end(gr2->keys)) {
|
|
|
+ match_add_fn(res, gr1, cur, NULL);
|
|
|
}
|
|
|
- } while (keyset_next(gr1->keys));
|
|
|
+ }
|
|
|
|
|
|
return LSUP_OK;
|
|
|
}
|
|
@@ -556,27 +457,30 @@ 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 (!keyset_seek(gr1->keys, 0))
|
|
|
- return LSUP_graph_copy(res, gr2);
|
|
|
+ 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 (!keyset_seek(gr2->keys, 0))
|
|
|
- return LSUP_graph_copy(res, gr1);
|
|
|
+ LSUP_graph_init(
|
|
|
+ res, min(LSUP_graph_capacity(gr1), LSUP_graph_capacity(gr2)),
|
|
|
+ NULL, LSUP_STORE_MEM);
|
|
|
|
|
|
- LSUP_graph_init(res, gr1->keys->capacity, 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);
|
|
|
|
|
|
- do {
|
|
|
- const LSUP_TripleKey *spok = keyset_peek(gr1->keys);
|
|
|
- if (!is_null_trp(spok) && !keyset_contains(gr2->keys, spok)) {
|
|
|
- match_add_fn(gr1, res, NULL);
|
|
|
+ khiter_t cur = kh_get_Keys(gr2->keys, *spok);
|
|
|
+ if (cur == kh_end(gr2->keys)) {
|
|
|
+ match_add_fn(res, gr1, cur, NULL);
|
|
|
}
|
|
|
- } while (keyset_next(gr1->keys));
|
|
|
+ }
|
|
|
|
|
|
- do {
|
|
|
- const LSUP_TripleKey *spok = keyset_peek(gr2->keys);
|
|
|
- if (!is_null_trp(spok) && !keyset_contains(gr1->keys, spok)) {
|
|
|
- match_add_fn(gr2, res, 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);
|
|
|
+
|
|
|
+ khiter_t cur = kh_get_Keys(gr1->keys, *spok);
|
|
|
+ if (cur == kh_end(gr1->keys)) {
|
|
|
+ match_add_fn(res, gr2, cur, NULL);
|
|
|
}
|
|
|
- } while (keyset_next(gr2->keys));
|
|
|
+ }
|
|
|
|
|
|
return LSUP_OK;
|
|
|
}
|
|
@@ -587,7 +491,15 @@ LSUP_graph_free(LSUP_Graph *gr)
|
|
|
{
|
|
|
if (LIKELY(gr != NULL)) {
|
|
|
LSUP_term_free(gr->uri);
|
|
|
- keyset_free(gr->keys);
|
|
|
+
|
|
|
+ // 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);
|
|
|
|
|
|
// Free up index entries and index.
|
|
|
for(khiter_t i = kh_begin(gr->idx); i != kh_end(gr->idx); ++i) {
|
|
@@ -610,30 +522,24 @@ 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, void *ctx)
|
|
|
+int match_add_fn(LSUP_Graph *src, LSUP_Graph *dest, khiter_t cur, void *ctx)
|
|
|
{
|
|
|
- if(LSUP_graph_size(src) >= LSUP_graph_capacity(src))
|
|
|
- keyset_resize(dest->keys, dest->keys->capacity * 2);
|
|
|
-
|
|
|
- LSUP_TripleKey *spok = keyset_peek(src->keys);
|
|
|
-
|
|
|
- memcpy(dest->keys->data + dest->keys->free_i, spok, TRP_KLEN);
|
|
|
-
|
|
|
+ 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 cur = kh_put_Index(dest->idx, *spok[i], &status);
|
|
|
+ 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, cur), &kh_value(src->idx, cur));
|
|
|
+ &kh_value(dest->idx, dest_cur), &kh_value(src->idx, cur));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- dest->keys->cur = dest->keys->free_i;
|
|
|
- dest->keys->free_i ++;
|
|
|
+ // Add triple.
|
|
|
+ kh_put_Keys(src->keys, *spok, &status);
|
|
|
|
|
|
return LSUP_OK;
|
|
|
}
|
|
@@ -642,9 +548,9 @@ int match_add_fn(LSUP_Graph *src, LSUP_Graph *dest, void *ctx)
|
|
|
/**
|
|
|
* Callback for removing a matched triple.
|
|
|
*/
|
|
|
-int match_rm_fn(LSUP_Graph *src, LSUP_Graph *dest, void *ctx)
|
|
|
+int match_rm_fn(LSUP_Graph *src, LSUP_Graph *dest, khint_t cur, void *ctx)
|
|
|
{
|
|
|
- memcpy(keyset_peek(src->keys), &NULL_TRP, TRP_KLEN);
|
|
|
+ kh_del_Keys(dest->keys, cur);
|
|
|
|
|
|
return LSUP_OK;
|
|
|
}
|