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.Cell;
27  import org.apache.hadoop.hbase.KeyValue;
28  import org.apache.hadoop.hbase.classification.InterfaceAudience;
29  
30  /**
31   * Base class for FilterList. Currently, we have two sub-classes to extend this class:
32   * {@link FilterListWithOR}, {@link FilterListWithAND}.
33   */
34  @InterfaceAudience.Private
35  public abstract class FilterListBase extends FilterBase {
36    private static final int MAX_LOG_FILTERS = 5;
37    protected final ArrayList<Filter> filters;
38  
39    /**
40     * For each sub-filter in filter list, we save a boolean flag to indicate that whether the return
41     * code of filterCell(c) for sub-filter is INCLUDE* (INCLUDE, INCLUDE_AND_NEXT_COL,
42     * INCLUDE_AND_SEEK_NEXT_ROW) case. if true, we need to transform cell for the sub-filter.
43     */
44    protected ArrayList<Boolean> subFiltersIncludedCell;
45  
46    public FilterListBase(List<Filter> filters) {
47      reversed = checkAndGetReversed(filters, reversed);
48      this.filters = new ArrayList<Filter>(filters);
49    }
50  
51    protected static boolean isInReturnCodes(ReturnCode testRC, ReturnCode... returnCodes) {
52      for (ReturnCode rc : returnCodes) {
53        if (testRC.equals(rc)) return true;
54      }
55      return false;
56    }
57  
58    protected static boolean checkAndGetReversed(List<Filter> rowFilters, boolean defaultValue) {
59      if (rowFilters.isEmpty()) {
60        return defaultValue;
61      }
62      boolean retValue = rowFilters.get(0).isReversed();
63      for (Filter filter : rowFilters) {
64        if (filter.isReversed() != retValue) {
65          throw new IllegalArgumentException("Filters in the list must have the same reversed flag");
66        }
67      }
68      return retValue;
69    }
70  
71    public abstract void addFilterLists(List<Filter> filters);
72  
73    public int size() {
74      return this.filters.size();
75    }
76  
77    public boolean isEmpty() {
78      return this.filters.isEmpty();
79    }
80  
81    public ArrayList<Filter> getFilters() {
82      return this.filters;
83    }
84  
85    protected int compareCell(Cell a, Cell b) {
86      int cmp = KeyValue.COMPARATOR.compare(a, b);
87      return reversed ? -1 * cmp : cmp;
88    }
89  
90    /**
91     * For FilterList, we can consider a filter list as a node in a tree. sub-filters of the filter
92     * list are children of the relative node. The logic of transforming cell of a filter list, well,
93     * we can consider it as the process of post-order tree traverse. For a node , before we traverse
94     * the current child, we should set the traverse result (transformed cell) of previous node(s) as
95     * the initial value. (HBASE-18879).
96     * @param c The cell in question.
97     * @return the transformed cell.
98     * @throws IOException
99     */
100   @Override
101   public Cell transformCell(Cell c) throws IOException {
102     Cell transformed = c;
103     for (int i = 0, n = filters.size(); i < n; i++) {
104       if (subFiltersIncludedCell.get(i)) {
105         transformed = filters.get(i).transformCell(transformed);
106       }
107     }
108     return transformed;
109   }
110 
111   /**
112    * Filters that never filter by modifying the returned List of Cells can inherit this
113    * implementation that does nothing. {@inheritDoc}
114    */
115   @Override
116   public void filterRowCells(List<Cell> cells) throws IOException {
117     for (int i = 0, n = filters.size(); i < n; i++) {
118       filters.get(i).filterRowCells(cells);
119     }
120   }
121 
122   @Override
123   public boolean hasFilterRow() {
124     for (int i = 0, n = filters.size(); i < n; i++) {
125       if (filters.get(i).hasFilterRow()) {
126         return true;
127       }
128     }
129     return false;
130   }
131 
132   @Override
133   public boolean isFamilyEssential(byte[] name) throws IOException {
134     if (this.filters.isEmpty()) {
135       return super.isFamilyEssential(name);
136     }
137     for (int i = 0, n = filters.size(); i < n; i++) {
138       if (filters.get(i).isFamilyEssential(name)) {
139         return true;
140       }
141     }
142     return false;
143   }
144 
145   @Override
146   public void setReversed(boolean reversed) {
147     for (int i = 0, n = filters.size(); i < n; i++) {
148       filters.get(i).setReversed(reversed);
149     }
150     this.reversed = reversed;
151   }
152 
153   @Override
154   public String toString() {
155     int endIndex = this.size() < MAX_LOG_FILTERS ? this.size() : MAX_LOG_FILTERS;
156     return formatLogFilters(filters.subList(0, endIndex));
157   }
158 
159   protected abstract String formatLogFilters(List<Filter> logFilters);
160 }