Pārlūkot izejas kodu

Setup store as part of the LSUP_store_new() call.

scossu 2 dienas atpakaļ
vecāks
revīzija
b9c6d18269

+ 1 - 1
Makefile

@@ -166,7 +166,7 @@ install: lib ## Install library and dependencies to $PREFIX. May require sudo.
 		cp include/*.h $(INCLUDEDIR)
 
 
-debug_install: install debug ## Install standard and debug libraries.
+debug_install: debug ## Install debug libraries.
 	@echo "Installing debug library files in $(PREFIX)."
 	cp $(DBG_LIBS) $(libdir)
 

+ 7 - 2
README.md

@@ -39,6 +39,10 @@ reformatting. This code is being integrated in higher-level projects and is
 being improved as issues arise. The status will move to beta as soon as at
 least one dependent project covers a significant range of `lsup_rdf` features.
 
+Portability is still under assessment. The goal is to make this code POSIX
+compatible. ANSI C compatibility is out of reach because of the LMDB
+dependency.
+
 This is my first stab at writing a C library (coming from Python) and an
 unpaid fun project, so don't be surprised if you find some gross stuff.
 
@@ -67,6 +71,7 @@ of features as a standalone library:
 - ⛌ Python bindings (moved to separate project and temporarily on hold)
 - ⚒ Basic command line utilities
 - ✓ Store interface for custom back end implementations
+- ⚒ POSIX conformance
 
 ### Possibly In scope – Long Term
 
@@ -119,7 +124,7 @@ RDF source. The default value is 8192, which is mildly conservative. If you
 experience parsing errors on decoding, and they happen to be on a term such a
 very long string literal, try recompiling the library with a larger value.
 
-## Embedding
+## Embedding & linking
 
 The generated `liblsuprdf.so` and `liblsuprdf.a` libraries can be linked
 dynamically or statically to your code. Only the `lsup_rdf.h` header, which
@@ -130,7 +135,7 @@ Environment variables and/or compiler options might have to be set in order to
 find the dynamic libraries and headers in their install locations.
 
 For compilation and linking examples, refer to `test`, `memtest`, `perftest`
-and other actions in the current Makefile.
+and other targets in the current Makefile.
 
 
 ### Environment Variables

+ 1 - 1
include/lsup/graph.h

@@ -475,7 +475,7 @@ LSUP_graph_unique_terms (const LSUP_Graph *gr, LSUP_TriplePos pos);
  * @return Term set of graph URIs, or NULL on error.
  */
 LSUP_TermSet *
-LSUP_graph_list_txn (void *txn, LSUP_Store *store);
+LSUP_graph_list_txn (void *txn, const LSUP_Store *store);
 
 
 /// Non-transactional version of #LSUP_graph_list_txn.

+ 6 - 3
include/lsup/store.h

@@ -103,12 +103,15 @@ LSUP_store_type_label (LSUP_StoreType type);
  *  purposes. It may be ignored by some implementations and it is always safe
  *  to set to 0.
  *
