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.io.IOException; 021import java.util.ArrayList; 022import java.util.Objects; 023import org.apache.hadoop.hbase.Cell; 024import org.apache.hadoop.hbase.exceptions.DeserializationException; 025import org.apache.yetus.audience.InterfaceAudience; 026 027import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; 028import org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException; 029 030import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos; 031 032/** 033 * Simple filter that returns first N columns on row only. This filter was written to test filters 034 * in Get and as soon as it gets its quota of columns, {@link #filterAllRemaining()} returns true. 035 * This makes this filter unsuitable as a Scan filter. 036 */ 037@InterfaceAudience.Public 038public class ColumnCountGetFilter extends FilterBase { 039 private int limit = 0; 040 private int count = 0; 041 042 public ColumnCountGetFilter(final int n) { 043 Preconditions.checkArgument(n >= 0, "limit be positive %s", n); 044 this.limit = n; 045 } 046 047 public int getLimit() { 048 return limit; 049 } 050 051 @Override 052 public boolean filterRowKey(Cell cell) throws IOException { 053 // Impl in FilterBase might do unnecessary copy for Off heap backed Cells. 054 if (filterAllRemaining()) return true; 055 return false; 056 } 057 058 @Override 059 public boolean filterAllRemaining() { 060 return this.count > this.limit; 061 } 062 063 @Override 064 public ReturnCode filterCell(final Cell c) { 065 this.count++; 066 return filterAllRemaining() ? ReturnCode.NEXT_COL : ReturnCode.INCLUDE_AND_NEXT_COL; 067 } 068 069 @Override 070 public void reset() { 071 this.count = 0; 072 } 073 074 public static Filter createFilterFromArguments(ArrayList<byte[]> filterArguments) { 075 Preconditions.checkArgument(filterArguments.size() == 1, "Expected 1 but got: %s", 076 filterArguments.size()); 077 int limit = ParseFilter.convertByteArrayToInt(filterArguments.get(0)); 078 return new ColumnCountGetFilter(limit); 079 } 080 081 /** Returns The filter serialized using pb */ 082 @Override 083 public byte[] toByteArray() { 084 FilterProtos.ColumnCountGetFilter.Builder builder = 085 FilterProtos.ColumnCountGetFilter.newBuilder(); 086 builder.setLimit(this.limit); 087 return builder.build().toByteArray(); 088 } 089 090 /** 091 * Parse a serialized representation of {@link ColumnCountGetFilter} 092 * @param pbBytes A pb serialized {@link ColumnCountGetFilter} instance 093 * @return An instance of {@link ColumnCountGetFilter} made from <code>bytes</code> 094 * @throws DeserializationException if an error occurred 095 * @see #toByteArray 096 */ 097 public static ColumnCountGetFilter parseFrom(final byte[] pbBytes) 098 throws DeserializationException { 099 FilterProtos.ColumnCountGetFilter proto; 100 try { 101 proto = FilterProtos.ColumnCountGetFilter.parseFrom(pbBytes); 102 } catch (InvalidProtocolBufferException e) { 103 throw new DeserializationException(e); 104 } 105 return new ColumnCountGetFilter(proto.getLimit()); 106 } 107 108 /** 109 * Returns true if and only if the fields of the filter that are serialized are equal to the 110 * corresponding fields in other. Used for testing. 111 */ 112 @Override 113 boolean areSerializedFieldsEqual(Filter o) { 114 if (o == this) { 115 return true; 116 } 117 if (!(o instanceof ColumnCountGetFilter)) { 118 return false; 119 } 120 ColumnCountGetFilter other = (ColumnCountGetFilter) o; 121 return this.getLimit() == other.getLimit(); 122 } 123 124 @Override 125 public String toString() { 126 return this.getClass().getSimpleName() + " " + this.limit; 127 } 128 129 @Override 130 public boolean equals(Object obj) { 131 return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj); 132 } 133 134 @Override 135 public int hashCode() { 136 return Objects.hash(this.limit); 137 } 138}