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