Optimize partitioner tokens

Patch by blambov, reviewed by jmckenzie for CASSANDRA-8230
This commit is contained in:
Joshua McKenzie 2014-11-05 12:17:25 -06:00
parent 82b91aba69
commit 6eef6f7856
10 changed files with 82 additions and 75 deletions

View File

@ -1,4 +1,5 @@
2.1.2
* Optimize partitioner tokens (CASSANDRA-8230)
* Improve compaction of repaired/unrepaired sstables (CASSANDRA-8004)
* Make cache serializers pluggable (CASSANDRA-8096)
* Fix issues with CONTAINS (KEY) queries on secondary indexes

View File

@ -23,7 +23,6 @@ import java.util.*;
import org.apache.cassandra.config.*;
import org.apache.cassandra.db.BufferDecoratedKey;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.cassandra.db.DecoratedKey;
@ -48,35 +47,12 @@ public abstract class AbstractByteOrderedPartitioner extends AbstractPartitioner
public BytesToken midpoint(Token lt, Token rt)
{
AbstractToken<?> ltoken = (AbstractToken<?>) lt;
AbstractToken<?> rtoken = (AbstractToken<?>) rt;
int ll,rl;
ByteBuffer lb,rb;
BytesToken ltoken = (BytesToken) lt;
BytesToken rtoken = (BytesToken) rt;
if(ltoken.token instanceof byte[])
{
ll = ((byte[])ltoken.token).length;
lb = ByteBuffer.wrap(((byte[])ltoken.token));
}
else
{
ll = ((ByteBuffer)ltoken.token).remaining();
lb = (ByteBuffer)ltoken.token;
}
if(rtoken.token instanceof byte[])
{
rl = ((byte[])rtoken.token).length;
rb = ByteBuffer.wrap(((byte[])rtoken.token));
}
else
{
rl = ((ByteBuffer)rtoken.token).remaining();
rb = (ByteBuffer)rtoken.token;
}
int sigbytes = Math.max(ll, rl);
BigInteger left = bigForBytes(lb, sigbytes);
BigInteger right = bigForBytes(rb, sigbytes);
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));
@ -86,10 +62,15 @@ public abstract class AbstractByteOrderedPartitioner extends AbstractPartitioner
* Convert a byte array containing the most significant of 'sigbytes' bytes
* representing a big-endian magnitude into a BigInteger.
*/
private BigInteger bigForBytes(ByteBuffer bytes, int sigbytes)
private BigInteger bigForBytes(byte[] bytes, int sigbytes)
{
byte[] b = new byte[sigbytes];
ByteBufferUtil.arrayCopy(bytes, bytes.position(), b, 0, bytes.remaining());
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);
}

View File

@ -19,7 +19,7 @@ package org.apache.cassandra.dht;
import java.math.BigInteger;
public class BigIntegerToken extends AbstractToken<BigInteger>
public class BigIntegerToken extends ComparableObjectToken<BigInteger>
{
static final long serialVersionUID = -5833589141319293006L;
@ -32,9 +32,4 @@ public class BigIntegerToken extends AbstractToken<BigInteger>
public BigIntegerToken(String token) {
this(new BigInteger(token));
}
public int compareTo(Token o)
{
return token.compareTo(((BigIntegerToken) o).token);
}
}

View File

@ -24,10 +24,12 @@ import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.Hex;
public class BytesToken extends AbstractToken<byte[]>
public class BytesToken extends Token
{
static final long serialVersionUID = -2630749093733680626L;
final byte[] token;
public BytesToken(ByteBuffer token)
{
this(ByteBufferUtil.getArray(token));
@ -35,7 +37,7 @@ public class BytesToken extends AbstractToken<byte[]>
public BytesToken(byte[] token)
{
super(token);
this.token = token;
}
@Override
@ -69,4 +71,10 @@ public class BytesToken extends AbstractToken<byte[]>
return Arrays.equals(token, other.token);
}
@Override
public byte[] getTokenValue()
{
return token;
}
}

View File

@ -17,17 +17,23 @@
*/
package org.apache.cassandra.dht;
abstract class AbstractToken<C> extends Token
abstract class ComparableObjectToken<C extends Comparable<C>> extends Token
{
private static final long serialVersionUID = 1L;
final C token; // Package-private to allow access from subtypes, which should all reside in the dht package.
protected AbstractToken(C token)
protected ComparableObjectToken(C token)
{
this.token = token;
}
@Override
public C getTokenValue()
{
return token;
}
@Override
public String toString()
{
@ -42,7 +48,7 @@ abstract class AbstractToken<C> extends Token
if (obj == null || this.getClass() != obj.getClass())
return false;
return token.equals(((AbstractToken<?>)obj).token);
return token.equals(((ComparableObjectToken<?>)obj).token);
}
@Override
@ -50,4 +56,14 @@ abstract class AbstractToken<C> extends Token
{
return token.hashCode();
}
@Override
@SuppressWarnings("unchecked")
public int compareTo(Token o)
{
if (o.getClass() != getClass())
throw new IllegalArgumentException("Invalid type of Token.compareTo() argument.");
return token.compareTo(((ComparableObjectToken<C>) o).token);
}
}

View File

@ -21,7 +21,7 @@ import java.nio.ByteBuffer;
import org.apache.cassandra.db.marshal.AbstractType;
public class LocalToken extends AbstractToken<ByteBuffer>
public class LocalToken extends ComparableObjectToken<ByteBuffer>
{
static final long serialVersionUID = 8437543776403014875L;
@ -43,23 +43,4 @@ public class LocalToken extends AbstractToken<ByteBuffer>
{
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);
}
}

View File

@ -17,17 +17,46 @@
*/
package org.apache.cassandra.dht;
public class LongToken extends AbstractToken<Long>
import com.google.common.primitives.Longs;
public class LongToken extends Token
{
static final long serialVersionUID = -5833580143318243006L;
public LongToken(Long token)
final long token;
public LongToken(long token)
{
super(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 token.compareTo(((LongToken) o).token);
return Long.compare(token, ((LongToken) o).token);
}
public Long getTokenValue()
{
return token;
}
}

View File

@ -174,8 +174,7 @@ public class Murmur3Partitioner extends AbstractPartitioner
public String toString(Token token)
{
LongToken longToken = (LongToken) token;
return longToken.token.toString();
return token.toString();
}
public void validate(String token) throws ConfigurationException

View File

@ -18,7 +18,7 @@
package org.apache.cassandra.dht;
public class StringToken extends AbstractToken<String>
public class StringToken extends ComparableObjectToken<String>
{
static final long serialVersionUID = 5464084395277974963L;
@ -26,9 +26,4 @@ public class StringToken extends AbstractToken<String>
{
super(token);
}
public int compareTo(Token o)
{
return token.compareTo(((StringToken) o).token);
}
}

View File

@ -72,6 +72,8 @@ public abstract class Token implements RingPosition<Token>, Serializable
}
}
abstract public Object getTokenValue();
public Token getToken()
{
return this;