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 * Parse a serialized representation of {@link InclusiveStopFilter} 096 * @param pbBytes A pb serialized {@link InclusiveStopFilter} instance 097 * @return An instance of {@link InclusiveStopFilter} made from <code>bytes</code> 098 * @throws DeserializationException if an error occurred 099 * @see #toByteArray 100 */ 101 public static InclusiveStopFilter parseFrom(final byte[] pbBytes) 102 throws DeserializationException { 103 FilterProtos.InclusiveStopFilter proto; 104 try { 105 proto = FilterProtos.InclusiveStopFilter.parseFrom(pbBytes); 106 } catch (InvalidProtocolBufferException e) { 107 throw new DeserializationException(e); 108 } 109 return new InclusiveStopFilter( 110 proto.hasStopRowKey() ? proto.getStopRowKey().toByteArray() : null); 111 } 112 113 /** 114 * Returns true if and only if the fields of the filter that are serialized are equal to the 115 * corresponding fields in other. Used for testing. 116 */ 117 @Override 118 boolean areSerializedFieldsEqual(Filter o) { 119 if (o == this) { 120 return true; 121 } 122 if (!(o instanceof InclusiveStopFilter)) { 123 return false; 124 } 125 InclusiveStopFilter other = (InclusiveStopFilter) o; 126 return Bytes.equals(this.getStopRowKey(), other.getStopRowKey()); 127 } 128 129 @Override 130 public String toString() { 131 return this.getClass().getSimpleName() + " " + Bytes.toStringBinary(this.stopRowKey); 132 } 133 134 @Override 135 public boolean equals(Object obj) { 136 return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj); 137 } 138 139 @Override 140 public int hashCode() { 141 return Bytes.hashCode(this.stopRowKey); 142 } 143}