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.ArrayList; 021import org.apache.hadoop.hbase.Cell; 022import org.apache.hadoop.hbase.CellComparator; 023import org.apache.hadoop.hbase.exceptions.DeserializationException; 024import org.apache.hadoop.hbase.util.Bytes; 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; 029import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; 030 031import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos; 032 033/** 034 * A Filter that stops after the given row. There is no "RowStopFilter" because the Scan spec allows 035 * you to specify a stop row. Use this filter to include the stop row, eg: [A,Z]. 036 */ 037@InterfaceAudience.Public 038public class InclusiveStopFilter extends FilterBase { 039 private byte[] stopRowKey; 040 private boolean done = false; 041 042 public InclusiveStopFilter(final byte[] stopRowKey) { 043 this.stopRowKey = stopRowKey; 044 } 045 046 public byte[] getStopRowKey() { 047 return this.stopRowKey; 048 } 049 050 @Deprecated 051 @Override 052 public ReturnCode filterKeyValue(final Cell c) { 053 return filterCell(c); 054 } 055 056 @Override 057 public ReturnCode filterCell(final Cell c) { 058 if (done) return ReturnCode.NEXT_ROW; 059 return ReturnCode.INCLUDE; 060 } 061 062 @Override 063 public boolean filterRowKey(Cell firstRowCell) { 064 // if stopRowKey is <= buffer, then true, filter row. 065 if (filterAllRemaining()) return true; 066 int cmp = 067 CellComparator.getInstance().compareRows(firstRowCell, stopRowKey, 0, stopRowKey.length); 068 done = reversed ? cmp < 0 : cmp > 0; 069 return done; 070 } 071 072 @Override 073 public boolean filterAllRemaining() { 074 return done; 075 } 076 077 public static Filter createFilterFromArguments(ArrayList<byte[]> filterArguments) { 078 Preconditions.checkArgument(filterArguments.size() == 1, "Expected 1 but got: %s", 079 filterArguments.size()); 080 byte[] stopRowKey = ParseFilter.removeQuotesFromByteArray(filterArguments.get(0)); 081 return new InclusiveStopFilter(stopRowKey); 082 } 083 084 /** Returns The filter serialized using pb */ 085 @Override 086 public byte[] toByteArray() { 087 FilterProtos.InclusiveStopFilter.Builder builder = 088 FilterProtos.InclusiveStopFilter.newBuilder(); 089 if (this.stopRowKey != null) 090 builder.setStopRowKey(UnsafeByteOperations.unsafeWrap(this.stopRowKey)); 091 return builder.build().toByteArray(); 092 } 093 094 /** 095 * @param pbBytes A pb serialized {@link InclusiveStopFilter} instance 096 * @return An instance of {@link InclusiveStopFilter} made from <code>bytes</code> 097 * @see #toByteArray 098 */ 099 public static InclusiveStopFilter parseFrom(final byte[] pbBytes) 100 throws DeserializationException { 101 FilterProtos.InclusiveStopFilter proto; 102 try { 103 proto = FilterProtos.InclusiveStopFilter.parseFrom(pbBytes); 104 } catch (InvalidProtocolBufferException e) { 105 throw new DeserializationException(e); 106 } 107 return new InclusiveStopFilter( 108 proto.hasStopRowKey() ? proto.getStopRowKey().toByteArray() : null); 109 } 110 111 /** 112 * @param o the other filter to compare with 113 * @return true if and only if the fields of the filter that are serialized are equal to the 114 * corresponding fields in other. Used for testing. 115 */ 116 @Override 117 boolean areSerializedFieldsEqual(Filter o) { 118 if (o == this) return true; 119 if (!(o instanceof InclusiveStopFilter)) return false; 120 121 InclusiveStopFilter other = (InclusiveStopFilter) o; 122 return Bytes.equals(this.getStopRowKey(), other.getStopRowKey()); 123 } 124 125 @Override 126 public String toString() { 127 return this.getClass().getSimpleName() + " " + Bytes.toStringBinary(this.stopRowKey); 128 } 129 130 @Override 131 public boolean equals(Object obj) { 132 return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj); 133 } 134 135 @Override 136 public int hashCode() { 137 return Bytes.hashCode(this.stopRowKey); 138 } 139}