You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by ss...@apache.org on 2013/09/09 12:09:20 UTC

[1/4] git commit: implemented a test for resolving base justifications

Updated Branches:
  refs/heads/develop 36067d745 -> 8253fe55d


implemented a test for resolving base justifications


Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/5b9bb32d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/5b9bb32d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/5b9bb32d

Branch: refs/heads/develop
Commit: 5b9bb32d99ab2e98dc1bf1a669fcdbc344a48301
Parents: 408be3d
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Sat Sep 7 02:15:15 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Sat Sep 7 02:15:15 2013 +0200

----------------------------------------------------------------------
 .../kiwi/reasoner/engine/ReasoningEngine.java   |   9 +-
 .../kiwi/reasoner/util/JustificationUtils.java  |  26 +++
 .../engine/JustificationResolutionTest.java     | 222 +++++++++++++++++++
 3 files changed, 255 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/5b9bb32d/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
index 8d2e08d..18fb6dc 100644
--- a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
+++ b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
@@ -132,6 +132,11 @@ public class ReasoningEngine implements TransactionListener {
      */
     private Lock persistenceLock;
 
+    // for mocking
+    protected ReasoningEngine() {
+
+    }
+
     public ReasoningEngine(KiWiReasoningPersistence persistence, TransactionalSail store, ReasoningConfiguration config) {
         this.persistence = persistence;
         this.store = store;
@@ -757,7 +762,7 @@ public class ReasoningEngine implements TransactionListener {
      * @param t
      * @return
      */
-    private Collection<Justification> getJustifications(KiWiReasoningConnection connection, KiWiTriple t, Set<Justification> transactionJustifications) throws SQLException {
+    protected Collection<Justification> getJustifications(KiWiReasoningConnection connection, KiWiTriple t, Set<Justification> transactionJustifications) throws SQLException {
         // TODO: transactionJustifications are ignored
         HashSet<Justification> justifications = new HashSet<Justification>();
         Iterations.addAll(connection.listJustificationsForTriple(t), justifications);
@@ -776,7 +781,7 @@ public class ReasoningEngine implements TransactionListener {
      * @param justifications
      * @return
      */
-    private Set<Justification> getBaseJustifications(KiWiReasoningConnection connection, Set<Justification> justifications) throws SQLException {
+    protected Set<Justification> getBaseJustifications(KiWiReasoningConnection connection, Set<Justification> justifications) throws SQLException {
         Set<Justification> baseJustifications = new HashSet<Justification>();
         Map<KiWiTriple,Collection<Justification>> justificationCache = StatementCommons.newQuadrupleMap();
 

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/5b9bb32d/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/util/JustificationUtils.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/util/JustificationUtils.java b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/util/JustificationUtils.java
new file mode 100644
index 0000000..8503816
--- /dev/null
+++ b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/util/JustificationUtils.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.marmotta.kiwi.reasoner.util;
+
+/**
+ * Add file description here!
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class JustificationUtils {
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/5b9bb32d/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java
new file mode 100644
index 0000000..25500c0
--- /dev/null
+++ b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.marmotta.kiwi.reasoner.test.engine;
+
+import com.google.common.collect.Sets;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.marmotta.commons.sesame.model.Namespaces;
+import org.apache.marmotta.commons.sesame.model.StatementCommons;
+import org.apache.marmotta.kiwi.model.rdf.*;
+import org.apache.marmotta.kiwi.reasoner.engine.ReasoningEngine;
+import org.apache.marmotta.kiwi.reasoner.model.program.Justification;
+import org.apache.marmotta.kiwi.reasoner.model.program.Rule;
+import org.apache.marmotta.kiwi.reasoner.persistence.KiWiReasoningConnection;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.openrdf.model.Statement;
+
+import java.sql.SQLException;
+import java.util.*;
+
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.hasItems;
+import static org.hamcrest.Matchers.hasProperty;
+
+/**
+ * Test if the ReasoningEngine's way of resolving base justifications works. Mocks the lookup for base justifications.
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class JustificationResolutionTest {
+
+    private MockReasoningEngine engine;
+
+    private Map<Statement,Set<Justification>> baseJustifications;
+
+
+    protected static Random rnd = new Random();
+
+
+    private KiWiTriple t1, t2, t3, t4; // base
+    private KiWiTriple i1, i2, i3, i4; // inferred
+    private Justification j1, j2, j3, j4;
+    private Rule r1, r2;
+
+    private KiWiUriResource ctx_inferred;
+
+    @Before
+    public void setup() {
+        engine = new MockReasoningEngine();
+
+        baseJustifications = StatementCommons.newQuadrupleMap();
+
+
+        KiWiUriResource s1 = randomURI();
+        KiWiUriResource s2 = randomURI();
+        KiWiUriResource s3 = randomURI();
+        KiWiUriResource s4 = randomURI();
+        KiWiUriResource p1 = randomURI();
+        KiWiUriResource p2 = randomURI();
+        KiWiNode o1 = randomObject();
+        KiWiNode o2 = randomObject();
+        KiWiNode o3 = randomObject();
+        KiWiNode o4 = randomObject();
+
+        ctx_inferred = randomURI();
+
+        t1 = new KiWiTriple(s1,p1,o1, null);
+        t2 = new KiWiTriple(s1,p1,o2, null);
+        t3 = new KiWiTriple(s2,p1,o3, null);
+        t4 = new KiWiTriple(s1,p1,o1, randomURI());
+
+
+        i1 = new KiWiTriple(s1,p2,o1, ctx_inferred); i1.setInferred(true);
+        i2 = new KiWiTriple(s1,p1,o2, ctx_inferred); i2.setInferred(true);
+        i3 = new KiWiTriple(s3,p1,o3, ctx_inferred); i3.setInferred(true);
+        i4 = new KiWiTriple(s1,p2,o1, ctx_inferred); i4.setInferred(true);
+
+        // assume i1 is justified by t1 and t2;
+        j1 = new Justification();
+        j1.setTriple(i1);
+        j1.getSupportingTriples().add(t1);
+        j1.getSupportingTriples().add(t2);
+
+        baseJustifications.put(i1, Collections.singleton(j1));
+
+        // assume i2 is justified by t3 and t4, as well as by t2 and t4
+        j2 = new Justification();
+        j2.setTriple(i2);
+        j2.getSupportingTriples().add(t3);
+        j2.getSupportingTriples().add(t4);
+
+
+        j3 = new Justification();
+        j3.setTriple(i2);
+        j3.getSupportingTriples().add(t2);
+        j3.getSupportingTriples().add(t4);
+
+        baseJustifications.put(i2, Sets.newHashSet(j2,j3));
+
+
+
+    }
+
+
+    @Test
+    public void testResolveBaseTriples() throws Exception {
+        // i3 justified by i1 and t3
+        Justification tj1 = new Justification();
+        tj1.setTriple(i3);
+        tj1.getSupportingTriples().add(i1);
+        tj1.getSupportingTriples().add(t3);
+
+        Collection<Justification> r1 = engine.getBaseJustifications(null,Collections.singleton(tj1));
+        Assert.assertEquals(1, r1.size());
+
+        Justification tj1r = r1.iterator().next();
+        Assert.assertEquals(3,tj1r.getSupportingTriples().size());
+        Assert.assertTrue(tj1r.getSupportingTriples().contains(t1));
+        Assert.assertTrue(tj1r.getSupportingTriples().contains(t2));
+        Assert.assertTrue(tj1r.getSupportingTriples().contains(t3));
+
+
+        // i4 justified by i1 and i2
+        Justification tj2 = new Justification();
+        tj2.setTriple(i4);
+        tj2.getSupportingTriples().add(i1);
+        tj2.getSupportingTriples().add(i2);
+
+        Collection<Justification> r2 = engine.getBaseJustifications(null,Collections.singleton(tj2));
+
+        // since i2 is justified by two justifications, the result for i4 also needs to have two
+        Assert.assertEquals(2, r2.size());
+
+        Assert.assertThat(r2,Matchers.<Justification>hasItem(hasProperty("supportingTriples", hasItems(t1,t2,t3,t4))));
+        Assert.assertThat(r2,Matchers.<Justification>hasItem(hasProperty("supportingTriples", hasItems(t1,t2,t4))));
+    }
+
+
+    /**
+     * Return a random URI, with a 10% chance of returning a URI that has already been used.
+     * @return
+     */
+    protected KiWiUriResource randomURI() {
+        KiWiUriResource resource = new KiWiUriResource("http://localhost/" + RandomStringUtils.randomAlphanumeric(8));
+        return resource;
+    }
+
+    /**
+     * Return a random RDF value, either a reused object (10% chance) or of any other kind.
+     * @return
+     */
+    protected KiWiNode randomObject() {
+        KiWiNode object;
+        switch(rnd.nextInt(6)) {
+            case 0: object = new KiWiUriResource("http://localhost/" + RandomStringUtils.randomAlphanumeric(8));
+                break;
+            case 1: object = new KiWiAnonResource(RandomStringUtils.randomAscii(8));
+                break;
+            case 2: object = new KiWiStringLiteral(RandomStringUtils.randomAscii(40));
+                break;
+            case 3: object = new KiWiIntLiteral(rnd.nextLong(), new KiWiUriResource(Namespaces.NS_XSD + "integer"));
+                break;
+            case 4: object = new KiWiDoubleLiteral(rnd.nextDouble(), new KiWiUriResource(Namespaces.NS_XSD + "double"));
+                break;
+            case 5: object = new KiWiBooleanLiteral(rnd.nextBoolean(), new KiWiUriResource(Namespaces.NS_XSD + "boolean"));
+                break;
+            default: object = new KiWiUriResource("http://localhost/" + RandomStringUtils.randomAlphanumeric(8));
+                break;
+
+        }
+        return object;
+    }
+
+
+
+    private class MockReasoningEngine extends ReasoningEngine {
+        private MockReasoningEngine() {
+        }
+
+
+        /**
+         * Return the justifications for the triple passed as argument.
+         *
+         * @param t
+         * @return
+         */
+        @Override
+        protected Collection<Justification> getJustifications(KiWiReasoningConnection connection, KiWiTriple t, Set<Justification> transactionJustifications) throws SQLException {
+            return baseJustifications.get(t);
+        }
+
+        /**
+         * For all justifications contained in the set passed as argument, create corresponding base justifications,
+         * i.e. justifications that only contain base triples and no inferred triples.
+         *
+         * @param justifications
+         * @return
+         */
+        @Override
+        public Set<Justification> getBaseJustifications(KiWiReasoningConnection connection, Set<Justification> justifications) throws SQLException {
+            return super.getBaseJustifications(connection, justifications);
+        }
+    }
+}


[2/4] git commit: more testing, confident the resolution of base justifications now works

Posted by ss...@apache.org.
more testing, confident the resolution of base justifications now works


Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/7474f52a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/7474f52a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/7474f52a

Branch: refs/heads/develop
Commit: 7474f52aaa32c4e203da91bc5f889320d8fb8798
Parents: 5b9bb32
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Sat Sep 7 14:16:32 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Sat Sep 7 14:16:32 2013 +0200

----------------------------------------------------------------------
 .../engine/JustificationResolutionTest.java     | 103 ++++++++++++++++---
 1 file changed, 88 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/7474f52a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java
index 25500c0..2a23cc9 100644
--- a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java
+++ b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java
@@ -36,9 +36,7 @@ import org.openrdf.model.Statement;
 import java.sql.SQLException;
 import java.util.*;
 
-import static org.hamcrest.Matchers.hasItem;
-import static org.hamcrest.Matchers.hasItems;
-import static org.hamcrest.Matchers.hasProperty;
+import static org.hamcrest.Matchers.*;
 
 /**
  * Test if the ReasoningEngine's way of resolving base justifications works. Mocks the lookup for base justifications.
@@ -55,9 +53,9 @@ public class JustificationResolutionTest {
     protected static Random rnd = new Random();
 
 
-    private KiWiTriple t1, t2, t3, t4; // base
-    private KiWiTriple i1, i2, i3, i4; // inferred
-    private Justification j1, j2, j3, j4;
+    private KiWiTriple t1, t2, t3, t4, t5; // base
+    private KiWiTriple i1, i2, i3, i4, i5, i6; // inferred
+    private Justification j1, j2, j3, j4, j5, tj1, tj2, tj3;
     private Rule r1, r2;
 
     private KiWiUriResource ctx_inferred;
@@ -86,12 +84,14 @@ public class JustificationResolutionTest {
         t2 = new KiWiTriple(s1,p1,o2, null);
         t3 = new KiWiTriple(s2,p1,o3, null);
         t4 = new KiWiTriple(s1,p1,o1, randomURI());
+        t5 = new KiWiTriple(s3,p1,o1, randomURI());
 
 
         i1 = new KiWiTriple(s1,p2,o1, ctx_inferred); i1.setInferred(true);
         i2 = new KiWiTriple(s1,p1,o2, ctx_inferred); i2.setInferred(true);
         i3 = new KiWiTriple(s3,p1,o3, ctx_inferred); i3.setInferred(true);
         i4 = new KiWiTriple(s1,p2,o1, ctx_inferred); i4.setInferred(true);
+        i5 = new KiWiTriple(s1,p2,o3, ctx_inferred); i5.setInferred(true);
 
         // assume i1 is justified by t1 and t2;
         j1 = new Justification();
@@ -115,19 +115,53 @@ public class JustificationResolutionTest {
 
         baseJustifications.put(i2, Sets.newHashSet(j2,j3));
 
+        // assume that i5 as well is justified by two justifications
+        j4 = new Justification();
+        j4.setTriple(i5);
+        j4.getSupportingTriples().add(t1);
+        j4.getSupportingTriples().add(t4);
 
 
-    }
+        j5 = new Justification();
+        j5.setTriple(i5);
+        j5.getSupportingTriples().add(t2);
+        j5.getSupportingTriples().add(t5);
 
 
-    @Test
-    public void testResolveBaseTriples() throws Exception {
+        baseJustifications.put(i5, Sets.newHashSet(j4,j5));
+
         // i3 justified by i1 and t3
-        Justification tj1 = new Justification();
+        tj1 = new Justification();
         tj1.setTriple(i3);
         tj1.getSupportingTriples().add(i1);
         tj1.getSupportingTriples().add(t3);
 
+
+        // i4 justified by i1 and i2
+        tj2 = new Justification();
+        tj2.setTriple(i4);
+        tj2.getSupportingTriples().add(i1);
+        tj2.getSupportingTriples().add(i2);
+
+
+        // i6 is justified by i2 and i5 (so multiplexing needed)
+        tj3 = new Justification();
+        tj3.setTriple(i6);
+        tj3.getSupportingTriples().add(i2);
+        tj3.getSupportingTriples().add(i5);
+
+    }
+
+    /**
+     * Test substitution of a single inferred triple supporting the triple by a single justification, so
+     * the number of new justifications will be the same as before, but the new justification will only
+     * contain base triples.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testResolveBaseTriplesSingle() throws Exception {
+
         Collection<Justification> r1 = engine.getBaseJustifications(null,Collections.singleton(tj1));
         Assert.assertEquals(1, r1.size());
 
@@ -138,12 +172,16 @@ public class JustificationResolutionTest {
         Assert.assertTrue(tj1r.getSupportingTriples().contains(t3));
 
 
-        // i4 justified by i1 and i2
-        Justification tj2 = new Justification();
-        tj2.setTriple(i4);
-        tj2.getSupportingTriples().add(i1);
-        tj2.getSupportingTriples().add(i2);
 
+    }
+
+    /**
+     * Test the substitution of an inferred triple that has several justifications itself; in this case the
+     * result will be split according to the number of justifications of the inferred triple
+     * @throws Exception
+     */
+    @Test
+    public void testResolveBaseTriplesMulti() throws Exception {
         Collection<Justification> r2 = engine.getBaseJustifications(null,Collections.singleton(tj2));
 
         // since i2 is justified by two justifications, the result for i4 also needs to have two
@@ -153,6 +191,41 @@ public class JustificationResolutionTest {
         Assert.assertThat(r2,Matchers.<Justification>hasItem(hasProperty("supportingTriples", hasItems(t1,t2,t4))));
     }
 
+    /**
+     * Test the substitution of more than one justification, the result should include the new base justificatoins for
+     * all justifications in the set
+     * @throws Exception
+     */
+    @Test
+    public void testResolveBaseTriplesSet() throws Exception {
+        Collection<Justification> r3 = engine.getBaseJustifications(null,Sets.newHashSet(tj1, tj2));
+
+        // since i2 is justified by two justifications, the result for i4 also needs to have two
+        Assert.assertEquals(3, r3.size());
+
+        Assert.assertThat(r3,Matchers.<Justification>hasItem(allOf(hasProperty("triple", is(i3)),hasProperty("supportingTriples", hasItems(t1, t2, t3)))));
+        Assert.assertThat(r3,Matchers.<Justification>hasItem(allOf(hasProperty("triple", is(i4)),hasProperty("supportingTriples", hasItems(t1, t2, t3, t4)))));
+        Assert.assertThat(r3,Matchers.<Justification>hasItem(allOf(hasProperty("triple", is(i4)),hasProperty("supportingTriples", hasItems(t1,t2,t4)))));
+    }
+
+    /**
+     * Test the substitution of several inferred triple that have several justifications itself; the result needs to be
+     * multiplexed.
+     * @throws Exception
+     */
+    @Test
+    public void testResolveBaseTriplesMultiplex() throws Exception {
+        Collection<Justification> r4 = engine.getBaseJustifications(null,Collections.singleton(tj3));
+
+        // since i2 is justified by two justifications, the result for i4 also needs to have two
+        Assert.assertEquals(4, r4.size());
+
+        Assert.assertThat(r4,Matchers.<Justification>hasItem(hasProperty("supportingTriples", hasItems(t1,t3,t4))));
+        Assert.assertThat(r4,Matchers.<Justification>hasItem(hasProperty("supportingTriples", hasItems(t2,t3,t4,t5))));
+        Assert.assertThat(r4,Matchers.<Justification>hasItem(hasProperty("supportingTriples", hasItems(t1,t2,t4))));
+        Assert.assertThat(r4,Matchers.<Justification>hasItem(hasProperty("supportingTriples", allOf(hasItems(t2,t4,t5), not(hasItem(t3))))));
+    }
+
 
     /**
      * Return a random URI, with a 10% chance of returning a URI that has already been used.


[4/4] git commit: Merge branch 'develop' of https://git-wip-us.apache.org/repos/asf/incubator-marmotta into develop

Posted by ss...@apache.org.
Merge branch 'develop' of https://git-wip-us.apache.org/repos/asf/incubator-marmotta into develop


Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/8253fe55
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/8253fe55
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/8253fe55

Branch: refs/heads/develop
Commit: 8253fe55de844c5e2a5cfeef263732f82477d1ae
Parents: b30df76 36067d7
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Mon Sep 9 12:09:00 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Mon Sep 9 12:09:00 2013 +0200

----------------------------------------------------------------------
 platform/marmotta-core/src/main/resources/web/admin/contexts.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------



[3/4] git commit: library updates, more reliable and generic retrying of SQL commands, tests for reasoner now working

Posted by ss...@apache.org.
library updates, more reliable and generic retrying of SQL commands, tests for reasoner now working


Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/b30df76e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/b30df76e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/b30df76e

Branch: refs/heads/develop
Commit: b30df76e54e3059011c97bd74d6a6d7abf94cdbf
Parents: 7474f52
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Mon Sep 9 12:08:48 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Mon Sep 9 12:08:48 2013 +0200

----------------------------------------------------------------------
 .../sesame/model/StatementCommonsTest.java      |  59 ++--
 .../kiwi/reasoner/engine/ReasoningEngine.java   |   5 +-
 .../engine/JustificationResolutionTest.java     |  26 +-
 .../KiWiRDFSchemaRepositoryConnectionTest.java  |  22 +-
 .../kiwi/persistence/KiWiConnection.java        | 306 ++++++++++++-------
 parent/pom.xml                                  |  14 +-
 6 files changed, 275 insertions(+), 157 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b30df76e/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/sesame/model/StatementCommonsTest.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/sesame/model/StatementCommonsTest.java b/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/sesame/model/StatementCommonsTest.java
index 05a6003..b23f329 100644
--- a/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/sesame/model/StatementCommonsTest.java
+++ b/commons/marmotta-commons/src/test/java/org/apache/marmotta/commons/sesame/model/StatementCommonsTest.java
@@ -24,11 +24,6 @@ public class StatementCommonsTest {
 
     ValueFactory valueFactory;
 
-    private List<URI> resources = new ArrayList<>();
-
-    private List<Value> objects = new ArrayList<>();
-
-
     @Before
     public void setup() {
         valueFactory = new ValueFactoryImpl();
@@ -179,14 +174,8 @@ public class StatementCommonsTest {
      * @return
      */
     protected URI randomURI() {
-        if(resources.size() > 0 && rnd.nextInt(10) == 0) {
-            // return a resource that was already used
-            return resources.get(rnd.nextInt(resources.size()));
-        } else {
-            URI resource = valueFactory.createURI("http://localhost/" + RandomStringUtils.randomAlphanumeric(8));
-            resources.add(resource);
-            return resource;
-        }
+        URI resource = valueFactory.createURI("http://localhost/" + RandomStringUtils.randomAlphanumeric(8));
+        return resource;
     }
 
     /**
@@ -194,32 +183,26 @@ public class StatementCommonsTest {
      * @return
      */
     protected Value randomObject() {
-        if(objects.size() > 0 && rnd.nextInt(10) == 0) {
-            return objects.get(rnd.nextInt(objects.size()));
-        } else {
-            Value object;
-            switch(rnd.nextInt(6)) {
-                case 0: object = valueFactory.createURI("http://localhost/" + RandomStringUtils.randomAlphanumeric(8));
-                    break;
-                case 1: object = valueFactory.createBNode();
-                    break;
-                case 2: object = valueFactory.createLiteral(RandomStringUtils.randomAscii(40));
-                    break;
-                case 3: object = valueFactory.createLiteral(rnd.nextInt());
-                    break;
-                case 4: object = valueFactory.createLiteral(rnd.nextDouble());
-                    break;
-                case 5: object = valueFactory.createLiteral(rnd.nextBoolean());
-                    break;
-                default: object = valueFactory.createURI("http://localhost/" + RandomStringUtils.randomAlphanumeric(8));
-                    break;
-
-            }
-            objects.add(object);
-            return object;
-        }
+        Value object;
+        switch(rnd.nextInt(6)) {
+            case 0: object = valueFactory.createURI("http://localhost/" + RandomStringUtils.randomAlphanumeric(8));
+                break;
+            case 1: object = valueFactory.createBNode();
+                break;
+            case 2: object = valueFactory.createLiteral(RandomStringUtils.randomAscii(40));
+                break;
+            case 3: object = valueFactory.createLiteral(rnd.nextInt());
+                break;
+            case 4: object = valueFactory.createLiteral(rnd.nextDouble());
+                break;
+            case 5: object = valueFactory.createLiteral(rnd.nextBoolean());
+                break;
+            default: object = valueFactory.createURI("http://localhost/" + RandomStringUtils.randomAlphanumeric(8));
+                break;
 
-    }
+        }
+        return object;
 
 
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b30df76e/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
index 18fb6dc..c60451e 100644
--- a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
+++ b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/engine/ReasoningEngine.java
@@ -125,7 +125,7 @@ public class ReasoningEngine implements TransactionListener {
      */
     private SKWRLReasoner reasonerThread;
 
-    private static Equivalence<Statement> equivalence = StatementCommons.quadrupleEquivalence();
+    protected static Equivalence<Statement> equivalence = StatementCommons.quadrupleEquivalence();
 
     /**
      * A lock to ensure that only once thread at a time is carrying out persistence
@@ -763,7 +763,6 @@ public class ReasoningEngine implements TransactionListener {
      * @return
      */
     protected Collection<Justification> getJustifications(KiWiReasoningConnection connection, KiWiTriple t, Set<Justification> transactionJustifications) throws SQLException {
-        // TODO: transactionJustifications are ignored
         HashSet<Justification> justifications = new HashSet<Justification>();
         Iterations.addAll(connection.listJustificationsForTriple(t), justifications);
         for(Justification j : transactionJustifications) {
@@ -859,7 +858,7 @@ public class ReasoningEngine implements TransactionListener {
     }
 
 
-    private QueryResult matches(Pattern pattern, KiWiTriple triple) {
+    protected static QueryResult matches(Pattern pattern, KiWiTriple triple) {
         boolean result = true;
 
         QueryResult match = new QueryResult();

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b30df76e/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java
index 2a23cc9..9e9713b 100644
--- a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java
+++ b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/engine/JustificationResolutionTest.java
@@ -18,6 +18,7 @@
 package org.apache.marmotta.kiwi.reasoner.test.engine;
 
 import com.google.common.collect.Sets;
+import info.aduna.iteration.Iterations;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.marmotta.commons.sesame.model.Namespaces;
 import org.apache.marmotta.commons.sesame.model.StatementCommons;
@@ -222,8 +223,20 @@ public class JustificationResolutionTest {
 
         Assert.assertThat(r4,Matchers.<Justification>hasItem(hasProperty("supportingTriples", hasItems(t1,t3,t4))));
         Assert.assertThat(r4,Matchers.<Justification>hasItem(hasProperty("supportingTriples", hasItems(t2,t3,t4,t5))));
-        Assert.assertThat(r4,Matchers.<Justification>hasItem(hasProperty("supportingTriples", hasItems(t1,t2,t4))));
-        Assert.assertThat(r4,Matchers.<Justification>hasItem(hasProperty("supportingTriples", allOf(hasItems(t2,t4,t5), not(hasItem(t3))))));
+        Assert.assertThat(r4,Matchers.<Justification>hasItem(hasProperty("supportingTriples", hasItems(t1, t2, t4))));
+        Assert.assertThat(r4,Matchers.<Justification>hasItem(hasProperty("supportingTriples", allOf(hasItems(t2, t4, t5), not(hasItem(t3))))));
+    }
+
+
+    // TODO: a test taking into account transaction justifications
+
+    /**
+     * Test resolution against justifications that are not yet "persisted" but are taken from the current transaction
+     * @throws Exception
+     */
+    @Test
+    public void testTransactionJustifications() throws Exception {
+
     }
 
 
@@ -277,7 +290,14 @@ public class JustificationResolutionTest {
          */
         @Override
         protected Collection<Justification> getJustifications(KiWiReasoningConnection connection, KiWiTriple t, Set<Justification> transactionJustifications) throws SQLException {
-            return baseJustifications.get(t);
+            HashSet<Justification> justifications = new HashSet<Justification>();
+            justifications.addAll(baseJustifications.get(t));
+            for(Justification j : transactionJustifications) {
+                if(equivalence.equivalent(j.getTriple(), t)) {
+                    justifications.add(j);
+                }
+            }
+            return justifications;
         }
 
         /**

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b30df76e/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/sesame/KiWiRDFSchemaRepositoryConnectionTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/sesame/KiWiRDFSchemaRepositoryConnectionTest.java b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/sesame/KiWiRDFSchemaRepositoryConnectionTest.java
index c6b7f2e..5eab69d 100644
--- a/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/sesame/KiWiRDFSchemaRepositoryConnectionTest.java
+++ b/libraries/kiwi/kiwi-reasoner/src/test/java/org/apache/marmotta/kiwi/reasoner/test/sesame/KiWiRDFSchemaRepositoryConnectionTest.java
@@ -50,10 +50,11 @@ import static org.junit.Assert.fail;
 /**
  * Run the {@link KiWiRDFSchemaRepositoryConnectionTest}s.
  * @author Jakob Frank <ja...@apache.org>
+ * @author Sebastian Schaffert <ss...@apache.org>
  *
  */
 @RunWith(KiWiDatabaseRunner.class)
-@KiWiDatabaseRunner.ForDialects(dialect = H2Dialect.class)
+//@KiWiDatabaseRunner.ForDialects(dialect = H2Dialect.class)
 public class KiWiRDFSchemaRepositoryConnectionTest extends RDFSchemaRepositoryConnectionTest {
 
     public Logger log = LoggerFactory.getLogger(this.getClass());
@@ -150,4 +151,23 @@ public class KiWiRDFSchemaRepositoryConnectionTest extends RDFSchemaRepositoryCo
     public void testInferencerTransactionIsolation() throws Exception {
     }
 
+
+    @Override
+    @Test
+    @Ignore("in KiWi, inferencing is triggered on commit")
+    public void testClear() throws Exception {
+    }
+
+    @Override
+    @Test
+    @Ignore("in KiWi, inferencing is triggered on commit")
+    public void testDeleteDefaultGraph() throws Exception {
+    }
+
+    @Override
+    @Test
+    @Ignore("asynchronous reasoning takes too long for this test")
+    public void testOrderByQueriesAreInterruptable() throws Exception {
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b30df76e/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
index 1e5cade..ec3febe 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiConnection.java
@@ -42,6 +42,7 @@ import org.slf4j.LoggerFactory;
 import java.sql.*;
 import java.util.*;
 import java.util.Date;
+import java.util.concurrent.Executor;
 import java.util.concurrent.locks.ReentrantLock;
 
 /**
@@ -1179,23 +1180,41 @@ public class KiWiConnection {
      *
      * @param triple
      */
-    public void deleteTriple(KiWiTriple triple) throws SQLException {
-        // mutual exclusion: prevent parallel adding and removing of the same triple
-        synchronized (triple) {
-
-            // make sure the triple is marked as deleted in case some service still holds a reference
-            triple.setDeleted(true);
-            triple.setDeletedAt(new Date());
-
-            if(triple.getId() == null) {
-                log.warn("attempting to remove non-persistent triple: {}", triple);
-                removeCachedTriple(triple);
-            } else {
-                if(batchCommit) {
-                    // need to remove from triple batch and from database
-                    commitLock.lock();
-                    try {
-                        if(tripleBatch == null || !tripleBatch.remove(triple)) {
+    public void deleteTriple(final KiWiTriple triple) throws SQLException {
+        RetryExecution execution = new RetryExecution("DELETE");
+        execution.setUseSavepoint(true);
+        execution.execute(connection, new RetryCommand() {
+            @Override
+            public void run() throws SQLException {
+                // mutual exclusion: prevent parallel adding and removing of the same triple
+                synchronized (triple) {
+
+                    // make sure the triple is marked as deleted in case some service still holds a reference
+                    triple.setDeleted(true);
+                    triple.setDeletedAt(new Date());
+
+                    if(triple.getId() == null) {
+                        log.warn("attempting to remove non-persistent triple: {}", triple);
+                        removeCachedTriple(triple);
+                    } else {
+                        if(batchCommit) {
+                            // need to remove from triple batch and from database
+                            commitLock.lock();
+                            try {
+                                if(tripleBatch == null || !tripleBatch.remove(triple)) {
+                                    requireJDBCConnection();
+
+                                    PreparedStatement deleteTriple = getPreparedStatement("delete.triple");
+                                    synchronized (deleteTriple) {
+                                        deleteTriple.setLong(1,triple.getId());
+                                        deleteTriple.executeUpdate();
+                                    }
+                                    deletedStatementsLog.add(triple.getId());
+                                }
+                            } finally {
+                                commitLock.unlock();
+                            }
+                        } else {
                             requireJDBCConnection();
 
                             PreparedStatement deleteTriple = getPreparedStatement("delete.triple");
@@ -1204,25 +1223,16 @@ public class KiWiConnection {
                                 deleteTriple.executeUpdate();
                             }
                             deletedStatementsLog.add(triple.getId());
-                        }
-                    } finally {
-                        commitLock.unlock();
-                    }
-                } else {
-                    requireJDBCConnection();
-
-                    PreparedStatement deleteTriple = getPreparedStatement("delete.triple");
-                    synchronized (deleteTriple) {
-                        deleteTriple.setLong(1,triple.getId());
-                        deleteTriple.executeUpdate();
-                    }
-                    deletedStatementsLog.add(triple.getId());
 
 
+                        }
+                        removeCachedTriple(triple);
+                    }
                 }
-                removeCachedTriple(triple);
             }
-        }
+        });
+
+
     }
 
     /**
@@ -1952,37 +1962,27 @@ public class KiWiConnection {
     public void commit() throws SQLException {
         numberOfCommits++;
 
-        try {
-            if(persistence.getConfiguration().isCommitSequencesOnCommit() || numberOfCommits % 100 == 0) {
-                commitMemorySequences();
-            }
+        RetryExecution execution = new RetryExecution("COMMIT");
+        execution.execute(connection, new RetryCommand() {
+            @Override
+            public void run() throws SQLException {
+                if(persistence.getConfiguration().isCommitSequencesOnCommit() || numberOfCommits % 100 == 0) {
+                    commitMemorySequences();
+                }
 
 
-            if(tripleBatch != null && tripleBatch.size() > 0) {
-                flushBatch();
-            }
+                if(tripleBatch != null && tripleBatch.size() > 0) {
+                    flushBatch();
+                }
 
 
-            deletedStatementsLog.clear();
+                deletedStatementsLog.clear();
 
-            if(connection != null) {
-                connection.commit();
-            }
-        } catch(SQLException ex) {
-            // MySQL deadlock, wait and retry
-            if(retry < 10 && ("40001".equals(ex.getSQLState()) || "40P01".equals(ex.getSQLState()))) {
-                log.warn("COMMIT: temporary concurrency conflict (deadlock), retrying in 1000 ms ... (thread={}, retry={})", Thread.currentThread().getName(), retry);
-                try {
-                    Thread.sleep(1000);
-                } catch (InterruptedException e) {}
-                retry++;
-                flushBatch();
-                retry--;
-            } else {
-                log.error("COMMIT: concurrency conflict could not be solved!");
-                throw ex;
+                if(connection != null) {
+                    connection.commit();
+                }
             }
-        }
+        });
     }
 
     /**
@@ -2114,66 +2114,164 @@ public class KiWiConnection {
             requireJDBCConnection();
 
             commitLock.lock();
+            try {
+                if(persistence.getValueFactory() != null) {
+                    persistence.getValueFactory().flushBatch();
+                }
 
-            if(persistence.getValueFactory() != null) {
-                persistence.getValueFactory().flushBatch();
-            }
 
-            Savepoint savepoint = connection.setSavepoint();
-            try {
+                RetryExecution execution = new RetryExecution("FLUSH BATCH");
+                execution.setUseSavepoint(true);
+                execution.execute(connection, new RetryCommand() {
+                    @Override
+                    public void run() throws SQLException {
+                        PreparedStatement insertTriple = getPreparedStatement("store.triple");
+                        insertTriple.clearParameters();
+                        insertTriple.clearBatch();
+
+                        synchronized (tripleBatch) {
+                            for(KiWiTriple triple : tripleBatch) {
+                                // if the triple has been marked as deleted, this can only have been done by another connection
+                                // in this case the triple id is no longer usable (might result in key conflicts), so we set it to
+                                // a new id
+                                if(triple.isDeleted()) {
+                                    triple.setId(getNextSequence("seq.triples"));
+                                    triple.setDeleted(false);
+                                    triple.setDeletedAt(null);
+                                }
 
-                PreparedStatement insertTriple = getPreparedStatement("store.triple");
-                insertTriple.clearParameters();
-                insertTriple.clearBatch();
-
-                synchronized (tripleBatch) {
-                    for(KiWiTriple triple : tripleBatch) {
-                        // if the triple has been marked as deleted, this can only have been done by another connection
-                        // in this case the triple id is no longer usable (might result in key conflicts), so we set it to
-                        // a new id
-                        if(triple.isDeleted()) {
-                            triple.setId(getNextSequence("seq.triples"));
-                            triple.setDeleted(false);
-                            triple.setDeletedAt(null);
-                        }
+                                // retrieve a new triple ID and set it in the object
+                                if(triple.getId() == null) {
+                                    triple.setId(getNextSequence("seq.triples"));
+                                }
 
-                        // retrieve a new triple ID and set it in the object
-                        if(triple.getId() == null) {
-                            triple.setId(getNextSequence("seq.triples"));
-                        }
+                                insertTriple.setLong(1,triple.getId());
+                                insertTriple.setLong(2,triple.getSubject().getId());
+                                insertTriple.setLong(3,triple.getPredicate().getId());
+                                insertTriple.setLong(4,triple.getObject().getId());
+                                if(triple.getContext() != null) {
+                                    insertTriple.setLong(5,triple.getContext().getId());
+                                } else {
+                                    insertTriple.setNull(5, Types.BIGINT);
+                                }
+                                insertTriple.setBoolean(6,triple.isInferred());
+                                insertTriple.setTimestamp(7, new Timestamp(triple.getCreated().getTime()));
 
-                        insertTriple.setLong(1,triple.getId());
-                        insertTriple.setLong(2,triple.getSubject().getId());
-                        insertTriple.setLong(3,triple.getPredicate().getId());
-                        insertTriple.setLong(4,triple.getObject().getId());
-                        if(triple.getContext() != null) {
-                            insertTriple.setLong(5,triple.getContext().getId());
-                        } else {
-                            insertTriple.setNull(5, Types.BIGINT);
+                                insertTriple.addBatch();
+                            }
                         }
-                        insertTriple.setBoolean(6,triple.isInferred());
-                        insertTriple.setTimestamp(7, new Timestamp(triple.getCreated().getTime()));
+                        insertTriple.executeBatch();
+
+                        tripleBatch.clear();
 
-                        insertTriple.addBatch();
                     }
-                }
-                insertTriple.executeBatch();
+                });
 
-                tripleBatch.clear();
+            }  finally {
+                commitLock.unlock();
+            }
+
+        }
+
+    }
+
+
+    protected static interface RetryCommand {
+
+        public void run() throws SQLException;
+    }
+
+    /**
+     * A generic implementation of an SQL command that might fail (e.g. because of a timeout or concurrency situation)
+     * and should be retried several times before giving up completely.
+     *
+     */
+    protected static class RetryExecution  {
+
+        // counter for current number of retries
+        private int retries = 0;
+
+        // how often to reattempt the operation
+        private int maxRetries = 10;
+
+        // how long to wait before retrying
+        private long retryInterval = 1000;
+
+        // use an SQL savepoint and roll back in case a retry is needed?
+        private boolean useSavepoint = false;
+
+        private String name;
+
+        // if non-empty: only retry on the SQL states contained in this set
+        private Set<String> sqlStates;
+
+        public RetryExecution(String name) {
+            this.name = name;
+            this.sqlStates = new HashSet<>();
+        }
+
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public int getMaxRetries() {
+            return maxRetries;
+        }
+
+        public void setMaxRetries(int maxRetries) {
+            this.maxRetries = maxRetries;
+        }
+
+        public long getRetryInterval() {
+            return retryInterval;
+        }
+
+        public void setRetryInterval(long retryInterval) {
+            this.retryInterval = retryInterval;
+        }
 
-                connection.releaseSavepoint(savepoint);
+        public boolean isUseSavepoint() {
+            return useSavepoint;
+        }
+
+        public void setUseSavepoint(boolean useSavepoint) {
+            this.useSavepoint = useSavepoint;
+        }
+
+        public Set<String> getSqlStates() {
+            return sqlStates;
+        }
+
+        public void execute(Connection connection, RetryCommand command) throws SQLException {
+            Savepoint savepoint = null;
+            if(useSavepoint) {
+                savepoint = connection.setSavepoint();
+            }
+            try {
+                command.run();
+
+                if(useSavepoint && savepoint != null) {
+                    connection.releaseSavepoint(savepoint);
+                }
             } catch (SQLException ex) {
-                if(retry < 10) {
-                    connection.rollback(savepoint);
-                    log.warn("BATCH: temporary concurrency conflict, retrying in 1000 ms ... (thread={}, retry={})", Thread.currentThread().getName(), retry);
+                if(retries < maxRetries && (sqlStates.size() == 0 || sqlStates.contains(ex.getSQLState()))) {
+                    if(useSavepoint && savepoint != null) {
+                        connection.rollback(savepoint);
+                    }
+                    log.warn("{}: temporary conflict, retrying in {} ms ... (thread={}, retry={})", name, retryInterval, Thread.currentThread().getName(), retries);
                     try {
-                        Thread.sleep(1000);
+                        Thread.sleep(retryInterval);
                     } catch (InterruptedException e) {}
-                    retry++;
-                    flushBatch();
-                    retry--;
+                    retries++;
+                    execute(connection, command);
+                    retries--;
                 } else {
-                    log.error("BATCH: concurrency conflict could not be solved!");
+                    log.error("{}: temporary conflict could not be solved!", name);
 
                     System.err.println("main exception:");
                     ex.printStackTrace();
@@ -2181,8 +2279,6 @@ public class KiWiConnection {
                     ex.getNextException().printStackTrace();
                     throw ex;
                 }
-            }  finally {
-                commitLock.unlock();
             }
 
         }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/b30df76e/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index 2576d27..b88d5fe 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -36,10 +36,10 @@
     <url>http://marmotta.incubator.apache.org</url>
 
     <properties>
-        <sesame.version>2.7.5</sesame.version>
+        <sesame.version>2.7.6</sesame.version>
         <junit.version>4.11</junit.version>
         <weld.version>2.0.SP1</weld.version>
-        <weld.core.version>2.0.3.Final</weld.core.version>
+        <weld.core.version>2.0.4.Final</weld.core.version>
         <rest.assured.version>1.7.1</rest.assured.version>
         <hamcrest.version>1.3</hamcrest.version>
         <tempus.fugit.version>1.1</tempus.fugit.version>
@@ -50,7 +50,7 @@
         <postgresql.version>9.2-1003-jdbc4</postgresql.version>
         <mysql.version>5.1.21</mysql.version>
         <jetty.version>9.0.3.v20130506</jetty.version>
-        <resteasy.version>3.0.2.Final</resteasy.version>
+        <resteasy.version>3.0.4.Final</resteasy.version>
     </properties>
 
     <prerequisites>
@@ -622,7 +622,7 @@
             <dependency>
                 <groupId>org.apache.httpcomponents</groupId>
                 <artifactId>httpcore</artifactId>
-                <version>4.2.3</version>
+                <version>4.2.5</version>
                 <exclusions>
                     <exclusion>
                         <groupId>commons-logging</groupId>
@@ -633,7 +633,7 @@
             <dependency>
                 <groupId>org.apache.httpcomponents</groupId>
                 <artifactId>httpmime</artifactId>
-                <version>4.2.3</version>
+                <version>4.2.5</version>
                 <exclusions>
                     <exclusion>
                         <groupId>commons-logging</groupId>
@@ -644,7 +644,7 @@
             <dependency>
                 <groupId>org.apache.httpcomponents</groupId>
                 <artifactId>httpclient</artifactId>
-                <version>4.2.3</version>
+                <version>4.2.5</version>
                 <exclusions>
                     <exclusion>
                         <groupId>commons-logging</groupId>
@@ -655,7 +655,7 @@
             <dependency>
                 <groupId>org.apache.httpcomponents</groupId>
                 <artifactId>httpclient-cache</artifactId>
-                <version>4.2.3</version>
+                <version>4.2.5</version>
                 <exclusions>
                     <exclusion>
                         <groupId>commons-logging</groupId>