Composite startComposite = CellNames.simpleDense(query.getSliceStart().asByteBuffer()); Composite endComposite = CellNames.simpleDense(query.getSliceEnd().asByteBuffer()); SliceQueryFilter sqf = new SliceQueryFilter(startComposite, endComposite, false, query.getLimit() + (query.hasLimit()?1:0)); ReadCommand sliceCmd = new SliceFromReadCommand(keyspace, query.getKey().asByteBuffer(), columnFamily, nowMillis, sqf);
public AbstractRangeCommand forSubRange(AbstractBounds<RowPosition> subRange) { Composite newStart = subRange.left.equals(keyRange.left) ? start : ((SliceQueryFilter)predicate).start(); Composite newStop = subRange.right.equals(keyRange.right) ? stop : ((SliceQueryFilter)predicate).finish(); return new PagedRangeCommand(keyspace, columnFamily, timestamp, subRange, ((SliceQueryFilter) predicate).cloneShallow(), newStart, newStop, rowFilter, limit, countCQL3Rows); }
public OnDiskAtomIterator getColumnIterator(final DecoratedKey key, final ColumnFamily cf) { assert cf != null; final Iterator<Cell> iter = getColumnIterator(cf); return new OnDiskAtomIterator() { public ColumnFamily getColumnFamily() { return cf; } public DecoratedKey getKey() { return key; } public boolean hasNext() { return iter.hasNext(); } public OnDiskAtom next() { return iter.next(); } public void close() throws IOException { } public void remove() { throw new UnsupportedOperationException(); } }; }
public static abstract class AbstractScanIterator extends AbstractIterator<Row> implements CloseableIterator<Row> { public boolean needsFiltering() { return true; } }
public static SliceQueryFilter fromSCSliceFilter(CellNameType type, ByteBuffer scName, SliceQueryFilter filter) { assert filter.slices.length == 1; if (scName == null) { // The filter is on the super column name CBuilder builder = type.builder(); Composite start = filter.start().isEmpty() ? Composites.EMPTY : builder.buildWith(filter.start().toByteBuffer()).withEOC(filter.reversed ? Composite.EOC.END : Composite.EOC.START); Composite finish = filter.finish().isEmpty() ? Composites.EMPTY : builder.buildWith(filter.finish().toByteBuffer()).withEOC(filter.reversed ? Composite.EOC.START : Composite.EOC.END); return new SliceQueryFilter(start, finish, filter.reversed, filter.count, 1); } else { CBuilder builder = type.builder().add(scName); Composite start = filter.start().isEmpty() ? builder.build().withEOC(filter.reversed ? Composite.EOC.END : Composite.EOC.START) : builder.buildWith(filter.start().toByteBuffer()); Composite end = filter.finish().isEmpty() ? builder.build().withEOC(filter.reversed ? Composite.EOC.START : Composite.EOC.END) : builder.buildWith(filter.finish().toByteBuffer()); return new SliceQueryFilter(start, end, filter.reversed, filter.count); } } }
public boolean isFullyCoveredBy(ColumnFamily cf, long now) { // cf is the beginning of a partition. It covers this filter if: // 1) either this filter requests the head of the partition and request less // than what cf has to offer (note: we do need to use getLiveCount() for that // as it knows if the filter count cells or CQL3 rows). // 2) the start and finish bound of this filter are included in cf. if (isHeadFilter() && count <= getLiveCount(cf, now)) return true; if (start().isEmpty() || finish().isEmpty() || !cf.hasColumns()) return false; Composite low = isReversed() ? finish() : start(); Composite high = isReversed() ? start() : finish(); CellName first = cf.iterator(ColumnSlice.ALL_COLUMNS_ARRAY).next().name(); CellName last = cf.reverseIterator(ColumnSlice.ALL_COLUMNS_ARRAY).next().name(); return cf.getComparator().compare(first, low) <= 0 && cf.getComparator().compare(high, last) <= 0; }
/** * Splits this filter into two SliceQueryFilters: one that slices only the static columns, and one that slices the * remainder of the normal data. * * This should only be called when the filter is reversed and the filter is known to cover static columns (through * hasStaticSlice()). * * @return a pair of (static, normal) SliceQueryFilters */ public Pair<SliceQueryFilter, SliceQueryFilter> splitOutStaticSlice(CFMetaData cfm) { assert reversed; Composite staticSliceEnd = cfm.comparator.staticPrefix().end(); List<ColumnSlice> nonStaticSlices = new ArrayList<>(slices.length); for (ColumnSlice slice : slices) { if (sliceIncludesStatics(slice, cfm)) nonStaticSlices.add(new ColumnSlice(slice.start, staticSliceEnd)); else nonStaticSlices.add(slice); } return Pair.create( new SliceQueryFilter(staticSliceEnd, Composites.EMPTY, true, count, compositesToGroup), new SliceQueryFilter(nonStaticSlices.toArray(new ColumnSlice[nonStaticSlices.size()]), true, count, compositesToGroup)); }
? new ColumnSlice[]{ baseCfs.metadata.comparator.staticPrefix().slice(), dataSlice } : new ColumnSlice[]{ dataSlice }; SliceQueryFilter dataFilter = new SliceQueryFilter(slices, false, Integer.MAX_VALUE, baseCfs.metadata.clusteringColumns().size()); ColumnFamily newData = baseCfs.getColumnFamily(new QueryFilter(dk, baseCfs.name, dataFilter, filter.timestamp)); if (newData == null || index.isStale(entry, newData, filter.timestamp)) data = ArrayBackedSortedColumns.factory.create(baseCfs.metadata); data.addAll(newData); columnsCount += dataFilter.lastCounted();
@Override public ReadCommand maybeGenerateRetryCommand(RowDataResolver resolver, Row row) { int maxLiveColumns = resolver.getMaxLiveCount(); int count = filter.count; // We generate a retry if at least one node reply with count live columns but after merge we have less // than the total number of column we are interested in (which may be < count on a retry). // So in particular, if no host returned count live columns, we know it's not a short read. if (maxLiveColumns < count) return null; int liveCountInRow = row == null || row.cf == null ? 0 : filter.getLiveCount(row.cf, timestamp); if (liveCountInRow < getOriginalRequestedCount()) { // We asked t (= count) live columns and got l (=liveCountInRow) ones. // From that, we can estimate that on this row, for x requested // columns, only l/t end up live after reconciliation. So for next // round we want to ask x column so that x * (l/t) == t, i.e. x = t^2/l. int retryCount = liveCountInRow == 0 ? count + 1 : ((count * count) / liveCountInRow) + 1; SliceQueryFilter newFilter = filter.withUpdatedCount(retryCount); return new RetriedSliceFromReadCommand(ksName, key, cfName, timestamp, newFilter, getOriginalRequestedCount()); } return null; }
public Row getRow(Keyspace keyspace) { CFMetaData cfm = Schema.instance.getCFMetaData(ksName, cfName); DecoratedKey dk = StorageService.getPartitioner().decorateKey(key); // If we're doing a reversed query and the filter includes static columns, we need to issue two separate // reads in order to guarantee that the static columns are fetched. See CASSANDRA-8502 for more details. if (filter.reversed && filter.hasStaticSlice(cfm)) { logger.debug("Splitting reversed slice with static columns into two reads"); Pair<SliceQueryFilter, SliceQueryFilter> newFilters = filter.splitOutStaticSlice(cfm); Row normalResults = keyspace.getRow(new QueryFilter(dk, cfName, newFilters.right, timestamp)); Row staticResults = keyspace.getRow(new QueryFilter(dk, cfName, newFilters.left, timestamp)); // add the static results to the start of the normal results if (normalResults.cf == null) return staticResults; if (staticResults.cf != null) for (Cell cell : staticResults.cf.getReverseSortedColumns()) normalResults.cf.addColumn(cell); return normalResults; } return keyspace.getRow(new QueryFilter(dk, cfName, filter, timestamp)); }
public void collectReducedColumns(ColumnFamily container, Iterator<Cell> reducedColumns, DecoratedKey key, int gcBefore, long now) columnCounter = columnCounter(container.getComparator(), now); DeletionInfo.InOrderTester tester = container.deletionInfo().inOrderTester(reversed); break; if (respectTombstoneThresholds() && columnCounter.tombstones() > DatabaseDescriptor.getTombstoneFailureThreshold()) if (logger.isWarnEnabled() && respectTombstoneThresholds() && columnCounter.tombstones() > DatabaseDescriptor.getTombstoneWarnThreshold())
if (toCache != null) Tracing.trace("Populating row cache ({} rows cached)", cacheSlice.lastCounted()); data = filterColumnFamily(toCache, filter); if (sliceFilter.finish().isEmpty() || sliceFilter.lastCounted() >= rowsToCache) Tracing.trace("Caching {} rows (out of {} requested)", cacheSlice.lastCounted(), sliceFilter.count); Tracing.trace("Not populating row cache, not enough rows fetched ({} fetched but {} required for the cache)", sliceFilter.lastCounted(), rowsToCache);
public int getLiveCount(ColumnFamily cf, long now) { return columnCounter(cf.getComparator(), now).countAll(cf).live(); }
public AbstractRangeCommand withUpdatedLimit(int newLimit) { return new PagedRangeCommand(keyspace, columnFamily, timestamp, keyRange, ((SliceQueryFilter) predicate).cloneShallow(), start, stop, rowFilter, newLimit, countCQL3Rows); }
/** * Convenience method that count (live) cells/rows for a given slice of a row, but page underneath. */ public static int countPaged(String keyspace, String columnFamily, ByteBuffer key, SliceQueryFilter filter, ConsistencyLevel consistencyLevel, ClientState cState, final int pageSize, long now) throws RequestValidationException, RequestExecutionException { SliceFromReadCommand command = new SliceFromReadCommand(keyspace, key, columnFamily, now, filter); final SliceQueryPager pager = new SliceQueryPager(command, consistencyLevel, cState, false); ColumnCounter counter = filter.columnCounter(Schema.instance.getCFMetaData(keyspace, columnFamily).comparator, now); while (!pager.isExhausted()) { List<Row> next = pager.fetchPage(pageSize); if (!next.isEmpty()) counter.countAll(next.get(0).cf); } return counter.live(); } }
public SliceQueryFilter withUpdatedCount(int newCount) { return new SliceQueryFilter(slices, reversed, newCount, compositesToGroup); }
protected List<Row> queryNextPage(int pageSize, ConsistencyLevel consistencyLevel, boolean localQuery) throws RequestExecutionException { SliceQueryFilter sf = (SliceQueryFilter)columnFilter; AbstractBounds<RowPosition> keyRange = lastReturnedKey == null ? command.keyRange : makeIncludingKeyBounds(lastReturnedKey); Composite start = lastReturnedName == null ? sf.start() : lastReturnedName; PagedRangeCommand pageCmd = new PagedRangeCommand(command.keyspace, command.columnFamily, command.timestamp, keyRange, sf, start, sf.finish(), command.rowFilter, pageSize, command.countCQL3Rows); return localQuery ? pageCmd.executeLocally() : StorageProxy.getRangeSlice(pageCmd, consistencyLevel); }
public ColumnFamily trim(ColumnFamily cf, int trimTo, long now) { // each cell can increment the count by at most one, so if we have fewer cells than trimTo, we can skip trimming if (cf.getColumnCount() < trimTo) return cf; ColumnCounter counter = columnCounter(cf.getComparator(), now); ColumnFamily trimmedCf = cf.getFactory().create(cf.metadata(), reversed, trimTo); trimmedCf.delete(cf); Collection<Cell> cells = reversed ? cf.getReverseSortedColumns() : cf.getSortedColumns(); DeletionInfo.InOrderTester tester = cf.deletionInfo().inOrderTester(reversed); for (Iterator<Cell> iter = cells.iterator(); iter.hasNext(); ) { Cell cell = iter.next(); counter.count(cell, tester); if (counter.live() > trimTo) { break; } else { trimmedCf.addColumn(cell); } } return trimmedCf; }