001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.filter; 019 020import java.io.IOException; 021import java.util.ArrayList; 022import java.util.List; 023import org.apache.hadoop.hbase.Cell; 024import org.apache.hadoop.hbase.CellComparator; 025import org.apache.yetus.audience.InterfaceAudience; 026 027/** 028 * Base class for FilterList. Currently, we have two sub-classes to extend this class: 029 * {@link FilterListWithOR}, {@link FilterListWithAND}. 030 */ 031@InterfaceAudience.Private 032public abstract class FilterListBase extends FilterBase { 033 private static final int MAX_LOG_FILTERS = 5; 034 protected final ArrayList<Filter> filters; 035 /** 036 * For each sub-filter in filter list, we save a boolean flag to indicate that whether the return 037 * code of filterCell(c) for sub-filter is INCLUDE* (INCLUDE, INCLUDE_AND_NEXT_COL, 038 * INCLUDE_AND_SEEK_NEXT_ROW) case. if true, we need to transform cell for the sub-filter. 039 */ 040 protected ArrayList<Boolean> subFiltersIncludedCell; 041 042 public FilterListBase(List<Filter> filters) { 043 reversed = checkAndGetReversed(filters, reversed); 044 this.filters = new ArrayList<>(filters); 045 } 046 047 protected static boolean isInReturnCodes(ReturnCode testRC, ReturnCode... returnCodes) { 048 for (ReturnCode rc : returnCodes) { 049 if (testRC == rc) { 050 return true; 051 } 052 } 053 return false; 054 } 055 056 protected static boolean checkAndGetReversed(List<Filter> rowFilters, boolean defaultValue) { 057 if (rowFilters.isEmpty()) { 058 return defaultValue; 059 } 060 boolean retValue = rowFilters.get(0).isReversed(); 061 for (int i = 1, n = rowFilters.size(); i < n; i++) { 062 if (rowFilters.get(i).isReversed() != retValue) { 063 throw new IllegalArgumentException("Filters in the list must have the same reversed flag"); 064 } 065 } 066 return retValue; 067 } 068 069 public abstract void addFilterLists(List<Filter> filters); 070 071 public int size() { 072 return this.filters.size(); 073 } 074 075 public boolean isEmpty() { 076 return this.filters.isEmpty(); 077 } 078 079 public ArrayList<Filter> getFilters() { 080 return this.filters; 081 } 082 083 protected int compareCell(Cell a, Cell b) { 084 int cmp = CellComparator.getInstance().compare(a, b); 085 return reversed ? -1 * cmp : cmp; 086 } 087 088 /** 089 * For FilterList, we can consider a filter list as a node in a tree. sub-filters of the filter 090 * list are children of the relative node. The logic of transforming cell of a filter list, well, 091 * we can consider it as the process of post-order tree traverse. For a node , before we traverse 092 * the current child, we should set the traverse result (transformed cell) of previous node(s) as 093 * the initial value. (HBASE-18879). 094 * @param c The cell in question. 095 * @return the transformed cell. 096 */ 097 @Override 098 public Cell transformCell(Cell c) throws IOException { 099 if (isEmpty()) { 100 return super.transformCell(c); 101 } 102 Cell transformed = c; 103 for (int i = 0, n = filters.size(); i < n; i++) { 104 if (subFiltersIncludedCell.get(i)) { 105 transformed = filters.get(i).transformCell(transformed); 106 } 107 } 108 return transformed; 109 } 110 111 /** 112 * Filters that never filter by modifying the returned List of Cells can inherit this 113 * implementation that does nothing. {@inheritDoc} 114 */ 115 @Override 116 public void filterRowCells(List<Cell> cells) throws IOException { 117 for (int i = 0, n = filters.size(); i < n; i++) { 118 filters.get(i).filterRowCells(cells); 119 } 120 } 121 122 @Override 123 public boolean hasFilterRow() { 124 for (int i = 0, n = filters.size(); i < n; i++) { 125 if (filters.get(i).hasFilterRow()) { 126 return true; 127 } 128 } 129 return false; 130 } 131 132 @Override 133 public boolean isFamilyEssential(byte[] name) throws IOException { 134 if (this.filters.isEmpty()) { 135 return super.isFamilyEssential(name); 136 } 137 for (int i = 0, n = filters.size(); i < n; i++) { 138 if (filters.get(i).isFamilyEssential(name)) { 139 return true; 140 } 141 } 142 return false; 143 } 144 145 @Override 146 public void setReversed(boolean reversed) { 147 for (int i = 0, n = filters.size(); i < n; i++) { 148 filters.get(i).setReversed(reversed); 149 } 150 this.reversed = reversed; 151 } 152 153 @Override 154 public String toString() { 155 int endIndex = this.size() < MAX_LOG_FILTERS ? this.size() : MAX_LOG_FILTERS; 156 return formatLogFilters(filters.subList(0, endIndex)); 157 } 158 159 protected abstract String formatLogFilters(List<Filter> logFilters); 160}