Fix serialization of AbstractBounds patch by Sylvain Lebresne; reviewed by Benjamin Lerer for CASSANDRA-9775
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/bd7d1198 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/bd7d1198 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/bd7d1198 Branch: refs/heads/trunk Commit: bd7d1198ac1e02785e912c7cfbb504ddaab6bb93 Parents: 028df72 Author: Sylvain Lebresne <[email protected]> Authored: Wed Aug 5 12:21:24 2015 +0200 Committer: blerer <[email protected]> Committed: Wed Aug 5 12:21:24 2015 +0200 ---------------------------------------------------------------------- src/java/org/apache/cassandra/db/DataRange.java | 14 ++++- .../apache/cassandra/dht/AbstractBounds.java | 58 +++++++++++++++++--- 2 files changed, 61 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/bd7d1198/src/java/org/apache/cassandra/db/DataRange.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/DataRange.java b/src/java/org/apache/cassandra/db/DataRange.java index 023f572..79b2448 100644 --- a/src/java/org/apache/cassandra/db/DataRange.java +++ b/src/java/org/apache/cassandra/db/DataRange.java @@ -42,7 +42,7 @@ public class DataRange { public static final Serializer serializer = new Serializer(); - private final AbstractBounds<PartitionPosition> keyRange; + protected final AbstractBounds<PartitionPosition> keyRange; protected final ClusteringIndexFilter clusteringIndexFilter; /** @@ -201,7 +201,7 @@ public class DataRange * @param range the range of partition keys to query. * @param comparator the comparator for the table queried. * @param lastReturned the clustering for the last result returned by the previous page, i.e. the result we want to start our new page - * from. This last returned must <b>must</b> correspond to left bound of {@code range} (in other words, {@code range.left} must be the + * from. This last returned <b>must</b> correspond to left bound of {@code range} (in other words, {@code range.left} must be the * partition key for that {@code lastReturned} result). * @param inclusive whether or not we want to include the {@code lastReturned} in the newly returned page of results. * @@ -354,6 +354,16 @@ public class DataRange { return false; } + + @Override + public String toString(CFMetaData metadata) + { + return String.format("range=%s pfilter=%s lastReturned=%s (%s)", + keyRange.getString(metadata.getKeyValidator()), + clusteringIndexFilter.toString(metadata), + lastReturned.toString(metadata), + inclusive ? "included" : "excluded"); + } } public static class Serializer http://git-wip-us.apache.org/repos/asf/cassandra/blob/bd7d1198/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 d9a0c62..9e74eb8 100644 --- a/src/java/org/apache/cassandra/dht/AbstractBounds.java +++ b/src/java/org/apache/cassandra/dht/AbstractBounds.java @@ -27,6 +27,7 @@ import org.apache.cassandra.db.PartitionPosition; import org.apache.cassandra.db.TypeSizes; import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.io.util.DataOutputPlus; +import org.apache.cassandra.net.MessagingService; import org.apache.cassandra.utils.Pair; public abstract class AbstractBounds<T extends RingPosition<T>> implements Serializable @@ -119,8 +120,13 @@ public abstract class AbstractBounds<T extends RingPosition<T>> implements Seria public static class AbstractBoundsSerializer<T extends RingPosition<T>> implements IPartitionerDependentSerializer<AbstractBounds<T>> { + private static final int IS_TOKEN_FLAG = 0x01; + private static final int START_INCLUSIVE_FLAG = 0x02; + private static final int END_INCLUSIVE_FLAG = 0x04; + IPartitionerDependentSerializer<T> serializer; + // Use for pre-3.0 protocol private static int kindInt(AbstractBounds<?> ab) { int kind = ab instanceof Range ? Type.RANGE.ordinal() : Type.BOUNDS.ordinal(); @@ -129,6 +135,19 @@ public abstract class AbstractBounds<T extends RingPosition<T>> implements Seria return kind; } + // For from 3.0 onwards + private static int kindFlags(AbstractBounds<?> ab) + { + int flags = 0; + if (ab.left instanceof Token) + flags |= IS_TOKEN_FLAG; + if (ab.isStartInclusive()) + flags |= START_INCLUSIVE_FLAG; + if (ab.isEndInclusive()) + flags |= END_INCLUSIVE_FLAG; + return flags; + } + public AbstractBoundsSerializer(IPartitionerDependentSerializer<T> serializer) { this.serializer = serializer; @@ -140,30 +159,51 @@ public abstract class AbstractBounds<T extends RingPosition<T>> implements Seria * The first int tells us if it's a range or bounds (depending on the value) _and_ if it's tokens or keys (depending on the * sign). We use negative kind for keys so as to preserve the serialization of token from older version. */ - out.writeInt(kindInt(range)); + if (version < MessagingService.VERSION_30) + out.writeInt(kindInt(range)); + else + out.writeByte(kindFlags(range)); serializer.serialize(range.left, out, version); serializer.serialize(range.right, out, version); } public AbstractBounds<T> deserialize(DataInput in, IPartitioner p, int version) throws IOException { - int kind = in.readInt(); - boolean isToken = kind >= 0; - if (!isToken) - kind = -(kind+1); + boolean isToken, startInclusive, endInclusive; + if (version < MessagingService.VERSION_30) + { + int kind = in.readInt(); + isToken = kind >= 0; + if (!isToken) + kind = -(kind+1); + + // Pre-3.0, everything that wasa not a Range was (wrongly) serialized as a Bound; + startInclusive = kind != Type.RANGE.ordinal(); + endInclusive = true; + } + else + { + int flags = in.readUnsignedByte(); + isToken = (flags & IS_TOKEN_FLAG) != 0; + startInclusive = (flags & START_INCLUSIVE_FLAG) != 0; + endInclusive = (flags & END_INCLUSIVE_FLAG) != 0; + } T left = serializer.deserialize(in, p, version); T right = serializer.deserialize(in, p, version); assert isToken == left instanceof Token; - if (kind == Type.RANGE.ordinal()) - return new Range<T>(left, right); - return new Bounds<T>(left, right); + if (startInclusive) + return endInclusive ? new Bounds<T>(left, right) : new IncludingExcludingBounds<T>(left, right); + else + return endInclusive ? new Range<T>(left, right) : new ExcludingBounds<T>(left, right); } public long serializedSize(AbstractBounds<T> ab, int version) { - int size = TypeSizes.sizeof(kindInt(ab)); + int size = version < MessagingService.VERSION_30 + ? TypeSizes.sizeof(kindInt(ab)) + : 1; size += serializer.serializedSize(ab.left, version); size += serializer.serializedSize(ab.right, version); return size;