- *  @return Store handle that should be passed to #LSUP_store_new(). It must be
- *  freed with #LSUP_store_free().
+ *  @param clear Flag that is passed to the `init_fn` function of the store
+ *   interface, if present, to clear an existing store with the same ID.
+ *
+ *  @return Store handle. It must be freed with #LSUP_store_free().
  */
 LSUP_Store *
 LSUP_store_new (
-        const LSUP_StoreType store_type, const char *store_id, size_t size);
+        const LSUP_StoreType store_type, const char *store_id, size_t size,
+        bool clear);
 
 
 /** @brief Free a store created with #LSUP_store_new().

+ 2 - 0
include/lsup/store_interface.h

@@ -66,6 +66,8 @@ typedef enum {
  */
 
 /** @brief Prototype: create any environment necessary for the store to work.
+ *
+ * #LSUP_store_new() calls this function before creating the store handle.
  *
  * This function should be idempotent on separate calls to the same `id`,
  * unless the `clear` option is set to `true`.

+ 4 - 0
include/lsup/store_mdb.h

@@ -6,6 +6,10 @@
  * into named graphs. The store is optimized and indexed for fast lookup of any
  * number of bound terms.
  *
+ * Note that this store does not keep track of empty contexts. Hence, if an
+ * empty graph is created under this store, nothing is effectively recorded
+ * until some triples are added to the graph.
+ *
  * The store must be first initialized once, to create the environment files
  * and folders as well as the internal databases, then it must be opened once
  * per session. Within that session multiple R/W operations can be performed

+ 3 - 2
src/graph.c

@@ -252,14 +252,15 @@ LSUP_graph_free (LSUP_Graph *gr)
     if (UNLIKELY (!gr)) return;
 
     LSUP_term_free (gr->uri);
-    free (gr->store->id);
     // If the store has the nsm_get_fn, it's been uniquely created for this
     // graph and it's safe to free.
     if (gr->store->sif->nsm_get_fn) LSUP_nsmap_free (gr->nsm);
     // If the store is a HTable, it means it has been created with the graph
     // and must go with it.
+    // TODO Use feature flags. Need some specs around this.
     if (gr->store->type == LSUP_STORE_HTABLE) {
         gr->store->sif->free_fn (gr->store->data);
+        free (gr->store->id);
         free (gr->store);
     }
 
@@ -641,7 +642,7 @@ LSUP_graph_iter_free (LSUP_GraphIterator *it)
 
 
 LSUP_TermSet *
-LSUP_graph_list_txn (void *txn, LSUP_Store *store)
+LSUP_graph_list_txn (void *txn, const LSUP_Store *store)
 {
     LSUP_Buffer **tdata = store->sif->ctx_list_fn (store->data, txn);
     if (UNLIKELY (!tdata)) return NULL;

+ 12 - 1
src/store.c

@@ -26,7 +26,8 @@ LSUP_store_type_label (LSUP_StoreType type)
 
 LSUP_Store *
 LSUP_store_new (
-        const LSUP_StoreType store_type, const char *store_id, size_t size)
+        const LSUP_StoreType store_type, const char *store_id, size_t size,
+        bool clear)
 {
     if (UNLIKELY (!LSUP_IS_INIT)) {
         log_error (
@@ -45,10 +46,20 @@ LSUP_store_new (
     store->type = store_type;
     store->sif = sif;
     store->id = store_id ? strdup (store_id) : NULL;
+
+    if (store->sif->setup_fn)
+        PCHECK (store->sif->setup_fn (store_id, clear), fail);
+
     // TODO implement custom default context.
     store->data = store->sif->new_fn (store_id, size);
 
     return store;
+
+fail:
+    free (store->id);
+    free (store);
+
+    return NULL;
 }
 
 

+ 3 - 4
src/store_mdb.c

@@ -355,9 +355,8 @@ mdbstore_setup (const char *id, bool clear)
     // If the directory exists (unless clear == true), do nothing.
     if (clear) rm_r (path);
     LSUP_rc rc = mkdir_p (path, ENV_DIR_MODE);
-    log_info ("Create dir rc: %d", rc);
-    log_info ("LSUP Create dir rc: %d", rc);
-    RCCK (rc);
+    log_info ("Create dir rc: %s", LSUP_strerror (rc));
+    PRCCK (rc);
 
     // Open a temporary environment and txn to create the DBs.
     MDB_env *env;
@@ -380,7 +379,7 @@ mdbstore_setup (const char *id, bool clear)
     mdb_txn_commit (txn);
     mdb_env_close (env);
 
-    return LSUP_OK;
+    return clear ? LSUP_OK : rc;
 }
 
 

+ 12 - 40
test/test_graph.c

@@ -7,15 +7,12 @@
 static int
 _graph_new (LSUP_StoreType type)
 {
-    const LSUP_StoreInt *sif = LSUP_store_int (type);
-    if (sif->setup_fn) sif->setup_fn (NULL, true);
-
     LSUP_Graph *gr;
     LSUP_Store *store = NULL;
     if (type == LSUP_STORE_HTABLE) {
         gr = LSUP_graph_new (NULL, NULL, NULL);
     } else {
-        store = LSUP_store_new (type, NULL, 0);
+        store = LSUP_store_new (type, NULL, 0, true);
         gr = LSUP_graph_new (store, NULL, NULL);
     }
     ASSERT (gr != NULL, "Error creating graph!");
@@ -24,6 +21,7 @@ _graph_new (LSUP_StoreType type)
     EXPECT_STR_EQ (LSUP_graph_uri (gr)->data, "urn:gr:1");
 
     // Check that setup function is idempotent with clear == false.
+    const LSUP_StoreInt *sif = LSUP_store_int (type);
     if (sif->setup_fn) EXPECT_INT_EQ (
             sif->setup_fn (NULL, false), LSUP_NOACTION);
 
@@ -44,7 +42,6 @@ static int
 _graph_ns_uri (LSUP_StoreType type)
 {
     const LSUP_StoreInt *sif = LSUP_store_int (type);
-    if (sif->setup_fn) sif->setup_fn (NULL, true);
 
     LSUP_NSMap *nsm = LSUP_nsmap_new();
     LSUP_nsmap_add (nsm, "ns1", "urn:ns1#");
@@ -54,7 +51,7 @@ _graph_ns_uri (LSUP_StoreType type)
     LSUP_Graph *gr;
     LSUP_Store *store = NULL;
     if (sif->features & LSUP_STORE_PERM) {
-        store = LSUP_store_new (type, NULL, 0);
+        store = LSUP_store_new (type, NULL, 0, true);
         store->sif->nsm_put_fn (store->data, nsm, NULL);
     }
     gr = LSUP_graph_new (store, "ns1:gr1", nsm);
@@ -81,15 +78,12 @@ _graph_ns_uri (LSUP_StoreType type)
 static int
 _graph_add (LSUP_StoreType type)
 {
-    const LSUP_StoreInt *sif = LSUP_store_int (type);
-    if (sif->setup_fn) sif->setup_fn (NULL, true);
-
     LSUP_Triple **trp = create_triples();
 
     LSUP_Graph *gr;
     LSUP_Store *store;
     if (type == LSUP_STORE_HTABLE) store = NULL;
-    else store = LSUP_store_new (type, NULL, 0);
+    else store = LSUP_store_new (type, NULL, 0, true);
 
     gr = LSUP_graph_new (store, NULL, NULL);
     ASSERT (gr != NULL, "Error creating graph!");
@@ -136,13 +130,11 @@ _graph_get (LSUP_StoreType type)
     // Skip if the store doesn't support contexts.
     if (!(sif->features & LSUP_STORE_CTX)) return 0;
 
-    if (sif->setup_fn) sif->setup_fn (NULL, true);
-
     LSUP_Triple **trp = create_triples();
 
     LSUP_Store *store;
     if (type == LSUP_STORE_HTABLE) store = NULL;
-    else store = LSUP_store_new (type, NULL, 0);
+    else store = LSUP_store_new (type, NULL, 0, true);
     LSUP_Graph
         *gr1 = LSUP_graph_new (store, NULL, NULL),
         *gr2 = LSUP_graph_new (store, NULL, NULL);
@@ -195,15 +187,11 @@ _graph_get (LSUP_StoreType type)
 static int
 _graph_link_map (LSUP_StoreType type)
 {
-    const LSUP_StoreInt *sif = LSUP_store_int (type);
-
-    if (sif->setup_fn) sif->setup_fn (NULL, true);
-
     LSUP_Triple **trp = create_triples();
 
     LSUP_Store *store;
     if (type == LSUP_STORE_HTABLE) store = NULL;
-    else store = LSUP_store_new (type, NULL, 0);
+    else store = LSUP_store_new (type, NULL, 0, true);
     LSUP_Graph *gr = LSUP_graph_new (store, NULL, NULL);
 
     size_t ct;
@@ -314,13 +302,11 @@ _graph_bool_ops (LSUP_StoreType type)
     // Skip if the store doesn't support contexts.
     if (!(sif->features & LSUP_STORE_CTX)) return 0;
 
-    if (sif->setup_fn) sif->setup_fn (NULL, true);
-
     LSUP_Triple **trp = create_triples();
 
     LSUP_Store *store;
     if (type == LSUP_STORE_HTABLE) store = NULL;
-    else store = LSUP_store_new (type, NULL, 0);
+    else store = LSUP_store_new (type, NULL, 0, true);
     LSUP_Graph
         *gr1 = LSUP_graph_new (store, NULL, NULL),
         *gr2 = LSUP_graph_new (store, NULL, NULL),
@@ -417,7 +403,6 @@ _graph_bool_ops (LSUP_StoreType type)
 static int
 _graph_lookup (LSUP_StoreType type)
 {
-    const LSUP_StoreInt *sif = LSUP_store_int (type);
     LSUP_Triple **trp = create_triples();
 
     // Lookup triples.
@@ -466,14 +451,12 @@ _graph_lookup (LSUP_StoreType type)
     };
     */
 
