Browse Source

WIP Separate update function.

scossu 1 year ago
parent
commit
c6c1387ebb
6 changed files with 149 additions and 136 deletions
  1. 2 1
      Makefile
  2. 3 0
      include/core.h
  3. 12 8
      include/desc.h
  4. 6 0
      src/core.c
  5. 108 115
      src/desc.c
  6. 18 12
      test/test_desc.c

+ 2 - 1
Makefile

@@ -88,9 +88,10 @@ debug_install: install debug ## Install default and debug libraries.
 	cp liblsuprdf_dbg.{a,so} $(DESTDIR)$(libdir)
 	
 
+
 .PHONY: clean
 clean:
-	rm -rf src/*.[aod] ./*[aod]
+	rm -rf src/*.[aod] ./*.{a,o,d,so}
 	rm -f bin/test*
 
 

+ 3 - 0
include/core.h

@@ -61,6 +61,9 @@ extern LSR_TermMap *LSR_managed_types;
 /// Default back end store.
 extern LSUP_Store *LSR_store;
 
+/// RDF type URI.
+extern LSUP_Term *LSR_rdf_t;
+
 
 /*
  * API.

+ 12 - 8
include/desc.h

@@ -124,17 +124,21 @@ LSR_desc_get (const uuid_t id, LSR_Desc **rsrc);
  *
  * @param[in] rsrc Resource handle.
  *
- * @param[in] rm_data Array of graph handles. Each graph contains triples to be
- * removed from graphs with a matching URI in the resource. If no matching
- * graph is found, that graph has no effect.
- *
- * @param[in] add_data Array of graph handles to add. If the resource has
- * already a matching graph for a graph being added, the triples are added to
- * the existing graph.
+ * @param[in] rm_data NULL-terminated array of graph handles. Each graph
+ * contains triples to be removed from graphs with a matching URI in the
+ * resource. If no matching graph is found, that graph has no effect.
+ * Note that some internal functions may pass NULL to this parameter. This
+ * should not be done externally because it assumes that the resource is
+ * new and may leave it in an inconsistent state. This is different from
+ * passing `{NULL}`.
+ *
+ * @param[in] add_data NULL-terminated array of graph handles to add. If the
+ * resource has already a matching graph for a graph being added, the triples
+ * are added to the existing graph.
  *
  * @return LSUP_OK on successful update; TODO
  */
-static LSUP_rc
+LSUP_rc
 LSR_desc_update (
         LSR_Desc *rsrc, LSUP_Graph *const *rm_data,
         LSUP_Graph *const *add_data);

+ 6 - 0
src/core.c

@@ -3,6 +3,8 @@
 
 bool LSR_is_init = false;
 
+LSUP_Term *LSR_rdf_t = NULL;
+
 /*
  * Initial namespace map.
  */
@@ -87,6 +89,8 @@ LSUP_rc LSR_init (void)
     LSUP_rc rc = LSUP_init();
     if (rc < 0) return rc;
 
+    LSR_rdf_t = LSUP_iriref_new ("rdf:type", LSUP_default_nsm);
+
     // Set up default back end.
     // If LSR_BACKEND_URN is not defined in env, LSUP_MDB_STORE_URN is used;
     // if that is also not set, lsup_rdf will use its default—which may be in
@@ -151,6 +155,8 @@ void LSR_done (void)
 
     hashmap_free (LSR_managed_preds);
     hashmap_free (LSR_managed_types);
+    LSUP_term_free (LSR_rdf_t);
+    LSR_rdf_t = NULL;
 
     LSUP_done();
     LSR_is_init = false;

+ 108 - 115
src/desc.c

@@ -1,10 +1,5 @@
 #include "desc.h"
 
-static LSUP_rc
-desc_update (
-        LSR_Desc *rsrc, LSUP_Graph *const *rm_data,
-        LSUP_Graph *const *add_data, bool _new);
-
 
 LSUP_rc
 LSR_desc_new_multi (LSUP_Graph *const *data, LSR_Desc **rsrc_p)
