You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jm...@apache.org on 2014/11/21 17:04:00 UTC

[2/2] cassandra git commit: Remove hidden references to partitioner in Tokens

Remove hidden references to partitioner in Tokens

Patch by blambov; reviewed by jmckenzie for CASSANDRA-8244


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/07893d70
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/07893d70
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/07893d70

Branch: refs/heads/trunk
Commit: 07893d704598f7cbbc316c9a65a8c415e5404dfa
Parents: 68fdb2d
Author: Branimir Lambov <br...@datastax.com>
Authored: Fri Nov 21 07:58:28 2014 -0800
Committer: Joshua McKenzie <jm...@apache.org>
Committed: Fri Nov 21 07:58:28 2014 -0800

----------------------------------------------------------------------
 .../org/apache/cassandra/client/RingCache.java  |   2 +-
 .../cql3/statements/SelectStatement.java        |   2 +-
 .../apache/cassandra/db/ColumnFamilyStore.java  |   6 +-
 .../org/apache/cassandra/db/DataTracker.java    |   2 +-
 .../org/apache/cassandra/db/DecoratedKey.java   |  15 +-
 .../cassandra/db/HintedHandOffManager.java      |   2 +-
 src/java/org/apache/cassandra/db/Memtable.java  |   6 +-
 .../compaction/AbstractCompactionStrategy.java  |   2 +-
 .../db/compaction/CompactionManager.java        |   2 +-
 .../compaction/LeveledCompactionStrategy.java   |   2 +-
 .../AbstractSimplePerColumnSecondaryIndex.java  |   7 -
 .../cassandra/db/index/SecondaryIndex.java      |  12 +-
 .../db/index/composites/CompositesSearcher.java |   2 +-
 .../cassandra/db/index/keys/KeysSearcher.java   |   2 +-
 .../apache/cassandra/dht/AbstractBounds.java    |   6 +-
 .../dht/AbstractByteOrderedPartitioner.java     | 206 ---------------
 .../cassandra/dht/AbstractPartitioner.java      |  31 ---
 .../apache/cassandra/dht/BigIntegerToken.java   |  35 ---
 src/java/org/apache/cassandra/dht/Bounds.java   |  24 +-
 .../cassandra/dht/ByteOrderedPartitioner.java   | 257 ++++++++++++++++++-
 .../org/apache/cassandra/dht/BytesToken.java    |  79 ------
 .../apache/cassandra/dht/ExcludingBounds.java   |  21 +-
 .../org/apache/cassandra/dht/IPartitioner.java  |   9 -
 .../cassandra/dht/IncludingExcludingBounds.java |  22 +-
 .../apache/cassandra/dht/LocalPartitioner.java  |  68 ++++-
 .../org/apache/cassandra/dht/LocalToken.java    |  46 ----
 .../org/apache/cassandra/dht/LongToken.java     |  62 -----
 .../cassandra/dht/Murmur3Partitioner.java       |  66 ++++-
 .../dht/OrderPreservingPartitioner.java         |  31 ++-
 .../apache/cassandra/dht/RandomPartitioner.java |  41 ++-
 src/java/org/apache/cassandra/dht/Range.java    |  45 ++--
 .../org/apache/cassandra/dht/RingPosition.java  |   4 +-
 .../org/apache/cassandra/dht/StringToken.java   |  29 ---
 src/java/org/apache/cassandra/dht/Token.java    |  35 ++-
 .../hadoop/AbstractColumnFamilyInputFormat.java |  11 +-
 .../cassandra/io/sstable/CQLSSTableWriter.java  |   2 +-
 .../io/sstable/format/big/BigTableScanner.java  |  14 +-
 .../apache/cassandra/service/StorageProxy.java  |   2 +-
 .../cassandra/thrift/CassandraServer.java       |   8 +-
 .../cassandra/thrift/ThriftValidation.java      |   4 +-
 .../org/apache/cassandra/tools/BulkLoader.java  |   2 +-
 .../org/apache/cassandra/utils/FBUtilities.java |  30 ++-
 .../org/apache/cassandra/utils/MerkleTree.java  |   2 +-
 test/unit/org/apache/cassandra/Util.java        |   1 +
 .../org/apache/cassandra/db/CleanupTest.java    |   2 +-
 .../org/apache/cassandra/db/RowCacheTest.java   |   2 +-
 .../apache/cassandra/db/SystemKeyspaceTest.java |   2 +-
 .../db/compaction/AntiCompactionTest.java       |   8 +-
 .../db/compaction/CompactionsTest.java          |   2 +-
 .../dht/ByteOrderedPartitionerTest.java         |   2 +-
 .../apache/cassandra/dht/KeyCollisionTest.java  |  55 ++--
 .../cassandra/dht/Murmur3PartitionerTest.java   |   2 +-
 .../dht/OrderPreservingPartitionerTest.java     |   2 +-
 .../cassandra/dht/PartitionerTestCase.java      |   5 +
 .../cassandra/dht/RandomPartitionerTest.java    |   2 +-
 .../org/apache/cassandra/dht/RangeTest.java     | 168 ++++++------
 .../cassandra/io/sstable/IndexSummaryTest.java  |   2 +-
 .../cassandra/io/sstable/SSTableReaderTest.java |   4 +-
 .../io/sstable/SSTableScannerTest.java          |   2 +-
 .../locator/NetworkTopologyStrategyTest.java    |   2 +-
 .../locator/OldNetworkTopologyStrategyTest.java |   2 +-
 .../ReplicationStrategyEndpointCacheTest.java   |   2 +-
 .../cassandra/locator/SimpleStrategyTest.java   |   4 +-
 .../cassandra/repair/LocalSyncTaskTest.java     |   2 +-
 .../cassandra/repair/RepairSessionTest.java     |   4 +-
 .../repair/messages/RepairOptionTest.java       |   2 +-
 .../service/LeaveAndBootstrapTest.java          |  15 +-
 .../org/apache/cassandra/service/MoveTest.java  |   7 +-
 .../apache/cassandra/service/RemoveTest.java    |   2 +-
 .../cassandra/service/SerializationsTest.java   |   2 +-
 .../service/StorageServiceServerTest.java       |   8 +-
 .../apache/cassandra/utils/MerkleTreeTest.java  |   3 +-
 72 files changed, 746 insertions(+), 826 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/client/RingCache.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/client/RingCache.java b/src/java/org/apache/cassandra/client/RingCache.java
