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; }