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.concurrent.ThreadLocalRandom; 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 036 protected float chance; 037 protected boolean filterOutRow; 038 039 /** 040 * Create a new filter with a specified chance for a row to be included. 041 */ 042 public RandomRowFilter(float chance) { 043 this.chance = chance; 044 } 045 046 /** Returns The chance that a row gets included. */ 047 public float getChance() { 048 return chance; 049 } 050 051 /** 052 * Set the chance that a row is included. 053 */ 054 public void setChance(float chance) { 055 this.chance = chance; 056 } 057 058 @Override 059 public boolean filterAllRemaining() { 060 return false; 061 } 062 063 @Override 064 public ReturnCode filterCell(final Cell c) { 065 if (filterOutRow) { 066 return ReturnCode.NEXT_ROW; 067 } 068 return ReturnCode.INCLUDE; 069 } 070 071 @Override 072 public boolean filterRow() { 073 return filterOutRow; 074 } 075 076 @Override 077 public boolean hasFilterRow() { 078 return true; 079 } 080 081 @Override 082 public boolean filterRowKey(Cell firstRowCell) { 083 if (chance < 0) { 084 // with a zero chance, the rows is always excluded 085 filterOutRow = true; 086 } else if (chance > 1) { 087 // always included 088 filterOutRow = false; 089 } else { 090 // roll the dice 091 filterOutRow = !(ThreadLocalRandom.current().nextFloat() < chance); 092 } 093 return filterOutRow; 094 } 095 096 @Override 097 public void reset() { 098 filterOutRow = false; 099 } 100 101 /** Returns The filter serialized using pb */ 102 @Override 103 public byte[] toByteArray() { 104 FilterProtos.RandomRowFilter.Builder builder = FilterProtos.RandomRowFilter.newBuilder(); 105 builder.setChance(this.chance); 106 return builder.build().toByteArray(); 107 } 108 109 /** 110 * Parse a serialized representation of {@link RandomRowFilter} 111 * @param pbBytes A pb serialized {@link RandomRowFilter} instance 112 * @return An instance of {@link RandomRowFilter} made from <code>bytes</code> 113 * @throws DeserializationException if an error occurred 114 * @see #toByteArray 115 */ 116 public static RandomRowFilter parseFrom(final byte[] pbBytes) throws DeserializationException { 117 FilterProtos.RandomRowFilter proto; 118 try { 119 proto = FilterProtos.RandomRowFilter.parseFrom(pbBytes); 120 } catch (InvalidProtocolBufferException e) { 121 throw new DeserializationException(e); 122 } 123 return new RandomRowFilter(proto.getChance()); 124 } 125 126 /** 127 * Returns true if and only if the fields of the filter that are serialized are equal to the 128 * corresponding fields in other. Used for testing. 129 */ 130 @Override 131 boolean areSerializedFieldsEqual(Filter o) { 132 if (o == this) { 133 return true; 134 } 135 if (!(o instanceof RandomRowFilter)) { 136 return false; 137 } 138 RandomRowFilter other = (RandomRowFilter) o; 139 return this.getChance() == other.getChance(); 140 } 141 142 @Override 143 public boolean equals(Object obj) { 144 return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj); 145 } 146 147 @Override 148 public int hashCode() { 149 return Objects.hash(this.getChance()); 150 } 151}