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.Objects; 021import java.util.Set; 022import java.util.TreeSet; 023import org.apache.hadoop.hbase.Cell; 024import org.apache.hadoop.hbase.CellUtil; 025import org.apache.hadoop.hbase.exceptions.DeserializationException; 026import org.apache.hadoop.hbase.util.Bytes; 027import org.apache.yetus.audience.InterfaceAudience; 028 029import org.apache.hbase.thirdparty.com.google.protobuf.ByteString; 030import org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException; 031import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; 032 033import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos; 034 035/** 036 * The filter looks for the given columns in KeyValue. Once there is a match for any one of the 037 * columns, it returns ReturnCode.NEXT_ROW for remaining KeyValues in the row. 038 * <p> 039 * Note : It may emit KVs which do not have the given columns in them, if these KVs happen to occur 040 * before a KV which does have a match. Given this caveat, this filter is only useful for special 041 * cases like org.apache.hadoop.hbase.mapreduce.RowCounter. 042 * <p> 043 * @deprecated Deprecated in 2.0.0 and will be removed in 3.0.0. 044 * @see <a href="https://issues.apache.org/jira/browse/HBASE-13347">HBASE-13347</a> 045 */ 046@InterfaceAudience.Public 047@Deprecated 048public class FirstKeyValueMatchingQualifiersFilter extends FirstKeyOnlyFilter { 049 050 private Set<byte[]> qualifiers; 051 052 /** 053 * Constructor which takes a set of columns. As soon as first KeyValue matching any of these 054 * columns is found, filter moves to next row. 055 * @param qualifiers the set of columns to me matched. 056 */ 057 public FirstKeyValueMatchingQualifiersFilter(Set<byte[]> qualifiers) { 058 this.qualifiers = qualifiers; 059 } 060 061 @Deprecated 062 @Override 063 public ReturnCode filterKeyValue(final Cell c) { 064 return filterCell(c); 065 } 066 067 @Override 068 public ReturnCode filterCell(final Cell c) { 069 if (hasFoundKV()) { 070 return ReturnCode.NEXT_ROW; 071 } else if (hasOneMatchingQualifier(c)) { 072 setFoundKV(true); 073 } 074 return ReturnCode.INCLUDE; 075 } 076 077 private boolean hasOneMatchingQualifier(Cell c) { 078 for (byte[] q : qualifiers) { 079 if (CellUtil.matchingQualifier(c, q)) { 080 return true; 081 } 082 } 083 return false; 084 } 085 086 /** Returns The filter serialized using pb */ 087 @Override 088 public byte[] toByteArray() { 089 FilterProtos.FirstKeyValueMatchingQualifiersFilter.Builder builder = 090 FilterProtos.FirstKeyValueMatchingQualifiersFilter.newBuilder(); 091 for (byte[] qualifier : qualifiers) { 092 if (qualifier != null) builder.addQualifiers(UnsafeByteOperations.unsafeWrap(qualifier)); 093 } 094 return builder.build().toByteArray(); 095 } 096 097 /** 098 * Parses a serialized representation of {@link FirstKeyValueMatchingQualifiersFilter} 099 * @param pbBytes A pb serialized {@link FirstKeyValueMatchingQualifiersFilter} instance 100 * @return An instance of {@link FirstKeyValueMatchingQualifiersFilter} made from 101 * <code>bytes</code> 102 * @throws DeserializationException if an error occurred 103 * @see #toByteArray 104 */ 105 public static FirstKeyValueMatchingQualifiersFilter parseFrom(final byte[] pbBytes) 106 throws DeserializationException { 107 FilterProtos.FirstKeyValueMatchingQualifiersFilter proto; 108 try { 109 proto = FilterProtos.FirstKeyValueMatchingQualifiersFilter.parseFrom(pbBytes); 110 } catch (InvalidProtocolBufferException e) { 111 throw new DeserializationException(e); 112 } 113 114 TreeSet<byte[]> qualifiers = new TreeSet<>(Bytes.BYTES_COMPARATOR); 115 for (ByteString qualifier : proto.getQualifiersList()) { 116 qualifiers.add(qualifier.toByteArray()); 117 } 118 return new FirstKeyValueMatchingQualifiersFilter(qualifiers); 119 } 120 121 /** 122 * @param o the other filter to compare with 123 * @return true if and only if the fields of the filter that are serialized are equal to the 124 * corresponding fields in other. Used for testing. 125 */ 126 @Override 127 boolean areSerializedFieldsEqual(Filter o) { 128 if (o == this) return true; 129 if (!(o instanceof FirstKeyValueMatchingQualifiersFilter)) return false; 130 131 FirstKeyValueMatchingQualifiersFilter other = (FirstKeyValueMatchingQualifiersFilter) o; 132 return this.qualifiers.equals(other.qualifiers); 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.qualifiers); 143 } 144}