You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by be...@apache.org on 2014/06/30 15:32:09 UTC
[1/3] git commit: Optimise CellName/Composite comparisons for
NativeCell
Repository: cassandra
Updated Branches:
refs/heads/cassandra-2.1 5c8569976 -> e77ea1252
refs/heads/trunk 2472701e1 -> 51cdeed48
Optimise CellName/Composite comparisons for NativeCell
patch by Jake Luciani and Benedict Elliott Smith for CASSANDRA-6755
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/e77ea125
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/e77ea125
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/e77ea125
Branch: refs/heads/cassandra-2.1
Commit: e77ea1252092bc0e589cfbc2341c2194cb750b08
Parents: 5c85699
Author: Benedict Elliott Smith <be...@apache.org>
Authored: Mon Jun 30 14:30:55 2014 +0100
Committer: Benedict Elliott Smith <be...@apache.org>
Committed: Mon Jun 30 14:30:55 2014 +0100
----------------------------------------------------------------------
build.xml | 4 +-
conf/cassandra-env.sh | 4 +
conf/cassandra.yaml | 2 +-
.../apache/cassandra/db/AbstractNativeCell.java | 55 ++++-
.../cassandra/db/ArrayBackedSortedColumns.java | 4 +-
.../apache/cassandra/db/AtomicBTreeColumns.java | 13 +-
.../apache/cassandra/db/BufferDecoratedKey.java | 2 +
.../cassandra/db/CollationController.java | 2 +
.../apache/cassandra/db/ConsistencyLevel.java | 2 +
.../org/apache/cassandra/db/DecoratedKey.java | 3 +
.../apache/cassandra/db/NativeDecoratedKey.java | 3 +-
.../cassandra/db/composites/AbstractCType.java | 93 ++++++--
.../db/composites/AbstractCellNameType.java | 23 +-
.../AbstractCompoundCellNameType.java | 2 +
.../composites/AbstractSimpleCellNameType.java | 80 +++++--
.../apache/cassandra/db/composites/CType.java | 2 +
.../cassandra/db/composites/CellNameType.java | 3 +-
.../cassandra/db/composites/Composites.java | 5 +-
.../composites/CompoundSparseCellNameType.java | 2 -
.../cassandra/db/composites/SimpleCType.java | 22 +-
.../apache/cassandra/db/filter/ColumnSlice.java | 52 +++--
.../cassandra/db/filter/NamesQueryFilter.java | 2 +-
.../cassandra/db/filter/SliceQueryFilter.java | 2 +-
.../cassandra/io/sstable/IndexHelper.java | 4 +-
.../org/apache/cassandra/io/util/Memory.java | 3 +-
.../apache/cassandra/service/StorageProxy.java | 3 +
.../cassandra/thrift/CassandraServer.java | 15 +-
.../apache/cassandra/utils/ByteBufferUtil.java | 4 +
.../cassandra/utils/FastByteOperations.java | 226 +++++++++----------
.../org/apache/cassandra/utils/MurmurHash.java | 3 +
.../cassandra/utils/btree/NodeBuilder.java | 5 +-
.../cassandra/utils/memory/MemoryUtil.java | 1 +
.../org/apache/cassandra/db/NativeCellTest.java | 80 +++++++
.../cassandra/db/composites/CTypeTest.java | 9 -
.../cassandra/db/filter/ColumnSliceTest.java | 4 +-
35 files changed, 501 insertions(+), 238 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index c34bcfc..bc2bbfd 100644
--- a/build.xml
+++ b/build.xml
@@ -62,7 +62,6 @@
<property name="test.long.src" value="${test.dir}/long"/>
<property name="test.pig.src" value="${test.dir}/pig"/>
<property name="dist.dir" value="${build.dir}/dist"/>
-
<property name="source.version" value="1.7"/>
<property name="target.version" value="1.7"/>
@@ -402,6 +401,7 @@
<dependency groupId="com.clearspring.analytics" artifactId="stream" version="2.5.2" />
<dependency groupId="com.datastax.cassandra" artifactId="cassandra-driver-core" version="2.0.1" />
<dependency groupId="net.sf.supercsv" artifactId="super-csv" version="2.1.0" />
+ <dependency groupId="net.ju-n.compile-command-annotations" artifactId="compile-command-annotations" version="1.2.0" />
</dependencyManagement>
<developer id="alakshman" name="Avinash Lakshman"/>
<developer id="antelder" name="Anthony Elder"/>
@@ -433,6 +433,7 @@
<dependency groupId="org.apache.pig" artifactId="pig"/>
<dependency groupId="com.google.code.findbugs" artifactId="jsr305"/>
<dependency groupId="com.datastax.cassandra" artifactId="cassandra-driver-core"/>
+ <dependency groupId="net.ju-n.compile-command-annotations" artifactId="compile-command-annotations"/>
</artifact:pom>
<artifact:pom id="coverage-deps-pom"
@@ -701,6 +702,7 @@
<copy todir="${build.classes.main}">
<fileset dir="${build.src.resources}" />
</copy>
+ <copy todir="${basedir}/conf" file="${build.classes.main}/META-INF/hotspot_compiler"/>
</target>
<!-- Stress build file -->
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/conf/cassandra-env.sh
----------------------------------------------------------------------
diff --git a/conf/cassandra-env.sh b/conf/cassandra-env.sh
index eb0553b..1655438 100644
--- a/conf/cassandra-env.sh
+++ b/conf/cassandra-env.sh
@@ -212,6 +212,7 @@ JVM_OPTS="$JVM_OPTS -XX:MaxTenuringThreshold=1"
JVM_OPTS="$JVM_OPTS -XX:CMSInitiatingOccupancyFraction=75"
JVM_OPTS="$JVM_OPTS -XX:+UseCMSInitiatingOccupancyOnly"
JVM_OPTS="$JVM_OPTS -XX:+UseTLAB"
+JVM_OPTS="$JVM_OPTS -XX:CompileCommandFile=$CASSANDRA_CONF/hotspot_compiler"
# note: bash evals '1.7.x' as > '1.7' so this is really a >= 1.7 jvm check
if [ "$JVM_ARCH" = "64-Bit" ] ; then
@@ -242,6 +243,9 @@ fi
# uncomment to have Cassandra JVM listen for remote debuggers/profilers on port 1414
# JVM_OPTS="$JVM_OPTS -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1414"
+# uncomment to have Cassandra JVM log internal method compilation (developers only)
+# JVM_OPTS="$JVM_OPTS -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation"
+
# Prefer binding to IPv4 network intefaces (when net.ipv6.bindv6only=1). See
# http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6342561 (short version:
# comment out this entry to enable IPv6 support).
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/conf/cassandra.yaml
----------------------------------------------------------------------
diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml
index f1e5576..4d97e86 100644
--- a/conf/cassandra.yaml
+++ b/conf/cassandra.yaml
@@ -290,7 +290,7 @@ memtable_cleanup_threshold: 0.4
# heap_buffers: on heap nio buffers
# offheap_buffers: off heap (direct) nio buffers
# offheap_objects: native memory, eliminating nio buffer heap overhead
-memtable_allocation_type: heap_buffers
+memtable_allocation_type: offheap_objects
# Total space to use for commitlogs. Since commitlog segments are
# mmapped, and hence use up address space, the default size is 32
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/AbstractNativeCell.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/AbstractNativeCell.java b/src/java/org/apache/cassandra/db/AbstractNativeCell.java
index f3128b8..d79ad19 100644
--- a/src/java/org/apache/cassandra/db/AbstractNativeCell.java
+++ b/src/java/org/apache/cassandra/db/AbstractNativeCell.java
@@ -21,6 +21,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.MessageDigest;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.ColumnIdentifier;
@@ -30,6 +31,7 @@ import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.FastByteOperations;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.*;
@@ -286,13 +288,24 @@ public abstract class AbstractNativeCell extends AbstractCell implements CellNam
public ByteBuffer get(int i)
{
+ return get(i, null);
+ }
+
+ @Inline
+ private ByteBuffer get(int i, AbstractAllocator copy)
+ {
// remember to take dense/sparse into account, and only return EOC when not dense
int size = size();
assert i >= 0 && i < size();
int cellNamesOffset = nameDeltaOffset(size);
int startDelta = i == 0 ? 0 : getShort(nameDeltaOffset(i));
int endDelta = i < size - 1 ? getShort(nameDeltaOffset(i + 1)) : valueStartOffset() - cellNamesOffset;
- return getByteBuffer(cellNamesOffset + startDelta, endDelta - startDelta).order(ByteOrder.BIG_ENDIAN);
+ int length = endDelta - startDelta;
+ if (copy == null)
+ return getByteBuffer(cellNamesOffset + startDelta, length).order(ByteOrder.BIG_ENDIAN);
+ ByteBuffer result = copy.allocate(length);
+ FastByteOperations.UnsafeOperations.copy(null, peer + cellNamesOffset + startDelta, result, 0, length);
+ return result;
}
private static final ThreadLocal<byte[]> BUFFER = new ThreadLocal<byte[]>()
@@ -496,12 +509,12 @@ public abstract class AbstractNativeCell extends AbstractCell implements CellNam
switch (nametype())
{
case SIMPLE_DENSE:
- return CellNames.simpleDense(allocator.clone(get(0)));
+ return CellNames.simpleDense(get(0, allocator));
case COMPOUND_DENSE:
r = new ByteBuffer[size()];
for (int i = 0; i < r.length; i++)
- r[i] = allocator.clone(get(i));
+ r[i] = get(i, allocator);
return CellNames.compositeDense(r);
case COMPOUND_SPARSE_STATIC:
@@ -509,7 +522,7 @@ public abstract class AbstractNativeCell extends AbstractCell implements CellNam
int clusteringSize = clusteringSize();
r = clusteringSize == 0 ? EMPTY : new ByteBuffer[clusteringSize()];
for (int i = 0; i < clusteringSize; i++)
- r[i] = allocator.clone(get(i));
+ r[i] = get(i, allocator);
ByteBuffer nameBuffer = get(r.length);
ColumnIdentifier name;
@@ -645,4 +658,38 @@ public abstract class AbstractNativeCell extends AbstractCell implements CellNam
checkPosition(offset, length);
return MemoryUtil.getByteBuffer(peer + offset, length);
}
+
+ // requires isByteOrderComparable to be true. Compares the name components only; ; may need to compare EOC etc still
+ public final int compareTo(final Composite that)
+ {
+ int size = size();
+ int size2 = that.size();
+ int minSize = Math.min(size, size2);
+ int startDelta = 0;
+ int cellNamesOffset = nameDeltaOffset(size);
+ for (int i = 0 ; i < minSize ; i++)
+ {
+ int endDelta = i < size - 1 ? getShort(nameDeltaOffset(i + 1)) : valueStartOffset() - cellNamesOffset;
+ long offset = peer + cellNamesOffset + startDelta;
+ int length = endDelta - startDelta;
+ int cmp = FastByteOperations.UnsafeOperations.compareTo(null, offset, length, that.get(i));
+ if (cmp != 0)
+ return cmp;
+ startDelta = endDelta;
+ }
+
+ EOC eoc = that.eoc();
+ if (size == size2)
+ return this.eoc().compareTo(eoc);
+
+ return size < size2 ? this.eoc().prefixComparisonResult : -eoc.prefixComparisonResult;
+ }
+
+ public final int compareToSimple(final Composite that)
+ {
+ assert size() == 1 && that.size() == 1;
+ int length = valueStartOffset() - nameDeltaOffset(1);
+ long offset = peer + nameDeltaOffset(1);
+ return FastByteOperations.UnsafeOperations.compareTo(null, offset, length, that.get(0));
+ }
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java b/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java
index 8a2d43e..e92d5a3 100644
--- a/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java
+++ b/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java
@@ -27,6 +27,7 @@ import com.google.common.base.Function;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Iterables;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.Composite;
@@ -122,6 +123,7 @@ public class ArrayBackedSortedColumns extends ColumnFamily
/**
* synchronized so that concurrent (read-only) accessors don't mess the internal state.
*/
+ @Inline
private synchronized void sortCells()
{
if (isSorted)
@@ -129,7 +131,7 @@ public class ArrayBackedSortedColumns extends ColumnFamily
Comparator<Cell> comparator = reversed
? getComparator().columnReverseComparator()
- : getComparator().columnComparator();
+ : getComparator().columnComparator(false);
// Sort the unsorted segment - will still potentially contain duplicate (non-reconciled) cells
Arrays.sort(cells, sortedSize, size, comparator);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/AtomicBTreeColumns.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/AtomicBTreeColumns.java b/src/java/org/apache/cassandra/db/AtomicBTreeColumns.java
index 03cd0c5..559e759 100644
--- a/src/java/org/apache/cassandra/db/AtomicBTreeColumns.java
+++ b/src/java/org/apache/cassandra/db/AtomicBTreeColumns.java
@@ -40,6 +40,8 @@ import org.apache.cassandra.utils.btree.UpdateFunction;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.HeapAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
+import org.apache.cassandra.utils.memory.NativeAllocator;
+import org.apache.cassandra.utils.memory.NativePool;
import static org.apache.cassandra.db.index.SecondaryIndexManager.Updater;
@@ -186,7 +188,7 @@ public class AtomicBTreeColumns extends ColumnFamily
deletionInfo = current.deletionInfo;
}
- Object[] tree = BTree.update(current.tree, metadata.comparator.columnComparator(), cm, cm.getColumnCount(), true, updater);
+ Object[] tree = BTree.update(current.tree, metadata.comparator.columnComparator(Memtable.MEMORY_POOL instanceof NativePool), cm, cm.getColumnCount(), true, updater);
if (tree != null && refUpdater.compareAndSet(this, current, new Holder(tree, deletionInfo)))
{
@@ -226,14 +228,7 @@ public class AtomicBTreeColumns extends ColumnFamily
private Comparator<Object> asymmetricComparator()
{
- final Comparator<Composite> cmp = metadata.comparator;
- return new Comparator<Object>()
- {
- public int compare(Object o1, Object o2)
- {
- return cmp.compare((Composite) o1, ((Cell) o2).name());
- }
- };
+ return metadata.comparator.asymmetricColumnComparator(Memtable.MEMORY_POOL instanceof NativePool);
}
public Iterable<CellName> getColumnNames()
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/BufferDecoratedKey.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/BufferDecoratedKey.java b/src/java/org/apache/cassandra/db/BufferDecoratedKey.java
index d375162..8a1ad59 100644
--- a/src/java/org/apache/cassandra/db/BufferDecoratedKey.java
+++ b/src/java/org/apache/cassandra/db/BufferDecoratedKey.java
@@ -20,6 +20,8 @@ package org.apache.cassandra.db;
import java.nio.ByteBuffer;
import org.apache.cassandra.dht.Token;
+import org.apache.cassandra.utils.FastByteOperations;
+import org.apache.cassandra.utils.memory.MemoryUtil;
public class BufferDecoratedKey extends DecoratedKey
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/CollationController.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/CollationController.java b/src/java/org/apache/cassandra/db/CollationController.java
index 061537b..c9cbf69 100644
--- a/src/java/org/apache/cassandra/db/CollationController.java
+++ b/src/java/org/apache/cassandra/db/CollationController.java
@@ -28,6 +28,7 @@ import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.cassandra.db.columniterator.OnDiskAtomIterator;
import org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy;
import org.apache.cassandra.db.composites.CellName;
@@ -67,6 +68,7 @@ public class CollationController
* Once we have data for all requests columns that is newer than the newest remaining maxtimestamp,
* we stop.
*/
+ @Inline
private ColumnFamily collectTimeOrderedData(boolean copyOnHeap)
{
final ColumnFamily container = ArrayBackedSortedColumns.factory.create(cfs.metadata, filter.filter.isReversed());
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/ConsistencyLevel.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ConsistencyLevel.java b/src/java/org/apache/cassandra/db/ConsistencyLevel.java
index 7583a90..986a2aa 100644
--- a/src/java/org/apache/cassandra/db/ConsistencyLevel.java
+++ b/src/java/org/apache/cassandra/db/ConsistencyLevel.java
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import com.google.common.collect.Iterables;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -244,6 +245,7 @@ public enum ConsistencyLevel
}
}
+ @Inline
public void assureSufficientLiveNodes(Keyspace keyspace, Iterable<InetAddress> liveEndpoints) throws UnavailableException
{
int blockFor = blockFor(keyspace);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/DecoratedKey.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/DecoratedKey.java b/src/java/org/apache/cassandra/db/DecoratedKey.java
index fb3d7ab..604cbb7 100644
--- a/src/java/org/apache/cassandra/db/DecoratedKey.java
+++ b/src/java/org/apache/cassandra/db/DecoratedKey.java
@@ -20,10 +20,13 @@ package org.apache.cassandra.db;
import java.nio.ByteBuffer;
import java.util.Comparator;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.FastByteOperations;
+import org.apache.cassandra.utils.memory.MemoryUtil;
/**
* Represents a decorated key, handy for certain operations
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/NativeDecoratedKey.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/NativeDecoratedKey.java b/src/java/org/apache/cassandra/db/NativeDecoratedKey.java
index 52aa50c..79dc53f 100644
--- a/src/java/org/apache/cassandra/db/NativeDecoratedKey.java
+++ b/src/java/org/apache/cassandra/db/NativeDecoratedKey.java
@@ -20,13 +20,14 @@ package org.apache.cassandra.db;
import java.nio.ByteBuffer;
import org.apache.cassandra.dht.Token;
+import org.apache.cassandra.utils.FastByteOperations;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.MemoryUtil;
import org.apache.cassandra.utils.memory.NativeAllocator;
public class NativeDecoratedKey extends DecoratedKey
{
- private final long peer;
+ final long peer;
public NativeDecoratedKey(Token token, NativeAllocator allocator, OpOrder.Group writeOp, ByteBuffer key)
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/AbstractCType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/AbstractCType.java b/src/java/org/apache/cassandra/db/composites/AbstractCType.java
index e299e42..491a9d1 100644
--- a/src/java/org/apache/cassandra/db/composites/AbstractCType.java
+++ b/src/java/org/apache/cassandra/db/composites/AbstractCType.java
@@ -22,7 +22,9 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Comparator;
+import org.apache.cassandra.db.Cell;
import org.apache.cassandra.db.DeletionInfo;
+import org.apache.cassandra.db.NativeCell;
import org.apache.cassandra.db.RangeTombstone;
import org.apache.cassandra.db.RowIndexEntry;
import org.apache.cassandra.db.TypeSizes;
@@ -39,6 +41,39 @@ import static org.apache.cassandra.io.sstable.IndexHelper.IndexInfo;
public abstract class AbstractCType implements CType
{
+ static final Comparator<Cell> rightNativeCell = new Comparator<Cell>()
+ {
+ public int compare(Cell o1, Cell o2)
+ {
+ return -((NativeCell) o2).compareTo(o1.name());
+ }
+ };
+
+ static final Comparator<Cell> neitherNativeCell = new Comparator<Cell>()
+ {
+ public int compare(Cell o1, Cell o2)
+ {
+ return compareUnsigned(o1.name(), o2.name());
+ }
+ };
+
+ // only one or the other of these will ever be used
+ static final Comparator<Object> asymmetricRightNativeCell = new Comparator<Object>()
+ {
+ public int compare(Object o1, Object o2)
+ {
+ return -((NativeCell) o2).compareTo((Composite) o1);
+ }
+ };
+
+ static final Comparator<Object> asymmetricNeitherNativeCell = new Comparator<Object>()
+ {
+ public int compare(Object o1, Object o2)
+ {
+ return compareUnsigned((Composite) o1, ((Cell) o2).name());
+ }
+ };
+
private final Comparator<Composite> reverseComparator;
private final Comparator<IndexInfo> indexComparator;
private final Comparator<IndexInfo> indexReverseComparator;
@@ -60,11 +95,6 @@ public abstract class AbstractCType implements CType
{
public int compare(Composite c1, Composite c2)
{
- if (c1.isEmpty())
- return c2.isEmpty() ? 0 : -1;
- if (c2.isEmpty())
- return 1;
-
return AbstractCType.this.compare(c2, c1);
}
};
@@ -102,30 +132,37 @@ public abstract class AbstractCType implements CType
return isByteOrderComparable;
}
- public int compare(Composite c1, Composite c2)
+ static int compareUnsigned(Composite c1, Composite c2)
{
int s1 = c1.size();
int s2 = c2.size();
int minSize = Math.min(s1, s2);
- if (isByteOrderComparable)
+ for (int i = 0; i < minSize; i++)
{
- for (int i = 0; i < minSize; i++)
- {
- int cmp = ByteBufferUtil.compareUnsigned(c1.get(i), c2.get(i));
- if (cmp != 0)
- return cmp;
- }
+ int cmp = ByteBufferUtil.compareUnsigned(c1.get(i), c2.get(i));
+ if (cmp != 0)
+ return cmp;
}
- else
+
+ if (s1 == s2)
+ return c1.eoc().compareTo(c2.eoc());
+ return s1 < s2 ? c1.eoc().prefixComparisonResult : -c2.eoc().prefixComparisonResult;
+ }
+
+ public int compare(Composite c1, Composite c2)
+ {
+ int s1 = c1.size();
+ int s2 = c2.size();
+ int minSize = Math.min(s1, s2);
+
+ for (int i = 0; i < minSize; i++)
{
- for (int i = 0; i < minSize; i++)
- {
- AbstractType<?> comparator = subtype(i);
- int cmp = comparator.compare(c1.get(i), c2.get(i));
- if (cmp != 0)
- return cmp;
- }
+ int cmp = isByteOrderComparable
+ ? ByteBufferUtil.compareUnsigned(c1.get(i), c2.get(i))
+ : subtype(i).compare(c1.get(i), c2.get(i));
+ if (cmp != 0)
+ return cmp;
}
if (s1 == s2)
@@ -133,6 +170,20 @@ public abstract class AbstractCType implements CType
return s1 < s2 ? c1.eoc().prefixComparisonResult : -c2.eoc().prefixComparisonResult;
}
+ protected Comparator<Cell> getByteOrderColumnComparator(boolean isRightNative)
+ {
+ if (isRightNative)
+ return rightNativeCell;
+ return neitherNativeCell;
+ }
+
+ protected Comparator<Object> getByteOrderAsymmetricColumnComparator(boolean isRightNative)
+ {
+ if (isRightNative)
+ return asymmetricRightNativeCell;
+ return asymmetricNeitherNativeCell;
+ }
+
public void validate(Composite name)
{
ByteBuffer previous = null;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java b/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
index 56be8cf..7570d2c 100644
--- a/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
@@ -40,8 +40,9 @@ import org.apache.cassandra.utils.ByteBufferUtil;
public abstract class AbstractCellNameType extends AbstractCType implements CellNameType
{
- private final Comparator<Cell> columnComparator;
+ final Comparator<Cell> columnComparator;
private final Comparator<Cell> columnReverseComparator;
+ final Comparator<Object> asymmetricComparator;
private final Comparator<OnDiskAtom> onDiskAtomComparator;
private final ISerializer<CellName> cellSerializer;
@@ -60,6 +61,13 @@ public abstract class AbstractCellNameType extends AbstractCType implements Cell
return AbstractCellNameType.this.compare(c1.name(), c2.name());
}
};
+ asymmetricComparator = new Comparator<Object>()
+ {
+ public int compare(Object c1, Object c2)
+ {
+ return AbstractCellNameType.this.compare((Composite) c1, ((Cell) c2).name());
+ }
+ };
columnReverseComparator = new Comparator<Cell>()
{
public int compare(Cell c1, Cell c2)
@@ -125,9 +133,18 @@ public abstract class AbstractCellNameType extends AbstractCType implements Cell
diskAtomFilterSerializer = new IDiskAtomFilter.Serializer(this);
}
- public Comparator<Cell> columnComparator()
+ public final Comparator<Cell> columnComparator(boolean isRightNative)
+ {
+ if (!isByteOrderComparable)
+ return columnComparator;
+ return getByteOrderColumnComparator(isRightNative);
+ }
+
+ public final Comparator<Object> asymmetricColumnComparator(boolean isRightNative)
{
- return columnComparator;
+ if (!isByteOrderComparable)
+ return asymmetricComparator;
+ return getByteOrderAsymmetricColumnComparator(isRightNative);
}
public Comparator<Cell> columnReverseComparator()
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/AbstractCompoundCellNameType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/AbstractCompoundCellNameType.java b/src/java/org/apache/cassandra/db/composites/AbstractCompoundCellNameType.java
index 641f14d..b748212 100644
--- a/src/java/org/apache/cassandra/db/composites/AbstractCompoundCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/AbstractCompoundCellNameType.java
@@ -20,7 +20,9 @@ package org.apache.cassandra.db.composites;
import java.io.DataInput;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.Comparator;
+import org.apache.cassandra.db.Cell;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CompositeType;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/AbstractSimpleCellNameType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/AbstractSimpleCellNameType.java b/src/java/org/apache/cassandra/db/composites/AbstractSimpleCellNameType.java
index 95386fd..f9c9641 100644
--- a/src/java/org/apache/cassandra/db/composites/AbstractSimpleCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/AbstractSimpleCellNameType.java
@@ -20,7 +20,11 @@ package org.apache.cassandra.db.composites;
import java.io.DataInput;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.Comparator;
+import net.nicoulaj.compilecommand.annotations.Inline;
+import org.apache.cassandra.db.Cell;
+import org.apache.cassandra.db.NativeCell;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.utils.ByteBufferUtil;
@@ -28,6 +32,39 @@ public abstract class AbstractSimpleCellNameType extends AbstractCellNameType
{
protected final AbstractType<?> type;
+ static final Comparator<Cell> rightNativeCell = new Comparator<Cell>()
+ {
+ public int compare(Cell o1, Cell o2)
+ {
+ return -((NativeCell) o2).compareToSimple(o1.name());
+ }
+ };
+
+ static final Comparator<Cell> neitherNativeCell = new Comparator<Cell>()
+ {
+ public int compare(Cell o1, Cell o2)
+ {
+ return compareUnsigned(o1.name(), o2.name());
+ }
+ };
+
+ // only one or the other of these will ever be used
+ static final Comparator<Object> asymmetricRightNativeCell = new Comparator<Object>()
+ {
+ public int compare(Object o1, Object o2)
+ {
+ return -((NativeCell) o2).compareToSimple((Composite) o1);
+ }
+ };
+
+ static final Comparator<Object> asymmetricNeitherNativeCell = new Comparator<Object>()
+ {
+ public int compare(Object o1, Object o2)
+ {
+ return compareUnsigned((Composite) o1, ((Cell) o2).name());
+ }
+ };
+
protected AbstractSimpleCellNameType(AbstractType<?> type)
{
super(type.isByteOrderComparable());
@@ -44,31 +81,38 @@ public abstract class AbstractSimpleCellNameType extends AbstractCellNameType
return 1;
}
- public int compare(Composite c1, Composite c2)
+ @Inline
+ static int compareUnsigned(Composite c1, Composite c2)
{
- // This method assumes that simple composites never have an EOC != NONE. This assumption
- // stands in particular on the fact that a Composites.EMPTY never has a non-NONE EOC. If
- // this ever change, we'll need to update this.
+ ByteBuffer b1 = c1.toByteBuffer();
+ ByteBuffer b2 = c2.toByteBuffer();
+ assert b1.hasRemaining() & b2.hasRemaining();
+ return ByteBufferUtil.compareUnsigned(b1, b2);
+ }
+ public int compare(Composite c1, Composite c2)
+ {
if (isByteOrderComparable)
- {
- // toByteBuffer is always cheap for simple types, and we keep virtual method calls to a minimum:
- // hasRemaining will always be inlined, as will most of the call-stack for BBU.compareUnsigned
- ByteBuffer b1 = c1.toByteBuffer();
- ByteBuffer b2 = c2.toByteBuffer();
- if (!b1.hasRemaining() || !b2.hasRemaining())
- return b1.hasRemaining() ? 1 : (b2.hasRemaining() ? -1 : 0);
- return ByteBufferUtil.compareUnsigned(b1, b2);
- }
-
- boolean c1isEmpty = c1.isEmpty();
- boolean c2isEmpty = c2.isEmpty();
- if (c1isEmpty || c2isEmpty)
- return !c1isEmpty ? 1 : (!c2isEmpty ? -1 : 0);
+ return compareUnsigned(c1, c2);
+ assert !(c1.isEmpty() | c2.isEmpty());
return type.compare(c1.get(0), c2.get(0));
}
+ protected Comparator<Cell> getByteOrderColumnComparator(boolean isRightNative)
+ {
+ if (isRightNative)
+ return rightNativeCell;
+ return neitherNativeCell;
+ }
+
+ protected Comparator<Object> getByteOrderAsymmetricColumnComparator(boolean isRightNative)
+ {
+ if (isRightNative)
+ return asymmetricRightNativeCell;
+ return asymmetricNeitherNativeCell;
+ }
+
public AbstractType<?> subtype(int i)
{
if (i != 0)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/CType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/CType.java b/src/java/org/apache/cassandra/db/composites/CType.java
index c2516f5..280f7af 100644
--- a/src/java/org/apache/cassandra/db/composites/CType.java
+++ b/src/java/org/apache/cassandra/db/composites/CType.java
@@ -55,6 +55,8 @@ public interface CType extends Comparator<Composite>
*/
public int size();
+ int compare(Composite o1, Composite o2);
+
/**
* Gets a subtype of this CType.
*/
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/CellNameType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/CellNameType.java b/src/java/org/apache/cassandra/db/composites/CellNameType.java
index acc0527..4f45d41 100644
--- a/src/java/org/apache/cassandra/db/composites/CellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/CellNameType.java
@@ -174,7 +174,8 @@ public interface CellNameType extends CType
// Ultimately, those might be split into an IVersionedSerializer and an ISSTableSerializer
public ISerializer<CellName> cellSerializer();
- public Comparator<Cell> columnComparator();
+ public Comparator<Cell> columnComparator(boolean isRightNative);
+ public Comparator<Object> asymmetricColumnComparator(boolean isRightNative);
public Comparator<Cell> columnReverseComparator();
public Comparator<OnDiskAtom> onDiskAtomComparator();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/Composites.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/Composites.java b/src/java/org/apache/cassandra/db/composites/Composites.java
index 154e9f7..f6626e0 100644
--- a/src/java/org/apache/cassandra/db/composites/Composites.java
+++ b/src/java/org/apache/cassandra/db/composites/Composites.java
@@ -57,7 +57,10 @@ public abstract class Composites
public ByteBuffer get(int i)
{
- throw new IndexOutOfBoundsException();
+ if (i > 0)
+ throw new IndexOutOfBoundsException();
+
+ return ByteBufferUtil.EMPTY_BYTE_BUFFER;
}
public EOC eoc()
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java b/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
index 29e1617..57eb5fd 100644
--- a/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
@@ -41,7 +41,6 @@ public class CompoundSparseCellNameType extends AbstractCompoundCellNameType
protected final Map<ByteBuffer, ColumnIdentifier> internedIds;
private final Composite staticPrefix;
- private final boolean isByteOrderComparable;
public CompoundSparseCellNameType(List<AbstractType<?>> types)
{
@@ -64,7 +63,6 @@ public class CompoundSparseCellNameType extends AbstractCompoundCellNameType
this.columnNameType = columnNameType;
this.internedIds = internedIds;
this.staticPrefix = makeStaticPrefix(clusteringType.size());
- this.isByteOrderComparable = isByteOrderComparable(fullType.types);
}
private static Composite makeStaticPrefix(int size)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/SimpleCType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/SimpleCType.java b/src/java/org/apache/cassandra/db/composites/SimpleCType.java
index 229d538..c824179 100644
--- a/src/java/org/apache/cassandra/db/composites/SimpleCType.java
+++ b/src/java/org/apache/cassandra/db/composites/SimpleCType.java
@@ -18,6 +18,7 @@
package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
+import java.util.Comparator;
import java.util.List;
import org.apache.cassandra.db.marshal.AbstractType;
@@ -48,26 +49,13 @@ public class SimpleCType extends AbstractCType
public int compare(Composite c1, Composite c2)
{
+ if (isByteOrderComparable)
+ return AbstractSimpleCellNameType.compareUnsigned(c1, c2);
+
+ assert !(c1.isEmpty() | c2.isEmpty());
// This method assumes that simple composites never have an EOC != NONE. This assumption
// stands in particular on the fact that a Composites.EMPTY never has a non-NONE EOC. If
// this ever change, we'll need to update this.
-
- if (isByteOrderComparable)
- {
- // toByteBuffer is always cheap for simple types, and we keep virtual method calls to a minimum:
- // hasRemaining will always be inlined, as will most of the call-stack for BBU.compareUnsigned
- ByteBuffer b1 = c1.toByteBuffer();
- ByteBuffer b2 = c2.toByteBuffer();
- if (!b1.hasRemaining() || !b2.hasRemaining())
- return b1.hasRemaining() ? 1 : (b2.hasRemaining() ? -1 : 0);
- return ByteBufferUtil.compareUnsigned(b1, b2);
- }
-
- boolean c1isEmpty = c1.isEmpty();
- boolean c2isEmpty = c2.isEmpty();
- if (c1isEmpty || c2isEmpty)
- return !c1isEmpty ? 1 : (!c2isEmpty ? -1 : 0);
-
return type.compare(c1.get(0), c2.get(0));
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/filter/ColumnSlice.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/filter/ColumnSlice.java b/src/java/org/apache/cassandra/db/filter/ColumnSlice.java
index bca4743..7d470b3 100644
--- a/src/java/org/apache/cassandra/db/filter/ColumnSlice.java
+++ b/src/java/org/apache/cassandra/db/filter/ColumnSlice.java
@@ -55,7 +55,7 @@ public class ColumnSlice
public boolean includes(Comparator<Composite> cmp, Composite name)
{
- return cmp.compare(start, name) <= 0 && (finish.isEmpty() || cmp.compare(finish, name) >= 0);
+ return (start.isEmpty() || cmp.compare(start, name) <= 0) && (finish.isEmpty() || cmp.compare(finish, name) >= 0);
}
public boolean isBefore(Comparator<Composite> cmp, Composite name)
@@ -114,26 +114,32 @@ public class ColumnSlice
* Validates that the provided slice array contains only non-overlapped slices valid for a query {@code reversed}
* or not on a table using {@code comparator}.
*/
- public static boolean validateSlices(ColumnSlice[] slices, CellNameType comparator, boolean reversed)
+ public static boolean validateSlices(ColumnSlice[] slices, CellNameType type, boolean reversed)
{
- return validateSlices(slices, reversed ? comparator.reverseComparator() : comparator);
- }
+ Comparator<Composite> comparator = reversed ? type.reverseComparator() : type;
- /**
- * Validates that the provided slice array contains only non-overlapped slices in {@code comparator} order.
- */
- public static boolean validateSlices(ColumnSlice[] slices, Comparator<Composite> comparator)
- {
for (int i = 0; i < slices.length; i++)
{
- if (i > 0 && comparator.compare(slices[i-1].finish, slices[i].start) >= 0)
- return false;
+ Composite start = slices[i].start;
+ Composite finish = slices[i].finish;
- if (slices[i].finish.isEmpty())
- return i == slices.length - 1;
+ if (start.isEmpty() || finish.isEmpty())
+ {
+ if (start.isEmpty() && i > 0)
+ return false;
- if (comparator.compare(slices[i].start, slices[i].finish) > 0)
- return false;
+ if (finish.isEmpty())
+ return i == slices.length - 1;
+ }
+ else
+ {
+ // !finish.isEmpty() is imposed by prior loop
+ if (i > 0 && comparator.compare(slices[i - 1].finish, start) >= 0)
+ return false;
+
+ if (comparator.compare(start, finish) > 0)
+ return false;
+ }
}
return true;
}
@@ -159,13 +165,21 @@ public class ColumnSlice
@Override
public int compare(ColumnSlice s1, ColumnSlice s2)
{
- int c = comparator.compare(s1.start, s2.start);
- if (c != 0)
- return c;
+ if (s1.start.isEmpty() || s2.start.isEmpty())
+ {
+ if (s1.start.isEmpty() != s2.start.isEmpty())
+ return s1.start.isEmpty() ? -1 : 1;
+ }
+ else
+ {
+ int c = comparator.compare(s1.start, s2.start);
+ if (c != 0)
+ return c;
+ }
// For the finish, empty always means greater
return s1.finish.isEmpty() || s2.finish.isEmpty()
- ? s1.finish.isEmpty() ? 1 : s2.finish.isEmpty() ? -1 : 0
+ ? (s1.finish.isEmpty() ? 1 : -1)
: comparator.compare(s1.finish, s2.finish);
}
});
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java b/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
index 0e0643f..77a5dc7 100644
--- a/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
@@ -103,7 +103,7 @@ public class NamesQueryFilter implements IDiskAtomFilter
public Comparator<Cell> getColumnComparator(CellNameType comparator)
{
- return comparator.columnComparator();
+ return comparator.columnComparator(false);
}
@Override
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java b/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
index e24f68b..b8c3e2f 100644
--- a/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
@@ -186,7 +186,7 @@ public class SliceQueryFilter implements IDiskAtomFilter
public Comparator<Cell> getColumnComparator(CellNameType comparator)
{
- return reversed ? comparator.columnReverseComparator() : comparator.columnComparator();
+ return reversed ? comparator.columnReverseComparator() : comparator.columnComparator(false);
}
public void collectReducedColumns(ColumnFamily container, Iterator<Cell> reducedColumns, int gcBefore, long now)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/io/sstable/IndexHelper.java b/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
index 7099a15..b0bbfc4 100644
--- a/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
+++ b/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
@@ -111,8 +111,8 @@ public class IndexHelper
*/
public static int indexFor(Composite name, List<IndexInfo> indexList, CType comparator, boolean reversed, int lastIndex)
{
- if (name.isEmpty() && reversed)
- return indexList.size() - 1;
+ if (name.isEmpty())
+ return lastIndex >= 0 ? lastIndex : reversed ? indexList.size() - 1 : 0;
if (lastIndex >= indexList.size())
return -1;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/io/util/Memory.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/io/util/Memory.java b/src/java/org/apache/cassandra/io/util/Memory.java
index 67dee81..5306433 100644
--- a/src/java/org/apache/cassandra/io/util/Memory.java
+++ b/src/java/org/apache/cassandra/io/util/Memory.java
@@ -22,6 +22,7 @@ import java.nio.ByteOrder;
import com.sun.jna.Native;
import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.utils.FastByteOperations;
import org.apache.cassandra.utils.memory.MemoryUtil;
import sun.misc.Unsafe;
import sun.nio.ch.DirectBuffer;
@@ -273,7 +274,7 @@ public class Memory
long end = memoryOffset + count;
checkPosition(end - 1);
- unsafe.copyMemory(null, peer + memoryOffset, buffer, BYTE_ARRAY_BASE_OFFSET + bufferOffset, count);
+ FastByteOperations.UnsafeOperations.copy(null, peer + memoryOffset, buffer, bufferOffset, count);
}
private void checkPosition(long offset)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/service/StorageProxy.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/StorageProxy.java b/src/java/org/apache/cassandra/service/StorageProxy.java
index 988c623..8d20af4 100644
--- a/src/java/org/apache/cassandra/service/StorageProxy.java
+++ b/src/java/org/apache/cassandra/service/StorageProxy.java
@@ -31,6 +31,7 @@ import com.google.common.base.Predicate;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.*;
import com.google.common.util.concurrent.Uninterruptibles;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -1142,6 +1143,7 @@ public class StorageProxy implements StorageProxyMBean
* Performs the actual reading of a row out of the StorageService, fetching
* a specific set of column names from a given column family.
*/
+ @Inline
public static List<Row> read(List<ReadCommand> commands, ConsistencyLevel consistency_level)
throws UnavailableException, IsBootstrappingException, ReadTimeoutException, InvalidRequestException
{
@@ -1220,6 +1222,7 @@ public class StorageProxy implements StorageProxyMBean
* 4. If the digests (if any) match the data return the data
* 5. else carry out read repair by getting data from all the nodes.
*/
+ @Inline
private static List<Row> fetchRows(List<ReadCommand> initialCommands, ConsistencyLevel consistencyLevel)
throws UnavailableException, ReadTimeoutException
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/thrift/CassandraServer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/thrift/CassandraServer.java b/src/java/org/apache/cassandra/thrift/CassandraServer.java
index 86b5bee..0621db9 100644
--- a/src/java/org/apache/cassandra/thrift/CassandraServer.java
+++ b/src/java/org/apache/cassandra/thrift/CassandraServer.java
@@ -404,7 +404,7 @@ public class CassandraServer implements Cassandra.Iface
if (metadata.isSuper())
{
CellNameType columnType = new SimpleDenseCellNameType(metadata.comparator.subtype(parent.isSetSuper_column() ? 1 : 0));
- SortedSet<CellName> s = new TreeSet<CellName>(columnType);
+ SortedSet<CellName> s = new TreeSet<>(columnType);
for (ByteBuffer bb : predicate.column_names)
s.add(columnType.cellFromByteBuffer(bb));
filter = SuperColumns.fromSCNamesFilter(metadata.comparator, parent.bufferForSuper_column(), new NamesQueryFilter(s));
@@ -2071,11 +2071,14 @@ public class CassandraServer implements Cassandra.Iface
fixOptionalSliceParameters(request.getColumn_slices().get(i));
Composite start = metadata.comparator.fromByteBuffer(request.getColumn_slices().get(i).start);
Composite finish = metadata.comparator.fromByteBuffer(request.getColumn_slices().get(i).finish);
- int compare = metadata.comparator.compare(start, finish);
- if (!request.reversed && compare > 0)
- throw new InvalidRequestException(String.format("Column slice at index %d had start greater than finish", i));
- else if (request.reversed && compare < 0)
- throw new InvalidRequestException(String.format("Reversed column slice at index %d had start less than finish", i));
+ if (!start.isEmpty() && !finish.isEmpty())
+ {
+ int compare = metadata.comparator.compare(start, finish);
+ if (!request.reversed && compare > 0)
+ throw new InvalidRequestException(String.format("Column slice at index %d had start greater than finish", i));
+ else if (request.reversed && compare < 0)
+ throw new InvalidRequestException(String.format("Reversed column slice at index %d had start less than finish", i));
+ }
slices[i] = new ColumnSlice(start, finish);
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/ByteBufferUtil.java b/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
index 420a776..62addfa 100644
--- a/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
+++ b/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
@@ -32,6 +32,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.UUID;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.io.util.FileDataInput;
import org.apache.cassandra.io.util.FileUtils;
@@ -78,16 +79,19 @@ public class ByteBufferUtil
{
public static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.wrap(new byte[0]);
+ @Inline
public static int compareUnsigned(ByteBuffer o1, ByteBuffer o2)
{
return FastByteOperations.compareUnsigned(o1, o2);
}
+ @Inline
public static int compare(byte[] o1, ByteBuffer o2)
{
return FastByteOperations.compareUnsigned(o1, 0, o1.length, o2);
}
+ @Inline
public static int compare(ByteBuffer o1, byte[] o2)
{
return FastByteOperations.compareUnsigned(o1, o2, 0, o2.length);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/utils/FastByteOperations.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/FastByteOperations.java b/src/java/org/apache/cassandra/utils/FastByteOperations.java
index e60b096..1431fd3 100644
--- a/src/java/org/apache/cassandra/utils/FastByteOperations.java
+++ b/src/java/org/apache/cassandra/utils/FastByteOperations.java
@@ -24,9 +24,9 @@ import java.nio.ByteOrder;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import com.google.common.primitives.Longs;
-import com.google.common.primitives.UnsignedBytes;
+import com.google.common.primitives.*;
+import net.nicoulaj.compilecommand.annotations.Inline;
import sun.misc.Unsafe;
/**
@@ -34,39 +34,43 @@ import sun.misc.Unsafe;
* This is borrowed and slightly modified from Guava's {@link UnsignedBytes}
* class to be able to compare arrays that start at non-zero offsets.
*/
-class FastByteOperations
+public class FastByteOperations
{
/**
* Lexicographically compare two byte arrays.
*/
+ @Inline
public static int compareUnsigned(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2)
{
return BestHolder.BEST.compare(b1, s1, l1, b2, s2, l2);
}
+ @Inline
public static int compareUnsigned(ByteBuffer b1, byte[] b2, int s2, int l2)
{
return BestHolder.BEST.compare(b1, b2, s2, l2);
}
+ @Inline
public static int compareUnsigned(byte[] b1, int s1, int l1, ByteBuffer b2)
{
return -BestHolder.BEST.compare(b2, b1, s1, l1);
}
+ @Inline
public static int compareUnsigned(ByteBuffer b1, ByteBuffer b2)
{
- if (b1 == b2)
- return 0;
return BestHolder.BEST.compare(b1, b2);
}
+ @Inline
public static void copy(ByteBuffer src, int srcPosition, byte[] trg, int trgPosition, int length)
{
BestHolder.BEST.copy(src, srcPosition, trg, trgPosition, length);
}
+ @Inline
public static void copy(ByteBuffer src, int srcPosition, ByteBuffer trg, int trgPosition, int length)
{
BestHolder.BEST.copy(src, srcPosition, trg, trgPosition, length);
@@ -180,122 +184,97 @@ class FastByteOperations
}
}
- static final boolean littleEndian =
- ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
-
- /**
- * Returns true if x1 is less than x2, when both values are treated as
- * unsigned.
- */
- static boolean lessThanUnsigned(long x1, long x2)
- {
- return (x1 + Long.MIN_VALUE) < (x2 + Long.MIN_VALUE);
- }
+ static final boolean BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN);
public int compare(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2)
{
- return compareTo(buffer1, BYTE_ARRAY_BASE_OFFSET + offset1, length1, buffer2, BYTE_ARRAY_BASE_OFFSET + offset2, length2);
+ return compareTo(buffer1, BYTE_ARRAY_BASE_OFFSET + offset1, length1,
+ buffer2, BYTE_ARRAY_BASE_OFFSET + offset2, length2);
}
public int compare(ByteBuffer buffer1, byte[] buffer2, int offset2, int length2)
{
- final Object obj1;
- final long offset1;
- final int length1;
+ Object obj1;
+ long offset1;
if (buffer1.hasArray())
{
obj1 = buffer1.array();
- offset1 = BYTE_ARRAY_BASE_OFFSET + buffer1.arrayOffset() + buffer1.position();
- length1 = buffer1.remaining();
+ offset1 = BYTE_ARRAY_BASE_OFFSET + buffer1.arrayOffset();
}
else
{
obj1 = null;
- offset1 = theUnsafe.getLong(buffer1, DIRECT_BUFFER_ADDRESS_OFFSET) + buffer1.position();
- length1 = buffer1.remaining();
+ offset1 = theUnsafe.getLong(buffer1, DIRECT_BUFFER_ADDRESS_OFFSET);
+ }
+ int length1;
+ {
+ int position = buffer1.position();
+ int limit = buffer1.limit();
+ length1 = limit - position;
+ offset1 += position;
}
return compareTo(obj1, offset1, length1, buffer2, BYTE_ARRAY_BASE_OFFSET + offset2, length2);
}
public int compare(ByteBuffer buffer1, ByteBuffer buffer2)
{
- final Object obj1, obj2;
- final long offset1, offset2;
- final int length1, length2;
- if (buffer1.hasArray())
- {
- obj1 = buffer1.array();
- offset1 = BYTE_ARRAY_BASE_OFFSET + buffer1.arrayOffset() + buffer1.position();
- length1 = buffer1.remaining();
- }
- else
- {
- obj1 = null;
- offset1 = theUnsafe.getLong(buffer1, DIRECT_BUFFER_ADDRESS_OFFSET) + buffer1.position();
- length1 = buffer1.remaining();
- }
- if (buffer2.hasArray())
- {
- obj2 = buffer2.array();
- offset2 = BYTE_ARRAY_BASE_OFFSET + buffer2.arrayOffset() + buffer2.position();
- length2 = buffer2.remaining();
- }
- else
- {
- obj2 = null;
- offset2 = theUnsafe.getLong(buffer2, DIRECT_BUFFER_ADDRESS_OFFSET) + buffer2.position();
- length2 = buffer2.remaining();
- }
- return compareTo(obj1, offset1, length1, obj2, offset2, length2);
+ return compareTo(buffer1, buffer2);
}
public void copy(ByteBuffer src, int srcPosition, byte[] trg, int trgPosition, int length)
{
if (src.hasArray())
- {
System.arraycopy(src.array(), src.arrayOffset() + srcPosition, trg, trgPosition, length);
- return;
- }
- long srcOffset = srcPosition + theUnsafe.getLong(src, DIRECT_BUFFER_ADDRESS_OFFSET);
- copy(null, srcOffset, trg, BYTE_ARRAY_BASE_OFFSET + trgPosition, length);
+ else
+ copy(null, srcPosition + theUnsafe.getLong(src, DIRECT_BUFFER_ADDRESS_OFFSET), trg, trgPosition, length);
}
public void copy(ByteBuffer srcBuf, int srcPosition, ByteBuffer trgBuf, int trgPosition, int length)
{
- if (srcBuf.hasArray() && trgBuf.hasArray())
+ Object src;
+ long srcOffset;
+ if (srcBuf.hasArray())
{
- System.arraycopy(srcBuf.array(), srcBuf.arrayOffset() + srcPosition, trgBuf.array(), trgBuf.arrayOffset() + trgPosition, length);
- return;
+ src = srcBuf.array();
+ srcOffset = BYTE_ARRAY_BASE_OFFSET + srcBuf.arrayOffset();
}
- Object src, trg;
- long srcOffset, trgOffset;
- if (srcBuf.isDirect())
+ else
{
- srcOffset = srcPosition + theUnsafe.getLong(srcBuf, DIRECT_BUFFER_ADDRESS_OFFSET);
src = null;
+ srcOffset = theUnsafe.getLong(srcBuf, DIRECT_BUFFER_ADDRESS_OFFSET);
}
+ copy(src, srcOffset + srcPosition, trgBuf, trgPosition, length);
+ }
+
+ @Inline
+ public static void copy(Object src, long srcOffset, ByteBuffer trgBuf, int trgPosition, int length)
+ {
+ if (trgBuf.hasArray())
+ copy(src, srcOffset, trgBuf.array(), trgBuf.arrayOffset() + trgPosition, length);
else
+ copy(src, srcOffset, null, trgPosition + theUnsafe.getLong(trgBuf, DIRECT_BUFFER_ADDRESS_OFFSET), length);
+ }
+
+ @Inline
+ public static void copy(Object src, long srcOffset, byte[] trg, int trgPosition, int length)
+ {
+ if (length <= MIN_COPY_THRESHOLD)
{
- src = srcBuf.array();
- srcOffset = BYTE_ARRAY_BASE_OFFSET + srcBuf.arrayOffset() + srcPosition;
- }
- if (trgBuf.isDirect())
- {
- trgOffset = trgPosition + theUnsafe.getLong(trgBuf, DIRECT_BUFFER_ADDRESS_OFFSET);
- trg = null;
+ for (int i = 0 ; i < length ; i++)
+ trg[trgPosition + i] = theUnsafe.getByte(src, srcOffset + i);
}
else
{
- trg = trgBuf.array();
- trgOffset = BYTE_ARRAY_BASE_OFFSET + trgBuf.arrayOffset() + trgPosition;
+ copy(src, srcOffset, trg, BYTE_ARRAY_BASE_OFFSET + trgPosition, length);
}
- copy(src, srcOffset, trg, trgOffset, length);
}
// 1M, copied from java.nio.Bits (unfortunately a package-private class)
private static final long UNSAFE_COPY_THRESHOLD = 1 << 20;
+ private static final long MIN_COPY_THRESHOLD = 6;
- static void copy(Object src, long srcOffset, Object dst, long dstOffset, long length)
+ @Inline
+ public static void copy(Object src, long srcOffset, Object dst, long dstOffset, long length)
{
while (length > 0) {
long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
@@ -307,6 +286,50 @@ class FastByteOperations
}
}
+ @Inline
+ public static int compareTo(ByteBuffer buffer1, ByteBuffer buffer2)
+ {
+ Object obj1;
+ long offset1;
+ int length1;
+ if (buffer1.hasArray())
+ {
+ obj1 = buffer1.array();
+ offset1 = BYTE_ARRAY_BASE_OFFSET + buffer1.arrayOffset();
+ }
+ else
+ {
+ obj1 = null;
+ offset1 = theUnsafe.getLong(buffer1, DIRECT_BUFFER_ADDRESS_OFFSET);
+ }
+ offset1 += buffer1.position();
+ length1 = buffer1.remaining();
+ return compareTo(obj1, offset1, length1, buffer2);
+ }
+
+ @Inline
+ public static int compareTo(Object buffer1, long offset1, int length1, ByteBuffer buffer)
+ {
+ Object obj2;
+ long offset2;
+
+ int position = buffer.position();
+ int limit = buffer.limit();
+ if (buffer.hasArray())
+ {
+ obj2 = buffer.array();
+ offset2 = BYTE_ARRAY_BASE_OFFSET + buffer.arrayOffset();
+ }
+ else
+ {
+ obj2 = null;
+ offset2 = theUnsafe.getLong(buffer, DIRECT_BUFFER_ADDRESS_OFFSET);
+ }
+ int length2 = limit - position;
+ offset2 += position;
+
+ return compareTo(buffer1, offset1, length1, obj2, offset2, length2);
+ }
/**
* Lexicographically compare two arrays.
@@ -319,65 +342,40 @@ class FastByteOperations
* @param length2 How much to compare from the right buffer
* @return 0 if equal, < 0 if left is less than right, etc.
*/
- public int compareTo(Object buffer1, long memoryOffset1, int length1,
+ @Inline
+ public static int compareTo(Object buffer1, long memoryOffset1, int length1,
Object buffer2, long memoryOffset2, int length2)
{
- // Short circuit equal case
- if (buffer1 == buffer2 && memoryOffset1 == memoryOffset2 && length1 == length2)
- return 0;
-
int minLength = Math.min(length1, length2);
- int minWords = minLength / Longs.BYTES;
/*
* Compare 8 bytes at a time. Benchmarking shows comparing 8 bytes at a
* time is no slower than comparing 4 bytes at a time even on 32-bit.
* On the other hand, it is substantially faster on 64-bit.
*/
-
- int wordComparisons = minWords * Longs.BYTES;
+ int wordComparisons = minLength & ~7;
for (int i = 0; i < wordComparisons ; i += Longs.BYTES)
{
long lw = theUnsafe.getLong(buffer1, memoryOffset1 + (long) i);
long rw = theUnsafe.getLong(buffer2, memoryOffset2 + (long) i);
- long diff = lw ^ rw;
- if (diff != 0)
+ if (lw != rw)
{
- if (!littleEndian)
- return lessThanUnsigned(lw, rw) ? -1 : 1;
-
- // Use binary search
- int n = 0;
- int y;
- int x = (int) diff;
- if (x == 0)
- {
- x = (int) (diff >>> 32);
- n = 32;
- }
-
- y = x << 16;
- if (y == 0)
- n += 16;
- else
- x = y;
-
- y = x << 8;
- if (y == 0)
- n += 8;
- return (int) (((lw >>> n) & 0xFFL) - ((rw >>> n) & 0xFFL));
+ if (BIG_ENDIAN)
+ return UnsignedLongs.compare(lw, rw);
+
+ return UnsignedLongs.compare(Long.reverseBytes(lw), Long.reverseBytes(rw));
}
}
- // The epilogue to cover the last (minLength % 8) elements.
- for (int i = minWords * Longs.BYTES; i < minLength; i++)
+ for (int i = wordComparisons ; i < minLength ; i++)
{
- int result = UnsignedBytes.compare(theUnsafe.getByte(buffer1, memoryOffset1 + i),
- theUnsafe.getByte(buffer2, memoryOffset2 + i));
- if (result != 0)
- return result;
+ int b1 = theUnsafe.getByte(buffer1, memoryOffset1 + i) & 0xFF;
+ int b2 = theUnsafe.getByte(buffer2, memoryOffset2 + i) & 0xFF;
+ if (b1 != b2)
+ return b1 - b2;
}
+
return length1 - length2;
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/utils/MurmurHash.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/MurmurHash.java b/src/java/org/apache/cassandra/utils/MurmurHash.java
index 9dcde6d..bf83681 100644
--- a/src/java/org/apache/cassandra/utils/MurmurHash.java
+++ b/src/java/org/apache/cassandra/utils/MurmurHash.java
@@ -17,6 +17,8 @@
*/
package org.apache.cassandra.utils;
+import net.nicoulaj.compilecommand.annotations.Inline;
+
import java.nio.ByteBuffer;
/**
@@ -170,6 +172,7 @@ public class MurmurHash
return k;
}
+ @Inline
public static void hash3_x64_128(ByteBuffer key, int offset, int length, long seed, long[] result)
{
final int nblocks = length >> 4; // Process as 128-bit blocks.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/utils/btree/NodeBuilder.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/btree/NodeBuilder.java b/src/java/org/apache/cassandra/utils/btree/NodeBuilder.java
index ba6cf21..9d57182 100644
--- a/src/java/org/apache/cassandra/utils/btree/NodeBuilder.java
+++ b/src/java/org/apache/cassandra/utils/btree/NodeBuilder.java
@@ -25,7 +25,6 @@ import java.util.Comparator;
import static org.apache.cassandra.utils.btree.BTree.EMPTY_BRANCH;
import static org.apache.cassandra.utils.btree.BTree.FAN_FACTOR;
-import static org.apache.cassandra.utils.btree.BTree.POSITIVE_INFINITY;
import static org.apache.cassandra.utils.btree.BTree.compare;
import static org.apache.cassandra.utils.btree.BTree.find;
import static org.apache.cassandra.utils.btree.BTree.getKeyEnd;
@@ -145,7 +144,7 @@ final class NodeBuilder
// and simply avoids performing a binary search until we've checked the proceeding key;
// possibly we should disable this check if we determine that it fails more than a handful of times
// during any given builder use to get the best of both worlds
- int c = comparator.compare(copyFrom[i], key);
+ int c = -comparator.compare(key, copyFrom[i]);
if (c >= 0)
{
found = c == 0;
@@ -168,7 +167,7 @@ final class NodeBuilder
return null;
key = next;
}
- else if (i == copyFromKeyEnd && compare(comparator, upperBound, key) <= 0)
+ else if (i == copyFromKeyEnd && compare(comparator, key, upperBound) >= 0)
owns = false;
if (isLeaf(copyFrom))
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/utils/memory/MemoryUtil.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/memory/MemoryUtil.java b/src/java/org/apache/cassandra/utils/memory/MemoryUtil.java
index 532d071..129a60b 100644
--- a/src/java/org/apache/cassandra/utils/memory/MemoryUtil.java
+++ b/src/java/org/apache/cassandra/utils/memory/MemoryUtil.java
@@ -22,6 +22,7 @@ import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import com.google.common.primitives.*;
import sun.misc.Unsafe;
public abstract class MemoryUtil
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/test/unit/org/apache/cassandra/db/NativeCellTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/NativeCellTest.java b/test/unit/org/apache/cassandra/db/NativeCellTest.java
index 0d03f55..6a2bf73 100644
--- a/test/unit/org/apache/cassandra/db/NativeCellTest.java
+++ b/test/unit/org/apache/cassandra/db/NativeCellTest.java
@@ -133,6 +133,86 @@ public class NativeCellTest
}
}
+
+ @Test
+ public void testComparator()
+ {
+
+ Random rand = ThreadLocalRandom.current();
+ for (Name test : TESTS)
+ {
+ byte[] bytes = new byte[7];
+ byte[] bytes2 = new byte[7];
+ rand.nextBytes(bytes);
+ rand.nextBytes(bytes2);
+
+ // test regular Cell
+ Cell buf, nat, buf2, nat2;
+ buf = new BufferCell(test.name, ByteBuffer.wrap(bytes), rand.nextLong());
+ nat = buf.localCopy(metadata, nativeAllocator, group);
+
+ buf2 = new BufferCell(test.name, ByteBuffer.wrap(bytes2), rand.nextLong());
+ nat2 = buf2.localCopy(metadata, nativeAllocator, group);
+
+ assert test.type.compare(buf.name(), nat.name()) == 0;
+ assert test.type.compare(buf2.name(), nat2.name()) == 0;
+
+ int val = test.type.compare(buf.name(), buf2.name());
+ assert test.type.compare(nat.name(), nat2.name()) == val;
+ assert test.type.compare(nat.name(), buf2.name()) == val;
+ assert test.type.compare(buf.name(), nat2.name()) == val;
+
+
+ // test DeletedCell
+ buf = new BufferDeletedCell(test.name, rand.nextInt(100000), rand.nextLong());
+ nat = buf.localCopy(metadata, nativeAllocator, group);
+ buf2 = new BufferDeletedCell(test.name, rand.nextInt(100000), rand.nextLong());
+ nat2 = buf2.localCopy(metadata, nativeAllocator, group);
+
+ assert test.type.compare(buf.name(), nat.name()) == 0;
+ assert test.type.compare(buf2.name(), nat2.name()) == 0;
+
+ val = test.type.compare(buf.name(), buf2.name());
+ assert test.type.compare(nat.name(), nat2.name()) == val;
+ assert test.type.compare(nat.name(), buf2.name()) == val;
+ assert test.type.compare(buf.name(), nat2.name()) == val;
+
+
+
+ // test ExpiringCell
+ buf = new BufferExpiringCell(test.name, ByteBuffer.wrap(bytes), rand.nextLong(), rand.nextInt(100000));
+ nat = buf.localCopy(metadata, nativeAllocator, group);
+
+ buf2 = new BufferExpiringCell(test.name, ByteBuffer.wrap(bytes2), rand.nextLong(), rand.nextInt(100000));
+ nat2 = buf2.localCopy(metadata, nativeAllocator, group);
+
+ assert test.type.compare(buf.name(), nat.name()) == 0;
+ assert test.type.compare(buf2.name(), nat2.name()) == 0;
+
+ val = test.type.compare(buf.name(), buf2.name());
+ assert test.type.compare(nat.name(), nat2.name()) == val;
+ assert test.type.compare(nat.name(), buf2.name()) == val;
+ assert test.type.compare(buf.name(), nat2.name()) == val;
+
+
+ // test CounterCell
+ buf = new BufferCounterCell(test.name, CounterContext.instance().createLocal(rand.nextLong()), rand.nextLong(), rand.nextInt(100000));
+ nat = buf.localCopy(metadata, nativeAllocator, group);
+
+ buf2 = new BufferCounterCell(test.name, CounterContext.instance().createLocal(rand.nextLong()), rand.nextLong(), rand.nextInt(100000));
+ nat2 = buf2.localCopy(metadata, nativeAllocator, group);
+
+ assert test.type.compare(buf.name(), nat.name()) == 0;
+ assert test.type.compare(buf2.name(), nat2.name()) == 0;
+
+ val = test.type.compare(buf.name(), buf2.name());
+ assert test.type.compare(nat.name(), nat2.name()) == val;
+ assert test.type.compare(nat.name(), buf2.name()) == val;
+ assert test.type.compare(buf.name(), nat2.name()) == val;
+
+ }
+ }
+
static void test(Name test, Cell buf, Cell nat) throws IOException
{
Assert.assertTrue(buf.equals(nat));
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/test/unit/org/apache/cassandra/db/composites/CTypeTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/composites/CTypeTest.java b/test/unit/org/apache/cassandra/db/composites/CTypeTest.java
index 4bd755b..496a2dc 100644
--- a/test/unit/org/apache/cassandra/db/composites/CTypeTest.java
+++ b/test/unit/org/apache/cassandra/db/composites/CTypeTest.java
@@ -91,15 +91,11 @@ public class CTypeTest
{
CellName a = stype2.makeCellName(UUIDType.instance.fromString("00000000-0000-0000-0000-000000000000"));
CellName z = stype2.makeCellName(UUIDType.instance.fromString("ffffffff-ffff-ffff-ffff-ffffffffffff"));
- Composite empty = Composites.EMPTY;
assert stype2.compare(a,z) < 0;
assert stype2.compare(z,a) > 0;
assert stype2.compare(a,a) == 0;
assert stype2.compare(z,z) == 0;
- assert stype2.compare(empty, a) < 0;
- assert stype2.compare(a,empty) > 0;
- assert stype2.compare(empty, empty) == 0;
}
@@ -108,16 +104,11 @@ public class CTypeTest
{
CellName a = stype1.makeCellName(ByteBufferUtil.bytes("a"));
CellName z = stype1.makeCellName(ByteBufferUtil.bytes("z"));
- Composite empty = Composites.EMPTY;
assert stype1.compare(a,z) < 0;
assert stype1.compare(z,a) > 0;
assert stype1.compare(a,a) == 0;
assert stype1.compare(z,z) == 0;
- assert stype1.compare(empty, a) < 0;
- assert stype1.compare(a,empty) > 0;
- assert stype1.compare(empty, empty) == 0;
-
}
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/test/unit/org/apache/cassandra/db/filter/ColumnSliceTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/filter/ColumnSliceTest.java b/test/unit/org/apache/cassandra/db/filter/ColumnSliceTest.java
index 2dc3744..15f1797 100644
--- a/test/unit/org/apache/cassandra/db/filter/ColumnSliceTest.java
+++ b/test/unit/org/apache/cassandra/db/filter/ColumnSliceTest.java
@@ -382,12 +382,12 @@ public class ColumnSliceTest
private static void assertSlicesValid(ColumnSlice[] slices)
{
- assertTrue("Slices " + toString(slices) + " should be valid", ColumnSlice.validateSlices(slices, simpleIntType));
+ assertTrue("Slices " + toString(slices) + " should be valid", ColumnSlice.validateSlices(slices, simpleIntType, false));
}
private static void assertSlicesInvalid(ColumnSlice[] slices)
{
- assertFalse("Slices " + toString(slices) + " shouldn't be valid", ColumnSlice.validateSlices(slices, simpleIntType));
+ assertFalse("Slices " + toString(slices) + " shouldn't be valid", ColumnSlice.validateSlices(slices, simpleIntType, false));
}
private static void assertSlicesEquals(ColumnSlice[] expected, ColumnSlice[] actual)
[3/3] git commit: Merge branch 'cassandra-2.1' into trunk
Posted by be...@apache.org.
Merge branch 'cassandra-2.1' into trunk
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/51cdeed4
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/51cdeed4
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/51cdeed4
Branch: refs/heads/trunk
Commit: 51cdeed483d4b00f6cc35d260745019da4c0d113
Parents: 2472701 e77ea12
Author: Benedict Elliott Smith <be...@apache.org>
Authored: Mon Jun 30 14:31:52 2014 +0100
Committer: Benedict Elliott Smith <be...@apache.org>
Committed: Mon Jun 30 14:31:52 2014 +0100
----------------------------------------------------------------------
build.xml | 4 +-
conf/cassandra-env.sh | 4 +
conf/cassandra.yaml | 2 +-
.../apache/cassandra/db/AbstractNativeCell.java | 55 ++++-
.../cassandra/db/ArrayBackedSortedColumns.java | 4 +-
.../apache/cassandra/db/AtomicBTreeColumns.java | 13 +-
.../apache/cassandra/db/BufferDecoratedKey.java | 2 +
.../cassandra/db/CollationController.java | 2 +
.../apache/cassandra/db/ConsistencyLevel.java | 2 +
.../org/apache/cassandra/db/DecoratedKey.java | 3 +
.../apache/cassandra/db/NativeDecoratedKey.java | 3 +-
.../cassandra/db/composites/AbstractCType.java | 93 ++++++--
.../db/composites/AbstractCellNameType.java | 23 +-
.../AbstractCompoundCellNameType.java | 2 +
.../composites/AbstractSimpleCellNameType.java | 80 +++++--
.../apache/cassandra/db/composites/CType.java | 2 +
.../cassandra/db/composites/CellNameType.java | 3 +-
.../cassandra/db/composites/Composites.java | 5 +-
.../composites/CompoundSparseCellNameType.java | 2 -
.../cassandra/db/composites/SimpleCType.java | 22 +-
.../apache/cassandra/db/filter/ColumnSlice.java | 52 +++--
.../cassandra/db/filter/NamesQueryFilter.java | 2 +-
.../cassandra/db/filter/SliceQueryFilter.java | 2 +-
.../cassandra/io/sstable/IndexHelper.java | 4 +-
.../org/apache/cassandra/io/util/Memory.java | 3 +-
.../apache/cassandra/service/StorageProxy.java | 3 +
.../cassandra/thrift/CassandraServer.java | 15 +-
.../apache/cassandra/utils/ByteBufferUtil.java | 4 +
.../cassandra/utils/FastByteOperations.java | 226 +++++++++----------
.../org/apache/cassandra/utils/MurmurHash.java | 3 +
.../cassandra/utils/btree/NodeBuilder.java | 4 +-
.../cassandra/utils/memory/MemoryUtil.java | 1 +
.../org/apache/cassandra/db/NativeCellTest.java | 80 +++++++
.../cassandra/db/composites/CTypeTest.java | 9 -
.../cassandra/db/filter/ColumnSliceTest.java | 4 +-
35 files changed, 501 insertions(+), 237 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/51cdeed4/build.xml
----------------------------------------------------------------------
diff --cc build.xml
index 27ac9c5,bc2bbfd..6ea57bc
--- a/build.xml
+++ b/build.xml
@@@ -423,8 -432,8 +423,9 @@@
<dependency groupId="org.apache.hadoop" artifactId="hadoop-minicluster"/>
<dependency groupId="org.apache.pig" artifactId="pig"/>
<dependency groupId="com.google.code.findbugs" artifactId="jsr305"/>
+ <dependency groupId="org.antlr" artifactId="antlr"/>
<dependency groupId="com.datastax.cassandra" artifactId="cassandra-driver-core"/>
+ <dependency groupId="net.ju-n.compile-command-annotations" artifactId="compile-command-annotations"/>
</artifact:pom>
<artifact:pom id="coverage-deps-pom"
http://git-wip-us.apache.org/repos/asf/cassandra/blob/51cdeed4/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/51cdeed4/src/java/org/apache/cassandra/db/AtomicBTreeColumns.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/51cdeed4/src/java/org/apache/cassandra/db/CollationController.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/51cdeed4/src/java/org/apache/cassandra/db/ConsistencyLevel.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/51cdeed4/src/java/org/apache/cassandra/db/composites/CType.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/51cdeed4/src/java/org/apache/cassandra/db/composites/CellNameType.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/51cdeed4/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/51cdeed4/src/java/org/apache/cassandra/io/util/Memory.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/io/util/Memory.java
index b908a9d,5306433..5b90d39
--- a/src/java/org/apache/cassandra/io/util/Memory.java
+++ b/src/java/org/apache/cassandra/io/util/Memory.java
@@@ -20,7 -20,9 +20,8 @@@ package org.apache.cassandra.io.util
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import com.sun.jna.Native;
import org.apache.cassandra.config.DatabaseDescriptor;
+ import org.apache.cassandra.utils.FastByteOperations;
import org.apache.cassandra.utils.memory.MemoryUtil;
import sun.misc.Unsafe;
import sun.nio.ch.DirectBuffer;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/51cdeed4/src/java/org/apache/cassandra/thrift/CassandraServer.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/thrift/CassandraServer.java
index 9a8ef8a,0621db9..343b811
--- a/src/java/org/apache/cassandra/thrift/CassandraServer.java
+++ b/src/java/org/apache/cassandra/thrift/CassandraServer.java
@@@ -2037,13 -2071,17 +2037,16 @@@ public class CassandraServer implement
fixOptionalSliceParameters(request.getColumn_slices().get(i));
Composite start = metadata.comparator.fromByteBuffer(request.getColumn_slices().get(i).start);
Composite finish = metadata.comparator.fromByteBuffer(request.getColumn_slices().get(i).finish);
- int compare = metadata.comparator.compare(start, finish);
- if (!request.reversed && compare > 0)
- throw new InvalidRequestException(String.format("Column slice at index %d had start greater than finish", i));
- else if (request.reversed && compare < 0)
- throw new InvalidRequestException(String.format("Reversed column slice at index %d had start less than finish", i));
+ if (!start.isEmpty() && !finish.isEmpty())
+ {
+ int compare = metadata.comparator.compare(start, finish);
+ if (!request.reversed && compare > 0)
+ throw new InvalidRequestException(String.format("Column slice at index %d had start greater than finish", i));
+ else if (request.reversed && compare < 0)
+ throw new InvalidRequestException(String.format("Reversed column slice at index %d had start less than finish", i));
+ }
slices[i] = new ColumnSlice(start, finish);
}
-
ColumnSlice[] deoverlapped = ColumnSlice.deoverlapSlices(slices, request.reversed ? metadata.comparator.reverseComparator() : metadata.comparator);
SliceQueryFilter filter = new SliceQueryFilter(deoverlapped, request.reversed, request.count);
ThriftValidation.validateKey(metadata, request.key);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/51cdeed4/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
----------------------------------------------------------------------
[2/3] git commit: Optimise CellName/Composite comparisons for
NativeCell
Posted by be...@apache.org.
Optimise CellName/Composite comparisons for NativeCell
patch by Jake Luciani and Benedict Elliott Smith for CASSANDRA-6755
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/e77ea125
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/e77ea125
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/e77ea125
Branch: refs/heads/trunk
Commit: e77ea1252092bc0e589cfbc2341c2194cb750b08
Parents: 5c85699
Author: Benedict Elliott Smith <be...@apache.org>
Authored: Mon Jun 30 14:30:55 2014 +0100
Committer: Benedict Elliott Smith <be...@apache.org>
Committed: Mon Jun 30 14:30:55 2014 +0100
----------------------------------------------------------------------
build.xml | 4 +-
conf/cassandra-env.sh | 4 +
conf/cassandra.yaml | 2 +-
.../apache/cassandra/db/AbstractNativeCell.java | 55 ++++-
.../cassandra/db/ArrayBackedSortedColumns.java | 4 +-
.../apache/cassandra/db/AtomicBTreeColumns.java | 13 +-
.../apache/cassandra/db/BufferDecoratedKey.java | 2 +
.../cassandra/db/CollationController.java | 2 +
.../apache/cassandra/db/ConsistencyLevel.java | 2 +
.../org/apache/cassandra/db/DecoratedKey.java | 3 +
.../apache/cassandra/db/NativeDecoratedKey.java | 3 +-
.../cassandra/db/composites/AbstractCType.java | 93 ++++++--
.../db/composites/AbstractCellNameType.java | 23 +-
.../AbstractCompoundCellNameType.java | 2 +
.../composites/AbstractSimpleCellNameType.java | 80 +++++--
.../apache/cassandra/db/composites/CType.java | 2 +
.../cassandra/db/composites/CellNameType.java | 3 +-
.../cassandra/db/composites/Composites.java | 5 +-
.../composites/CompoundSparseCellNameType.java | 2 -
.../cassandra/db/composites/SimpleCType.java | 22 +-
.../apache/cassandra/db/filter/ColumnSlice.java | 52 +++--
.../cassandra/db/filter/NamesQueryFilter.java | 2 +-
.../cassandra/db/filter/SliceQueryFilter.java | 2 +-
.../cassandra/io/sstable/IndexHelper.java | 4 +-
.../org/apache/cassandra/io/util/Memory.java | 3 +-
.../apache/cassandra/service/StorageProxy.java | 3 +
.../cassandra/thrift/CassandraServer.java | 15 +-
.../apache/cassandra/utils/ByteBufferUtil.java | 4 +
.../cassandra/utils/FastByteOperations.java | 226 +++++++++----------
.../org/apache/cassandra/utils/MurmurHash.java | 3 +
.../cassandra/utils/btree/NodeBuilder.java | 5 +-
.../cassandra/utils/memory/MemoryUtil.java | 1 +
.../org/apache/cassandra/db/NativeCellTest.java | 80 +++++++
.../cassandra/db/composites/CTypeTest.java | 9 -
.../cassandra/db/filter/ColumnSliceTest.java | 4 +-
35 files changed, 501 insertions(+), 238 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index c34bcfc..bc2bbfd 100644
--- a/build.xml
+++ b/build.xml
@@ -62,7 +62,6 @@
<property name="test.long.src" value="${test.dir}/long"/>
<property name="test.pig.src" value="${test.dir}/pig"/>
<property name="dist.dir" value="${build.dir}/dist"/>
-
<property name="source.version" value="1.7"/>
<property name="target.version" value="1.7"/>
@@ -402,6 +401,7 @@
<dependency groupId="com.clearspring.analytics" artifactId="stream" version="2.5.2" />
<dependency groupId="com.datastax.cassandra" artifactId="cassandra-driver-core" version="2.0.1" />
<dependency groupId="net.sf.supercsv" artifactId="super-csv" version="2.1.0" />
+ <dependency groupId="net.ju-n.compile-command-annotations" artifactId="compile-command-annotations" version="1.2.0" />
</dependencyManagement>
<developer id="alakshman" name="Avinash Lakshman"/>
<developer id="antelder" name="Anthony Elder"/>
@@ -433,6 +433,7 @@
<dependency groupId="org.apache.pig" artifactId="pig"/>
<dependency groupId="com.google.code.findbugs" artifactId="jsr305"/>
<dependency groupId="com.datastax.cassandra" artifactId="cassandra-driver-core"/>
+ <dependency groupId="net.ju-n.compile-command-annotations" artifactId="compile-command-annotations"/>
</artifact:pom>
<artifact:pom id="coverage-deps-pom"
@@ -701,6 +702,7 @@
<copy todir="${build.classes.main}">
<fileset dir="${build.src.resources}" />
</copy>
+ <copy todir="${basedir}/conf" file="${build.classes.main}/META-INF/hotspot_compiler"/>
</target>
<!-- Stress build file -->
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/conf/cassandra-env.sh
----------------------------------------------------------------------
diff --git a/conf/cassandra-env.sh b/conf/cassandra-env.sh
index eb0553b..1655438 100644
--- a/conf/cassandra-env.sh
+++ b/conf/cassandra-env.sh
@@ -212,6 +212,7 @@ JVM_OPTS="$JVM_OPTS -XX:MaxTenuringThreshold=1"
JVM_OPTS="$JVM_OPTS -XX:CMSInitiatingOccupancyFraction=75"
JVM_OPTS="$JVM_OPTS -XX:+UseCMSInitiatingOccupancyOnly"
JVM_OPTS="$JVM_OPTS -XX:+UseTLAB"
+JVM_OPTS="$JVM_OPTS -XX:CompileCommandFile=$CASSANDRA_CONF/hotspot_compiler"
# note: bash evals '1.7.x' as > '1.7' so this is really a >= 1.7 jvm check
if [ "$JVM_ARCH" = "64-Bit" ] ; then
@@ -242,6 +243,9 @@ fi
# uncomment to have Cassandra JVM listen for remote debuggers/profilers on port 1414
# JVM_OPTS="$JVM_OPTS -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1414"
+# uncomment to have Cassandra JVM log internal method compilation (developers only)
+# JVM_OPTS="$JVM_OPTS -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation"
+
# Prefer binding to IPv4 network intefaces (when net.ipv6.bindv6only=1). See
# http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6342561 (short version:
# comment out this entry to enable IPv6 support).
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/conf/cassandra.yaml
----------------------------------------------------------------------
diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml
index f1e5576..4d97e86 100644
--- a/conf/cassandra.yaml
+++ b/conf/cassandra.yaml
@@ -290,7 +290,7 @@ memtable_cleanup_threshold: 0.4
# heap_buffers: on heap nio buffers
# offheap_buffers: off heap (direct) nio buffers
# offheap_objects: native memory, eliminating nio buffer heap overhead
-memtable_allocation_type: heap_buffers
+memtable_allocation_type: offheap_objects
# Total space to use for commitlogs. Since commitlog segments are
# mmapped, and hence use up address space, the default size is 32
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/AbstractNativeCell.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/AbstractNativeCell.java b/src/java/org/apache/cassandra/db/AbstractNativeCell.java
index f3128b8..d79ad19 100644
--- a/src/java/org/apache/cassandra/db/AbstractNativeCell.java
+++ b/src/java/org/apache/cassandra/db/AbstractNativeCell.java
@@ -21,6 +21,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.MessageDigest;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.ColumnIdentifier;
@@ -30,6 +31,7 @@ import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.FastByteOperations;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.*;
@@ -286,13 +288,24 @@ public abstract class AbstractNativeCell extends AbstractCell implements CellNam
public ByteBuffer get(int i)
{
+ return get(i, null);
+ }
+
+ @Inline
+ private ByteBuffer get(int i, AbstractAllocator copy)
+ {
// remember to take dense/sparse into account, and only return EOC when not dense
int size = size();
assert i >= 0 && i < size();
int cellNamesOffset = nameDeltaOffset(size);
int startDelta = i == 0 ? 0 : getShort(nameDeltaOffset(i));
int endDelta = i < size - 1 ? getShort(nameDeltaOffset(i + 1)) : valueStartOffset() - cellNamesOffset;
- return getByteBuffer(cellNamesOffset + startDelta, endDelta - startDelta).order(ByteOrder.BIG_ENDIAN);
+ int length = endDelta - startDelta;
+ if (copy == null)
+ return getByteBuffer(cellNamesOffset + startDelta, length).order(ByteOrder.BIG_ENDIAN);
+ ByteBuffer result = copy.allocate(length);
+ FastByteOperations.UnsafeOperations.copy(null, peer + cellNamesOffset + startDelta, result, 0, length);
+ return result;
}
private static final ThreadLocal<byte[]> BUFFER = new ThreadLocal<byte[]>()
@@ -496,12 +509,12 @@ public abstract class AbstractNativeCell extends AbstractCell implements CellNam
switch (nametype())
{
case SIMPLE_DENSE:
- return CellNames.simpleDense(allocator.clone(get(0)));
+ return CellNames.simpleDense(get(0, allocator));
case COMPOUND_DENSE:
r = new ByteBuffer[size()];
for (int i = 0; i < r.length; i++)
- r[i] = allocator.clone(get(i));
+ r[i] = get(i, allocator);
return CellNames.compositeDense(r);
case COMPOUND_SPARSE_STATIC:
@@ -509,7 +522,7 @@ public abstract class AbstractNativeCell extends AbstractCell implements CellNam
int clusteringSize = clusteringSize();
r = clusteringSize == 0 ? EMPTY : new ByteBuffer[clusteringSize()];
for (int i = 0; i < clusteringSize; i++)
- r[i] = allocator.clone(get(i));
+ r[i] = get(i, allocator);
ByteBuffer nameBuffer = get(r.length);
ColumnIdentifier name;
@@ -645,4 +658,38 @@ public abstract class AbstractNativeCell extends AbstractCell implements CellNam
checkPosition(offset, length);
return MemoryUtil.getByteBuffer(peer + offset, length);
}
+
+ // requires isByteOrderComparable to be true. Compares the name components only; ; may need to compare EOC etc still
+ public final int compareTo(final Composite that)
+ {
+ int size = size();
+ int size2 = that.size();
+ int minSize = Math.min(size, size2);
+ int startDelta = 0;
+ int cellNamesOffset = nameDeltaOffset(size);
+ for (int i = 0 ; i < minSize ; i++)
+ {
+ int endDelta = i < size - 1 ? getShort(nameDeltaOffset(i + 1)) : valueStartOffset() - cellNamesOffset;
+ long offset = peer + cellNamesOffset + startDelta;
+ int length = endDelta - startDelta;
+ int cmp = FastByteOperations.UnsafeOperations.compareTo(null, offset, length, that.get(i));
+ if (cmp != 0)
+ return cmp;
+ startDelta = endDelta;
+ }
+
+ EOC eoc = that.eoc();
+ if (size == size2)
+ return this.eoc().compareTo(eoc);
+
+ return size < size2 ? this.eoc().prefixComparisonResult : -eoc.prefixComparisonResult;
+ }
+
+ public final int compareToSimple(final Composite that)
+ {
+ assert size() == 1 && that.size() == 1;
+ int length = valueStartOffset() - nameDeltaOffset(1);
+ long offset = peer + nameDeltaOffset(1);
+ return FastByteOperations.UnsafeOperations.compareTo(null, offset, length, that.get(0));
+ }
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java b/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java
index 8a2d43e..e92d5a3 100644
--- a/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java
+++ b/src/java/org/apache/cassandra/db/ArrayBackedSortedColumns.java
@@ -27,6 +27,7 @@ import com.google.common.base.Function;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Iterables;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.Composite;
@@ -122,6 +123,7 @@ public class ArrayBackedSortedColumns extends ColumnFamily
/**
* synchronized so that concurrent (read-only) accessors don't mess the internal state.
*/
+ @Inline
private synchronized void sortCells()
{
if (isSorted)
@@ -129,7 +131,7 @@ public class ArrayBackedSortedColumns extends ColumnFamily
Comparator<Cell> comparator = reversed
? getComparator().columnReverseComparator()
- : getComparator().columnComparator();
+ : getComparator().columnComparator(false);
// Sort the unsorted segment - will still potentially contain duplicate (non-reconciled) cells
Arrays.sort(cells, sortedSize, size, comparator);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/AtomicBTreeColumns.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/AtomicBTreeColumns.java b/src/java/org/apache/cassandra/db/AtomicBTreeColumns.java
index 03cd0c5..559e759 100644
--- a/src/java/org/apache/cassandra/db/AtomicBTreeColumns.java
+++ b/src/java/org/apache/cassandra/db/AtomicBTreeColumns.java
@@ -40,6 +40,8 @@ import org.apache.cassandra.utils.btree.UpdateFunction;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.HeapAllocator;
import org.apache.cassandra.utils.memory.MemtableAllocator;
+import org.apache.cassandra.utils.memory.NativeAllocator;
+import org.apache.cassandra.utils.memory.NativePool;
import static org.apache.cassandra.db.index.SecondaryIndexManager.Updater;
@@ -186,7 +188,7 @@ public class AtomicBTreeColumns extends ColumnFamily
deletionInfo = current.deletionInfo;
}
- Object[] tree = BTree.update(current.tree, metadata.comparator.columnComparator(), cm, cm.getColumnCount(), true, updater);
+ Object[] tree = BTree.update(current.tree, metadata.comparator.columnComparator(Memtable.MEMORY_POOL instanceof NativePool), cm, cm.getColumnCount(), true, updater);
if (tree != null && refUpdater.compareAndSet(this, current, new Holder(tree, deletionInfo)))
{
@@ -226,14 +228,7 @@ public class AtomicBTreeColumns extends ColumnFamily
private Comparator<Object> asymmetricComparator()
{
- final Comparator<Composite> cmp = metadata.comparator;
- return new Comparator<Object>()
- {
- public int compare(Object o1, Object o2)
- {
- return cmp.compare((Composite) o1, ((Cell) o2).name());
- }
- };
+ return metadata.comparator.asymmetricColumnComparator(Memtable.MEMORY_POOL instanceof NativePool);
}
public Iterable<CellName> getColumnNames()
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/BufferDecoratedKey.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/BufferDecoratedKey.java b/src/java/org/apache/cassandra/db/BufferDecoratedKey.java
index d375162..8a1ad59 100644
--- a/src/java/org/apache/cassandra/db/BufferDecoratedKey.java
+++ b/src/java/org/apache/cassandra/db/BufferDecoratedKey.java
@@ -20,6 +20,8 @@ package org.apache.cassandra.db;
import java.nio.ByteBuffer;
import org.apache.cassandra.dht.Token;
+import org.apache.cassandra.utils.FastByteOperations;
+import org.apache.cassandra.utils.memory.MemoryUtil;
public class BufferDecoratedKey extends DecoratedKey
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/CollationController.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/CollationController.java b/src/java/org/apache/cassandra/db/CollationController.java
index 061537b..c9cbf69 100644
--- a/src/java/org/apache/cassandra/db/CollationController.java
+++ b/src/java/org/apache/cassandra/db/CollationController.java
@@ -28,6 +28,7 @@ import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.cassandra.db.columniterator.OnDiskAtomIterator;
import org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy;
import org.apache.cassandra.db.composites.CellName;
@@ -67,6 +68,7 @@ public class CollationController
* Once we have data for all requests columns that is newer than the newest remaining maxtimestamp,
* we stop.
*/
+ @Inline
private ColumnFamily collectTimeOrderedData(boolean copyOnHeap)
{
final ColumnFamily container = ArrayBackedSortedColumns.factory.create(cfs.metadata, filter.filter.isReversed());
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/ConsistencyLevel.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ConsistencyLevel.java b/src/java/org/apache/cassandra/db/ConsistencyLevel.java
index 7583a90..986a2aa 100644
--- a/src/java/org/apache/cassandra/db/ConsistencyLevel.java
+++ b/src/java/org/apache/cassandra/db/ConsistencyLevel.java
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import com.google.common.collect.Iterables;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -244,6 +245,7 @@ public enum ConsistencyLevel
}
}
+ @Inline
public void assureSufficientLiveNodes(Keyspace keyspace, Iterable<InetAddress> liveEndpoints) throws UnavailableException
{
int blockFor = blockFor(keyspace);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/DecoratedKey.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/DecoratedKey.java b/src/java/org/apache/cassandra/db/DecoratedKey.java
index fb3d7ab..604cbb7 100644
--- a/src/java/org/apache/cassandra/db/DecoratedKey.java
+++ b/src/java/org/apache/cassandra/db/DecoratedKey.java
@@ -20,10 +20,13 @@ package org.apache.cassandra.db;
import java.nio.ByteBuffer;
import java.util.Comparator;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.FastByteOperations;
+import org.apache.cassandra.utils.memory.MemoryUtil;
/**
* Represents a decorated key, handy for certain operations
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/NativeDecoratedKey.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/NativeDecoratedKey.java b/src/java/org/apache/cassandra/db/NativeDecoratedKey.java
index 52aa50c..79dc53f 100644
--- a/src/java/org/apache/cassandra/db/NativeDecoratedKey.java
+++ b/src/java/org/apache/cassandra/db/NativeDecoratedKey.java
@@ -20,13 +20,14 @@ package org.apache.cassandra.db;
import java.nio.ByteBuffer;
import org.apache.cassandra.dht.Token;
+import org.apache.cassandra.utils.FastByteOperations;
import org.apache.cassandra.utils.concurrent.OpOrder;
import org.apache.cassandra.utils.memory.MemoryUtil;
import org.apache.cassandra.utils.memory.NativeAllocator;
public class NativeDecoratedKey extends DecoratedKey
{
- private final long peer;
+ final long peer;
public NativeDecoratedKey(Token token, NativeAllocator allocator, OpOrder.Group writeOp, ByteBuffer key)
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/AbstractCType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/AbstractCType.java b/src/java/org/apache/cassandra/db/composites/AbstractCType.java
index e299e42..491a9d1 100644
--- a/src/java/org/apache/cassandra/db/composites/AbstractCType.java
+++ b/src/java/org/apache/cassandra/db/composites/AbstractCType.java
@@ -22,7 +22,9 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Comparator;
+import org.apache.cassandra.db.Cell;
import org.apache.cassandra.db.DeletionInfo;
+import org.apache.cassandra.db.NativeCell;
import org.apache.cassandra.db.RangeTombstone;
import org.apache.cassandra.db.RowIndexEntry;
import org.apache.cassandra.db.TypeSizes;
@@ -39,6 +41,39 @@ import static org.apache.cassandra.io.sstable.IndexHelper.IndexInfo;
public abstract class AbstractCType implements CType
{
+ static final Comparator<Cell> rightNativeCell = new Comparator<Cell>()
+ {
+ public int compare(Cell o1, Cell o2)
+ {
+ return -((NativeCell) o2).compareTo(o1.name());
+ }
+ };
+
+ static final Comparator<Cell> neitherNativeCell = new Comparator<Cell>()
+ {
+ public int compare(Cell o1, Cell o2)
+ {
+ return compareUnsigned(o1.name(), o2.name());
+ }
+ };
+
+ // only one or the other of these will ever be used
+ static final Comparator<Object> asymmetricRightNativeCell = new Comparator<Object>()
+ {
+ public int compare(Object o1, Object o2)
+ {
+ return -((NativeCell) o2).compareTo((Composite) o1);
+ }
+ };
+
+ static final Comparator<Object> asymmetricNeitherNativeCell = new Comparator<Object>()
+ {
+ public int compare(Object o1, Object o2)
+ {
+ return compareUnsigned((Composite) o1, ((Cell) o2).name());
+ }
+ };
+
private final Comparator<Composite> reverseComparator;
private final Comparator<IndexInfo> indexComparator;
private final Comparator<IndexInfo> indexReverseComparator;
@@ -60,11 +95,6 @@ public abstract class AbstractCType implements CType
{
public int compare(Composite c1, Composite c2)
{
- if (c1.isEmpty())
- return c2.isEmpty() ? 0 : -1;
- if (c2.isEmpty())
- return 1;
-
return AbstractCType.this.compare(c2, c1);
}
};
@@ -102,30 +132,37 @@ public abstract class AbstractCType implements CType
return isByteOrderComparable;
}
- public int compare(Composite c1, Composite c2)
+ static int compareUnsigned(Composite c1, Composite c2)
{
int s1 = c1.size();
int s2 = c2.size();
int minSize = Math.min(s1, s2);
- if (isByteOrderComparable)
+ for (int i = 0; i < minSize; i++)
{
- for (int i = 0; i < minSize; i++)
- {
- int cmp = ByteBufferUtil.compareUnsigned(c1.get(i), c2.get(i));
- if (cmp != 0)
- return cmp;
- }
+ int cmp = ByteBufferUtil.compareUnsigned(c1.get(i), c2.get(i));
+ if (cmp != 0)
+ return cmp;
}
- else
+
+ if (s1 == s2)
+ return c1.eoc().compareTo(c2.eoc());
+ return s1 < s2 ? c1.eoc().prefixComparisonResult : -c2.eoc().prefixComparisonResult;
+ }
+
+ public int compare(Composite c1, Composite c2)
+ {
+ int s1 = c1.size();
+ int s2 = c2.size();
+ int minSize = Math.min(s1, s2);
+
+ for (int i = 0; i < minSize; i++)
{
- for (int i = 0; i < minSize; i++)
- {
- AbstractType<?> comparator = subtype(i);
- int cmp = comparator.compare(c1.get(i), c2.get(i));
- if (cmp != 0)
- return cmp;
- }
+ int cmp = isByteOrderComparable
+ ? ByteBufferUtil.compareUnsigned(c1.get(i), c2.get(i))
+ : subtype(i).compare(c1.get(i), c2.get(i));
+ if (cmp != 0)
+ return cmp;
}
if (s1 == s2)
@@ -133,6 +170,20 @@ public abstract class AbstractCType implements CType
return s1 < s2 ? c1.eoc().prefixComparisonResult : -c2.eoc().prefixComparisonResult;
}
+ protected Comparator<Cell> getByteOrderColumnComparator(boolean isRightNative)
+ {
+ if (isRightNative)
+ return rightNativeCell;
+ return neitherNativeCell;
+ }
+
+ protected Comparator<Object> getByteOrderAsymmetricColumnComparator(boolean isRightNative)
+ {
+ if (isRightNative)
+ return asymmetricRightNativeCell;
+ return asymmetricNeitherNativeCell;
+ }
+
public void validate(Composite name)
{
ByteBuffer previous = null;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java b/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
index 56be8cf..7570d2c 100644
--- a/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
@@ -40,8 +40,9 @@ import org.apache.cassandra.utils.ByteBufferUtil;
public abstract class AbstractCellNameType extends AbstractCType implements CellNameType
{
- private final Comparator<Cell> columnComparator;
+ final Comparator<Cell> columnComparator;
private final Comparator<Cell> columnReverseComparator;
+ final Comparator<Object> asymmetricComparator;
private final Comparator<OnDiskAtom> onDiskAtomComparator;
private final ISerializer<CellName> cellSerializer;
@@ -60,6 +61,13 @@ public abstract class AbstractCellNameType extends AbstractCType implements Cell
return AbstractCellNameType.this.compare(c1.name(), c2.name());
}
};
+ asymmetricComparator = new Comparator<Object>()
+ {
+ public int compare(Object c1, Object c2)
+ {
+ return AbstractCellNameType.this.compare((Composite) c1, ((Cell) c2).name());
+ }
+ };
columnReverseComparator = new Comparator<Cell>()
{
public int compare(Cell c1, Cell c2)
@@ -125,9 +133,18 @@ public abstract class AbstractCellNameType extends AbstractCType implements Cell
diskAtomFilterSerializer = new IDiskAtomFilter.Serializer(this);
}
- public Comparator<Cell> columnComparator()
+ public final Comparator<Cell> columnComparator(boolean isRightNative)
+ {
+ if (!isByteOrderComparable)
+ return columnComparator;
+ return getByteOrderColumnComparator(isRightNative);
+ }
+
+ public final Comparator<Object> asymmetricColumnComparator(boolean isRightNative)
{
- return columnComparator;
+ if (!isByteOrderComparable)
+ return asymmetricComparator;
+ return getByteOrderAsymmetricColumnComparator(isRightNative);
}
public Comparator<Cell> columnReverseComparator()
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/AbstractCompoundCellNameType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/AbstractCompoundCellNameType.java b/src/java/org/apache/cassandra/db/composites/AbstractCompoundCellNameType.java
index 641f14d..b748212 100644
--- a/src/java/org/apache/cassandra/db/composites/AbstractCompoundCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/AbstractCompoundCellNameType.java
@@ -20,7 +20,9 @@ package org.apache.cassandra.db.composites;
import java.io.DataInput;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.Comparator;
+import org.apache.cassandra.db.Cell;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CompositeType;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/AbstractSimpleCellNameType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/AbstractSimpleCellNameType.java b/src/java/org/apache/cassandra/db/composites/AbstractSimpleCellNameType.java
index 95386fd..f9c9641 100644
--- a/src/java/org/apache/cassandra/db/composites/AbstractSimpleCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/AbstractSimpleCellNameType.java
@@ -20,7 +20,11 @@ package org.apache.cassandra.db.composites;
import java.io.DataInput;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.Comparator;
+import net.nicoulaj.compilecommand.annotations.Inline;
+import org.apache.cassandra.db.Cell;
+import org.apache.cassandra.db.NativeCell;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.utils.ByteBufferUtil;
@@ -28,6 +32,39 @@ public abstract class AbstractSimpleCellNameType extends AbstractCellNameType
{
protected final AbstractType<?> type;
+ static final Comparator<Cell> rightNativeCell = new Comparator<Cell>()
+ {
+ public int compare(Cell o1, Cell o2)
+ {
+ return -((NativeCell) o2).compareToSimple(o1.name());
+ }
+ };
+
+ static final Comparator<Cell> neitherNativeCell = new Comparator<Cell>()
+ {
+ public int compare(Cell o1, Cell o2)
+ {
+ return compareUnsigned(o1.name(), o2.name());
+ }
+ };
+
+ // only one or the other of these will ever be used
+ static final Comparator<Object> asymmetricRightNativeCell = new Comparator<Object>()
+ {
+ public int compare(Object o1, Object o2)
+ {
+ return -((NativeCell) o2).compareToSimple((Composite) o1);
+ }
+ };
+
+ static final Comparator<Object> asymmetricNeitherNativeCell = new Comparator<Object>()
+ {
+ public int compare(Object o1, Object o2)
+ {
+ return compareUnsigned((Composite) o1, ((Cell) o2).name());
+ }
+ };
+
protected AbstractSimpleCellNameType(AbstractType<?> type)
{
super(type.isByteOrderComparable());
@@ -44,31 +81,38 @@ public abstract class AbstractSimpleCellNameType extends AbstractCellNameType
return 1;
}
- public int compare(Composite c1, Composite c2)
+ @Inline
+ static int compareUnsigned(Composite c1, Composite c2)
{
- // This method assumes that simple composites never have an EOC != NONE. This assumption
- // stands in particular on the fact that a Composites.EMPTY never has a non-NONE EOC. If
- // this ever change, we'll need to update this.
+ ByteBuffer b1 = c1.toByteBuffer();
+ ByteBuffer b2 = c2.toByteBuffer();
+ assert b1.hasRemaining() & b2.hasRemaining();
+ return ByteBufferUtil.compareUnsigned(b1, b2);
+ }
+ public int compare(Composite c1, Composite c2)
+ {
if (isByteOrderComparable)
- {
- // toByteBuffer is always cheap for simple types, and we keep virtual method calls to a minimum:
- // hasRemaining will always be inlined, as will most of the call-stack for BBU.compareUnsigned
- ByteBuffer b1 = c1.toByteBuffer();
- ByteBuffer b2 = c2.toByteBuffer();
- if (!b1.hasRemaining() || !b2.hasRemaining())
- return b1.hasRemaining() ? 1 : (b2.hasRemaining() ? -1 : 0);
- return ByteBufferUtil.compareUnsigned(b1, b2);
- }
-
- boolean c1isEmpty = c1.isEmpty();
- boolean c2isEmpty = c2.isEmpty();
- if (c1isEmpty || c2isEmpty)
- return !c1isEmpty ? 1 : (!c2isEmpty ? -1 : 0);
+ return compareUnsigned(c1, c2);
+ assert !(c1.isEmpty() | c2.isEmpty());
return type.compare(c1.get(0), c2.get(0));
}
+ protected Comparator<Cell> getByteOrderColumnComparator(boolean isRightNative)
+ {
+ if (isRightNative)
+ return rightNativeCell;
+ return neitherNativeCell;
+ }
+
+ protected Comparator<Object> getByteOrderAsymmetricColumnComparator(boolean isRightNative)
+ {
+ if (isRightNative)
+ return asymmetricRightNativeCell;
+ return asymmetricNeitherNativeCell;
+ }
+
public AbstractType<?> subtype(int i)
{
if (i != 0)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/CType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/CType.java b/src/java/org/apache/cassandra/db/composites/CType.java
index c2516f5..280f7af 100644
--- a/src/java/org/apache/cassandra/db/composites/CType.java
+++ b/src/java/org/apache/cassandra/db/composites/CType.java
@@ -55,6 +55,8 @@ public interface CType extends Comparator<Composite>
*/
public int size();
+ int compare(Composite o1, Composite o2);
+
/**
* Gets a subtype of this CType.
*/
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/CellNameType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/CellNameType.java b/src/java/org/apache/cassandra/db/composites/CellNameType.java
index acc0527..4f45d41 100644
--- a/src/java/org/apache/cassandra/db/composites/CellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/CellNameType.java
@@ -174,7 +174,8 @@ public interface CellNameType extends CType
// Ultimately, those might be split into an IVersionedSerializer and an ISSTableSerializer
public ISerializer<CellName> cellSerializer();
- public Comparator<Cell> columnComparator();
+ public Comparator<Cell> columnComparator(boolean isRightNative);
+ public Comparator<Object> asymmetricColumnComparator(boolean isRightNative);
public Comparator<Cell> columnReverseComparator();
public Comparator<OnDiskAtom> onDiskAtomComparator();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/Composites.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/Composites.java b/src/java/org/apache/cassandra/db/composites/Composites.java
index 154e9f7..f6626e0 100644
--- a/src/java/org/apache/cassandra/db/composites/Composites.java
+++ b/src/java/org/apache/cassandra/db/composites/Composites.java
@@ -57,7 +57,10 @@ public abstract class Composites
public ByteBuffer get(int i)
{
- throw new IndexOutOfBoundsException();
+ if (i > 0)
+ throw new IndexOutOfBoundsException();
+
+ return ByteBufferUtil.EMPTY_BYTE_BUFFER;
}
public EOC eoc()
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java b/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
index 29e1617..57eb5fd 100644
--- a/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
@@ -41,7 +41,6 @@ public class CompoundSparseCellNameType extends AbstractCompoundCellNameType
protected final Map<ByteBuffer, ColumnIdentifier> internedIds;
private final Composite staticPrefix;
- private final boolean isByteOrderComparable;
public CompoundSparseCellNameType(List<AbstractType<?>> types)
{
@@ -64,7 +63,6 @@ public class CompoundSparseCellNameType extends AbstractCompoundCellNameType
this.columnNameType = columnNameType;
this.internedIds = internedIds;
this.staticPrefix = makeStaticPrefix(clusteringType.size());
- this.isByteOrderComparable = isByteOrderComparable(fullType.types);
}
private static Composite makeStaticPrefix(int size)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/composites/SimpleCType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/SimpleCType.java b/src/java/org/apache/cassandra/db/composites/SimpleCType.java
index 229d538..c824179 100644
--- a/src/java/org/apache/cassandra/db/composites/SimpleCType.java
+++ b/src/java/org/apache/cassandra/db/composites/SimpleCType.java
@@ -18,6 +18,7 @@
package org.apache.cassandra.db.composites;
import java.nio.ByteBuffer;
+import java.util.Comparator;
import java.util.List;
import org.apache.cassandra.db.marshal.AbstractType;
@@ -48,26 +49,13 @@ public class SimpleCType extends AbstractCType
public int compare(Composite c1, Composite c2)
{
+ if (isByteOrderComparable)
+ return AbstractSimpleCellNameType.compareUnsigned(c1, c2);
+
+ assert !(c1.isEmpty() | c2.isEmpty());
// This method assumes that simple composites never have an EOC != NONE. This assumption
// stands in particular on the fact that a Composites.EMPTY never has a non-NONE EOC. If
// this ever change, we'll need to update this.
-
- if (isByteOrderComparable)
- {
- // toByteBuffer is always cheap for simple types, and we keep virtual method calls to a minimum:
- // hasRemaining will always be inlined, as will most of the call-stack for BBU.compareUnsigned
- ByteBuffer b1 = c1.toByteBuffer();
- ByteBuffer b2 = c2.toByteBuffer();
- if (!b1.hasRemaining() || !b2.hasRemaining())
- return b1.hasRemaining() ? 1 : (b2.hasRemaining() ? -1 : 0);
- return ByteBufferUtil.compareUnsigned(b1, b2);
- }
-
- boolean c1isEmpty = c1.isEmpty();
- boolean c2isEmpty = c2.isEmpty();
- if (c1isEmpty || c2isEmpty)
- return !c1isEmpty ? 1 : (!c2isEmpty ? -1 : 0);
-
return type.compare(c1.get(0), c2.get(0));
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/filter/ColumnSlice.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/filter/ColumnSlice.java b/src/java/org/apache/cassandra/db/filter/ColumnSlice.java
index bca4743..7d470b3 100644
--- a/src/java/org/apache/cassandra/db/filter/ColumnSlice.java
+++ b/src/java/org/apache/cassandra/db/filter/ColumnSlice.java
@@ -55,7 +55,7 @@ public class ColumnSlice
public boolean includes(Comparator<Composite> cmp, Composite name)
{
- return cmp.compare(start, name) <= 0 && (finish.isEmpty() || cmp.compare(finish, name) >= 0);
+ return (start.isEmpty() || cmp.compare(start, name) <= 0) && (finish.isEmpty() || cmp.compare(finish, name) >= 0);
}
public boolean isBefore(Comparator<Composite> cmp, Composite name)
@@ -114,26 +114,32 @@ public class ColumnSlice
* Validates that the provided slice array contains only non-overlapped slices valid for a query {@code reversed}
* or not on a table using {@code comparator}.
*/
- public static boolean validateSlices(ColumnSlice[] slices, CellNameType comparator, boolean reversed)
+ public static boolean validateSlices(ColumnSlice[] slices, CellNameType type, boolean reversed)
{
- return validateSlices(slices, reversed ? comparator.reverseComparator() : comparator);
- }
+ Comparator<Composite> comparator = reversed ? type.reverseComparator() : type;
- /**
- * Validates that the provided slice array contains only non-overlapped slices in {@code comparator} order.
- */
- public static boolean validateSlices(ColumnSlice[] slices, Comparator<Composite> comparator)
- {
for (int i = 0; i < slices.length; i++)
{
- if (i > 0 && comparator.compare(slices[i-1].finish, slices[i].start) >= 0)
- return false;
+ Composite start = slices[i].start;
+ Composite finish = slices[i].finish;
- if (slices[i].finish.isEmpty())
- return i == slices.length - 1;
+ if (start.isEmpty() || finish.isEmpty())
+ {
+ if (start.isEmpty() && i > 0)
+ return false;
- if (comparator.compare(slices[i].start, slices[i].finish) > 0)
- return false;
+ if (finish.isEmpty())
+ return i == slices.length - 1;
+ }
+ else
+ {
+ // !finish.isEmpty() is imposed by prior loop
+ if (i > 0 && comparator.compare(slices[i - 1].finish, start) >= 0)
+ return false;
+
+ if (comparator.compare(start, finish) > 0)
+ return false;
+ }
}
return true;
}
@@ -159,13 +165,21 @@ public class ColumnSlice
@Override
public int compare(ColumnSlice s1, ColumnSlice s2)
{
- int c = comparator.compare(s1.start, s2.start);
- if (c != 0)
- return c;
+ if (s1.start.isEmpty() || s2.start.isEmpty())
+ {
+ if (s1.start.isEmpty() != s2.start.isEmpty())
+ return s1.start.isEmpty() ? -1 : 1;
+ }
+ else
+ {
+ int c = comparator.compare(s1.start, s2.start);
+ if (c != 0)
+ return c;
+ }
// For the finish, empty always means greater
return s1.finish.isEmpty() || s2.finish.isEmpty()
- ? s1.finish.isEmpty() ? 1 : s2.finish.isEmpty() ? -1 : 0
+ ? (s1.finish.isEmpty() ? 1 : -1)
: comparator.compare(s1.finish, s2.finish);
}
});
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java b/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
index 0e0643f..77a5dc7 100644
--- a/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
@@ -103,7 +103,7 @@ public class NamesQueryFilter implements IDiskAtomFilter
public Comparator<Cell> getColumnComparator(CellNameType comparator)
{
- return comparator.columnComparator();
+ return comparator.columnComparator(false);
}
@Override
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java b/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
index e24f68b..b8c3e2f 100644
--- a/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
@@ -186,7 +186,7 @@ public class SliceQueryFilter implements IDiskAtomFilter
public Comparator<Cell> getColumnComparator(CellNameType comparator)
{
- return reversed ? comparator.columnReverseComparator() : comparator.columnComparator();
+ return reversed ? comparator.columnReverseComparator() : comparator.columnComparator(false);
}
public void collectReducedColumns(ColumnFamily container, Iterator<Cell> reducedColumns, int gcBefore, long now)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/io/sstable/IndexHelper.java b/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
index 7099a15..b0bbfc4 100644
--- a/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
+++ b/src/java/org/apache/cassandra/io/sstable/IndexHelper.java
@@ -111,8 +111,8 @@ public class IndexHelper
*/
public static int indexFor(Composite name, List<IndexInfo> indexList, CType comparator, boolean reversed, int lastIndex)
{
- if (name.isEmpty() && reversed)
- return indexList.size() - 1;
+ if (name.isEmpty())
+ return lastIndex >= 0 ? lastIndex : reversed ? indexList.size() - 1 : 0;
if (lastIndex >= indexList.size())
return -1;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/io/util/Memory.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/io/util/Memory.java b/src/java/org/apache/cassandra/io/util/Memory.java
index 67dee81..5306433 100644
--- a/src/java/org/apache/cassandra/io/util/Memory.java
+++ b/src/java/org/apache/cassandra/io/util/Memory.java
@@ -22,6 +22,7 @@ import java.nio.ByteOrder;
import com.sun.jna.Native;
import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.utils.FastByteOperations;
import org.apache.cassandra.utils.memory.MemoryUtil;
import sun.misc.Unsafe;
import sun.nio.ch.DirectBuffer;
@@ -273,7 +274,7 @@ public class Memory
long end = memoryOffset + count;
checkPosition(end - 1);
- unsafe.copyMemory(null, peer + memoryOffset, buffer, BYTE_ARRAY_BASE_OFFSET + bufferOffset, count);
+ FastByteOperations.UnsafeOperations.copy(null, peer + memoryOffset, buffer, bufferOffset, count);
}
private void checkPosition(long offset)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/service/StorageProxy.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/StorageProxy.java b/src/java/org/apache/cassandra/service/StorageProxy.java
index 988c623..8d20af4 100644
--- a/src/java/org/apache/cassandra/service/StorageProxy.java
+++ b/src/java/org/apache/cassandra/service/StorageProxy.java
@@ -31,6 +31,7 @@ import com.google.common.base.Predicate;
import com.google.common.cache.CacheLoader;
import com.google.common.collect.*;
import com.google.common.util.concurrent.Uninterruptibles;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -1142,6 +1143,7 @@ public class StorageProxy implements StorageProxyMBean
* Performs the actual reading of a row out of the StorageService, fetching
* a specific set of column names from a given column family.
*/
+ @Inline
public static List<Row> read(List<ReadCommand> commands, ConsistencyLevel consistency_level)
throws UnavailableException, IsBootstrappingException, ReadTimeoutException, InvalidRequestException
{
@@ -1220,6 +1222,7 @@ public class StorageProxy implements StorageProxyMBean
* 4. If the digests (if any) match the data return the data
* 5. else carry out read repair by getting data from all the nodes.
*/
+ @Inline
private static List<Row> fetchRows(List<ReadCommand> initialCommands, ConsistencyLevel consistencyLevel)
throws UnavailableException, ReadTimeoutException
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/thrift/CassandraServer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/thrift/CassandraServer.java b/src/java/org/apache/cassandra/thrift/CassandraServer.java
index 86b5bee..0621db9 100644
--- a/src/java/org/apache/cassandra/thrift/CassandraServer.java
+++ b/src/java/org/apache/cassandra/thrift/CassandraServer.java
@@ -404,7 +404,7 @@ public class CassandraServer implements Cassandra.Iface
if (metadata.isSuper())
{
CellNameType columnType = new SimpleDenseCellNameType(metadata.comparator.subtype(parent.isSetSuper_column() ? 1 : 0));
- SortedSet<CellName> s = new TreeSet<CellName>(columnType);
+ SortedSet<CellName> s = new TreeSet<>(columnType);
for (ByteBuffer bb : predicate.column_names)
s.add(columnType.cellFromByteBuffer(bb));
filter = SuperColumns.fromSCNamesFilter(metadata.comparator, parent.bufferForSuper_column(), new NamesQueryFilter(s));
@@ -2071,11 +2071,14 @@ public class CassandraServer implements Cassandra.Iface
fixOptionalSliceParameters(request.getColumn_slices().get(i));
Composite start = metadata.comparator.fromByteBuffer(request.getColumn_slices().get(i).start);
Composite finish = metadata.comparator.fromByteBuffer(request.getColumn_slices().get(i).finish);
- int compare = metadata.comparator.compare(start, finish);
- if (!request.reversed && compare > 0)
- throw new InvalidRequestException(String.format("Column slice at index %d had start greater than finish", i));
- else if (request.reversed && compare < 0)
- throw new InvalidRequestException(String.format("Reversed column slice at index %d had start less than finish", i));
+ if (!start.isEmpty() && !finish.isEmpty())
+ {
+ int compare = metadata.comparator.compare(start, finish);
+ if (!request.reversed && compare > 0)
+ throw new InvalidRequestException(String.format("Column slice at index %d had start greater than finish", i));
+ else if (request.reversed && compare < 0)
+ throw new InvalidRequestException(String.format("Reversed column slice at index %d had start less than finish", i));
+ }
slices[i] = new ColumnSlice(start, finish);
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/ByteBufferUtil.java b/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
index 420a776..62addfa 100644
--- a/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
+++ b/src/java/org/apache/cassandra/utils/ByteBufferUtil.java
@@ -32,6 +32,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.UUID;
+import net.nicoulaj.compilecommand.annotations.Inline;
import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.io.util.FileDataInput;
import org.apache.cassandra.io.util.FileUtils;
@@ -78,16 +79,19 @@ public class ByteBufferUtil
{
public static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.wrap(new byte[0]);
+ @Inline
public static int compareUnsigned(ByteBuffer o1, ByteBuffer o2)
{
return FastByteOperations.compareUnsigned(o1, o2);
}
+ @Inline
public static int compare(byte[] o1, ByteBuffer o2)
{
return FastByteOperations.compareUnsigned(o1, 0, o1.length, o2);
}
+ @Inline
public static int compare(ByteBuffer o1, byte[] o2)
{
return FastByteOperations.compareUnsigned(o1, o2, 0, o2.length);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/utils/FastByteOperations.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/FastByteOperations.java b/src/java/org/apache/cassandra/utils/FastByteOperations.java
index e60b096..1431fd3 100644
--- a/src/java/org/apache/cassandra/utils/FastByteOperations.java
+++ b/src/java/org/apache/cassandra/utils/FastByteOperations.java
@@ -24,9 +24,9 @@ import java.nio.ByteOrder;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import com.google.common.primitives.Longs;
-import com.google.common.primitives.UnsignedBytes;
+import com.google.common.primitives.*;
+import net.nicoulaj.compilecommand.annotations.Inline;
import sun.misc.Unsafe;
/**
@@ -34,39 +34,43 @@ import sun.misc.Unsafe;
* This is borrowed and slightly modified from Guava's {@link UnsignedBytes}
* class to be able to compare arrays that start at non-zero offsets.
*/
-class FastByteOperations
+public class FastByteOperations
{
/**
* Lexicographically compare two byte arrays.
*/
+ @Inline
public static int compareUnsigned(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2)
{
return BestHolder.BEST.compare(b1, s1, l1, b2, s2, l2);
}
+ @Inline
public static int compareUnsigned(ByteBuffer b1, byte[] b2, int s2, int l2)
{
return BestHolder.BEST.compare(b1, b2, s2, l2);
}
+ @Inline
public static int compareUnsigned(byte[] b1, int s1, int l1, ByteBuffer b2)
{
return -BestHolder.BEST.compare(b2, b1, s1, l1);
}
+ @Inline
public static int compareUnsigned(ByteBuffer b1, ByteBuffer b2)
{
- if (b1 == b2)
- return 0;
return BestHolder.BEST.compare(b1, b2);
}
+ @Inline
public static void copy(ByteBuffer src, int srcPosition, byte[] trg, int trgPosition, int length)
{
BestHolder.BEST.copy(src, srcPosition, trg, trgPosition, length);
}
+ @Inline
public static void copy(ByteBuffer src, int srcPosition, ByteBuffer trg, int trgPosition, int length)
{
BestHolder.BEST.copy(src, srcPosition, trg, trgPosition, length);
@@ -180,122 +184,97 @@ class FastByteOperations
}
}
- static final boolean littleEndian =
- ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN);
-
- /**
- * Returns true if x1 is less than x2, when both values are treated as
- * unsigned.
- */
- static boolean lessThanUnsigned(long x1, long x2)
- {
- return (x1 + Long.MIN_VALUE) < (x2 + Long.MIN_VALUE);
- }
+ static final boolean BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN);
public int compare(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2)
{
- return compareTo(buffer1, BYTE_ARRAY_BASE_OFFSET + offset1, length1, buffer2, BYTE_ARRAY_BASE_OFFSET + offset2, length2);
+ return compareTo(buffer1, BYTE_ARRAY_BASE_OFFSET + offset1, length1,
+ buffer2, BYTE_ARRAY_BASE_OFFSET + offset2, length2);
}
public int compare(ByteBuffer buffer1, byte[] buffer2, int offset2, int length2)
{
- final Object obj1;
- final long offset1;
- final int length1;
+ Object obj1;
+ long offset1;
if (buffer1.hasArray())
{
obj1 = buffer1.array();
- offset1 = BYTE_ARRAY_BASE_OFFSET + buffer1.arrayOffset() + buffer1.position();
- length1 = buffer1.remaining();
+ offset1 = BYTE_ARRAY_BASE_OFFSET + buffer1.arrayOffset();
}
else
{
obj1 = null;
- offset1 = theUnsafe.getLong(buffer1, DIRECT_BUFFER_ADDRESS_OFFSET) + buffer1.position();
- length1 = buffer1.remaining();
+ offset1 = theUnsafe.getLong(buffer1, DIRECT_BUFFER_ADDRESS_OFFSET);
+ }
+ int length1;
+ {
+ int position = buffer1.position();
+ int limit = buffer1.limit();
+ length1 = limit - position;
+ offset1 += position;
}
return compareTo(obj1, offset1, length1, buffer2, BYTE_ARRAY_BASE_OFFSET + offset2, length2);
}
public int compare(ByteBuffer buffer1, ByteBuffer buffer2)
{
- final Object obj1, obj2;
- final long offset1, offset2;
- final int length1, length2;
- if (buffer1.hasArray())
- {
- obj1 = buffer1.array();
- offset1 = BYTE_ARRAY_BASE_OFFSET + buffer1.arrayOffset() + buffer1.position();
- length1 = buffer1.remaining();
- }
- else
- {
- obj1 = null;
- offset1 = theUnsafe.getLong(buffer1, DIRECT_BUFFER_ADDRESS_OFFSET) + buffer1.position();
- length1 = buffer1.remaining();
- }
- if (buffer2.hasArray())
- {
- obj2 = buffer2.array();
- offset2 = BYTE_ARRAY_BASE_OFFSET + buffer2.arrayOffset() + buffer2.position();
- length2 = buffer2.remaining();
- }
- else
- {
- obj2 = null;
- offset2 = theUnsafe.getLong(buffer2, DIRECT_BUFFER_ADDRESS_OFFSET) + buffer2.position();
- length2 = buffer2.remaining();
- }
- return compareTo(obj1, offset1, length1, obj2, offset2, length2);
+ return compareTo(buffer1, buffer2);
}
public void copy(ByteBuffer src, int srcPosition, byte[] trg, int trgPosition, int length)
{
if (src.hasArray())
- {
System.arraycopy(src.array(), src.arrayOffset() + srcPosition, trg, trgPosition, length);
- return;
- }
- long srcOffset = srcPosition + theUnsafe.getLong(src, DIRECT_BUFFER_ADDRESS_OFFSET);
- copy(null, srcOffset, trg, BYTE_ARRAY_BASE_OFFSET + trgPosition, length);
+ else
+ copy(null, srcPosition + theUnsafe.getLong(src, DIRECT_BUFFER_ADDRESS_OFFSET), trg, trgPosition, length);
}
public void copy(ByteBuffer srcBuf, int srcPosition, ByteBuffer trgBuf, int trgPosition, int length)
{
- if (srcBuf.hasArray() && trgBuf.hasArray())
+ Object src;
+ long srcOffset;
+ if (srcBuf.hasArray())
{
- System.arraycopy(srcBuf.array(), srcBuf.arrayOffset() + srcPosition, trgBuf.array(), trgBuf.arrayOffset() + trgPosition, length);
- return;
+ src = srcBuf.array();
+ srcOffset = BYTE_ARRAY_BASE_OFFSET + srcBuf.arrayOffset();
}
- Object src, trg;
- long srcOffset, trgOffset;
- if (srcBuf.isDirect())
+ else
{
- srcOffset = srcPosition + theUnsafe.getLong(srcBuf, DIRECT_BUFFER_ADDRESS_OFFSET);
src = null;
+ srcOffset = theUnsafe.getLong(srcBuf, DIRECT_BUFFER_ADDRESS_OFFSET);
}
+ copy(src, srcOffset + srcPosition, trgBuf, trgPosition, length);
+ }
+
+ @Inline
+ public static void copy(Object src, long srcOffset, ByteBuffer trgBuf, int trgPosition, int length)
+ {
+ if (trgBuf.hasArray())
+ copy(src, srcOffset, trgBuf.array(), trgBuf.arrayOffset() + trgPosition, length);
else
+ copy(src, srcOffset, null, trgPosition + theUnsafe.getLong(trgBuf, DIRECT_BUFFER_ADDRESS_OFFSET), length);
+ }
+
+ @Inline
+ public static void copy(Object src, long srcOffset, byte[] trg, int trgPosition, int length)
+ {
+ if (length <= MIN_COPY_THRESHOLD)
{
- src = srcBuf.array();
- srcOffset = BYTE_ARRAY_BASE_OFFSET + srcBuf.arrayOffset() + srcPosition;
- }
- if (trgBuf.isDirect())
- {
- trgOffset = trgPosition + theUnsafe.getLong(trgBuf, DIRECT_BUFFER_ADDRESS_OFFSET);
- trg = null;
+ for (int i = 0 ; i < length ; i++)
+ trg[trgPosition + i] = theUnsafe.getByte(src, srcOffset + i);
}
else
{
- trg = trgBuf.array();
- trgOffset = BYTE_ARRAY_BASE_OFFSET + trgBuf.arrayOffset() + trgPosition;
+ copy(src, srcOffset, trg, BYTE_ARRAY_BASE_OFFSET + trgPosition, length);
}
- copy(src, srcOffset, trg, trgOffset, length);
}
// 1M, copied from java.nio.Bits (unfortunately a package-private class)
private static final long UNSAFE_COPY_THRESHOLD = 1 << 20;
+ private static final long MIN_COPY_THRESHOLD = 6;
- static void copy(Object src, long srcOffset, Object dst, long dstOffset, long length)
+ @Inline
+ public static void copy(Object src, long srcOffset, Object dst, long dstOffset, long length)
{
while (length > 0) {
long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
@@ -307,6 +286,50 @@ class FastByteOperations
}
}
+ @Inline
+ public static int compareTo(ByteBuffer buffer1, ByteBuffer buffer2)
+ {
+ Object obj1;
+ long offset1;
+ int length1;
+ if (buffer1.hasArray())
+ {
+ obj1 = buffer1.array();
+ offset1 = BYTE_ARRAY_BASE_OFFSET + buffer1.arrayOffset();
+ }
+ else
+ {
+ obj1 = null;
+ offset1 = theUnsafe.getLong(buffer1, DIRECT_BUFFER_ADDRESS_OFFSET);
+ }
+ offset1 += buffer1.position();
+ length1 = buffer1.remaining();
+ return compareTo(obj1, offset1, length1, buffer2);
+ }
+
+ @Inline
+ public static int compareTo(Object buffer1, long offset1, int length1, ByteBuffer buffer)
+ {
+ Object obj2;
+ long offset2;
+
+ int position = buffer.position();
+ int limit = buffer.limit();
+ if (buffer.hasArray())
+ {
+ obj2 = buffer.array();
+ offset2 = BYTE_ARRAY_BASE_OFFSET + buffer.arrayOffset();
+ }
+ else
+ {
+ obj2 = null;
+ offset2 = theUnsafe.getLong(buffer, DIRECT_BUFFER_ADDRESS_OFFSET);
+ }
+ int length2 = limit - position;
+ offset2 += position;
+
+ return compareTo(buffer1, offset1, length1, obj2, offset2, length2);
+ }
/**
* Lexicographically compare two arrays.
@@ -319,65 +342,40 @@ class FastByteOperations
* @param length2 How much to compare from the right buffer
* @return 0 if equal, < 0 if left is less than right, etc.
*/
- public int compareTo(Object buffer1, long memoryOffset1, int length1,
+ @Inline
+ public static int compareTo(Object buffer1, long memoryOffset1, int length1,
Object buffer2, long memoryOffset2, int length2)
{
- // Short circuit equal case
- if (buffer1 == buffer2 && memoryOffset1 == memoryOffset2 && length1 == length2)
- return 0;
-
int minLength = Math.min(length1, length2);
- int minWords = minLength / Longs.BYTES;
/*
* Compare 8 bytes at a time. Benchmarking shows comparing 8 bytes at a
* time is no slower than comparing 4 bytes at a time even on 32-bit.
* On the other hand, it is substantially faster on 64-bit.
*/
-
- int wordComparisons = minWords * Longs.BYTES;
+ int wordComparisons = minLength & ~7;
for (int i = 0; i < wordComparisons ; i += Longs.BYTES)
{
long lw = theUnsafe.getLong(buffer1, memoryOffset1 + (long) i);
long rw = theUnsafe.getLong(buffer2, memoryOffset2 + (long) i);
- long diff = lw ^ rw;
- if (diff != 0)
+ if (lw != rw)
{
- if (!littleEndian)
- return lessThanUnsigned(lw, rw) ? -1 : 1;
-
- // Use binary search
- int n = 0;
- int y;
- int x = (int) diff;
- if (x == 0)
- {
- x = (int) (diff >>> 32);
- n = 32;
- }
-
- y = x << 16;
- if (y == 0)
- n += 16;
- else
- x = y;
-
- y = x << 8;
- if (y == 0)
- n += 8;
- return (int) (((lw >>> n) & 0xFFL) - ((rw >>> n) & 0xFFL));
+ if (BIG_ENDIAN)
+ return UnsignedLongs.compare(lw, rw);
+
+ return UnsignedLongs.compare(Long.reverseBytes(lw), Long.reverseBytes(rw));
}
}
- // The epilogue to cover the last (minLength % 8) elements.
- for (int i = minWords * Longs.BYTES; i < minLength; i++)
+ for (int i = wordComparisons ; i < minLength ; i++)
{
- int result = UnsignedBytes.compare(theUnsafe.getByte(buffer1, memoryOffset1 + i),
- theUnsafe.getByte(buffer2, memoryOffset2 + i));
- if (result != 0)
- return result;
+ int b1 = theUnsafe.getByte(buffer1, memoryOffset1 + i) & 0xFF;
+ int b2 = theUnsafe.getByte(buffer2, memoryOffset2 + i) & 0xFF;
+ if (b1 != b2)
+ return b1 - b2;
}
+
return length1 - length2;
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/utils/MurmurHash.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/MurmurHash.java b/src/java/org/apache/cassandra/utils/MurmurHash.java
index 9dcde6d..bf83681 100644
--- a/src/java/org/apache/cassandra/utils/MurmurHash.java
+++ b/src/java/org/apache/cassandra/utils/MurmurHash.java
@@ -17,6 +17,8 @@
*/
package org.apache.cassandra.utils;
+import net.nicoulaj.compilecommand.annotations.Inline;
+
import java.nio.ByteBuffer;
/**
@@ -170,6 +172,7 @@ public class MurmurHash
return k;
}
+ @Inline
public static void hash3_x64_128(ByteBuffer key, int offset, int length, long seed, long[] result)
{
final int nblocks = length >> 4; // Process as 128-bit blocks.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/utils/btree/NodeBuilder.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/btree/NodeBuilder.java b/src/java/org/apache/cassandra/utils/btree/NodeBuilder.java
index ba6cf21..9d57182 100644
--- a/src/java/org/apache/cassandra/utils/btree/NodeBuilder.java
+++ b/src/java/org/apache/cassandra/utils/btree/NodeBuilder.java
@@ -25,7 +25,6 @@ import java.util.Comparator;
import static org.apache.cassandra.utils.btree.BTree.EMPTY_BRANCH;
import static org.apache.cassandra.utils.btree.BTree.FAN_FACTOR;
-import static org.apache.cassandra.utils.btree.BTree.POSITIVE_INFINITY;
import static org.apache.cassandra.utils.btree.BTree.compare;
import static org.apache.cassandra.utils.btree.BTree.find;
import static org.apache.cassandra.utils.btree.BTree.getKeyEnd;
@@ -145,7 +144,7 @@ final class NodeBuilder
// and simply avoids performing a binary search until we've checked the proceeding key;
// possibly we should disable this check if we determine that it fails more than a handful of times
// during any given builder use to get the best of both worlds
- int c = comparator.compare(copyFrom[i], key);
+ int c = -comparator.compare(key, copyFrom[i]);
if (c >= 0)
{
found = c == 0;
@@ -168,7 +167,7 @@ final class NodeBuilder
return null;
key = next;
}
- else if (i == copyFromKeyEnd && compare(comparator, upperBound, key) <= 0)
+ else if (i == copyFromKeyEnd && compare(comparator, key, upperBound) >= 0)
owns = false;
if (isLeaf(copyFrom))
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/src/java/org/apache/cassandra/utils/memory/MemoryUtil.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/memory/MemoryUtil.java b/src/java/org/apache/cassandra/utils/memory/MemoryUtil.java
index 532d071..129a60b 100644
--- a/src/java/org/apache/cassandra/utils/memory/MemoryUtil.java
+++ b/src/java/org/apache/cassandra/utils/memory/MemoryUtil.java
@@ -22,6 +22,7 @@ import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import com.google.common.primitives.*;
import sun.misc.Unsafe;
public abstract class MemoryUtil
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/test/unit/org/apache/cassandra/db/NativeCellTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/NativeCellTest.java b/test/unit/org/apache/cassandra/db/NativeCellTest.java
index 0d03f55..6a2bf73 100644
--- a/test/unit/org/apache/cassandra/db/NativeCellTest.java
+++ b/test/unit/org/apache/cassandra/db/NativeCellTest.java
@@ -133,6 +133,86 @@ public class NativeCellTest
}
}
+
+ @Test
+ public void testComparator()
+ {
+
+ Random rand = ThreadLocalRandom.current();
+ for (Name test : TESTS)
+ {
+ byte[] bytes = new byte[7];
+ byte[] bytes2 = new byte[7];
+ rand.nextBytes(bytes);
+ rand.nextBytes(bytes2);
+
+ // test regular Cell
+ Cell buf, nat, buf2, nat2;
+ buf = new BufferCell(test.name, ByteBuffer.wrap(bytes), rand.nextLong());
+ nat = buf.localCopy(metadata, nativeAllocator, group);
+
+ buf2 = new BufferCell(test.name, ByteBuffer.wrap(bytes2), rand.nextLong());
+ nat2 = buf2.localCopy(metadata, nativeAllocator, group);
+
+ assert test.type.compare(buf.name(), nat.name()) == 0;
+ assert test.type.compare(buf2.name(), nat2.name()) == 0;
+
+ int val = test.type.compare(buf.name(), buf2.name());
+ assert test.type.compare(nat.name(), nat2.name()) == val;
+ assert test.type.compare(nat.name(), buf2.name()) == val;
+ assert test.type.compare(buf.name(), nat2.name()) == val;
+
+
+ // test DeletedCell
+ buf = new BufferDeletedCell(test.name, rand.nextInt(100000), rand.nextLong());
+ nat = buf.localCopy(metadata, nativeAllocator, group);
+ buf2 = new BufferDeletedCell(test.name, rand.nextInt(100000), rand.nextLong());
+ nat2 = buf2.localCopy(metadata, nativeAllocator, group);
+
+ assert test.type.compare(buf.name(), nat.name()) == 0;
+ assert test.type.compare(buf2.name(), nat2.name()) == 0;
+
+ val = test.type.compare(buf.name(), buf2.name());
+ assert test.type.compare(nat.name(), nat2.name()) == val;
+ assert test.type.compare(nat.name(), buf2.name()) == val;
+ assert test.type.compare(buf.name(), nat2.name()) == val;
+
+
+
+ // test ExpiringCell
+ buf = new BufferExpiringCell(test.name, ByteBuffer.wrap(bytes), rand.nextLong(), rand.nextInt(100000));
+ nat = buf.localCopy(metadata, nativeAllocator, group);
+
+ buf2 = new BufferExpiringCell(test.name, ByteBuffer.wrap(bytes2), rand.nextLong(), rand.nextInt(100000));
+ nat2 = buf2.localCopy(metadata, nativeAllocator, group);
+
+ assert test.type.compare(buf.name(), nat.name()) == 0;
+ assert test.type.compare(buf2.name(), nat2.name()) == 0;
+
+ val = test.type.compare(buf.name(), buf2.name());
+ assert test.type.compare(nat.name(), nat2.name()) == val;
+ assert test.type.compare(nat.name(), buf2.name()) == val;
+ assert test.type.compare(buf.name(), nat2.name()) == val;
+
+
+ // test CounterCell
+ buf = new BufferCounterCell(test.name, CounterContext.instance().createLocal(rand.nextLong()), rand.nextLong(), rand.nextInt(100000));
+ nat = buf.localCopy(metadata, nativeAllocator, group);
+
+ buf2 = new BufferCounterCell(test.name, CounterContext.instance().createLocal(rand.nextLong()), rand.nextLong(), rand.nextInt(100000));
+ nat2 = buf2.localCopy(metadata, nativeAllocator, group);
+
+ assert test.type.compare(buf.name(), nat.name()) == 0;
+ assert test.type.compare(buf2.name(), nat2.name()) == 0;
+
+ val = test.type.compare(buf.name(), buf2.name());
+ assert test.type.compare(nat.name(), nat2.name()) == val;
+ assert test.type.compare(nat.name(), buf2.name()) == val;
+ assert test.type.compare(buf.name(), nat2.name()) == val;
+
+ }
+ }
+
static void test(Name test, Cell buf, Cell nat) throws IOException
{
Assert.assertTrue(buf.equals(nat));
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/test/unit/org/apache/cassandra/db/composites/CTypeTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/composites/CTypeTest.java b/test/unit/org/apache/cassandra/db/composites/CTypeTest.java
index 4bd755b..496a2dc 100644
--- a/test/unit/org/apache/cassandra/db/composites/CTypeTest.java
+++ b/test/unit/org/apache/cassandra/db/composites/CTypeTest.java
@@ -91,15 +91,11 @@ public class CTypeTest
{
CellName a = stype2.makeCellName(UUIDType.instance.fromString("00000000-0000-0000-0000-000000000000"));
CellName z = stype2.makeCellName(UUIDType.instance.fromString("ffffffff-ffff-ffff-ffff-ffffffffffff"));
- Composite empty = Composites.EMPTY;
assert stype2.compare(a,z) < 0;
assert stype2.compare(z,a) > 0;
assert stype2.compare(a,a) == 0;
assert stype2.compare(z,z) == 0;
- assert stype2.compare(empty, a) < 0;
- assert stype2.compare(a,empty) > 0;
- assert stype2.compare(empty, empty) == 0;
}
@@ -108,16 +104,11 @@ public class CTypeTest
{
CellName a = stype1.makeCellName(ByteBufferUtil.bytes("a"));
CellName z = stype1.makeCellName(ByteBufferUtil.bytes("z"));
- Composite empty = Composites.EMPTY;
assert stype1.compare(a,z) < 0;
assert stype1.compare(z,a) > 0;
assert stype1.compare(a,a) == 0;
assert stype1.compare(z,z) == 0;
- assert stype1.compare(empty, a) < 0;
- assert stype1.compare(a,empty) > 0;
- assert stype1.compare(empty, empty) == 0;
-
}
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/e77ea125/test/unit/org/apache/cassandra/db/filter/ColumnSliceTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/filter/ColumnSliceTest.java b/test/unit/org/apache/cassandra/db/filter/ColumnSliceTest.java
index 2dc3744..15f1797 100644
--- a/test/unit/org/apache/cassandra/db/filter/ColumnSliceTest.java
+++ b/test/unit/org/apache/cassandra/db/filter/ColumnSliceTest.java
@@ -382,12 +382,12 @@ public class ColumnSliceTest
private static void assertSlicesValid(ColumnSlice[] slices)
{
- assertTrue("Slices " + toString(slices) + " should be valid", ColumnSlice.validateSlices(slices, simpleIntType));
+ assertTrue("Slices " + toString(slices) + " should be valid", ColumnSlice.validateSlices(slices, simpleIntType, false));
}
private static void assertSlicesInvalid(ColumnSlice[] slices)
{
- assertFalse("Slices " + toString(slices) + " shouldn't be valid", ColumnSlice.validateSlices(slices, simpleIntType));
+ assertFalse("Slices " + toString(slices) + " shouldn't be valid", ColumnSlice.validateSlices(slices, simpleIntType, false));
}
private static void assertSlicesEquals(ColumnSlice[] expected, ColumnSlice[] actual)