-    if (sif->setup_fn) sif->setup_fn (NULL, true);
-
     LSUP_Graph *gr;
     LSUP_Store *store = NULL;
     if (type == LSUP_STORE_HTABLE) {
         gr = LSUP_graph_new (NULL, NULL, NULL);
     } else {
-        store = LSUP_store_new (type, NULL, 0);
+        store = LSUP_store_new (type, NULL, 0, true);
         gr = LSUP_graph_new (store, NULL, NULL);
     }
 
@@ -534,9 +517,6 @@ _graph_lookup (LSUP_StoreType type)
 static int
 _graph_remove (LSUP_StoreType type)
 {
-    const LSUP_StoreInt *sif = LSUP_store_int (type);
-    if (sif->setup_fn) sif->setup_fn (NULL, true);
-
     LSUP_Triple **trp = create_triples();
 
     LSUP_Graph *gr;
@@ -544,7 +524,7 @@ _graph_remove (LSUP_StoreType type)
     if (type == LSUP_STORE_HTABLE) {
         gr = LSUP_graph_new (NULL, NULL, NULL);
     } else {
-        store = LSUP_store_new (type, NULL, 0);
+        store = LSUP_store_new (type, NULL, 0, true);
         gr = LSUP_graph_new (store, NULL, NULL);
     }
 
@@ -586,14 +566,12 @@ _graph_txn (LSUP_StoreType type)
     const LSUP_StoreInt *sif = LSUP_store_int (type);
     if (!(sif->features & LSUP_STORE_TXN)) return 0;
 
-    if (sif->setup_fn) sif->setup_fn (NULL, true);
-
     LSUP_Triple **trp = create_triples();
 
     LSUP_Graph *gr;
     LSUP_Store *store =
         type == LSUP_STORE_HTABLE ? NULL
-        : LSUP_store_new (type, NULL, 0);
+        : LSUP_store_new (type, NULL, 0, true);
 
     gr = LSUP_graph_new (store, NULL, NULL);
 
@@ -628,10 +606,6 @@ _graph_txn (LSUP_StoreType type)
 static int
 _graph_relative (LSUP_StoreType type)
 {
-    const LSUP_StoreInt *sif = LSUP_store_int (type);
-
-    if (sif->setup_fn) sif->setup_fn (NULL, true);
-
     LSUP_Term
         *s = LSUP_iriref_new ("http://onto.knowledgetx.com/gr1/s1", NULL),
         *s2 = LSUP_iriref_new ("http://onto.knowledgetx.com/gr2/s1", NULL),
@@ -649,7 +623,7 @@ _graph_relative (LSUP_StoreType type)
 
     LSUP_Store *store =
         type == LSUP_STORE_HTABLE ? NULL
-        : LSUP_store_new (type, NULL, 0);
+        : LSUP_store_new (type, NULL, 0, true);
 
     LSUP_Graph *gr = LSUP_graph_new (store, c->data, NULL);
 
@@ -690,9 +664,7 @@ _graph_list (LSUP_StoreType type)
     const LSUP_StoreInt *sif = LSUP_store_int (type);
     if (!(sif->features & LSUP_STORE_CTX)) return 0;
 
-    if (sif->setup_fn) sif->setup_fn (NULL, true);
-
-    LSUP_Store *store = LSUP_store_new (type, NULL, 0);
+    LSUP_Store *store = LSUP_store_new (type, NULL, 0, true);
 
     LSUP_Graph *gg[3] = {
         LSUP_graph_new (store,  "urn:gr:1", NULL),

+ 1 - 2
test/test_store_mdb.c

@@ -12,9 +12,8 @@
 static int test_ctx_switch()
 {
     const LSUP_StoreInt *sif = LSUP_store_int (LSUP_STORE_MDB);
-    sif->setup_fn (MDBSTORE_ID, true);
 
-    LSUP_Store *store = LSUP_store_new (LSUP_STORE_MDB, MDBSTORE_ID, 0);
+    LSUP_Store *store = LSUP_store_new (LSUP_STORE_MDB, MDBSTORE_ID, 0, true);
     ASSERT (store != NULL, "Error initializing store!");
 
     // Create enough triples to test a multi-page copy of triple data.