Repository: cassandra Updated Branches: refs/heads/cassandra-3.0 715c1513c -> 70819bf77
Make sure sets and maps are always sorted patch by slebresne; reviewed by snazy for CASSANDRA-10162 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/70819bf7 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/70819bf7 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/70819bf7 Branch: refs/heads/cassandra-3.0 Commit: 70819bf77c5a52921f3686eb7db1adeb1e6d0609 Parents: 715c151 Author: Sylvain Lebresne <[email protected]> Authored: Mon Aug 24 14:32:39 2015 +0200 Committer: Sylvain Lebresne <[email protected]> Committed: Wed Aug 26 10:52:35 2015 +0200 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cassandra/auth/CassandraAuthorizer.java | 2 +- .../apache/cassandra/db/marshal/MapType.java | 2 +- .../apache/cassandra/db/marshal/SetType.java | 2 +- .../cassandra/serializers/MapSerializer.java | 29 ++++++++++++++++---- .../cassandra/serializers/SetSerializer.java | 10 +++++-- 6 files changed, 34 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/70819bf7/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 2643bfc..5fb6874 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.0.0-beta2 + * Ensures frozen sets and maps are always sorted (CASSANDRA-10162) * Don't deadlock when flushing CFS backed custom indexes (CASSANDRA-10181) * Fix double flushing of secondary index tables (CASSANDRA-10180) * Fix incorrect handling of range tombstones in thrift (CASSANDRA-10046) http://git-wip-us.apache.org/repos/asf/cassandra/blob/70819bf7/src/java/org/apache/cassandra/auth/CassandraAuthorizer.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/auth/CassandraAuthorizer.java b/src/java/org/apache/cassandra/auth/CassandraAuthorizer.java index 5cdea3f..d98c582 100644 --- a/src/java/org/apache/cassandra/auth/CassandraAuthorizer.java +++ b/src/java/org/apache/cassandra/auth/CassandraAuthorizer.java @@ -417,7 +417,7 @@ public class CassandraAuthorizer implements IAuthorizer return resource.applicablePermissions().contains(Permission.valueOf(s)); } }; - SetSerializer<String> serializer = SetSerializer.getInstance(UTF8Serializer.instance); + SetSerializer<String> serializer = SetSerializer.getInstance(UTF8Serializer.instance, UTF8Type.instance); Set<String> originalPerms = serializer.deserialize(row.getBytes("permissions")); Set<String> filteredPerms = ImmutableSet.copyOf(Iterables.filter(originalPerms, isApplicable)); insertStatement.execute(QueryState.forInternalCalls(), http://git-wip-us.apache.org/repos/asf/cassandra/blob/70819bf7/src/java/org/apache/cassandra/db/marshal/MapType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/MapType.java b/src/java/org/apache/cassandra/db/marshal/MapType.java index 28a4fd5..b1440a5 100644 --- a/src/java/org/apache/cassandra/db/marshal/MapType.java +++ b/src/java/org/apache/cassandra/db/marshal/MapType.java @@ -70,7 +70,7 @@ public class MapType<K, V> extends CollectionType<Map<K, V>> super(Kind.MAP); this.keys = keys; this.values = values; - this.serializer = MapSerializer.getInstance(keys.getSerializer(), values.getSerializer()); + this.serializer = MapSerializer.getInstance(keys.getSerializer(), values.getSerializer(), keys); this.isMultiCell = isMultiCell; } http://git-wip-us.apache.org/repos/asf/cassandra/blob/70819bf7/src/java/org/apache/cassandra/db/marshal/SetType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/SetType.java b/src/java/org/apache/cassandra/db/marshal/SetType.java index 126c6aa..7e94fcb 100644 --- a/src/java/org/apache/cassandra/db/marshal/SetType.java +++ b/src/java/org/apache/cassandra/db/marshal/SetType.java @@ -64,7 +64,7 @@ public class SetType<T> extends CollectionType<Set<T>> { super(Kind.SET); this.elements = elements; - this.serializer = SetSerializer.getInstance(elements.getSerializer()); + this.serializer = SetSerializer.getInstance(elements.getSerializer(), elements); this.isMultiCell = isMultiCell; } http://git-wip-us.apache.org/repos/asf/cassandra/blob/70819bf7/src/java/org/apache/cassandra/serializers/MapSerializer.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/serializers/MapSerializer.java b/src/java/org/apache/cassandra/serializers/MapSerializer.java index 7d81598..6a6965b 100644 --- a/src/java/org/apache/cassandra/serializers/MapSerializer.java +++ b/src/java/org/apache/cassandra/serializers/MapSerializer.java @@ -33,32 +33,49 @@ public class MapSerializer<K, V> extends CollectionSerializer<Map<K, V>> public final TypeSerializer<K> keys; public final TypeSerializer<V> values; + private final Comparator<Pair<ByteBuffer, ByteBuffer>> comparator; - public static synchronized <K, V> MapSerializer<K, V> getInstance(TypeSerializer<K> keys, TypeSerializer<V> values) + public static synchronized <K, V> MapSerializer<K, V> getInstance(TypeSerializer<K> keys, TypeSerializer<V> values, Comparator<ByteBuffer> comparator) { Pair<TypeSerializer<?>, TypeSerializer<?>> p = Pair.<TypeSerializer<?>, TypeSerializer<?>>create(keys, values); MapSerializer<K, V> t = instances.get(p); if (t == null) { - t = new MapSerializer<K, V>(keys, values); + t = new MapSerializer<K, V>(keys, values, comparator); instances.put(p, t); } return t; } - private MapSerializer(TypeSerializer<K> keys, TypeSerializer<V> values) + private MapSerializer(TypeSerializer<K> keys, TypeSerializer<V> values, Comparator<ByteBuffer> comparator) { this.keys = keys; this.values = values; + this.comparator = (p1, p2) -> comparator.compare(p1.left, p2.left); } public List<ByteBuffer> serializeValues(Map<K, V> map) { - List<ByteBuffer> buffers = new ArrayList<>(map.size() * 2); + if (map instanceof SortedMap) + { + List<ByteBuffer> buffers = new ArrayList<>(map.size() * 2); + for (Map.Entry<K, V> entry : map.entrySet()) + { + buffers.add(keys.serialize(entry.getKey())); + buffers.add(values.serialize(entry.getValue())); + } + return buffers; + } + + List<Pair<ByteBuffer, ByteBuffer>> pairs = new ArrayList<>(map.size()); for (Map.Entry<K, V> entry : map.entrySet()) + pairs.add(Pair.create(keys.serialize(entry.getKey()), values.serialize(entry.getValue()))); + Collections.sort(pairs, comparator); + List<ByteBuffer> buffers = new ArrayList<>(pairs.size() * 2); + for (Pair<ByteBuffer, ByteBuffer> p : pairs) { - buffers.add(keys.serialize(entry.getKey())); - buffers.add(values.serialize(entry.getValue())); + buffers.add(p.left); + buffers.add(p.right); } return buffers; } http://git-wip-us.apache.org/repos/asf/cassandra/blob/70819bf7/src/java/org/apache/cassandra/serializers/SetSerializer.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/serializers/SetSerializer.java b/src/java/org/apache/cassandra/serializers/SetSerializer.java index 7108630..167d620 100644 --- a/src/java/org/apache/cassandra/serializers/SetSerializer.java +++ b/src/java/org/apache/cassandra/serializers/SetSerializer.java @@ -28,21 +28,23 @@ public class SetSerializer<T> extends CollectionSerializer<Set<T>> private static final Map<TypeSerializer<?>, SetSerializer> instances = new HashMap<TypeSerializer<?>, SetSerializer>(); public final TypeSerializer<T> elements; + private final Comparator<ByteBuffer> comparator; - public static synchronized <T> SetSerializer<T> getInstance(TypeSerializer<T> elements) + public static synchronized <T> SetSerializer<T> getInstance(TypeSerializer<T> elements, Comparator<ByteBuffer> elementComparator) { SetSerializer<T> t = instances.get(elements); if (t == null) { - t = new SetSerializer<T>(elements); + t = new SetSerializer<T>(elements, elementComparator); instances.put(elements, t); } return t; } - private SetSerializer(TypeSerializer<T> elements) + private SetSerializer(TypeSerializer<T> elements, Comparator<ByteBuffer> comparator) { this.elements = elements; + this.comparator = comparator; } public List<ByteBuffer> serializeValues(Set<T> values) @@ -50,6 +52,8 @@ public class SetSerializer<T> extends CollectionSerializer<Set<T>> List<ByteBuffer> buffers = new ArrayList<>(values.size()); for (T value : values) buffers.add(elements.serialize(value)); + if (!(values instanceof SortedSet)) + Collections.sort(buffers, comparator); return buffers; }
