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:11 UTC

[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

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();
+        }
+    }
 }