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.classification.InterfaceAudience;
25  import org.apache.hadoop.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
83    public boolean filterRow() {
84      return filterOutRow;
85    }
86    
87    public boolean hasFilterRow() {
88      return true;
89    }
90  
91    @Override
92    public boolean filterRowKey(byte[] buffer, int offset, int length) {
93      if (chance < 0) {
94        // with a zero chance, the rows is always excluded
95        filterOutRow = true;
96      } else if (chance > 1) {
97        // always included
98        filterOutRow = false;
99      } else {
100       // roll the dice
101       filterOutRow = !(random.nextFloat() < chance);
102     }
103     return filterOutRow;
104   }
105 
106   @Override
107   public void reset() {
108     filterOutRow = false;
109   }
110 
111   /**
112    * @return The filter serialized using pb
113    */
114   public byte [] toByteArray() {
115     FilterProtos.RandomRowFilter.Builder builder =
116       FilterProtos.RandomRowFilter.newBuilder();
117     builder.setChance(this.chance);
118     return builder.build().toByteArray();
119   }
120 
121   /**
122    * @param pbBytes A pb serialized {@link RandomRowFilter} instance
123    * @return An instance of {@link RandomRowFilter} made from <code>bytes</code>
124    * @throws DeserializationException
125    * @see #toByteArray
126    */
127   public static RandomRowFilter parseFrom(final byte [] pbBytes)
128   throws DeserializationException {
129     FilterProtos.RandomRowFilter proto;
130     try {
131       proto = FilterProtos.RandomRowFilter.parseFrom(pbBytes);
132     } catch (InvalidProtocolBufferException e) {
133       throw new DeserializationException(e);
134     }
135     return new RandomRowFilter(proto.getChance());
136   }
137 
138   /**
139    * @param other
140    * @return true if and only if the fields of the filter that are serialized
141    * are equal to the corresponding fields in other.  Used for testing.
142    */
143   boolean areSerializedFieldsEqual(Filter o) {
144     if (o == this) return true;
145     if (!(o instanceof RandomRowFilter)) return false;
146 
147     RandomRowFilter other = (RandomRowFilter)o;
148     return this.getChance() == other.getChance();
149   }
150 }