1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.hadoop.hbase.filter; 20 21 import org.apache.hadoop.hbase.classification.InterfaceAudience; 22 import org.apache.hadoop.hbase.classification.InterfaceStability; 23 import org.apache.hadoop.hbase.Cell; 24 import org.apache.hadoop.hbase.CellUtil; 25 import org.apache.hadoop.hbase.exceptions.DeserializationException; 26 import org.apache.hadoop.hbase.protobuf.generated.FilterProtos; 27 import org.apache.hadoop.hbase.util.ByteStringer; 28 import org.apache.hadoop.hbase.util.Bytes; 29 30 import com.google.protobuf.ByteString; 31 import com.google.protobuf.InvalidProtocolBufferException; 32 33 import java.util.Set; 34 import java.util.TreeSet; 35 36 /** 37 * The filter looks for the given columns in KeyValue. Once there is a match for 38 * any one of the columns, it returns ReturnCode.NEXT_ROW for remaining 39 * KeyValues in the row. 40 * <p> 41 * Note : It may emit KVs which do not have the given columns in them, if 42 * these KVs happen to occur before a KV which does have a match. Given this 43 * caveat, this filter is only useful for special cases 44 * like {@link org.apache.hadoop.hbase.mapreduce.RowCounter}. 45 * <p> 46 */ 47 @InterfaceAudience.Public 48 @InterfaceStability.Stable 49 public class FirstKeyValueMatchingQualifiersFilter extends FirstKeyOnlyFilter { 50 51 private Set<byte []> qualifiers; 52 53 /** 54 * Constructor which takes a set of columns. As soon as first KeyValue 55 * matching any of these columns is found, filter moves to next row. 56 * 57 * @param qualifiers the set of columns to me matched. 58 */ FirstKeyValueMatchingQualifiersFilter(Set<byte []> qualifiers)59 public FirstKeyValueMatchingQualifiersFilter(Set<byte []> qualifiers) { 60 this.qualifiers = qualifiers; 61 } 62 63 @Override filterKeyValue(Cell v)64 public ReturnCode filterKeyValue(Cell v) { 65 if (hasFoundKV()) { 66 return ReturnCode.NEXT_ROW; 67 } else if (hasOneMatchingQualifier(v)) { 68 setFoundKV(true); 69 } 70 return ReturnCode.INCLUDE; 71 } 72 hasOneMatchingQualifier(Cell v)73 private boolean hasOneMatchingQualifier(Cell v) { 74 for (byte[] q : qualifiers) { 75 if (CellUtil.matchingQualifier(v, q)) { 76 return true; 77 } 78 } 79 return false; 80 } 81 82 /** 83 * @return The filter serialized using pb 84 */ toByteArray()85 public byte [] toByteArray() { 86 FilterProtos.FirstKeyValueMatchingQualifiersFilter.Builder builder = 87 FilterProtos.FirstKeyValueMatchingQualifiersFilter.newBuilder(); 88 for (byte[] qualifier : qualifiers) { 89 if (qualifier != null) builder.addQualifiers(ByteStringer.wrap(qualifier)); 90 } 91 return builder.build().toByteArray(); 92 } 93 94 /** 95 * @param pbBytes A pb serialized {@link FirstKeyValueMatchingQualifiersFilter} instance 96 * @return An instance of {@link FirstKeyValueMatchingQualifiersFilter} made from <code>bytes</code> 97 * @throws DeserializationException 98 * @see #toByteArray 99 */ parseFrom(final byte [] pbBytes)100 public static FirstKeyValueMatchingQualifiersFilter parseFrom(final byte [] pbBytes) 101 throws DeserializationException { 102 FilterProtos.FirstKeyValueMatchingQualifiersFilter proto; 103 try { 104 proto = FilterProtos.FirstKeyValueMatchingQualifiersFilter.parseFrom(pbBytes); 105 } catch (InvalidProtocolBufferException e) { 106 throw new DeserializationException(e); 107 } 108 109 TreeSet<byte []> qualifiers = new TreeSet<byte []>(Bytes.BYTES_COMPARATOR); 110 for (ByteString qualifier : proto.getQualifiersList()) { 111 qualifiers.add(qualifier.toByteArray()); 112 } 113 return new FirstKeyValueMatchingQualifiersFilter(qualifiers); 114 } 115 116 /** 117 * @param other 118 * @return true if and only if the fields of the filter that are serialized 119 * are equal to the corresponding fields in other. Used for testing. 120 */ areSerializedFieldsEqual(Filter o)121 boolean areSerializedFieldsEqual(Filter o) { 122 if (o == this) return true; 123 if (!(o instanceof FirstKeyValueMatchingQualifiersFilter)) return false; 124 125 FirstKeyValueMatchingQualifiersFilter other = (FirstKeyValueMatchingQualifiersFilter)o; 126 return this.qualifiers.equals(other.qualifiers); 127 } 128 } 129