001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.filter;
019
020import java.io.IOException;
021import java.util.List;
022import org.apache.hadoop.hbase.Cell;
023import org.apache.hadoop.hbase.exceptions.DeserializationException;
024import org.apache.yetus.audience.InterfaceAudience;
025
026/**
027 * Interface for row and column filters directly applied within the regionserver. A filter can
028 * expect the following call sequence:
029 * <ul>
030 * <li>{@link #reset()} : reset the filter state before filtering a new row.</li>
031 * <li>{@link #filterAllRemaining()}: true means row scan is over; false means keep going.</li>
032 * <li>{@link #filterRowKey(Cell)}: true means drop this row; false means include.</li>
033 * <li>{@link #getHintForRejectedRow(Cell)}: if {@code filterRowKey} returned true, optionally
034 * provide a seek hint to skip past the rejected row efficiently.</li>
035 * <li>{@link #getSkipHint(Cell)}: when a cell is structurally skipped (time-range, column, or
036 * version gate) before {@code filterCell} is reached, optionally provide a seek hint.</li>
037 * <li>{@link #filterCell(Cell)}: decides whether to include or exclude this Cell. See
038 * {@link ReturnCode}.</li>
039 * <li>{@link #transformCell(Cell)}: if the Cell is included, let the filter transform the Cell.
040 * </li>
041 * <li>{@link #filterRowCells(List)}: allows direct modification of the final list to be submitted
042 * <li>{@link #filterRow()}: last chance to drop entire row based on the sequence of filter calls.
043 * Eg: filter a row if it doesn't contain a specified column.</li>
044 * </ul>
045 * Filter instances are created one per region/scan. This abstract class replaces the old
046 * RowFilterInterface. When implementing your own filters, consider inheriting {@link FilterBase} to
047 * help you reduce boilerplate.
048 * @see FilterBase
049 */
050@InterfaceAudience.Public
051public abstract class Filter {
052  protected transient boolean reversed;
053
054  /**
055   * Reset the state of the filter between rows. Concrete implementers can signal a failure
056   * condition in their code by throwing an {@link IOException}.
057   * @throws IOException in case an I/O or an filter specific failure needs to be signaled.
058   */
059  abstract public void reset() throws IOException;
060
061  /**
062   * Filters a row based on the row key. If this returns true, the entire row will be excluded. If
063   * false, each KeyValue in the row will be passed to {@link #filterCell(Cell)} below. If
064   * {@link #filterAllRemaining()} returns true, then {@link #filterRowKey(Cell)} should also return
065   * true. Concrete implementers can signal a failure condition in their code by throwing an
066   * {@link IOException}.
067   * @param firstRowCell The first cell coming in the new row
068   * @return true, remove entire row, false, include the row (maybe).
069   * @throws IOException in case an I/O or an filter specific failure needs to be signaled.
070   */
071  abstract public boolean filterRowKey(Cell firstRowCell) throws IOException;
072
073  /**
074   * If this returns true, the scan will terminate. Concrete implementers can signal a failure
075   * condition in their code by throwing an {@link IOException}.
076   * @return true to end scan, false to continue.
077   * @throws IOException in case an I/O or an filter specific failure needs to be signaled.
078   */
079  abstract public boolean filterAllRemaining() throws IOException;
080
081  /**
082   * A way to filter based on the column family, column qualifier and/or the column value. Return
083   * code is described below. This allows filters to filter only certain number of columns, then
084   * terminate without matching ever column. If filterRowKey returns true, filterCell needs to be
085   * consistent with it. filterCell can assume that filterRowKey has already been called for the
086   * row. If your filter returns <code>ReturnCode.NEXT_ROW</code>, it should return
087   * <code>ReturnCode.NEXT_ROW</code> until {@link #reset()} is called just in case the caller calls
088   * for the next row. Concrete implementers can signal a failure condition in their code by
089   * throwing an {@link IOException}.
090   * @param c the Cell in question
091   * @return code as described below
092   * @throws IOException in case an I/O or an filter specific failure needs to be signaled.
093   * @see Filter.ReturnCode
094   */
095  public ReturnCode filterCell(final Cell c) throws IOException {
096    return ReturnCode.INCLUDE;
097  }
098
099  /**
100   * Give the filter a chance to transform the passed Cell. If the Cell is changed a new Cell object
101   * must be returned.
102   * <p/>
103   * <strong>NOTICE:</strong> Filter will be evaluate at server side so the returned {@link Cell}
104   * must be an {@link org.apache.hadoop.hbase.ExtendedCell}, although it is marked as IA.Private.
105   * @see org.apache.hadoop.hbase.KeyValue#shallowCopy() The transformed KeyValue is what is
106   *      eventually returned to the client. Most filters will return the passed KeyValue unchanged.
107   * @see org.apache.hadoop.hbase.filter.KeyOnlyFilter#transformCell(Cell) for an example of a
108   *      transformation. Concrete implementers can signal a failure condition in their code by
109   *      throwing an {@link IOException}.
110   * @param v the Cell in question
111   * @return the changed Cell
112   * @throws IOException in case an I/O or an filter specific failure needs to be signaled.
113   */
114  abstract public Cell transformCell(final Cell v) throws IOException;
115
116  /**
117   * Return codes for filterValue().
118   */
119  @InterfaceAudience.Public
120  public enum ReturnCode {
121    /**
122     * Include the Cell
123     */
124    INCLUDE,
125    /**
126     * Include the Cell and seek to the next column skipping older versions.
127     */
128    INCLUDE_AND_NEXT_COL,
129    /**
130     * Skip this Cell
131     */
132    SKIP,
133    /**
134     * Skip this column. Go to the next column in this row.
135     */
136    NEXT_COL,
137    /**
138     * Seek to next row in current family. It may still pass a cell whose family is different but
139     * row is the same as previous cell to {@link #filterCell(Cell)} , even if we get a NEXT_ROW
140     * returned for previous cell. For more details see HBASE-18368. <br>
141     * Once reset() method was invoked, then we switch to the next row for all family, and you can
142     * catch the event by invoking CellUtils.matchingRows(previousCell, currentCell). <br>
143     * Note that filterRow() will still be called. <br>
144     */
145    NEXT_ROW,
146    /**
147     * Seek to next key which is given as hint by the filter.
148     */
149    SEEK_NEXT_USING_HINT,
150    /**
151     * Include KeyValue and done with row, seek to next. See NEXT_ROW.
152     */
153    INCLUDE_AND_SEEK_NEXT_ROW,
154  }
155
156  /**
157   * Chance to alter the list of Cells to be submitted. Modifications to the list will carry on
158   * Concrete implementers can signal a failure condition in their code by throwing an
159   * {@link IOException}.
160   * @param kvs the list of Cells to be filtered
161   * @throws IOException in case an I/O or an filter specific failure needs to be signaled.
162   */
163  abstract public void filterRowCells(List<Cell> kvs) throws IOException;
164
165  /**
166   * Primarily used to check for conflicts with scans(such as scans that do not read a full row at a
167   * time).
168   * @return True if this filter actively uses filterRowCells(List) or filterRow().
169   */
170  abstract public boolean hasFilterRow();
171
172  /**
173   * Last chance to veto row based on previous {@link #filterCell(Cell)} calls. The filter needs to
174   * retain state then return a particular value for this call if they wish to exclude a row if a
175   * certain column is missing (for example). Concrete implementers can signal a failure condition
176   * in their code by throwing an {@link IOException}.
177   * @return true to exclude row, false to include row.
178   * @throws IOException in case an I/O or an filter specific failure needs to be signaled.
179   */
180  abstract public boolean filterRow() throws IOException;
181
182  /**
183   * If the filter returns the match code SEEK_NEXT_USING_HINT, then it should also tell which is
184   * the next key it must seek to. After receiving the match code SEEK_NEXT_USING_HINT, the
185   * QueryMatcher would call this function to find out which key it must next seek to. Concrete
186   * implementers can signal a failure condition in their code by throwing an {@link IOException}.
187   * <strong>NOTICE:</strong> Filter will be evaluate at server side so the returned {@link Cell}
188   * must be an {@link org.apache.hadoop.hbase.ExtendedCell}, although it is marked as IA.Private.
189   * @return KeyValue which must be next seeked. return null if the filter is not sure which key to
190   *         seek to next.
191   * @throws IOException in case an I/O or an filter specific failure needs to be signaled.
192   */
193  abstract public Cell getNextCellHint(final Cell currentCell) throws IOException;
194
195  /**
196   * Provides a seek hint to bypass row-by-row scanning after {@link #filterRowKey(Cell)} rejects a
197   * row. When {@code filterRowKey} returns {@code true} the scan pipeline would normally iterate
198   * through every remaining cell in the rejected row one-by-one (via {@code nextRow()}) before
199   * moving on. If the filter can determine a better forward position — for example, the next range
200   * boundary in a {@code MultiRowRangeFilter} — it should return that target cell here, allowing
201   * the scanner to seek directly past the unwanted rows.
202   * <p>
203   * Contract:
204   * <ul>
205   * <li>Only called after {@link #filterRowKey(Cell)} has returned {@code true} for the same
206   * {@code firstRowCell}.</li>
207   * <li>Implementations may use state that was set during {@link #filterRowKey(Cell)} (e.g. an
208   * updated range pointer), but <strong>must not</strong> invoke {@link #filterCell(Cell)} logic —
209   * the caller guarantees that {@code filterCell} has not been called for this row.</li>
210   * <li>The returned {@link Cell}, if non-null, must be an
211   * {@link org.apache.hadoop.hbase.ExtendedCell} because filters are evaluated on the server
212   * side.</li>
213   * <li>Returning {@code null} (the default) falls through to the existing {@code nextRow()}
214   * behaviour, preserving full backward compatibility.</li>
215   * <li>For reversed scans ({@link org.apache.hadoop.hbase.client.Scan#isReversed()}), the hint
216   * must point to a <em>smaller</em> row key (earlier in reverse-scan direction). The scanner
217   * validates hint direction and falls back to {@code nextRow()} if the hint does not advance in
218   * the scan direction.</li>
219   * <li><strong>Composite filter support:</strong> {@code FilterList} (both {@code MUST_PASS_ALL}
220   * and {@code MUST_PASS_ONE}), {@code SkipFilter}, and {@code WhileMatchFilter} delegate this
221   * method to their sub-filters and merge the results. For AND ({@code MUST_PASS_ALL}), only
222   * sub-filters whose {@code filterRowKey} individually returned {@code true} are consulted, and
223   * the farthest (maximal-step) hint among them is returned. For OR ({@code MUST_PASS_ONE}), the
224   * nearest hint is returned only when every non-terminated sub-filter provides one — any null
225   * collapses the OR result to null.</li>
226   * </ul>
227   * @param firstRowCell the first cell encountered in the rejected row; contains the row key that
228   *                     was passed to {@code filterRowKey}
229   * @return a {@link Cell} representing the earliest position the scanner should seek to, or
230   *         {@code null} if this filter cannot provide a better position than a sequential skip
231   * @throws IOException in case an I/O or filter-specific failure needs to be signaled
232   * @see #filterRowKey(Cell)
233   */
234  public Cell getHintForRejectedRow(final Cell firstRowCell) throws IOException {
235    return null;
236  }
237
238  /**
239   * Provides a seek hint for cells that are structurally skipped by the scan pipeline
240   * <em>before</em> {@link #filterCell(Cell)} is ever reached. The pipeline short-circuits on
241   * several criteria — time-range mismatch, column-set exclusion, and version-limit exhaustion —
242   * and in each case the filter is bypassed entirely. When an implementation can compute a
243   * meaningful forward position purely from the cell's coordinates (without needing the
244   * {@code filterCell} call sequence), it should return that position here so the scanner can seek
245   * ahead instead of advancing one cell at a time.
246   * <p>
247   * Contract:
248   * <ul>
249   * <li>May be called for cells that have <strong>never</strong> been passed to
250   * {@link #filterCell(Cell)}.</li>
251   * <li>Implementations <strong>must not</strong> modify any filter state; this method is treated
252   * as logically stateless. Only filters whose hint computation is based solely on immutable
253   * configuration (e.g. a fixed column range or a fuzzy-row pattern) should override this.</li>
254   * <li>The returned {@link Cell}, if non-null, must be an
255   * {@link org.apache.hadoop.hbase.ExtendedCell} because filters are evaluated on the server
256   * side.</li>
257   * <li>Returning {@code null} (the default) falls through to the existing structural skip/seek
258   * behaviour, preserving full backward compatibility.</li>
259   * <li>For reversed scans, the returned cell must have a <em>smaller</em> row key (i.e., earlier
260   * in reverse-scan direction) than the {@code skippedCell}. Hints that do not advance in the scan
261   * direction are silently ignored.</li>
262   * <li><strong>Composite filter support:</strong> {@code FilterList} (both {@code MUST_PASS_ALL}
263   * and {@code MUST_PASS_ONE}), {@code SkipFilter}, and {@code WhileMatchFilter} delegate this
264   * method to their sub-filters and merge the results (maximal step for AND; for OR, the nearest
265   * hint is returned only when every non-terminated sub-filter provides one — any null collapses
266   * the OR result to null).</li>
267   * </ul>
268   * @param skippedCell the cell that was rejected by the time-range, column, or version gate before
269   *                    {@code filterCell} could be consulted
270   * @return a {@link Cell} representing the earliest position the scanner should seek to, or
271   *         {@code null} if this filter cannot provide a better position than the structural hint
272   * @throws IOException in case an I/O or filter-specific failure needs to be signaled
273   * @see #filterCell(Cell)
274   * @see #getNextCellHint(Cell)
275   */
276  public Cell getSkipHint(final Cell skippedCell) throws IOException {
277    return null;
278  }
279
280  /**
281   * Check that given column family is essential for filter to check row. Most filters always return
282   * true here. But some could have more sophisticated logic which could significantly reduce
283   * scanning process by not even touching columns until we are 100% sure that it's data is needed
284   * in result. Concrete implementers can signal a failure condition in their code by throwing an
285   * {@link IOException}.
286   * @throws IOException in case an I/O or an filter specific failure needs to be signaled.
287   */
288  abstract public boolean isFamilyEssential(byte[] name) throws IOException;
289
290  /**
291   * TODO: JAVADOC Concrete implementers can signal a failure condition in their code by throwing an
292   * {@link IOException}.
293   * @return The filter serialized using pb
294   * @throws IOException in case an I/O or an filter specific failure needs to be signaled.
295   */
296  abstract public byte[] toByteArray() throws IOException;
297
298  /**
299   * Concrete implementers can signal a failure condition in their code by throwing an
300   * {@link IOException}.
301   * @param pbBytes A pb serialized {@link Filter} instance
302   * @return An instance of {@link Filter} made from <code>bytes</code>
303   * @throws DeserializationException if an error occurred
304   * @see #toByteArray
305   */
306  public static Filter parseFrom(final byte[] pbBytes) throws DeserializationException {
307    throw new DeserializationException(
308      "parseFrom called on base Filter, but should be called on derived type");
309  }
310
311  /**
312   * Concrete implementers can signal a failure condition in their code by throwing an
313   * {@link IOException}.
314   * @return true if and only if the fields of the filter that are serialized are equal to the
315   *         corresponding fields in other. Used for testing.
316   */
317  abstract boolean areSerializedFieldsEqual(Filter other);
318
319  /**
320   * alter the reversed scan flag
321   * @param reversed flag
322   */
323  public void setReversed(boolean reversed) {
324    this.reversed = reversed;
325  }
326
327  public boolean isReversed() {
328    return this.reversed;
329  }
330}