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.util.Random; 023 024import org.apache.hadoop.hbase.Cell; 025import org.apache.yetus.audience.InterfaceAudience; 026import org.apache.hadoop.hbase.exceptions.DeserializationException; 027import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos; 028 029import org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException; 030 031/** 032 * A filter that includes rows based on a chance. 033 * 034 */ 035@InterfaceAudience.Public 036public class RandomRowFilter extends FilterBase { 037 protected static final Random random = new Random(); 038 039 protected float chance; 040 protected boolean filterOutRow; 041 042 /** 043 * Create a new filter with a specified chance for a row to be included. 044 * 045 * @param chance 046 */ 047 public RandomRowFilter(float chance) { 048 this.chance = chance; 049 } 050 051 /** 052 * @return The chance that a row gets included. 053 */ 054 public float getChance() { 055 return chance; 056 } 057 058 /** 059 * Set the chance that a row is included. 060 * 061 * @param chance 062 */ 063 public void setChance(float chance) { 064 this.chance = chance; 065 } 066 067 @Override 068 public boolean filterAllRemaining() { 069 return false; 070 } 071 072 @Deprecated 073 @Override 074 public ReturnCode filterKeyValue(final Cell c) { 075 return filterCell(c); 076 } 077 078 @Override 079 public ReturnCode filterCell(final Cell c) { 080 if (filterOutRow) { 081 return ReturnCode.NEXT_ROW; 082 } 083 return ReturnCode.INCLUDE; 084 } 085 086 @Override 087 public boolean filterRow() { 088 return filterOutRow; 089 } 090 091 @Override 092 public boolean hasFilterRow() { 093 return true; 094 } 095 096 @Override 097 public boolean filterRowKey(Cell firstRowCell) { 098 if (chance < 0) { 099 // with a zero chance, the rows is always excluded 100 filterOutRow = true; 101 } else if (chance > 1) { 102 // always included 103 filterOutRow = false; 104 } else { 105 // roll the dice 106 filterOutRow = !(random.nextFloat() < chance); 107 } 108 return filterOutRow; 109 } 110 111 @Override 112 public void reset() { 113 filterOutRow = false; 114 } 115 116 /** 117 * @return The filter serialized using pb 118 */ 119 @Override 120 public byte [] toByteArray() { 121 FilterProtos.RandomRowFilter.Builder builder = 122 FilterProtos.RandomRowFilter.newBuilder(); 123 builder.setChance(this.chance); 124 return builder.build().toByteArray(); 125 } 126 127 /** 128 * @param pbBytes A pb serialized {@link RandomRowFilter} instance 129 * @return An instance of {@link RandomRowFilter} made from <code>bytes</code> 130 * @throws DeserializationException 131 * @see #toByteArray 132 */ 133 public static RandomRowFilter parseFrom(final byte [] pbBytes) 134 throws DeserializationException { 135 FilterProtos.RandomRowFilter proto; 136 try { 137 proto = FilterProtos.RandomRowFilter.parseFrom(pbBytes); 138 } catch (InvalidProtocolBufferException e) { 139 throw new DeserializationException(e); 140 } 141 return new RandomRowFilter(proto.getChance()); 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 RandomRowFilter)) return false; 153 154 RandomRowFilter other = (RandomRowFilter)o; 155 return this.getChance() == other.getChance(); 156 } 157}