index d58d5d9..5865cd0 100644
--- a/src/java/org/apache/cassandra/client/RingCache.java
+++ b/src/java/org/apache/cassandra/client/RingCache.java
@@ -75,7 +75,7 @@ public class RingCache
             {
                 Token left = partitioner.getTokenFactory().fromString(range.start_token);
                 Token right = partitioner.getTokenFactory().fromString(range.end_token);
-                Range<Token> r = new Range<Token>(left, right, partitioner);
+                Range<Token> r = new Range<Token>(left, right);
                 for (String host : range.endpoints)
                 {
                     try

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
index 99c2297..9fb636e 100644
--- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
@@ -424,7 +424,7 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
             RowPosition startKey = RowPosition.ForKey.get(startKeyBytes, p);
             RowPosition finishKey = RowPosition.ForKey.get(finishKeyBytes, p);
 
-            if (startKey.compareTo(finishKey) > 0 && !finishKey.isMinimum(p))
+            if (startKey.compareTo(finishKey) > 0 && !finishKey.isMinimum())
                 return null;
 
             if (includeKeyBound(Bound.START))

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
index 999886e..82132ca 100644
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
@@ -1804,7 +1804,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
      */
     public Function<DataTracker.View, List<SSTableReader>> viewFilter(final DecoratedKey key)
     {
-        assert !key.isMinimum(partitioner);
+        assert !key.isMinimum();
         return new Function<DataTracker.View, List<SSTableReader>>()
         {
             public List<SSTableReader> apply(DataTracker.View view)
@@ -1914,7 +1914,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
      */
     private AbstractScanIterator getSequentialIterator(final DataRange range, long now)
     {
-        assert !(range.keyRange() instanceof Range) || !((Range)range.keyRange()).isWrapAround() || range.keyRange().right.isMinimum(partitioner) : range.keyRange();
+        assert !(range.keyRange() instanceof Range) || !((Range)range.keyRange()).isWrapAround() || range.keyRange().right.isMinimum() : range.keyRange();
 
         final ViewFragment view = select(viewFilter(range.keyRange()));
         Tracing.trace("Executing seq scan across {} sstables for {}", view.sstables.size(), range.keyRange().getString(metadata.getKeyValidator()));
@@ -1933,7 +1933,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
                 Row current = iterator.next();
                 DecoratedKey key = current.key;
 
-                if (!range.stopKey().isMinimum(partitioner) && range.stopKey().compareTo(key) < 0)
+                if (!range.stopKey().isMinimum() && range.stopKey().compareTo(key) < 0)
                     return endOfData();
 
                 // skipping outside of assigned range

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/db/DataTracker.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/DataTracker.java b/src/java/org/apache/cassandra/db/DataTracker.java
index f8b9376..5eda67e 100644
--- a/src/java/org/apache/cassandra/db/DataTracker.java
+++ b/src/java/org/apache/cassandra/db/DataTracker.java
@@ -757,7 +757,7 @@ public class DataTracker
 
         public List<SSTableReader> sstablesInBounds(AbstractBounds<RowPosition> rowBounds)
         {
-            RowPosition stopInTree = rowBounds.right.isMinimum(liveMemtables.get(0).cfs.partitioner) ? intervalTree.max() : rowBounds.right;
+            RowPosition stopInTree = rowBounds.right.isMinimum() ? intervalTree.max() : rowBounds.right;
             return intervalTree.search(Interval.<RowPosition, SSTableReader>create(rowBounds.left, stopInTree));
         }
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/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..365d261 100644
--- a/src/java/org/apache/cassandra/db/DecoratedKey.java
+++ b/src/java/org/apache/cassandra/db/DecoratedKey.java
@@ -22,7 +22,7 @@ import java.util.Comparator;
 
 import org.apache.cassandra.dht.IPartitioner;
 import org.apache.cassandra.dht.Token;
-import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.dht.Token.KeyBound;
 import org.apache.cassandra.utils.ByteBufferUtil;
 
 /**
@@ -95,15 +95,20 @@ public abstract class DecoratedKey implements RowPosition
         return cmp == 0 ? ByteBufferUtil.compareUnsigned(key, otherKey.getKey()) : cmp;
     }
 
-    public boolean isMinimum(IPartitioner partitioner)
+    public IPartitioner getPartitioner()
     {
-        // A DecoratedKey can never be the minimum position on the ring
-        return false;
+        return getToken().getPartitioner();
+    }
+
+    public KeyBound minValue()
+    {
+        return getPartitioner().getMinimumToken().minKeyBound();
     }
 
     public boolean isMinimum()
     {
-        return isMinimum(StorageService.getPartitioner());
+        // A DecoratedKey can never be the minimum position on the ring
+        return false;
     }
 
     public RowPosition.Kind kind()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/db/HintedHandOffManager.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/HintedHandOffManager.java b/src/java/org/apache/cassandra/db/HintedHandOffManager.java
index b976ef7..a17a42f 100644
--- a/src/java/org/apache/cassandra/db/HintedHandOffManager.java
+++ b/src/java/org/apache/cassandra/db/HintedHandOffManager.java
@@ -513,7 +513,7 @@ public class HintedHandOffManager implements HintedHandOffManagerMBean
 
         IPartitioner p = StorageService.getPartitioner();
         RowPosition minPos = p.getMinimumToken().minKeyBound();
-        Range<RowPosition> range = new Range<RowPosition>(minPos, minPos, p);
+        Range<RowPosition> range = new Range<RowPosition>(minPos, minPos);
         IDiskAtomFilter filter = new NamesQueryFilter(ImmutableSortedSet.<CellName>of());
         List<Row> rows = hintStore.getRangeSlice(range, null, filter, Integer.MAX_VALUE, System.currentTimeMillis());
         for (Row row : rows)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/db/Memtable.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/Memtable.java b/src/java/org/apache/cassandra/db/Memtable.java
index 565bf04..505d889 100644
--- a/src/java/org/apache/cassandra/db/Memtable.java
+++ b/src/java/org/apache/cassandra/db/Memtable.java
@@ -39,7 +39,7 @@ import org.apache.cassandra.db.commitlog.CommitLog;
 import org.apache.cassandra.db.commitlog.ReplayPosition;
 import org.apache.cassandra.db.composites.CellNameType;
 import org.apache.cassandra.db.index.SecondaryIndexManager;
-import org.apache.cassandra.dht.LongToken;
+import org.apache.cassandra.dht.Murmur3Partitioner.LongToken;
 import org.apache.cassandra.io.sstable.metadata.MetadataCollector;
 import org.apache.cassandra.io.util.DiskAwareRunnable;
 import org.apache.cassandra.service.ActiveRepairService;
@@ -179,7 +179,7 @@ public class Memtable
                 previous = empty;
                 // allocate the row overhead after the fact; this saves over allocating and having to free after, but
                 // means we can overshoot our declared limit.
-                int overhead = (int) (cfs.partitioner.getHeapSizeOf(key.getToken()) + ROW_OVERHEAD_HEAP_SIZE);
+                int overhead = (int) (key.getToken().getHeapSize() + ROW_OVERHEAD_HEAP_SIZE);
                 allocator.onHeap().allocate(overhead, opGroup);
             }
             else
@@ -226,7 +226,7 @@ public class Memtable
     {
         return new Iterator<Map.Entry<DecoratedKey, ColumnFamily>>()
         {
-            private Iterator<? extends Map.Entry<? extends RowPosition, AtomicBTreeColumns>> iter = stopAt.isMinimum(cfs.partitioner)
+            private Iterator<? extends Map.Entry<? extends RowPosition, AtomicBTreeColumns>> iter = stopAt.isMinimum()
                     ? rows.tailMap(startWith).entrySet().iterator()
                     : rows.subMap(startWith, true, stopAt, true).entrySet().iterator();
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/db/compaction/AbstractCompactionStrategy.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/compaction/AbstractCompactionStrategy.java b/src/java/org/apache/cassandra/db/compaction/AbstractCompactionStrategy.java
index 333c609..1d6d2e1 100644
--- a/src/java/org/apache/cassandra/db/compaction/AbstractCompactionStrategy.java
+++ b/src/java/org/apache/cassandra/db/compaction/AbstractCompactionStrategy.java
@@ -385,7 +385,7 @@ public abstract class AbstractCompactionStrategy
             long keys = sstable.estimatedKeys();
             Set<Range<Token>> ranges = new HashSet<Range<Token>>(overlaps.size());
             for (SSTableReader overlap : overlaps)
-                ranges.add(new Range<>(overlap.first.getToken(), overlap.last.getToken(), overlap.partitioner));
+                ranges.add(new Range<>(overlap.first.getToken(), overlap.last.getToken()));
             long remainingKeys = keys - sstable.estimatedKeysForRanges(ranges);
             // next, calculate what percentage of columns we have within those keys
             long columns = sstable.getEstimatedColumnCount().mean() * remainingKeys;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
index 55311a0..a9a4773 100644
--- a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
+++ b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
@@ -412,7 +412,7 @@ public class CompactionManager implements CompactionManagerMBean
             SSTableReader sstable = sstableIterator.next();
             for (Range<Token> r : Range.normalize(ranges))
             {
-                Range<Token> sstableRange = new Range<>(sstable.first.getToken(), sstable.last.getToken(), sstable.partitioner);
+                Range<Token> sstableRange = new Range<>(sstable.first.getToken(), sstable.last.getToken());
                 if (r.contains(sstableRange))
                 {
                     logger.info("SSTable {} fully contained in range {}, mutating repairedAt instead of anticompacting", sstable, r);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/db/compaction/LeveledCompactionStrategy.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/compaction/LeveledCompactionStrategy.java b/src/java/org/apache/cassandra/db/compaction/LeveledCompactionStrategy.java
index 3ac16ab..99ae9cd 100644
--- a/src/java/org/apache/cassandra/db/compaction/LeveledCompactionStrategy.java
+++ b/src/java/org/apache/cassandra/db/compaction/LeveledCompactionStrategy.java
@@ -316,7 +316,7 @@ public class LeveledCompactionStrategy extends AbstractCompactionStrategy
             ArrayList<SSTableReader> filtered = new ArrayList<>();
             for (SSTableReader sstable : sstables)
             {
-                Range<Token> sstableRange = new Range<>(sstable.first.getToken(), sstable.last.getToken(), sstable.partitioner);
+                Range<Token> sstableRange = new Range<>(sstable.first.getToken(), sstable.last.getToken());
                 if (range == null || sstableRange.intersects(range))
                     filtered.add(sstable);
             }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/db/index/AbstractSimplePerColumnSecondaryIndex.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/index/AbstractSimplePerColumnSecondaryIndex.java b/src/java/org/apache/cassandra/db/index/AbstractSimplePerColumnSecondaryIndex.java
index 4c398c4..e52e519 100644
--- a/src/java/org/apache/cassandra/db/index/AbstractSimplePerColumnSecondaryIndex.java
+++ b/src/java/org/apache/cassandra/db/index/AbstractSimplePerColumnSecondaryIndex.java
@@ -27,7 +27,6 @@ import org.apache.cassandra.db.composites.CellName;
 import org.apache.cassandra.db.composites.CellNameType;
 import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.dht.LocalPartitioner;
-import org.apache.cassandra.dht.LocalToken;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FBUtilities;
 import org.apache.cassandra.utils.concurrent.OpOrder;
@@ -66,12 +65,6 @@ public abstract class AbstractSimplePerColumnSecondaryIndex extends PerColumnSec
     }
 
     @Override
-    public DecoratedKey getIndexKeyFor(ByteBuffer value)
-    {
-        return new BufferDecoratedKey(new LocalToken(getIndexKeyComparator(), value), value);
-    }
-
-    @Override
     String indexTypeForGrouping()
     {
         return "_internal_";

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/db/index/SecondaryIndex.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/index/SecondaryIndex.java b/src/java/org/apache/cassandra/db/index/SecondaryIndex.java
index b74b84e..2df7f91 100644
--- a/src/java/org/apache/cassandra/db/index/SecondaryIndex.java
+++ b/src/java/org/apache/cassandra/db/index/SecondaryIndex.java
@@ -36,7 +36,10 @@ import org.slf4j.LoggerFactory;
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.ColumnDefinition;
 import org.apache.cassandra.cql3.Operator;
-import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.Cell;
+import org.apache.cassandra.db.ColumnFamilyStore;
+import org.apache.cassandra.db.DecoratedKey;
+import org.apache.cassandra.db.SystemKeyspace;
 import org.apache.cassandra.db.compaction.CompactionManager;
 import org.apache.cassandra.db.composites.CellName;
 import org.apache.cassandra.db.composites.CellNameType;
@@ -46,7 +49,6 @@ import org.apache.cassandra.db.index.keys.KeysIndex;
 import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.db.marshal.BytesType;
 import org.apache.cassandra.db.marshal.LocalByPartionerType;
-import org.apache.cassandra.dht.LocalToken;
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.io.sstable.ReducingKeyIterator;
 import org.apache.cassandra.service.StorageService;
@@ -296,15 +298,13 @@ public abstract class SecondaryIndex
     }
 
     /**
-     * Returns the decoratedKey for a column value
+     * Returns the decoratedKey for a column value. Assumes an index CFS is present.
      * @param value column value
      * @return decorated key
      */
     public DecoratedKey getIndexKeyFor(ByteBuffer value)
     {
-        // FIXME: this imply one column definition per index
-        ByteBuffer name = columnDefs.iterator().next().name.bytes;
-        return new BufferDecoratedKey(new LocalToken(baseCfs.metadata.getColumnDefinition(name).type, value), value);
+        return getIndexCfs().partitioner.decorateKey(value);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/db/index/composites/CompositesSearcher.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/index/composites/CompositesSearcher.java b/src/java/org/apache/cassandra/db/index/composites/CompositesSearcher.java
index 5c1abc9..df4aab0 100644
--- a/src/java/org/apache/cassandra/db/index/composites/CompositesSearcher.java
+++ b/src/java/org/apache/cassandra/db/index/composites/CompositesSearcher.java
@@ -233,7 +233,7 @@ public class CompositesSearcher extends SecondaryIndexSearcher
                         {
                             // Either we're not yet in the range cause the range is start excluding, or we're
                             // past it.
-                            if (!range.right.isMinimum(baseCfs.partitioner) && range.right.compareTo(dk) < 0)
+                            if (!range.right.isMinimum() && range.right.compareTo(dk) < 0)
                             {
                                 logger.trace("Reached end of assigned scan range");
                                 return endOfData();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/db/index/keys/KeysSearcher.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/index/keys/KeysSearcher.java b/src/java/org/apache/cassandra/db/index/keys/KeysSearcher.java
index 4055b7c..3e04674 100644
--- a/src/java/org/apache/cassandra/db/index/keys/KeysSearcher.java
+++ b/src/java/org/apache/cassandra/db/index/keys/KeysSearcher.java
@@ -161,7 +161,7 @@ public class KeysSearcher extends SecondaryIndexSearcher
                         }
 
                         DecoratedKey dk = baseCfs.partitioner.decorateKey(lastSeenKey.toByteBuffer());
-                        if (!range.right.isMinimum(baseCfs.partitioner) && range.right.compareTo(dk) < 0)
+                        if (!range.right.isMinimum() && range.right.compareTo(dk) < 0)
                         {
                             logger.trace("Reached end of assigned scan range");
                             return endOfData();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/AbstractBounds.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/AbstractBounds.java b/src/java/org/apache/cassandra/dht/AbstractBounds.java
index 90eb6b5..c7a3505 100644
--- a/src/java/org/apache/cassandra/dht/AbstractBounds.java
+++ b/src/java/org/apache/cassandra/dht/AbstractBounds.java
@@ -44,13 +44,11 @@ public abstract class AbstractBounds<T extends RingPosition<T>> implements Seria
     public final T left;
     public final T right;
 
-    protected transient final IPartitioner partitioner;
-
-    public AbstractBounds(T left, T right, IPartitioner partitioner)
+    public AbstractBounds(T left, T right)
     {
+        assert left.getPartitioner() == right.getPartitioner();
         this.left = left;
         this.right = right;
-        this.partitioner = partitioner;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/AbstractByteOrderedPartitioner.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/AbstractByteOrderedPartitioner.java b/src/java/org/apache/cassandra/dht/AbstractByteOrderedPartitioner.java
deleted file mode 100644
index d3124ef..0000000
--- a/src/java/org/apache/cassandra/dht/AbstractByteOrderedPartitioner.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.dht;
-
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.util.*;
-
-import org.apache.cassandra.config.*;
-import org.apache.cassandra.db.BufferDecoratedKey;
-import org.apache.commons.lang3.ArrayUtils;
-
-import org.apache.cassandra.db.DecoratedKey;
-import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.db.marshal.BytesType;
-import org.apache.cassandra.exceptions.ConfigurationException;
-import org.apache.cassandra.service.StorageService;
-import org.apache.cassandra.utils.FBUtilities;
-import org.apache.cassandra.utils.Hex;
-import org.apache.cassandra.utils.Pair;
-
-public abstract class AbstractByteOrderedPartitioner extends AbstractPartitioner
-{
-    public static final BytesToken MINIMUM = new BytesToken(ArrayUtils.EMPTY_BYTE_ARRAY);
-
-    public static final BigInteger BYTE_MASK = new BigInteger("255");
-
-    public DecoratedKey decorateKey(ByteBuffer key)
-    {
-        return new BufferDecoratedKey(getToken(key), key);
-    }
-
-    public BytesToken midpoint(Token lt, Token rt)
-    {
-        BytesToken ltoken = (BytesToken) lt;
-        BytesToken rtoken = (BytesToken) rt;
-
-        int sigbytes = Math.max(ltoken.token.length, rtoken.token.length);
-        BigInteger left = bigForBytes(ltoken.token, sigbytes);
-        BigInteger right = bigForBytes(rtoken.token, sigbytes);
-
-        Pair<BigInteger,Boolean> midpair = FBUtilities.midpoint(left, right, 8*sigbytes);
-        return new BytesToken(bytesForBig(midpair.left, sigbytes, midpair.right));
-    }
-
-    /**
-     * Convert a byte array containing the most significant of 'sigbytes' bytes
-     * representing a big-endian magnitude into a BigInteger.
-     */
-    private BigInteger bigForBytes(byte[] bytes, int sigbytes)
-    {
-        byte[] b;
-        if (sigbytes != bytes.length)
-        {
-            b = new byte[sigbytes];
-            System.arraycopy(bytes, 0, b, 0, bytes.length);
-        } else
-            b = bytes;
-        return new BigInteger(1, b);
-    }
-
-    /**
-     * Convert a (positive) BigInteger into a byte array representing its magnitude.
-     * If remainder is true, an additional byte with the high order bit enabled
-     * will be added to the end of the array
-     */
-    private byte[] bytesForBig(BigInteger big, int sigbytes, boolean remainder)
-    {
-        byte[] bytes = new byte[sigbytes + (remainder ? 1 : 0)];
-        if (remainder)
-        {
-            // remaining bit is the most significant in the last byte
-            bytes[sigbytes] |= 0x80;
-        }
-        // bitmask for a single byte
-        for (int i = 0; i < sigbytes; i++)
-        {
-            int maskpos = 8 * (sigbytes - (i + 1));
-            // apply bitmask and get byte value
-            bytes[i] = (byte)(big.and(BYTE_MASK.shiftLeft(maskpos)).shiftRight(maskpos).intValue() & 0xFF);
-        }
-        return bytes;
-    }
-
-    public BytesToken getMinimumToken()
-    {
-        return MINIMUM;
-    }
-
-    public BytesToken getRandomToken()
-    {
-        Random r = new Random();
-        byte[] buffer = new byte[16];
-        r.nextBytes(buffer);
-        return new BytesToken(buffer);
-    }
-
-    private final Token.TokenFactory tokenFactory = new Token.TokenFactory() {
-        public ByteBuffer toByteArray(Token token)
-        {
-            BytesToken bytesToken = (BytesToken) token;
-            return ByteBuffer.wrap(bytesToken.token);
-        }
-
-        public Token fromByteArray(ByteBuffer bytes)
-        {
-            return new BytesToken(bytes);
-        }
-
-        public String toString(Token token)
-        {
-            BytesToken bytesToken = (BytesToken) token;
-            return Hex.bytesToHex(bytesToken.token);
-        }
-
-        public void validate(String token) throws ConfigurationException
-        {
-            try
-            {
-                if (token.length() % 2 == 1)
-                    token = "0" + token;
-                Hex.hexToBytes(token);
-            }
-            catch (NumberFormatException e)
-            {
-                throw new ConfigurationException("Token " + token + " contains non-hex digits");
-            }
-        }
-
-        public Token fromString(String string)
-        {
-            if (string.length() % 2 == 1)
-                string = "0" + string;
-            return new BytesToken(Hex.hexToBytes(string));
-        }
-    };
-
-    public Token.TokenFactory getTokenFactory()
-    {
-        return tokenFactory;
-    }
-
-    public boolean preservesOrder()
-    {
-        return true;
-    }
-
-    public abstract BytesToken getToken(ByteBuffer key);
-
-    public Map<Token, Float> describeOwnership(List<Token> sortedTokens)
-    {
-        // allTokens will contain the count and be returned, sorted_ranges is shorthand for token<->token math.
-        Map<Token, Float> allTokens = new HashMap<Token, Float>();
-        List<Range<Token>> sortedRanges = new ArrayList<Range<Token>>(sortedTokens.size());
-
-        // this initializes the counts to 0 and calcs the ranges in order.
-        Token lastToken = sortedTokens.get(sortedTokens.size() - 1);
-        for (Token node : sortedTokens)
-        {
-            allTokens.put(node, new Float(0.0));
-            sortedRanges.add(new Range<Token>(lastToken, node));
-            lastToken = node;
-        }
-
-        for (String ks : Schema.instance.getKeyspaces())
-        {
-            for (CFMetaData cfmd : Schema.instance.getKSMetaData(ks).cfMetaData().values())
-            {
-                for (Range<Token> r : sortedRanges)
-                {
-                    // Looping over every KS:CF:Range, get the splits size and add it to the count
-                    allTokens.put(r.right, allTokens.get(r.right) + StorageService.instance.getSplits(ks, cfmd.cfName, r, 1).size());
-                }
-            }
-        }
-
-        // Sum every count up and divide count/total for the fractional ownership.
-        Float total = new Float(0.0);
-        for (Float f : allTokens.values())
-            total += f;
-        for (Map.Entry<Token, Float> row : allTokens.entrySet())
-            allTokens.put(row.getKey(), row.getValue() / total);
-
-        return allTokens;
-    }
-
-    public AbstractType<?> getTokenValidator()
-    {
-        return BytesType.instance;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/AbstractPartitioner.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/AbstractPartitioner.java b/src/java/org/apache/cassandra/dht/AbstractPartitioner.java
deleted file mode 100644
index ed077c9..0000000
--- a/src/java/org/apache/cassandra/dht/AbstractPartitioner.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.dht;
-
-abstract class AbstractPartitioner implements IPartitioner
-{
-    @SuppressWarnings("unchecked")
-    public <R extends RingPosition<R>> R minValue(Class<R> klass)
-    {
-        Token minToken = getMinimumToken();
-        if (minToken.getClass().equals(klass))
-            return (R)minToken;
-        else
-            return (R)minToken.minKeyBound();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/BigIntegerToken.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/BigIntegerToken.java b/src/java/org/apache/cassandra/dht/BigIntegerToken.java
deleted file mode 100644
index f050519..0000000
--- a/src/java/org/apache/cassandra/dht/BigIntegerToken.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.dht;
-
-import java.math.BigInteger;
-
-public class BigIntegerToken extends ComparableObjectToken<BigInteger>
-{
-    static final long serialVersionUID = -5833589141319293006L;
-
-    public BigIntegerToken(BigInteger token)
-    {
-        super(token);
-    }
-
-    // convenience method for testing
-    public BigIntegerToken(String token) {
-        this(new BigInteger(token));
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/Bounds.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/Bounds.java b/src/java/org/apache/cassandra/dht/Bounds.java
index 396fc30..8f87553 100644
--- a/src/java/org/apache/cassandra/dht/Bounds.java
+++ b/src/java/org/apache/cassandra/dht/Bounds.java
@@ -21,7 +21,6 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.cassandra.db.RowPosition;
-import org.apache.cassandra.service.StorageService;
 import org.apache.cassandra.utils.Pair;
 
 /**
@@ -31,14 +30,9 @@ public class Bounds<T extends RingPosition<T>> extends AbstractBounds<T>
 {
     public Bounds(T left, T right)
     {
-        this(left, right, StorageService.getPartitioner());
-    }
-
-    public Bounds(T left, T right, IPartitioner partitioner)
-    {
-        super(left, right, partitioner);
+        super(left, right);
         // unlike a Range, a Bounds may not wrap
-        assert left.compareTo(right) <= 0 || right.isMinimum(partitioner) : "[" + left + "," + right + "]";
+        assert left.compareTo(right) <= 0 || right.isMinimum() : "[" + left + "," + right + "]";
     }
 
     public boolean contains(T position)
@@ -46,7 +40,7 @@ public class Bounds<T extends RingPosition<T>> extends AbstractBounds<T>
         // Range.contains doesnt work correctly if left == right (unless both
         // are minimum) because for Range that means a wrapping range that select
         // the whole ring. So we must explicitely handle this case
-        return left.equals(position) || ((right.isMinimum(partitioner) || !left.equals(right)) && Range.contains(left, right, position));
+        return left.equals(position) || ((right.isMinimum() || !left.equals(right)) && Range.contains(left, right, position));
     }
 
     public Pair<AbstractBounds<T>, AbstractBounds<T>> split(T position)
@@ -56,8 +50,8 @@ public class Bounds<T extends RingPosition<T>> extends AbstractBounds<T>
         if (position.equals(right))
             return null;
 
-        AbstractBounds<T> lb = new Bounds<T>(left, position, partitioner);
-        AbstractBounds<T> rb = new Range<T>(position, right, partitioner);
+        AbstractBounds<T> lb = new Bounds<T>(left, position);
+        AbstractBounds<T> rb = new Range<T>(position, right);
         return Pair.create(lb, rb);
     }
 
@@ -101,21 +95,21 @@ public class Bounds<T extends RingPosition<T>> extends AbstractBounds<T>
     /**
      * Compute a bounds of keys corresponding to a given bounds of token.
      */
-    public static Bounds<RowPosition> makeRowBounds(Token left, Token right, IPartitioner partitioner)
+    public static Bounds<RowPosition> makeRowBounds(Token left, Token right)
     {
-        return new Bounds<RowPosition>(left.minKeyBound(partitioner), right.maxKeyBound(partitioner), partitioner);
+        return new Bounds<RowPosition>(left.minKeyBound(), right.maxKeyBound());
     }
 
     @SuppressWarnings("unchecked")
     public AbstractBounds<RowPosition> toRowBounds()
     {
-        return (left instanceof Token) ? makeRowBounds((Token)left, (Token)right, partitioner) : (Bounds<RowPosition>)this;
+        return (left instanceof Token) ? makeRowBounds((Token)left, (Token)right) : (Bounds<RowPosition>)this;
     }
 
     @SuppressWarnings("unchecked")
     public AbstractBounds<Token> toTokenBounds()
     {
-        return (left instanceof RowPosition) ? new Bounds<Token>(((RowPosition)left).getToken(), ((RowPosition)right).getToken(), partitioner) : (Bounds<Token>)this;
+        return (left instanceof RowPosition) ? new Bounds<Token>(((RowPosition)left).getToken(), ((RowPosition)right).getToken()) : (Bounds<Token>)this;
     }
 
     public AbstractBounds<T> withNewRight(T newRight)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/ByteOrderedPartitioner.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/ByteOrderedPartitioner.java b/src/java/org/apache/cassandra/dht/ByteOrderedPartitioner.java
index 888ef35..297e5a6 100644
--- a/src/java/org/apache/cassandra/dht/ByteOrderedPartitioner.java
+++ b/src/java/org/apache/cassandra/dht/ByteOrderedPartitioner.java
@@ -17,14 +17,107 @@
  */
 package org.apache.cassandra.dht;
 
+import org.apache.cassandra.config.CFMetaData;
+import org.apache.cassandra.config.Schema;
+import org.apache.cassandra.db.BufferDecoratedKey;
+import org.apache.cassandra.db.DecoratedKey;
+import org.apache.cassandra.db.marshal.AbstractType;
+import org.apache.cassandra.db.marshal.BytesType;
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.service.StorageService;
+import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.utils.Hex;
 import org.apache.cassandra.utils.ObjectSizes;
+import org.apache.cassandra.utils.Pair;
 
+import org.apache.commons.lang3.ArrayUtils;
+
+import java.math.BigInteger;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
 
-public class ByteOrderedPartitioner extends AbstractByteOrderedPartitioner
+public class ByteOrderedPartitioner implements IPartitioner
 {
+    public static final BytesToken MINIMUM = new BytesToken(ArrayUtils.EMPTY_BYTE_ARRAY);
+
+    public static final BigInteger BYTE_MASK = new BigInteger("255");
+
     private static final long EMPTY_SIZE = ObjectSizes.measure(MINIMUM);
 
+    public static final ByteOrderedPartitioner instance = new ByteOrderedPartitioner();
+
+    public static class BytesToken extends Token
+    {
+        static final long serialVersionUID = -2630749093733680626L;
+
+        final byte[] token;
+
+        public BytesToken(ByteBuffer token)
+        {
+            this(ByteBufferUtil.getArray(token));
+        }
+
+        public BytesToken(byte[] token)
+        {
+            this.token = token;
+        }
+
+        @Override
+        public String toString()
+        {
+            return Hex.bytesToHex(token);
+        }
+
+        public int compareTo(Token other)
+        {
+            BytesToken o = (BytesToken) other;
+            return FBUtilities.compareUnsigned(token, o.token, 0, 0, token.length, o.token.length);
+        }
+
+        @Override
+        public int hashCode()
+        {
+            final int prime = 31;
+            return prime + Arrays.hashCode(token);
+        }
+
+        @Override
+        public boolean equals(Object obj)
+        {
+            if (this == obj)
+                return true;
+            if (!(obj instanceof BytesToken))
+                return false;
+            BytesToken other = (BytesToken) obj;
+
+            return Arrays.equals(token, other.token);
+        }
+
+        @Override
+        public IPartitioner getPartitioner()
+        {
+            return instance;
+        }
+
+        @Override
+        public long getHeapSize()
+        {
+            return EMPTY_SIZE + ObjectSizes.sizeOfArray(token);
+        }
+
+        @Override
+        public Object getTokenValue()
+        {
+            return token;
+        }
+    }
+
     public BytesToken getToken(ByteBuffer key)
     {
         if (key.remaining() == 0)
@@ -32,9 +125,165 @@ public class ByteOrderedPartitioner extends AbstractByteOrderedPartitioner
         return new BytesToken(key);
     }
 
-    @Override
-    public long getHeapSizeOf(Token token)
+    public DecoratedKey decorateKey(ByteBuffer key)
+    {
+        return new BufferDecoratedKey(getToken(key), key);
+    }
+
+    public BytesToken midpoint(Token lt, Token rt)
+    {
+        BytesToken ltoken = (BytesToken) lt;
+        BytesToken rtoken = (BytesToken) rt;
+
+        int sigbytes = Math.max(ltoken.token.length, rtoken.token.length);
+        BigInteger left = bigForBytes(ltoken.token, sigbytes);
+        BigInteger right = bigForBytes(rtoken.token, sigbytes);
+
+        Pair<BigInteger,Boolean> midpair = FBUtilities.midpoint(left, right, 8*sigbytes);
+        return new BytesToken(bytesForBig(midpair.left, sigbytes, midpair.right));
+    }
+
+    /**
+     * Convert a byte array containing the most significant of 'sigbytes' bytes
+     * representing a big-endian magnitude into a BigInteger.
+     */
+    private BigInteger bigForBytes(byte[] bytes, int sigbytes)
+    {
+        byte[] b;
+        if (sigbytes != bytes.length)
+        {
+            b = new byte[sigbytes];
+            System.arraycopy(bytes, 0, b, 0, bytes.length);
+        } else
+            b = bytes;
+        return new BigInteger(1, b);
+    }
+
+    /**
+     * Convert a (positive) BigInteger into a byte array representing its magnitude.
+     * If remainder is true, an additional byte with the high order bit enabled
+     * will be added to the end of the array
+     */
+    private byte[] bytesForBig(BigInteger big, int sigbytes, boolean remainder)
+    {
+        byte[] bytes = new byte[sigbytes + (remainder ? 1 : 0)];
+        if (remainder)
+        {
+            // remaining bit is the most significant in the last byte
+            bytes[sigbytes] |= 0x80;
+        }
+        // bitmask for a single byte
+        for (int i = 0; i < sigbytes; i++)
+        {
+            int maskpos = 8 * (sigbytes - (i + 1));
+            // apply bitmask and get byte value
+            bytes[i] = (byte)(big.and(BYTE_MASK.shiftLeft(maskpos)).shiftRight(maskpos).intValue() & 0xFF);
+        }
+        return bytes;
+    }
+
+    public BytesToken getMinimumToken()
+    {
+        return MINIMUM;
+    }
+
+    public BytesToken getRandomToken()
+    {
+        Random r = new Random();
+        byte[] buffer = new byte[16];
+        r.nextBytes(buffer);
+        return new BytesToken(buffer);
+    }
+
+    private final Token.TokenFactory tokenFactory = new Token.TokenFactory() {
+        public ByteBuffer toByteArray(Token token)
+        {
+            BytesToken bytesToken = (BytesToken) token;
+            return ByteBuffer.wrap(bytesToken.token);
+        }
+
+        public Token fromByteArray(ByteBuffer bytes)
+        {
+            return new BytesToken(bytes);
+        }
+
+        public String toString(Token token)
+        {
+            BytesToken bytesToken = (BytesToken) token;
+            return Hex.bytesToHex(bytesToken.token);
+        }
+
+        public void validate(String token) throws ConfigurationException
+        {
+            try
+            {
+                if (token.length() % 2 == 1)
+                    token = "0" + token;
+                Hex.hexToBytes(token);
+            }
+            catch (NumberFormatException e)
+            {
+                throw new ConfigurationException("Token " + token + " contains non-hex digits");
+            }
+        }
+
+        public Token fromString(String string)
+        {
+            if (string.length() % 2 == 1)
+                string = "0" + string;
+            return new BytesToken(Hex.hexToBytes(string));
+        }
+    };
+
+    public Token.TokenFactory getTokenFactory()
+    {
+        return tokenFactory;
+    }
+
+    public boolean preservesOrder()
+    {
+        return true;
+    }
+
+    public Map<Token, Float> describeOwnership(List<Token> sortedTokens)
+    {
+        // allTokens will contain the count and be returned, sorted_ranges is shorthand for token<->token math.
+        Map<Token, Float> allTokens = new HashMap<Token, Float>();
+        List<Range<Token>> sortedRanges = new ArrayList<Range<Token>>(sortedTokens.size());
+
+        // this initializes the counts to 0 and calcs the ranges in order.
+        Token lastToken = sortedTokens.get(sortedTokens.size() - 1);
+        for (Token node : sortedTokens)
+        {
+            allTokens.put(node, new Float(0.0));
+            sortedRanges.add(new Range<Token>(lastToken, node));
+            lastToken = node;
+        }
+
+        for (String ks : Schema.instance.getKeyspaces())
+        {
+            for (CFMetaData cfmd : Schema.instance.getKSMetaData(ks).cfMetaData().values())
+            {
+                for (Range<Token> r : sortedRanges)
+                {
+                    // Looping over every KS:CF:Range, get the splits size and add it to the count
+                    allTokens.put(r.right, allTokens.get(r.right) + StorageService.instance.getSplits(ks, cfmd.cfName, r, 1).size());
+                }
+            }
+        }
+
+        // Sum every count up and divide count/total for the fractional ownership.
+        Float total = new Float(0.0);
+        for (Float f : allTokens.values())
+            total += f;
+        for (Map.Entry<Token, Float> row : allTokens.entrySet())
+            allTokens.put(row.getKey(), row.getValue() / total);
+
+        return allTokens;
+    }
+
+    public AbstractType<?> getTokenValidator()
     {
-        return EMPTY_SIZE + ObjectSizes.sizeOfArray(((BytesToken) token).token);
+        return BytesType.instance;
     }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/BytesToken.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/BytesToken.java b/src/java/org/apache/cassandra/dht/BytesToken.java
deleted file mode 100644
index b130d36..0000000
--- a/src/java/org/apache/cassandra/dht/BytesToken.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.dht;
-
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-import org.apache.cassandra.utils.ByteBufferUtil;
-import org.apache.cassandra.utils.FBUtilities;
-import org.apache.cassandra.utils.Hex;
-
-public class BytesToken extends Token
-{
-    static final long serialVersionUID = -2630749093733680626L;
-
-    final byte[] token;
-
-    public BytesToken(ByteBuffer token)
-    {
-        this(ByteBufferUtil.getArray(token));
-    }
-
-    public BytesToken(byte[] token)
-    {
-        this.token = token;
-    }
-
-    @Override
-    public String toString()
-    {
-        return Hex.bytesToHex(token);
-    }
-
-    public int compareTo(Token other)
-    {
-        BytesToken o = (BytesToken) other;
-        return FBUtilities.compareUnsigned(token, o.token, 0, 0, token.length, o.token.length);
-    }
-
-    @Override
-    public int hashCode()
-    {
-        final int prime = 31;
-        return prime + Arrays.hashCode(token);
-    }
-
-    @Override
-    public boolean equals(Object obj)
-    {
-        if (this == obj)
-            return true;
-        if (!(obj instanceof BytesToken))
-            return false;
-        BytesToken other = (BytesToken) obj;
-
-        return Arrays.equals(token, other.token);
-    }
-
-    @Override
-    public byte[] getTokenValue()
-    {
-        return token;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/ExcludingBounds.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/ExcludingBounds.java b/src/java/org/apache/cassandra/dht/ExcludingBounds.java
index 33e48b6..f4f313d 100644
--- a/src/java/org/apache/cassandra/dht/ExcludingBounds.java
+++ b/src/java/org/apache/cassandra/dht/ExcludingBounds.java
@@ -31,14 +31,9 @@ public class ExcludingBounds<T extends RingPosition<T>> extends AbstractBounds<T
 {
     public ExcludingBounds(T left, T right)
     {
-        this(left, right, StorageService.getPartitioner());
-    }
-
-    ExcludingBounds(T left, T right, IPartitioner partitioner)
-    {
-        super(left, right, partitioner);
+        super(left, right);
         // unlike a Range, an ExcludingBounds may not wrap, nor be empty
-        assert left.compareTo(right) < 0 || right.isMinimum(partitioner) : "(" + left + "," + right + ")";
+        assert left.compareTo(right) < 0 || right.isMinimum() : "(" + left + "," + right + ")";
     }
 
     public boolean contains(T position)
@@ -51,8 +46,8 @@ public class ExcludingBounds<T extends RingPosition<T>> extends AbstractBounds<T
         assert contains(position) || left.equals(position);
         if (left.equals(position))
             return null;
-        AbstractBounds<T> lb = new Range<T>(left, position, partitioner);
-        AbstractBounds<T> rb = new ExcludingBounds<T>(position, right, partitioner);
+        AbstractBounds<T> lb = new Range<T>(left, position);
+        AbstractBounds<T> rb = new ExcludingBounds<T>(position, right);
         return Pair.create(lb, rb);
     }
 
@@ -90,21 +85,21 @@ public class ExcludingBounds<T extends RingPosition<T>> extends AbstractBounds<T
     /**
      * Compute a bounds of keys corresponding to a given bounds of token.
      */
-    private static ExcludingBounds<RowPosition> makeRowBounds(Token left, Token right, IPartitioner partitioner)
+    private static ExcludingBounds<RowPosition> makeRowBounds(Token left, Token right)
     {
-        return new ExcludingBounds<RowPosition>(left.maxKeyBound(partitioner), right.minKeyBound(partitioner), partitioner);
+        return new ExcludingBounds<RowPosition>(left.maxKeyBound(), right.minKeyBound());
     }
 
     @SuppressWarnings("unchecked")
     public AbstractBounds<RowPosition> toRowBounds()
     {
-        return (left instanceof Token) ? makeRowBounds((Token)left, (Token)right, partitioner) : (ExcludingBounds<RowPosition>)this;
+        return (left instanceof Token) ? makeRowBounds((Token)left, (Token)right) : (ExcludingBounds<RowPosition>)this;
     }
 
     @SuppressWarnings("unchecked")
     public AbstractBounds<Token> toTokenBounds()
     {
-        return (left instanceof RowPosition) ? new ExcludingBounds<Token>(((RowPosition)left).getToken(), ((RowPosition)right).getToken(), partitioner) : (ExcludingBounds<Token>)this;
+        return (left instanceof RowPosition) ? new ExcludingBounds<Token>(((RowPosition)left).getToken(), ((RowPosition)right).getToken()) : (ExcludingBounds<Token>)this;
     }
 
     public AbstractBounds<T> withNewRight(T newRight)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/IPartitioner.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/IPartitioner.java b/src/java/org/apache/cassandra/dht/IPartitioner.java
index 6451535..b22da66 100644
--- a/src/java/org/apache/cassandra/dht/IPartitioner.java
+++ b/src/java/org/apache/cassandra/dht/IPartitioner.java
@@ -56,13 +56,6 @@ public interface IPartitioner
     public Token getToken(ByteBuffer key);
 
     /**
-     *
-     * @param token
-     * @return the on-heap memory used by the provided token
-     */
-    public long getHeapSizeOf(Token token);
-
-    /**
      * @return a randomly generated token
      */
     public Token getRandomToken();
@@ -85,6 +78,4 @@ public interface IPartitioner
     public Map<Token, Float> describeOwnership(List<Token> sortedTokens);
 
     public AbstractType<?> getTokenValidator();
-
-    public <R extends RingPosition<R>> R minValue(Class<R> klass);
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/IncludingExcludingBounds.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/IncludingExcludingBounds.java b/src/java/org/apache/cassandra/dht/IncludingExcludingBounds.java
index e8e9c74..e9801ca 100644
--- a/src/java/org/apache/cassandra/dht/IncludingExcludingBounds.java
+++ b/src/java/org/apache/cassandra/dht/IncludingExcludingBounds.java
@@ -21,7 +21,6 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.cassandra.db.RowPosition;
-import org.apache.cassandra.service.StorageService;
 import org.apache.cassandra.utils.Pair;
 
 /**
@@ -31,15 +30,10 @@ public class IncludingExcludingBounds<T extends RingPosition<T>> extends Abstrac
 {
     public IncludingExcludingBounds(T left, T right)
     {
-        this(left, right, StorageService.getPartitioner());
-    }
-
-    IncludingExcludingBounds(T left, T right, IPartitioner partitioner)
-    {
-        super(left, right, partitioner);
+        super(left, right);
         // unlike a Range, an IncludingExcludingBounds may not wrap, nor have
         // right == left unless the right is the min token
-        assert left.compareTo(right) < 0 || right.isMinimum(partitioner) : "[" + left + "," + right + ")";
+        assert left.compareTo(right) < 0 || right.isMinimum() : "[" + left + "," + right + ")";
     }
 
     public boolean contains(T position)
@@ -50,8 +44,8 @@ public class IncludingExcludingBounds<T extends RingPosition<T>> extends Abstrac
     public Pair<AbstractBounds<T>, AbstractBounds<T>> split(T position)
     {
         assert contains(position);
-        AbstractBounds<T> lb = new Bounds<T>(left, position, partitioner);
-        AbstractBounds<T> rb = new ExcludingBounds<T>(position, right, partitioner);
+        AbstractBounds<T> lb = new Bounds<T>(left, position);
+        AbstractBounds<T> rb = new ExcludingBounds<T>(position, right);
         return Pair.create(lb, rb);
     }
 
@@ -89,21 +83,21 @@ public class IncludingExcludingBounds<T extends RingPosition<T>> extends Abstrac
     /**
      * Compute a bounds of keys corresponding to a given bounds of token.
      */
-    private static IncludingExcludingBounds<RowPosition> makeRowBounds(Token left, Token right, IPartitioner partitioner)
+    private static IncludingExcludingBounds<RowPosition> makeRowBounds(Token left, Token right)
     {
-        return new IncludingExcludingBounds<RowPosition>(left.maxKeyBound(partitioner), right.minKeyBound(partitioner), partitioner);
+        return new IncludingExcludingBounds<RowPosition>(left.maxKeyBound(), right.minKeyBound());
     }
 
     @SuppressWarnings("unchecked")
     public AbstractBounds<RowPosition> toRowBounds()
     {
-        return (left instanceof Token) ? makeRowBounds((Token)left, (Token)right, partitioner) : (IncludingExcludingBounds<RowPosition>)this;
+        return (left instanceof Token) ? makeRowBounds((Token)left, (Token)right) : (IncludingExcludingBounds<RowPosition>)this;
     }
 
     @SuppressWarnings("unchecked")
     public AbstractBounds<Token> toTokenBounds()
     {
-        return (left instanceof RowPosition) ? new IncludingExcludingBounds<Token>(((RowPosition)left).getToken(), ((RowPosition)right).getToken(), partitioner) : (IncludingExcludingBounds<Token>)this;
+        return (left instanceof RowPosition) ? new IncludingExcludingBounds<Token>(((RowPosition)left).getToken(), ((RowPosition)right).getToken()) : (IncludingExcludingBounds<Token>)this;
     }
 
     public AbstractBounds<T> withNewRight(T newRight)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/LocalPartitioner.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/LocalPartitioner.java b/src/java/org/apache/cassandra/dht/LocalPartitioner.java
index 1cbeba4..dfb0e7d 100644
--- a/src/java/org/apache/cassandra/dht/LocalPartitioner.java
+++ b/src/java/org/apache/cassandra/dht/LocalPartitioner.java
@@ -28,11 +28,11 @@ import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.ObjectSizes;
 
-public class LocalPartitioner extends AbstractPartitioner
+public class LocalPartitioner implements IPartitioner
 {
-    private static final long EMPTY_SIZE = ObjectSizes.measure(new LocalToken(null, null));
+    private static final long EMPTY_SIZE = ObjectSizes.measure(new LocalPartitioner(null).new LocalToken(null));
 
-    private final AbstractType<?> comparator;
+    final AbstractType<?> comparator;   // package-private to avoid access workarounds in embedded LocalToken.
 
     public LocalPartitioner(AbstractType<?> comparator)
     {
@@ -51,17 +51,12 @@ public class LocalPartitioner extends AbstractPartitioner
 
     public LocalToken getMinimumToken()
     {
-        return new LocalToken(comparator, ByteBufferUtil.EMPTY_BYTE_BUFFER);
+        return new LocalToken(ByteBufferUtil.EMPTY_BYTE_BUFFER);
     }
 
     public LocalToken getToken(ByteBuffer key)
     {
-        return new LocalToken(comparator, key);
-    }
-
-    public long getHeapSizeOf(Token token)
-    {
-        return EMPTY_SIZE + ObjectSizes.sizeOnHeapOf(((LocalToken) token).token);
+        return new LocalToken(key);
     }
 
     public LocalToken getRandomToken()
@@ -88,4 +83,57 @@ public class LocalPartitioner extends AbstractPartitioner
     {
         return comparator;
     }
+
+    public class LocalToken extends ComparableObjectToken<ByteBuffer>
+    {
+        static final long serialVersionUID = 8437543776403014875L;
+
+        public LocalToken(ByteBuffer token)
+        {
+            super(token);
+        }
+
+        @Override
+        public String toString()
+        {
+            return comparator.getString(token);
+        }
+
+        @Override
+        public int compareTo(Token o)
+        {
+            assert getPartitioner() == o.getPartitioner();
+            return comparator.compare(token, ((LocalToken) o).token);
+        }
+
+        @Override
+        public int hashCode()
+        {
+            final int prime = 31;
+            return prime + token.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj)
+        {
+            if (this == obj)
+                return true;
+            if (!(obj instanceof LocalToken))
+                return false;
+            LocalToken other = (LocalToken) obj;
+            return token.equals(other.token);
+        }
+
+        @Override
+        public IPartitioner getPartitioner()
+        {
+            return LocalPartitioner.this;
+        }
+
+        @Override
+        public long getHeapSize()
+        {
+            return EMPTY_SIZE + ObjectSizes.sizeOnHeapOf(token);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/LocalToken.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/LocalToken.java b/src/java/org/apache/cassandra/dht/LocalToken.java
deleted file mode 100644
index 29e98eb..0000000
--- a/src/java/org/apache/cassandra/dht/LocalToken.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.dht;
-
-import java.nio.ByteBuffer;
-
-import org.apache.cassandra.db.marshal.AbstractType;
-
-public class LocalToken extends ComparableObjectToken<ByteBuffer>
-{
-    static final long serialVersionUID = 8437543776403014875L;
-
-    private final AbstractType<?> comparator;
-
-    public LocalToken(AbstractType<?> comparator, ByteBuffer token)
-    {
-        super(token);
-        this.comparator = comparator;
-    }
-
-    @Override
-    public String toString()
-    {
-        return comparator.getString(token);
-    }
-
-    public int compareTo(Token o)
-    {
-        return comparator.compare(token, ((LocalToken) o).token);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/LongToken.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/LongToken.java b/src/java/org/apache/cassandra/dht/LongToken.java
deleted file mode 100644
index 8d60653..0000000
--- a/src/java/org/apache/cassandra/dht/LongToken.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.dht;
-
-import com.google.common.primitives.Longs;
-
-public class LongToken extends Token
-{
-    static final long serialVersionUID = -5833580143318243006L;
-
-    final long token;
-
-    public LongToken(long token)
-    {
-        this.token = token;
-    }
-
-    public String toString()
-    {
-        return Long.toString(token);
-    }
-
-    public boolean equals(Object obj)
-    {
-        if (this == obj)
-            return true;
-        if (obj == null || this.getClass() != obj.getClass())
-            return false;
-
-        return token == (((LongToken)obj).token);
-    }
-
-    public int hashCode()
-    {
-        return Longs.hashCode(token);
-    }
-
-    public int compareTo(Token o)
-    {
-        return Long.compare(token, ((LongToken) o).token);
-    }
-
-    public Long getTokenValue()
-    {
-        return token;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/Murmur3Partitioner.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/Murmur3Partitioner.java b/src/java/org/apache/cassandra/dht/Murmur3Partitioner.java
index cf91c86..0ff5eeb 100644
--- a/src/java/org/apache/cassandra/dht/Murmur3Partitioner.java
+++ b/src/java/org/apache/cassandra/dht/Murmur3Partitioner.java
@@ -35,16 +35,20 @@ import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.MurmurHash;
 import org.apache.cassandra.utils.ObjectSizes;
 
+import com.google.common.primitives.Longs;
+
 /**
  * This class generates a BigIntegerToken using a Murmur3 hash.
  */
-public class Murmur3Partitioner extends AbstractPartitioner
+public class Murmur3Partitioner implements IPartitioner
 {
     public static final LongToken MINIMUM = new LongToken(Long.MIN_VALUE);
     public static final long MAXIMUM = Long.MAX_VALUE;
 
     private static final int HEAP_SIZE = (int) ObjectSizes.measureDeep(MINIMUM);
 
+    public static final Murmur3Partitioner instance = new Murmur3Partitioner();
+
     public DecoratedKey decorateKey(ByteBuffer key)
     {
         return new BufferDecoratedKey(getToken(key), key);
@@ -82,6 +86,61 @@ public class Murmur3Partitioner extends AbstractPartitioner
         return MINIMUM;
     }
 
+    public static class LongToken extends Token
+    {
+        static final long serialVersionUID = -5833580143318243006L;
+
+        final long token;
+
+        public LongToken(long token)
+        {
+            this.token = token;
+        }
+
+        public String toString()
+        {
+            return Long.toString(token);
+        }
+
+        public boolean equals(Object obj)
+        {
+            if (this == obj)
+                return true;
+            if (obj == null || this.getClass() != obj.getClass())
+                return false;
+
+            return token == (((LongToken)obj).token);
+        }
+
+        public int hashCode()
+        {
+            return Longs.hashCode(token);
+        }
+
+        public int compareTo(Token o)
+        {
+            return Long.compare(token, ((LongToken) o).token);
+        }
+
+        @Override
+        public IPartitioner getPartitioner()
+        {
+            return instance;
+        }
+
+        @Override
+        public long getHeapSize()
+        {
+            return HEAP_SIZE;
+        }
+
+        @Override
+        public Object getTokenValue()
+        {
+            return token;
+        }
+    }
+
     /**
      * Generate the token of a key.
      * Note that we need to ensure all generated token are strictly bigger than MINIMUM.
@@ -98,11 +157,6 @@ public class Murmur3Partitioner extends AbstractPartitioner
         return new LongToken(normalize(hash[0]));
     }
 
-    public long getHeapSizeOf(Token token)
-    {
-        return HEAP_SIZE;
-    }
-
     public LongToken getRandomToken()
     {
         return new LongToken(normalize(ThreadLocalRandom.current().nextLong()));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/OrderPreservingPartitioner.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/OrderPreservingPartitioner.java b/src/java/org/apache/cassandra/dht/OrderPreservingPartitioner.java
index 44d98e0..86ff184 100644
--- a/src/java/org/apache/cassandra/dht/OrderPreservingPartitioner.java
+++ b/src/java/org/apache/cassandra/dht/OrderPreservingPartitioner.java
@@ -35,7 +35,7 @@ import org.apache.cassandra.utils.FBUtilities;
 import org.apache.cassandra.utils.ObjectSizes;
 import org.apache.cassandra.utils.Pair;
 
-public class OrderPreservingPartitioner extends AbstractPartitioner
+public class OrderPreservingPartitioner implements IPartitioner
 {
     public static final StringToken MINIMUM = new StringToken("");
 
@@ -43,6 +43,8 @@ public class OrderPreservingPartitioner extends AbstractPartitioner
 
     private static final long EMPTY_SIZE = ObjectSizes.measure(MINIMUM);
 
+    public static final OrderPreservingPartitioner instance = new OrderPreservingPartitioner();
+
     public DecoratedKey decorateKey(ByteBuffer key)
     {
         return new BufferDecoratedKey(getToken(key), key);
@@ -161,6 +163,28 @@ public class OrderPreservingPartitioner extends AbstractPartitioner
         return true;
     }
 
+    public static class StringToken extends ComparableObjectToken<String>
+    {
+        static final long serialVersionUID = 5464084395277974963L;
+
+        public StringToken(String token)
+        {
+            super(token);
+        }
+
+        @Override
+        public IPartitioner getPartitioner()
+        {
+            return instance;
+        }
+
+        @Override
+        public long getHeapSize()
+        {
+            return EMPTY_SIZE + ObjectSizes.sizeOf(token);
+        }
+    }
+
     public StringToken getToken(ByteBuffer key)
     {
         String skey;
@@ -175,11 +199,6 @@ public class OrderPreservingPartitioner extends AbstractPartitioner
         return new StringToken(skey);
     }
 
-    public long getHeapSizeOf(Token token)
-    {
-        return EMPTY_SIZE + ObjectSizes.sizeOf(((StringToken) token).token);
-    }
-
     public Map<Token, Float> describeOwnership(List<Token> sortedTokens)
     {
         // allTokens will contain the count and be returned, sorted_ranges is shorthand for token<->token math.

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/RandomPartitioner.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/RandomPartitioner.java b/src/java/org/apache/cassandra/dht/RandomPartitioner.java
index fa44f47..eec08b8 100644
--- a/src/java/org/apache/cassandra/dht/RandomPartitioner.java
+++ b/src/java/org/apache/cassandra/dht/RandomPartitioner.java
@@ -22,6 +22,8 @@ import java.math.BigInteger;
 import java.nio.ByteBuffer;
 import java.util.*;
 
+import com.google.common.annotations.VisibleForTesting;
+
 import org.apache.cassandra.db.BufferDecoratedKey;
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.db.DecoratedKey;
@@ -36,13 +38,15 @@ import org.apache.cassandra.utils.Pair;
 /**
  * This class generates a BigIntegerToken using MD5 hash.
  */
-public class RandomPartitioner extends AbstractPartitioner
+public class RandomPartitioner implements IPartitioner
 {
     public static final BigInteger ZERO = new BigInteger("0");
     public static final BigIntegerToken MINIMUM = new BigIntegerToken("-1");
     public static final BigInteger MAXIMUM = new BigInteger("2").pow(127);
 
-    private static final int EMPTY_SIZE = (int) ObjectSizes.measureDeep(new BigIntegerToken(FBUtilities.hashToBigInteger(ByteBuffer.allocate(1))));
+    private static final int HEAP_SIZE = (int) ObjectSizes.measureDeep(new BigIntegerToken(FBUtilities.hashToBigInteger(ByteBuffer.allocate(1))));
+
+    public static final RandomPartitioner instance = new RandomPartitioner();
 
     public DecoratedKey decorateKey(ByteBuffer key)
     {
@@ -122,6 +126,34 @@ public class RandomPartitioner extends AbstractPartitioner
         return false;
     }
 
+    public static class BigIntegerToken extends ComparableObjectToken<BigInteger>
+    {
+        static final long serialVersionUID = -5833589141319293006L;
+
+        public BigIntegerToken(BigInteger token)
+        {
+            super(token);
+        }
+
+        // convenience method for testing
+        @VisibleForTesting
+        public BigIntegerToken(String token) {
+            this(new BigInteger(token));
+        }
+
+        @Override
+        public IPartitioner getPartitioner()
+        {
+            return instance;
+        }
+
+        @Override
+        public long getHeapSize()
+        {
+            return HEAP_SIZE;
+        }
+    }
+
     public BigIntegerToken getToken(ByteBuffer key)
     {
         if (key.remaining() == 0)
@@ -129,11 +161,6 @@ public class RandomPartitioner extends AbstractPartitioner
         return new BigIntegerToken(FBUtilities.hashToBigInteger(key));
     }
 
-    public long getHeapSizeOf(Token token)
-    {
-        return EMPTY_SIZE;
-    }
-
     public Map<Token, Float> describeOwnership(List<Token> sortedTokens)
     {
         Map<Token, Float> ownerships = new HashMap<Token, Float>();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/Range.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/Range.java b/src/java/org/apache/cassandra/dht/Range.java
index 44b76d5..7ab328f 100644
--- a/src/java/org/apache/cassandra/dht/Range.java
+++ b/src/java/org/apache/cassandra/dht/Range.java
@@ -22,7 +22,6 @@ import java.util.*;
 
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.cassandra.db.RowPosition;
-import org.apache.cassandra.service.StorageService;
 import org.apache.cassandra.utils.Pair;
 
 /**
@@ -38,12 +37,7 @@ public class Range<T extends RingPosition<T>> extends AbstractBounds<T> implemen
 
     public Range(T left, T right)
     {
-        this(left, right, StorageService.getPartitioner());
-    }
-
-    public Range(T left, T right, IPartitioner partitioner)
-    {
-        super(left, right, partitioner);
+        super(left, right);
     }
 
     public static <T extends RingPosition<T>> boolean contains(T left, T right, T point)
@@ -173,8 +167,7 @@ public class Range<T extends RingPosition<T>> extends AbstractBounds<T> implemen
             if (!(left.compareTo(that.right) < 0 && that.left.compareTo(right) < 0))
                 return Collections.emptySet();
             return rangeSet(new Range<T>(ObjectUtils.max(this.left, that.left),
-                                         ObjectUtils.min(this.right, that.right),
-                                         partitioner));
+                                         ObjectUtils.min(this.right, that.right)));
         }
         if (thiswraps && thatwraps)
         {
@@ -202,8 +195,8 @@ public class Range<T extends RingPosition<T>> extends AbstractBounds<T> implemen
     {
         Set<Range<T>> intersection = new HashSet<Range<T>>(2);
         if (that.right.compareTo(first.left) > 0)
-            intersection.add(new Range<T>(first.left, that.right, first.partitioner));
-        intersection.add(new Range<T>(that.left, first.right, first.partitioner));
+            intersection.add(new Range<T>(first.left, that.right));
+        intersection.add(new Range<T>(that.left, first.right));
         return Collections.unmodifiableSet(intersection);
     }
 
@@ -211,10 +204,10 @@ public class Range<T extends RingPosition<T>> extends AbstractBounds<T> implemen
     {
         Set<Range<T>> intersection = new HashSet<Range<T>>(2);
         if (other.contains(wrapping.right))
-            intersection.add(new Range<T>(other.left, wrapping.right, wrapping.partitioner));
+            intersection.add(new Range<T>(other.left, wrapping.right));
         // need the extra compareto here because ranges are asymmetrical; wrapping.left _is not_ contained by the wrapping range
         if (other.contains(wrapping.left) && wrapping.left.compareTo(other.right) < 0)
-            intersection.add(new Range<T>(wrapping.left, other.right, wrapping.partitioner));
+            intersection.add(new Range<T>(wrapping.left, other.right));
         return Collections.unmodifiableSet(intersection);
     }
 
@@ -225,20 +218,19 @@ public class Range<T extends RingPosition<T>> extends AbstractBounds<T> implemen
         if (position.equals(left) || position.equals(right))
             return null;
 
-        AbstractBounds<T> lb = new Range<T>(left, position, partitioner);
-        AbstractBounds<T> rb = new Range<T>(position, right, partitioner);
+        AbstractBounds<T> lb = new Range<T>(left, position);
+        AbstractBounds<T> rb = new Range<T>(position, right);
         return Pair.create(lb, rb);
     }
 
     public List<Range<T>> unwrap()
     {
-        @SuppressWarnings("unchecked")
-        T minValue = (T) partitioner.minValue(right.getClass());
+        T minValue = right.minValue();
         if (!isWrapAround() || right.equals(minValue))
             return Arrays.asList(this);
         List<Range<T>> unwrapped = new ArrayList<Range<T>>(2);
-        unwrapped.add(new Range<T>(left, minValue, partitioner));
-        unwrapped.add(new Range<T>(minValue, right, partitioner));
+        unwrapped.add(new Range<T>(left, minValue));
+        unwrapped.add(new Range<T>(minValue, right));
         return unwrapped;
     }
 
@@ -277,9 +269,9 @@ public class Range<T extends RingPosition<T>> extends AbstractBounds<T> implemen
         ArrayList<Range<T>> difference = new ArrayList<Range<T>>(2);
 
         if (!left.equals(contained.left))
-            difference.add(new Range<T>(left, contained.left, partitioner));
+            difference.add(new Range<T>(left, contained.left));
         if (!right.equals(contained.right))
-            difference.add(new Range<T>(contained.right, right, partitioner));
+            difference.add(new Range<T>(contained.right, right));
         return difference;
     }
 
@@ -420,8 +412,7 @@ public class Range<T extends RingPosition<T>> extends AbstractBounds<T> implemen
         Iterator<Range<T>> iter = ranges.iterator();
         Range<T> current = iter.next();
 
-        @SuppressWarnings("unchecked")
-        T min = (T) current.partitioner.minValue(current.left.getClass());
+        T min = (T) current.left.minValue();
         while (iter.hasNext())
         {
             // If current goes to the end of the ring, we're done
@@ -460,21 +451,21 @@ public class Range<T extends RingPosition<T>> extends AbstractBounds<T> implemen
     /**
      * Compute a range of keys corresponding to a given range of token.
      */
-    public static Range<RowPosition> makeRowRange(Token left, Token right, IPartitioner partitioner)
+    public static Range<RowPosition> makeRowRange(Token left, Token right)
     {
-        return new Range<RowPosition>(left.maxKeyBound(partitioner), right.maxKeyBound(partitioner), partitioner);
+        return new Range<RowPosition>(left.maxKeyBound(), right.maxKeyBound());
     }
 
     @SuppressWarnings("unchecked")
     public AbstractBounds<RowPosition> toRowBounds()
     {
-        return (left instanceof Token) ? makeRowRange((Token)left, (Token)right, partitioner) : (Range<RowPosition>)this;
+        return (left instanceof Token) ? makeRowRange((Token)left, (Token)right) : (Range<RowPosition>)this;
     }
 
     @SuppressWarnings("unchecked")
     public AbstractBounds<Token> toTokenBounds()
     {
-        return (left instanceof RowPosition) ? new Range<Token>(((RowPosition)left).getToken(), ((RowPosition)right).getToken(), partitioner) : (Range<Token>)this;
+        return (left instanceof RowPosition) ? new Range<Token>(((RowPosition)left).getToken(), ((RowPosition)right).getToken()) : (Range<Token>)this;
     }
 
     public AbstractBounds<T> withNewRight(T newRight)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/RingPosition.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/RingPosition.java b/src/java/org/apache/cassandra/dht/RingPosition.java
index fefc3b3..f2d83ad 100644
--- a/src/java/org/apache/cassandra/dht/RingPosition.java
+++ b/src/java/org/apache/cassandra/dht/RingPosition.java
@@ -25,5 +25,7 @@ package org.apache.cassandra.dht;
 public interface RingPosition<C extends RingPosition<C>> extends Comparable<C>
 {
     public Token getToken();
-    public boolean isMinimum(IPartitioner partitioner);
+    public IPartitioner getPartitioner();
+    public boolean isMinimum();
+    public C minValue();
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/StringToken.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/StringToken.java b/src/java/org/apache/cassandra/dht/StringToken.java
deleted file mode 100644
index f541313..0000000
--- a/src/java/org/apache/cassandra/dht/StringToken.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.dht;
-
-
-public class StringToken extends ComparableObjectToken<String>
-{
-    static final long serialVersionUID = 5464084395277974963L;
-
-    public StringToken(String token)
-    {
-        super(token);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07893d70/src/java/org/apache/cassandra/dht/Token.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/dht/Token.java b/src/java/org/apache/cassandra/dht/Token.java
index 98babf5..719fd46 100644
--- a/src/java/org/apache/cassandra/dht/Token.java
+++ b/src/java/org/apache/cassandra/dht/Token.java
@@ -72,6 +72,8 @@ public abstract class Token implements RingPosition<Token>, Serializable
         }
     }
 
+    abstract public IPartitioner getPartitioner();
+    abstract public long getHeapSize();
     abstract public Object getTokenValue();
 
     public Token getToken()
@@ -79,14 +81,14 @@ public abstract class Token implements RingPosition<Token>, Serializable
         return this;
     }
 
-    public boolean isMinimum(IPartitioner partitioner)
+    public Token minValue()
     {
-        return this.equals(partitioner.getMinimumToken());
+        return getPartitioner().getMinimumToken();
     }
 
     public boolean isMinimum()
     {
-        return isMinimum(StorageService.getPartitioner());
+        return this.equals(minValue());
     }
 
     /*
@@ -103,17 +105,12 @@ public abstract class Token implements RingPosition<Token>, Serializable
      * Note that those are "fake" keys and should only be used for comparison
      * of other keys, for selection of keys when only a token is known.
      */
-    public KeyBound minKeyBound(IPartitioner partitioner)
-    {
-        return new KeyBound(this, true);
-    }
-
     public KeyBound minKeyBound()
     {
-        return minKeyBound(null);
+        return new KeyBound(this, true);
     }
 
-    public KeyBound maxKeyBound(IPartitioner partitioner)
+    public KeyBound maxKeyBound()
     {
         /*
          * For each token, we needs both minKeyBound and maxKeyBound
@@ -122,16 +119,11 @@ public abstract class Token implements RingPosition<Token>, Serializable
          * simpler to associate the same value for minKeyBound and
          * maxKeyBound for the minimun token.
          */
-        if (isMinimum(partitioner))
+        if (isMinimum())
             return minKeyBound();
         return new KeyBound(this, false);
     }
 
-    public KeyBound maxKeyBound()
-    {
-        return maxKeyBound(StorageService.getPartitioner());
-    }
-
     @SuppressWarnings("unchecked")
     public <R extends RingPosition<R>> R upperBound(Class<R> klass)
     {
@@ -172,14 +164,19 @@ public abstract class Token implements RingPosition<Token>, Serializable
                 return ((pos instanceof KeyBound) && !((KeyBound)pos).isMinimumBound) ? 0 : 1;
         }
 
-        public boolean isMinimum(IPartitioner partitioner)
+        public IPartitioner getPartitioner()
+        {
+            return getToken().getPartitioner();
+        }
+
+        public KeyBound minValue()
         {
-            return getToken().isMinimum(partitioner);
+            return getPartitioner().getMinimumToken().minKeyBound();
         }
 
         public boolean isMinimum()
         {
-            return isMinimum(StorageService.getPartitioner());
+            return getToken().isMinimum();
         }
 
         public RowPosition.Kind kind()