Fix AbstractTokenTreeBuilder#serializedSize() when there is a single leaf and 
overflow collisions

patch by Jordan West; reviewed by jasobrown for CASSANDRA-13869


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

Branch: refs/heads/trunk
Commit: 436761ed6afbfdc333c6642f6b4418d44712a0b7
Parents: 2a93c22
Author: Jordan West <jorda...@gmail.com>
Authored: Wed Sep 13 23:37:02 2017 -0700
Committer: Jason Brown <jasedbr...@gmail.com>
Committed: Fri Sep 15 14:05:02 2017 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../sasi/disk/AbstractTokenTreeBuilder.java     |  8 +++++-
 .../index/sasi/disk/TokenTreeBuilder.java       |  6 ++--
 .../index/sasi/disk/TokenTreeTest.java          | 30 +++++++++++++-------
 4 files changed, 31 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/436761ed/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 33055e5..f0c05bf 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.11.1
+ * AbstractTokenTreeBuilder#serializedSize returns wrong value when there is a 
single leaf and overflow collisions (CASSANDRA-13869)
  * Add a compaction option to TWCS to ignore sstables overlapping checks 
(CASSANDRA-13418)
  * BTree.Builder memory leak (CASSANDRA-13754)
  * Revert CASSANDRA-10368 of supporting non-pk column filtering due to 
correctness (CASSANDRA-13798)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/436761ed/src/java/org/apache/cassandra/index/sasi/disk/AbstractTokenTreeBuilder.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/index/sasi/disk/AbstractTokenTreeBuilder.java 
b/src/java/org/apache/cassandra/index/sasi/disk/AbstractTokenTreeBuilder.java
index 18994de..ae1024f 100644
--- 
a/src/java/org/apache/cassandra/index/sasi/disk/AbstractTokenTreeBuilder.java
+++ 
b/src/java/org/apache/cassandra/index/sasi/disk/AbstractTokenTreeBuilder.java
@@ -65,7 +65,9 @@ public abstract class AbstractTokenTreeBuilder implements 
TokenTreeBuilder
     public int serializedSize()
     {
         if (numBlocks == 1)
-            return (BLOCK_HEADER_BYTES + ((int) tokenCount * 16));
+            return BLOCK_HEADER_BYTES +
+                   ((int) tokenCount * BLOCK_ENTRY_BYTES) +
+                   (((Leaf) root).overflowCollisionCount() * 
OVERFLOW_ENTRY_BYTES);
         else
             return numBlocks * BLOCK_BYTES;
     }
@@ -263,6 +265,10 @@ public abstract class AbstractTokenTreeBuilder implements 
TokenTreeBuilder
             return 0;
         }
 
+        public int overflowCollisionCount() {
+            return overflowCollisions == null ? 0 : overflowCollisions.size();
+        }
+
         protected void serializeOverflowCollisions(ByteBuffer buf)
         {
             if (overflowCollisions != null)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/436761ed/src/java/org/apache/cassandra/index/sasi/disk/TokenTreeBuilder.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/index/sasi/disk/TokenTreeBuilder.java 
b/src/java/org/apache/cassandra/index/sasi/disk/TokenTreeBuilder.java
index 2210964..29cecc8 100644
--- a/src/java/org/apache/cassandra/index/sasi/disk/TokenTreeBuilder.java
+++ b/src/java/org/apache/cassandra/index/sasi/disk/TokenTreeBuilder.java
@@ -29,9 +29,11 @@ public interface TokenTreeBuilder extends 
Iterable<Pair<Long, LongSet>>
 {
     int BLOCK_BYTES = 4096;
     int BLOCK_HEADER_BYTES = 64;
+    int BLOCK_ENTRY_BYTES = 2 * Long.BYTES;
     int OVERFLOW_TRAILER_BYTES = 64;
-    int OVERFLOW_TRAILER_CAPACITY = OVERFLOW_TRAILER_BYTES / 8;
-    int TOKENS_PER_BLOCK = (BLOCK_BYTES - BLOCK_HEADER_BYTES - 
OVERFLOW_TRAILER_BYTES) / 16;
+    int OVERFLOW_ENTRY_BYTES = Long.BYTES;
+    int OVERFLOW_TRAILER_CAPACITY = OVERFLOW_TRAILER_BYTES / 
OVERFLOW_ENTRY_BYTES;
+    int TOKENS_PER_BLOCK = (BLOCK_BYTES - BLOCK_HEADER_BYTES - 
OVERFLOW_TRAILER_BYTES) / BLOCK_ENTRY_BYTES;
     long MAX_OFFSET = (1L << 47) - 1; // 48 bits for (signed) offset
     byte LAST_LEAF_SHIFT = 1;
     byte SHARED_HEADER_BYTES = 19;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/436761ed/test/unit/org/apache/cassandra/index/sasi/disk/TokenTreeTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/index/sasi/disk/TokenTreeTest.java 
b/test/unit/org/apache/cassandra/index/sasi/disk/TokenTreeTest.java
index 927e165..3d0850a 100644
--- a/test/unit/org/apache/cassandra/index/sasi/disk/TokenTreeTest.java
+++ b/test/unit/org/apache/cassandra/index/sasi/disk/TokenTreeTest.java
@@ -87,25 +87,29 @@ public class TokenTreeTest
                 put(i, singleOffset);
     }};
 
