Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
  • 3 commits
  • 9 files changed
  • 0 commit comments
  • 1 contributor
View
2 community/kernel/src/main/java/org/neo4j/helpers/Enc128.java
@@ -31,7 +31,7 @@
*/
public int encode( ByteBuffer target, long value )
{
- assert value >= 0;
+ assert value >= 0 : "Invalid value " + value;
int startPosition = target.position();
while ( true )
View
130 community/kernel/src/main/java/org/neo4j/helpers/LinkBlock.java
@@ -0,0 +1,130 @@
+/**
+ * Copyright (c) 2002-2013 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.neo4j.helpers;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Comparator;
+
+public class LinkBlock
+{
+ private static final int HEADER_SIZE = 8+8+4+4;
+ private final Enc128 encoder = new Enc128();
+ private final Type type;
+ private final ByteBuffer buffer;
+ private int idCount;
+ private long firstRelId, lastRelId;
+
+ public LinkBlock( Type type )
+ {
+ this.type = type;
+ this.buffer = type.allocateBuffer();
+ }
+
+ public void set( long[][] relAndNodeIdPairs )
+ {
+ Arrays.sort( relAndNodeIdPairs, SORTER );
+
+ // Header
+ buffer.putLong( (firstRelId = relAndNodeIdPairs[0][0]) );
+ buffer.putLong( (lastRelId = relAndNodeIdPairs[relAndNodeIdPairs.length-1][0]) );
+ buffer.putInt( (idCount = relAndNodeIdPairs.length) );
+
+ // Ids
+ long previousRelId = relAndNodeIdPairs[0][0], previousRelNodeDelta = relAndNodeIdPairs[0][1] - previousRelId;
+ encoder.encode( buffer, previousRelId );
+ encoder.encode( buffer, previousRelNodeDelta );
+ for ( int i = 1; i < relAndNodeIdPairs.length; i++ )
+ {
+ long[] pair = relAndNodeIdPairs[i];
+ long relDelta = pair[0]-previousRelId;
+ long relNodeDelta = pair[1]-pair[0];
+ long derivativeRelNodeDelta = relNodeDelta-previousRelNodeDelta;
+ encoder.encode( buffer, relDelta );
+ encoder.encode( buffer, derivativeRelNodeDelta );
+ previousRelId = pair[0];
+ previousRelNodeDelta = relNodeDelta;
+ }
+ }
+
+ public void get( long[][] target )
+ {
+ assert target.length >= idCount;
+
+ // Header
+ buffer.position( HEADER_SIZE );
+
+ target[0][0] = encoder.decode( buffer );
+ target[0][1] = target[0][0] + encoder.decode( buffer );
+ for ( int i = 1; i < target.length; i++ )
+ {
+ long relDelta = encoder.decode( buffer );
+ long relId = target[i-1][0] + relDelta;
+ long derivativeRelNodeDelta = encoder.decode( buffer );
+ long previousRelNodeDelta = target[i-1][1] - target[i-1][0];
+ target[i][0] = relId;
+ target[i][1] = previousRelNodeDelta + relId + derivativeRelNodeDelta;
+ }
+ }
+
+ // TODO method for looking up a node for a relationship
+
+ private static final Comparator<long[]> SORTER = new Comparator<long[]>()
+ {
+ @Override
+ public int compare( long[] o1, long[] o2 )
+ {
+ return Long.compare( o1[0], o2[0] );
+ }
+ };
+
+ public static enum Type
+ {
+ // TODO think about sizes
+ SMALL( 256 ),
+ MEDIUM( 256*256 ),
+ LARGE( 256*256*256 );
+
+ private final int byteSize;
+
+ private Type( int byteSize )
+ {
+ this.byteSize = byteSize;
+ }
+
+ int byteSize()
+ {
+ return byteSize;
+ }
+
+ ByteBuffer allocateBuffer()
+ {
+ ByteBuffer result = ByteBuffer.allocate( byteSize );
+ result.putInt( byteSize() );
+ return result;
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return getClass().getSimpleName() + "[" + buffer + "]";
+ }
+}
View
624 community/kernel/src/main/java/org/neo4j/kernel/impl/util/RelIdArray.java
@@ -19,19 +19,30 @@
*/
package org.neo4j.kernel.impl.util;
-import static org.neo4j.kernel.impl.cache.SizeOfs.withArrayOverhead;
import static org.neo4j.kernel.impl.cache.SizeOfs.withObjectOverhead;
import static org.neo4j.kernel.impl.cache.SizeOfs.withReference;
+import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.NoSuchElementException;
import org.neo4j.graphdb.Direction;
+import org.neo4j.helpers.Enc128;
import org.neo4j.kernel.impl.cache.SizeOf;
-import org.neo4j.kernel.impl.cache.SizeOfs;
+/**
+ * About the state of the {@link ByteBuffer}s that store the ids in here:
+ *
+ * A buffer that is currently assigned to the fields has:
+ * + its position where to write new ids.
+ *
+ * @author Mattias
+ *
+ */
public class RelIdArray implements SizeOf
{
+ private static final Enc128 enc128 = new Enc128();
+
private static final DirectionWrapper[] DIRECTIONS_FOR_OUTGOING =
new DirectionWrapper[] { DirectionWrapper.OUTGOING, DirectionWrapper.BOTH };
private static final DirectionWrapper[] DIRECTIONS_FOR_INCOMING =
@@ -56,10 +67,12 @@ protected boolean nextBlock()
return false;
}
+ @Override
public void doAnotherRound()
{
}
+ @Override
public RelIdIterator updateSource( RelIdArray newSource, DirectionWrapper direction )
{
return direction.iterator( newSource );
@@ -86,22 +99,23 @@ public static RelIdArray empty( int type )
public static final RelIdArray EMPTY = new EmptyRelIdArray( -1 );
private final int type;
- private IdBlock lastOutBlock;
- private IdBlock lastInBlock;
+ private ByteBuffer outIds;
+ private ByteBuffer inIds;
public RelIdArray( int type )
{
this.type = type;
}
+ @Override
public int size()
{
- return withObjectOverhead( 8 /*type (padded)*/ + sizeOfBlockWithReference( lastOutBlock ) + sizeOfBlockWithReference( lastInBlock ) );
+ return withObjectOverhead( 8 /*type (padded)*/ + sizeOfBlockWithReference( outIds ) + sizeOfBlockWithReference( inIds ) );
}
- static int sizeOfBlockWithReference( IdBlock block )
+ static int sizeOfBlockWithReference( ByteBuffer ids )
{
- return withReference( block != null ? block.size() : 0 );
+ return withReference( ids != null ? withObjectOverhead( ids.capacity() ) : 0 );
}
public int getType()
@@ -112,15 +126,15 @@ public int getType()
protected RelIdArray( RelIdArray from )
{
this( from.type );
- this.lastOutBlock = from.lastOutBlock;
- this.lastInBlock = from.lastInBlock;
+ this.outIds = from.outIds;
+ this.inIds = from.inIds;
}
- protected RelIdArray( int type, IdBlock out, IdBlock in )
+ protected RelIdArray( int type, ByteBuffer out, ByteBuffer in )
{
this( type );
- this.lastOutBlock = out;
- this.lastInBlock = in;
+ this.outIds = out;
+ this.inIds = in;
}
/*
@@ -128,32 +142,49 @@ protected RelIdArray( int type, IdBlock out, IdBlock in )
*/
public void add( long id, DirectionWrapper direction )
{
- IdBlock lastBlock = direction.getLastBlock( this );
- long highBits = id&0xFFFFFFFF00000000L;
- if ( lastBlock == null || lastBlock.getHighBits() != highBits )
+ ByteBuffer lastBlock = direction.getLastBlock( this );
+ if ( lastBlock == null )
{
- IdBlock newLastBlock = null;
- if ( highBits == 0 && lastBlock == null )
- {
- newLastBlock = new LowIdBlock();
- }
- else
- {
- // TODO: instead of always creating a new id block when high bits change
- // traverse back and try find a fit
- newLastBlock = new HighIdBlock( highBits );
- if ( lastBlock != null )
- {
- lastBlock = lastBlock.upgradeIfNeeded();
- newLastBlock.setPrev( lastBlock );
- }
- }
+ ByteBuffer newLastBlock = null;
+ newLastBlock = ByteBuffer.allocate( 20 );
direction.setLastBlock( this, newLastBlock );
lastBlock = newLastBlock;
}
- lastBlock.add( (int) id );
+ add( lastBlock, id, direction );
}
+ private void add( ByteBuffer buffer, long id, DirectionWrapper direction )
+ {
+ buffer = ensureBufferSpace( buffer, 1, direction );
+ enc128.encode( buffer, id );
+ }
+
+ private int remainingToWriter( ByteBuffer buffer )
+ {
+ return buffer.capacity()-buffer.position();
+ }
+
+ private ByteBuffer ensureBufferSpace( ByteBuffer buffer, int bytesToAdd, DirectionWrapper direction )
+ {
+ int remaining = remainingToWriter( buffer );
+ if ( bytesToAdd > remaining )
+ {
+ int candidateSize = buffer.capacity()*3;
+ if ( candidateSize < remaining+bytesToAdd )
+ candidateSize = (remaining+bytesToAdd)*2;
+
+ buffer = copy( buffer, candidateSize );
+ direction.setLastBlock( this, buffer );
+ }
+ return buffer;
+ }
+
+ private void addAll( ByteBuffer target, ByteBuffer source, DirectionWrapper direction )
+ {
+ target = ensureBufferSpace( target, source.capacity(), direction );
+ target.put( newBufferForReading( source ) );
+ }
+
public RelIdArray addAll( RelIdArray source )
{
if ( source == null )
@@ -172,20 +203,37 @@ public RelIdArray addAll( RelIdArray source )
return this;
}
- protected IdBlock getLastLoopBlock()
+ protected ByteBuffer getLastLoopBlock()
{
return null;
}
public RelIdArray shrink()
{
- IdBlock shrunkOut = lastOutBlock != null ? lastOutBlock.shrink() : null;
- IdBlock shrunkIn = lastInBlock != null ? lastInBlock.shrink() : null;
- return shrunkOut == lastOutBlock && shrunkIn == lastInBlock ? this :
+ ByteBuffer shrunkOut = shrink( outIds );
+ ByteBuffer shrunkIn = shrink( inIds );
+ return shrunkOut == outIds && shrunkIn == inIds ? this :
new RelIdArray( type, shrunkOut, shrunkIn );
}
- protected void setLastLoopBlock( IdBlock block )
+ protected ByteBuffer shrink( ByteBuffer buffer )
+ {
+ if ( buffer == null || buffer.position() == buffer.capacity() )
+ return buffer;
+
+ return copy( buffer, buffer.position() );
+ }
+
+ private ByteBuffer copy( ByteBuffer buffer, int newSize )
+ {
+ ByteBuffer newBuffer = ByteBuffer.allocate( newSize );
+ ByteBuffer reader = buffer.duplicate();
+ reader.flip();
+ newBuffer.put( reader );
+ return newBuffer;
+ }
+
+ protected void setLastLoopBlock( ByteBuffer block )
{
throw new UnsupportedOperationException( "Should've upgraded to RelIdArrayWithLoops before this" );
}
@@ -202,67 +250,24 @@ public RelIdArray downgradeIfPossible()
protected void append( RelIdArray source, DirectionWrapper direction )
{
- IdBlock toBlock = direction.getLastBlock( this );
- IdBlock fromBlock = direction.getLastBlock( source );
+ ByteBuffer toBlock = direction.getLastBlock( this );
+ ByteBuffer fromBlock = direction.getLastBlock( source );
if ( fromBlock != null )
{
if ( toBlock == null )
{
- direction.setLastBlock( this, fromBlock.copy() );
- }
- else if ( toBlock.getHighBits() == fromBlock.getHighBits() )
- {
- toBlock.addAll( fromBlock );
- if ( fromBlock.getPrev() != null )
- {
- boolean isTheOnlyOne = toBlock.getPrev() == null;
- IdBlock last = last( toBlock );
- last.setPrev( fromBlock.getPrev().copy() );
- if ( isTheOnlyOne )
- {
- direction.setLastBlock( this, last );
- }
- }
+ direction.setLastBlock( this, copy( fromBlock, fromBlock.position() ) );
}
else
{
- boolean isTheOnlyOne = toBlock.getPrev() == null;
- IdBlock last = last( toBlock );
- last.setPrev( fromBlock.copy() );
- if ( isTheOnlyOne )
- {
- direction.setLastBlock( this, last );
- }
+ addAll( toBlock, fromBlock, direction );
}
}
}
- /**
- * Also upgrade along the way if necessary
- */
- private static IdBlock last( IdBlock block )
- {
- IdBlock previousInLoop = null;
- while ( true )
- {
- block = block.upgradeIfNeeded();
- if ( previousInLoop != null )
- {
- previousInLoop.setPrev( block );
- }
- IdBlock prev = block.getPrev();
- if ( prev == null )
- {
- return block;
- }
- previousInLoop = block;
- block = prev;
- }
- }
-
public boolean isEmpty()
{
- return lastOutBlock == null && lastInBlock == null && getLastLoopBlock() == null ;
+ return outIds == null && inIds == null && getLastLoopBlock() == null;
}
public RelIdIterator iterator( DirectionWrapper direction )
@@ -275,8 +280,6 @@ public RelIdArray newSimilarInstance()
return new RelIdArray( type );
}
- public static final IdBlock EMPTY_BLOCK = new LowIdBlock();
-
public static enum DirectionWrapper
{
OUTGOING( Direction.OUTGOING )
@@ -288,15 +291,15 @@ RelIdIterator iterator( RelIdArray ids )
}
@Override
- IdBlock getLastBlock( RelIdArray ids )
+ ByteBuffer getLastBlock( RelIdArray ids )
{
- return ids.lastOutBlock;
+ return ids.outIds;
}
@Override
- void setLastBlock( RelIdArray ids, IdBlock block )
+ void setLastBlock( RelIdArray ids, ByteBuffer buffer )
{
- ids.lastOutBlock = block;
+ ids.outIds = buffer;
}
},
INCOMING( Direction.INCOMING )
@@ -308,15 +311,15 @@ RelIdIterator iterator( RelIdArray ids )
}
@Override
- IdBlock getLastBlock( RelIdArray ids )
+ ByteBuffer getLastBlock( RelIdArray ids )
{
- return ids.lastInBlock;
+ return ids.inIds;
}
@Override
- void setLastBlock( RelIdArray ids, IdBlock block )
+ void setLastBlock( RelIdArray ids, ByteBuffer buffer )
{
- ids.lastInBlock = block;
+ ids.inIds = buffer;
}
},
BOTH( Direction.BOTH )
@@ -328,13 +331,13 @@ RelIdIterator iterator( RelIdArray ids )
}
@Override
- IdBlock getLastBlock( RelIdArray ids )
+ ByteBuffer getLastBlock( RelIdArray ids )
{
return ids.getLastLoopBlock();
}
@Override
- void setLastBlock( RelIdArray ids, IdBlock block )
+ void setLastBlock( RelIdArray ids, ByteBuffer block )
{
ids.setLastLoopBlock( block );
}
@@ -352,12 +355,12 @@ private DirectionWrapper( Direction direction )
/*
* Only used during add
*/
- abstract IdBlock getLastBlock( RelIdArray ids );
+ abstract ByteBuffer getLastBlock( RelIdArray ids );
/*
* Only used during add
*/
- abstract void setLastBlock( RelIdArray ids, IdBlock block );
+ abstract void setLastBlock( RelIdArray ids, ByteBuffer buffer );
public Direction direction()
{
@@ -376,238 +379,121 @@ public static DirectionWrapper wrap( Direction direction )
}
}
- public static abstract class IdBlock implements SizeOf
- {
- // First element is the actual length w/o the slack
- private int[] ids = new int[3];
-
- /**
- * @return a copy of itself. The copy is also shrunk so that there's no
- * slack in the id array.
- */
- IdBlock copy()
- {
- IdBlock copy = copyInstance();
- int length = length();
- copy.ids = new int[length+1];
- System.arraycopy( ids, 0, copy.ids, 0, length+1 );
- return copy;
- }
-
- public int size()
- {
- return withObjectOverhead( withReference( withArrayOverhead( 4*ids.length ) ) );
- }
-
- /**
- * @return a shrunk version of itself. It returns itself if there is
- * no need to shrink it or a {@link #copy()} if there is slack in the array.
- */
- IdBlock shrink()
- {
- return length() == ids.length-1 ? this : copy();
- }
-
- /**
- * Upgrades to a {@link HighIdBlock} if this is a {@link LowIdBlock}.
- */
- abstract IdBlock upgradeIfNeeded();
-
- int length()
- {
- return ids[0];
- }
-
- IdBlock getPrev()
- {
- return null;
- }
-
- abstract void setPrev( IdBlock prev );
-
- protected abstract IdBlock copyInstance();
-
- // Assume id has same high bits
- void add( int id )
- {
- int length = ensureSpace( 1 );
- ids[length+1] = id;
- ids[0] = length+1;
- }
-
- int ensureSpace( int delta )
- {
- int length = length();
- int newLength = length+delta;
- if ( newLength >= ids.length-1 )
- {
- int calculatedLength = ids.length*2;
- if ( newLength > calculatedLength )
- {
- calculatedLength = newLength*2;
- }
- int[] newIds = new int[calculatedLength];
- System.arraycopy( ids, 0, newIds, 0, length+1 );
- ids = newIds;
- }
- return length;
- }
-
- void addAll( IdBlock block )
- {
- int otherBlockLength = block.length();
- int length = ensureSpace( otherBlockLength+1 );
- System.arraycopy( block.ids, 1, ids, length+1, otherBlockLength );
- ids[0] = otherBlockLength+length;
- }
-
- long get( int index )
- {
- assert index >= 0 && index < length();
- return transform( ids[index+1] );
- }
-
- abstract long transform( int id );
-
- void set( long id, int index )
- {
- // Assume same high bits
- ids[index+1] = (int) id;
- }
-
- abstract long getHighBits();
- }
-
- private static class LowIdBlock extends IdBlock
- {
- @Override
- void setPrev( IdBlock prev )
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- IdBlock upgradeIfNeeded()
- {
- IdBlock highBlock = new HighIdBlock( 0 );
- highBlock.ids = ((IdBlock)this).ids;
- return highBlock;
- }
-
- @Override
- long transform( int id )
- {
- return (long)(id&0xFFFFFFFFL);
- }
-
- @Override
- protected IdBlock copyInstance()
- {
- return new LowIdBlock();
- }
-
- @Override
- long getHighBits()
- {
- return 0;
- }
- }
-
- private static class HighIdBlock extends IdBlock
- {
- private final long highBits;
- private IdBlock prev;
-
- HighIdBlock( long highBits )
- {
- this.highBits = highBits;
- }
-
- public int size()
- {
- int size = super.size() + 8 + SizeOfs.REFERENCE_SIZE;
- if ( prev != null )
- {
- size += prev.size();
- }
- return size;
- }
-
- @Override
- IdBlock upgradeIfNeeded()
- {
- return this;
- }
-
- @Override
- IdBlock copy()
- {
- IdBlock copy = super.copy();
- if ( prev != null )
- {
- copy.setPrev( prev.copy() );
- }
- return copy;
- }
-
- @Override
- IdBlock getPrev()
- {
- return prev;
- }
-
- @Override
- void setPrev( IdBlock prev )
- {
- this.prev = prev;
- }
-
- @Override
- long transform( int id )
- {
- return (((long)(id&0xFFFFFFFFL))|(highBits));
- }
-
- @Override
- protected IdBlock copyInstance()
- {
- return new HighIdBlock( highBits );
- }
-
- @Override
- long getHighBits()
- {
- return highBits;
- }
- }
+// public static abstract class IdBlock implements SizeOf
+// {
+// // First element is the actual length w/o the slack
+// private int[] ids = new int[3];
+//
+// /**
+// * @return a copy of itself. The copy is also shrunk so that there's no
+// * slack in the id array.
+// */
+// IdBlock copy()
+// {
+// IdBlock copy = copyInstance();
+// int length = length();
+// copy.ids = new int[length+1];
+// System.arraycopy( ids, 0, copy.ids, 0, length+1 );
+// return copy;
+// }
+//
+// public int size()
+// {
+// return withObjectOverhead( withReference( withArrayOverhead( 4*ids.length ) ) );
+// }
+//
+// /**
+// * @return a shrunk version of itself. It returns itself if there is
+// * no need to shrink it or a {@link #copy()} if there is slack in the array.
+// */
+// IdBlock shrink()
+// {
+// return length() == ids.length-1 ? this : copy();
+// }
+//
+// /**
+// * Upgrades to a {@link HighIdBlock} if this is a {@link LowIdBlock}.
+// */
+// abstract IdBlock upgradeIfNeeded();
+//
+// int length()
+// {
+// return ids[0];
+// }
+//
+// IdBlock getPrev()
+// {
+// return null;
+// }
+//
+// abstract void setPrev( IdBlock prev );
+//
+// protected abstract IdBlock copyInstance();
+//
+// // Assume id has same high bits
+// void add( int id )
+// {
+// int length = ensureSpace( 1 );
+// ids[length+1] = id;
+// ids[0] = length+1;
+// }
+//
+// int ensureSpace( int delta )
+// {
+// int length = length();
+// int newLength = length+delta;
+// if ( newLength >= ids.length-1 )
+// {
+// int calculatedLength = ids.length*2;
+// if ( newLength > calculatedLength )
+// {
+// calculatedLength = newLength*2;
+// }
+// int[] newIds = new int[calculatedLength];
+// System.arraycopy( ids, 0, newIds, 0, length+1 );
+// ids = newIds;
+// }
+// return length;
+// }
+//
+// void addAll( IdBlock block )
+// {
+// int otherBlockLength = block.length();
+// int length = ensureSpace( otherBlockLength+1 );
+// System.arraycopy( block.ids, 1, ids, length+1, otherBlockLength );
+// ids[0] = otherBlockLength+length;
+// }
+//
+// long get( int index )
+// {
+// assert index >= 0 && index < length();
+// return transform( ids[index+1] );
+// }
+//
+// abstract long transform( int id );
+//
+// void set( long id, int index )
+// {
+// // Assume same high bits
+// ids[index+1] = (int) id;
+// }
+//
+// abstract long getHighBits();
+// }
private static class IteratorState
{
- private int blockIndex;
- private IdBlock block;
- private int relativePosition;
-
- public IteratorState( IdBlock block, int relativePosition )
- {
- this.block = block;
- this.relativePosition = relativePosition;
- }
+ private ByteBuffer block;
- boolean nextBlock()
+ public IteratorState( ByteBuffer block, int relativePosition )
{
- if ( block.getPrev() != null )
- {
- block = block.getPrev();
- relativePosition = 0;
- blockIndex++;
- return true;
- }
- return false;
+ this.block = newBufferForReading( block );
+ // TODO use relativePosition?
}
boolean hasNext()
{
- return relativePosition < block.length();
+ return block.hasRemaining();
}
/*
@@ -615,19 +501,25 @@ boolean hasNext()
*/
long next()
{
- return block.get( relativePosition++ );
+ return enc128.decode( block );
}
- public void update( IdBlock lastBlock )
+ public void update( ByteBuffer lastBlock )
{
- for ( int i = 0; i < blockIndex; i++ )
- {
- lastBlock = lastBlock.getPrev();
- }
this.block = lastBlock;
}
}
+ private static ByteBuffer newBufferForReading( ByteBuffer buffer )
+ {
+ if ( buffer == null )
+ return buffer;
+ ByteBuffer result = buffer.duplicate();
+ result.position( 0 );
+ result.limit( buffer.position() );
+ return result;
+ }
+
public static class RelIdIteratorImpl implements RelIdIterator
{
private final DirectionWrapper[] directions;
@@ -649,7 +541,7 @@ public void update( IdBlock lastBlock )
// Find the initial block which isn't null. There can be directions
// which have a null block currently, but could potentially be set
// after the next getMoreRelationships.
- IdBlock block = null;
+ ByteBuffer block = null;
while ( block == null && directionPosition+1 < directions.length )
{
currentDirection = directions[++directionPosition];
@@ -726,32 +618,15 @@ public boolean hasNext()
nextElement = -1;
return false;
}
-
- protected boolean nextBlock()
- {
- // Try next block in the chain
- if ( currentState != null && currentState.nextBlock() )
- {
- return true;
- }
-
- // It's ok to return null here... which will result in hasNext
- // returning false. IntArrayIterator will try to get more relationships
- // and call hasNext again.
- return findNextBlock();
- }
- /* (non-Javadoc)
- * @see org.neo4j.kernel.impl.util.RelIdIterator#doAnotherRound()
- */
@Override
public void doAnotherRound()
{
directionPosition = -1;
- findNextBlock();
+ nextBlock();
}
- protected boolean findNextBlock()
+ protected boolean nextBlock()
{
while ( directionPosition+1 < directions.length )
{
@@ -762,7 +637,7 @@ protected boolean findNextBlock()
currentState = nextState;
return true;
}
- IdBlock block = currentDirection.getLastBlock( ids );
+ ByteBuffer block = currentDirection.getLastBlock( ids );
if ( block != null )
{
currentState = new IteratorState( block, 0 );
@@ -773,9 +648,6 @@ protected boolean findNextBlock()
return false;
}
- /* (non-Javadoc)
- * @see org.neo4j.kernel.impl.util.RelIdIterator#next()
- */
@Override
public long next()
{
@@ -813,8 +685,8 @@ public static RelIdArray from( RelIdArray src, RelIdArray add, Collection<Long>
if ( src != null )
{
newArray = src.newSimilarInstance();
- newArray.addAll( src );
- evictExcluded( newArray, remove );
+ newArray = newArray.addAll( src );
+ newArray.removeAll( remove );
}
else
{
@@ -836,33 +708,28 @@ public static RelIdArray from( RelIdArray src, RelIdArray add, Collection<Long>
}
}
- private static void evictExcluded( RelIdArray ids, Collection<Long> excluded )
+ private void removeAll( Collection<Long> excluded )
+ {
+ removeAll( excluded, DirectionWrapper.OUTGOING );
+ removeAll( excluded, DirectionWrapper.INCOMING );
+ removeAll( excluded, DirectionWrapper.BOTH );
+ }
+
+ private void removeAll( Collection<Long> excluded, DirectionWrapper direction )
{
- for ( RelIdIteratorImpl iterator = (RelIdIteratorImpl) DirectionWrapper.BOTH.iterator( ids ); iterator.hasNext(); )
+ ByteBuffer buffer = direction.getLastBlock( this );
+ if ( buffer == null )
+ return;
+
+ ByteBuffer newBuffer = ByteBuffer.allocate( buffer.capacity() );
+ for ( RelIdIteratorImpl iterator = (RelIdIteratorImpl) direction.iterator( this ); iterator.hasNext(); )
{
long value = iterator.next();
- if ( excluded.contains( value ) )
- {
- boolean swapSuccessful = false;
- IteratorState state = iterator.currentState;
- IdBlock block = state.block;
- for ( int j = block.length() - 1; j >= state.relativePosition; j--)
- {
- long backValue = block.get( j );
- block.ids[0] = block.ids[0]-1;
- if ( !excluded.contains( backValue) )
- {
- block.set( backValue, state.relativePosition-1 );
- swapSuccessful = true;
- break;
- }
- }
- if ( !swapSuccessful ) // all elements from pos in remove
- {
- block.ids[0] = block.ids[0]-1;
- }
- }
+ if ( !excluded.contains( value ) )
+ add( newBuffer, value, iterator.currentDirection );
}
+ newBuffer = copy( newBuffer, newBuffer.position() );
+ direction.setLastBlock( this, newBuffer );
}
/**
@@ -874,7 +741,6 @@ private static void evictExcluded( RelIdArray ids, Collection<Long> excluded )
*/
public boolean couldBeNeedingUpdate()
{
- return (lastOutBlock != null && lastOutBlock.getPrev() != null) ||
- (lastInBlock != null && lastInBlock.getPrev() != null);
+ return false;
}
}
View
23 community/kernel/src/main/java/org/neo4j/kernel/impl/util/RelIdArrayWithLoops.java
@@ -19,9 +19,11 @@
*/
package org.neo4j.kernel.impl.util;
+import java.nio.ByteBuffer;
+
public class RelIdArrayWithLoops extends RelIdArray
{
- private IdBlock lastLoopBlock;
+ private ByteBuffer lastLoopBlock;
public RelIdArrayWithLoops( int type )
{
@@ -40,20 +42,20 @@ protected RelIdArrayWithLoops( RelIdArray from )
lastLoopBlock = from.getLastLoopBlock();
}
- protected RelIdArrayWithLoops( int type, IdBlock out, IdBlock in, IdBlock loop )
+ protected RelIdArrayWithLoops( int type, ByteBuffer out, ByteBuffer in, ByteBuffer loop )
{
super( type, out, in );
this.lastLoopBlock = loop;
}
@Override
- protected IdBlock getLastLoopBlock()
+ protected ByteBuffer getLastLoopBlock()
{
return this.lastLoopBlock;
}
@Override
- protected void setLastLoopBlock( IdBlock block )
+ protected void setLastLoopBlock( ByteBuffer block )
{
this.lastLoopBlock = block;
}
@@ -83,6 +85,7 @@ public RelIdArray addAll( RelIdArray source )
return this;
}
+ @Override
public RelIdArray newSimilarInstance()
{
return new RelIdArrayWithLoops( getType() );
@@ -97,12 +100,12 @@ public boolean couldBeNeedingUpdate()
@Override
public RelIdArray shrink()
{
- IdBlock lastOutBlock = DirectionWrapper.OUTGOING.getLastBlock( this );
- IdBlock lastInBlock = DirectionWrapper.INCOMING.getLastBlock( this );
- IdBlock shrunkOut = lastOutBlock != null ? lastOutBlock.shrink() : null;
- IdBlock shrunkIn = lastInBlock != null ? lastInBlock.shrink() : null;
- IdBlock shrunkLoop = lastLoopBlock != null ? lastLoopBlock.shrink() : null;
- return shrunkOut == lastOutBlock && shrunkIn == lastInBlock && shrunkLoop == lastLoopBlock ? this :
+ ByteBuffer outBuffer = DirectionWrapper.OUTGOING.getLastBlock( this );
+ ByteBuffer shrunkOut = shrink( outBuffer );
+ ByteBuffer inBuffer = DirectionWrapper.INCOMING.getLastBlock( this );
+ ByteBuffer shrunkIn = shrink( inBuffer );
+ ByteBuffer shrunkLoop = shrink( lastLoopBlock );
+ return shrunkOut == outBuffer && shrunkIn == inBuffer && shrunkLoop == lastLoopBlock ? this :
new RelIdArrayWithLoops( getType(), shrunkOut, shrunkIn, shrunkLoop );
}
}
View
2 community/kernel/src/test/java/org/neo4j/helpers/Enc128Test.java
@@ -73,7 +73,7 @@ public void testPerformance() throws Exception
{
int idCount = 10_000_000;
ByteBuffer buffer = ByteBuffer.allocate( idCount*4 );
- for ( int i = 0; i < 1000; i++ )
+ for ( int i = 0; i < 10; i++ )
timeEncodeDecode( buffer, 10_000_000, 100000 );
}
View
73 community/kernel/src/test/java/org/neo4j/helpers/LinkBlockTest.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2002-2013 "Neo Technology,"
+ * Network Engine for Objects in Lund AB [http://neotechnology.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.neo4j.helpers;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import org.junit.Test;
+
+public class LinkBlockTest
+{
+ @Test
+ public void setSinglePair() throws Exception
+ {
+ // GIVEN
+ LinkBlock block = new LinkBlock( LinkBlock.Type.SMALL );
+ long[][] expected = idPairs( 10, 10, 1 );
+ block.set( expected );
+
+ // WHEN
+ long[][] read = new long[1][2];
+ block.get( read );
+
+ // THEN
+ assertArrayEquals( expected[0], read[0] );
+ }
+
+ @Test
+ public void setManyPairs() throws Exception
+ {
+ // GIVEN
+ LinkBlock block = new LinkBlock( LinkBlock.Type.LARGE );
+ long[][] expected = idPairs( 5, 10, 10000 );
+ block.set( expected );
+ System.out.println( block );
+
+ // WHEN
+ long[][] read = new long[expected.length][2];
+ block.get( read );
+
+ for ( int i = 0; i < read.length; i++ )
+ {
+ assertArrayEquals( "At index " + i, expected[i], read[i] );
+ }
+ }
+
+ private long[][] idPairs( long firstRelId, long firstNodeId, int count )
+ {
+ long result[][] = new long[count][2];
+ for ( int i = 0; i < count; i++ )
+ {
+ result[i][0] = firstRelId+i;
+ result[i][1] = firstNodeId+i;
+ }
+ return result;
+ }
+}
View
16 community/kernel/src/test/java/org/neo4j/kernel/impl/core/TestRelIdArray.java
@@ -22,12 +22,12 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.neo4j.helpers.collection.IteratorUtil.asSet;
import static org.neo4j.kernel.impl.util.RelIdArray.DirectionWrapper.BOTH;
import static org.neo4j.kernel.impl.util.RelIdArray.DirectionWrapper.INCOMING;
import static org.neo4j.kernel.impl.util.RelIdArray.DirectionWrapper.OUTGOING;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -56,7 +56,7 @@ public void testBasic() throws Exception
assertEquals( 1L, itr.next() );
assertTrue( itr.hasNext() );
assertEquals( 2L, itr.next() );
- assertFalse( itr.hasNext() );
+ assertFalse( "Should have no more", itr.hasNext() );
assertFalse( itr.hasNext() );
// Iterate INCOMING
@@ -95,7 +95,7 @@ public void testWithAddRemove() throws Exception
remove.add( 6L );
List<Long> allIds = asList( RelIdArray.from( source, add, remove ) );
Collections.sort( allIds );
- assertEquals( Arrays.asList( 1L, 3L, 4L, 5L, 7L ), allIds );
+ assertEquals( asSet( 1L, 3L, 4L, 5L, 7L ), asSet( allIds ) );
}
@Test
@@ -115,12 +115,13 @@ public void testDifferentBlocks() throws Exception
array.add( verySmall, OUTGOING );
array.add( verySmall+1, OUTGOING );
- Collection<Long> allIds = new HashSet<Long>( asList( array ) );
- assertEquals( new HashSet<Long>( Arrays.asList(
+ assertEquals( asSet(
justUnderIntMax, justUnderIntMax+1,
justOverIntMax, justOverIntMax+1,
aBitOverIntMax, aBitOverIntMax+1,
- verySmall, verySmall+1 ) ), allIds );
+ verySmall, verySmall+1 ),
+
+ asSet( asList( array ) ) );
}
@Test
@@ -139,8 +140,7 @@ public void testAddDifferentBlocks() throws Exception
all.addAll( array1 );
all.addAll( array2 );
- assertEquals( new HashSet<Long>( Arrays.asList(
- 0L, 1L, justOverIntMax, justOverIntMax+1 ) ), new HashSet<Long>( asList( all ) ) );
+ assertEquals( asSet( 0L, 1L, justOverIntMax, justOverIntMax+1 ), asSet( asList( all ) ) );
}
private List<Long> asList( RelIdArray ids )
View
7 community/server/src/main/java/org/neo4j/server/rest/web/CypherService.java
@@ -35,7 +35,6 @@
import org.neo4j.server.rest.repr.CypherResultRepresentation;
import org.neo4j.server.rest.repr.InputFormat;
import org.neo4j.server.rest.repr.OutputFormat;
-import org.neo4j.server.rest.repr.ValueRepresentation;
@Path("/cypher")
public class CypherService
@@ -46,9 +45,9 @@
private static final String INCLUDE_PLAN_PARAM = "includePlan";
private static final String PROFILE_PARAM = "profile";
- private CypherExecutor cypherExecutor;
- private OutputFormat output;
- private InputFormat input;
+ private final CypherExecutor cypherExecutor;
+ private final OutputFormat output;
+ private final InputFormat input;
public CypherService( @Context CypherExecutor cypherExecutor, @Context InputFormat input,
@Context OutputFormat output )
View
2 enterprise/cluster/src/main/java/org/neo4j/cluster/ClusterSettings.java
@@ -20,12 +20,10 @@
package org.neo4j.cluster;
import static org.neo4j.graphdb.factory.GraphDatabaseSetting.ANY;
-import static org.neo4j.graphdb.factory.GraphDatabaseSetting.FALSE;
import static org.neo4j.graphdb.factory.GraphDatabaseSetting.TRUE;
import static org.neo4j.helpers.Settings.BOOLEAN;
import static org.neo4j.helpers.Settings.DURATION;
import static org.neo4j.helpers.Settings.HOSTNAME_PORT;
-import static org.neo4j.helpers.Settings.NO_DEFAULT;
import static org.neo4j.helpers.Settings.STRING;
import static org.neo4j.helpers.Settings.illegalValueMessage;
import static org.neo4j.helpers.Settings.list;

No commit comments for this range

Something went wrong with that request. Please try again.