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