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 com.google.common.base.Preconditions;
23  import com.google.protobuf.InvalidProtocolBufferException;
24  
25  import java.util.ArrayList;
26  
27  import org.apache.hadoop.hbase.Cell;
28  import org.apache.hadoop.hbase.classification.InterfaceAudience;
29  import org.apache.hadoop.hbase.classification.InterfaceStability;
30  import org.apache.hadoop.hbase.exceptions.DeserializationException;
31  import org.apache.hadoop.hbase.protobuf.generated.FilterProtos;
32  import org.apache.hadoop.hbase.util.Bytes;
33  import org.apache.hadoop.hbase.util.ByteStringer;
34  
35  /**
36   * Pass results that have same row prefix.
37   */
38  @InterfaceAudience.Public
39  @InterfaceStability.Stable
40  public class PrefixFilter extends FilterBase {
41    protected byte [] prefix = null;
42    protected boolean passedPrefix = false;
43    protected boolean filterRow = true;
44  
45    public PrefixFilter(final byte [] prefix) {
46      this.prefix = prefix;
47    }
48  
49    public byte[] getPrefix() {
50      return prefix;
51    }
52  
53    @Override
54    public boolean filterRowKey(byte[] buffer, int offset, int length) {
55      if (buffer == null || this.prefix == null)
56        return true;
57      if (length < prefix.length)
58        return true;
59      // if they are equal, return false => pass row
60      // else return true, filter row
61      // if we are passed the prefix, set flag
62      int cmp = Bytes.compareTo(buffer, offset, this.prefix.length, this.prefix, 0,
63          this.prefix.length);
64      if ((!isReversed() && cmp > 0) || (isReversed() && cmp < 0)) {
65        passedPrefix = true;
66      }
67      filterRow = (cmp != 0);
68      return filterRow;
69    }
70  
71    @Override
72    public ReturnCode filterKeyValue(Cell v) {
73      if (filterRow) return ReturnCode.NEXT_ROW;
74      return ReturnCode.INCLUDE;
75    }
76  
77    // Override here explicitly as the method in super class FilterBase might do a KeyValue recreate.
78    // See HBASE-12068
79    @Override
80    public Cell transformCell(Cell v) {
81      return v;
82    }
83  
84    @Override
85    public boolean filterRow() {
86      return filterRow;
87    }
88  
89    @Override
90    public void reset() {
91      filterRow = true;
92    }
93  
94    @Override
95    public boolean filterAllRemaining() {
96      return passedPrefix;
97    }
98  
99    public static Filter createFilterFromArguments(ArrayList<byte []> filterArguments) {
100     Preconditions.checkArgument(filterArguments.size() == 1,
101                                 "Expected 1 but got: %s", filterArguments.size());
102     byte [] prefix = ParseFilter.removeQuotesFromByteArray(filterArguments.get(0));
103     return new PrefixFilter(prefix);
104   }
105 
106   /**
107    * @return The filter serialized using pb
108    */
109   @Override
110   public byte [] toByteArray() {
111     FilterProtos.PrefixFilter.Builder builder =
112       FilterProtos.PrefixFilter.newBuilder();
113     if (this.prefix != null) builder.setPrefix(ByteStringer.wrap(this.prefix));
114     return builder.build().toByteArray();
115   }
116 
117   /**
118    * @param pbBytes A pb serialized {@link PrefixFilter} instance
119    * @return An instance of {@link PrefixFilter} made from <code>bytes</code>
120    * @throws org.apache.hadoop.hbase.exceptions.DeserializationException
121    * @see #toByteArray
122    */
123   public static PrefixFilter parseFrom(final byte [] pbBytes)
124   throws DeserializationException {
125     FilterProtos.PrefixFilter proto;
126     try {
127       proto = FilterProtos.PrefixFilter.parseFrom(pbBytes);
128     } catch (InvalidProtocolBufferException e) {
129       throw new DeserializationException(e);
130     }
131     return new PrefixFilter(proto.hasPrefix()?proto.getPrefix().toByteArray():null);
132   }
133 
134   /**
135    * @param other
136    * @return true if and only if the fields of the filter that are serialized
137    * are equal to the corresponding fields in other.  Used for testing.
138    */
139   @Override
140   boolean areSerializedFieldsEqual(Filter o) {
141     if (o == this) return true;
142     if (!(o instanceof PrefixFilter)) return false;
143 
144     PrefixFilter other = (PrefixFilter)o;
145     return Bytes.equals(this.getPrefix(), other.getPrefix());
146   }
147 
148   @Override
149   public String toString() {
150     return this.getClass().getSimpleName() + " " + Bytes.toStringBinary(this.prefix);
151   }
152 
153   @Override
154   public boolean equals(Object obj) {
155     return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj);
156   }
157 
158   @Override
159   public int hashCode() {
160     return Bytes.hashCode(this.getPrefix());
161   }
162 }