|
@@ -77,8 +77,8 @@ LSUP_graph_get_txn (
|
|
|
|
|
|
size_t _ct = 0;
|
|
|
while (store->sif->lu_next_fn (it, sspo, NULL) == LSUP_OK) {
|
|
|
- // TODO This is inefficient, it's deserializing a buffer triple that
|
|
|
- // will be re-serialized by LSUP_graph_add_iter.
|
|
|
+ // This is deserializing a buffer triple that will be re-serialized by
|
|
|
+ // LSUP_graph_add_iter. But it's necessary to relativize URIs.
|
|
|
LSUP_Triple *spo = LSUP_triple_new_from_btriple (sspo);
|
|
|
LSUP_graph_add_iter (add_it, spo);
|
|
|
LSUP_triple_free (spo);
|
|
@@ -141,24 +141,48 @@ LSUP_graph_bool_op_txn (
|
|
|
// Handle transactions for graphs possibly in different storage back ends.
|
|
|
void
|
|
|
*lu1_txn = NULL,
|
|
|
- *lu2_txn = NULL;
|
|
|
+ *lu2_txn = NULL,
|
|
|
+ *res_txn = NULL;
|
|
|
+ // Whether gr1 or gr2 txn will be open independently from res txn.
|
|
|
+ bool
|
|
|
+ open_txn1 = false,
|
|
|
+ open_txn2 = false;
|
|
|
|
|
|
add_it = res->store->sif->add_init_fn (res->store->data, res_sc, txn);
|
|
|
|
|
|
- // If either source graph is in the same store as the destination and has
|
|
|
- // an open transaction, reuse that transaction. A new reader cannot be
|
|
|
- // opened in LMDB while a writer is open already.
|
|
|
- if (
|
|
|
- gr1->store->sif->features & LSUP_STORE_TXN
|
|
|
- && gr1->store == res->store)
|
|
|
- lu1_txn = res->store->sif->iter_txn_fn (add_it);
|
|
|
+ if (res->store->sif->features & LSUP_STORE_TXN)
|
|
|
+ res_txn = res->store->sif->iter_txn_fn (add_it);
|
|
|
+
|
|
|
+ /* If either source graph is in the same store as the destination and has
|
|
|
+ * an open transaction, reuse that transaction. A new reader cannot be
|
|
|
+ * opened in LMDB while a writer is open already.
|
|
|
+ */
|
|
|
+ // Handle gr1 transaction.
|
|
|
if (gr1->store->sif->features & LSUP_STORE_TXN) {
|
|
|
- if (gr1->store == res->store)
|
|
|
- lu2_txn = res->store->sif->iter_txn_fn (add_it);
|
|
|
- else if (gr2->store == gr1->store)
|
|
|
- lu2_txn = lu1_txn;
|
|
|
+ if (gr1->store == res->store) lu1_txn = res_txn;
|
|
|
+ // FIXME: MDB_RDONLY is implementation-specific and doesn't belong here.
|
|
|
+ else {
|
|
|
+ CHECK (gr1->store->sif->txn_begin_fn (
|
|
|
+ gr1->store->data, MDB_RDONLY, &lu1_txn), fail);
|
|
|
+ open_txn1 = true;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ // Handle gr2 transaction.
|
|
|
+ if (gr2->store->sif->features & LSUP_STORE_TXN) {
|
|
|
+ if (gr2->store == res->store) lu2_txn = res_txn;
|
|
|
+ else if (gr2->store == gr1->store) lu2_txn = lu1_txn;
|
|
|
+ // FIXME: see above.
|
|
|
+ else {
|
|
|
+ CHECK (gr2->store->sif->txn_begin_fn (
|
|
|
+ gr2->store->data, MDB_RDONLY, &lu2_txn), fail);
|
|
|
+ open_txn2 = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ LOG_TRACE (
|
|
|
+ "lu1_txn: %p ; lu2_txn: %p ; res_txn: %p",
|
|
|
+ lu1_txn, lu2_txn, res_txn);
|
|
|
+
|
|
|
/* BEGIN XOR block. */
|
|
|
|
|
|
if (op == LSUP_BOOL_XOR) {
|
|
@@ -201,6 +225,9 @@ LSUP_graph_bool_op_txn (
|
|
|
}
|
|
|
gr1->store->sif->lu_free_fn (lu1_it);
|
|
|
|
|
|
+ if (open_txn1) gr1->store->sif->txn_commit_fn (lu1_txn);
|
|
|
+ if (open_txn2) gr2->store->sif->txn_commit_fn (lu2_txn);
|
|
|
+
|
|
|
res->store->sif->add_done_fn (add_it);
|
|
|
LSUP_btriple_free (sspo);
|
|
|
LSUP_buffer_free (res_sc);
|
|
@@ -212,6 +239,8 @@ LSUP_graph_bool_op_txn (
|
|
|
return rc;
|
|
|
|
|
|
fail:
|
|
|
+ if (lu1_txn) gr1->store->sif->txn_abort_fn (lu1_txn);
|
|
|
+ if (lu2_txn) gr2->store->sif->txn_abort_fn (lu2_txn);
|
|
|
LSUP_graph_free (res);
|
|
|
return rc;
|
|
|
}
|
|
@@ -626,7 +655,10 @@ LSUP_graph_print (LSUP_Graph *gr)
|
|
|
{
|
|
|
size_t ct;
|
|
|
LSUP_GraphIterator *it = LSUP_graph_lookup (gr, NULL, NULL, NULL, &ct);
|
|
|
- if (UNLIKELY (!it)) log_error ("Could not print graph contents.");
|
|
|
+ if (UNLIKELY (!it)) {
|
|
|
+ log_error ("Could not inspect graph for printing.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
printf ("*** Graph %s (%zu triples):\n\n", gr->uri->data, ct);
|
|
|
|