1 /*
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 package org.apache.hadoop.hbase.filter;
21
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import org.apache.hadoop.hbase.classification.InterfaceAudience;
27 import org.apache.hadoop.hbase.classification.InterfaceStability;
28 import org.apache.hadoop.hbase.Cell;
29 import org.apache.hadoop.hbase.KeyValue;
30 import org.apache.hadoop.hbase.KeyValueUtil;
31
32 /**
33 * Abstract base class to help you implement new Filters. Common "ignore" or NOOP type
34 * methods can go here, helping to reduce boiler plate in an ever-expanding filter
35 * library.
36 *
37 * If you could instantiate FilterBase, it would end up being a "null" filter -
38 * that is one that never filters anything.
39 */
40 @InterfaceAudience.Private // TODO add filter limited private level
41 public abstract class FilterBase extends Filter {
42
43 /**
44 * Filters that are purely stateless and do nothing in their reset() methods can inherit
45 * this null/empty implementation.
46 *
47 * @inheritDoc
48 */
49 @Override
50 public void reset() throws IOException {
51 }
52
53 /**
54 * Filters that do not filter by row key can inherit this implementation that
55 * never filters anything. (ie: returns false).
56 *
57 * @inheritDoc
58 */
59 @Override
60 public boolean filterRowKey(byte[] buffer, int offset, int length) throws IOException {
61 return false;
62 }
63
64 /**
65 * Filters that never filter all remaining can inherit this implementation that
66 * never stops the filter early.
67 *
68 * @inheritDoc
69 */
70 @Override
71 public boolean filterAllRemaining() throws IOException {
72 return false;
73 }
74
75 /**
76 * Filters that dont filter by key value can inherit this implementation that
77 * includes all Cells.
78 *
79 * @inheritDoc
80 */
81 @Override
82 public ReturnCode filterKeyValue(Cell ignored) throws IOException {
83 return ReturnCode.INCLUDE;
84 }
85
86 /**
87 * By default no transformation takes place
88 *
89 * @inheritDoc
90 */
91 @Override
92 public Cell transformCell(Cell v) throws IOException {
93 // Old filters based off of this class will override KeyValue transform(KeyValue).
94 // Thus to maintain compatibility we need to call the old version.
95 return transform(KeyValueUtil.ensureKeyValue(v));
96 }
97
98 /**
99 * WARNING: please to not override this method. Instead override {@link #transformCell(Cell)}.
100 *
101 * This is for transition from 0.94 -> 0.96
102 */
103 @Override
104 @Deprecated
105 public KeyValue transform(KeyValue currentKV) throws IOException {
106 return currentKV;
107 }
108
109 /**
110 * Filters that never filter by modifying the returned List of Cells can
111 * inherit this implementation that does nothing.
112 *
113 * @inheritDoc
114 */
115 @Override
116 public void filterRowCells(List<Cell> ignored) throws IOException {
117 // Old filters based off of this class will override KeyValue transform(KeyValue).
118 // Thus to maintain compatibility we need to call the old version.
119 List<KeyValue> kvs = new ArrayList<KeyValue>(ignored.size());
120 for (Cell c : ignored) {
121 kvs.add(KeyValueUtil.ensureKeyValue(c));
122 }
123 filterRow(kvs);
124 ignored.clear();
125 ignored.addAll(kvs);
126 }
127
128 /**
129 * WARNING: please to not override this method. Instead override {@link #transformCell(Cell)}.
130 *
131 * This is for transition from 0.94 -> 0.96
132 */
133 @Override
134 @Deprecated
135 public void filterRow(List<KeyValue> kvs) throws IOException {
136 }
137
138 /**
139 * Fitlers that never filter by modifying the returned List of Cells can
140 * inherit this implementation that does nothing.
141 *
142 * @inheritDoc
143 */
144 @Override
145 public boolean hasFilterRow() {
146 return false;
147 }
148
149 /**
150 * Filters that never filter by rows based on previously gathered state from
151 * {@link #filterKeyValue(Cell)} can inherit this implementation that
152 * never filters a row.
153 *
154 * @inheritDoc
155 */
156 @Override
157 public boolean filterRow() throws IOException {
158 return false;
159 }
160
161 /**
162 * This method is deprecated and you should override Cell getNextKeyHint(Cell) instead.
163 */
164 @Override
165 @Deprecated
166 public KeyValue getNextKeyHint(KeyValue currentKV) throws IOException {
167 return null;
168 }
169
170 /**
171 * Filters that are not sure which key must be next seeked to, can inherit
172 * this implementation that, by default, returns a null Cell.
173 *
174 * @inheritDoc
175 */
176 public Cell getNextCellHint(Cell currentKV) throws IOException {
177 // Old filters based off of this class will override KeyValue getNextKeyHint(KeyValue).
178 // Thus to maintain compatibility we need to call the old version.
179 return getNextKeyHint(KeyValueUtil.ensureKeyValue(currentKV));
180 }
181
182 /**
183 * By default, we require all scan's column families to be present. Our
184 * subclasses may be more precise.
185 *
186 * @inheritDoc
187 */
188 public boolean isFamilyEssential(byte[] name) throws IOException {
189 return true;
190 }
191
192 /**
193 * Given the filter's arguments it constructs the filter
194 * <p>
195 * @param filterArguments the filter's arguments
196 * @return constructed filter object
197 */
198 public static Filter createFilterFromArguments(ArrayList<byte []> filterArguments) {
199 throw new IllegalArgumentException("This method has not been implemented");
200 }
201
202 /**
203 * Return filter's info for debugging and logging purpose.
204 */
205 public String toString() {
206 return this.getClass().getSimpleName();
207 }
208
209 /**
210 * Return length 0 byte array for Filters that don't require special serialization
211 */
212 public byte[] toByteArray() throws IOException {
213 return new byte[0];
214 }
215
216 /**
217 * Default implementation so that writers of custom filters aren't forced to implement.
218 *
219 * @param other
220 * @return true if and only if the fields of the filter that are serialized
221 * are equal to the corresponding fields in other. Used for testing.
222 */
223 boolean areSerializedFieldsEqual(Filter other) {
224 return true;
225 }
226 }