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 @Override 051 public ReturnCode filterCell(final Cell c) { 052 if (done) return ReturnCode.NEXT_ROW; 053 return ReturnCode.INCLUDE; 054 } 055 056 @Override 057 public boolean filterRowKey(Cell firstRowCell) { 058 // if stopRowKey is <= buffer, then true, filter row. 059 if (filterAllRemaining()) return true; 060 int cmp = 061 CellComparator.getInstance().compareRows(firstRowCell, stopRowKey, 0, stopRowKey.length); 062 done = reversed ? cmp < 0 : cmp > 0; 063 return done; 064 } 065 066 @Override 067 public boolean filterAllRemaining() { 068 return done; 069 } 070 071 public static Filter createFilterFromArguments(ArrayList<byte[]> filterArguments) { 072 Preconditions.checkArgument(filterArguments.size() == 1, "Expected 1 but got: %s", 073 filterArguments.size()); 074 byte[] stopRowKey = ParseFilter.removeQuotesFromByteArray(filterArguments.get(0)); 075 return new InclusiveStopFilter(stopRowKey); 076 } 077 078 /** Returns The filter serialized using pb */ 079 @Override 080 public byte[] toByteArray() { 081 FilterProtos.InclusiveStopFilter.Builder builder = 082 FilterProtos.InclusiveStopFilter.newBuilder(); 083 if (this.stopRowKey != null) 084 builder.setStopRowKey(UnsafeByteOperations.unsafeWrap(this.stopRowKey)); 085 return builder.build().toByteArray(); 086 } 087 088 /** 089 * Parse a serialized representation of {@link InclusiveStopFilter} 090 * @param pbBytes A pb serialized {@link InclusiveStopFilter} instance 091 * @return An instance of {@link InclusiveStopFilter} made from <code>bytes</code> 092 * @throws DeserializationException if an error occurred 093 * @see #toByteArray 094 */ 095 public static InclusiveStopFilter parseFrom(final byte[] pbBytes) 096 throws DeserializationException { 097 FilterProtos.InclusiveStopFilter proto; 098 try { 099 proto = FilterProtos.InclusiveStopFilter.parseFrom(pbBytes); 100 } catch (InvalidProtocolBufferException e) { 101 throw new DeserializationException(e); 102 } 103 return new InclusiveStopFilter( 104 proto.hasStopRowKey() ? proto.getStopRowKey().toByteArray() : null); 105 } 106 107 /** 108 * Returns true if and only if the fields of the filter that are serialized are equal to the 109 * corresponding fields in other. Used for testing. 110 */ 111 @Override 112 boolean areSerializedFieldsEqual(Filter o) { 113 if (o == this) { 114 return true; 115 } 116 if (!(o instanceof InclusiveStopFilter)) { 117 return false; 118 } 119 InclusiveStopFilter other = (InclusiveStopFilter) o; 120 return Bytes.equals(this.getStopRowKey(), other.getStopRowKey()); 121 } 122 123 @Override 124 public String toString() { 125 return this.getClass().getSimpleName() + " " + Bytes.toStringBinary(this.stopRowKey); 126 } 127 128 @Override 129 public boolean equals(Object obj) { 130 return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj); 131 } 132 133 @Override 134 public int hashCode() { 135 return Bytes.hashCode(this.stopRowKey); 136 } 137}