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.CellUtil;
24 import org.apache.hadoop.hbase.KeyValueUtil;
25 import org.apache.hadoop.hbase.classification.InterfaceAudience;
26
27 import java.io.IOException;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.List;
31
32
33
34
35
36 @InterfaceAudience.Private
37 public class FilterListWithOR extends FilterListBase {
38
39
40
41
42
43
44 private List<ReturnCode> prevFilterRCList = null;
45 private List<Cell> prevCellList = null;
46
47 public FilterListWithOR(List<Filter> filters) {
48 super(filters);
49 prevFilterRCList =
50 new ArrayList<ReturnCode>(Collections.nCopies(filters.size(), (ReturnCode) null));
51 prevCellList = new ArrayList<Cell>(Collections.nCopies(filters.size(), (Cell) null));
52 subFiltersIncludedCell = new ArrayList<Boolean>(Collections.nCopies(filters.size(), false));
53 }
54
55 @Override
56 public void addFilterLists(List<Filter> filters) {
57 if (checkAndGetReversed(filters, isReversed()) != isReversed()) {
58 throw new IllegalArgumentException("Filters in the list must have the same reversed flag");
59 }
60 this.filters.addAll(filters);
61 this.subFiltersIncludedCell.addAll(Collections.nCopies(filters.size(), false));
62 this.prevFilterRCList.addAll(Collections.nCopies(filters.size(), (ReturnCode) null));
63 this.prevCellList.addAll(Collections.nCopies(filters.size(), (Cell) null));
64 }
65
66 @Override
67 protected String formatLogFilters(List<Filter> logFilters) {
68 return String.format("FilterList OR (%d/%d): %s", logFilters.size(), this.size(),
69 logFilters.toString());
70 }
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 private boolean shouldPassCurrentCellToFilter(Cell prevCell, Cell currentCell,
88 ReturnCode prevCode) throws IOException {
89 if (prevCell == null || prevCode == null) {
90 return true;
91 }
92 switch (prevCode) {
93 case INCLUDE:
94 case SKIP:
95 return true;
96 case SEEK_NEXT_USING_HINT:
97 Cell nextHintCell = getNextCellHint(prevCell);
98 return nextHintCell == null || this.compareCell(currentCell, nextHintCell) >= 0;
99 case NEXT_COL:
100 case INCLUDE_AND_NEXT_COL:
101
102
103 return !CellUtil.matchingColumn(prevCell, currentCell);
104 case NEXT_ROW:
105 case INCLUDE_AND_SEEK_NEXT_ROW:
106
107 return !CellUtil.matchingFamily(prevCell, currentCell);
108 default:
109 throw new IllegalStateException("Received code is not valid.");
110 }
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147 private ReturnCode mergeReturnCode(ReturnCode rc, ReturnCode localRC) {
148 if (rc == null) return localRC;
149 switch (localRC) {
150 case INCLUDE:
151 return ReturnCode.INCLUDE;
152 case INCLUDE_AND_NEXT_COL:
153 if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.SKIP,
154 ReturnCode.SEEK_NEXT_USING_HINT)) {
155 return ReturnCode.INCLUDE;
156 }
157 if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW,
158 ReturnCode.NEXT_COL, ReturnCode.NEXT_ROW)) {
159 return ReturnCode.INCLUDE_AND_NEXT_COL;
160 }
161 break;
162 case INCLUDE_AND_SEEK_NEXT_ROW:
163 if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.SKIP,
164 ReturnCode.SEEK_NEXT_USING_HINT)) {
165 return ReturnCode.INCLUDE;
166 }
167 if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_NEXT_COL, ReturnCode.NEXT_COL)) {
168 return ReturnCode.INCLUDE_AND_NEXT_COL;
169 }
170 if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW, ReturnCode.NEXT_ROW)) {
171 return ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW;
172 }
173 break;
174 case SKIP:
175 if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL,
176 ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) {
177 return ReturnCode.INCLUDE;
178 }
179 if (isInReturnCodes(rc, ReturnCode.SKIP, ReturnCode.NEXT_COL, ReturnCode.NEXT_ROW,
180 ReturnCode.SEEK_NEXT_USING_HINT)) {
181 return ReturnCode.SKIP;
182 }
183 break;
184 case NEXT_COL:
185 if (isInReturnCodes(rc, ReturnCode.INCLUDE)) {
186 return ReturnCode.INCLUDE;
187 }
188 if (isInReturnCodes(rc, ReturnCode.NEXT_COL, ReturnCode.NEXT_ROW)) {
189 return ReturnCode.NEXT_COL;
190 }
191 if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_NEXT_COL,
192 ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) {
193 return ReturnCode.INCLUDE_AND_NEXT_COL;
194 }
195 if (isInReturnCodes(rc, ReturnCode.SKIP, ReturnCode.SEEK_NEXT_USING_HINT)) {
196 return ReturnCode.SKIP;
197 }
198 break;
199 case NEXT_ROW:
200 if (isInReturnCodes(rc, ReturnCode.INCLUDE)) {
201 return ReturnCode.INCLUDE;
202 }
203 if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_NEXT_COL)) {
204 return ReturnCode.INCLUDE_AND_NEXT_COL;
205 }
206 if (isInReturnCodes(rc, ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) {
207 return ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW;
208 }
209 if (isInReturnCodes(rc, ReturnCode.SKIP, ReturnCode.SEEK_NEXT_USING_HINT)) {
210 return ReturnCode.SKIP;
211 }
212 if (isInReturnCodes(rc, ReturnCode.NEXT_COL)) {
213 return ReturnCode.NEXT_COL;
214 }
215 if (isInReturnCodes(rc, ReturnCode.NEXT_ROW)) {
216 return ReturnCode.NEXT_ROW;
217 }
218 break;
219 case SEEK_NEXT_USING_HINT:
220 if (isInReturnCodes(rc, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL,
221 ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) {
222 return ReturnCode.INCLUDE;
223 }
224 if (isInReturnCodes(rc, ReturnCode.SKIP, ReturnCode.NEXT_COL, ReturnCode.NEXT_ROW)) {
225 return ReturnCode.SKIP;
226 }
227 if (isInReturnCodes(rc, ReturnCode.SEEK_NEXT_USING_HINT)) {
228 return ReturnCode.SEEK_NEXT_USING_HINT;
229 }
230 break;
231 }
232 throw new IllegalStateException(
233 "Received code is not valid. rc: " + rc + ", localRC: " + localRC);
234 }
235
236 private void updatePrevFilterRCList(int index, ReturnCode currentRC) {
237 prevFilterRCList.set(index, currentRC);
238 }
239
240 private void updatePrevCellList(int index, Cell currentCell, ReturnCode currentRC) {
241 if (currentCell == null || currentRC == ReturnCode.INCLUDE || currentRC == ReturnCode.SKIP) {
242
243
244
245 prevCellList.set(index, null);
246 } else {
247 prevCellList.set(index, KeyValueUtil.copyToNewKeyValue(currentCell));
248 }
249 }
250
251 @Override
252 public ReturnCode filterKeyValue(Cell c) throws IOException {
253 if (isEmpty()) {
254 return ReturnCode.INCLUDE;
255 }
256 ReturnCode rc = null;
257 boolean everyFilterReturnHint = true;
258 for (int i = 0, n = filters.size(); i < n; i++) {
259 Filter filter = filters.get(i);
260 subFiltersIncludedCell.set(i, false);
261
262 Cell prevCell = this.prevCellList.get(i);
263 ReturnCode prevCode = this.prevFilterRCList.get(i);
264 if (filter.filterAllRemaining() || !shouldPassCurrentCellToFilter(prevCell, c, prevCode)) {
265 everyFilterReturnHint = false;
266 continue;
267 }
268
269 ReturnCode localRC = filter.filterKeyValue(c);
270
271
272 updatePrevFilterRCList(i, localRC);
273 updatePrevCellList(i, c, localRC);
274
275 if (localRC != ReturnCode.SEEK_NEXT_USING_HINT) {
276 everyFilterReturnHint = false;
277 }
278
279 rc = mergeReturnCode(rc, localRC);
280
281
282 if (isInReturnCodes(localRC, ReturnCode.INCLUDE, ReturnCode.INCLUDE_AND_NEXT_COL,
283 ReturnCode.INCLUDE_AND_SEEK_NEXT_ROW)) {
284 subFiltersIncludedCell.set(i, true);
285 }
286 }
287
288 if (everyFilterReturnHint) {
289 return ReturnCode.SEEK_NEXT_USING_HINT;
290 } else if (rc == null) {
291
292 return ReturnCode.SKIP;
293 } else {
294 return rc;
295 }
296 }
297
298 @Override
299 public void reset() throws IOException {
300 for (int i = 0, n = filters.size(); i < n; i++) {
301 filters.get(i).reset();
302 subFiltersIncludedCell.set(i, false);
303 prevFilterRCList.set(i, null);
304 prevCellList.set(i, null);
305 }
306 }
307
308 @Override
309 public boolean filterRowKey(byte[] rowKey, int offset, int length) throws IOException {
310 if (isEmpty()) {
311 return super.filterRowKey(rowKey, offset, length);
312 }
313 boolean retVal = true;
314 for (int i = 0, n = filters.size(); i < n; i++) {
315 Filter filter = filters.get(i);
316 if (!filter.filterAllRemaining() && !filter.filterRowKey(rowKey, offset, length)) {
317 retVal = false;
318 }
319 }
320 return retVal;
321 }
322
323 @Override
324 public boolean filterAllRemaining() throws IOException {
325 if (isEmpty()) {
326 return super.filterAllRemaining();
327 }
328 for (int i = 0, n = filters.size(); i < n; i++) {
329 if (!filters.get(i).filterAllRemaining()) {
330 return false;
331 }
332 }
333 return true;
334 }
335
336 @Override
337 public boolean filterRow() throws IOException {
338 if (isEmpty()) {
339 return super.filterRow();
340 }
341 for (int i = 0, n = filters.size(); i < n; i++) {
342 Filter filter = filters.get(i);
343 if (!filter.filterRow()) {
344 return false;
345 }
346 }
347 return true;
348 }
349
350 @Override
351 public Cell getNextCellHint(Cell currentCell) throws IOException {
352 if (isEmpty()) {
353 return super.getNextCellHint(currentCell);
354 }
355 Cell minKeyHint = null;
356
357 for (int i = 0, n = filters.size(); i < n; i++) {
358 if (filters.get(i).filterAllRemaining()) {
359 continue;
360 }
361 Cell curKeyHint = filters.get(i).getNextCellHint(currentCell);
362 if (curKeyHint == null) {
363
364 return null;
365 }
366
367 if (minKeyHint == null) {
368 minKeyHint = curKeyHint;
369 continue;
370 }
371 if (this.compareCell(minKeyHint, curKeyHint) > 0) {
372 minKeyHint = curKeyHint;
373 }
374 }
375 return minKeyHint;
376 }
377 }