001/*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020package org.apache.hadoop.hbase.filter;
021
022import java.io.IOException;
023import java.util.Objects;
024
025import org.apache.hadoop.hbase.Cell;
026import org.apache.yetus.audience.InterfaceAudience;
027import org.apache.hadoop.hbase.exceptions.DeserializationException;
028import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
029import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos;
030import org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException;
031
032/**
033 * A wrapper filter that returns true from {@link #filterAllRemaining()} as soon
034 * as the wrapped filters {@link Filter#filterRowKey(byte[], int, int)},
035 * {@link Filter#filterCell(org.apache.hadoop.hbase.Cell)},
036 * {@link org.apache.hadoop.hbase.filter.Filter#filterRow()} or
037 * {@link org.apache.hadoop.hbase.filter.Filter#filterAllRemaining()} methods
038 * returns true.
039 */
040@InterfaceAudience.Public
041public class WhileMatchFilter extends FilterBase {
042  private boolean filterAllRemaining = false;
043  private Filter filter;
044
045  public WhileMatchFilter(Filter filter) {
046    this.filter = filter;
047  }
048
049  public Filter getFilter() {
050    return filter;
051  }
052
053  @Override
054  public void reset() throws IOException {
055    this.filter.reset();
056  }
057
058  private void changeFAR(boolean value) {
059    filterAllRemaining = filterAllRemaining || value;
060  }
061
062  @Override
063  public boolean filterAllRemaining() throws IOException {
064    return this.filterAllRemaining || this.filter.filterAllRemaining();
065  }
066
067  @Override
068  public boolean filterRowKey(byte[] buffer, int offset, int length) throws IOException {
069    boolean value = filter.filterRowKey(buffer, offset, length);
070    changeFAR(value);
071    return value;
072  }
073
074  @Override
075  public boolean filterRowKey(Cell cell) throws IOException {
076    if (filterAllRemaining()) return true;
077    boolean value = filter.filterRowKey(cell);
078    changeFAR(value);
079    return value;
080  }
081
082  @Deprecated
083  @Override
084  public ReturnCode filterKeyValue(final Cell c) throws IOException {
085    return filterCell(c);
086  }
087
088  @Override
089  public ReturnCode filterCell(final Cell c) throws IOException {
090    ReturnCode code = filter.filterCell(c);
091    changeFAR(code != ReturnCode.INCLUDE);
092    return code;
093  }
094
095  @Override
096  public Cell transformCell(Cell v) throws IOException {
097    return filter.transformCell(v);
098  }
099
100  @Override
101  public boolean filterRow() throws IOException {
102    boolean filterRow = this.filter.filterRow();
103    changeFAR(filterRow);
104    return filterRow;
105  }
106  
107  @Override
108  public boolean hasFilterRow() {
109    return true;
110  }
111
112  /**
113   * @return The filter serialized using pb
114   */
115  @Override
116  public byte[] toByteArray() throws IOException {
117    FilterProtos.WhileMatchFilter.Builder builder =
118      FilterProtos.WhileMatchFilter.newBuilder();
119    builder.setFilter(ProtobufUtil.toFilter(this.filter));
120    return builder.build().toByteArray();
121  }
122
123  /**
124   * @param pbBytes A pb serialized {@link WhileMatchFilter} instance
125   * @return An instance of {@link WhileMatchFilter} made from <code>bytes</code>
126   * @throws org.apache.hadoop.hbase.exceptions.DeserializationException
127   * @see #toByteArray
128   */
129  public static WhileMatchFilter parseFrom(final byte [] pbBytes)
130  throws DeserializationException {
131    FilterProtos.WhileMatchFilter proto;
132    try {
133      proto = FilterProtos.WhileMatchFilter.parseFrom(pbBytes);
134    } catch (InvalidProtocolBufferException e) {
135      throw new DeserializationException(e);
136    }
137    try {
138      return new WhileMatchFilter(ProtobufUtil.toFilter(proto.getFilter()));
139    } catch (IOException ioe) {
140      throw new DeserializationException(ioe);
141    }
142  }
143
144  /**
145   * @param o the other filter to compare with
146   * @return true if and only if the fields of the filter that are serialized
147   * are equal to the corresponding fields in other.  Used for testing.
148   */
149  @Override
150  boolean areSerializedFieldsEqual(Filter o) {
151    if (o == this) return true;
152    if (!(o instanceof WhileMatchFilter)) return false;
153
154    WhileMatchFilter other = (WhileMatchFilter)o;
155    return getFilter().areSerializedFieldsEqual(other.getFilter());
156  }
157
158  @Override
159  public boolean isFamilyEssential(byte[] name) throws IOException {
160    return filter.isFamilyEssential(name);
161  }
162
163  @Override
164  public String toString() {
165    return this.getClass().getSimpleName() + " " + this.filter.toString();
166  }
167
168  @Override
169  public boolean equals(Object obj) {
170    return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj);
171  }
172
173  @Override
174  public int hashCode() {
175    return Objects.hash(this.filter);
176  }
177}