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/07/22 12:56:06 UTC

[1/7] git commit: trying to prevent a potential concurrency problem

Updated Branches:
  refs/heads/develop 3af07e3d1 -> a6a441011


trying to prevent a potential concurrency problem


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

Branch: refs/heads/develop
Commit: 1b85aa450dc39da067a6317ddecb2d329be4ba16
Parents: 64ba028
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Fri Jul 19 11:02:07 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Fri Jul 19 11:02:07 2013 +0200

----------------------------------------------------------------------
 .../kiwi/persistence/KiWiConnection.java        |  4 +-
 .../kiwi/persistence/KiWiPersistence.java       | 80 +++++++++++++-------
 2 files changed, 53 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/1b85aa45/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 cf95598..2b62024 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
@@ -1673,8 +1673,8 @@ public class KiWiConnection {
      * @throws SQLException
      */
     public long getNextSequence(String sequenceName) throws SQLException {
-        if(batchCommit && persistence.getConfiguration().isMemorySequences() && persistence.getMemorySequences().containsKey(sequenceName)) {
-            AtomicLong sequence = persistence.getMemorySequences().get(sequenceName);
+        AtomicLong sequence = persistence.getMemorySequence(sequenceName);
+        if(batchCommit && persistence.getConfiguration().isMemorySequences() && sequence != null) {
             return sequence.incrementAndGet();
         } else {
             requireJDBCConnection();

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/1b85aa45/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
index b35bed7..c297eff 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
@@ -42,6 +42,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * Add file description here!
@@ -77,6 +78,8 @@ public class KiWiPersistence {
      */
     private Map<String,AtomicLong> memorySequences;
 
+    private ReentrantLock          sequencesLock;
+
 
     /**
      * A reference to the value factory used to access this store. Used for notifications when to flush batches.
@@ -100,6 +103,7 @@ public class KiWiPersistence {
     public KiWiPersistence(KiWiConfiguration configuration) {
         this.configuration = configuration;
         this.maintenance = false;
+        this.sequencesLock = new ReentrantLock();
 
         // init JDBC connection pool
         initConnectionPool();
@@ -189,42 +193,47 @@ public class KiWiPersistence {
      */
     public void initSequences(String scriptName) {
         if(configuration.isBatchCommit() && configuration.isMemorySequences()) {
-            if(memorySequences == null) {
-                memorySequences = new ConcurrentHashMap<String,AtomicLong>();
-            }
-
+            sequencesLock.lock();
             try {
-                Connection con = getJDBCConnection(true);
+                if(memorySequences == null) {
+                    memorySequences = new ConcurrentHashMap<String,AtomicLong>();
+                }
+
                 try {
-                    for(String sequenceName : getDialect().listSequences(scriptName)) {
-
-                        // load sequence value from database
-                        // if there is a preparation needed to update the transaction, run it first
-                        if(getDialect().hasStatement(sequenceName+".prep")) {
-                            PreparedStatement prepNodeId = con.prepareStatement(getDialect().getStatement(sequenceName+".prep"));
-                            prepNodeId.executeUpdate();
-                            prepNodeId.close();
-                        }
+                    Connection con = getJDBCConnection(true);
+                    try {
+                        for(String sequenceName : getDialect().listSequences(scriptName)) {
+
+                            // load sequence value from database
+                            // if there is a preparation needed to update the transaction, run it first
+                            if(getDialect().hasStatement(sequenceName+".prep")) {
+                                PreparedStatement prepNodeId = con.prepareStatement(getDialect().getStatement(sequenceName+".prep"));
+                                prepNodeId.executeUpdate();
+                                prepNodeId.close();
+                            }
 
-                        PreparedStatement queryNodeId = con.prepareStatement(getDialect().getStatement(sequenceName));
-                        ResultSet resultNodeId = queryNodeId.executeQuery();
-                        try {
-                            if(resultNodeId.next()) {
-                                memorySequences.put(sequenceName,new AtomicLong(resultNodeId.getLong(1)-1));
-                            } else {
-                                throw new SQLException("the sequence did not return a new value");
+                            PreparedStatement queryNodeId = con.prepareStatement(getDialect().getStatement(sequenceName));
+                            ResultSet resultNodeId = queryNodeId.executeQuery();
+                            try {
+                                if(resultNodeId.next()) {
+                                    memorySequences.put(sequenceName,new AtomicLong(resultNodeId.getLong(1)-1));
+                                } else {
+                                    throw new SQLException("the sequence did not return a new value");
+                                }
+                            } finally {
+                                resultNodeId.close();
                             }
-                        } finally {
-                            resultNodeId.close();
-                        }
 
-                        con.commit();
+                            con.commit();
+                        }
+                    } finally {
+                        releaseJDBCConnection(con);
                     }
-                } finally {
-                    releaseJDBCConnection(con);
+                } catch(SQLException ex) {
+                    log.warn("database error: could not initialise in-memory sequences",ex);
                 }
-            } catch(SQLException ex) {
-                log.warn("database error: could not initialise in-memory sequences",ex);
+            } finally {
+                sequencesLock.unlock();
             }
         }
     }
@@ -558,6 +567,19 @@ public class KiWiPersistence {
         return memorySequences;
     }
 
+    public AtomicLong getMemorySequence(String name) {
+        if(memorySequences != null) {
+            sequencesLock.lock();
+            try {
+                return memorySequences.get(name);
+            } finally {
+                sequencesLock.unlock();
+            }
+        } else {
+            return null;
+        }
+    }
+
     public void setMemorySequences(Map<String, AtomicLong> memorySequences) {
         this.memorySequences = memorySequences;
     }


[3/7] git commit: implemented deletion of versions (MARMOTTA-18)

Posted by ss...@apache.org.
implemented deletion of versions (MARMOTTA-18)


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

Branch: refs/heads/develop
Commit: 18c428af2115acc84e47e6473a59ad7fa8552388
Parents: 1ba8179
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Mon Jul 22 11:07:07 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Mon Jul 22 11:07:07 2013 +0200

----------------------------------------------------------------------
 .../persistence/KiWiVersioningConnection.java   |  60 ++++++++++
 .../versioning/sail/KiWiVersioningSail.java     | 116 +++++++++++++++----
 .../kiwi/persistence/h2/statements.properties   |   2 +-
 .../persistence/mysql/statements.properties     |   2 +-
 .../persistence/pgsql/statements.properties     |   2 +-
 .../versioning/test/SnapshotRepositoryTest.java |  14 +--
 .../test/VersioningPersistenceTest.java         |  92 +++++++++++++--
 .../test/VersioningRepositoryTest.java          |  13 +--
 8 files changed, 242 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/18c428af/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/persistence/KiWiVersioningConnection.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/persistence/KiWiVersioningConnection.java b/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/persistence/KiWiVersioningConnection.java
index 054cf20..2ef8946 100644
--- a/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/persistence/KiWiVersioningConnection.java
+++ b/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/persistence/KiWiVersioningConnection.java
@@ -17,6 +17,7 @@
  */
 package org.apache.marmotta.kiwi.versioning.persistence;
 
+import com.google.common.base.Preconditions;
 import info.aduna.iteration.CloseableIteration;
 import info.aduna.iteration.EmptyIteration;
 import info.aduna.iteration.ExceptionConvertingIteration;
@@ -130,6 +131,65 @@ public class KiWiVersioningConnection extends KiWiConnection {
     }
 
     /**
+     * Remove the version with the id passed as argument, including all references to added and removed triples. The
+     * triples themselves are not deleted immediately, we let the garbage collector carry this out periodically.
+     * @param id
+     * @throws SQLException
+     */
+    public void removeVersion(Long id) throws SQLException {
+        Preconditions.checkNotNull(id);
+        Preconditions.checkArgument(id > 0);
+
+        requireJDBCConnection();
+
+        PreparedStatement removeAdded = getPreparedStatement("delete.version_added");
+        removeAdded.clearParameters();
+        removeAdded.setLong(1, id);
+        removeAdded.executeUpdate();
+
+        PreparedStatement removeRemoved = getPreparedStatement("delete.version_removed");
+        removeRemoved.clearParameters();
+        removeRemoved.setLong(1, id);
+        removeRemoved.executeUpdate();
+
+        PreparedStatement removeVersion = getPreparedStatement("delete.version");
+        removeVersion.clearParameters();
+        removeVersion.setLong(1, id);
+        removeVersion.executeUpdate();
+
+    }
+
+    /**
+     * Remove all versions until the date given as argument. Iterates over all versions and deletes them individually.
+     * Entries in join tables (added/removed triples) are also deleted, the triples themselves not. Deleted triples
+     * without version will later be cleaned up by the garbage collector
+     * @param until date until when to delete versions
+     * @throws SQLException
+     */
+    public void removeVersions(Date until) throws SQLException {
+        removeVersions(new Date(0), until);
+    }
+
+
+    /**
+     * Remove all versions in the given time interval. Iterates over all versions and deletes them individually.
+     * Entries in join tables (added/removed triples) are also deleted, the triples themselves not. Deleted triples
+     * without version will later be cleaned up by the garbage collector
+     * @param from date after which versions will be deleted
+     * @param to   date before which versions will be deleted
+     * @throws SQLException
+     */
+    public void removeVersions(Date from, Date to) throws SQLException {
+        CloseableIteration<Version, SQLException> it = listVersionsInternal(from,to);
+        while(it.hasNext()) {
+            Version next = it.next();
+            removeVersion(next.getId());
+        }
+    }
+
+
+
+    /**
      * Retrieve a version by its id. If the version does not exist, returns null
      *
      * @param id

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/18c428af/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/sail/KiWiVersioningSail.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/sail/KiWiVersioningSail.java b/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/sail/KiWiVersioningSail.java
index 91de399..7a96b7e 100644
--- a/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/sail/KiWiVersioningSail.java
+++ b/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/sail/KiWiVersioningSail.java
@@ -72,33 +72,33 @@ public class KiWiVersioningSail extends TransactionalSailWrapper implements Tran
 
     private SesameFilter<Statement> filter;
 
-	/**
-	 * Build a new {@link KiWiVersioningSail} based on the provided parent
-	 * {@link TransactionalSail}.
-	 * 
-	 * @param parent
-	 *            the {@link TransactionalSail} to base the
-	 *            {@link KiWiVersioningSail} on.
-	 */
+    /**
+     * Build a new {@link KiWiVersioningSail} based on the provided parent
+     * {@link TransactionalSail}.
+     *
+     * @param parent
+     *            the {@link TransactionalSail} to base the
+     *            {@link KiWiVersioningSail} on.
+     */
     public KiWiVersioningSail(TransactionalSail parent) {
         this(parent,new AlwaysTrueFilter<Statement>());
     }
 
-	/**
-	 * Build a new selective {@link KiWiVersioningSail} based on the provided
-	 * parent {@link TransactionalSail}. Only {@link Statement}s that are
-	 * accepted by the filter are included in versioning.
-	 * 
-	 * @param parent
-	 *            the {@link TransactionalSail} to base the
-	 *            {@link KiWiVersioningSail} on.
-	 * @param filter
-	 *            a {@link SesameFilter} to filter out {@link Statement}s that
-	 *            should not be versioned. Only a {@link Statement} that is
-	 *            accepted by this filter will be versioned.
-	 * 
-	 * @see SesameFilter#accept(Object)
-	 */
+    /**
+     * Build a new selective {@link KiWiVersioningSail} based on the provided
+     * parent {@link TransactionalSail}. Only {@link Statement}s that are
+     * accepted by the filter are included in versioning.
+     *
+     * @param parent
+     *            the {@link TransactionalSail} to base the
+     *            {@link KiWiVersioningSail} on.
+     * @param filter
+     *            a {@link SesameFilter} to filter out {@link Statement}s that
+     *            should not be versioned. Only a {@link Statement} that is
+     *            accepted by this filter will be versioned.
+     *
+     * @see SesameFilter#accept(Object)
+     */
     public KiWiVersioningSail(TransactionalSail parent, SesameFilter<Statement> filter) {
         super(parent);
         this.persistence = new KiWiVersioningPersistence(getBaseStore().getPersistence());
@@ -316,12 +316,80 @@ public class KiWiVersioningSail extends TransactionalSailWrapper implements Tran
         }
     }
 
+
+    /**
+     * Remove the version with the id passed as argument, including all references to added and removed triples. The
+     * triples themselves are not deleted immediately, we let the garbage collector carry this out periodically.
+     * @param id  the database ID of the version (see {@link Version#getId()})
+     * @throws SailException
+     */
+    public void removeVersion(Long id) throws SailException {
+        try {
+            final KiWiVersioningConnection connection = persistence.getConnection();
+            try {
+                connection.removeVersion(id);
+                connection.commit();
+            } finally {
+                connection.close();
+            }
+
+        } catch(SQLException ex) {
+            throw new SailException("database error while listing versions",ex);
+        }
+    }
+
+    /**
+     * Remove all versions until the date given as argument. Iterates over all versions and deletes them individually.
+     * Entries in join tables (added/removed triples) are also deleted, the triples themselves not. Deleted triples
+     * without version will later be cleaned up by the garbage collector
+     * @param until date until when to delete versions
+     * @throws SailException
+     */
+    public void removeVersions(Date until) throws SailException {
+        try {
+            final KiWiVersioningConnection connection = persistence.getConnection();
+            try {
+                connection.removeVersions(until);
+                connection.commit();
+            } finally {
+                connection.close();
+            }
+
+        } catch(SQLException ex) {
+            throw new SailException("database error while listing versions",ex);
+        }
+    }
+
+
+    /**
+     * Remove all versions in the given time interval. Iterates over all versions and deletes them individually.
+     * Entries in join tables (added/removed triples) are also deleted, the triples themselves not. Deleted triples
+     * without version will later be cleaned up by the garbage collector
+     * @param from date after which versions will be deleted
+     * @param to   date before which versions will be deleted
+     * @throws SailException
+     */
+    public void removeVersions(Date from, Date to) throws SailException {
+        try {
+            final KiWiVersioningConnection connection = persistence.getConnection();
+            try {
+                connection.removeVersions(from, to);
+                connection.commit();
+            } finally {
+                connection.close();
+            }
+
+        } catch(SQLException ex) {
+            throw new SailException("database error while listing versions",ex);
+        }
+    }
+
     /**
      * Return the version that is the most recent version for a resource given a reference date. The method will either
      * return the version that was current for the resource at the given date or return null in case such a version
      * does not exist (e.g. before the resource was created).
      *
-     * @param resource  the resource for which to find a version
+     * @param r         the resource for which to find a version
      * @param date      the reference date
      * @return the latest version of the resource at the given date, or null if such a version does not exist
      * @throws SQLException

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/18c428af/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties b/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
index 1001040..e5b1ae3 100644
--- a/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
+++ b/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
@@ -48,4 +48,4 @@ store.version_removed = INSERT INTO versions_removed (version_id,triple_id) VALU
 
 delete.version_added   = DELETE FROM versions_added WHERE version_id = ?
 delete.version_removed = DELETE FROM versions_removed WHERE version_id = ?
-delete.version         = DELETE FROM verions WHERE id = ?
\ No newline at end of file
+delete.version         = DELETE FROM versions WHERE id = ?
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/18c428af/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties b/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
index 5fce913..47d7f6a 100644
--- a/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
+++ b/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
@@ -50,4 +50,4 @@ store.version_removed = INSERT INTO versions_removed (version_id,triple_id) VALU
 
 delete.version_added   = DELETE FROM versions_added WHERE version_id = ?
 delete.version_removed = DELETE FROM versions_removed WHERE version_id = ?
-delete.version         = DELETE FROM verions WHERE id = ?
\ No newline at end of file
+delete.version         = DELETE FROM versions WHERE id = ?
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/18c428af/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties b/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
index 313e5b7..441adfc 100644
--- a/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
+++ b/libraries/kiwi/kiwi-versioning/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
@@ -50,7 +50,7 @@ store.version_removed = INSERT INTO versions_removed (version_id,triple_id) VALU
 
 delete.version_added   = DELETE FROM versions_added WHERE version_id = ?
 delete.version_removed = DELETE FROM versions_removed WHERE version_id = ?
-delete.version         = DELETE FROM verions WHERE id = ?
+delete.version         = DELETE FROM versions WHERE id = ?
 
 query.snapshot_size           = SELECT count(*) FROM triples WHERE createdAt <= ? AND (deleted = false OR deletedAt > ?)
 query.snapshot_size_ctx       = SELECT count(*) FROM triples WHERE context = ? AND createdAt <= ? AND (deleted = false OR deletedAt > ?)

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/18c428af/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/SnapshotRepositoryTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/SnapshotRepositoryTest.java b/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/SnapshotRepositoryTest.java
index 7cc52e3..562da23 100644
--- a/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/SnapshotRepositoryTest.java
+++ b/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/SnapshotRepositoryTest.java
@@ -17,6 +17,7 @@
  */
 package org.apache.marmotta.kiwi.versioning.test;
 
+import info.aduna.iteration.Iterations;
 import org.apache.marmotta.kiwi.persistence.KiWiDialect;
 import org.apache.marmotta.kiwi.persistence.h2.H2Dialect;
 import org.apache.marmotta.kiwi.persistence.mysql.MySQLDialect;
@@ -378,17 +379,6 @@ public class SnapshotRepositoryTest {
      * @return
      */
     public static <E> List<E> asList(RepositoryResult<E> result) throws RepositoryException {
-        ArrayList<E> collection = new ArrayList<E>();
-        try {
-            while (result.hasNext()) {
-                collection.add(result.next());
-            }
-
-            return collection;
-        }
-        finally {
-            result.close();
-        }
+        return Iterations.asList(result);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/18c428af/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningPersistenceTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningPersistenceTest.java b/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningPersistenceTest.java
index a7d6ad4..4477586 100644
--- a/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningPersistenceTest.java
+++ b/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningPersistenceTest.java
@@ -17,6 +17,8 @@
  */
 package org.apache.marmotta.kiwi.versioning.test;
 
+import info.aduna.iteration.Iteration;
+import info.aduna.iteration.Iterations;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.marmotta.kiwi.model.rdf.KiWiStringLiteral;
 import org.apache.marmotta.kiwi.model.rdf.KiWiTriple;
@@ -217,13 +219,13 @@ public class VersioningPersistenceTest {
             connection.commit();
 
             // check if listVersions now gives exactly one version
-            List<Version> list1 = connection.listVersions().asList();
+            List<Version> list1 = Iterations.asList(connection.listVersions());
             Assert.assertEquals("there should be exactly one version",1,list1.size());
             Assert.assertEquals("contents of version differ", version1, list1.get(0));
             Assert.assertEquals("version id is not 1", 1L, (long)list1.get(0).getId());
 
             // check if listVersions with subject1 now gives exactly one version
-            List<Version> listr1 = connection.listVersions(subject1).asList();
+            List<Version> listr1 = Iterations.asList(connection.listVersions(subject1));
             Assert.assertEquals("there should be exactly one version", 1, listr1.size());
             Assert.assertEquals("contents of version differ", version1, listr1.get(0));
             Assert.assertEquals("version id is not 1", 1L, (long)listr1.get(0).getId());
@@ -237,13 +239,13 @@ public class VersioningPersistenceTest {
             connection.commit();
 
             // check if listVersions now gives exactly two versions
-            List<Version> list2 = connection.listVersions().asList();
+            List<Version> list2 = Iterations.asList(connection.listVersions());
             Assert.assertEquals("there should be exactly two version",2,list2.size());
             Assert.assertEquals("contents of version differ", version2, list2.get(1));
 
 
             // check if listVersions with subject1 still gives exactly one version
-            List<Version> listr2 = connection.listVersions(subject1).asList();
+            List<Version> listr2 = Iterations.asList(connection.listVersions(subject1));
             Assert.assertEquals("there should be exactly one version", 2, listr2.size());
             Assert.assertEquals("contents of version differ", version1, listr2.get(0));
             Assert.assertEquals("version id is not 1", 1L, (long)listr2.get(0).getId());
@@ -320,7 +322,7 @@ public class VersioningPersistenceTest {
 
 
             // now we test different ways of listing versions between dates
-            List<Version> list1 = connection.listVersions(date1,date2).asList();
+            List<Version> list1 = Iterations.asList(connection.listVersions(date1,date2));
             Assert.assertEquals("there should be exactly one version from "+date1+" to "+date2,1,list1.size());
             Assert.assertEquals("contents of version differ", version1, list1.get(0));
             Assert.assertEquals("version id is not 1", 1L, (long)list1.get(0).getId());
@@ -331,21 +333,21 @@ public class VersioningPersistenceTest {
             Assert.assertEquals("latest version is not the expected version", version1,latest2);
 
             // check if listVersions with subject1 now gives exactly one version
-            List<Version> listr1 = connection.listVersions(subject,date1,date2).asList();
+            List<Version> listr1 = Iterations.asList(connection.listVersions(subject,date1,date2));
             Assert.assertEquals("there should be exactly one version", 1, listr1.size());
             Assert.assertEquals("contents of version differ", version1, listr1.get(0));
             Assert.assertEquals("version id is not 1", 1L, (long)listr1.get(0).getId());
 
 
-            List<Version> list2 = connection.listVersions(date2,date3).asList();
+            List<Version> list2 = Iterations.asList(connection.listVersions(date2,date3));
             Assert.assertEquals("there should be exactly one version from "+date2+" to "+date3,1,list2.size());
             Assert.assertEquals("contents of version differ", version2, list2.get(0));
             Assert.assertEquals("version id is not 2", 2L, (long)list2.get(0).getId());
 
-            List<Version> list3 = connection.listVersions(date3,new Date()).asList();
+            List<Version> list3 = Iterations.asList(connection.listVersions(date3,new Date()));
             Assert.assertEquals("there should be no version from "+date3+" to now",0,list3.size());
 
-            List<Version> list4 = connection.listVersions(date1,date3).asList();
+            List<Version> list4 = Iterations.asList(connection.listVersions(date1,date3));
             Assert.assertEquals("there should be exactly two versions from "+date1+" to "+date3,2,list4.size());
             Assert.assertEquals("contents of version1 differ", version1, list4.get(0));
             Assert.assertEquals("contents of version2 differ", version2, list4.get(1));
@@ -359,6 +361,78 @@ public class VersioningPersistenceTest {
 
     }
 
+
+    @Test
+    public void testCreateRemoveVersions() throws Exception {
+        KiWiVersioningConnection connection = vpersistence.getConnection();
+        try {
+            KiWiUriResource subject1  = new KiWiUriResource("http://localhost/resource/"+ RandomStringUtils.randomAlphanumeric(8));
+            KiWiUriResource subject2  = new KiWiUriResource("http://localhost/resource/"+ RandomStringUtils.randomAlphanumeric(8));
+            KiWiUriResource pred_1   = new KiWiUriResource("http://localhost/predicate/P1");
+            KiWiUriResource pred_2   = new KiWiUriResource("http://localhost/predicate/P2");
+            KiWiUriResource object_1 = new KiWiUriResource("http://localhost/resource/"+RandomStringUtils.randomAlphanumeric(8));
+            KiWiStringLiteral object_2 = new KiWiStringLiteral(RandomStringUtils.randomAlphanumeric(32));
+            KiWiUriResource context  = new KiWiUriResource("http://localhost/context/"+RandomStringUtils.randomAlphanumeric(8));
+
+            connection.storeNode(subject1, false);
+            connection.storeNode(subject2, false);
+            connection.storeNode(pred_1, false);
+            connection.storeNode(pred_2, false);
+            connection.storeNode(object_1, false);
+            connection.storeNode(object_2, false);
+            connection.storeNode(context, false);
+
+            KiWiTriple triple1 = new KiWiTriple(subject1,pred_1,object_1,context);
+            KiWiTriple triple2 = new KiWiTriple(subject2,pred_2,object_2,context);
+
+            connection.storeTriple(triple1);
+            connection.storeTriple(triple2);
+            connection.commit();
+
+            Version version1 = new Version();
+            version1.setCommitTime(new Date());
+            version1.addTriple(triple1);
+            connection.storeVersion(version1);
+            connection.commit();
+
+            // check if listVersions now gives exactly one version
+            List<Version> list1 = Iterations.asList(connection.listVersions());
+            Assert.assertEquals("there should be exactly one version",1,list1.size());
+            Assert.assertEquals("contents of version differ", version1, list1.get(0));
+            Assert.assertEquals("version id is not 1", 1L, (long)list1.get(0).getId());
+
+            Version version2 = new Version();
+            version2.setCommitTime(new Date());
+            version2.addTriple(triple2);
+            version2.removeTriple(triple1);
+            connection.storeVersion(version2);
+            connection.commit();
+
+            // check if listVersions now gives exactly two versions
+            List<Version> list2 = Iterations.asList(connection.listVersions());
+            Assert.assertEquals("there should be exactly two version",2,list2.size());
+            Assert.assertEquals("contents of version differ", version2, list2.get(1));
+
+            connection.commit();
+
+            connection.removeVersion(version1.getId());
+            connection.commit();
+
+            // check if listVersions now gives exactly two versions
+            List<Version> list3 = Iterations.asList(connection.listVersions());
+            Assert.assertEquals("there should be exactly one version",1,list3.size());
+            Assert.assertEquals("contents of version differ", version2, list3.get(0));
+
+            connection.commit();
+
+        } finally {
+            connection.close();
+        }
+
+    }
+
+
+
     /**
      * MYSQL rounds timestamps to the second, so it is sometimes necessary to sleep before doing a test
      */

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/18c428af/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java b/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java
index f0b720a..6757a58 100644
--- a/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java
+++ b/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java
@@ -17,6 +17,7 @@
  */
 package org.apache.marmotta.kiwi.versioning.test;
 
+import info.aduna.iteration.Iterations;
 import org.apache.marmotta.kiwi.persistence.KiWiDialect;
 import org.apache.marmotta.kiwi.persistence.h2.H2Dialect;
 import org.apache.marmotta.kiwi.persistence.mysql.MySQLDialect;
@@ -267,16 +268,6 @@ public class VersioningRepositoryTest {
      * @return
      */
     public static <E> List<E> asList(RepositoryResult<E> result) throws RepositoryException {
-        ArrayList<E> collection = new ArrayList<E>();
-        try {
-            while (result.hasNext()) {
-                collection.add(result.next());
-            }
-
-            return collection;
-        }
-        finally {
-            result.close();
-        }
+        return Iterations.asList(result);
     }
 }


[2/7] git commit: Merge remote-tracking branch 'origin/develop' into develop

Posted by ss...@apache.org.
Merge remote-tracking branch 'origin/develop' 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/1ba81793
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/1ba81793
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/1ba81793

Branch: refs/heads/develop
Commit: 1ba81793ea278ab38789bd490c7a2d7f98b4d984
Parents: 1b85aa4 857c77b
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Sat Jul 20 20:08:10 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Sat Jul 20 20:08:10 2013 +0200

----------------------------------------------------------------------
 .../apache/marmotta/platform/core/filters/TemplatingFilter.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------



[6/7] git commit: improved concurrency in value factory and triple store persistence by using Guava's specialised implementations; hopefully fixes the issue with spurious duplicate node creation

Posted by ss...@apache.org.
improved concurrency in value factory and triple store persistence by using Guava's specialised implementations; hopefully fixes the issue with spurious duplicate node creation


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

Branch: refs/heads/develop
Commit: 7dc785137fbb799b3843322de5cc35f500fa8b90
Parents: c5e4411
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Mon Jul 22 12:55:36 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Mon Jul 22 12:55:36 2013 +0200

----------------------------------------------------------------------
 .../kiwi/persistence/KiWiConnection.java        |  13 +-
 .../kiwi/persistence/KiWiPersistence.java       |  24 +-
 .../marmotta/kiwi/sail/KiWiValueFactory.java    | 452 +++++++++----------
 3 files changed, 228 insertions(+), 261 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/7dc78513/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 2b62024..506c567 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
@@ -29,8 +29,6 @@ import org.apache.marmotta.kiwi.caching.KiWiCacheManager;
 import org.apache.marmotta.kiwi.config.KiWiConfiguration;
 import org.apache.marmotta.kiwi.model.caching.TripleTable;
 import org.apache.marmotta.kiwi.model.rdf.*;
-import org.apache.marmotta.kiwi.persistence.mysql.MySQLDialect;
-import org.apache.marmotta.kiwi.persistence.pgsql.PostgreSQLDialect;
 import org.apache.marmotta.kiwi.persistence.util.ResultSetIteration;
 import org.apache.marmotta.kiwi.persistence.util.ResultTransformerFunction;
 import org.openrdf.model.Literal;
@@ -1673,9 +1671,8 @@ public class KiWiConnection {
      * @throws SQLException
      */
     public long getNextSequence(String sequenceName) throws SQLException {
-        AtomicLong sequence = persistence.getMemorySequence(sequenceName);
-        if(batchCommit && persistence.getConfiguration().isMemorySequences() && sequence != null) {
-            return sequence.incrementAndGet();
+        if(batchCommit && persistence.getConfiguration().isMemorySequences()) {
+            return persistence.incrementAndGetMemorySequence(sequenceName);
         } else {
             requireJDBCConnection();
 
@@ -1893,10 +1890,10 @@ public class KiWiConnection {
             requireJDBCConnection();
 
             try {
-                for(Map.Entry<String,AtomicLong> entry : persistence.getMemorySequences().entrySet()) {
-                    if( entry.getValue().get() > 0) {
+                for(Map.Entry<String,Long> entry : persistence.getMemorySequences().asMap().entrySet()) {
+                    if( entry.getValue() > 0) {
                         PreparedStatement updateSequence = getPreparedStatement(entry.getKey()+".set");
-                        updateSequence.setLong(1, entry.getValue().get());
+                        updateSequence.setLong(1, entry.getValue());
                         if(updateSequence.execute()) {
                             updateSequence.getResultSet().close();
                         } else {

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/7dc78513/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
index c297eff..12ff73f 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/persistence/KiWiPersistence.java
@@ -17,6 +17,7 @@
  */
 package org.apache.marmotta.kiwi.persistence;
 
+import com.google.common.util.concurrent.AtomicLongMap;
 import org.apache.marmotta.kiwi.caching.KiWiCacheManager;
 import org.apache.marmotta.kiwi.config.KiWiConfiguration;
 import org.apache.marmotta.kiwi.model.rdf.KiWiNode;
@@ -76,7 +77,7 @@ public class KiWiPersistence {
      * A map holding in-memory sequences to be used for sequence caching in case the appropriate configuration option
      * is configued and batched commits are enabled.
      */
-    private Map<String,AtomicLong> memorySequences;
+    private AtomicLongMap<String> memorySequences;
 
     private ReentrantLock          sequencesLock;
 
@@ -196,7 +197,7 @@ public class KiWiPersistence {
             sequencesLock.lock();
             try {
                 if(memorySequences == null) {
-                    memorySequences = new ConcurrentHashMap<String,AtomicLong>();
+                    memorySequences = AtomicLongMap.create();
                 }
 
                 try {
@@ -216,7 +217,7 @@ public class KiWiPersistence {
                             ResultSet resultNodeId = queryNodeId.executeQuery();
                             try {
                                 if(resultNodeId.next()) {
-                                    memorySequences.put(sequenceName,new AtomicLong(resultNodeId.getLong(1)-1));
+                                    memorySequences.put(sequenceName,resultNodeId.getLong(1)-1);
                                 } else {
                                     throw new SQLException("the sequence did not return a new value");
                                 }
@@ -563,27 +564,18 @@ public class KiWiPersistence {
         return configuration;
     }
 
-    public Map<String, AtomicLong> getMemorySequences() {
+    public AtomicLongMap<String> getMemorySequences() {
         return memorySequences;
     }
 
-    public AtomicLong getMemorySequence(String name) {
+    public long incrementAndGetMemorySequence(String name) {
         if(memorySequences != null) {
-            sequencesLock.lock();
-            try {
-                return memorySequences.get(name);
-            } finally {
-                sequencesLock.unlock();
-            }
+            return memorySequences.incrementAndGet(name);
         } else {
-            return null;
+            return 0;
         }
     }
 
-    public void setMemorySequences(Map<String, AtomicLong> memorySequences) {
-        this.memorySequences = memorySequences;
-    }
-
 
     public void garbageCollect() throws SQLException {
         this.garbageCollector.garbageCollect();

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/7dc78513/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java
index b2b5a28..3331704 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java
@@ -17,45 +17,27 @@
  */
 package org.apache.marmotta.kiwi.sail;
 
-import info.aduna.iteration.Iterations;
-
-import java.sql.SQLException;
-import java.util.*;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.locks.ReentrantLock;
-
-import javax.xml.datatype.XMLGregorianCalendar;
-
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.Monitor;
 import org.apache.commons.lang3.LocaleUtils;
 import org.apache.marmotta.commons.sesame.model.LiteralCommons;
 import org.apache.marmotta.commons.sesame.model.Namespaces;
 import org.apache.marmotta.commons.util.DateUtils;
 import org.apache.marmotta.kiwi.model.caching.IntArray;
-import org.apache.marmotta.kiwi.model.rdf.KiWiAnonResource;
-import org.apache.marmotta.kiwi.model.rdf.KiWiBooleanLiteral;
-import org.apache.marmotta.kiwi.model.rdf.KiWiDateLiteral;
-import org.apache.marmotta.kiwi.model.rdf.KiWiDoubleLiteral;
-import org.apache.marmotta.kiwi.model.rdf.KiWiIntLiteral;
-import org.apache.marmotta.kiwi.model.rdf.KiWiLiteral;
-import org.apache.marmotta.kiwi.model.rdf.KiWiNode;
-import org.apache.marmotta.kiwi.model.rdf.KiWiResource;
-import org.apache.marmotta.kiwi.model.rdf.KiWiStringLiteral;
-import org.apache.marmotta.kiwi.model.rdf.KiWiTriple;
-import org.apache.marmotta.kiwi.model.rdf.KiWiUriResource;
+import org.apache.marmotta.kiwi.model.rdf.*;
 import org.apache.marmotta.kiwi.persistence.KiWiConnection;
-import org.openrdf.model.BNode;
-import org.openrdf.model.Literal;
-import org.openrdf.model.Resource;
-import org.openrdf.model.Statement;
-import org.openrdf.model.URI;
-import org.openrdf.model.Value;
-import org.openrdf.model.ValueFactory;
+import org.openrdf.model.*;
 import org.openrdf.model.impl.ContextStatementImpl;
-import org.openrdf.repository.RepositoryException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.MapMaker;
+import javax.xml.datatype.XMLGregorianCalendar;
+import java.sql.SQLException;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 /**
  * Add file description here!
@@ -86,11 +68,9 @@ public class KiWiValueFactory implements ValueFactory {
 
     private KiWiStore store;
 
-    private ReentrantLock nodeLock;
-    //private ReentrantLock tripleLock;
 
-    private ConcurrentMap<String,ReentrantLock> resourceLocks;
-    private ConcurrentMap<Object,ReentrantLock> literalLocks;
+    private LoadingCache<String,Monitor> resourceLocks;
+    private LoadingCache<String,Monitor> literalLocks;
 
     private String defaultContext;
 
@@ -110,13 +90,11 @@ public class KiWiValueFactory implements ValueFactory {
     // used for generating sequence numbers for RDF nodes
     private KiWiConnection batchConnection;
 
-    private ReentrantLock commitLock;
+    private Monitor commitLock;
 
     public KiWiValueFactory(KiWiStore store, String defaultContext) {
-        nodeLock = store.nodeLock;
-        //tripleLock = store.tripleLock;
-        resourceLocks = new MapMaker().weakKeys().weakValues().makeMap();
-        literalLocks  = new MapMaker().weakKeys().weakValues().makeMap();
+        resourceLocks = CacheBuilder.newBuilder().weakValues().build(new LockCacheLoader());
+        literalLocks  = CacheBuilder.newBuilder().weakValues().build(new LockCacheLoader());
 
         anonIdGenerator = new Random();
         tripleRegistry  = store.tripleRegistry;
@@ -126,14 +104,14 @@ public class KiWiValueFactory implements ValueFactory {
 
         // batch commits
         this.nodeBatch      = new ArrayList<KiWiNode>(batchSize);
-        this.commitLock     = new ReentrantLock();
+        this.commitLock     = new Monitor();
 
         this.batchCommit    = store.getPersistence().getConfiguration().isBatchCommit();
         this.batchSize      = store.getPersistence().getConfiguration().getBatchSize();
 
-        this.batchUriLookup     = new HashMap<String,KiWiUriResource>();
-        this.batchBNodeLookup   = new HashMap<String, KiWiAnonResource>();
-        this.batchLiteralLookup = new HashMap<String,KiWiLiteral>();
+        this.batchUriLookup     = new ConcurrentHashMap<String,KiWiUriResource>();
+        this.batchBNodeLookup   = new ConcurrentHashMap<String, KiWiAnonResource>();
+        this.batchLiteralLookup = new ConcurrentHashMap<String,KiWiLiteral>();
     }
 
     protected KiWiConnection aqcuireConnection() {
@@ -165,33 +143,6 @@ public class KiWiValueFactory implements ValueFactory {
         }
     }
 
-    protected ReentrantLock acquireResourceLock(String uri) {
-        ReentrantLock lock;
-        synchronized (resourceLocks) {
-            lock = resourceLocks.get(uri);
-            if(lock == null) {
-                lock = new ReentrantLock();
-                resourceLocks.put(uri,lock);
-            }
-        }
-        lock.lock();
-
-        return lock;
-    }
-
-    protected ReentrantLock acquireLiteralLock(Object value) {
-        ReentrantLock lock;
-        synchronized (literalLocks) {
-            lock = literalLocks.get(value);
-            if(lock == null) {
-                lock = new ReentrantLock();
-                literalLocks.put(value,lock);
-            }
-        }
-        lock.lock();
-
-        return lock;
-    }
     /**
      * Creates a new bNode.
      *
@@ -211,51 +162,56 @@ public class KiWiValueFactory implements ValueFactory {
     @Override
     public URI createURI(String uri) {
 
-        KiWiUriResource result = batchUriLookup.get(uri);
-
-        if(result != null) {
-            return result;
-        } else {
+        Monitor lock = resourceLocks.getUnchecked(uri);
+        lock.enter();
 
-            ReentrantLock lock = acquireResourceLock(uri);
-            KiWiConnection connection = aqcuireConnection();
-            try {
-                // first look in the registry for newly created resources if the resource has already been created and
-                // is still volatile
-                result = connection.loadUriResource(uri);
+        try {
+            KiWiUriResource result = batchUriLookup.get(uri);
 
-                if(result == null) {
-                    result = new KiWiUriResource(uri);
+            if(result != null) {
+                return result;
+            } else {
 
-                    if(result.getId() == null) {
-                        if(batchCommit) {
-                            result.setId(connection.getNodeId());
-                            synchronized (nodeBatch) {
-                                nodeBatch.add(result);
-                                batchUriLookup.put(uri,result);
+                KiWiConnection connection = aqcuireConnection();
+                try {
+                    // first look in the registry for newly created resources if the resource has already been created and
+                    // is still volatile
+                    result = connection.loadUriResource(uri);
 
-                                if(nodeBatch.size() >= batchSize) {
-                                    flushBatch(connection);
+                    if(result == null) {
+                        result = new KiWiUriResource(uri);
+
+                        if(result.getId() == null) {
+                            if(batchCommit) {
+                                result.setId(connection.getNodeId());
+                                synchronized (nodeBatch) {
+                                    nodeBatch.add(result);
+                                    batchUriLookup.put(uri,result);
+
+                                    if(nodeBatch.size() >= batchSize) {
+                                        flushBatch(connection);
+                                    }
                                 }
+                            } else {
+                                connection.storeNode(result, false);
                             }
-                        } else {
-                            connection.storeNode(result, false);
                         }
-                    }
 
-                    if(result.getId() == null) {
-                        log.error("node ID is null!");
+                        if(result.getId() == null) {
+                            log.error("node ID is null!");
+                        }
                     }
-                }
 
-                return result;
-            } catch (SQLException e) {
-                log.error("database error, could not load URI resource",e);
-                throw new IllegalStateException("database error, could not load URI resource",e);
-            } finally {
-                releaseConnection(connection);
-                lock.unlock();
+                    return result;
+                } catch (SQLException e) {
+                    log.error("database error, could not load URI resource",e);
+                    throw new IllegalStateException("database error, could not load URI resource",e);
+                } finally {
+                    releaseConnection(connection);
+                }
             }
+        } finally {
+            lock.leave();
         }
     }
 
@@ -286,45 +242,50 @@ public class KiWiValueFactory implements ValueFactory {
      */
     @Override
     public BNode createBNode(String nodeID) {
-        KiWiAnonResource result = batchBNodeLookup.get(nodeID);
+        Monitor lock = resourceLocks.getUnchecked(nodeID);
+        lock.enter();
 
-        if(result != null) {
-            return result;
-        } else {
-            nodeLock.lock();
-            KiWiConnection connection = aqcuireConnection();
-            try {
-                // first look in the registry for newly created resources if the resource has already been created and
-                // is still volatile
-                result = connection.loadAnonResource(nodeID);
+        try {
+            KiWiAnonResource result = batchBNodeLookup.get(nodeID);
 
-                if(result == null) {
-                    result = new KiWiAnonResource(nodeID);
+            if(result != null) {
+                return result;
+            } else {
+                KiWiConnection connection = aqcuireConnection();
+                try {
+                    // first look in the registry for newly created resources if the resource has already been created and
+                    // is still volatile
+                    result = connection.loadAnonResource(nodeID);
 
-                    if(result.getId() == null) {
-                        if(batchCommit) {
-                            result.setId(connection.getNodeId());
-                            synchronized (nodeBatch) {
-                                nodeBatch.add(result);
-                                batchBNodeLookup.put(nodeID,result);
-                            }
-                            if(nodeBatch.size() >= batchSize) {
-                                flushBatch(connection);
+                    if(result == null) {
+                        result = new KiWiAnonResource(nodeID);
+
+                        if(result.getId() == null) {
+                            if(batchCommit) {
+                                result.setId(connection.getNodeId());
+                                synchronized (nodeBatch) {
+                                    nodeBatch.add(result);
+                                    batchBNodeLookup.put(nodeID,result);
+                                }
+                                if(nodeBatch.size() >= batchSize) {
+                                    flushBatch(connection);
+                                }
+                            } else {
+                                connection.storeNode(result, false);
                             }
-                        } else {
-                            connection.storeNode(result, false);
                         }
                     }
-                }
 
-                return result;
-            } catch (SQLException e) {
-                log.error("database error, could not load anonymous resource",e);
-                throw new IllegalStateException("database error, could not load anonymous resource",e);
-            } finally {
-                releaseConnection(connection);
-                nodeLock.unlock();
+                    return result;
+                } catch (SQLException e) {
+                    log.error("database error, could not load anonymous resource",e);
+                    throw new IllegalStateException("database error, could not load anonymous resource",e);
+                } finally {
+                    releaseConnection(connection);
+                }
             }
+        } finally {
+            lock.leave();
         }
     }
 
@@ -418,119 +379,125 @@ public class KiWiValueFactory implements ValueFactory {
         } else if(type == null) {
             type = LiteralCommons.getXSDType(value.getClass());
         }
+        String key = LiteralCommons.createCacheKey(value.toString(),locale,type);
 
-        KiWiLiteral result = batchLiteralLookup.get(LiteralCommons.createCacheKey(value.toString(),locale,type));
+        Monitor lock = literalLocks.getUnchecked(key);
+        lock.enter();
 
+        try {
+            KiWiLiteral result = batchLiteralLookup.get(key);
 
-        if(result != null) {
-            return result;
-        } else {
-            final KiWiUriResource rtype = (KiWiUriResource)createURI(type);
 
-            ReentrantLock lock = acquireLiteralLock(value);
-            KiWiConnection connection = aqcuireConnection();
-            try {
+            if(result != null) {
+                return result;
+            } else {
+                final KiWiUriResource rtype = (KiWiUriResource)createURI(type);
 
+                KiWiConnection connection = aqcuireConnection();
+                try {
 
-                // differentiate between the different types of the value
-                if(value instanceof Date || type.equals(Namespaces.NS_XSD+"dateTime")) {
-                    // parse if necessary
-                    final Date dvalue;
-                    if(value instanceof Date) {
-                        dvalue = (Date)value;
-                    } else {
-                        dvalue = DateUtils.parseDate(value.toString());
-                    }
 
-                    result = connection.loadLiteral(dvalue);
+                    // differentiate between the different types of the value
+                    if(value instanceof Date || type.equals(Namespaces.NS_XSD+"dateTime")) {
+                        // parse if necessary
+                        final Date dvalue;
+                        if(value instanceof Date) {
+                            dvalue = (Date)value;
+                        } else {
+                            dvalue = DateUtils.parseDate(value.toString());
+                        }
 
-                    if(result == null) {
-                        result= new KiWiDateLiteral(dvalue, rtype);
-                    }
-                } else if(Integer.class.equals(value.getClass()) || int.class.equals(value.getClass())  ||
-                        Long.class.equals(value.getClass())    || long.class.equals(value.getClass()) ||
-                        type.equals(Namespaces.NS_XSD+"integer") || type.equals(Namespaces.NS_XSD+"long")) {
-                    long ivalue = 0;
-                    if(Integer.class.equals(value.getClass()) || int.class.equals(value.getClass())) {
-                        ivalue = (Integer)value;
-                    } else if(Long.class.equals(value.getClass()) || long.class.equals(value.getClass())) {
-                        ivalue = (Long)value;
-                    } else {
-                        ivalue = Long.parseLong(value.toString());
-                    }
+                        result = connection.loadLiteral(dvalue);
 
+                        if(result == null) {
+                            result= new KiWiDateLiteral(dvalue, rtype);
+                        }
+                    } else if(Integer.class.equals(value.getClass()) || int.class.equals(value.getClass())  ||
+                            Long.class.equals(value.getClass())    || long.class.equals(value.getClass()) ||
+                            type.equals(Namespaces.NS_XSD+"integer") || type.equals(Namespaces.NS_XSD+"long")) {
+                        long ivalue = 0;
+                        if(Integer.class.equals(value.getClass()) || int.class.equals(value.getClass())) {
+                            ivalue = (Integer)value;
+                        } else if(Long.class.equals(value.getClass()) || long.class.equals(value.getClass())) {
+                            ivalue = (Long)value;
+                        } else {
+                            ivalue = Long.parseLong(value.toString());
+                        }
 
-                    result = connection.loadLiteral(ivalue);
 
-                    if(result == null) {
-                        result= new KiWiIntLiteral(ivalue, rtype);
-                    }
-                } else if(Double.class.equals(value.getClass())   || double.class.equals(value.getClass())  ||
-                        Float.class.equals(value.getClass())    || float.class.equals(value.getClass()) ||
-                        type.equals(Namespaces.NS_XSD+"double") || type.equals(Namespaces.NS_XSD+"float")) {
-                    double dvalue = 0.0;
-                    if(Float.class.equals(value.getClass()) || float.class.equals(value.getClass())) {
-                        dvalue = (Float)value;
-                    } else if(Double.class.equals(value.getClass()) || double.class.equals(value.getClass())) {
-                        dvalue = (Double)value;
-                    } else {
-                        dvalue = Double.parseDouble(value.toString());
-                    }
+                        result = connection.loadLiteral(ivalue);
 
+                        if(result == null) {
+                            result= new KiWiIntLiteral(ivalue, rtype);
+                        }
+                    } else if(Double.class.equals(value.getClass())   || double.class.equals(value.getClass())  ||
+                            Float.class.equals(value.getClass())    || float.class.equals(value.getClass()) ||
+                            type.equals(Namespaces.NS_XSD+"double") || type.equals(Namespaces.NS_XSD+"float")) {
+                        double dvalue = 0.0;
+                        if(Float.class.equals(value.getClass()) || float.class.equals(value.getClass())) {
+                            dvalue = (Float)value;
+                        } else if(Double.class.equals(value.getClass()) || double.class.equals(value.getClass())) {
+                            dvalue = (Double)value;
+                        } else {
+                            dvalue = Double.parseDouble(value.toString());
+                        }
 
-                    result = connection.loadLiteral(dvalue);
 
-                    if(result == null) {
-                        result= new KiWiDoubleLiteral(dvalue, rtype);
-                    }
-                } else if(Boolean.class.equals(value.getClass())   || boolean.class.equals(value.getClass())  ||
-                        type.equals(Namespaces.NS_XSD+"boolean")) {
-                    boolean bvalue = false;
-                    if(Boolean.class.equals(value.getClass())   || boolean.class.equals(value.getClass())) {
-                        bvalue = (Boolean)value;
-                    } else {
-                        bvalue = Boolean.parseBoolean(value.toString());
-                    }
+                        result = connection.loadLiteral(dvalue);
 
+                        if(result == null) {
+                            result= new KiWiDoubleLiteral(dvalue, rtype);
+                        }
+                    } else if(Boolean.class.equals(value.getClass())   || boolean.class.equals(value.getClass())  ||
+                            type.equals(Namespaces.NS_XSD+"boolean")) {
+                        boolean bvalue = false;
+                        if(Boolean.class.equals(value.getClass())   || boolean.class.equals(value.getClass())) {
+                            bvalue = (Boolean)value;
+                        } else {
+                            bvalue = Boolean.parseBoolean(value.toString());
+                        }
 
-                    result = connection.loadLiteral(bvalue);
 
-                    if(result == null) {
-                        result= new KiWiBooleanLiteral(bvalue, rtype);
-                    }
-                } else {
-                    result = connection.loadLiteral(value.toString(), lang, rtype);
+                        result = connection.loadLiteral(bvalue);
 
-                    if(result == null) {
-                        result = new KiWiStringLiteral(value.toString(), locale, rtype);
+                        if(result == null) {
+                            result= new KiWiBooleanLiteral(bvalue, rtype);
+                        }
+                    } else {
+                        result = connection.loadLiteral(value.toString(), lang, rtype);
+
+                        if(result == null) {
+                            result = new KiWiStringLiteral(value.toString(), locale, rtype);
+                        }
                     }
-                }
 
-                if(result.getId() == null) {
-                    if(batchCommit) {
-                        result.setId(connection.getNodeId());
-                        synchronized (nodeBatch) {
-                            nodeBatch.add(result);
-                            batchLiteralLookup.put(LiteralCommons.createCacheKey(value.toString(),locale,type), result);
-
-                            if(nodeBatch.size() >= batchSize) {
-                                flushBatch(connection);
+                    if(result.getId() == null) {
+                        if(batchCommit) {
+                            result.setId(connection.getNodeId());
+                            synchronized (nodeBatch) {
+                                nodeBatch.add(result);
+                                batchLiteralLookup.put(LiteralCommons.createCacheKey(value.toString(),locale,type), result);
+
+                                if(nodeBatch.size() >= batchSize) {
+                                    flushBatch(connection);
+                                }
                             }
+                        } else {
+                            connection.storeNode(result, false);
                         }
-                    } else {
-                        connection.storeNode(result, false);
                     }
-                }
 
-                return result;
+                    return result;
 
-            } catch (SQLException e) {
-                log.error("database error, could not load literal",e);
-                throw new IllegalStateException("database error, could not load literal",e);
-            } finally {
-                releaseConnection(connection);
-                lock.unlock();
+                } catch (SQLException e) {
+                    log.error("database error, could not load literal",e);
+                    throw new IllegalStateException("database error, could not load literal",e);
+                } finally {
+                    releaseConnection(connection);
+                }
             }
+        } finally {
+            lock.leave();
         }
     }
 
@@ -790,27 +757,28 @@ public class KiWiValueFactory implements ValueFactory {
      * the node batch.
      */
     public void flushBatch(KiWiConnection con) throws SQLException {
-        commitLock.lock();
-        try {
-            if(batchCommit && nodeBatch.size() > 0) {
-                con.startNodeBatch();
+        if(commitLock.tryEnter()) {
+            try {
+                if(batchCommit && nodeBatch.size() > 0) {
+                    con.startNodeBatch();
 
-                synchronized (nodeBatch) {
-                    for(KiWiNode n : nodeBatch) {
-                        con.storeNode(n,true);
-                    }
-                    nodeBatch.clear();
+                    synchronized (nodeBatch) {
+                        for(KiWiNode n : nodeBatch) {
+                            con.storeNode(n,true);
+                        }
+                        nodeBatch.clear();
 
-                    batchLiteralLookup.clear();
-                    batchUriLookup.clear();
-                    batchBNodeLookup.clear();
-                }
+                        batchLiteralLookup.clear();
+                        batchUriLookup.clear();
+                        batchBNodeLookup.clear();
+                    }
 
-                con.commitNodeBatch();
+                    con.commitNodeBatch();
 
+                }
+            } finally {
+                commitLock.leave();
             }
-        } finally {
-            commitLock.unlock();
         }
 
     }
@@ -825,4 +793,14 @@ public class KiWiValueFactory implements ValueFactory {
             log.warn("could not close value factory connection: {}",e.getMessage());
         }
     }
+
+    /**
+     * A simple Guava cache loader implementation for generating object-based locks
+     */
+    private static class LockCacheLoader extends CacheLoader<Object,Monitor> {
+        @Override
+        public Monitor load(Object key) throws Exception {
+            return new Monitor();
+        }
+    }
 }


[4/7] git commit: implemented deletion of versions also in platform and webservice (MARMOTTA-18)

Posted by ss...@apache.org.
implemented deletion of versions also in platform and webservice (MARMOTTA-18)


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

Branch: refs/heads/develop
Commit: c550034d3a8d76595c662269c260eafc9325c80d
Parents: 18c428a
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Mon Jul 22 11:13:58 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Mon Jul 22 11:13:58 2013 +0200

----------------------------------------------------------------------
 .../services/VersioningSailProvider.java        | 33 +++++++++++++++++++
 .../webservices/VersioningWebService.java       | 34 +++++++++++++++++---
 2 files changed, 62 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c550034d/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java
index 67ad27c..13ebe79 100644
--- a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java
@@ -223,4 +223,37 @@ public class VersioningSailProvider implements TransactionalSailProvider {
     public Version getLatestVersion(Resource r, Date date) throws SailException {
         return sail.getLatestVersion(r, date);
     }
+
+    /**
+     * Remove the version with the id passed as argument, including all references to added and removed triples. The
+     * triples themselves are not deleted immediately, we let the garbage collector carry this out periodically.
+     * @param id  the database ID of the version (see {@link org.apache.marmotta.kiwi.versioning.model.Version#getId()})
+     * @throws org.openrdf.sail.SailException
+     */
+    public void removeVersion(Long id) throws SailException {
+        sail.removeVersion(id);
+    }
+
+    /**
+     * Remove all versions in the given time interval. Iterates over all versions and deletes them individually.
+     * Entries in join tables (added/removed triples) are also deleted, the triples themselves not. Deleted triples
+     * without version will later be cleaned up by the garbage collector
+     * @param from date after which versions will be deleted
+     * @param to   date before which versions will be deleted
+     * @throws org.openrdf.sail.SailException
+     */
+    public void removeVersions(Date from, Date to) throws SailException {
+        sail.removeVersions(from, to);
+    }
+
+    /**
+     * Remove all versions until the date given as argument. Iterates over all versions and deletes them individually.
+     * Entries in join tables (added/removed triples) are also deleted, the triples themselves not. Deleted triples
+     * without version will later be cleaned up by the garbage collector
+     * @param until date until when to delete versions
+     * @throws org.openrdf.sail.SailException
+     */
+    public void removeVersions(Date until) throws SailException {
+        sail.removeVersions(until);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c550034d/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java
index 22a7f32..a71d624 100644
--- a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java
@@ -38,11 +38,7 @@ import org.slf4j.Logger;
 import javax.enterprise.context.ApplicationScoped;
 import javax.enterprise.event.Observes;
 import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
+import javax.ws.rs.*;
 import javax.ws.rs.core.Response;
 import java.util.ArrayList;
 import java.util.Date;
@@ -201,5 +197,33 @@ public class VersioningWebService {
         }
     }
 
+    /**
+     * Remove the version with the given ID from the triple store. Calling this service will only remove the versioning
+     * metadata, not the triples themselves. Triples that are marked as deleted and no longer attached to a version will
+     * be cleaned up by a garbage collection process that is running periodically or can be triggered manually.
+     *
+     * @param id
+     * @return
+     */
+    @DELETE
+    @Path("/versions/{id:[0-9]+}")
+    public Response deleteVersion(@PathParam("id") Long id) {
+        try {
+            Version version = versioningService.getVersion(id);
+
+            if(version != null) {
+                versioningService.removeVersion(id);
+
+                return Response.ok().entity("success").build();
+
+            } else {
+                return Response.status(Response.Status.NOT_FOUND).entity("version with id "+id+" does not exist").build();
+            }
+
+        } catch (SailException e) {
+            return Response.serverError().entity("error deleting version "+id+": "+e.getMessage()).build();
+        }
+    }
+
 
 }


[5/7] git commit: implement reverting of versions (MARMOTTA-19)

Posted by ss...@apache.org.
implement reverting of versions (MARMOTTA-19)


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

Branch: refs/heads/develop
Commit: c5e44113c329cc79f1d4e36af5f4ebedeeac6d2c
Parents: c550034
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Mon Jul 22 11:42:08 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Mon Jul 22 11:42:08 2013 +0200

----------------------------------------------------------------------
 .../versioning/sail/KiWiVersioningSail.java     | 28 ++++++
 .../test/VersioningRepositoryTest.java          | 90 ++++++++++++++++++++
 .../services/VersioningSailProvider.java        | 12 +++
 .../webservices/VersioningWebService.java       | 27 ++++++
 4 files changed, 157 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c5e44113/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/sail/KiWiVersioningSail.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/sail/KiWiVersioningSail.java b/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/sail/KiWiVersioningSail.java
index 7a96b7e..84f448b 100644
--- a/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/sail/KiWiVersioningSail.java
+++ b/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/sail/KiWiVersioningSail.java
@@ -34,6 +34,8 @@ import org.openrdf.model.Statement;
 import org.openrdf.model.URI;
 import org.openrdf.repository.RepositoryException;
 import org.openrdf.repository.RepositoryResult;
+import org.openrdf.repository.sail.SailRepositoryConnection;
+import org.openrdf.sail.SailConnection;
 import org.openrdf.sail.SailException;
 import org.openrdf.sail.StackableSail;
 import org.slf4j.Logger;
@@ -473,6 +475,32 @@ public class KiWiVersioningSail extends TransactionalSailWrapper implements Tran
         }
     }
 
+    /**
+     * Revert (undo) the version given as argument. This method creates a new transaction, adds all triples
+     * that were deleted in the old version, removes all triples that were added in the old version, and commits
+     * the transaction, effectively creating a new (reverted) version.
+     *
+     * @param version    the version to revert
+     * @throws SailException in case reverting the version failed
+     */
+    public void revertVersion(Version version) throws SailException {
+        SailConnection con = getConnection();
+        try {
+            con.begin();
+
+            for(Statement stmt : version.getAddedTriples()) {
+                con.removeStatements(stmt.getSubject(), stmt.getPredicate(), stmt.getObject(), stmt.getContext());
+            }
+
+            for(Statement stmt : version.getRemovedTriples()) {
+                con.addStatement(stmt.getSubject(), stmt.getPredicate(), stmt.getObject(), stmt.getContext());
+            }
+
+            con.commit();
+        } finally {
+            con.close();
+        }
+    }
 
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c5e44113/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java b/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java
index 6757a58..79f9415 100644
--- a/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java
+++ b/libraries/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java
@@ -36,6 +36,7 @@ import org.junit.rules.TestWatcher;
 import org.junit.runner.Description;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
+import org.openrdf.model.URI;
 import org.openrdf.repository.Repository;
 import org.openrdf.repository.RepositoryConnection;
 import org.openrdf.repository.RepositoryException;
@@ -250,6 +251,95 @@ public class VersioningRepositoryTest {
 
 
     /**
+     * This test imports three small RDF files in sequence and checks afterwards that the number of versions
+     * is correct and they contain the correct information
+     * @throws Exception
+     */
+    @Test
+    public void testRevertVersions() throws Exception {
+        // import three files in sequence and check if the versions are created properly
+
+        Date date1 = new Date();
+
+        mysqlSleep();
+
+        // base data
+        InputStream baseData = this.getClass().getResourceAsStream("version-base.rdf");
+        assumeThat("Could not load test-data: version-base.rdf", baseData, notNullValue(InputStream.class));
+
+        RepositoryConnection connectionBase = repository.getConnection();
+        try {
+            connectionBase.add(baseData, "http://marmotta.incubator.apache.org/testing/ns1/", RDFFormat.RDFXML);
+            connectionBase.commit();
+        } finally {
+            connectionBase.close();
+        }
+
+        mysqlSleep();
+
+        Date date2 = new Date();
+
+        mysqlSleep();
+
+        // update 1
+        InputStream update1Data = this.getClass().getResourceAsStream("version-update1.rdf");
+        assumeThat("Could not load test-data: version-update1.rdf", update1Data, notNullValue(InputStream.class));
+
+        RepositoryConnection connectionUpdate1 = repository.getConnection();
+        try {
+            connectionUpdate1.add(update1Data, "http://marmotta.incubator.apache.org/testing/ns1/", RDFFormat.RDFXML);
+            connectionUpdate1.commit();
+        } finally {
+            connectionUpdate1.close();
+        }
+
+        // update 2
+        InputStream update2Data = this.getClass().getResourceAsStream("version-update2.rdf");
+        assumeThat("Could not load test-data: version-update2.rdf", update2Data, notNullValue(InputStream.class));
+
+        RepositoryConnection connectionUpdate2 = repository.getConnection();
+        try {
+            connectionUpdate2.add(update2Data, "http://marmotta.incubator.apache.org/testing/ns1/", RDFFormat.RDFXML);
+            connectionUpdate2.commit();
+        } finally {
+            connectionUpdate2.close();
+        }
+
+        // list all versions
+        List<Version> versions = asList(vsail.listVersions());
+        Assert.assertEquals("expected 3 versions!", 3, versions.size());
+        Assert.assertEquals(1, (long)versions.get(0).getId());
+
+        URI subject = repository.getValueFactory().createURI("http://marmotta.incubator.apache.org/testing/ns1/R1");
+        URI predicate = repository.getValueFactory().createURI("http://marmotta.incubator.apache.org/testing/ns1/P2");
+
+        RepositoryConnection connectionBeforeRevert = repository.getConnection();
+        try {
+            Assert.assertTrue(connectionBeforeRevert.hasStatement(subject,predicate,null,true));
+        } finally {
+            connectionBeforeRevert.close();
+        }
+
+        // revert version; afterwards we expect there to be 4 versions
+        vsail.revertVersion(versions.get(0));
+
+        List<Version> versions2 = asList(vsail.listVersions());
+        Assert.assertEquals("expected 4 versions!", 4, versions2.size());
+
+        // the repository should now lo longer contain any P2 property for ns1:C
+        RepositoryConnection connectionAfterRevert = repository.getConnection();
+        try {
+            Assert.assertFalse(connectionAfterRevert.hasStatement(subject, predicate, null, true));
+        } finally {
+            connectionAfterRevert.close();
+        }
+
+
+
+    }
+
+
+    /**
      * MYSQL rounds timestamps to the second, so it is sometimes necessary to sleep before doing a test
      */
     private  void mysqlSleep() {

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c5e44113/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java
index 13ebe79..f470c6c 100644
--- a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java
@@ -256,4 +256,16 @@ public class VersioningSailProvider implements TransactionalSailProvider {
     public void removeVersions(Date until) throws SailException {
         sail.removeVersions(until);
     }
+
+    /**
+     * Revert (undo) the version given as argument. This method creates a new transaction, adds all triples
+     * that were deleted in the old version, removes all triples that were added in the old version, and commits
+     * the transaction, effectively creating a new (reverted) version.
+     *
+     * @param version    the version to revert
+     * @throws org.openrdf.sail.SailException in case reverting the version failed
+     */
+    public void revertVersion(Version version) throws SailException {
+        sail.revertVersion(version);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c5e44113/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java
index a71d624..22aa6bd 100644
--- a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java
@@ -226,4 +226,31 @@ public class VersioningWebService {
     }
 
 
+    /**
+     * Revert (undo) the version with the given ID. Calling this service will add all removed triples and remove all
+     * added triples of the old version. If versioning is active, this will create a new version as well.
+     *
+     * @param id
+     * @return
+     */
+    @POST
+    @Path("/versions/{id:[0-9]+}")
+    public Response revertVersion(@PathParam("id") Long id) {
+        try {
+            Version version = versioningService.getVersion(id);
+
+            if(version != null) {
+                versioningService.removeVersion(id);
+
+                return Response.ok().entity("success").build();
+
+            } else {
+                return Response.status(Response.Status.NOT_FOUND).entity("version with id "+id+" does not exist").build();
+            }
+
+        } catch (SailException e) {
+            return Response.serverError().entity("error deleting version "+id+": "+e.getMessage()).build();
+        }
+    }
+
 }


[7/7] git commit: Merge remote-tracking branch 'origin/develop' into develop

Posted by ss...@apache.org.
Merge remote-tracking branch 'origin/develop' 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/a6a44101
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/a6a44101
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/a6a44101

Branch: refs/heads/develop
Commit: a6a441011365b1bcb91a9e1c90cf429c94d38c83
Parents: 7dc7851 3af07e3
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Mon Jul 22 12:55:50 2013 +0200
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Mon Jul 22 12:55:50 2013 +0200

----------------------------------------------------------------------
 extras/webjars/codemirror/pom.xml | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
----------------------------------------------------------------------