Author: mir
Date: Tue Jul 6 16:46:12 2010
New Revision: 960941
URL: http://svn.apache.org/viewvc?rev=960941&view=rev
Log:
CLEREZZA-245: Added read/write locks to hierarchy service.
SimpleTripleCollection is now configurable to throw
ConcurrentModificationExceptions (for testing). Implemented
LockableMGraphWrapperForTesting in rdf.core.test.
Added:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockChecker.java
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockableMGraphWrapperForTesting.java
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockingIteratorForTesting.java
Modified:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/pom.xml
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/CollectionNode.java
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/HierarchyNode.java
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/HierarchyService.java
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/test/java/org/apache/clerezza/platform/content/hierarchy/HierarchyTest.java
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/impl/SimpleTripleCollection.java
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/test/java/org/apache/clerezza/rdf/core/impl/SimpleTripleCollectionTest.java
Modified:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/pom.xml
URL:
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/pom.xml?rev=960941&r1=960940&r2=960941&view=diff
==============================================================================
---
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/pom.xml
(original)
+++
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/pom.xml
Tue Jul 6 16:46:12 2010
@@ -94,6 +94,11 @@
<artifactId>org.apache.clerezza.rdf.metadata</artifactId>
</dependency>
<dependency>
+ <groupId>org.apache.clerezza</groupId>
+
<artifactId>org.apache.clerezza.rdf.core.test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
Modified:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/CollectionNode.java
URL:
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/CollectionNode.java?rev=960941&r1=960940&r2=960941&view=diff
==============================================================================
---
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/CollectionNode.java
(original)
+++
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/CollectionNode.java
Tue Jul 6 16:46:12 2010
@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.locks.Lock;
import org.apache.clerezza.rdf.core.BNode;
import org.apache.clerezza.rdf.core.NonLiteral;
import org.apache.clerezza.rdf.core.Resource;
@@ -48,7 +49,12 @@ public class CollectionNode extends Hier
}
boolean isValid() {
- return this.hasProperty(RDF.type, HIERARCHY.Collection);
+ readLock().lock();
+ try {
+ return this.hasProperty(RDF.type, HIERARCHY.Collection);
+ } finally {
+ readLock().unlock();
+ }
}
/**
@@ -78,19 +84,24 @@ public class CollectionNode extends Hier
* @return
*/
public List<HierarchyNode> getMembers() {
+ List<HierarchyNode> nodes;
List<Resource> membersListRdf = getMembersRdf();
- List<HierarchyNode> nodes =
- new
ArrayList<HierarchyNode>(membersListRdf.size());
- Iterator<Resource> membersIter = membersListRdf.iterator();
- while (membersIter.hasNext()) {
- UriRef uri = (UriRef) membersIter.next();
- try {
-
nodes.add(hierarchyService.getHierarchyNode(uri));
- } catch (NodeDoesNotExistException ex) {
- throw new RuntimeException(ex);
- } catch (UnknownRootExcetpion ex) {
- throw new RuntimeException(ex);
+ readLock().lock();
+ try {
+ nodes = new
ArrayList<HierarchyNode>(membersListRdf.size());
+ Iterator<Resource> membersIter =
membersListRdf.iterator();
+ while (membersIter.hasNext()) {
+ UriRef uri = (UriRef) membersIter.next();
+ try {
+
nodes.add(hierarchyService.getHierarchyNode(uri));
+ } catch (NodeDoesNotExistException ex) {
+ throw new RuntimeException(ex);
+ } catch (UnknownRootExcetpion ex) {
+ throw new RuntimeException(ex);
+ }
}
+ } finally {
+ readLock().unlock();
}
return Collections.unmodifiableList(nodes);
}
@@ -100,15 +111,30 @@ public class CollectionNode extends Hier
* @return
*/
List<Resource> getMembersRdf() {
- Iterator<Resource> members = this.getObjects(HIERARCHY.members);
- RdfList membersList;
- if (members.hasNext()) {
- membersList = new RdfList((BNode)members.next(),
getGraph());
- } else {
+ RdfList membersList = null;
+ Lock readLock = readLock();
+ readLock.lock();
+ try {
+ Iterator<Resource> members =
this.getObjects(HIERARCHY.members);
+ if (members.hasNext()) {
+ membersList = new RdfList((BNode)
members.next(), getGraph());
+ }
+ } finally {
+ readLock.unlock();
+ }
+ if (membersList == null) {
BNode newMembers = new BNode();
- this.addProperty(HIERARCHY.members, newMembers);
- membersList = new RdfList(newMembers, getGraph());
+ Lock writLock = writeLock();
+ writLock.lock();
+ try {
+ this.addProperty(HIERARCHY.members, newMembers);
+ membersList = new RdfList(newMembers,
getGraph());
+ } finally {
+ writLock.unlock();
+ }
+
}
+
return membersList;
}
@@ -163,16 +189,22 @@ public class CollectionNode extends Hier
@Override
public void delete() {
- List<HierarchyNode> members = getMembers();
- Iterator<HierarchyNode> membersIter = members.iterator();
- while (membersIter.hasNext()) {
- HierarchyNode hierarchyNode = membersIter.next();
- hierarchyNode.delete();
- }
- deleteCollection();
- super.delete();
- if (hierarchyService.getRoots().contains(this)) {
- hierarchyService.removeRoot(this);
+ Lock writeLock = writeLock();
+ writeLock.lock();
+ try {
+ List<HierarchyNode> members = getMembers();
+ Iterator<HierarchyNode> membersIter =
members.iterator();
+ while (membersIter.hasNext()) {
+ HierarchyNode hierarchyNode =
membersIter.next();
+ hierarchyNode.delete();
+ }
+ deleteCollection();
+ super.delete();
+ if (hierarchyService.getRoots().contains(this)) {
+ hierarchyService.removeRoot(this);
+ }
+ } finally {
+ writeLock.unlock();
}
}
Modified:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/HierarchyNode.java
URL:
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/HierarchyNode.java?rev=960941&r1=960940&r2=960941&view=diff
==============================================================================
---
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/HierarchyNode.java
(original)
+++
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/HierarchyNode.java
Tue Jul 6 16:46:12 2010
@@ -19,6 +19,7 @@
package org.apache.clerezza.platform.content.hierarchy;
import java.util.List;
+import java.util.concurrent.locks.Lock;
import org.apache.clerezza.rdf.core.NonLiteral;
import org.apache.clerezza.rdf.core.Resource;
import org.apache.clerezza.rdf.core.TripleCollection;
@@ -120,23 +121,31 @@ public class HierarchyNode extends Graph
} catch (UriException ex) {
throw new RuntimeException(ex);
}
- if (newParent.equals(getParent())) {
- UriRef nodeUri = getNode();
- List<Resource> membersRdfList =
newParent.getMembersRdf();
- int oldPos = membersRdfList.indexOf(nodeUri);
- if (oldPos < pos) {
- pos -= 1;
- }
- if (name.equals(getName())) {
- if (oldPos != pos) {
- membersRdfList.remove(nodeUri);
- membersRdfList.add(pos, nodeUri);
- }
- return this;
+
+ Lock writeLock = writeLock();
+ writeLock.lock();
+ try {
+ if (newParent.equals(getParent())) {
+ UriRef nodeUri = getNode();
+ List<Resource> membersRdfList =
newParent.getMembersRdf();
+ int oldPos = membersRdfList.indexOf(nodeUri);
+ if (oldPos < pos) {
+ pos -= 1;
+ }
+ if (name.equals(getName())) {
+ if (oldPos != pos) {
+ membersRdfList.remove(nodeUri);
+ membersRdfList.add(pos,
nodeUri);
+ }
+ return this;
+ }
}
- }
- String newUriString = newParent.getNode().getUnicodeString() +
- name;
+ } finally {
+ writeLock.unlock();
+ }
+ String newUriString = newParent.getNode().getUnicodeString()
+ + name;
+
String alternativeUriString = newUriString;
if (this instanceof CollectionNode) {
newUriString += "/";
@@ -146,28 +155,39 @@ public class HierarchyNode extends Graph
UriRef newUri = new UriRef(newUriString);
UriRef alternativeUri = new UriRef(alternativeUriString);
List<Resource> parentMembers = newParent.getMembersRdf();
- if (parentMembers.contains(newUri) ||
parentMembers.contains(alternativeUri)) {
- HierarchyNode existingNode = null;
- try {
+ Lock newParentReadLock = newParent.readLock();
+ newParentReadLock.lock();
+ try {
+ if (parentMembers.contains(newUri) ||
parentMembers.contains(alternativeUri)) {
+ HierarchyNode existingNode = null;
try {
- existingNode =
hierarchyService.getHierarchyNode(newUri);
- } catch (NodeDoesNotExistException ex) {
try {
- existingNode =
hierarchyService.getHierarchyNode(alternativeUri);
- } catch (NodeDoesNotExistException e) {
- throw new RuntimeException(ex);
+ existingNode =
hierarchyService.getHierarchyNode(newUri);
+ } catch (NodeDoesNotExistException ex) {
+ try {
+ existingNode =
hierarchyService.getHierarchyNode(alternativeUri);
+ } catch
(NodeDoesNotExistException e) {
+ throw new
RuntimeException(ex);
+ }
}
+ } catch (UnknownRootExcetpion ex) {
+ throw new RuntimeException(ex);
}
- } catch (UnknownRootExcetpion ex) {
- throw new RuntimeException(ex);
+ throw new
NodeAlreadyExistsException(existingNode);
}
- throw new NodeAlreadyExistsException(existingNode);
+ } finally {
+ newParentReadLock.unlock();
}
- deleteFromParent();
+ writeLock().lock();
+ try {
+ deleteFromParent();
- HierarchyNode movedNode = replaceWith(newUri);
- newParent.addMember(movedNode, pos);
- return movedNode;
+ HierarchyNode movedNode = replaceWith(newUri);
+ newParent.addMember(movedNode, pos);
+ return movedNode;
+ } finally {
+ writeLock().unlock();
+ }
}
/**
Modified:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/HierarchyService.java
URL:
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/HierarchyService.java?rev=960941&r1=960940&r2=960941&view=diff
==============================================================================
---
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/HierarchyService.java
(original)
+++
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/main/java/org/apache/clerezza/platform/content/hierarchy/HierarchyService.java
Tue Jul 6 16:46:12 2010
@@ -116,8 +116,14 @@ public class HierarchyService {
throw ex;
}
}
- if (!parent.getMembersRdf().contains(nodeUri)) {
- throw new NodeDoesNotExistException(nodeUri);
+ Lock parentReadLock = parent.readLock();
+ parentReadLock.lock();
+ try {
+ if (!parent.getMembersRdf().contains(nodeUri)) {
+ throw new
NodeDoesNotExistException(nodeUri);
+ }
+ } finally {
+ parentReadLock.unlock();
}
}
}
@@ -169,8 +175,14 @@ public class HierarchyService {
handleRootOfUri(uri);
HierarchyNode hierarchyNode;
hierarchyNode = new HierarchyNode(uri,
cgProvider.getContentGraph(), this);
- addToParent(hierarchyNode, posInParent);
- addCreationProperties(hierarchyNode);
+ Lock writeLocke = hierarchyNode.writeLock();
+ writeLocke.lock();
+ try {
+ addToParent(hierarchyNode, posInParent);
+ addCreationProperties(hierarchyNode);
+ } finally {
+ writeLocke.lock();
+ }
return hierarchyNode;
}
@@ -324,9 +336,15 @@ public class HierarchyService {
handleRootOfUri(uri);
CollectionNode collectionNode;
collectionNode = new CollectionNode(uri,
cgProvider.getContentGraph(), this);
- addCollectionTypeTriple(collectionNode);
- addToParent(collectionNode, posInParent);
- addCreationProperties(collectionNode);
+ Lock writeLocke = collectionNode.writeLock();
+ writeLocke.lock();
+ try {
+ addCollectionTypeTriple(collectionNode);
+ addToParent(collectionNode, posInParent);
+ addCreationProperties(collectionNode);
+ } finally {
+ writeLocke.unlock();
+ }
return collectionNode;
}
@@ -415,8 +433,14 @@ public class HierarchyService {
private void addRoot(UriRef baseUri) {
CollectionNode node = new CollectionNode(baseUri,
cgProvider.getContentGraph(), this);
- addCollectionTypeTriple(node);
- roots.add(node);
+ Lock writeLock = node.writeLock();
+ writeLock.lock();
+ try {
+ addCollectionTypeTriple(node);
+ roots.add(node);
+ } finally {
+ writeLock.unlock();
+ }
}
protected void deactivate(ComponentContext componentContext) {
Modified:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/test/java/org/apache/clerezza/platform/content/hierarchy/HierarchyTest.java
URL:
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/test/java/org/apache/clerezza/platform/content/hierarchy/HierarchyTest.java?rev=960941&r1=960940&r2=960941&view=diff
==============================================================================
---
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/test/java/org/apache/clerezza/platform/content/hierarchy/HierarchyTest.java
(original)
+++
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.platform.content/src/test/java/org/apache/clerezza/platform/content/hierarchy/HierarchyTest.java
Tue Jul 6 16:46:12 2010
@@ -22,6 +22,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.locks.Lock;
import org.apache.clerezza.rdf.utils.GraphNode;
import org.junit.Assert;
import org.junit.Test;
@@ -31,10 +32,12 @@ import org.apache.clerezza.rdf.core.BNod
import org.apache.clerezza.rdf.core.MGraph;
import org.apache.clerezza.rdf.core.Triple;
import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.LockableMGraph;
import org.apache.clerezza.rdf.core.access.LockableMGraphWrapper;
import org.apache.clerezza.rdf.core.impl.PlainLiteralImpl;
import org.apache.clerezza.rdf.core.impl.SimpleMGraph;
import org.apache.clerezza.rdf.core.impl.TripleImpl;
+import org.apache.clerezza.rdf.core.test.LockableMGraphWrapperForTesting;
import org.apache.clerezza.rdf.ontologies.HIERARCHY;
import org.apache.clerezza.rdf.ontologies.PLATFORM;
import org.apache.clerezza.rdf.ontologies.RDF;
@@ -62,8 +65,8 @@ public class HierarchyTest{
private UriRef newRoot = new UriRef("http://newRoot/");
private UriRef newRootTest = new UriRef("http://newRoot/test/");
private UriRef newRoot2Resource = new
UriRef("http://newRoot2/resource");
- private UriRef newRoot2 = new UriRef("http://newRoot2/");
-
+ private UriRef newRoot2 = new UriRef("http://newRoot2/");
+
@Test
public void listPositionTest() throws Exception{
HierarchyService hierarchyService = getHierarchyService();
@@ -288,8 +291,12 @@ public class HierarchyTest{
Assert.assertTrue(exceptionThrown);
}
- private static class MyContentGraphProvider extends
ContentGraphProvider {
- private MGraph graph = new SimpleMGraph();
+ private class MyContentGraphProvider extends ContentGraphProvider {
+ SimpleMGraph contentGraph = new SimpleMGraph();
+ {
+ contentGraph.setCheckConcurrency(true);
+ }
+ private MGraph graph = new
LockableMGraphWrapperForTesting(contentGraph);
@Override
public MGraph getContentGraph() {
return graph;
@@ -321,7 +328,14 @@ public class HierarchyTest{
hierarchyService.systemGraph = systemGraph;
Triple rootTriple = new TripleImpl(root,
RDF.type, HIERARCHY.Collection);
- myCgProvider.getContentGraph().add(rootTriple);
+ LockableMGraph lockableContentGraph = (LockableMGraph)
myCgProvider.getContentGraph();
+ Lock writeLock = lockableContentGraph.getLock().writeLock();
+ writeLock.lock();
+ try {
+ lockableContentGraph.add(rootTriple);
+ } finally {
+ writeLock.unlock();
+ }
hierarchyService.activate(null);
return hierarchyService;
}
Added:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockChecker.java
URL:
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockChecker.java?rev=960941&view=auto
==============================================================================
---
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockChecker.java
(added)
+++
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockChecker.java
Tue Jul 6 16:46:12 2010
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 mir.
+ *
+ * Licensed 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.
+ * under the License.
+ */
+
+package org.apache.clerezza.rdf.core.test;
+
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ *
+ * @author mir
+ */
+class LockChecker {
+
+ public static void checkIfReadLocked(ReentrantReadWriteLock lock) {
+ if (lock.getReadLockCount() == 0 &&
!lock.isWriteLockedByCurrentThread()) {
+ throw new RuntimeException("Neither read- nor
write-locked");
+ }
+ }
+
+ public static void checkIfWriteLocked(ReentrantReadWriteLock lock) {
+ if (!lock.isWriteLockedByCurrentThread()) {
+ throw new RuntimeException("Not write-locked");
+ }
+ }
+}
Added:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockableMGraphWrapperForTesting.java
URL:
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockableMGraphWrapperForTesting.java?rev=960941&view=auto
==============================================================================
---
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockableMGraphWrapperForTesting.java
(added)
+++
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockableMGraphWrapperForTesting.java
Tue Jul 6 16:46:12 2010
@@ -0,0 +1,245 @@
+/*
+ * 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.clerezza.rdf.core.test;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.NonLiteral;
+import org.apache.clerezza.rdf.core.Resource;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.LockableMGraph;
+import org.apache.clerezza.rdf.core.event.FilterTriple;
+import org.apache.clerezza.rdf.core.event.GraphListener;
+
+/**
+ * Wrappes an MGraph as a LockableMGraph. If a method is called that reads
+ * or modifies the wrapped graph and the appropriate lock is not set, then a
+ * RuntimeException is thrown.
+ *
+ * @author rbn, mir
+ */
+public class LockableMGraphWrapperForTesting implements LockableMGraph {
+
+ private final ReentrantReadWriteLock lock = new
ReentrantReadWriteLock();
+ private final Lock readLock = lock.readLock();
+ private final Lock writeLock = lock.writeLock();
+ private final MGraph wrapped;
+
+ /**
+ * Constructs a LocalbleMGraph for an MGraph.
+ *
+ * @param providedMGraph a non-lockable mgraph
+ */
+ public LockableMGraphWrapperForTesting(final MGraph providedMGraph) {
+ this.wrapped = providedMGraph;
+ }
+
+ @Override
+ public ReadWriteLock getLock() {
+ return lock;
+ }
+
+ @Override
+ public Graph getGraph() {
+ LockChecker.checkIfReadLocked(lock);
+ readLock.lock();
+ try {
+ return wrapped.getGraph();
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public Iterator<Triple> filter(NonLiteral subject, UriRef predicate,
Resource object) {
+ LockChecker.checkIfReadLocked(lock);
+ readLock.lock();
+ try {
+ return new
LockingIteratorForTesting(wrapped.filter(subject, predicate, object), lock);
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public int size() {
+ LockChecker.checkIfReadLocked(lock);
+ readLock.lock();
+ try {
+ return wrapped.size();
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean isEmpty() {
+ LockChecker.checkIfReadLocked(lock);
+ readLock.lock();
+ try {
+ return wrapped.isEmpty();
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ @SuppressWarnings("element-type-mismatch")
+ public boolean contains(Object o) {
+ LockChecker.checkIfReadLocked(lock);
+ readLock.lock();
+ try {
+ return wrapped.contains(o);
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public Iterator<Triple> iterator() {
+ LockChecker.checkIfReadLocked(lock);
+ readLock.lock();
+ try {
+ return new
LockingIteratorForTesting(wrapped.iterator(), lock);
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public Object[] toArray() {
+ LockChecker.checkIfReadLocked(lock);
+ readLock.lock();
+ try {
+ return wrapped.toArray();
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ LockChecker.checkIfReadLocked(lock);
+ readLock.lock();
+ try {
+ return wrapped.toArray(a);
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ LockChecker.checkIfReadLocked(lock);
+ readLock.lock();
+ try {
+ return wrapped.containsAll(c);
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean add(Triple e) {
+ LockChecker.checkIfWriteLocked(lock);
+ writeLock.lock();
+ try {
+ return wrapped.add(e);
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ LockChecker.checkIfWriteLocked(lock);
+ writeLock.lock();
+ try {
+ return wrapped.remove(o);
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Triple> c) {
+ LockChecker.checkIfWriteLocked(lock);
+ writeLock.lock();
+ try {
+ return wrapped.addAll(c);
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ LockChecker.checkIfWriteLocked(lock);
+ writeLock.lock();
+ try {
+ return wrapped.removeAll(c);
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ LockChecker.checkIfWriteLocked(lock);
+ writeLock.lock();
+ try {
+ return wrapped.retainAll(c);
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ @Override
+ public void clear() {
+ LockChecker.checkIfWriteLocked(lock);
+ writeLock.lock();
+ try {
+ wrapped.clear();
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ @Override
+ public void addGraphListener(GraphListener listener, FilterTriple
filter, long delay) {
+ wrapped.addGraphListener(listener, filter, delay);
+ }
+
+ @Override
+ public void addGraphListener(GraphListener listener, FilterTriple
filter) {
+ wrapped.addGraphListener(listener, filter);
+ }
+
+ @Override
+ public void removeGraphListener(GraphListener listener) {
+ wrapped.removeGraphListener(listener);
+ }
+
+}
Added:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockingIteratorForTesting.java
URL:
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockingIteratorForTesting.java?rev=960941&view=auto
==============================================================================
---
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockingIteratorForTesting.java
(added)
+++
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core.test/src/main/java/org/apache/clerezza/rdf/core/test/LockingIteratorForTesting.java
Tue Jul 6 16:46:12 2010
@@ -0,0 +1,79 @@
+/*
+ * 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.clerezza.rdf.core.test;
+
+import java.util.Iterator;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.clerezza.rdf.core.Triple;
+
+/**
+ * Wrapps an iterator<Triple> reading all elements to a cache on construction
+ * and returning them from that cache.
+ * @author reto
+ */
+class LockingIteratorForTesting implements Iterator<Triple> {
+
+ private Iterator<Triple> base;
+ private Lock readLock;
+ private Lock writeLock;
+ private ReentrantReadWriteLock lock;
+
+ public LockingIteratorForTesting(Iterator<Triple> iterator,
ReentrantReadWriteLock lock) {
+ base = iterator;
+ readLock = lock.readLock();
+ writeLock = lock.writeLock();
+ this.lock = lock;
+ }
+
+ @Override
+ public boolean hasNext() {
+ LockChecker.checkIfReadLocked(lock);
+ readLock.lock();
+ try {
+ return base.hasNext();
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public Triple next() {
+ LockChecker.checkIfReadLocked(lock);
+ readLock.lock();
+ try {
+ return base.next();
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @Override
+ public void remove() {
+ LockChecker.checkIfWriteLocked(lock);
+ writeLock.lock();
+ try {
+ base.remove();
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+
+}
Modified:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/impl/SimpleTripleCollection.java
URL:
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/impl/SimpleTripleCollection.java?rev=960941&r1=960940&r2=960941&view=diff
==============================================================================
---
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/impl/SimpleTripleCollection.java
(original)
+++
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/main/java/org/apache/clerezza/rdf/core/impl/SimpleTripleCollection.java
Tue Jul 6 16:46:12 2010
@@ -18,8 +18,11 @@
*/
package org.apache.clerezza.rdf.core.impl;
+import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -41,13 +44,62 @@ import org.apache.clerezza.rdf.core.UriR
*/
class SimpleTripleCollection extends AbstractTripleCollection {
- Set<Triple> triples;
+ final Set<Triple> triples;
+ private boolean checkConcurrency = false;
+
+ class SimpleIterator implements Iterator<Triple> {
+
+ private Iterator<Triple> listIter;
+ private boolean isValid = true;
+
+ public SimpleIterator(Iterator<Triple> listIter) {
+ this.listIter = listIter;
+ }
+ private Triple currentNext;
+
+ @Override
+ public boolean hasNext() {
+ checkValidity();
+ return listIter.hasNext();
+ }
+
+ @Override
+ public Triple next() {
+ checkValidity();
+ currentNext = listIter.next();
+ return currentNext;
+ }
+
+ @Override
+ public void remove() {
+ checkValidity();
+ listIter.remove();
+ triples.remove(currentNext);
+ invalidateIterators(this);
+ }
+
+ private void checkValidity() throws
ConcurrentModificationException {
+ if (checkConcurrency && !isValid) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ private void invalidate() {
+ if (checkConcurrency) {
+ isValid = false;
+ }
+ }
+ }
+
+ private Set<SoftReference<SimpleIterator>> iterators =
+ Collections.synchronizedSet(new
HashSet<SoftReference<SimpleIterator>>());
+
/**
* Creates an empty SimpleTripleCollection
*/
public SimpleTripleCollection() {
- triples = new HashSet<Triple>();
+ triples = Collections.synchronizedSet(new HashSet<Triple>());
}
/**
@@ -91,53 +143,69 @@ class SimpleTripleCollection extends Abs
@Override
public Iterator<Triple> performFilter(final NonLiteral subject, final
UriRef predicate, final Resource object) {
- Iterator<Triple> baseIter = triples.iterator();
final List<Triple> tripleList = new ArrayList<Triple>();
- while (baseIter.hasNext()) {
- Triple triple = baseIter.next();
- if ((subject != null) &&
- (!triple.getSubject().equals(subject))) {
+ synchronized (triples) {
+ Iterator<Triple> baseIter = triples.iterator();
+ while (baseIter.hasNext()) {
+ Triple triple = baseIter.next();
+ if ((subject != null)
+ &&
(!triple.getSubject().equals(subject))) {
continue;
}
- if ((predicate != null) &&
-
(!triple.getPredicate().equals(predicate))) {
+ if ((predicate != null)
+ &&
(!triple.getPredicate().equals(predicate))) {
continue;
}
- if ((object != null) &&
-
(!triple.getObject().equals(object))) {
+ if ((object != null)
+ &&
(!triple.getObject().equals(object))) {
continue;
}
- tripleList.add(triple);
- }
-
- final Iterator<Triple> listIter = tripleList.iterator();
-
- return new Iterator<Triple>() {
-
- private Triple currentNext;
-
- @Override
- public boolean hasNext() {
- return listIter.hasNext();
+ tripleList.add(triple);
}
- @Override
- public Triple next() {
- currentNext = listIter.next();
- return currentNext;
- }
-
- @Override
- public void remove() {
- listIter.remove();
- triples.remove(currentNext);
- }
- };
+ final Iterator<Triple> listIter = tripleList.iterator();
+ SimpleIterator resultIter = new
SimpleIterator(listIter);
+ iterators.add(new
SoftReference<SimpleIterator>(resultIter));
+ return resultIter;
+ }
}
@Override
public boolean performAdd(Triple e) {
- return triples.add(e);
+ boolean modified = triples.add(e);
+ if (modified) {
+ invalidateIterators(null);
+ }
+ return modified;
+ }
+
+ private void invalidateIterators(SimpleIterator caller) {
+ if (!checkConcurrency) {
+ return;
+ }
+ Set<SoftReference> oldReferences = new HashSet<SoftReference>();
+ for (SoftReference<SimpleTripleCollection.SimpleIterator>
softReference : iterators) {
+ SimpleIterator simpleIterator = softReference.get();
+ if (simpleIterator == null) {
+ oldReferences.add(softReference);
+ continue;
+ }
+ if (simpleIterator != caller) {
+ simpleIterator.invalidate();
+ }
+ }
+ iterators.removeAll(oldReferences);
+ }
+
+ /**
+ * Specifies whether or not to throw
<code>ConcurrentModificationException</code>s,
+ * if this simple triple collection is modified concurrently.
Concurrency
+ * check is set to false by default.
+ *
+ * @param bool Specifies whether or not to check concurrent
modifications.
+ */
+ public void setCheckConcurrency(boolean bool) {
+ checkConcurrency = bool;
}
}
Modified:
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/test/java/org/apache/clerezza/rdf/core/impl/SimpleTripleCollectionTest.java
URL:
http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/test/java/org/apache/clerezza/rdf/core/impl/SimpleTripleCollectionTest.java?rev=960941&r1=960940&r2=960941&view=diff
==============================================================================
---
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/test/java/org/apache/clerezza/rdf/core/impl/SimpleTripleCollectionTest.java
(original)
+++
incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.core/src/test/java/org/apache/clerezza/rdf/core/impl/SimpleTripleCollectionTest.java
Tue Jul 6 16:46:12 2010
@@ -18,6 +18,7 @@
*/
package org.apache.clerezza.rdf.core.impl;
+import java.util.ConcurrentModificationException;
import java.util.Iterator;
import org.junit.Assert;
import org.junit.Test;
@@ -85,5 +86,22 @@ public class SimpleTripleCollectionTest
iter.remove();
}
Assert.assertEquals(3, stc.size());
- }
+ }
+
+ @Test(expected=ConcurrentModificationException.class)
+ public void remove() {
+ SimpleTripleCollection stc = new SimpleTripleCollection();
+ stc.setCheckConcurrency(true);
+ stc.add(triple1);
+ stc.add(triple2);
+ stc.add(triple3);
+ stc.add(triple4);
+ stc.add(triple5);
+ Iterator<Triple> iter = stc.filter(uriRef1, null, null);
+ while (iter.hasNext()) {
+ Triple triple = iter.next();
+ stc.remove(triple);
+ }
+ Assert.assertEquals(3, stc.size());
+ }
}