Permalink
Browse files

Merge pull request #8 from brycenz/master

Cool... I will look and see if your concurrency solutions can be incorporated in the other collections tooo.
  • Loading branch information...
NielsHoogeveen committed Sep 28, 2011
2 parents aa0a421 + cea66e3 commit c11d431093447442c13f88bdfeb389110184eeef
@@ -26,6 +26,9 @@
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
+import org.neo4j.kernel.AbstractGraphDatabase;
+import org.neo4j.kernel.Config;
+import org.neo4j.kernel.impl.transaction.LockType;
import java.util.ArrayList;
import java.util.Collections;
@@ -159,11 +162,12 @@ public int compare( Relationship o1, Relationship o2 )
@Override
public Relationship addNode( Node node )
{
- acquireLock();
+ acquireLock( LockType.WRITE );
Node page = checkSplitNode( getPage( node ), node );
+ Relationship relationship = page.createRelationshipTo( node, GraphCollection.RelationshipTypes.VALUE );
page.setProperty( ITEM_COUNT, ((Integer) page.getProperty( ITEM_COUNT )) + 1 );
- return page.createRelationshipTo( node, GraphCollection.RelationshipTypes.VALUE );
+ return relationship;
}
@Override
@@ -175,6 +179,8 @@ public Node getBaseNode()
@Override
public boolean remove( Node node )
{
+ acquireLock( LockType.WRITE );
+
Node page = getPage( node );
do
{
@@ -203,38 +209,41 @@ public boolean remove( Node node )
}
while ( shouldContainNode( page, node ) );
-
return false;
}
@Override
public Iterator<Node> iterator()
{
- return new NodeIterator( getHead(), nodeComparator );
+ acquireLock( LockType.READ );
+
+ return new NodeIterator( getHead( false ), nodeComparator );
}
@Override
public Iterable<Relationship> getValueRelationships()
{
+ acquireLock( LockType.READ );
+
return new Iterable<Relationship>()
{
@Override
public Iterator<Relationship> iterator()
{
- return new RelationshipIterator( getHead(), relationshipComparator );
+ return new RelationshipIterator( getHead( false ), relationshipComparator );
}
};
}
- private Node getHead()
+ private Node getHead( boolean createMissing )
{
- Node head;
+ Node head = null;
Relationship relationship = baseNode.getSingleRelationship( RelationshipTypes.HEAD, Direction.OUTGOING );
if ( relationship != null )
{
head = relationship.getEndNode();
}
- else
+ else if ( createMissing )
{
head = baseNode.getGraphDatabase().createNode();
head.setProperty( ITEM_COUNT, 0 );
@@ -245,7 +254,7 @@ private Node getHead()
private Node getPage( Node node )
{
- Node pageNode = getHead();
+ Node pageNode = getHead( true );
while ( true )
{
if ( shouldContainNode( pageNode, node ) )
@@ -489,9 +498,20 @@ private void moveValueRelationship( Relationship valueRelationship, Node targetP
valueRelationship.delete();
}
- private void acquireLock()
+ private void acquireLock( LockType lockType )
{
- baseNode.removeProperty( "___dummy_property_to_acquire_lock___" );
+ GraphDatabaseService graphDb = baseNode.getGraphDatabase();
+ if ( lockType == LockType.READ && graphDb instanceof AbstractGraphDatabase )
+ {
+ Config config = ((AbstractGraphDatabase) baseNode.getGraphDatabase()).getConfig();
+ config.getLockManager().getReadLock( baseNode );
+ config.getLockReleaser().addLockToTransaction( baseNode, LockType.READ );
+ }
+ else
+ {
+ // default to write lock if read locks unavailable
+ baseNode.removeProperty( "___dummy_property_to_acquire_lock___" );
+ }
}
private static abstract class ItemIterator<T> implements Iterator<T>
@@ -507,9 +527,12 @@ public ItemIterator( Node head, Comparator<T> comparator )
{
currentPage = head;
itemComparator = comparator;
- hasNext = true;
- populate();
- checkNext();
+ hasNext = currentPage != null;
+ if ( hasNext )
+ {
+ populate();
+ checkNext();
+ }
}
@Override
@@ -20,47 +20,25 @@
package org.neo4j.collections.list;
import org.junit.Test;
-import org.neo4j.collections.GraphCollection;
-import org.neo4j.collections.Neo4jTestCase;
import org.neo4j.collections.NodeCollectionLoader;
-import org.neo4j.graphdb.Direction;
-import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertTrue;
/**
* The normal order of adding to an UnrolledLinkedList would be in the end of the list forwards order, e.g. adding
* oldest by date first when the list is ordered by date (most recent first). This is why the creation of the nodes
* reverses the order of the nodes after sorting by the comparator, and why the adding in reverse test reverses it again
* therefore actually adding the items in order.
*/
-public class TestUnrolledLinkedList extends Neo4jTestCase
+public class TestUnrolledLinkedList extends UnrolledLinkedListTestCase
{
- public static class IdComparator implements java.util.Comparator<Node>
- {
- public int compare( Node n1, Node n2 )
- {
- return ((Long) n1.getId()).compareTo( n2.getId() );
- }
- }
-
- public static class EqualComparator implements java.util.Comparator<Node>
- {
- public int compare( Node n1, Node n2 )
- {
- return 0;
- }
- }
-
@Test
public void testCreationAndRecreating()
{
@@ -410,78 +388,4 @@ public void testValueRelationshipKeepsAttributes()
}
assertEquals( nodes.size(), count );
}
-
- private void checkPageCount( Node baseNode, int min, int max )
- {
- int count = 1;
- Node node = baseNode.getSingleRelationship(
- DynamicRelationshipType.withName( "HEAD" ), Direction.OUTGOING ).getEndNode();
- while ( node.hasRelationship( DynamicRelationshipType.withName( "NEXT_PAGE" ), Direction.OUTGOING ) )
- {
- count++;
- node = node.getSingleRelationship(
- DynamicRelationshipType.withName( "NEXT_PAGE" ), Direction.OUTGOING ).getEndNode();
- }
-
- assertTrue( "Page count should be greater than or equal to " + min + " was " + count, count >= min );
- assertTrue( "Page count should be less than or equal to " + max + " was " + count, count <= max );
- }
-
- private void checkItemCounts( Node baseNode )
- {
- Node page = baseNode.getSingleRelationship(
- DynamicRelationshipType.withName( "HEAD" ), Direction.OUTGOING ).getEndNode();
- do
- {
- Integer count = 0;
- for ( Relationship relationship : page.getRelationships(
- GraphCollection.RelationshipTypes.VALUE, Direction.OUTGOING ) )
- {
- count++;
- }
- assertTrue( page.hasProperty( UnrolledLinkedList.ITEM_COUNT ) );
- assertEquals( count, page.getProperty( UnrolledLinkedList.ITEM_COUNT ) );
-
- Relationship next = page.getSingleRelationship(
- DynamicRelationshipType.withName( "NEXT_PAGE" ), Direction.OUTGOING );
- if ( next != null )
- {
- page = next.getEndNode();
- }
- else
- {
- page = null;
- }
- }
- while ( page != null );
- }
-
- private void removeNodes( ArrayList<Node> nodes, UnrolledLinkedList list, int removalCount )
- {
- int count = 0;
- for ( Iterator<Node> nodeIterator = nodes.iterator(); nodeIterator.hasNext(); )
- {
- Node node = nodeIterator.next();
- assertTrue( list.remove( node ) );
- nodeIterator.remove();
-
- count++;
- if ( count == removalCount )
- {
- return;
- }
- }
- }
-
- private ArrayList<Node> createNodes( int count )
- {
- ArrayList<Node> nodes = new ArrayList<Node>();
- for ( int i = 0; i < count; i++ )
- {
- nodes.add( graphDb().createNode() );
- }
- Collections.sort( nodes, new IdComparator() );
- Collections.reverse( nodes );
- return nodes;
- }
}
Oops, something went wrong.

0 comments on commit c11d431

Please sign in to comment.