Fix IllegalArgumentException when upgrading from 1.2 with SC

patch by slebresne; reviewed by vijay2win for CASSANDRA-6733


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

Branch: refs/heads/trunk
Commit: 0ff7f9969a3f3315eb2fb7e115d72d37dda05157
Parents: 6137b38
Author: Sylvain Lebresne <sylv...@datastax.com>
Authored: Tue Mar 4 11:30:54 2014 +0100
Committer: Sylvain Lebresne <sylv...@datastax.com>
Committed: Tue Mar 4 11:30:54 2014 +0100

----------------------------------------------------------------------
 CHANGES.txt                                     |  2 +
 .../db/columniterator/IndexedSliceReader.java   | 44 +++++++++++++++++---
 .../db/columniterator/SSTableNamesIterator.java |  6 ++-
 3 files changed, 45 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/0ff7f996/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 41c89e1..8eb10cd 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -30,6 +30,8 @@
  * Fix NPE on BulkLoader caused by losing StreamEvent (CASSANDRA-6636)
  * Fix truncating compression metadata (CASSANDRA-6791)
  * Fix UPDATE updating PRIMARY KEY columns implicitly (CASSANDRA-6782)
+ * Fix IllegalArgumentException when updating from 1.2 with SuperColumns
+   (CASSANDRA-6733)
 Merged from 1.2:
  * Add CMSClassUnloadingEnabled JVM option (CASSANDRA-6541)
  * Catch memtable flush exceptions during shutdown (CASSANDRA-6735)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/0ff7f996/src/java/org/apache/cassandra/db/columniterator/IndexedSliceReader.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/db/columniterator/IndexedSliceReader.java 
b/src/java/org/apache/cassandra/db/columniterator/IndexedSliceReader.java
index 036d0cf..b6aa085 100644
--- a/src/java/org/apache/cassandra/db/columniterator/IndexedSliceReader.java
+++ b/src/java/org/apache/cassandra/db/columniterator/IndexedSliceReader.java
@@ -179,6 +179,34 @@ class IndexedSliceReader extends 
AbstractIterator<OnDiskAtom> implements OnDiskA
         }
     }
 
+    static int indexFor(SSTableReader sstable, ByteBuffer name, 
List<IndexHelper.IndexInfo> indexes, AbstractType<?> comparator, boolean 
reversed, int startIdx)
+    {
+        // If it's a super CF and the sstable is from the old format, then the 
index will contain old format info, i.e. non composite
+        // SC names. So we need to 1) use only the SC name part of the 
comparator and 2) extract only that part from 'name'
+        if (sstable.metadata.isSuper() && 
sstable.descriptor.version.hasSuperColumns)
+        {
+            AbstractType<?> scComparator = 
SuperColumns.getComparatorFor(sstable.metadata, false);
+            ByteBuffer scName = SuperColumns.scName(name);
+            return IndexHelper.indexFor(scName, indexes, scComparator, 
reversed, startIdx);
+        }
+        return IndexHelper.indexFor(name, indexes, comparator, reversed, 
startIdx);
+    }
+
+    static ByteBuffer forIndexComparison(SSTableReader sstable, ByteBuffer 
name)
+    {
+        // See indexFor above.
+        return sstable.metadata.isSuper() && 
sstable.descriptor.version.hasSuperColumns
+             ? SuperColumns.scName(name)
+             : name;
+    }
+
+    static AbstractType<?> comparatorForIndex(SSTableReader sstable, 
AbstractType<?> comparator)
+    {
+        return sstable.metadata.isSuper() && 
sstable.descriptor.version.hasSuperColumns
+             ? SuperColumns.getComparatorFor(sstable.metadata, false)
+             : comparator;
+    }
+
     private abstract class BlockFetcher
     {
         protected int currentSliceIdx;
@@ -219,16 +247,22 @@ class IndexedSliceReader extends 
AbstractIterator<OnDiskAtom> implements OnDiskA
             return start.remaining() != 0 && comparator.compare(name, start) < 
0;
         }
 
