@Override public ColumnCount getColumnHint() { if (columns != null) { if (columnIndex < columns.length) { return new ColumnCount(columns[columnIndex]); } } return null; }
@Override public void reset() { this.index = 0; this.column = this.columns[this.index]; for (ColumnCount col : this.columns) { col.setCount(0); } resetTS(); }
@Override public void doneWithColumn(Cell cell) { while (this.column != null) { int compare = CellUtil.compareQualifiers(cell, column.getBuffer(), column.getOffset(), column.getLength()); resetTS(); if (compare >= 0) { ++this.index; if (done()) { // Will not hit any more columns in this storefile this.column = null; } else { this.column = this.columns[this.index]; } if (compare > 0) { continue; } } return; } }
@Override public ScanQueryMatcher.MatchCode checkVersions(Cell cell, long timestamp, byte type, boolean ignoreCount) throws IOException { assert !PrivateCellUtil.isDelete(type); if (ignoreCount) { return ScanQueryMatcher.MatchCode.INCLUDE; } // Check if it is a duplicate timestamp if (sameAsPreviousTS(timestamp)) { // If duplicate, skip this Key return ScanQueryMatcher.MatchCode.SKIP; } int count = this.column.increment(); if (count >= maxVersions || (count >= minVersions && isExpired(timestamp))) { // Done with versions for this column ++this.index; resetTS(); if (done()) { // We have served all the requested columns. this.column = null; return ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_ROW; } // We are done with current column; advance to next column // of interest. this.column = this.columns[this.index]; return ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL; } setTS(timestamp); return ScanQueryMatcher.MatchCode.INCLUDE; }
public Cell getKeyForNextColumn(Cell cell) { // We aren't sure whether any DeleteFamily cells exist, so we can't skip to next column. // TODO: Current way disable us to seek to next column quickly. Is there any better solution? // see HBASE-18471 for more details // see TestFromClientSide3#testScanAfterDeletingSpecifiedRow // see TestFromClientSide3#testScanAfterDeletingSpecifiedRowV2 if (cell.getQualifierLength() == 0) { Cell nextKey = PrivateCellUtil.createNextOnRowCol(cell); if (nextKey != cell) { return nextKey; } // The cell is at the end of row/family/qualifier, so it is impossible to find any DeleteFamily cells. // Let us seek to next column. } ColumnCount nextColumn = columns.getColumnHint(); if (nextColumn == null) { return PrivateCellUtil.createLastOnRowCol(cell); } else { return PrivateCellUtil.createFirstOnRowCol(cell, nextColumn.getBuffer(), nextColumn.getOffset(), nextColumn.getLength()); } }
/** * @param nextIndexed the key of the next entry in the block index (if any) * @param currentCell The Cell we're using to calculate the seek key * @return result of the compare between the indexed key and the key portion of the passed cell */ public int compareKeyForNextColumn(Cell nextIndexed, Cell currentCell) { ColumnCount nextColumn = columns.getColumnHint(); if (nextColumn == null) { return PrivateCellUtil.compareKeyBasedOnColHint(rowComparator, nextIndexed, currentCell, 0, 0, null, 0, 0, HConstants.OLDEST_TIMESTAMP, Type.Minimum.getCode()); } else { return PrivateCellUtil.compareKeyBasedOnColHint(rowComparator, nextIndexed, currentCell, currentCell.getFamilyOffset(), currentCell.getFamilyLength(), nextColumn.getBuffer(), nextColumn.getOffset(), nextColumn.getLength(), HConstants.LATEST_TIMESTAMP, Type.Maximum.getCode()); } }
/** * Default constructor. * @param columns columns specified user in query * @param minVersions minimum number of versions to keep * @param maxVersions maximum versions to return per column * @param oldestUnexpiredTS the oldest timestamp we are interested in, based on TTL */ public ExplicitColumnTracker(NavigableSet<byte[]> columns, int minVersions, int maxVersions, long oldestUnexpiredTS) { this.maxVersions = maxVersions; this.minVersions = minVersions; this.oldestStamp = oldestUnexpiredTS; this.columns = new ColumnCount[columns.size()]; int i = 0; for (byte[] column : columns) { this.columns[i++] = new ColumnCount(column); } reset(); }