@@ -16,9 +11,6 @@ LSR_desc_new_multi (LSUP_Graph *const *data, LSR_Desc **rsrc_p)
 
     uuid_generate_random (rsrc->id);
 
-    LSUP_Graph *const *rm_data = {NULL};
-    PCHECK (desc_update (rsrc, rm_data, data, true), finally);
-
     // Default context graph.
     LSUP_Term *main_data_urn = LSR_id_to_urn (rsrc->id, "__main");
     rsrc->main_data = LSUP_graph_new (NULL, main_data_urn, LSUP_default_nsm);
@@ -27,97 +19,82 @@ LSR_desc_new_multi (LSUP_Graph *const *data, LSR_Desc **rsrc_p)
             "Main data graph: %s",
             LSUP_graph_uri(rsrc->main_data)->data);
 
-    LSUP_GraphIterator *add_it = NULL;
-
-    LSUP_Term *s, *p, *o;
-    LSUP_Triple dest_spo_s;
-    LSUP_Triple *dest_spo = &dest_spo_s;
+    PCHECK (LSR_desc_update (rsrc, NULL, data), finally);
 
     LSUP_Term *rsrc_uri = LSR_id_to_urn (rsrc->id, NULL);
-    LSUP_Term *rdf_t = LSUP_iriref_new ("rdf:type", LSUP_default_nsm);
 
     /* BEGIN adding managed (admin) data. */
 
-    LSUP_Term *gr_uri = LSR_id_to_urn (rsrc->id, "__admin");
-    rsrc->admin_data = LSUP_graph_new (NULL, gr_uri, NULL);
+    LSUP_Term *admin_uri = LSR_id_to_urn (rsrc->id, "__admin");
+    rsrc->admin_data = LSUP_graph_new (NULL, admin_uri, NULL);
+
     log_debug (
             "Admin data graph (@%p): %s",
-            LSUP_graph_uri(rsrc->admin_data),
-            LSUP_graph_uri(rsrc->admin_data)->data);
-
-    add_it = LSUP_graph_add_init (rsrc->admin_data);
-    s = LSUP_iriref_new("", NULL); // Relative to resource URI.
-    LSUP_Triple admin_spo_s;
-    LSUP_Triple *admin_spo = &admin_spo_s;
-
-    // RDF types.
-    p = rdf_t;
+            LSUP_graph_uri (rsrc->admin_data),
+            LSUP_graph_uri (rsrc->admin_data)->data);
 
-    o = LSUP_iriref_new ("lsup:Resource", LSUP_default_nsm);
-    LSUP_triple_init (admin_spo, s, p, o);
-    LSUP_graph_add_iter (add_it, admin_spo);
-    LSUP_term_free (o);
-
-    o = LSUP_iriref_new ("lsup:DescriptiveResource", LSUP_default_nsm);
-    LSUP_triple_init (admin_spo, s, p, o);
-    LSUP_graph_add_iter (add_it, admin_spo);
-    LSUP_term_free (o);
-
-    // Timestamps. For now, second precision is fine.
+    // Calculate timestamp.
     time_t now;
     time (&now);
