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/03/21 14:58:28 UTC
[2/4] git commit: fix bug in KiWiValueFactory and improve concurrency
performance
fix bug in KiWiValueFactory and improve concurrency performance
Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/c4ca14f0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/c4ca14f0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/c4ca14f0
Branch: refs/heads/master
Commit: c4ca14f0af00bd79e2ab5b03f2cde7b2a292f7f1
Parents: ca4cc05
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Thu Mar 21 14:55:54 2013 +0100
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Thu Mar 21 14:55:54 2013 +0100
----------------------------------------------------------------------
.../persistence/KiWiReasoningConnection.java | 41 ++-
.../persistence/KiWiReasoningPersistence.java | 2 +-
.../kiwi/model/collection/WeakValueMap.java | 357 ---------------
.../marmotta/kiwi/persistence/KiWiConnection.java | 148 ++++++-
.../marmotta/kiwi/persistence/KiWiPersistence.java | 8 +-
.../marmotta/kiwi/sail/KiWiSailConnection.java | 18 +-
.../org/apache/marmotta/kiwi/sail/KiWiStore.java | 5 -
.../marmotta/kiwi/sail/KiWiValueFactory.java | 51 ++-
.../kiwi/persistence/h2/statements.properties | 1 +
.../kiwi/persistence/mysql/statements.properties | 1 +
.../kiwi/persistence/pgsql/statements.properties | 1 +
.../apache/marmotta/kiwi/test/RepositoryTest.java | 56 +++
.../persistence/KiWiVersioningConnection.java | 24 +-
.../persistence/KiWiVersioningPersistence.java | 2 +-
14 files changed, 319 insertions(+), 396 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/persistence/KiWiReasoningConnection.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/persistence/KiWiReasoningConnection.java b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/persistence/KiWiReasoningConnection.java
index ce041e7..94daf8a 100644
--- a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/persistence/KiWiReasoningConnection.java
+++ b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/persistence/KiWiReasoningConnection.java
@@ -29,6 +29,7 @@ import org.apache.marmotta.kiwi.model.rdf.KiWiNode;
import org.apache.marmotta.kiwi.model.rdf.KiWiTriple;
import org.apache.marmotta.kiwi.persistence.KiWiConnection;
import org.apache.marmotta.kiwi.persistence.KiWiDialect;
+import org.apache.marmotta.kiwi.persistence.KiWiPersistence;
import org.apache.marmotta.kiwi.persistence.util.ResultSetIteration;
import org.apache.marmotta.kiwi.persistence.util.ResultTransformerFunction;
import org.apache.marmotta.kiwi.reasoner.model.program.Field;
@@ -75,8 +76,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
private Cache ruleIdCache;
- public KiWiReasoningConnection(Connection connection, KiWiDialect dialect, KiWiCacheManager cacheManager, ValueFactory valueFactory) throws SQLException {
- super(connection, dialect, cacheManager);
+ public KiWiReasoningConnection(KiWiPersistence persistence, KiWiDialect dialect, KiWiCacheManager cacheManager, ValueFactory valueFactory) throws SQLException {
+ super(persistence, dialect, cacheManager);
this.valueFactory = valueFactory;
this.ruleIdCache = getCacheManager().getCacheByName("reasoning-rule-id");
@@ -96,6 +97,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
return;
}
+ requireJDBCConnection();
+
// first create a new entry in the rules table
rule.setId(getNextSequence("seq.rules"));
@@ -125,6 +128,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
if(cached != null) {
return (Rule) cached.getObjectValue();
} else {
+ requireJDBCConnection();
+
// load namespaces if they are not yet given
if(namespaces == null) {
namespaces = new HashMap<String, String>();
@@ -166,6 +171,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
*/
public CloseableIteration<Rule,SQLException> loadRulesByProgram(long programId, final Map<String, String> namespaces) throws SQLException, ParseException {
+ requireJDBCConnection();
+
PreparedStatement loadRule = getPreparedStatement("rules.load_by_program");
synchronized (loadRule) {
loadRule.setLong(1,programId);
@@ -218,6 +225,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
return;
}
+ requireJDBCConnection();
+
PreparedStatement deleteRule = getPreparedStatement("rules.delete_by_id");
synchronized (deleteRule) {
deleteRule.setLong(1, rule.getId());
@@ -242,6 +251,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
throw new SQLException("Program already stored in the database");
}
+ requireJDBCConnection();
+
// steps:
// 1) create a program entry in the reasoner_programs table
@@ -316,6 +327,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
* @throws SQLException
*/
public void updateProgram(Program program) throws SQLException {
+ requireJDBCConnection();
+
// steps:
// 1) load old program by name
// 2) create a diff between old and new program as follows:
@@ -435,6 +448,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
* @throws SQLException in case of a database problem or an unparsable program
*/
public Program loadProgram(String name) throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement loadProgram = getPreparedStatement("programs.load_by_name");
synchronized (loadProgram) {
loadProgram.setString(1, name);
@@ -462,6 +477,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
* @throws SQLException
*/
public Program loadProgram(Long id) throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement loadProgram = getPreparedStatement("programs.load_by_id");
synchronized (loadProgram) {
loadProgram.setLong(1, id);
@@ -519,6 +536,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
* @throws SQLException
*/
public CloseableIteration<Program, SQLException> listPrograms() throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement listPrograms = getPreparedStatement("programs.list");
synchronized (listPrograms) {
ResultSet result = listPrograms.executeQuery();
@@ -550,6 +569,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
return;
}
+ requireJDBCConnection();
+
// 1. delete all rule associations and rules including the justifications they depend on
PreparedStatement deleteProgramRule = getPreparedStatement("programs.delete_rule");
PreparedStatement deleteRule = getPreparedStatement("rules.delete_by_id");
@@ -600,6 +621,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
* @throws SQLException
*/
public void storeJustifications(Iterable<Justification> justifications) throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement insertJustification = getPreparedStatement("justifications.insert");
PreparedStatement justificationAddTriple = getPreparedStatement("justifications.add_triple");
PreparedStatement justificationAddRule = getPreparedStatement("justifications.add_rule");
@@ -675,6 +698,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
* @throws SQLException
*/
public void deleteJustifications(Iteration<Justification, SQLException> justifications) throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement deleteJustification = getPreparedStatement("justifications.delete");
PreparedStatement deleteJustificationRules = getPreparedStatement("justifications.del_rule");
PreparedStatement deleteJustificationTriples = getPreparedStatement("justifications.del_triple");
@@ -736,6 +761,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
* @throws SQLException
*/
public void deleteJustifications() throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement deleteJustification = getPreparedStatement("justifications.delete_all");
PreparedStatement deleteJustificationRules = getPreparedStatement("justifications.delete_all_rules");
PreparedStatement deleteJustificationTriples = getPreparedStatement("justifications.delete_all_triples");
@@ -757,6 +784,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
if(rule.getId() == null) {
return new EmptyIteration<Justification, SQLException>();
} else {
+ requireJDBCConnection();
+
PreparedStatement listByRule = getPreparedStatement("justifications.load_by_srule");
synchronized (listByRule) {
listByRule.setLong(1, rule.getId());
@@ -783,6 +812,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
if(triple.getId() == null) {
return new EmptyIteration<Justification, SQLException>();
} else {
+ requireJDBCConnection();
+
PreparedStatement listByTriple = getPreparedStatement("justifications.load_by_striple");
synchronized (listByTriple) {
listByTriple.setLong(1, triple.getId());
@@ -820,6 +851,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
* @throws SQLException
*/
public CloseableIteration<Justification,SQLException> listJustificationsForTriple(long tripleId) throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement listForTriple = getPreparedStatement("justifications.load_by_triple");
synchronized (listForTriple) {
listForTriple.setLong(1, tripleId);
@@ -872,6 +905,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
* @throws SQLException
*/
public CloseableIteration<KiWiTriple, SQLException> listUnsupportedTriples() throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement listUnsupported = getPreparedStatement("justifications.list_unsupported");
synchronized (listUnsupported) {
ResultSet result = listUnsupported.executeQuery();
@@ -913,6 +948,8 @@ public class KiWiReasoningConnection extends KiWiConnection {
* variables and offset and limited by the parameters given
*/
public CloseableIteration<QueryResult, SQLException> query(final Collection<Pattern> patterns, final QueryResult initialBindings, Set<Filter> filters, List<VariableField> orderBy, final boolean justifications) throws SQLException {
+ requireJDBCConnection();
+
if(filters != null) {
throw new IllegalArgumentException("filters are not yet supported by the QueryService");
}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/persistence/KiWiReasoningPersistence.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/persistence/KiWiReasoningPersistence.java b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/persistence/KiWiReasoningPersistence.java
index e6fccc0..db1bb7a 100644
--- a/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/persistence/KiWiReasoningPersistence.java
+++ b/libraries/kiwi/kiwi-reasoner/src/main/java/org/apache/marmotta/kiwi/reasoner/persistence/KiWiReasoningPersistence.java
@@ -90,7 +90,7 @@ public class KiWiReasoningPersistence {
* @throws java.sql.SQLException in case a new connection could not be established
*/
public KiWiReasoningConnection getConnection() throws SQLException {
- return new KiWiReasoningConnection(persistence.getJDBCConnection(), persistence.getDialect(), persistence.getCacheManager(), valueFactory );
+ return new KiWiReasoningConnection(persistence, persistence.getDialect(), persistence.getCacheManager(), valueFactory );
}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/model/collection/WeakValueMap.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/model/collection/WeakValueMap.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/model/collection/WeakValueMap.java
deleted file mode 100644
index c85969d..0000000
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/model/collection/WeakValueMap.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.marmotta.kiwi.model.collection;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableSet;
-
-import java.lang.ref.WeakReference;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * An implementation of a hash map with weak values (similar to the Java WeakHashMap, which uses weak keys).
- * <p/>
- * Author: Sebastian Schaffert
- */
-public class WeakValueMap<K,V> implements Map<K,V> {
-
-
- private HashMap<K,WeakReference<V>> delegate;
-
-
- public WeakValueMap() {
- delegate = new HashMap<K, WeakReference<V>>();
- }
-
-
- public WeakValueMap(int initialCapacity) {
- delegate = new HashMap<K, WeakReference<V>>(initialCapacity);
- }
-
-
- /**
- * Removes all of the mappings from this map (optional operation).
- * The map will be empty after this call returns.
- *
- * @throws UnsupportedOperationException if the <tt>clear</tt> operation
- * is not supported by this map
- */
- @Override
- public void clear() {
- delegate.clear();
- }
-
- /**
- * Returns the number of key-value mappings in this map. If the
- * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
- * <tt>Integer.MAX_VALUE</tt>.
- *
- * @return the number of key-value mappings in this map
- */
- @Override
- public int size() {
- return delegate.size();
- }
-
- /**
- * Returns <tt>true</tt> if this map contains no key-value mappings.
- *
- * @return <tt>true</tt> if this map contains no key-value mappings
- */
- @Override
- public boolean isEmpty() {
- return delegate.isEmpty();
- }
-
-
- /**
- * Returns <tt>true</tt> if this map contains a mapping for the specified
- * key. More formally, returns <tt>true</tt> if and only if
- * this map contains a mapping for a key <tt>k</tt> such that
- * <tt>(key==null ? k==null : key.equals(k))</tt>. (There can be
- * at most one such mapping.)
- *
- * @param key key whose presence in this map is to be tested
- * @return <tt>true</tt> if this map contains a mapping for the specified
- * key
- * @throws ClassCastException if the key is of an inappropriate type for
- * this map
- * (<a href="Collection.html#optional-restrictions">optional</a>)
- * @throws NullPointerException if the specified key is null and this map
- * does not permit null keys
- * (<a href="Collection.html#optional-restrictions">optional</a>)
- */
- @Override
- public boolean containsKey(Object key) {
- return delegate.containsKey(key);
- }
-
- /**
- * Returns <tt>true</tt> if this map maps one or more keys to the
- * specified value. More formally, returns <tt>true</tt> if and only if
- * this map contains at least one mapping to a value <tt>v</tt> such that
- * <tt>(value==null ? v==null : value.equals(v))</tt>. This operation
- * will probably require time linear in the map size for most
- * implementations of the <tt>Map</tt> interface.
- *
- * @param value value whose presence in this map is to be tested
- * @return <tt>true</tt> if this map maps one or more keys to the
- * specified value
- * @throws ClassCastException if the value is of an inappropriate type for
- * this map
- * (<a href="Collection.html#optional-restrictions">optional</a>)
- * @throws NullPointerException if the specified value is null and this
- * map does not permit null values
- * (<a href="Collection.html#optional-restrictions">optional</a>)
- */
- @Override
- @SuppressWarnings("unchecked")
- public boolean containsValue(Object value) {
- try {
- return delegate.containsValue(new WeakReference<V>((V)value));
- } catch(ClassCastException ex) {
- return false;
- }
- }
-
- /**
- * Returns the value to which the specified key is mapped,
- * or {@code null} if this map contains no mapping for the key.
- * <p/>
- * <p>More formally, if this map contains a mapping from a key
- * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
- * key.equals(k))}, then this method returns {@code v}; otherwise
- * it returns {@code null}. (There can be at most one such mapping.)
- * <p/>
- * <p>If this map permits null values, then a return value of
- * {@code null} does not <i>necessarily</i> indicate that the map
- * contains no mapping for the key; it's also possible that the map
- * explicitly maps the key to {@code null}. The {@link #containsKey
- * containsKey} operation may be used to distinguish these two cases.
- *
- * @param key the key whose associated value is to be returned
- * @return the value to which the specified key is mapped, or
- * {@code null} if this map contains no mapping for the key
- * @throws ClassCastException if the key is of an inappropriate type for
- * this map
- * (<a href="Collection.html#optional-restrictions">optional</a>)
- * @throws NullPointerException if the specified key is null and this map
- * does not permit null keys
- * (<a href="Collection.html#optional-restrictions">optional</a>)
- */
- @Override
- public V get(Object key) {
- WeakReference<V> ref = delegate.get(key);
- if(ref != null) {
- return ref.get();
- } else {
- return null;
- }
- }
-
- /**
- * Associates the specified value with the specified key in this map
- * (optional operation). If the map previously contained a mapping for
- * the key, the old value is replaced by the specified value. (A map
- * <tt>m</tt> is said to contain a mapping for a key <tt>k</tt> if and only
- * if {@link #containsKey(Object) m.containsKey(k)} would return
- * <tt>true</tt>.)
- *
- * @param key key with which the specified value is to be associated
- * @param value value to be associated with the specified key
- * @return the previous value associated with <tt>key</tt>, or
- * <tt>null</tt> if there was no mapping for <tt>key</tt>.
- * (A <tt>null</tt> return can also indicate that the map
- * previously associated <tt>null</tt> with <tt>key</tt>,
- * if the implementation supports <tt>null</tt> values.)
- * @throws UnsupportedOperationException if the <tt>put</tt> operation
- * is not supported by this map
- * @throws ClassCastException if the class of the specified key or value
- * prevents it from being stored in this map
- * @throws NullPointerException if the specified key or value is null
- * and this map does not permit null keys or values
- * @throws IllegalArgumentException if some property of the specified key
- * or value prevents it from being stored in this map
- */
- @Override
- public V put(K key, V value) {
- WeakReference<V> prev = delegate.put(key,new WeakReference<V>(value));
-
- if(prev != null) {
- return prev.get();
- } else {
- return null;
- }
- }
-
- /**
- * Removes the mapping for a key from this map if it is present
- * (optional operation). More formally, if this map contains a mapping
- * from key <tt>k</tt> to value <tt>v</tt> such that
- * <code>(key==null ? k==null : key.equals(k))</code>, that mapping
- * is removed. (The map can contain at most one such mapping.)
- * <p/>
- * <p>Returns the value to which this map previously associated the key,
- * or <tt>null</tt> if the map contained no mapping for the key.
- * <p/>
- * <p>If this map permits null values, then a return value of
- * <tt>null</tt> does not <i>necessarily</i> indicate that the map
- * contained no mapping for the key; it's also possible that the map
- * explicitly mapped the key to <tt>null</tt>.
- * <p/>
- * <p>The map will not contain a mapping for the specified key once the
- * call returns.
- *
- * @param key key whose mapping is to be removed from the map
- * @return the previous value associated with <tt>key</tt>, or
- * <tt>null</tt> if there was no mapping for <tt>key</tt>.
- * @throws UnsupportedOperationException if the <tt>remove</tt> operation
- * is not supported by this map
- * @throws ClassCastException if the key is of an inappropriate type for
- * this map
- * (<a href="Collection.html#optional-restrictions">optional</a>)
- * @throws NullPointerException if the specified key is null and this
- * map does not permit null keys
- * (<a href="Collection.html#optional-restrictions">optional</a>)
- */
- @Override
- public V remove(Object key) {
- WeakReference<V> ref = delegate.remove(key);
- if(ref != null) {
- return ref.get();
- } else {
- return null;
- }
- }
-
- /**
- * Copies all of the mappings from the specified map to this map
- * (optional operation). The effect of this call is equivalent to that
- * of calling {@link #put(Object, Object) put(k, v)} on this map once
- * for each mapping from key <tt>k</tt> to value <tt>v</tt> in the
- * specified map. The behavior of this operation is undefined if the
- * specified map is modified while the operation is in progress.
- *
- * @param m mappings to be stored in this map
- * @throws UnsupportedOperationException if the <tt>putAll</tt> operation
- * is not supported by this map
- * @throws ClassCastException if the class of a key or value in the
- * specified map prevents it from being stored in this map
- * @throws NullPointerException if the specified map is null, or if
- * this map does not permit null keys or values, and the
- * specified map contains null keys or values
- * @throws IllegalArgumentException if some property of a key or value in
- * the specified map prevents it from being stored in this map
- */
- @Override
- public void putAll(Map<? extends K, ? extends V> m) {
- for(Entry<? extends K,? extends V> entry : m.entrySet()) {
- delegate.put(entry.getKey(),new WeakReference<V>(entry.getValue()));
- }
- }
-
- /**
- * Returns a {@link java.util.Set} view of the keys contained in this map.
- * The set is backed by the map, so changes to the map are
- * reflected in the set, and vice-versa. If the map is modified
- * while an iteration over the set is in progress (except through
- * the iterator's own <tt>remove</tt> operation), the results of
- * the iteration are undefined. The set supports element removal,
- * which removes the corresponding mapping from the map, via the
- * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
- * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
- * operations. It does not support the <tt>add</tt> or <tt>addAll</tt>
- * operations.
- *
- * @return a set view of the keys contained in this map
- */
- @Override
- public Set<K> keySet() {
- return delegate.keySet();
- }
-
- /**
- * Returns a {@link java.util.Collection} view of the values contained in this map.
- * The collection is backed by the map, so changes to the map are
- * reflected in the collection, and vice-versa. If the map is
- * modified while an iteration over the collection is in progress
- * (except through the iterator's own <tt>remove</tt> operation),
- * the results of the iteration are undefined. The collection
- * supports element removal, which removes the corresponding
- * mapping from the map, via the <tt>Iterator.remove</tt>,
- * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
- * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not
- * support the <tt>add</tt> or <tt>addAll</tt> operations.
- *
- * @return a collection view of the values contained in this map
- */
- @Override
- public Collection<V> values() {
- return Collections2.transform(delegate.values(), new Function<WeakReference<V>, V>() {
- @Override
- public V apply(WeakReference<V> input) {
- return input.get();
- }
- });
- }
-
- /**
- * Returns a {@link java.util.Set} view of the mappings contained in this map.
- * The set is backed by the map, so changes to the map are
- * reflected in the set, and vice-versa. If the map is modified
- * while an iteration over the set is in progress (except through
- * the iterator's own <tt>remove</tt> operation, or through the
- * <tt>setValue</tt> operation on a map entry returned by the
- * iterator) the results of the iteration are undefined. The set
- * supports element removal, which removes the corresponding
- * mapping from the map, via the <tt>Iterator.remove</tt>,
- * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
- * <tt>clear</tt> operations. It does not support the
- * <tt>add</tt> or <tt>addAll</tt> operations.
- *
- * @return a set view of the mappings contained in this map
- */
- @Override
- public Set<Entry<K, V>> entrySet() {
- return ImmutableSet.copyOf(Collections2.transform(delegate.entrySet(), new Function<Entry<K, WeakReference<V>>, Entry<K, V>>() {
- @Override
- public Entry<K, V> apply(final Entry<K, WeakReference<V>> input) {
- return new Entry<K,V>() {
- @Override
- public K getKey() {
- return input.getKey();
- }
-
- @Override
- public V getValue() {
- return input.getValue().get();
- }
-
- @Override
- public V setValue(V value) {
- return input.setValue(new WeakReference<V>(value)).get();
- }
- };
- }
- }));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/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 c8e27d0..e582631 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
@@ -66,6 +66,7 @@ public class KiWiConnection {
protected Connection connection;
+ protected KiWiPersistence persistence;
protected KiWiCacheManager cacheManager;
@@ -116,11 +117,13 @@ public class KiWiConnection {
private Map<String,PreparedStatement> statementCache;
+ private boolean autoCommit = false;
- public KiWiConnection(Connection connection, KiWiDialect dialect, KiWiCacheManager cacheManager) throws SQLException {
+
+ public KiWiConnection(KiWiPersistence persistence, KiWiDialect dialect, KiWiCacheManager cacheManager) throws SQLException {
this.cacheManager = cacheManager;
- this.connection = connection;
- this.dialect = dialect;
+ this.dialect = dialect;
+ this.persistence = persistence;
initCachePool();
initStatementCache();
@@ -151,6 +154,16 @@ public class KiWiConnection {
*/
}
+ /**
+ * This method must be called by all methods as soon as they actually require a JDBC connection. This allows
+ * more efficient implementations in case the queries can be answered directly from the cache.
+ */
+ protected void requireJDBCConnection() throws SQLException {
+ if(connection == null) {
+ connection = persistence.getJDBCConnection();
+ connection.setAutoCommit(autoCommit);
+ }
+ }
/**
* Get direct access to the JDBC connection used by this KiWiConnection.
@@ -184,6 +197,8 @@ public class KiWiConnection {
return (KiWiNamespace)element.getObjectValue();
}
+ requireJDBCConnection();
+
// prepare a query; we will only iterate once, read only, and need only one result row since the id is unique
PreparedStatement query = getPreparedStatement("load.namespace_prefix");
query.setString(1, prefix);
@@ -218,6 +233,8 @@ public class KiWiConnection {
return (KiWiNamespace)element.getObjectValue();
}
+ requireJDBCConnection();
+
// prepare a query; we will only iterate once, read only, and need only one result row since the id is unique
PreparedStatement query = getPreparedStatement("load.namespace_uri");
query.setString(1, uri);
@@ -251,6 +268,8 @@ public class KiWiConnection {
return;
}
+ requireJDBCConnection();
+
namespace.setId(getNextSequence("seq.namespaces"));
PreparedStatement insertNamespace = getPreparedStatement("store.namespace");
@@ -276,6 +295,8 @@ public class KiWiConnection {
return;
}
+ requireJDBCConnection();
+
PreparedStatement deleteNamespace = getPreparedStatement("delete.namespace");
deleteNamespace.setLong(1, namespace.getId());
deleteNamespace.executeUpdate();
@@ -290,6 +311,8 @@ public class KiWiConnection {
* @throws SQLException
*/
public long getSize() throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement querySize = getPreparedStatement("query.size");
ResultSet result = querySize.executeQuery();
try {
@@ -312,6 +335,9 @@ public class KiWiConnection {
if(context.getId() == null) {
return 0;
};
+
+ requireJDBCConnection();
+
PreparedStatement querySize = getPreparedStatement("query.size_ctx");
querySize.setLong(1,context.getId());
@@ -361,6 +387,8 @@ public class KiWiConnection {
return (KiWiNode)element.getObjectValue();
}
+ requireJDBCConnection();
+
// prepare a query; we will only iterate once, read only, and need only one result row since the id is unique
PreparedStatement query = getPreparedStatement("load.node_by_id");
query.setLong(1,id);
@@ -389,6 +417,8 @@ public class KiWiConnection {
return (KiWiTriple)element.getObjectValue();
}
+ requireJDBCConnection();
+
// prepare a query; we will only iterate once, read only, and need only one result row since the id is unique
PreparedStatement query = getPreparedStatement("load.triple_by_id");
query.setLong(1,id);
@@ -427,6 +457,8 @@ public class KiWiConnection {
return (KiWiUriResource)element.getObjectValue();
}
+ requireJDBCConnection();
+
// prepare a query; we will only iterate once, read only, and need only one result row since the id is unique
PreparedStatement query = getPreparedStatement("load.uri_by_uri");
query.setString(1, uri);
@@ -466,6 +498,8 @@ public class KiWiConnection {
return (KiWiAnonResource)element.getObjectValue();
}
+ requireJDBCConnection();
+
// prepare a query; we will only iterate once, read only, and need only one result row since the id is unique
PreparedStatement query = getPreparedStatement("load.bnode_by_anonid");
query.setString(1,id);
@@ -512,6 +546,8 @@ public class KiWiConnection {
return null;
}
+ requireJDBCConnection();
+
// otherwise prepare a query, depending on the parameters given
final PreparedStatement query;
if(lang == null && ltype == null) {
@@ -570,6 +606,8 @@ public class KiWiConnection {
return (KiWiDateLiteral)element.getObjectValue();
}
+ requireJDBCConnection();
+
// otherwise prepare a query, depending on the parameters given
PreparedStatement query = getPreparedStatement("load.literal_by_tv");
query.setTimestamp(1, new Timestamp(DateUtils.getDateWithoutFraction(date).getTime()));
@@ -617,6 +655,8 @@ public class KiWiConnection {
return (KiWiIntLiteral)element.getObjectValue();
}
+ requireJDBCConnection();
+
// otherwise prepare a query, depending on the parameters given
PreparedStatement query = getPreparedStatement("load.literal_by_iv");
query.setLong(1,value);
@@ -663,6 +703,8 @@ public class KiWiConnection {
return (KiWiDoubleLiteral)element.getObjectValue();
}
+ requireJDBCConnection();
+
// otherwise prepare a query, depending on the parameters given
PreparedStatement query = getPreparedStatement("load.literal_by_dv");
query.setDouble(1, value);
@@ -710,6 +752,8 @@ public class KiWiConnection {
}
+ requireJDBCConnection();
+
// otherwise prepare a query, depending on the parameters given
PreparedStatement query = getPreparedStatement("load.literal_by_bv");
query.setBoolean(1, value);
@@ -760,6 +804,8 @@ public class KiWiConnection {
}
}
+ requireJDBCConnection();
+
// retrieve a new node id and set it in the node object
node.setId(getNextSequence("seq.nodes"));
@@ -884,6 +930,8 @@ public class KiWiConnection {
Preconditions.checkNotNull(triple.getContext().getId());
+ requireJDBCConnection();
+
// retrieve a new triple ID and set it in the object
triple.setId(getNextSequence("seq.triples"));
@@ -916,6 +964,8 @@ public class KiWiConnection {
return;
}
+ requireJDBCConnection();
+
PreparedStatement deleteTriple = getPreparedStatement("delete.triple");
deleteTriple.setLong(1,triple.getId());
deleteTriple.executeUpdate();
@@ -928,6 +978,43 @@ public class KiWiConnection {
}
/**
+ * Mark the triple passed as argument as not deleted, setting the "deleted" flag to false and
+ * clearing the timestamp value of "deletedAt".
+ * <p/>
+ * Note that this operation should only be called if the triple was deleted before in the same
+ * transaction!
+ *
+ * @param triple
+ */
+ public void undeleteTriple(KiWiTriple triple) throws SQLException {
+ if(triple.getId() == null) {
+ log.warn("attempting to undelete non-persistent triple: {}",triple);
+ return;
+ }
+
+ requireJDBCConnection();
+
+ synchronized (triple) {
+ if(!triple.isDeleted()) {
+ log.warn("attemting to undelete triple that was not deleted: {}",triple);
+ return;
+ }
+
+ PreparedStatement undeleteTriple = getPreparedStatement("undelete.triple");
+ undeleteTriple.setLong(1, triple.getId());
+ undeleteTriple.executeUpdate();
+
+ // make sure the triple is marked as deleted in case some service still holds a reference
+ triple.setDeleted(false);
+ triple.setDeletedAt(null);
+
+ cacheTriple(triple);
+ }
+
+ }
+
+
+ /**
* Remove from the database all triples that have been marked as deleted and are not referenced by any other
* entity.
*/
@@ -942,6 +1029,8 @@ public class KiWiConnection {
* @throws SQLException
*/
public CloseableIteration<KiWiResource, SQLException> listContexts() throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement queryContexts = getPreparedStatement("query.contexts");
final ResultSet result = queryContexts.executeQuery();
@@ -957,6 +1046,8 @@ public class KiWiConnection {
public CloseableIteration<KiWiNamespace, SQLException> listNamespaces() throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement queryContexts = getPreparedStatement("query.namespaces");
final ResultSet result = queryContexts.executeQuery();
@@ -1030,6 +1121,8 @@ public class KiWiConnection {
return new EmptyIteration<Statement, SQLException>();
}
+ requireJDBCConnection();
+
// otherwise we need to create an appropriate SQL query and execute it, the repository result will be read-only
// and only allow forward iteration, so we can limit the query using the respective flags
PreparedStatement query = connection.prepareStatement(
@@ -1283,6 +1376,8 @@ public class KiWiConnection {
* @throws SQLException
*/
public PreparedStatement getPreparedStatement(String key) throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement statement = statementCache.get(key);
if(statement == null) {
statement = connection.prepareStatement(dialect.getStatement(key));
@@ -1301,6 +1396,8 @@ public class KiWiConnection {
* @throws SQLException
*/
public long getNextSequence(String sequenceName) throws SQLException {
+ requireJDBCConnection();
+
// retrieve a new node id and set it in the node object
// if there is a preparation needed to update the transaction, run it first
@@ -1359,6 +1456,8 @@ public class KiWiConnection {
* @throws SQLException
*/
public Set<String> getDatabaseTables() throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement statement = getPreparedStatement("meta.tables");
ResultSet result = statement.executeQuery();
try {
@@ -1380,6 +1479,8 @@ public class KiWiConnection {
* @return
*/
public int getDatabaseVersion() throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement statement = getPreparedStatement("meta.version");
ResultSet result = statement.executeQuery();
try {
@@ -1430,7 +1531,10 @@ public class KiWiConnection {
* @see #getAutoCommit
*/
public void setAutoCommit(boolean autoCommit) throws SQLException {
- connection.setAutoCommit(autoCommit);
+ this.autoCommit = autoCommit;
+ if(connection != null) {
+ connection.setAutoCommit(autoCommit);
+ }
}
@@ -1445,7 +1549,7 @@ public class KiWiConnection {
* @see #setAutoCommit
*/
public boolean getAutoCommit() throws SQLException {
- return connection.getAutoCommit();
+ return autoCommit;
}
/**
@@ -1462,7 +1566,9 @@ public class KiWiConnection {
* @see #setAutoCommit
*/
public void commit() throws SQLException {
- connection.commit();
+ if(connection != null) {
+ connection.commit();
+ }
}
/**
@@ -1478,7 +1584,7 @@ public class KiWiConnection {
* @see #setAutoCommit
*/
public void rollback() throws SQLException {
- if(!connection.isClosed()) {
+ if(connection != null && !connection.isClosed()) {
connection.rollback();
}
}
@@ -1501,7 +1607,11 @@ public class KiWiConnection {
* @exception java.sql.SQLException if a database access error occurs
*/
public boolean isClosed() throws SQLException {
- return connection.isClosed();
+ if(connection != null) {
+ return connection.isClosed();
+ } else {
+ return false;
+ }
}
@@ -1521,17 +1631,19 @@ public class KiWiConnection {
* @exception java.sql.SQLException SQLException if a database access error occurs
*/
public void close() throws SQLException {
- // close all prepared statements
- try {
- for(Map.Entry<String,PreparedStatement> entry : statementCache.entrySet()) {
- try {
- entry.getValue().close();
- } catch (SQLException ex) {}
+ if(connection != null) {
+ // close all prepared statements
+ try {
+ for(Map.Entry<String,PreparedStatement> entry : statementCache.entrySet()) {
+ try {
+ entry.getValue().close();
+ } catch (SQLException ex) {}
+ }
+ } catch(AbstractMethodError ex) {
+ log.debug("database system does not allow closing statements");
}
- } catch(AbstractMethodError ex) {
- log.debug("database system does not allow closing statements");
- }
- connection.close();
+ connection.close();
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/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 399b4eb..bb8604d 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
@@ -291,13 +291,7 @@ public class KiWiPersistence {
* @throws SQLException in case a new connection could not be established
*/
public KiWiConnection getConnection() throws SQLException {
- Connection conn = connectionPool.getConnection();
- conn.setAutoCommit(false);
- //conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
-
- //managedConnections.add(conn);
-
- return new KiWiConnection(conn,dialect,cacheManager);
+ return new KiWiConnection(this,dialect,cacheManager);
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiSailConnection.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiSailConnection.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiSailConnection.java
index 9ba9399..d4c84b3 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiSailConnection.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiSailConnection.java
@@ -89,6 +89,7 @@ public class KiWiSailConnection extends NotifyingSailConnectionBase implements I
private boolean triplesAdded, triplesRemoved;
+ private HashSet<Long> deletedStatementsLog;
public KiWiSailConnection(KiWiStore sailBase) throws SailException {
super(sailBase);
@@ -160,13 +161,21 @@ public class KiWiSailConnection extends NotifyingSailConnectionBase implements I
for(Resource context : contextSet) {
KiWiResource kcontext = valueFactory.convert(context);
- KiWiTriple triple = (KiWiTriple)valueFactory.createStatement(ksubj,kpred,kobj,kcontext);
+ KiWiTriple triple = (KiWiTriple)valueFactory.createStatement(ksubj,kpred,kobj,kcontext, databaseConnection);
triple.setInferred(inferred);
if(triple.getId() == null) {
databaseConnection.storeTriple(triple);
triplesAdded = true;
notifyStatementAdded(triple);
+ } else if(deletedStatementsLog.contains(triple.getId())) {
+ // this is a hack for a concurrency problem that may occur in case the triple is removed in the
+ // transaction and then added again; in these cases the createStatement method might return
+ // an expired state of the triple because it uses its own database connection
+
+ databaseConnection.undeleteTriple(triple);
+ triplesAdded = true;
+ notifyStatementAdded(triple);
}
added.add(triple);
@@ -334,6 +343,7 @@ public class KiWiSailConnection extends NotifyingSailConnectionBase implements I
// nothing to do, the database transaction is started automatically
triplesAdded = false;
triplesRemoved = false;
+ deletedStatementsLog = new HashSet<Long>();
}
@Override
@@ -344,6 +354,8 @@ public class KiWiSailConnection extends NotifyingSailConnectionBase implements I
throw new SailException("database error while committing transaction",e);
}
if(triplesAdded || triplesRemoved) {
+ deletedStatementsLog.clear();
+
store.notifySailChanged(new SailChangedEvent() {
@Override
public Sail getSail() {
@@ -367,6 +379,7 @@ public class KiWiSailConnection extends NotifyingSailConnectionBase implements I
protected void rollbackInternal() throws SailException {
try {
databaseConnection.rollback();
+ deletedStatementsLog.clear();
} catch (SQLException e) {
throw new SailException("database error while rolling back transaction",e);
}
@@ -381,6 +394,7 @@ public class KiWiSailConnection extends NotifyingSailConnectionBase implements I
if(triple.getId() != null) {
databaseConnection.deleteTriple(triple);
triplesRemoved = true;
+ deletedStatementsLog.add(triple.getId());
notifyStatementRemoved(triple);
}
}
@@ -411,6 +425,7 @@ public class KiWiSailConnection extends NotifyingSailConnectionBase implements I
if(triple.getId() != null && triple.isInferred()) {
databaseConnection.deleteTriple(triple);
triplesRemoved = true;
+ deletedStatementsLog.add(triple.getId());
notifyStatementRemoved(triple);
}
}
@@ -438,6 +453,7 @@ public class KiWiSailConnection extends NotifyingSailConnectionBase implements I
if(triple.getId() != null && triple.isInferred()) {
databaseConnection.deleteTriple(triple);
triplesRemoved = true;
+ deletedStatementsLog.add(triple.getId());
notifyStatementRemoved(triple);
}
} catch(SQLException ex) {
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiStore.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiStore.java b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiStore.java
index d07bd8a..3c71e2c 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiStore.java
+++ b/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiStore.java
@@ -19,11 +19,6 @@ package org.apache.marmotta.kiwi.sail;
import com.google.common.collect.MapMaker;
import org.apache.marmotta.kiwi.model.caching.IntArray;
-import org.apache.marmotta.kiwi.model.collection.WeakValueMap;
-import org.apache.marmotta.kiwi.model.rdf.KiWiAnonResource;
-import org.apache.marmotta.kiwi.model.rdf.KiWiLiteral;
-import org.apache.marmotta.kiwi.model.rdf.KiWiUriResource;
-import org.apache.marmotta.kiwi.persistence.KiWiConnection;
import org.apache.marmotta.kiwi.persistence.KiWiDialect;
import org.apache.marmotta.kiwi.persistence.KiWiPersistence;
import org.openrdf.model.Statement;
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/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 3c948a0..22038f6 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
@@ -18,12 +18,11 @@
package org.apache.marmotta.kiwi.sail;
import com.google.common.collect.MapMaker;
+import org.apache.commons.lang.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.commons.lang.LocaleUtils;
import org.apache.marmotta.kiwi.model.caching.IntArray;
-import org.apache.marmotta.kiwi.model.collection.WeakValueMap;
import org.apache.marmotta.kiwi.model.rdf.*;
import org.apache.marmotta.kiwi.persistence.KiWiConnection;
import org.openrdf.model.BNode;
@@ -33,6 +32,8 @@ import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.ValueFactory;
+import org.openrdf.model.impl.ContextStatementImpl;
+import org.openrdf.model.impl.StatementImpl;
import org.openrdf.repository.RepositoryException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -546,6 +547,8 @@ public class KiWiValueFactory implements ValueFactory {
*/
@Override
public Statement createStatement(Resource subject, URI predicate, Value object, Resource context) {
+ return new ContextStatementImpl(subject,predicate,object,context);
+ /*
tripleLock.lock();
KiWiConnection connection = aqcuireConnection();
try {
@@ -579,8 +582,52 @@ public class KiWiValueFactory implements ValueFactory {
releaseConnection(connection);
tripleLock.unlock();
}
+ */
}
+ /**
+ * Creates a new statement with the supplied subject, predicate and object and associated context. This is a
+ * specialised form of createStatement that allows the existance check for a triple to run in the same connection
+ * as the rest of the repository operations.
+ *
+ * @param subject The statement's subject.
+ * @param predicate The statement's predicate.
+ * @param object The statement's object.
+ * @param context The statement's context.
+ * @return The created statement.
+ */
+ public Statement createStatement(Resource subject, URI predicate, Value object, Resource context, KiWiConnection connection) {
+ IntArray cacheKey = IntArray.createSPOCKey(subject,predicate,object,context);
+ Statement result = tripleRegistry.get(cacheKey);
+ try {
+ if(result == null || ((KiWiTriple)result).isDeleted()) {
+ KiWiResource ksubject = convert(subject);
+ KiWiUriResource kpredicate = convert(predicate);
+ KiWiNode kobject = convert(object);
+ KiWiResource kcontext = convert(context);
+
+ // test if the triple already exists in the database; if yes, return it
+ List<Statement> triples = connection.listTriples(ksubject,kpredicate,kobject,kcontext,true).asList();
+ if(triples.size() == 1) {
+ result = triples.get(0);
+ } else {
+ result = new KiWiTriple(ksubject,kpredicate,kobject,kcontext);
+ ((KiWiTriple)result).setMarkedForReasoning(true);
+ }
+
+ tripleRegistry.put(cacheKey,result);
+ }
+ return result;
+ } catch (SQLException e) {
+ log.error("database error, could not load triple", e);
+ throw new IllegalStateException("database error, could not load triple",e);
+ } catch (RepositoryException e) {
+ log.error("database error, could not load triple", e);
+ throw new IllegalStateException("database error, could not load triple",e);
+ }
+ }
+
+
public KiWiResource convert(Resource r) {
return (KiWiResource)convert((Value)r);
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
index 42a67ea..2fc9afc 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
+++ b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/h2/statements.properties
@@ -71,4 +71,5 @@ query.namespaces = SELECT id,prefix,uri,createdAt FROM namespaces
# delete entities
delete.triple = UPDATE triples SET deleted = true, deletedAt = now() WHERE id = ?
+undelete.triple = UPDATE triples SET deleted = false, deletedAt = NULL WHERE id = ?
delete.namespace = DELETE FROM namespaces WHERE id = ?
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
index 9fe6a82..fae51bc 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
+++ b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/mysql/statements.properties
@@ -75,4 +75,5 @@ query.namespaces = SELECT id,prefix,uri,createdAt FROM namespaces
# delete entities
delete.triple = UPDATE triples SET deleted = true, deletedAt = now() WHERE id = ?
+undelete.triple = UPDATE triples SET deleted = false, deletedAt = NULL WHERE id = ?
delete.namespace = DELETE FROM namespaces WHERE id = ?
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
index f0d0e90..2b2f0c6 100644
--- a/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
+++ b/libraries/kiwi/kiwi-triplestore/src/main/resources/org/apache/marmotta/kiwi/persistence/pgsql/statements.properties
@@ -67,4 +67,5 @@ query.namespaces = SELECT id,prefix,uri,createdAt FROM namespaces
# delete entities
delete.triple = UPDATE triples SET deleted = true, deletedAt = now() WHERE id = ?
+undelete.triple = UPDATE triples SET deleted = false, deletedAt = NULL WHERE id = ?
delete.namespace = DELETE FROM namespaces WHERE id = ?
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/libraries/kiwi/kiwi-triplestore/src/test/java/org/apache/marmotta/kiwi/test/RepositoryTest.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-triplestore/src/test/java/org/apache/marmotta/kiwi/test/RepositoryTest.java b/libraries/kiwi/kiwi-triplestore/src/test/java/org/apache/marmotta/kiwi/test/RepositoryTest.java
index 6ff74ff..ff914e8 100644
--- a/libraries/kiwi/kiwi-triplestore/src/test/java/org/apache/marmotta/kiwi/test/RepositoryTest.java
+++ b/libraries/kiwi/kiwi-triplestore/src/test/java/org/apache/marmotta/kiwi/test/RepositoryTest.java
@@ -475,4 +475,60 @@ public class RepositoryTest {
}
+
+ /**
+ * Test adding-deleting-adding a triple
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testRepeatedAddRemoveTransaction() throws Exception {
+ String value = RandomStringUtils.randomAlphanumeric(8);
+
+ URI subject = repository.getValueFactory().createURI("http://localhost/resource/" + RandomStringUtils.randomAlphanumeric(8));
+ URI predicate = repository.getValueFactory().createURI("http://localhost/resource/" + RandomStringUtils.randomAlphanumeric(8));
+ Literal object1 = repository.getValueFactory().createLiteral(value);
+
+ RepositoryConnection connection1 = repository.getConnection();
+ try {
+ connection1.add(subject,predicate,object1);
+ connection1.commit();
+
+ Assert.assertTrue(connection1.hasStatement(subject,predicate,object1,true));
+
+ connection1.commit();
+ } finally {
+ connection1.close();
+ }
+
+ Literal object2 = repository.getValueFactory().createLiteral(value);
+ Literal object3 = repository.getValueFactory().createLiteral(value);
+ RepositoryConnection connection2 = repository.getConnection();
+ try {
+ Assert.assertTrue(connection2.hasStatement(subject,predicate,object2,true));
+
+ connection2.remove(subject,predicate,object2);
+ Assert.assertFalse(connection2.hasStatement(subject,predicate,object2,true));
+
+ connection2.add(subject,predicate,object3);
+ Assert.assertTrue(connection2.hasStatement(subject,predicate,object3,true));
+
+ connection2.commit();
+ } finally {
+ connection2.close();
+ }
+
+ Literal object4 = repository.getValueFactory().createLiteral(value);
+ RepositoryConnection connection4 = repository.getConnection();
+ try {
+ Assert.assertTrue(connection4.hasStatement(subject,predicate,object4,true));
+
+ connection4.commit();
+ } finally {
+ connection4.close();
+ }
+
+
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/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 0ae8118..054cf20 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
@@ -27,6 +27,7 @@ import org.apache.marmotta.kiwi.model.rdf.KiWiTriple;
import org.apache.marmotta.kiwi.model.rdf.KiWiUriResource;
import org.apache.marmotta.kiwi.persistence.KiWiConnection;
import org.apache.marmotta.kiwi.persistence.KiWiDialect;
+import org.apache.marmotta.kiwi.persistence.KiWiPersistence;
import org.apache.marmotta.kiwi.persistence.util.ResultSetIteration;
import org.apache.marmotta.kiwi.persistence.util.ResultTransformerFunction;
import org.apache.marmotta.kiwi.versioning.model.Version;
@@ -52,8 +53,8 @@ public class KiWiVersioningConnection extends KiWiConnection {
private static Logger log = LoggerFactory.getLogger(KiWiVersioningConnection.class);
- public KiWiVersioningConnection(Connection connection, KiWiDialect dialect, KiWiCacheManager cacheManager) throws SQLException {
- super(connection, dialect, cacheManager);
+ public KiWiVersioningConnection(KiWiPersistence persistence, KiWiDialect dialect, KiWiCacheManager cacheManager) throws SQLException {
+ super(persistence, dialect, cacheManager);
}
@@ -75,6 +76,8 @@ public class KiWiVersioningConnection extends KiWiConnection {
return;
}
+ requireJDBCConnection();
+
// first create a new entry in the version table
data.setId(getNextSequence("seq.versions"));
@@ -134,6 +137,8 @@ public class KiWiVersioningConnection extends KiWiConnection {
* @throws SQLException
*/
public Version getVersion(Long id) throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement queryVersions = getPreparedStatement("load.version_by_id");
queryVersions.setLong(1,id);
queryVersions.setMaxRows(1);
@@ -161,6 +166,8 @@ public class KiWiVersioningConnection extends KiWiConnection {
* @throws SQLException
*/
public Version getLatestVersion(KiWiResource resource, Date date) throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement queryVersions = getPreparedStatement("load.versions_by_resource_latest");
synchronized (queryVersions) {
queryVersions.setLong(1, resource.getId());
@@ -210,6 +217,8 @@ public class KiWiVersioningConnection extends KiWiConnection {
* @throws SQLException
*/
private CloseableIteration<Version, SQLException> listVersionsInternal() throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement queryVersions = getPreparedStatement("load.versions");
final ResultSet result = queryVersions.executeQuery();
@@ -253,6 +262,8 @@ public class KiWiVersioningConnection extends KiWiConnection {
if(r.getId() == null) {
return new EmptyIteration<Version, SQLException>();
} else {
+ requireJDBCConnection();
+
PreparedStatement queryVersions = getPreparedStatement("load.versions_by_resource");
queryVersions.setLong(1,r.getId());
@@ -297,6 +308,8 @@ public class KiWiVersioningConnection extends KiWiConnection {
* @throws SQLException
*/
private CloseableIteration<Version, SQLException> listVersionsInternal(Date from, Date to) throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement queryVersions = getPreparedStatement("load.version_between");
synchronized (queryVersions) {
queryVersions.clearParameters();
@@ -343,6 +356,8 @@ public class KiWiVersioningConnection extends KiWiConnection {
* @throws SQLException
*/
private CloseableIteration<Version, SQLException> listVersionsInternal(KiWiResource r, Date from, Date to) throws SQLException {
+ requireJDBCConnection();
+
PreparedStatement queryVersions = getPreparedStatement("load.versions_by_resource_between");
synchronized (queryVersions) {
queryVersions.clearParameters();
@@ -477,6 +492,8 @@ public class KiWiVersioningConnection extends KiWiConnection {
return new EmptyIteration<Statement, SQLException>();
}
+ requireJDBCConnection();
+
// otherwise we need to create an appropriate SQL query and execute it, the repository result will be read-only
// and only allow forward iteration, so we can limit the query using the respective flags
PreparedStatement query = connection.prepareStatement(
@@ -578,6 +595,9 @@ public class KiWiVersioningConnection extends KiWiConnection {
if(context.getId() == null) {
return 0;
};
+
+ requireJDBCConnection();
+
PreparedStatement querySize = getPreparedStatement("query.snapshot_size_ctx");
querySize.setLong(1,context.getId());
querySize.setTimestamp(2, new Timestamp(snapshotDate.getTime()));
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c4ca14f0/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/persistence/KiWiVersioningPersistence.java
----------------------------------------------------------------------
diff --git a/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/persistence/KiWiVersioningPersistence.java b/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/persistence/KiWiVersioningPersistence.java
index 82a026b..797c58c 100644
--- a/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/persistence/KiWiVersioningPersistence.java
+++ b/libraries/kiwi/kiwi-versioning/src/main/java/org/apache/marmotta/kiwi/versioning/persistence/KiWiVersioningPersistence.java
@@ -77,7 +77,7 @@ public class KiWiVersioningPersistence {
* @throws java.sql.SQLException in case a new connection could not be established
*/
public KiWiVersioningConnection getConnection() throws SQLException {
- return new KiWiVersioningConnection(persistence.getJDBCConnection(), persistence.getDialect(), persistence.getCacheManager());
+ return new KiWiVersioningConnection(persistence, persistence.getDialect(), persistence.getCacheManager());
}