浏览代码

WIP Some3 function name changing; start quad testing.

Stefano Cossu 4 年之前
父节点
当前提交
f5816f19d0
共有 3 个文件被更改,包括 155 次插入35 次删除
  1. 21 3
      include/store_mdb.h
  2. 32 26
      src/store_mdb.c
  3. 102 6
      test/test_store_mdb.c

+ 21 - 3
include/store_mdb.h

@@ -28,7 +28,7 @@
 typedef char DbLabel[8];
 typedef struct MDBStore LSUP_MDBStore;
 
-typedef LSUP_rc (*mdb_store_match_fn_t)(const LSUP_TripleKey spok, void *ctx);
+typedef LSUP_rc (*mdb_store_match_fn_t)(const LSUP_TripleKey spok, void *data);
 
 // TODO Introduce compile-time LSUP_BIG_STORE option to define two store
 // options: false: 64-bit hashes, uint32 keys, max 4G entries; true:
@@ -138,7 +138,7 @@ LSUP_rc LSUP_store_add(
  *  triple keys. It may be NULL if the function is called only to count the
  *  matches; which in most cases will be much faster.
  *
- * @param ctx[in] Arbitrary data to be used in the callback function.
+ * @param data[in,out] Arbitrary data to be used in the callback function.
  *
  * @return LSUP_OK if entries were found, LSUP_NORESULT if none were found; if
  *  a callback was applied, and an error (<0) code was returned in any of the
@@ -146,7 +146,25 @@ LSUP_rc LSUP_store_add(
  */
 LSUP_rc LSUP_store_lookup(
         LSUP_MDBStore *store, LSUP_SerTerm *sspoc[], size_t *ct,
-        mdb_store_match_fn_t callback_fn, void *ctx);
+        mdb_store_match_fn_t callback_fn, void *data);
 
 
+
+/** @brief Contexts that a triple key appears in.
+ *
+ * This function is most conveniently used by a callback to #LSUP_store_lookup
+ * because it handles triple keys.
+ *
+ * @param store[in] The store to be queried.
+ *
+ * @param spok[in] Triple key to look up.
+ *
+ * @param ck[out] Pointer to an array of contexts. Memory is allocated by this
+ * function and must be freed by the caller.
+ *
+ * @param ct[out] Number of contexts found.
+ */
+LSUP_rc LSUP_store_triple_contexts(
+        LSUP_MDBStore *store, LSUP_Key spok[], LSUP_Key **ck, size_t *ct);
+
 #endif

+ 32 - 26
src/store_mdb.c

@@ -50,15 +50,15 @@ struct MDBStore {
 
 /** @brief Common match callback arguments.
  */
-struct MatchArgs {
-    LSUP_Key luks[2];
-    uint8_t idx0, idx1;
-    size_t *ct;
-    mdb_store_match_fn_t callback_fn;
-    void *ctx;
-};
-
-static LSUP_Buffer *default_ctx = NULL; // Default context URI for quad store.
+typedef struct LookupArgs {
+    LSUP_Key luks[2];               // 0÷2 lookup keys.
+    uint8_t idx0, idx1;             // Which term in the triple the lookup keys
+                                    // represent, respectively.
+    LSUP_Key ck;                    // Context key to restrict results to.
+    size_t *ct;                     // Result count.
+    mdb_store_match_fn_t callback_fn; // Callback function to apply to matches.
+    void *data;                     // Arbitrary data usable by the callback.
+} LookupArgs;
 
 /*
  * TODO At the moment up to 64-bit key / hash values are allowed. Later on,
@@ -181,13 +181,13 @@ static int index_triple(
         LSUP_TripleKey spok, LSUP_Key ck);
 
 inline static LSUP_rc lookup_0bound(
-        struct MDBStore *store, struct MatchArgs *args);
+        struct MDBStore *store, LookupArgs *args);
 inline static LSUP_rc lookup_1bound(
-        struct MDBStore *store, struct MatchArgs *args);
+        struct MDBStore *store, LookupArgs *args);
 inline static LSUP_rc lookup_2bound(
-        struct MDBStore *store, struct MatchArgs *args);
+        struct MDBStore *store, LookupArgs *args);
 inline static LSUP_rc lookup_3bound(
-        struct MDBStore *store, struct MatchArgs *args);
+        struct MDBStore *store, LookupArgs *args);
 /* TODO
 inline static int check_txn_open(MDB_txn *txn, bool write);
 */
@@ -505,7 +505,7 @@ LSUP_store_key_to_sterm(
 LSUP_rc
 LSUP_store_lookup(
         LSUP_MDBStore *store, LSUP_SerTerm *sspoc[], size_t *ct,
-        mdb_store_match_fn_t callback_fn, void *ctx)
+        mdb_store_match_fn_t callback_fn, void *data)
 {
     LSUP_TripleKey spok = {
         LSUP_sterm_to_key(sspoc[0]),
@@ -513,14 +513,20 @@ LSUP_store_lookup(
         LSUP_sterm_to_key(sspoc[2]),
     };
 
-    LSUP_Key ck = store->default_ctx ? LSUP_sterm_to_key(sspoc[3]) : NULL_KEY;
+    LookupArgs args_s;
+    LookupArgs *args = &args_s;
+
+    if (store->default_ctx) {
+        if (args->ck = LSUP_sterm_to_key(sspoc[3]) == NULL_KEY)
+            args->ck = LSUP_sterm_to_key(store->default_ctx);
+    } else {
+        args->ck = NULL_KEY;
+    }
 
-    struct MatchArgs args_s;
-    struct MatchArgs *args = &args_s;
     args->ct = ct;
     *args->ct = 0;
     args->callback_fn = callback_fn;
-    args->ctx = ctx;
+    args->data = data;
 
     // s p o (all terms bound)
     if (spok[0] != NULL_KEY && spok[1] != NULL_KEY && spok[2] != NULL_KEY) {
@@ -784,7 +790,7 @@ index_triple(
 /* * * Match callbacks. * * */
 
 inline static LSUP_rc
-lookup_0bound(struct MDBStore *store, struct MatchArgs *args)
+lookup_0bound(struct MDBStore *store, LookupArgs *args)
 {
     int rc = LSUP_NORESULT;
 
@@ -811,7 +817,7 @@ lookup_0bound(struct MDBStore *store, struct MatchArgs *args)
         while (rc != MDB_NOTFOUND) {
             LSUP_TripleKey spok;
 
-            rc = args->callback_fn(spok, args->ctx);
+            rc = args->callback_fn(spok, args->data);
             if (rc < 0) goto _match0b_abort;
         }
     }
@@ -825,7 +831,7 @@ _match0b_abort:
 
 
 inline static LSUP_rc
-lookup_1bound(struct MDBStore *store, struct MatchArgs *args)
+lookup_1bound(struct MDBStore *store, LookupArgs *args)
 {
     int rc = LSUP_NORESULT, db_rc;
 
@@ -870,7 +876,7 @@ lookup_1bound(struct MDBStore *store, struct MatchArgs *args)
                 spok[term_order[1]] = lu_dset[i][0];
                 spok[term_order[2]] = lu_dset[i][1];
 
-                rc = args->callback_fn(spok, args->ctx);
+                rc = args->callback_fn(spok, args->data);
                 if (rc < 0) goto _match1b_abort;
             }
             rc = mdb_cursor_get(cur, &key_v, &data_v, MDB_NEXT_MULTIPLE);
@@ -886,7 +892,7 @@ _match1b_abort:
 
 
 inline static LSUP_rc
-lookup_2bound(struct MDBStore *store, struct MatchArgs *args)
+lookup_2bound(struct MDBStore *store, LookupArgs *args)
 {
     int rc = LSUP_NORESULT;
 
@@ -967,7 +973,7 @@ lookup_2bound(struct MDBStore *store, struct MatchArgs *args)
                 spok[term_order[1]] = luk[1];
                 spok[term_order[2]] = lu_dset[i];
 
-                rc = args->callback_fn(spok, args->ctx);
+                rc = args->callback_fn(spok, args->data);
                 if (rc < 0) goto _match2b_abort;
             }
             rc = mdb_cursor_get(cur, &key_v, &data_v, MDB_NEXT_MULTIPLE);
@@ -983,7 +989,7 @@ _match2b_abort:
 
 
 inline static LSUP_rc
-lookup_3bound(struct MDBStore *store, struct MatchArgs *args)
+lookup_3bound(struct MDBStore *store, LookupArgs *args)
 {
     int rc = LSUP_NORESULT;
 
@@ -1012,7 +1018,7 @@ lookup_3bound(struct MDBStore *store, struct MatchArgs *args)
         while (rc != MDB_NOTFOUND) {
             LSUP_TripleKey spok;
 
-            rc = args->callback_fn(spok, args->ctx);
+            rc = args->callback_fn(spok, args->data);
             if (rc < 0) goto _match3b_abort;
         }
     }

+ 102 - 6
test/test_store_mdb.c

@@ -113,7 +113,7 @@ static int test_quad_store()
     LSUP_term_serialize(ctx1, &sc1_s);
 
     LSUP_MDBStore *store;
-    store = LSUP_store_new(path, &sc1_s); // triple store.
+    store = LSUP_store_new(path, &sc1_s); // quad store.
     ASSERT(store != NULL, "Error initializing store!");
 
     LSUP_Triple *trp = create_triples();
@@ -131,17 +131,113 @@ static int test_quad_store()
         }
     }
 
-    // Use store default context.
-    EXPECT_PASS(LSUP_store_add(store, NULL, ser_trp, NUM_TRP));
+    // Only triples 0÷5 in default context.
+    EXPECT_PASS(LSUP_store_add(store, NULL, ser_trp, 6));
 
     LSUP_Term *ctx2 = LSUP_uri_new("urn:c:2");
     LSUP_SerTerm sc2_s;
     LSUP_term_serialize(ctx2, &sc2_s);
 
-    // Use specific context.
-    EXPECT_PASS(LSUP_store_add(store, &sc2_s, ser_trp, NUM_TRP));
+    // Only triples 4÷9 in default context.
+    EXPECT_PASS(LSUP_store_add(store, &sc2_s, ser_trp + 4, 6));
+
+    // 6 triples in ctx1 + 6 in ctx2 - 2 duplicates
+    EXPECT_INT_EQ(LSUP_store_size(store), 10);
+
+    // Test lookups.
+    // This context is not with any triple.
+    LSUP_Term *ctx3 = LSUP_uri_new("urn:c:3");
+    LSUP_SerTerm sc3_s;
+    LSUP_term_serialize(ctx2, &sc3_s);
+
+    size_t ct;
+    LSUP_SerTerm *lut[12][4] = {
+        // No context
+        {NULL, NULL, NULL, NULL},
+
+        {ser_trp[0].s, NULL, NULL, NULL},
+        {ser_trp[2].s, NULL, NULL, ser_trp[2].s},
+        {NULL, ser_trp[0].p, NULL, NULL},
+        {NULL, ser_trp[0].s, NULL, NULL},
+        {NULL, NULL, ser_trp[6].o, NULL},
+
+        {ser_trp[4].s, ser_trp[4].p, NULL, NULL},
+        {NULL, ser_trp[7].p, ser_trp[7].o, NULL},
+        {ser_trp[5].s, NULL, ser_trp[5].o, NULL},
+        {ser_trp[6].s, NULL, ser_trp[5].o, ser_trp[2].s},
+
+        {ser_trp[4].s, ser_trp[4].p, ser_trp[4].o, NULL},
+        {ser_trp[4].s, ser_trp[4].p, ser_trp[5].o, NULL},
+
+        // Context 1
+        {NULL, NULL, NULL, NULL},
+
+        {ser_trp[0].s, NULL, NULL, NULL},
+        {ser_trp[2].s, NULL, NULL, ser_trp[2].s},
+        {NULL, ser_trp[0].p, NULL, NULL},
+        {NULL, ser_trp[0].s, NULL, NULL},
+        {NULL, NULL, ser_trp[6].o, NULL},
+
+        {ser_trp[4].s, ser_trp[4].p, NULL, NULL},
+        {NULL, ser_trp[7].p, ser_trp[7].o, NULL},
+        {ser_trp[5].s, NULL, ser_trp[5].o, NULL},
+        {ser_trp[6].s, NULL, ser_trp[5].o, ser_trp[2].s},
+
+        {ser_trp[4].s, ser_trp[4].p, ser_trp[4].o, NULL},
+        {ser_trp[4].s, ser_trp[4].p, ser_trp[5].o, NULL},
+
+
+        // Context 2
+        {NULL, NULL, NULL, NULL},
+
+        {ser_trp[0].s, NULL, NULL, NULL},
+        {ser_trp[2].s, NULL, NULL, ser_trp[2].s},
+        {NULL, ser_trp[0].p, NULL, NULL},
+        {NULL, ser_trp[0].s, NULL, NULL},
+        {NULL, NULL, ser_trp[6].o, NULL},
+
+        {ser_trp[4].s, ser_trp[4].p, NULL, NULL},
+        {NULL, ser_trp[7].p, ser_trp[7].o, NULL},
+        {ser_trp[5].s, NULL, ser_trp[5].o, NULL},
+        {ser_trp[6].s, NULL, ser_trp[5].o, ser_trp[2].s},
+
+        {ser_trp[4].s, ser_trp[4].p, ser_trp[4].o, NULL},
+        {ser_trp[4].s, ser_trp[4].p, ser_trp[5].o, NULL},
+
+
+        // Non-existing context
+        {NULL, NULL, NULL, NULL},
+
+        {ser_trp[0].s, NULL, NULL, NULL},
+        {ser_trp[2].s, NULL, NULL, ser_trp[2].s},
+        {NULL, ser_trp[0].p, NULL, NULL},
+        {NULL, ser_trp[0].s, NULL, NULL},
+        {NULL, NULL, ser_trp[6].o, NULL},
+
+        {ser_trp[4].s, ser_trp[4].p, NULL, NULL},
+        {NULL, ser_trp[7].p, ser_trp[7].o, NULL},
+        {ser_trp[5].s, NULL, ser_trp[5].o, NULL},
+        {ser_trp[6].s, NULL, ser_trp[5].o, ser_trp[2].s},
+
+        {ser_trp[4].s, ser_trp[4].p, ser_trp[4].o, NULL},
+        {ser_trp[4].s, ser_trp[4].p, ser_trp[5].o, NULL},
+    };
+
+    size_t results[12] = {
+        8,
+        5, 1, 1, 0, 1,
+        2, 1, 2, 0,
+        1, 0,
+    };
+
+    for (int i = 0; i < 8; i++) {
+        TRACE("Testing triple lookup #%d.\n", i);
+        int rc = LSUP_store_lookup(store, lut[i], &ct, NULL, NULL);
+        if (ct > 0) EXPECT_INT_EQ(rc, LSUP_OK);
+        else if (ct == 0) EXPECT_INT_EQ(rc, LSUP_NORESULT);
 
-    EXPECT_INT_EQ(LSUP_store_size(store), 16);
+        EXPECT_INT_EQ(ct, results[i]);
+    }
 
     for (int i = 0; i < NUM_TRP; i++) {
         LSUP_buffer_done(ser_trp[i].s);