-    final static SortedMap<Long, LongSet> collidingTokensMap = new 
TreeMap<Long, LongSet>()
-    {{
-            put(1L, singleOffset); put(7L, singleOffset); put(8L, 
singleOffset);
-    }};
+    @FunctionalInterface
+    private static interface CheckedConsumer<C> {
+        public void accept(C c) throws Exception;
+    }
 
-    final static SortedMap<Long, LongSet> tokens = bigTokensMap;
+    final static List<SortedMap<Long, LongSet>> tokenMaps = 
Arrays.asList(simpleTokenMap, bigTokensMap);
+    private void forAllTokenMaps(CheckedConsumer<SortedMap<Long, LongSet>> c) 
throws Exception {
+        for (SortedMap<Long, LongSet> tokens : tokenMaps)
+            c.accept(tokens);
+    }
 
     final static SequentialWriterOption DEFAULT_OPT = 
SequentialWriterOption.newBuilder().bufferSize(4096).build();
 
     @Test
     public void testSerializedSizeDynamic() throws Exception
     {
-        testSerializedSize(new DynamicTokenTreeBuilder(tokens));
+        forAllTokenMaps(tokens -> testSerializedSize(new 
DynamicTokenTreeBuilder(tokens)));
     }
 
     @Test
     public void testSerializedSizeStatic() throws Exception
     {
-        testSerializedSize(new StaticTokenTreeBuilder(new 
FakeCombinedTerm(tokens)));
+        forAllTokenMaps(tokens -> testSerializedSize(new 
StaticTokenTreeBuilder(new FakeCombinedTerm(tokens))));
     }
 
 
@@ -129,13 +133,14 @@ public class TokenTreeTest
     @Test
     public void buildSerializeAndIterateDynamic() throws Exception
     {
-        buildSerializeAndIterate(new DynamicTokenTreeBuilder(simpleTokenMap), 
simpleTokenMap);
+        forAllTokenMaps(tokens -> buildSerializeAndIterate(new 
DynamicTokenTreeBuilder(tokens), tokens));
     }
 
     @Test
     public void buildSerializeAndIterateStatic() throws Exception
     {
-        buildSerializeAndIterate(new StaticTokenTreeBuilder(new 
FakeCombinedTerm(tokens)), tokens);
+        forAllTokenMaps(tokens ->
+                        buildSerializeAndIterate(new 
StaticTokenTreeBuilder(new FakeCombinedTerm(tokens)), tokens));
     }
 
 
@@ -207,15 +212,18 @@ public class TokenTreeTest
     @Test
     public void buildSerializeIterateAndSkipDynamic() throws Exception
     {
-        buildSerializeIterateAndSkip(new DynamicTokenTreeBuilder(tokens), 
tokens);
+        forAllTokenMaps(tokens -> buildSerializeIterateAndSkip(new 
DynamicTokenTreeBuilder(tokens), tokens));
     }
 
     @Test
     public void buildSerializeIterateAndSkipStatic() throws Exception
     {
-        buildSerializeIterateAndSkip(new StaticTokenTreeBuilder(new 
FakeCombinedTerm(tokens)), tokens);
+        forAllTokenMaps(tokens ->
+                        buildSerializeIterateAndSkip(new 
StaticTokenTreeBuilder(new FakeCombinedTerm(tokens)), tokens));
     }
 
+    // works with maps other than bigTokensMap but skips to a rather large 
token
+    // so likely for maps other than bigTokensMap skipping is not tested by 
this.
     public void buildSerializeIterateAndSkip(TokenTreeBuilder builder, 
SortedMap<Long, LongSet> tokens) throws Exception
     {
         builder.finish();


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to