001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.filter; 019 020import java.util.Objects; 021import java.util.Random; 022import org.apache.hadoop.hbase.Cell; 023import org.apache.hadoop.hbase.exceptions.DeserializationException; 024import org.apache.yetus.audience.InterfaceAudience; 025 026import org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException; 027 028import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos; 029 030/** 031 * A filter that includes rows based on a chance. 032 */ 033@InterfaceAudience.Public 034public class RandomRowFilter extends FilterBase { 035 protected static final Random random = new Random(); 036 037 protected float chance; 038 protected boolean filterOutRow; 039 040 /** 041 * Create a new filter with a specified chance for a row to be included. n 042 */ 043 public RandomRowFilter(float chance) { 044 this.chance = chance; 045 } 046 047 /** Returns The chance that a row gets included. */ 048 public float getChance() { 049 return chance; 050 } 051 052 /** 053 * Set the chance that a row is included. n 054 */ 055 public void setChance(float chance) { 056 this.chance = chance; 057 } 058 059 @Override 060 public boolean filterAllRemaining() { 061 return false; 062 } 063 064 @Deprecated 065 @Override 066 public ReturnCode filterKeyValue(final Cell c) { 067 return filterCell(c); 068 } 069 070 @Override 071 public ReturnCode filterCell(final Cell c) { 072 if (filterOutRow) { 073 return ReturnCode.NEXT_ROW; 074 } 075 return ReturnCode.INCLUDE; 076 } 077 078 @Override 079 public boolean filterRow() { 080 return filterOutRow; 081 } 082 083 @Override 084 public boolean hasFilterRow() { 085 return true; 086 } 087 088 @Override 089 public boolean filterRowKey(Cell firstRowCell) { 090 if (chance < 0) { 091 // with a zero chance, the rows is always excluded 092 filterOutRow = true; 093 } else if (chance > 1) { 094 // always included 095 filterOutRow = false; 096 } else { 097 // roll the dice 098 filterOutRow = !(random.nextFloat() < chance); 099 } 100 return filterOutRow; 101 } 102 103 @Override 104 public void reset() { 105 filterOutRow = false; 106 } 107 108 /** Returns The filter serialized using pb */ 109 @Override 110 public byte[] toByteArray() { 111 FilterProtos.RandomRowFilter.Builder builder = FilterProtos.RandomRowFilter.newBuilder(); 112 builder.setChance(this.chance); 113 return builder.build().toByteArray(); 114 } 115 116 /** 117 * Parse a serialized representation of {@link RandomRowFilter} 118 * @param pbBytes A pb serialized {@link RandomRowFilter} instance 119 * @return An instance of {@link RandomRowFilter} made from <code>bytes</code> 120 * @throws DeserializationException if an error occurred 121 * @see #toByteArray 122 */ 123 public static RandomRowFilter parseFrom(final byte[] pbBytes) throws DeserializationException { 124 FilterProtos.RandomRowFilter proto; 125 try { 126 proto = FilterProtos.RandomRowFilter.parseFrom(pbBytes); 127 } catch (InvalidProtocolBufferException e) { 128 throw new DeserializationException(e); 129 } 130 return new RandomRowFilter(proto.getChance()); 131 } 132 133 /** 134 * Returns true if and only if the fields of the filter that are serialized are equal to the 135 * corresponding fields in other. Used for testing. 136 */ 137 @Override 138 boolean areSerializedFieldsEqual(Filter o) { 139 if (o == this) { 140 return true; 141 } 142 if (!(o instanceof RandomRowFilter)) { 143 return false; 144 } 145 RandomRowFilter other = (RandomRowFilter) o; 146 return this.getChance() == other.getChance(); 147 } 148 149 @Override 150 public boolean equals(Object obj) { 151 return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj); 152 } 153 154 @Override 155 public int hashCode() { 156 return Objects.hash(this.getChance()); 157 } 158}