Jelajahi Sumber

Fix txn issues with nsm initialization in MDB.

scossu 2 hari lalu
induk
melakukan
3b39d4f518
4 mengubah file dengan 61 tambahan dan 31 penghapusan
  1. 2 2
      include/lsup/graph.h
  2. 2 1
      src/graph.c
  3. 51 28
      src/store_mdb.c
  4. 6 0
      test/test_graph.c

+ 2 - 2
include/lsup/graph.h

@@ -36,8 +36,8 @@ typedef struct graph_iter_t LSUP_GraphIterator;
  *
  * @param[in] nsm Namespace map to use for an in-memory graph. This is ignored
  *  by graphs backed by permanent stores, which handle their own namespace map.
- *  If this is NULL, the graph is assigned a global namespace map that lives
- *  until #LSUP_done() is called.
+ *  If this is NULL, the graph is assigned a global namespace map
+ *  (#LSUP_default_nsm) that lives until #LSUP_done() is called.
  *
  * @return New graph, or NULL on error. Must be freed with #LSUP_graph_free().
  */

+ 2 - 1
src/graph.c

@@ -48,7 +48,8 @@ LSUP_graph_new (LSUP_Store *store, const char *uri_str, LSUP_NSMap *nsm)
     LSUP_Graph *gr;
     MALLOC_GUARD (gr, NULL);
 
-    gr->store = (store) ? store : LSUP_store_new (LSUP_STORE_HTABLE, NULL, 0);
+    gr->store = (store) ? store : LSUP_store_new (
+            LSUP_STORE_HTABLE, NULL, 0, false);
 
     if (gr->store->sif->nsm_get_fn)
         gr->nsm = gr->store->sif->nsm_get_fn (gr->store->data);

+ 51 - 28
src/store_mdb.c

@@ -256,24 +256,22 @@ finally:
 
 
 static LSUP_rc
-mdbstore_nsm_put (void *h, const LSUP_NSMap *nsm, void *th)
+nsm_put (MDB_env *env, MDB_txn *p_txn, const LSUP_NSMap *nsm)
 {
-    MDBStore *store = h;
-    MDB_txn *txn;
-    RCCK (mdb_txn_begin (store->env, (MDB_txn *) th, 0, &txn));
-
     LSUP_rc rc = LSUP_NOACTION;
     int db_rc;
 
+    MDB_txn *txn;
+    RCCK (mdb_txn_begin (env, p_txn, 0, &txn));
+
     MDB_cursor *dcur = NULL, *icur = NULL;
-    if (
-        mdb_cursor_open (txn, store->dbi[IDX_PFX_NS], &dcur) != MDB_SUCCESS
-        ||
-        mdb_cursor_open (txn, store->dbi[IDX_NS_PFX], &icur) != MDB_SUCCESS
-    ) {
-        mdb_txn_abort (txn);
-        return LSUP_DB_ERR;
-    }
+    MDB_dbi ddbi, idbi;
+    RCCK (mdb_dbi_open (
+                txn, db_labels[IDX_PFX_NS], db_flags[IDX_PFX_NS], &ddbi));
+    RCCK (mdb_dbi_open (
+                txn, db_labels[IDX_NS_PFX], db_flags[IDX_NS_PFX], &idbi));
+    RCCK (mdb_cursor_open (txn, ddbi, &dcur));
+    RCCK (mdb_cursor_open (txn, idbi, &icur));
 
     MDB_val pfx_v, ns_v;
     const char ***nsm_data = LSUP_nsmap_dump (nsm);
@@ -320,6 +318,11 @@ loop_end:
 }
 
 
+static LSUP_rc
+mdbstore_nsm_put (void *h, const LSUP_NSMap *nsm, void *th)
+{ return nsm_put (((MDBStore *)h)->env, (MDB_txn *)th, nsm); }
+
+
 static const char *
 mdbstore_path_from_id (const char *id)
 {
@@ -342,7 +345,7 @@ mdbstore_path_from_id (const char *id)
 
 /** @brief Create the MDB environment and databases on disk.
  *
- * This function takes care of creaating the environment path if not existing,
+ * This function takes care of creating the environment path if not existing,
  * and checking that it's a writable directory. If the path is not specified
  * in the LSUP_MDB_STORE_URN environment variable, a default directory is used.
  */
@@ -368,18 +371,50 @@ mdbstore_setup (const char *id, bool clear)
 
     MDB_txn *txn;
     RCCK (mdb_txn_begin (env, NULL, 0, &txn));
+    MDB_dbi dbi;
     for (int i = 0; i < N_DB; i++) {
         LOG_TRACE("Creating DB %s", db_labels[i]);
-        MDB_dbi dbi;
         RCCK (
             mdb_dbi_open (txn, db_labels[i], db_flags[i] | MDB_CREATE, &dbi)
         );
     }
 
+    // Bootstrap the permanent store with initial data.
+    MDB_stat stat;
+    CHECK (mdb_dbi_open (
+                txn, db_labels[IDX_PFX_NS], db_flags[IDX_PFX_NS], &dbi), fail);
+    CHECK (mdb_stat (txn, dbi, &stat), fail);
+    if (stat.ms_entries == 0) {
+        LOG_DEBUG ("Loading initial data into %s", id);
+        // Load initial NS map.
+        PCHECK (nsm_put (env, txn, LSUP_default_nsm), fail);
+
+        // Index default context.
+        CHECK (mdb_dbi_open (
+                txn, db_labels[IDX_T_ST], db_flags[IDX_T_ST], &dbi), fail);
+        MDB_cursor *cur;
+        CHECK (mdb_cursor_open (txn, dbi, &cur), fail);
+        LSUP_Key k = LSUP_buffer_hash (LSUP_default_ctx_buf);
+        MDB_val key, data;
+        key.mv_data = &k;
+        key.mv_size = sizeof (k);
+
+        data.mv_data = LSUP_default_ctx_buf->addr;
+        data.mv_size = LSUP_default_ctx_buf->size;
+
+        LSUP_rc db_rc = mdb_cursor_put (cur, &key, &data, MDB_NOOVERWRITE);
+        LOG_DEBUG ("Add default ctx rc: %i", rc);
+        if (db_rc != MDB_KEYEXIST) CHECK (db_rc, fail);
+    }
+
     mdb_txn_commit (txn);
     mdb_env_close (env);
 
     return clear ? LSUP_OK : rc;
+
+fail:
+    mdb_txn_abort (txn);
+    return rc;
 }
 
 
@@ -424,18 +459,6 @@ mdbstore_new (const char *id, size_t _unused)
         CHECK (mdb_dbi_open (
                 txn, db_labels[i], db_flags[i], store->dbi + i), fail);
 
-    // Bootstrap the permanent store with initial data.
-    MDB_stat stat;
-    CHECK (mdb_stat (txn, store->dbi[IDX_PFX_NS], &stat), fail);
-    if (stat.ms_entries == 0) {
-        LOG_DEBUG("Loading initial data into %s", path);
-        // Load initial NS map.
-        mdbstore_nsm_put (store, LSUP_default_nsm, txn);
-
-        // Index default context.
-        mdbstore_add_term (store, LSUP_default_ctx_buf, txn);
-    }
-
     store->flags |= LSSTORE_OPEN;
     mdb_txn_commit (txn);
     txn = NULL;
@@ -927,7 +950,7 @@ mdbiter_next (
             size_t i = 0;
             while (it->ck[i++]); // Include sentinel in count.
             LSUP_Buffer *ctx;
-            LOG_TRACE("Allocating %lu context buffers.", i);
+            LOG_TRACE("Allocating %lu context buffers + sentinel.", i - 1);
             ctx = malloc(i * sizeof (*ctx));
             if (!ctx) return LSUP_MEM_ERR;
 

+ 6 - 0
test/test_graph.c

@@ -205,6 +205,7 @@ _graph_link_map (LSUP_StoreType type)
     LSUP_Term *ts_res[9] = {NULL};  // Collected terms in term set in loop.
     size_t i = 0, j = 0;
 
+    /*
     LSUP_Term *po[6][4] = {
         {trp[0]->p, trp[0]->o, NULL},
         {trp[3]->p, trp[3]->o, NULL},
@@ -212,6 +213,7 @@ _graph_link_map (LSUP_StoreType type)
         {trp[5]->p, trp[5]->o, NULL},
         {NULL}
     };
+    */
 
     // terms connected to subject, urn:s:0
     lmap = LSUP_graph_connections (gr, trp[0]->s, LSUP_LINK_OUTBOUND);
@@ -237,10 +239,12 @@ _graph_link_map (LSUP_StoreType type)
     i = 0; j = 0;
     memset (k_res, 0, sizeof (k_res));
     memset (ts_res, 0, sizeof (ts_res));
+    /*
     LSUP_Term *so[3][3] = {
         {trp[1]->s, trp[1]->o, NULL},
         {trp[3]->s, trp[3]->o, NULL},
     };
+    */
     // terms connected to predicate, urn:p:1
     lmap = LSUP_graph_connections (gr, trp[1]->p, LSUP_LINK_EDGE);
     lmit = LSUP_link_map_iter_new (lmap);
@@ -264,9 +268,11 @@ _graph_link_map (LSUP_StoreType type)
     i = 0; j = 0;
     memset (k_res, 0, sizeof (k_res));
     memset (ts_res, 0, sizeof (ts_res));
+    /*
     LSUP_Term *sp[1][3] = {
         {trp[6]->s, trp[6]->p, NULL},
     };
+    */
     // terms connected to object, "String 1"@es-ES
     lmap = LSUP_graph_connections (gr, trp[6]->o, LSUP_LINK_INBOUND);
     lmit = LSUP_link_map_iter_new (lmap);