/** * Constructor that takes a set of {@link Filter}s and an operator. * @param operator Operator to process filter set with. * @param filters Set of row filters. */ public FilterList(final Operator operator, final List<Filter> filters) { if (operator == Operator.MUST_PASS_ALL) { filterListBase = new FilterListWithAND(filters); } else if (operator == Operator.MUST_PASS_ONE) { filterListBase = new FilterListWithOR(filters); } else { throw new IllegalArgumentException("Invalid operator: " + operator); } this.operator = operator; }
@Override public void addFilterLists(List<Filter> filters) { if (checkAndGetReversed(filters, isReversed()) != isReversed()) { throw new IllegalArgumentException("Filters in the list must have the same reversed flag"); } this.filters.addAll(filters); this.subFiltersIncludedCell.addAll(Collections.nCopies(filters.size(), false)); this.prevFilterRCList.addAll(Collections.nCopies(filters.size(), null)); this.prevCellList.addAll(Collections.nCopies(filters.size(), null)); }
@Override public Cell getNextCellHint(Cell currentCell) throws IOException { if (isEmpty()) { return super.getNextCellHint(currentCell); } Cell minKeyHint = null; // If any condition can pass, we need to keep the min hint for (int i = 0, n = filters.size(); i < n; i++) { if (filters.get(i).filterAllRemaining()) { continue; } Cell curKeyHint = filters.get(i).getNextCellHint(currentCell); if (curKeyHint == null) { // If we ever don't have a hint and this is must-pass-one, then no hint return null; } // If this is the first hint we find, set it if (minKeyHint == null) { minKeyHint = curKeyHint; continue; } if (this.compareCell(minKeyHint, curKeyHint) > 0) { minKeyHint = curKeyHint; } } return minKeyHint; }
@Override public ReturnCode filterCell(Cell c) throws IOException { if (isEmpty()) { return ReturnCode.INCLUDE; continue; ReturnCode localRC = calculateReturnCodeByPrevCellAndRC(filter, c, prevCell, prevCode); if (localRC == null) { updatePrevFilterRCList(i, localRC); updatePrevCellList(i, c, localRC); rc = mergeReturnCode(rc, localRC); if (isInReturnCodes(localRC, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) { subFiltersIncludedCell.set(i, true);
@Override public ReturnCode filterCell(Cell c) throws IOException { if (isEmpty()) { return ReturnCode.INCLUDE; if (filter.filterAllRemaining() || !shouldPassCurrentCellToFilter(prevCell, c, prevCode)) { everyFilterReturnHint = false; continue; updatePrevFilterRCList(i, localRC); updatePrevCellList(i, c, localRC); rc = mergeReturnCode(rc, localRC); if (isInReturnCodes(localRC, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) { subFiltersIncludedCell.set(i, true);
@Override public boolean filterAllRemaining() throws IOException { if (isEmpty()) { return super.filterAllRemaining(); } for (int i = 0, n = filters.size(); i < n; i++) { if (!filters.get(i).filterAllRemaining()) { return false; } } return true; }
return true; case SEEK_NEXT_USING_HINT: Cell nextHintCell = getNextCellHint(prevCell); return nextHintCell == null || this.compareCell(currentCell, nextHintCell) >= 0; case NEXT_COL: case INCLUDE_AND_NEXT_COL:
@Override protected String formatLogFilters(List<Filter> logFilters) { return String.format("FilterList OR (%d/%d): %s", logFilters.size(), this.size(), logFilters.toString()); }
return ReturnCode.INCLUDE; case INCLUDE_AND_NEXT_COL: if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.SKIP, ReturnCode.SEEK_NEXT_USING_HINT)) { return ReturnCode.INCLUDE; if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW, ReturnCode.NEXT_COL, ReturnCode.NEXT_ROW)) { return ReturnCode.INCLUDE_AND_NEXT_COL; if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.SKIP, ReturnCode.SEEK_NEXT_USING_HINT)) { return ReturnCode.INCLUDE; if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.NEXT_COL)) { return ReturnCode.INCLUDE_AND_NEXT_COL; if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW, ReturnCode.NEXT_ROW)) { return ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW; if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) { return ReturnCode.INCLUDE; if (isInReturnCodes(rc, ReturnCode.SKIP, ReturnCode.NEXT_COL, ReturnCode.NEXT_ROW, ReturnCode.SEEK_NEXT_USING_HINT)) { return ReturnCode.SKIP; if (isInReturnCodes(rc, ReturnCode.INCLUDE)) {
case SEEK_NEXT_USING_HINT: Cell nextHintCell = subFilter.getNextCellHint(prevCell); return nextHintCell != null && compareCell(currentCell, nextHintCell) < 0 ? ReturnCode.SEEK_NEXT_USING_HINT : null; case NEXT_COL:
@Override public ReturnCode filterCell(Cell c) throws IOException { if (isEmpty()) { return ReturnCode.INCLUDE; continue; ReturnCode localRC = calculateReturnCodeByPrevCellAndRC(filter, c, prevCell, prevCode); if (localRC == null) { updatePrevFilterRCList(i, localRC); updatePrevCellList(i, c, localRC); rc = mergeReturnCode(rc, localRC); if (isInReturnCodes(localRC, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) { subFiltersIncludedCell.set(i, true);
@Override public boolean filterRow() throws IOException { if (isEmpty()) { return super.filterRow(); } for (int i = 0, n = filters.size(); i < n; i++) { Filter filter = filters.get(i); if (!filter.filterRow()) { return false; } } return true; }
@Override protected String formatLogFilters(List<Filter> logFilters) { return String.format("FilterList OR (%d/%d): %s", logFilters.size(), this.size(), logFilters.toString()); }
return ReturnCode.INCLUDE; case INCLUDE_AND_NEXT_COL: if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.SKIP, ReturnCode.SEEK_NEXT_USING_HINT)) { return ReturnCode.INCLUDE; if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW, ReturnCode.NEXT_COL, ReturnCode.NEXT_ROW)) { return ReturnCode.INCLUDE_AND_NEXT_COL; if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.SKIP, ReturnCode.SEEK_NEXT_USING_HINT)) { return ReturnCode.INCLUDE; if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.NEXT_COL)) { return ReturnCode.INCLUDE_AND_NEXT_COL; if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW, ReturnCode.NEXT_ROW)) { return ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW; if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) { return ReturnCode.INCLUDE; if (isInReturnCodes(rc, ReturnCode.SKIP, ReturnCode.NEXT_COL, ReturnCode.NEXT_ROW, ReturnCode.SEEK_NEXT_USING_HINT)) { return ReturnCode.SKIP; if (isInReturnCodes(rc, ReturnCode.INCLUDE)) {
case SEEK_NEXT_USING_HINT: Cell nextHintCell = subFilter.getNextCellHint(prevCell); return nextHintCell != null && compareCell(currentCell, nextHintCell) < 0 ? ReturnCode.SEEK_NEXT_USING_HINT : null; case NEXT_COL:
@Override public boolean filterRowKey(byte[] rowKey, int offset, int length) throws IOException { if (isEmpty()) { return super.filterRowKey(rowKey, offset, length); } boolean retVal = true; for (int i = 0, n = filters.size(); i < n; i++) { Filter filter = filters.get(i); if (!filter.filterAllRemaining() && !filter.filterRowKey(rowKey, offset, length)) { retVal = false; } } return retVal; }
@Override public void addFilterLists(List<Filter> filters) { if (checkAndGetReversed(filters, isReversed()) != isReversed()) { throw new IllegalArgumentException("Filters in the list must have the same reversed flag"); } this.filters.addAll(filters); this.subFiltersIncludedCell.addAll(Collections.nCopies(filters.size(), false)); this.prevFilterRCList.addAll(Collections.nCopies(filters.size(), null)); this.prevCellList.addAll(Collections.nCopies(filters.size(), null)); }
@Override public Cell getNextCellHint(Cell currentCell) throws IOException { if (isEmpty()) { return super.getNextCellHint(currentCell); } Cell minKeyHint = null; // If any condition can pass, we need to keep the min hint for (int i = 0, n = filters.size(); i < n; i++) { if (filters.get(i).filterAllRemaining()) { continue; } Cell curKeyHint = filters.get(i).getNextCellHint(currentCell); if (curKeyHint == null) { // If we ever don't have a hint and this is must-pass-one, then no hint return null; } // If this is the first hint we find, set it if (minKeyHint == null) { minKeyHint = curKeyHint; continue; } if (this.compareCell(minKeyHint, curKeyHint) > 0) { minKeyHint = curKeyHint; } } return minKeyHint; } }
@Override protected String formatLogFilters(List<Filter> logFilters) { return String.format("FilterList OR (%d/%d): %s", logFilters.size(), this.size(), logFilters.toString()); }
/** * Constructor that takes a set of {@link Filter}s and an operator. * @param operator Operator to process filter set with. * @param filters Set of row filters. */ public FilterList(final Operator operator, final List<Filter> filters) { if (operator == Operator.MUST_PASS_ALL) { filterListBase = new FilterListWithAND(filters); } else if (operator == Operator.MUST_PASS_ONE) { filterListBase = new FilterListWithOR(filters); } else { throw new IllegalArgumentException("Invalid operator: " + operator); } this.operator = operator; }