1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.filter;
21
22 import org.apache.hadoop.hbase.Cell;
23 import org.apache.hadoop.hbase.classification.InterfaceAudience;
24
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.Objects;
30
31
32
33
34
35 @InterfaceAudience.Private
36 public class FilterListWithAND extends FilterListBase {
37
38 private List<Filter> seekHintFilters = new ArrayList<>();
39
40 public FilterListWithAND(List<Filter> filters) {
41 super(filters);
42
43
44
45 subFiltersIncludedCell = new ArrayList<>(Collections.nCopies(filters.size(), true));
46 }
47
48 @Override
49 public void addFilterLists(List<Filter> filters) {
50 if (checkAndGetReversed(filters, isReversed()) != isReversed()) {
51 throw new IllegalArgumentException("Filters in the list must have the same reversed flag");
52 }
53 this.filters.addAll(filters);
54 this.subFiltersIncludedCell.addAll(Collections.nCopies(filters.size(), true));
55 }
56
57 @Override
58 protected String formatLogFilters(List<Filter> logFilters) {
59 return String.format("FilterList AND (%d/%d): %s", logFilters.size(), this.size(),
60 logFilters.toString());
61 }
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 private ReturnCode mergeReturnCode(ReturnCode rc, ReturnCode localRC) {
100 if (rc == ReturnCode.SEEK_NEXT_USING_HINT) {
101 return ReturnCode.SEEK_NEXT_USING_HINT;
102 }
103 switch (localRC) {
104 case SEEK_NEXT_USING_HINT:
105 return ReturnCode.SEEK_NEXT_USING_HINT;
106 case INCLUDE:
107 return rc;
108 case INCLUDE_AND_NEXT_COL:
109 if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL)) {
110 return ReturnCode.INCLUDE_AND_NEXT_COL;
111 }
112 if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) {
113 return ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW;
114 }
115 if (isInReturnCodes(rc, ReturnCode.SKIP, ReturnCode.NEXT_COL)) {
116 return ReturnCode.NEXT_COL;
117 }
118 if (isInReturnCodes(rc, ReturnCode.NEXT_ROW)) {
119 return ReturnCode.NEXT_ROW;
120 }
121 break;
122 case INCLUDE_AND_SEEK_NEXT_ROW:
123 if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL,
124 ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) {
125 return ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW;
126 }
127 if (isInReturnCodes(rc, ReturnCode.SKIP, ReturnCode.NEXT_COL, ReturnCode.NEXT_ROW)) {
128 return ReturnCode.NEXT_ROW;
129 }
130 break;
131 case SKIP:
132 if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.SKIP)) {
133 return ReturnCode.SKIP;
134 }
135 if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.NEXT_COL)) {
136 return ReturnCode.NEXT_COL;
137 }
138 if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW, ReturnCode.NEXT_ROW)) {
139 return ReturnCode.NEXT_ROW;
140 }
141 break;
142 case NEXT_COL:
143 if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.SKIP,
144 ReturnCode.NEXT_COL)) {
145 return ReturnCode.NEXT_COL;
146 }
147 if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW, ReturnCode.NEXT_ROW)) {
148 return ReturnCode.NEXT_ROW;
149 }
150 break;
151 case NEXT_ROW:
152 return ReturnCode.NEXT_ROW;
153 }
154 throw new IllegalStateException(
155 "Received code is not valid. rc: " + rc + ", localRC: " + localRC);
156 }
157
158 private boolean isIncludeRelatedReturnCode(ReturnCode rc) {
159 return isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL,
160 ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW);
161 }
162
163 @Override
164 public ReturnCode filterKeyValue(Cell c) throws IOException {
165 if (isEmpty()) {
166 return ReturnCode.INCLUDE;
167 }
168 ReturnCode rc = ReturnCode.INCLUDE;
169 this.seekHintFilters.clear();
170 for (int i = 0, n = filters.size(); i < n; i++) {
171 Filter filter = filters.get(i);
172 if (filter.filterAllRemaining()) {
173 return ReturnCode.NEXT_ROW;
174 }
175 ReturnCode localRC = filter.filterKeyValue(c);
176 if (localRC == ReturnCode.SEEK_NEXT_USING_HINT) {
177 seekHintFilters.add(filter);
178 }
179 rc = mergeReturnCode(rc, localRC);
180
181
182
183 if (!isIncludeRelatedReturnCode(rc)) {
184 return rc;
185 }
186 }
187 if (!seekHintFilters.isEmpty()) {
188 return ReturnCode.SEEK_NEXT_USING_HINT;
189 }
190 return rc;
191 }
192
193 @Override
194 public void reset() throws IOException {
195 for (int i = 0, n = filters.size(); i < n; i++) {
196 filters.get(i).reset();
197 }
198 seekHintFilters.clear();
199 }
200
201 @Override
202 public boolean filterRowKey(byte[] rowKey, int offset, int length) throws IOException {
203 if (isEmpty()) {
204 return super.filterRowKey(rowKey, offset, length);
205 }
206 boolean retVal = false;
207 for (int i = 0, n = filters.size(); i < n; i++) {
208 Filter filter = filters.get(i);
209 if (filter.filterAllRemaining() || filter.filterRowKey(rowKey, offset, length)) {
210 retVal = true;
211 }
212 }
213 return retVal;
214 }
215
216 @Override
217 public boolean filterAllRemaining() throws IOException {
218 if (isEmpty()) {
219 return super.filterAllRemaining();
220 }
221 for (int i = 0, n = filters.size(); i < n; i++) {
222 if (filters.get(i).filterAllRemaining()) {
223 return true;
224 }
225 }
226 return false;
227 }
228
229 @Override
230 public boolean filterRow() throws IOException {
231 if (isEmpty()) {
232 return super.filterRow();
233 }
234 for (int i = 0, n = filters.size(); i < n; i++) {
235 Filter filter = filters.get(i);
236 if (filter.filterRow()) {
237 return true;
238 }
239 }
240 return false;
241 }
242
243 @Override
244 public Cell getNextCellHint(Cell currentCell) throws IOException {
245 if (isEmpty()) {
246 return super.getNextCellHint(currentCell);
247 }
248 Cell maxHint = null;
249 for (Filter filter : seekHintFilters) {
250 if (filter.filterAllRemaining()) {
251 continue;
252 }
253 Cell curKeyHint = filter.getNextCellHint(currentCell);
254 if (maxHint == null) {
255 maxHint = curKeyHint;
256 continue;
257 }
258 if (this.compareCell(maxHint, curKeyHint) < 0) {
259 maxHint = curKeyHint;
260 }
261 }
262 return maxHint;
263 }
264
265 @Override
266 public boolean equals(Object obj) {
267 if (!(obj instanceof FilterListWithAND)) {
268 return false;
269 }
270 if (this == obj) {
271 return true;
272 }
273 FilterListWithAND f = (FilterListWithAND) obj;
274 return this.filters.equals(f.getFilters()) && this.seekHintFilters.equals(f.seekHintFilters);
275 }
276
277 @Override
278 public int hashCode() {
279 return Objects.hash(this.seekHintFilters, this.filters);
280 }
281 }