View Javadoc

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 }