-    char buf [sizeof ("0000-00-00T00:00:00Z")];
-    strftime (buf, sizeof (buf), "%FT%TZ", gmtime (&now));
-
-    p = LSUP_iriref_new ("lsup:created", LSUP_default_nsm);
-    o = LSUP_literal_new (
-            buf, LSUP_iriref_new ("xsd:dateTime", LSUP_default_nsm));
-    LSUP_triple_init (admin_spo, s, p, o);
-    LSUP_graph_add_iter (add_it, admin_spo);
-    LSUP_term_free (p);
-
-    p = LSUP_iriref_new ("lsup:lastModified", LSUP_default_nsm);
-    LSUP_triple_init (admin_spo, s, p, o);
-    LSUP_graph_add_iter (add_it, admin_spo);
-    LSUP_term_free (p);
-    LSUP_term_free (o);
-    LSUP_graph_add_done (add_it);
+    char tstamp [sizeof ("0000-00-00T00:00:00Z")];
+    strftime (tstamp, sizeof (tstamp), "%FT%TZ", gmtime (&now));
+
+    LSUP_Term
+        *s = LSUP_iriref_new("", NULL), // Relative to resource URI.
+        *created_t = LSUP_iriref_new ("lsup:created", LSUP_default_nsm),
+        *rsrc_t = LSUP_iriref_new ("lsup:Resource", LSUP_default_nsm),
+        *desc_rsrc_t = LSUP_iriref_new (
+                "lsup:DescriptiveResource", LSUP_default_nsm),
+        *ts_t = LSUP_literal_new (
+                tstamp, LSUP_iriref_new ("xsd:dateTime", LSUP_default_nsm));
+
+    LSUP_Triple *admin_trp[] = {
+        LSUP_triple_new (s, LSR_rdf_t, rsrc_t),
+        LSUP_triple_new (s, LSR_rdf_t, desc_rsrc_t),
+        LSUP_triple_new (s, created_t, ts_t),
+        NULL,
+    };
+
+    rc = LSUP_graph_add (rsrc->admin_data, admin_trp, NULL);
+    PCHECK (rc, finally);
+
+    for (size_t i = 0; admin_trp[i]; i++)
+        free (admin_trp[i]);
+    LSUP_term_free (s);
+    LSUP_term_free (created_t);
+    LSUP_term_free (rsrc_t);
+    LSUP_term_free (desc_rsrc_t);
+    LSUP_term_free (ts_t);
 
     /* END adding admin data. */
 
     /* BEGIN adding graph metadata (main). */
 
-    add_it = LSUP_graph_add_init (rsrc->main_data);
-    LSUP_term_free (s);
-    s = gr_uri;
-    p = rdf_t;
-
-    o = LSUP_iriref_new ("lsup:Metadata", LSUP_default_nsm);
-    LSUP_triple_init (dest_spo, s, p, o);
-    LSUP_graph_add_iter (add_it, dest_spo);
-    LSUP_term_free (o);
-
-    o = LSUP_iriref_new ("lsup:AdminMetadata", LSUP_default_nsm);
-    LSUP_triple_init (dest_spo, s, p, o);
-    LSUP_graph_add_iter (add_it, dest_spo);
-    LSUP_term_free (o);
-
-    // Relationship between data graph and resource.
-    p = LSUP_iriref_new ("foaf:primaryTopic", LSUP_default_nsm);
-    o = rsrc_uri;
-    LSUP_triple_init (dest_spo, s, p, o);
-    LSUP_graph_add_iter (add_it, dest_spo);
-    LSUP_term_free (p);
-    LSUP_term_free (s); // === gr_uri
-
-    LSUP_graph_add_done (add_it);
-    add_it = NULL;
+    LSUP_Term
+            *meta_t = LSUP_iriref_new ("lsup:Metadata", LSUP_default_nsm),
+            *admin_meta_t = LSUP_iriref_new (
+                    "lsup:AdminMetadata", LSUP_default_nsm),
+            *topic_t = LSUP_iriref_new ("foaf:primaryTopic", LSUP_default_nsm);
+    LSUP_Triple *main_trp[] = {
+        LSUP_triple_new (admin_uri, LSR_rdf_t, meta_t),
+        LSUP_triple_new (admin_uri, LSR_rdf_t, admin_meta_t),
+        LSUP_triple_new (admin_uri, topic_t, rsrc_uri),
+        NULL
+    };
+
+    rc = LSUP_graph_add (rsrc->main_data, main_trp, NULL);
+
+    for (size_t i = 0; main_trp[i]; i++)
+        free (main_trp[i]);
+    LSUP_term_free (meta_t);
+    LSUP_term_free (admin_meta_t);
+    LSUP_term_free (topic_t);
 
     /* END adding graph metadata. */
 
 finally:
     LSUP_term_free (rsrc_uri);
-    LSUP_term_free (rdf_t);
+    LSUP_term_free (admin_uri);
 
     if (rc < 0) goto fail;
 
@@ -128,17 +105,29 @@ finally:
     return rc;
 
 fail:
