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.util.Objects;
23  import java.util.Random;
24  
25  import org.apache.hadoop.hbase.classification.InterfaceAudience;
26  import org.apache.hadoop.hbase.classification.InterfaceStability;
27  import org.apache.hadoop.hbase.Cell;
28  import org.apache.hadoop.hbase.exceptions.DeserializationException;
29  import org.apache.hadoop.hbase.protobuf.generated.FilterProtos;
30  
31  import com.google.protobuf.InvalidProtocolBufferException;
32  
33  /**
34   * A filter that includes rows based on a chance.
35   * 
36   */
37  @InterfaceAudience.Public
38  @InterfaceStability.Stable
39  public class RandomRowFilter extends FilterBase {
40    protected static final Random random = new Random();
41  
42    protected float chance;
43    protected boolean filterOutRow;
44  
45    /**
46     * Create a new filter with a specified chance for a row to be included.
47     * 
48     * @param chance
49     */
50    public RandomRowFilter(float chance) {
51      this.chance = chance;
52    }
53  
54    /**
55     * @return The chance that a row gets included.
56     */
57    public float getChance() {
58      return chance;
59    }
60  
61    /**
62     * Set the chance that a row is included.
63     * 
64     * @param chance
65     */
66    public void setChance(float chance) {
67      this.chance = chance;
68    }
69  
70    @Override
71    public boolean filterAllRemaining() {
72      return false;
73    }
74  
75    @Override
76    public ReturnCode filterKeyValue(Cell v) {
77      if (filterOutRow) {
78        return ReturnCode.NEXT_ROW;
79      }
80      return ReturnCode.INCLUDE;
81    }
82  
83    // Override here explicitly as the method in super class FilterBase might do a KeyValue recreate.
84    // See HBASE-12068
85    @Override
86    public Cell transformCell(Cell v) {
87      return v;
88    }
89  
90    @Override
91    public boolean filterRow() {
92      return filterOutRow;
93    }
94  
95    @Override
96    public boolean hasFilterRow() {
97      return true;
98    }
99  
100   @Override
101   public boolean filterRowKey(byte[] buffer, int offset, int length) {
102     if (chance < 0) {
103       // with a zero chance, the rows is always excluded
104       filterOutRow = true;
105     } else if (chance > 1) {
106       // always included
107       filterOutRow = false;
108     } else {
109       // roll the dice
110       filterOutRow = !(random.nextFloat() < chance);
111     }
112     return filterOutRow;
113   }
114 
115   @Override
116   public void reset() {
117     filterOutRow = false;
118   }
119 
120   /**
121    * @return The filter serialized using pb
122    */
123   @Override
124   public byte [] toByteArray() {
125     FilterProtos.RandomRowFilter.Builder builder =
126       FilterProtos.RandomRowFilter.newBuilder();
127     builder.setChance(this.chance);
128     return builder.build().toByteArray();
129   }
130 
131   /**
132    * @param pbBytes A pb serialized {@link RandomRowFilter} instance
133    * @return An instance of {@link RandomRowFilter} made from <code>bytes</code>
134    * @throws DeserializationException
135    * @see #toByteArray
136    */
137   public static RandomRowFilter parseFrom(final byte [] pbBytes)
138   throws DeserializationException {
139     FilterProtos.RandomRowFilter proto;
140     try {
141       proto = FilterProtos.RandomRowFilter.parseFrom(pbBytes);
142     } catch (InvalidProtocolBufferException e) {
143       throw new DeserializationException(e);
144     }
145     return new RandomRowFilter(proto.getChance());
146   }
147 
148   /**
149    * @param other
150    * @return true if and only if the fields of the filter that are serialized
151    * are equal to the corresponding fields in other.  Used for testing.
152    */
153   @Override
154   boolean areSerializedFieldsEqual(Filter o) {
155     if (o == this) return true;
156     if (!(o instanceof RandomRowFilter)) return false;
157 
158     RandomRowFilter other = (RandomRowFilter)o;
159     return this.getChance() == other.getChance();
160   }
161 
162   @Override
163   public boolean equals(Object obj) {
164     return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj);
165   }
166 
167   @Override
168   public int hashCode() {
169     return Objects.hash(this.getChance());
170   }
171 }