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 @Deprecated 064 @Override 065 public ReturnCode filterKeyValue(final Cell c) { 066 return filterCell(c); 067 } 068 069 @Override 070 public ReturnCode filterCell(final Cell c) { 071 this.count++; 072 return filterAllRemaining() ? ReturnCode.NEXT_COL : ReturnCode.INCLUDE_AND_NEXT_COL; 073 } 074 075 @Override 076 public void reset() { 077 this.count = 0; 078 } 079 080 public static Filter createFilterFromArguments(ArrayList<byte[]> filterArguments) { 081 Preconditions.checkArgument(filterArguments.size() == 1, "Expected 1 but got: %s", 082 filterArguments.size()); 083 int limit = ParseFilter.convertByteArrayToInt(filterArguments.get(0)); 084 return new ColumnCountGetFilter(limit); 085 } 086 087 /** Returns The filter serialized using pb */ 088 @Override 089 public byte[] toByteArray() { 090 FilterProtos.ColumnCountGetFilter.Builder builder = 091 FilterProtos.ColumnCountGetFilter.newBuilder(); 092 builder.setLimit(this.limit); 093 return builder.build().toByteArray(); 094 } 095 096 /** 097 * Parse a serialized representation of {@link ColumnCountGetFilter} 098 * @param pbBytes A pb serialized {@link ColumnCountGetFilter} instance 099 * @return An instance of {@link ColumnCountGetFilter} made from <code>bytes</code> 100 * @throws DeserializationException if an error occurred 101 * @see #toByteArray 102 */ 103 public static ColumnCountGetFilter parseFrom(final byte[] pbBytes) 104 throws DeserializationException { 105 FilterProtos.ColumnCountGetFilter proto; 106 try { 107 proto = FilterProtos.ColumnCountGetFilter.parseFrom(pbBytes); 108 } catch (InvalidProtocolBufferException e) { 109 throw new DeserializationException(e); 110 } 111 return new ColumnCountGetFilter(proto.getLimit()); 112 } 113 114 /** 115 * Returns true if and only if the fields of the filter that are serialized are equal to the 116 * corresponding fields in other. Used for testing. 117 */ 118 @Override 119 boolean areSerializedFieldsEqual(Filter o) { 120 if (o == this) { 121 return true; 122 } 123 if (!(o instanceof ColumnCountGetFilter)) { 124 return false; 125 } 126 ColumnCountGetFilter other = (ColumnCountGetFilter) o; 127 return this.getLimit() == other.getLimit(); 128 } 129 130 @Override 131 public String toString() { 132 return this.getClass().getSimpleName() + " " + this.limit; 133 } 134 135 @Override 136 public boolean equals(Object obj) { 137 return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj); 138 } 139 140 @Override 141 public int hashCode() { 142 return Objects.hash(this.limit); 143 } 144}