-    LSUP_graph_add_done (add_it);
     LSR_desc_free (rsrc);
     *rsrc_p = NULL;
 
     return rc;
 }
 
+
+void LSR_desc_free (LSR_Desc *rsrc)
+{
+    size_t i = 0;
+    while (rsrc->user_data[i])
+        LSUP_graph_free (rsrc->user_data[i++]);
+    free (rsrc->user_data);
+
+    LSUP_graph_free (rsrc->admin_data);
+    LSUP_graph_free (rsrc->main_data);
+    free (rsrc);
+}
+
+
 LSUP_rc
 LSR_desc_store (const LSR_Desc *rsrc)
 {
-    // TODO Make atomic. Needs to implement transactions in backend.
     LSR_Desc *old_rsrc;
     PRCCK (LSR_desc_get (rsrc->id, &old_rsrc));
 
@@ -315,44 +304,41 @@ LSR_desc_user_data (const LSR_Desc *rsrc)
 }
 
 
-LSUP_Graph *
+LSUP_rc
 LSR_desc_update (
-        LSR_Desc *rsrc, LSUP_Graph *const *remove, LSUP_Graph *const *add)
-{ return desc_update (rsrc, remove, add, false); }
-
-
-void LSR_desc_free (LSR_Desc *rsrc)
-{
-    size_t i = 0;
-    while (rsrc->user_data[i])
-        LSUP_graph_free (rsrc->user_data[i++]);
-    free (rsrc->user_data);
-
-    LSUP_graph_free (rsrc->admin_data);
-    LSUP_graph_free (rsrc->main_data);
-    free (rsrc);
-}
-
-
-/** @brief Update a resource's user data.
- *
- * This is exposed externally by #LSR_desc_update(), in which it only differs
- * from the additional "new" parameter, which is used by #LSR_desc_new_multi()
- * to indicate that the resource being updated has just been created.
- */
-static LSUP_rc
-desc_update (
         LSR_Desc *rsrc, LSUP_Graph *const *rm_data,
-        LSUP_Graph *const *add_data, bool _new)
+        LSUP_Graph *const *add_data)
 {
     LSUP_rc rc = LSUP_NOACTION;
     LSUP_Term *rsrc_uri = LSR_id_to_urn (rsrc->id, NULL);
 
+    size_t ct;
+
+    /*
+     * REMOVE user data.
+     */
+
+    if (rm_data) {
+        // Count graphs to be removed.
+        ct = 0;
+        while (add_data[ct]) ct++;
+        for (size_t i = 0; i < ct; i++) {
+            LSUP_Term *gr_uri = LSUP_graph_uri (rm_data[i]);
+            // TODO remove ops.
+            // TODO if graph is empty after removal, remove it.
+            LSUP_term_free (gr_uri);
+        }
+    }
+
+    /*
+     * ADD user data.
+     */
+
     // Count graphs inserted and allocate space.
-    size_t ct = 0;
+    ct = 0;
     while (add_data[ct]) ct++;
     rsrc->user_data = calloc (sizeof (*rsrc->user_data), ct + 1);
-    if (UNLIKELY (! rsrc->user_data)) return NULL;
+    if (UNLIKELY (! rsrc->user_data)) return LSUP_MEM_ERR;
 
     LSUP_Triple spo_s;
     LSUP_Triple *spo = &spo_s;
@@ -383,6 +369,7 @@ desc_update (
 
         // Loop over graph triples.
         LSUP_Term *dest_s, *dest_p, *dest_o;
+        LSUP_Triple *src_spo;
         while (LSUP_graph_iter_next (lu_it, &src_spo) == LSUP_OK) {
             dest_s = LSUP_IS_IRI (src_spo->s) ?
                     LSUP_iriref_relative (rsrc_uri, src_spo->s) : src_spo->s;
@@ -412,7 +399,7 @@ desc_update (
                 if (tmp_rc != LSUP_OK) {
                     log_error (
                             "Referenced subject does not exist: %s",
-                            dest_s->data + strlen (LSR_RSRC_NS));
+                            dest_s->data);
                     rc = LSUP_VALUE_ERR;
                     goto finally;
                 }
@@ -434,7 +421,7 @@ desc_update (
             if (
                 LSUP_term_equals (
                     gr_uri, LSUP_iriref_absolute (rsrc_uri, spo->s))
-                && LSUP_term_equals (rdf_t, spo->p)
+                && LSUP_term_equals (LSR_rdf_t, spo->p)
             ) {
                 // If the resource is a special type, handle specific workflow.
                 if (hashmap_get (LSR_managed_types, spo->o)) {
@@ -461,8 +448,13 @@ loop_end:
             if (dest_o != src_spo->o) LSUP_term_free (dest_o);
         }
 
+        /*
+         * UPDATE graph metadata.
+         */
+
         // Add user graph metadata to default graph.
-        admin_add_it = LSUP_graph_add_init (rsrc->main_data);
+        LSUP_GraphIterator *admin_add_it = LSUP_graph_add_init (
+                rsrc->main_data);
         dest_s = gr_uri;
         dest_p = LSUP_iriref_new ("rdf:type", LSUP_default_nsm);
 
@@ -492,9 +484,10 @@ loop_end:
 
 finally:
     LSUP_term_free (rsrc_uri);
-    LSUP_graph_iter_free (lu_it);
-    LSUP_graph_add_done (add_it);
+    if (lu_it) LSUP_graph_iter_free (lu_it);
+    if (add_it) LSUP_graph_add_done (add_it);
 
+    return rc;
 }
 
 

+ 18 - 12
test/test_desc.c

@@ -21,19 +21,19 @@ test_desc_create()
         LSUP_iriref_new ("urn:o:20", NULL),
     };
 
-    LSUP_Triple trp1[] = {
-        {terms1[0], terms1[2], terms1[4]},
-        {terms1[0], terms1[3], terms1[4]},
-        {terms1[0], terms1[3], terms1[5]},
-        {terms1[1], terms1[2], terms1[4]},
-        {NULL}
+    LSUP_Triple *trp1[] = {
+        LSUP_triple_new (terms1[0], terms1[2], terms1[4]),
+        LSUP_triple_new (terms1[0], terms1[3], terms1[4]),
+        LSUP_triple_new (terms1[0], terms1[3], terms1[5]),
+        LSUP_triple_new (terms1[1], terms1[2], terms1[4]),
+        NULL
     };
-    LSUP_Triple trp2[] = {
-        {terms2[0], terms2[2], terms2[4]},
-        {terms2[0], terms2[3], terms2[4]},
-        {terms2[0], terms2[3], terms2[5]},
-        {terms2[1], terms2[2], terms2[4]},
-        {NULL}
+    LSUP_Triple *trp2[] = {
+        LSUP_triple_new (terms2[0], terms2[2], terms2[4]),
+        LSUP_triple_new (terms2[0], terms2[3], terms2[4]),
+        LSUP_triple_new (terms2[0], terms2[3], terms2[5]),
+        LSUP_triple_new (terms2[1], terms2[2], terms2[4]),
+        NULL
     };
 
     LSUP_Term *usr1_uri = LSUP_iriref_new ("#usr1", NULL);
@@ -42,12 +42,18 @@ test_desc_create()
     ASSERT (gr1, "Error creating graph!");
     EXPECT_PASS (LSUP_graph_add (gr1, trp1, NULL));
 
+    for (size_t i = 0; trp1[i]; i++)
+        free (trp1[i]);
+
     LSUP_Term *usr2_uri = LSUP_iriref_new ("#usr2", NULL);
     LSUP_Graph *gr2 = LSUP_graph_new (NULL, usr2_uri, NULL);
     LSUP_term_free (usr2_uri);
     ASSERT (gr2, "Error creating graph!");
     EXPECT_PASS (LSUP_graph_add (gr2, trp2, NULL));
 
+    for (size_t i = 0; trp2[i]; i++)
+        free (trp2[i]);
+
     LSUP_Graph *data[] = {gr1, gr2, NULL};
     LSR_Desc *rsrc;
     EXPECT_PASS (LSR_desc_new_multi (data, &rsrc));