+        protected boolean isIndexEntryBeforeSliceStart(ByteBuffer name)
+        {
+            ByteBuffer start = currentStart();
+            return start.remaining() != 0 && comparatorForIndex(sstable, 
comparator).compare(name, forIndexComparison(sstable, start)) < 0;
+        }
+
         protected boolean isColumnBeforeSliceFinish(OnDiskAtom column)
         {
             ByteBuffer finish = currentFinish();
             return finish.remaining() == 0 || 
comparator.compare(column.name(), finish) <= 0;
         }
 
-        protected boolean isAfterSliceFinish(ByteBuffer name)
+        protected boolean isIndexEntryAfterSliceFinish(ByteBuffer name)
         {
             ByteBuffer finish = currentFinish();
-            return finish.remaining() != 0 && comparator.compare(name, finish) 
> 0;
+            return finish.remaining() != 0 && comparatorForIndex(sstable, 
comparator).compare(name, forIndexComparison(sstable, finish)) > 0;
         }
     }
 
@@ -259,7 +293,7 @@ class IndexedSliceReader extends 
AbstractIterator<OnDiskAtom> implements OnDiskA
         {
             while (++currentSliceIdx < slices.length)
             {
-                nextIndexIdx = 
IndexHelper.indexFor(slices[currentSliceIdx].start, indexes, comparator, 
reversed, nextIndexIdx);
+                nextIndexIdx = indexFor(sstable, 
slices[currentSliceIdx].start, indexes, comparator, reversed, nextIndexIdx);
                 if (nextIndexIdx < 0 || nextIndexIdx >= indexes.size())
                     // no index block for that slice
                     continue;
@@ -268,12 +302,12 @@ class IndexedSliceReader extends 
AbstractIterator<OnDiskAtom> implements OnDiskA
                 IndexInfo info = indexes.get(nextIndexIdx);
                 if (reversed)
                 {
-                    if (!isBeforeSliceStart(info.lastName))
+                    if (!isIndexEntryBeforeSliceStart(info.lastName))
                         return true;
                 }
                 else
                 {
-                    if (!isAfterSliceFinish(info.firstName))
+                    if (!isIndexEntryAfterSliceFinish(info.firstName))
                         return true;
                 }
             }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/0ff7f996/src/java/org/apache/cassandra/db/columniterator/SSTableNamesIterator.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/db/columniterator/SSTableNamesIterator.java 
b/src/java/org/apache/cassandra/db/columniterator/SSTableNamesIterator.java
index 3467244..2e84d8d 100644
--- a/src/java/org/apache/cassandra/db/columniterator/SSTableNamesIterator.java
+++ b/src/java/org/apache/cassandra/db/columniterator/SSTableNamesIterator.java
@@ -189,13 +189,15 @@ public class SSTableNamesIterator extends 
AbstractIterator<OnDiskAtom> implement
         int lastIndexIdx = -1;
         for (ByteBuffer name : columns)
         {
-            int index = IndexHelper.indexFor(name, indexList, comparator, 
false, lastIndexIdx);
+            int index = IndexedSliceReader.indexFor(sstable, name, indexList, 
comparator, false, lastIndexIdx);
             if (index < 0 || index == indexList.size())
                 continue;
             IndexHelper.IndexInfo indexInfo = indexList.get(index);
             // Check the index block does contain the column names and that we 
haven't inserted this block yet.
-            if (comparator.compare(name, indexInfo.firstName) < 0 || index == 
lastIndexIdx)
+            if (IndexedSliceReader.comparatorForIndex(sstable, 
comparator).compare(IndexedSliceReader.forIndexComparison(sstable, name), 
indexInfo.firstName) < 0
+              || index == lastIndexIdx)
                 continue;
+
             ranges.add(indexInfo);
             lastIndexIdx = index;
         }

Reply via email to