Repository: cassandra Updated Branches: refs/heads/cassandra-3.0 f96a5dc58 -> e22cb278b refs/heads/cassandra-3.11 88fa16977 -> 5c9db9af9 refs/heads/trunk a741efd94 -> 96899bbb6
Fix the reported number of sstable data files accessed per read patch by Benjamin Lerer; reviewed by Stefania Alborghetti for CASSANDRA-13120 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/e22cb278 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/e22cb278 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/e22cb278 Branch: refs/heads/cassandra-3.0 Commit: e22cb278b63a6ee5f03c7213071d07fd3b198659 Parents: f96a5dc Author: Benjamin Lerer <b.le...@gmail.com> Authored: Thu Jun 1 10:11:59 2017 +0200 Committer: Benjamin Lerer <b.le...@gmail.com> Committed: Thu Jun 1 10:11:59 2017 +0200 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cassandra/db/PartitionRangeReadCommand.java | 20 ++- .../db/SinglePartitionReadCommand.java | 74 +++++++--- .../db/columniterator/SSTableIterator.java | 9 +- .../columniterator/SSTableReversedIterator.java | 9 +- .../io/sstable/format/SSTableReader.java | 54 ++++++-- .../io/sstable/format/SSTableReadsListener.java | 81 +++++++++++ .../io/sstable/format/big/BigTableReader.java | 40 ++++-- .../io/sstable/format/big/BigTableScanner.java | 40 +++++- .../org/apache/cassandra/cql3/CQLTester.java | 21 ++- .../miscellaneous/SSTablesIteratedTest.java | 136 +++++++++++++++++++ .../cassandra/db/compaction/TTLExpiryTest.java | 7 +- .../sstable/SSTableCorruptionDetectionTest.java | 7 +- .../io/sstable/SSTableScannerTest.java | 6 +- .../cassandra/io/sstable/SSTableWriterTest.java | 7 +- .../sstable/format/ClientModeSSTableTest.java | 6 +- 16 files changed, 456 insertions(+), 62 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index c75ca87..4232084 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.0.14 + * Fix the reported number of sstable data files accessed per read (CASSANDRA-13120) * Fix schema digest mismatch during rolling upgrades from versions before 3.0.12 (CASSANDRA-13559) * Upgrade JNA version to 4.4.0 (CASSANDRA-13072) * Interned ColumnIdentifiers should use minimal ByteBuffers (CASSANDRA-13533) http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java b/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java index 17adef0..1cf332d 100644 --- a/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java +++ b/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java @@ -36,6 +36,7 @@ import org.apache.cassandra.dht.AbstractBounds; import org.apache.cassandra.exceptions.RequestExecutionException; import org.apache.cassandra.index.Index; import org.apache.cassandra.io.sstable.format.SSTableReader; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.metrics.TableMetrics; @@ -191,10 +192,11 @@ public class PartitionRangeReadCommand extends ReadCommand iterators.add(isForThrift() ? ThriftResultsMerger.maybeWrap(iter, metadata(), nowInSec()) : iter); } + SSTableReadsListener readCountUpdater = newReadCountUpdater(); for (SSTableReader sstable : view.sstables) { @SuppressWarnings("resource") // We close on exception and on closing the result returned by this method - UnfilteredPartitionIterator iter = sstable.getScanner(columnFilter(), dataRange(), isForThrift()); + UnfilteredPartitionIterator iter = sstable.getScanner(columnFilter(), dataRange(), isForThrift(), readCountUpdater); iterators.add(isForThrift() ? ThriftResultsMerger.maybeWrap(iter, metadata(), nowInSec()) : iter); if (!sstable.isRepaired()) oldestUnrepairedTombstone = Math.min(oldestUnrepairedTombstone, sstable.getMinLocalDeletionTime()); @@ -217,6 +219,22 @@ public class PartitionRangeReadCommand extends ReadCommand } } + /** + * Creates a new {@code SSTableReadsListener} to update the SSTables read counts. + * @return a new {@code SSTableReadsListener} to update the SSTables read counts. + */ + private static SSTableReadsListener newReadCountUpdater() + { + return new SSTableReadsListener() + { + @Override + public void onScanningStarted(SSTableReader sstable) + { + sstable.incrementReadCount(); + } + }; + } + @Override protected int oldestUnrepairedTombstone() { http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java b/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java index 99abd10..72b4465 100644 --- a/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java +++ b/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java @@ -38,6 +38,7 @@ import org.apache.cassandra.db.partitions.*; import org.apache.cassandra.db.rows.*; import org.apache.cassandra.exceptions.RequestExecutionException; import org.apache.cassandra.io.sstable.format.SSTableReader; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener; import org.apache.cassandra.io.util.DataInputPlus; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.metrics.TableMetrics; @@ -551,12 +552,12 @@ public class SinglePartitionReadCommand extends ReadCommand * In other words, iterating in maxTimestamp order allow to do our mostRecentPartitionTombstone elimination * in one pass, and minimize the number of sstables for which we read a partition tombstone. */ - int sstablesIterated = 0; Collections.sort(view.sstables, SSTableReader.maxTimestampComparator); List<SSTableReader> skippedSSTables = null; long mostRecentPartitionTombstone = Long.MIN_VALUE; long minTimestamp = Long.MAX_VALUE; int nonIntersectingSSTables = 0; + SSTableReadMetricsCollector metricsCollector = new SSTableReadMetricsCollector(); for (SSTableReader sstable : view.sstables) { @@ -579,15 +580,17 @@ public class SinglePartitionReadCommand extends ReadCommand continue; } - sstable.incrementReadCount(); @SuppressWarnings("resource") // 'iter' is added to iterators which is closed on exception, or through the closing of the final merged iterator - UnfilteredRowIterator iter = filter.filter(sstable.iterator(partitionKey(), columnFilter(), filter.isReversed(), isForThrift())); + UnfilteredRowIterator iter = filter.filter(sstable.iterator(partitionKey(), + columnFilter(), + filter.isReversed(), + isForThrift(), + metricsCollector)); if (!sstable.isRepaired()) oldestUnrepairedTombstone = Math.min(oldestUnrepairedTombstone, sstable.getMinLocalDeletionTime()); iterators.add(isForThrift() ? ThriftResultsMerger.maybeWrap(iter, nowInSec()) : iter); mostRecentPartitionTombstone = Math.max(mostRecentPartitionTombstone, iter.partitionLevelDeletion().markedForDeleteAt()); - sstablesIterated++; } int includedDueToTombstones = 0; @@ -599,16 +602,19 @@ public class SinglePartitionReadCommand extends ReadCommand if (sstable.getMaxTimestamp() <= minTimestamp) continue; - sstable.incrementReadCount(); @SuppressWarnings("resource") // 'iter' is either closed right away, or added to iterators which is close on exception, or through the closing of the final merged iterator - UnfilteredRowIterator iter = filter.filter(sstable.iterator(partitionKey(), columnFilter(), filter.isReversed(), isForThrift())); + UnfilteredRowIterator iter = filter.filter(sstable.iterator(partitionKey(), + columnFilter(), + filter.isReversed(), + isForThrift(), + metricsCollector)); + if (iter.partitionLevelDeletion().markedForDeleteAt() > minTimestamp) { iterators.add(iter); if (!sstable.isRepaired()) oldestUnrepairedTombstone = Math.min(oldestUnrepairedTombstone, sstable.getMinLocalDeletionTime()); includedDueToTombstones++; - sstablesIterated++; } else { @@ -620,12 +626,12 @@ public class SinglePartitionReadCommand extends ReadCommand Tracing.trace("Skipped {}/{} non-slice-intersecting sstables, included {} due to tombstones", nonIntersectingSSTables, view.sstables.size(), includedDueToTombstones); - cfs.metric.updateSSTableIterated(sstablesIterated); + cfs.metric.updateSSTableIterated(metricsCollector.getMergedSSTables()); if (iterators.isEmpty()) return EmptyIterators.unfilteredRow(cfs.metadata, partitionKey(), filter.isReversed()); - Tracing.trace("Merging data from memtables and {} sstables", sstablesIterated); + Tracing.trace("Merging data from memtables and {} sstables", metricsCollector.getMergedSSTables()); @SuppressWarnings("resource") // Closed through the closing of the result of that method. UnfilteredRowIterator merged = UnfilteredRowIterators.merge(iterators, nowInSec()); @@ -709,9 +715,9 @@ public class SinglePartitionReadCommand extends ReadCommand /* add the SSTables on disk */ Collections.sort(view.sstables, SSTableReader.maxTimestampComparator); - int sstablesIterated = 0; boolean onlyUnrepaired = true; // read sorted sstables + SSTableReadMetricsCollector metricsCollector = new SSTableReadMetricsCollector(); for (SSTableReader sstable : view.sstables) { // if we've already seen a partition tombstone with a timestamp greater @@ -735,10 +741,12 @@ public class SinglePartitionReadCommand extends ReadCommand continue; // Means no tombstone at all, we can skip that sstable // We need to get the partition deletion and include it if it's live. In any case though, we're done with that sstable. - sstable.incrementReadCount(); - try (UnfilteredRowIterator iter = filter.filter(sstable.iterator(partitionKey(), columnFilter(), filter.isReversed(), isForThrift()))) + try (UnfilteredRowIterator iter = filter.filter(sstable.iterator(partitionKey(), + columnFilter(), + filter.isReversed(), + isForThrift(), + metricsCollector))) { - sstablesIterated++; if (!iter.partitionLevelDeletion().isLive()) result = add(UnfilteredRowIterators.noRowsIterator(iter.metadata(), iter.partitionKey(), Rows.EMPTY_STATIC_ROW, iter.partitionLevelDeletion(), filter.isReversed()), result, filter, sstable.isRepaired()); else @@ -748,20 +756,22 @@ public class SinglePartitionReadCommand extends ReadCommand } Tracing.trace("Merging data from sstable {}", sstable.descriptor.generation); - sstable.incrementReadCount(); - try (UnfilteredRowIterator iter = filter.filter(sstable.iterator(partitionKey(), columnFilter(), filter.isReversed(), isForThrift()))) + try (UnfilteredRowIterator iter = filter.filter(sstable.iterator(partitionKey(), + columnFilter(), + filter.isReversed(), + isForThrift(), + metricsCollector))) { if (iter.isEmpty()) continue; if (sstable.isRepaired()) onlyUnrepaired = false; - sstablesIterated++; result = add(isForThrift() ? ThriftResultsMerger.maybeWrap(iter, nowInSec()) : iter, result, filter, sstable.isRepaired()); } } - cfs.metric.updateSSTableIterated(sstablesIterated); + cfs.metric.updateSSTableIterated(metricsCollector.getMergedSSTables()); if (result == null || result.isEmpty()) return EmptyIterators.unfilteredRow(metadata(), partitionKey(), false); @@ -770,7 +780,7 @@ public class SinglePartitionReadCommand extends ReadCommand cfs.metric.samplers.get(TableMetrics.Sampler.READS).addSample(key.getKey(), key.hashCode(), 1); // "hoist up" the requested data into a more recent sstable - if (sstablesIterated > cfs.getMinimumCompactionThreshold() + if (metricsCollector.getMergedSSTables() > cfs.getMinimumCompactionThreshold() && onlyUnrepaired && !cfs.isAutoCompactionDisabled() && cfs.getCompactionStrategyManager().shouldDefragment()) @@ -1022,4 +1032,32 @@ public class SinglePartitionReadCommand extends ReadCommand return new SinglePartitionReadCommand(isDigest, digestVersion, isForThrift, metadata, nowInSec, columnFilter, rowFilter, limits, key, filter); } } + + /** + * {@code SSTableReaderListener} used to collect metrics about SSTable read access. + */ + private static final class SSTableReadMetricsCollector implements SSTableReadsListener + { + /** + * The number of SSTables that need to be merged. This counter is only updated for single partition queries + * since this has been the behavior so far. + */ + private int mergedSSTables; + + @Override + public void onSSTableSelected(SSTableReader sstable, RowIndexEntry<?> indexEntry, SelectionReason reason) + { + sstable.incrementReadCount(); + mergedSSTables++; + } + + /** + * Returns the number of SSTables that need to be merged. + * @return the number of SSTables that need to be merged. + */ + public int getMergedSSTables() + { + return mergedSSTables; + } + } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/src/java/org/apache/cassandra/db/columniterator/SSTableIterator.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/columniterator/SSTableIterator.java b/src/java/org/apache/cassandra/db/columniterator/SSTableIterator.java index fa337c0..ff91871 100644 --- a/src/java/org/apache/cassandra/db/columniterator/SSTableIterator.java +++ b/src/java/org/apache/cassandra/db/columniterator/SSTableIterator.java @@ -24,6 +24,7 @@ import org.apache.cassandra.db.*; import org.apache.cassandra.db.filter.ColumnFilter; import org.apache.cassandra.db.rows.*; import org.apache.cassandra.io.sstable.format.SSTableReader; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener; import org.apache.cassandra.io.util.FileDataInput; /** @@ -31,9 +32,13 @@ import org.apache.cassandra.io.util.FileDataInput; */ public class SSTableIterator extends AbstractSSTableIterator { - public SSTableIterator(SSTableReader sstable, DecoratedKey key, ColumnFilter columns, boolean isForThrift) + public SSTableIterator(SSTableReader sstable, + DecoratedKey key, + ColumnFilter columns, + boolean isForThrift, + SSTableReadsListener listener) { - this(sstable, null, key, sstable.getPosition(key, SSTableReader.Operator.EQ), columns, isForThrift); + this(sstable, null, key, sstable.getPosition(key, SSTableReader.Operator.EQ, listener), columns, isForThrift); } public SSTableIterator(SSTableReader sstable, http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/src/java/org/apache/cassandra/db/columniterator/SSTableReversedIterator.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/columniterator/SSTableReversedIterator.java b/src/java/org/apache/cassandra/db/columniterator/SSTableReversedIterator.java index 4bb7fe8..b12ed67 100644 --- a/src/java/org/apache/cassandra/db/columniterator/SSTableReversedIterator.java +++ b/src/java/org/apache/cassandra/db/columniterator/SSTableReversedIterator.java @@ -26,6 +26,7 @@ import org.apache.cassandra.db.filter.ColumnFilter; import org.apache.cassandra.db.partitions.ImmutableBTreePartition; import org.apache.cassandra.db.rows.*; import org.apache.cassandra.io.sstable.format.SSTableReader; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener; import org.apache.cassandra.io.util.FileDataInput; import org.apache.cassandra.utils.AbstractIterator; import org.apache.cassandra.utils.btree.BTree; @@ -35,9 +36,13 @@ import org.apache.cassandra.utils.btree.BTree; */ public class SSTableReversedIterator extends AbstractSSTableIterator { - public SSTableReversedIterator(SSTableReader sstable, DecoratedKey key, ColumnFilter columns, boolean isForThrift) + public SSTableReversedIterator(SSTableReader sstable, + DecoratedKey key, + ColumnFilter columns, + boolean isForThrift, + SSTableReadsListener listener) { - this(sstable, null, key, sstable.getPosition(key, SSTableReader.Operator.EQ), columns, isForThrift); + this(sstable, null, key, sstable.getPosition(key, SSTableReader.Operator.EQ, listener), columns, isForThrift); } public SSTableReversedIterator(SSTableReader sstable, http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java b/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java index 8be1fe2..f38738d 100644 --- a/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java +++ b/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java @@ -1504,14 +1504,19 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS * Get position updating key cache and stats. * @see #getPosition(PartitionPosition, SSTableReader.Operator, boolean) */ - public RowIndexEntry getPosition(PartitionPosition key, Operator op) + public final RowIndexEntry getPosition(PartitionPosition key, Operator op) { - return getPosition(key, op, true, false); + return getPosition(key, op, SSTableReadsListener.NOOP_LISTENER); } - public RowIndexEntry getPosition(PartitionPosition key, Operator op, boolean updateCacheAndStats) + public final RowIndexEntry getPosition(PartitionPosition key, Operator op, SSTableReadsListener listener) { - return getPosition(key, op, updateCacheAndStats, false); + return getPosition(key, op, true, false, listener); + } + + public final RowIndexEntry getPosition(PartitionPosition key, Operator op, boolean updateCacheAndStats) + { + return getPosition(key, op, updateCacheAndStats, false, SSTableReadsListener.NOOP_LISTENER); } /** * @param key The key to apply as the rhs to the given Operator. A 'fake' key is allowed to @@ -1520,10 +1525,24 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS * @param updateCacheAndStats true if updating stats and cache * @return The index entry corresponding to the key, or null if the key is not present */ - protected abstract RowIndexEntry getPosition(PartitionPosition key, Operator op, boolean updateCacheAndStats, boolean permitMatchPastLast); - - public abstract SliceableUnfilteredRowIterator iterator(DecoratedKey key, ColumnFilter selectedColumns, boolean reversed, boolean isForThrift); - public abstract SliceableUnfilteredRowIterator iterator(FileDataInput file, DecoratedKey key, RowIndexEntry indexEntry, ColumnFilter selectedColumns, boolean reversed, boolean isForThrift); + protected abstract RowIndexEntry getPosition(PartitionPosition key, + Operator op, + boolean updateCacheAndStats, + boolean permitMatchPastLast, + SSTableReadsListener listener); + + public abstract SliceableUnfilteredRowIterator iterator(DecoratedKey key, + ColumnFilter selectedColumns, + boolean reversed, + boolean isForThrift, + SSTableReadsListener listener); + + public abstract SliceableUnfilteredRowIterator iterator(FileDataInput file, + DecoratedKey key, + RowIndexEntry indexEntry, + ColumnFilter selectedColumns, + boolean reversed, + boolean isForThrift); /** * Finds and returns the first key beyond a given token in this SSTable or null if no such key exists. @@ -1656,11 +1675,15 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS /** * @param columns the columns to return. * @param dataRange filter to use when reading the columns + * @param listener a listener used to handle internal read events * @return A Scanner for seeking over the rows of the SSTable. */ - public ISSTableScanner getScanner(ColumnFilter columns, DataRange dataRange, boolean isForThrift) + public ISSTableScanner getScanner(ColumnFilter columns, + DataRange dataRange, + boolean isForThrift, + SSTableReadsListener listener) { - return getScanner(columns, dataRange, null, isForThrift); + return getScanner(columns, dataRange, null, isForThrift, listener); } /** @@ -1702,9 +1725,14 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS /** * @param columns the columns to return. * @param dataRange filter to use when reading the columns + * @param listener a listener used to handle internal read events * @return A Scanner for seeking over the rows of the SSTable. */ - public abstract ISSTableScanner getScanner(ColumnFilter columns, DataRange dataRange, RateLimiter limiter, boolean isForThrift); + public abstract ISSTableScanner getScanner(ColumnFilter columns, + DataRange dataRange, + RateLimiter limiter, + boolean isForThrift, + SSTableReadsListener listener); public FileDataInput getFileDataInput(long position) { @@ -1953,8 +1981,8 @@ public abstract class SSTableReader extends SSTable implements SelfRefCounted<SS } /** - * Increment the total row read count and read rate for this SSTable. This should not be incremented for range - * slice queries, row cache hits, or non-query reads, like compaction. + * Increment the total read count and read rate for this SSTable. This should not be incremented for non-query reads, + * like compaction. */ public void incrementReadCount() { http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/src/java/org/apache/cassandra/io/sstable/format/SSTableReadsListener.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/sstable/format/SSTableReadsListener.java b/src/java/org/apache/cassandra/io/sstable/format/SSTableReadsListener.java new file mode 100644 index 0000000..6d384bf --- /dev/null +++ b/src/java/org/apache/cassandra/io/sstable/format/SSTableReadsListener.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.io.sstable.format; + +import org.apache.cassandra.db.RowIndexEntry; + +/** + * Listener for receiving notifications associated with reading SSTables. + */ +public interface SSTableReadsListener +{ + /** + * The reasons for skipping an SSTable + */ + enum SkippingReason + { + BLOOM_FILTER, + MIN_MAX_KEYS, + PARTITION_INDEX_LOOKUP, + INDEX_ENTRY_NOT_FOUND; + } + + /** + * The reasons for selecting an SSTable + */ + enum SelectionReason + { + KEY_CACHE_HIT, + INDEX_ENTRY_FOUND; + } + + /** + * Listener that does nothing. + */ + static final SSTableReadsListener NOOP_LISTENER = new SSTableReadsListener() {}; + + /** + * Handles notification that the specified SSTable has been skipped during a single partition query. + * + * @param sstable the SSTable reader + * @param reason the reason for which the SSTable has been skipped + */ + default void onSSTableSkipped(SSTableReader sstable, SkippingReason reason) + { + } + + /** + * Handles notification that the specified SSTable has been selected during a single partition query. + * + * @param sstable the SSTable reader + * @param indexEntry the index entry + * @param reason the reason for which the SSTable has been selected + */ + default void onSSTableSelected(SSTableReader sstable, RowIndexEntry<?> indexEntry, SelectionReason reason) + { + } + + /** + * Handles notification that the specified SSTable is being scanned during a partition range query. + * + * @param sstable the SSTable reader of the SSTable being scanned. + */ + default void onScanningStarted(SSTableReader sstable) + { + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/src/java/org/apache/cassandra/io/sstable/format/big/BigTableReader.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/sstable/format/big/BigTableReader.java b/src/java/org/apache/cassandra/io/sstable/format/big/BigTableReader.java index 1fbf1f2..eeea18f 100644 --- a/src/java/org/apache/cassandra/io/sstable/format/big/BigTableReader.java +++ b/src/java/org/apache/cassandra/io/sstable/format/big/BigTableReader.java @@ -33,6 +33,9 @@ import org.apache.cassandra.io.sstable.CorruptSSTableException; import org.apache.cassandra.io.sstable.Descriptor; import org.apache.cassandra.io.sstable.ISSTableScanner; import org.apache.cassandra.io.sstable.format.SSTableReader; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener.SkippingReason; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener.SelectionReason; import org.apache.cassandra.io.sstable.metadata.StatsMetadata; import org.apache.cassandra.io.util.FileDataInput; import org.apache.cassandra.tracing.Tracing; @@ -57,11 +60,15 @@ public class BigTableReader extends SSTableReader super(desc, components, metadata, maxDataAge, sstableMetadata, openReason, header); } - public SliceableUnfilteredRowIterator iterator(DecoratedKey key, ColumnFilter selectedColumns, boolean reversed, boolean isForThrift) + public SliceableUnfilteredRowIterator iterator(DecoratedKey key, + ColumnFilter selectedColumns, + boolean reversed, + boolean isForThrift, + SSTableReadsListener listener) { return reversed - ? new SSTableReversedIterator(this, key, selectedColumns, isForThrift) - : new SSTableIterator(this, key, selectedColumns, isForThrift); + ? new SSTableReversedIterator(this, key, selectedColumns, isForThrift, listener) + : new SSTableIterator(this, key, selectedColumns, isForThrift, listener); } public SliceableUnfilteredRowIterator iterator(FileDataInput file, DecoratedKey key, RowIndexEntry indexEntry, ColumnFilter selectedColumns, boolean reversed, boolean isForThrift) @@ -71,14 +78,14 @@ public class BigTableReader extends SSTableReader : new SSTableIterator(this, file, key, indexEntry, selectedColumns, isForThrift); } - /** - * @param columns the columns to return. - * @param dataRange filter to use when reading the columns - * @return A Scanner for seeking over the rows of the SSTable. - */ - public ISSTableScanner getScanner(ColumnFilter columns, DataRange dataRange, RateLimiter limiter, boolean isForThrift) + @Override + public ISSTableScanner getScanner(ColumnFilter columns, + DataRange dataRange, + RateLimiter limiter, + boolean isForThrift, + SSTableReadsListener listener) { - return BigTableScanner.getScanner(this, columns, dataRange, limiter, isForThrift); + return BigTableScanner.getScanner(this, columns, dataRange, limiter, isForThrift, listener); } /** @@ -122,15 +129,21 @@ public class BigTableReader extends SSTableReader * allow key selection by token bounds but only if op != * EQ * @param op The Operator defining matching keys: the nearest key to the target matching the operator wins. * @param updateCacheAndStats true if updating stats and cache + * @param listener a listener used to handle internal events * @return The index entry corresponding to the key, or null if the key is not present */ - protected RowIndexEntry getPosition(PartitionPosition key, Operator op, boolean updateCacheAndStats, boolean permitMatchPastLast) + protected RowIndexEntry getPosition(PartitionPosition key, + Operator op, + boolean updateCacheAndStats, + boolean permitMatchPastLast, + SSTableReadsListener listener) { if (op == Operator.EQ) { assert key instanceof DecoratedKey; // EQ only make sense if the key is a valid row key if (!bf.isPresent((DecoratedKey)key)) { + listener.onSSTableSkipped(this, SkippingReason.BLOOM_FILTER); Tracing.trace("Bloom filter allows skipping sstable {}", descriptor.generation); return null; } @@ -144,6 +157,7 @@ public class BigTableReader extends SSTableReader RowIndexEntry cachedPosition = getCachedPosition(cacheKey, updateCacheAndStats); if (cachedPosition != null) { + listener.onSSTableSelected(this, cachedPosition, SelectionReason.KEY_CACHE_HIT); Tracing.trace("Key cache hit for sstable {}", descriptor.generation); return cachedPosition; } @@ -172,6 +186,7 @@ public class BigTableReader extends SSTableReader { if (op == Operator.EQ && updateCacheAndStats) bloomFilterTracker.addFalsePositive(); + listener.onSSTableSkipped(this, SkippingReason.MIN_MAX_KEYS); Tracing.trace("Check against min and max keys allows skipping sstable {}", descriptor.generation); return null; } @@ -219,6 +234,7 @@ public class BigTableReader extends SSTableReader exactMatch = (comparison == 0); if (v < 0) { + listener.onSSTableSkipped(this, SkippingReason.PARTITION_INDEX_LOOKUP); Tracing.trace("Partition index lookup allows skipping sstable {}", descriptor.generation); return null; } @@ -249,6 +265,7 @@ public class BigTableReader extends SSTableReader } if (op == Operator.EQ && updateCacheAndStats) bloomFilterTracker.addTruePositive(); + listener.onSSTableSelected(this, indexEntry, SelectionReason.INDEX_ENTRY_FOUND); Tracing.trace("Partition index with {} entries found for sstable {}", indexEntry.columnsIndex().size(), descriptor.generation); return indexEntry; } @@ -264,6 +281,7 @@ public class BigTableReader extends SSTableReader if (op == SSTableReader.Operator.EQ && updateCacheAndStats) bloomFilterTracker.addFalsePositive(); + listener.onSSTableSkipped(this, SkippingReason.INDEX_ENTRY_NOT_FOUND); Tracing.trace("Partition index lookup complete (bloom filter false positive) for sstable {}", descriptor.generation); return null; } http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/src/java/org/apache/cassandra/io/sstable/format/big/BigTableScanner.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/sstable/format/big/BigTableScanner.java b/src/java/org/apache/cassandra/io/sstable/format/big/BigTableScanner.java index a3bd442..82d8211 100644 --- a/src/java/org/apache/cassandra/io/sstable/format/big/BigTableScanner.java +++ b/src/java/org/apache/cassandra/io/sstable/format/big/BigTableScanner.java @@ -39,6 +39,7 @@ import org.apache.cassandra.io.sstable.CorruptSSTableException; import org.apache.cassandra.io.sstable.ISSTableScanner; import org.apache.cassandra.io.sstable.SSTableIdentityIterator; import org.apache.cassandra.io.sstable.format.SSTableReader; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener; import org.apache.cassandra.io.util.FileUtils; import org.apache.cassandra.io.util.RandomAccessReader; import org.apache.cassandra.utils.ByteBufferUtil; @@ -62,18 +63,30 @@ public class BigTableScanner implements ISSTableScanner private final DataRange dataRange; private final RowIndexEntry.IndexSerializer rowIndexEntrySerializer; private final boolean isForThrift; + private final SSTableReadsListener listener; protected Iterator<UnfilteredRowIterator> iterator; // Full scan of the sstables public static ISSTableScanner getScanner(SSTableReader sstable, RateLimiter limiter) { - return new BigTableScanner(sstable, ColumnFilter.all(sstable.metadata), null, limiter, false, Iterators.singletonIterator(fullRange(sstable))); + return new BigTableScanner(sstable, limiter, Iterators.singletonIterator(fullRange(sstable))); } - public static ISSTableScanner getScanner(SSTableReader sstable, ColumnFilter columns, DataRange dataRange, RateLimiter limiter, boolean isForThrift) + public static ISSTableScanner getScanner(SSTableReader sstable, + ColumnFilter columns, + DataRange dataRange, + RateLimiter limiter, + boolean isForThrift, + SSTableReadsListener listener) { - return new BigTableScanner(sstable, columns, dataRange, limiter, isForThrift, makeBounds(sstable, dataRange).iterator()); + return new BigTableScanner(sstable, + columns, + dataRange, + limiter, + isForThrift, + makeBounds(sstable, dataRange).iterator(), + listener); } public static ISSTableScanner getScanner(SSTableReader sstable, Collection<Range<Token>> tokenRanges, RateLimiter limiter) @@ -83,15 +96,28 @@ public class BigTableScanner implements ISSTableScanner if (positions.isEmpty()) return new EmptySSTableScanner(sstable); - return new BigTableScanner(sstable, ColumnFilter.all(sstable.metadata), null, limiter, false, makeBounds(sstable, tokenRanges).iterator()); + return new BigTableScanner(sstable, limiter, makeBounds(sstable, tokenRanges).iterator()); } public static ISSTableScanner getScanner(SSTableReader sstable, Iterator<AbstractBounds<PartitionPosition>> rangeIterator) { - return new BigTableScanner(sstable, ColumnFilter.all(sstable.metadata), null, null, false, rangeIterator); + return new BigTableScanner(sstable, null, rangeIterator); } - private BigTableScanner(SSTableReader sstable, ColumnFilter columns, DataRange dataRange, RateLimiter limiter, boolean isForThrift, Iterator<AbstractBounds<PartitionPosition>> rangeIterator) + private BigTableScanner(SSTableReader sstable, + RateLimiter limiter, + Iterator<AbstractBounds<PartitionPosition>> rangeIterator) + { + this(sstable, ColumnFilter.all(sstable.metadata), null, limiter, false, rangeIterator, SSTableReadsListener.NOOP_LISTENER); + } + + private BigTableScanner(SSTableReader sstable, + ColumnFilter columns, + DataRange dataRange, + RateLimiter limiter, + boolean isForThrift, + Iterator<AbstractBounds<PartitionPosition>> rangeIterator, + SSTableReadsListener listener) { assert sstable != null; @@ -105,6 +131,7 @@ public class BigTableScanner implements ISSTableScanner sstable.header); this.isForThrift = isForThrift; this.rangeIterator = rangeIterator; + this.listener = listener; } private static List<AbstractBounds<PartitionPosition>> makeBounds(SSTableReader sstable, Collection<Range<Token>> tokenRanges) @@ -259,6 +286,7 @@ public class BigTableScanner implements ISSTableScanner private Iterator<UnfilteredRowIterator> createIterator() { + listener.onScanningStarted(sstable); return new KeyScanningIterator(); } http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/test/unit/org/apache/cassandra/cql3/CQLTester.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/CQLTester.java b/test/unit/org/apache/cassandra/cql3/CQLTester.java index db3652b..39278f0 100644 --- a/test/unit/org/apache/cassandra/cql3/CQLTester.java +++ b/test/unit/org/apache/cassandra/cql3/CQLTester.java @@ -367,21 +367,36 @@ public abstract class CQLTester return list.isEmpty() ? Collections.<String>emptyList() : new ArrayList<>(list); } - public ColumnFamilyStore getCurrentColumnFamilyStore() + public ColumnFamilyStore getCurrentColumnFamilyStore(String keyspace) { String currentTable = currentTable(); return currentTable == null ? null - : Keyspace.open(KEYSPACE).getColumnFamilyStore(currentTable); + : Keyspace.open(keyspace).getColumnFamilyStore(currentTable); + } + + public ColumnFamilyStore getCurrentColumnFamilyStore() + { + return getCurrentColumnFamilyStore(KEYSPACE); } public void flush() { - ColumnFamilyStore store = getCurrentColumnFamilyStore(); + flush(KEYSPACE); + } + + public void flush(String keyspace) + { + ColumnFamilyStore store = getCurrentColumnFamilyStore(keyspace); if (store != null) store.forceBlockingFlush(); } + public void disableCompaction(String keyspace) + { + ColumnFamilyStore store = getCurrentColumnFamilyStore(keyspace); + store.disableAutoCompaction(); + } public void flush(boolean forceFlush) { http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/test/unit/org/apache/cassandra/cql3/validation/miscellaneous/SSTablesIteratedTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/miscellaneous/SSTablesIteratedTest.java b/test/unit/org/apache/cassandra/cql3/validation/miscellaneous/SSTablesIteratedTest.java new file mode 100644 index 0000000..2cf518a --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/validation/miscellaneous/SSTablesIteratedTest.java @@ -0,0 +1,136 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.cassandra.cql3.validation.miscellaneous; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import org.apache.cassandra.cql3.CQLTester; +import org.apache.cassandra.cql3.UntypedResultSet; +import org.apache.cassandra.db.ColumnFamilyStore; +import org.apache.cassandra.metrics.ClearableHistogram; + +/** + * Tests for checking how many sstables we access during cql queries. + */ +public class SSTablesIteratedTest extends CQLTester +{ + private void executeAndCheck(String query, int numSSTables, Object[]... rows) throws Throwable + { + ColumnFamilyStore cfs = getCurrentColumnFamilyStore(KEYSPACE_PER_TEST); + + ((ClearableHistogram) cfs.metric.sstablesPerReadHistogram.cf).clear(); // resets counts + + assertRows(execute(query), rows); + + long numSSTablesIterated = cfs.metric.sstablesPerReadHistogram.cf.getSnapshot().getMax(); // max sstables read + assertEquals(String.format("Expected %d sstables iterated but got %d instead, with %d live sstables", + numSSTables, numSSTablesIterated, cfs.getLiveSSTables().size()), + numSSTables, + numSSTablesIterated); + } + + @Override + protected String createTable(String query) + { + String ret = super.createTable(KEYSPACE_PER_TEST, query); + disableCompaction(KEYSPACE_PER_TEST); + return ret; + } + + @Override + protected UntypedResultSet execute(String query, Object... values) throws Throwable + { + return executeFormattedQuery(formatQuery(KEYSPACE_PER_TEST, query), values); + } + + @Override + public void flush() + { + super.flush(KEYSPACE_PER_TEST); + } + + @Test + public void testSinglePartitionQuery() throws Throwable + { + createTable("CREATE TABLE %s (pk int, c int, v text, PRIMARY KEY (pk, c))"); + + execute("INSERT INTO %s (pk, c, v) VALUES (?, ?, ?)", 1, 40, "41"); + execute("INSERT INTO %s (pk, c, v) VALUES (?, ?, ?)", 2, 10, "12"); + flush(); + + execute("INSERT INTO %s (pk, c, v) VALUES (?, ?, ?)", 1, 10, "11"); + execute("INSERT INTO %s (pk, c, v) VALUES (?, ?, ?)", 3, 30, "33"); + flush(); + + execute("INSERT INTO %s (pk, c, v) VALUES (?, ?, ?)", 1, 20, "21"); + execute("INSERT INTO %s (pk, c, v) VALUES (?, ?, ?)", 2, 40, "42"); + execute("UPDATE %s SET v = '12' WHERE pk = 2 AND c = 10"); + flush(); + + // Test with all the table being merged + executeAndCheck("SELECT * FROM %s WHERE pk = 1", 3, + row(1, 10, "11"), + row(1, 20, "21"), + row(1, 40, "41")); + + // Test with only 2 of the 3 SSTables being merged + executeAndCheck("SELECT * FROM %s WHERE pk = 2", 2, + row(2, 10, "12"), + row(2, 40, "42")); + + executeAndCheck("SELECT * FROM %s WHERE pk = 2 ORDER BY c DESC", 2, + row(2, 40, "42"), + row(2, 10, "12")); + + // Test with only 2 of the 3 SSTables being merged and a Slice filter + executeAndCheck("SELECT * FROM %s WHERE pk = 2 AND c > 20", 2, + row(2, 40, "42")); + + executeAndCheck("SELECT * FROM %s WHERE pk = 2 AND c > 20 ORDER BY c DESC", 2, + row(2, 40, "42")); + + // Test with only 2 of the 3 SSTables being merged and a Name filter + // This test checks the SinglePartitionReadCommand::queryMemtableAndSSTablesInTimestampOrder which is only + // used for ClusteringIndexNamesFilter when there are no multi-cell columns + executeAndCheck("SELECT * FROM %s WHERE pk = 2 AND c = 10", 2, + row(2, 10, "12")); + + // For partition range queries the metric must not be updated. The reason being that range queries simply + // scan all the SSTables containing data within the partition range. Due to that they might pollute the metric + // and give a wrong view of the system. + executeAndCheck("SELECT * FROM %s", 0, + row(1, 10, "11"), + row(1, 20, "21"), + row(1, 40, "41"), + row(2, 10, "12"), + row(2, 40, "42"), + row(3, 30, "33")); + + executeAndCheck("SELECT * FROM %s WHERE token(pk) = token(1)", 0, + row(1, 10, "11"), + row(1, 20, "21"), + row(1, 40, "41")); + + assertInvalidMessage("ORDER BY is only supported when the partition key is restricted by an EQ or an IN", + "SELECT * FROM %s WHERE token(pk) = token(1) ORDER BY C DESC"); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/test/unit/org/apache/cassandra/db/compaction/TTLExpiryTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/db/compaction/TTLExpiryTest.java b/test/unit/org/apache/cassandra/db/compaction/TTLExpiryTest.java index eb42865..e0378f6 100644 --- a/test/unit/org/apache/cassandra/db/compaction/TTLExpiryTest.java +++ b/test/unit/org/apache/cassandra/db/compaction/TTLExpiryTest.java @@ -33,12 +33,12 @@ import org.apache.cassandra.SchemaLoader; import org.apache.cassandra.Util; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.db.*; -import org.apache.cassandra.db.rows.BTreeRow; import org.apache.cassandra.db.filter.ColumnFilter; import org.apache.cassandra.db.lifecycle.SSTableSet; import org.apache.cassandra.db.rows.UnfilteredRowIterator; import org.apache.cassandra.db.marshal.*; import org.apache.cassandra.io.sstable.format.SSTableReader; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.io.sstable.ISSTableScanner; import org.apache.cassandra.schema.KeyspaceParams; @@ -243,7 +243,10 @@ public class TTLExpiryTest cfs.enableAutoCompaction(true); assertEquals(1, cfs.getLiveSSTables().size()); SSTableReader sstable = cfs.getLiveSSTables().iterator().next(); - ISSTableScanner scanner = sstable.getScanner(ColumnFilter.all(sstable.metadata), DataRange.allData(cfs.getPartitioner()), false); + ISSTableScanner scanner = sstable.getScanner(ColumnFilter.all(sstable.metadata), + DataRange.allData(cfs.getPartitioner()), + false, + SSTableReadsListener.NOOP_LISTENER); assertTrue(scanner.hasNext()); while(scanner.hasNext()) { http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/test/unit/org/apache/cassandra/io/sstable/SSTableCorruptionDetectionTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/io/sstable/SSTableCorruptionDetectionTest.java b/test/unit/org/apache/cassandra/io/sstable/SSTableCorruptionDetectionTest.java index 4da8519..451af25 100644 --- a/test/unit/org/apache/cassandra/io/sstable/SSTableCorruptionDetectionTest.java +++ b/test/unit/org/apache/cassandra/io/sstable/SSTableCorruptionDetectionTest.java @@ -42,6 +42,7 @@ import org.apache.cassandra.db.lifecycle.LifecycleTransaction; import org.apache.cassandra.db.marshal.*; import org.apache.cassandra.db.rows.*; import org.apache.cassandra.io.sstable.format.SSTableReader; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener; import org.apache.cassandra.io.sstable.format.SSTableWriter; import org.apache.cassandra.io.util.*; import org.apache.cassandra.schema.*; @@ -207,7 +208,11 @@ public class SSTableCorruptionDetectionTest extends SSTableWriterTestBase for (int i = 0; i < numberOfPks; i++) { DecoratedKey dk = Util.dk(String.format("pkvalue_%07d", i)); - try (UnfilteredRowIterator rowIter = sstable.iterator(dk, ColumnFilter.all(cfs.metadata), false, false)) + try (UnfilteredRowIterator rowIter = sstable.iterator(dk, + ColumnFilter.all(cfs.metadata), + false, + false, + SSTableReadsListener.NOOP_LISTENER)) { while (rowIter.hasNext()) { http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/test/unit/org/apache/cassandra/io/sstable/SSTableScannerTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/io/sstable/SSTableScannerTest.java b/test/unit/org/apache/cassandra/io/sstable/SSTableScannerTest.java index d73c278..cf57b17 100644 --- a/test/unit/org/apache/cassandra/io/sstable/SSTableScannerTest.java +++ b/test/unit/org/apache/cassandra/io/sstable/SSTableScannerTest.java @@ -46,6 +46,7 @@ import org.apache.cassandra.dht.ByteOrderedPartitioner; import org.apache.cassandra.dht.Range; import org.apache.cassandra.dht.Token; import org.apache.cassandra.io.sstable.format.SSTableReader; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener; import org.apache.cassandra.schema.KeyspaceParams; import org.apache.cassandra.utils.ByteBufferUtil; @@ -182,7 +183,10 @@ public class SSTableScannerTest assert boundaries.length % 2 == 0; for (DataRange range : dataRanges(sstable.metadata, scanStart, scanEnd)) { - try(ISSTableScanner scanner = sstable.getScanner(ColumnFilter.all(sstable.metadata), range, false)) + try(ISSTableScanner scanner = sstable.getScanner(ColumnFilter.all(sstable.metadata), + range, + false, + SSTableReadsListener.NOOP_LISTENER)) { for (int b = 0; b < boundaries.length; b += 2) for (int i = boundaries[b]; i <= boundaries[b + 1]; i++) http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/test/unit/org/apache/cassandra/io/sstable/SSTableWriterTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/io/sstable/SSTableWriterTest.java b/test/unit/org/apache/cassandra/io/sstable/SSTableWriterTest.java index 6f18461..e714c60 100644 --- a/test/unit/org/apache/cassandra/io/sstable/SSTableWriterTest.java +++ b/test/unit/org/apache/cassandra/io/sstable/SSTableWriterTest.java @@ -30,6 +30,7 @@ import org.apache.cassandra.db.filter.*; import org.apache.cassandra.db.lifecycle.LifecycleTransaction; import org.apache.cassandra.db.rows.*; import org.apache.cassandra.io.sstable.format.SSTableReader; +import org.apache.cassandra.io.sstable.format.SSTableReadsListener; import org.apache.cassandra.io.sstable.format.SSTableWriter; import org.apache.cassandra.utils.FBUtilities; @@ -223,7 +224,11 @@ public class SSTableWriterTest extends SSTableWriterTestBase try { DecoratedKey dk = Util.dk("large_value"); - UnfilteredRowIterator rowIter = sstable.iterator(dk, ColumnFilter.all(cfs.metadata), false, false); + UnfilteredRowIterator rowIter = sstable.iterator(dk, + ColumnFilter.all(cfs.metadata), + false, + false, + SSTableReadsListener.NOOP_LISTENER); while (rowIter.hasNext()) { rowIter.next(); http://git-wip-us.apache.org/repos/asf/cassandra/blob/e22cb278/test/unit/org/apache/cassandra/io/sstable/format/ClientModeSSTableTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/io/sstable/format/ClientModeSSTableTest.java b/test/unit/org/apache/cassandra/io/sstable/format/ClientModeSSTableTest.java index 661fcd5..48a8af5 100644 --- a/test/unit/org/apache/cassandra/io/sstable/format/ClientModeSSTableTest.java +++ b/test/unit/org/apache/cassandra/io/sstable/format/ClientModeSSTableTest.java @@ -107,7 +107,11 @@ public class ClientModeSSTableTest ByteBuffer key = bytes(Integer.toString(100)); - try (SliceableUnfilteredRowIterator iter = reader.iterator(metadata.decorateKey(key), ColumnFilter.selection(metadata.partitionColumns()), false, false)) + try (SliceableUnfilteredRowIterator iter = reader.iterator(metadata.decorateKey(key), + ColumnFilter.selection(metadata.partitionColumns()), + false, + false, + SSTableReadsListener.NOOP_LISTENER)) { assert iter.next().clustering().get(0).equals(key); } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org