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  package org.apache.hadoop.hbase.filter;
20  
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.Collections;
25  import java.util.List;
26  import java.util.Objects;
27  
28  import com.google.protobuf.InvalidProtocolBufferException;
29  import org.apache.hadoop.hbase.Cell;
30  import org.apache.hadoop.hbase.KeyValue;
31  import org.apache.hadoop.hbase.KeyValueUtil;
32  import org.apache.hadoop.hbase.classification.InterfaceAudience;
33  import org.apache.hadoop.hbase.classification.InterfaceStability;
34  import org.apache.hadoop.hbase.exceptions.DeserializationException;
35  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
36  import org.apache.hadoop.hbase.protobuf.generated.FilterProtos;
37  
38  /**
39   * Implementation of {@link Filter} that represents an ordered List of Filters which will be
40   * evaluated with a specified boolean operator {@link Operator#MUST_PASS_ALL} (<code>AND</code>) or
41   * {@link Operator#MUST_PASS_ONE} (<code>OR</code>). Since you can use Filter Lists as children of
42   * Filter Lists, you can create a hierarchy of filters to be evaluated. <br>
43   * {@link Operator#MUST_PASS_ALL} evaluates lazily: evaluation stops as soon as one filter does not
44   * include the KeyValue. <br>
45   * {@link Operator#MUST_PASS_ONE} evaluates non-lazily: all filters are always evaluated. <br>
46   * Defaults to {@link Operator#MUST_PASS_ALL}.
47   */
48  @InterfaceAudience.Public
49  @InterfaceStability.Stable
50  final public class FilterList extends Filter {
51  
52    /** set operator */
53    @InterfaceAudience.Public
54    @InterfaceStability.Stable
55    public enum Operator {
56      /** !AND */
57      MUST_PASS_ALL,
58      /** !OR */
59      MUST_PASS_ONE
60    }
61  
62    private Operator operator = Operator.MUST_PASS_ALL;
63    private FilterListBase filterListBase;
64  
65    /**
66     * Constructor that takes a set of {@link Filter}s and an operator.
67     * @param operator Operator to process filter set with.
68     * @param filters Set of row filters.
69     */
70    public FilterList(final Operator operator, final List<Filter> filters) {
71      if (operator == Operator.MUST_PASS_ALL) {
72        filterListBase = new FilterListWithAND(filters);
73      } else if (operator == Operator.MUST_PASS_ONE) {
74        filterListBase = new FilterListWithOR(filters);
75      } else {
76        throw new IllegalArgumentException("Invalid operator: " + operator);
77      }
78      this.operator = operator;
79    }
80  
81    /**
82     * Constructor that takes a set of {@link Filter}s. The default operator MUST_PASS_ALL is assumed.
83     * All filters are cloned to internal list.
84     * @param filters list of filters
85     */
86    public FilterList(final List<Filter> filters) {
87      this(Operator.MUST_PASS_ALL, filters);
88    }
89  
90    /**
91     * Constructor that takes a var arg number of {@link Filter}s. The default operator MUST_PASS_ALL
92     * is assumed.
93     * @param filters
94     */
95    public FilterList(final Filter... filters) {
96      this(Operator.MUST_PASS_ALL, Arrays.asList(filters));
97    }
98  
99    /**
100    * Constructor that takes an operator.
101    * @param operator Operator to process filter set with.
102    */
103   public FilterList(final Operator operator) {
104     this(operator, new ArrayList<Filter>());
105   }
106 
107   /**
108    * Constructor that takes a var arg number of {@link Filter}s and an operator.
109    * @param operator Operator to process filter set with.
110    * @param filters Filters to use
111    */
112   public FilterList(final Operator operator, final Filter... filters) {
113     this(operator, Arrays.asList(filters));
114   }
115 
116   /**
117    * Get the operator.
118    * @return operator
119    */
120   public Operator getOperator() {
121     return operator;
122   }
123 
124   /**
125    * Get the filters.
126    * @return filters
127    */
128   public List<Filter> getFilters() {
129     return filterListBase.getFilters();
130   }
131 
132   public int size() {
133     return filterListBase.size();
134   }
135 
136   public void addFilter(List<Filter> filters) {
137     filterListBase.addFilterLists(filters);
138   }
139 
140   /**
141    * Add a filter.
142    * @param filter another filter
143    */
144   public void addFilter(Filter filter) {
145     addFilter(Collections.singletonList(filter));
146   }
147 
148   @Override
149   public void reset() throws IOException {
150     filterListBase.reset();
151   }
152 
153   @Override
154   public boolean filterRowKey(byte[] rowKey, int offset, int length) throws IOException {
155     return filterListBase.filterRowKey(rowKey, offset, length);
156   }
157 
158   @Override
159   public boolean filterAllRemaining() throws IOException {
160     return filterListBase.filterAllRemaining();
161   }
162 
163   @Override
164   public Cell transformCell(Cell c) throws IOException {
165     return filterListBase.transformCell(c);
166   }
167 
168   /**
169    * WARNING: please to not override this method. Instead override {@link #transformCell(Cell)}.
170    * When removing this, its body should be placed in transformCell. This is for transition from
171    * 0.94 -&gt; 0.96
172    */
173   @Deprecated
174   @Override
175   public KeyValue transform(KeyValue v) throws IOException {
176     return KeyValueUtil.ensureKeyValue(transformCell((Cell) v));
177   }
178 
179   @Override
180   public ReturnCode filterKeyValue(Cell c) throws IOException {
181     return filterListBase.filterKeyValue(c);
182   }
183 
184   /**
185    * Filters that never filter by modifying the returned List of Cells can inherit this
186    * implementation that does nothing. {@inheritDoc}
187    */
188   @Override
189   public void filterRowCells(List<Cell> cells) throws IOException {
190     filterListBase.filterRowCells(cells);
191   }
192 
193   @Override
194   public boolean hasFilterRow() {
195     return filterListBase.hasFilterRow();
196   }
197 
198   @Override
199   public boolean filterRow() throws IOException {
200     return filterListBase.filterRow();
201   }
202 
203   /**
204    * @return The filter serialized using pb
205    */
206   @Override
207   public byte[] toByteArray() throws IOException {
208     FilterProtos.FilterList.Builder builder = FilterProtos.FilterList.newBuilder();
209     builder.setOperator(FilterProtos.FilterList.Operator.valueOf(operator.name()));
210     ArrayList<Filter> filters = filterListBase.getFilters();
211     for (int i = 0, n = filters.size(); i < n; i++) {
212       builder.addFilters(ProtobufUtil.toFilter(filters.get(i)));
213     }
214     return builder.build().toByteArray();
215   }
216 
217   /**
218    * @param pbBytes A pb serialized {@link FilterList} instance
219    * @return An instance of {@link FilterList} made from <code>bytes</code>
220    * @throws DeserializationException
221    * @see #toByteArray
222    */
223   public static FilterList parseFrom(final byte[] pbBytes) throws DeserializationException {
224     FilterProtos.FilterList proto;
225     try {
226       proto = FilterProtos.FilterList.parseFrom(pbBytes);
227     } catch (InvalidProtocolBufferException e) {
228       throw new DeserializationException(e);
229     }
230 
231     List<Filter> rowFilters = new ArrayList<Filter>(proto.getFiltersCount());
232     try {
233       List<FilterProtos.Filter> filtersList = proto.getFiltersList();
234       for (int i = 0, n = filtersList.size(); i < n; i++) {
235         rowFilters.add(ProtobufUtil.toFilter(filtersList.get(i)));
236       }
237     } catch (IOException ioe) {
238       throw new DeserializationException(ioe);
239     }
240     return new FilterList(Operator.valueOf(proto.getOperator().name()), rowFilters);
241   }
242 
243   /**
244    * @param other
245    * @return true if and only if the fields of the filter that are serialized are equal to the
246    *         corresponding fields in other. Used for testing.
247    */
248   @Override
249   boolean areSerializedFieldsEqual(Filter other) {
250     if (other == this) return true;
251     if (!(other instanceof FilterList)) return false;
252 
253     FilterList o = (FilterList) other;
254     return this.getOperator().equals(o.getOperator())
255         && ((this.getFilters() == o.getFilters()) || this.getFilters().equals(o.getFilters()));
256   }
257 
258   @Override
259   @Deprecated
260   public KeyValue getNextKeyHint(KeyValue currentKV) throws IOException {
261     return KeyValueUtil.ensureKeyValue(getNextCellHint((Cell) currentKV));
262   }
263 
264   @Override
265   public Cell getNextCellHint(Cell currentCell) throws IOException {
266     return this.filterListBase.getNextCellHint(currentCell);
267   }
268 
269   @Override
270   public boolean isFamilyEssential(byte[] name) throws IOException {
271     return this.filterListBase.isFamilyEssential(name);
272   }
273 
274   @Override
275   public void setReversed(boolean reversed) {
276     this.reversed = reversed;
277     this.filterListBase.setReversed(reversed);
278   }
279 
280   @Override
281   public boolean isReversed() {
282     assert this.reversed == this.filterListBase.isReversed();
283     return this.reversed;
284   }
285 
286   /**
287    * @param maxFilters ignored
288    * @deprecated
289    */
290   @Deprecated
291   public String toString(int maxFilters) {
292     return this.filterListBase.toString();
293   }
294 
295   @Override
296   public String toString() {
297     return this.filterListBase.toString();
298   }
299 
300   @Override
301   public boolean equals(Object obj) {
302     return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj);
303   }
304 
305   @Override
306   public int hashCode() {
307     return Objects.hash(getOperator(), getFilters());
308   }
309 }