1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.filter;
21
22 import com.google.common.base.Preconditions;
23 import com.google.protobuf.ByteString;
24 import com.google.protobuf.InvalidProtocolBufferException;
25 import org.apache.hadoop.classification.InterfaceAudience;
26 import org.apache.hadoop.classification.InterfaceStability;
27 import org.apache.hadoop.hbase.KeyValue;
28 import org.apache.hadoop.hbase.exceptions.DeserializationException;
29 import org.apache.hadoop.hbase.protobuf.generated.FilterProtos;
30 import org.apache.hadoop.hbase.util.Bytes;
31
32 import java.util.ArrayList;
33
34
35
36
37
38
39 @InterfaceAudience.Public
40 @InterfaceStability.Stable
41 public class ColumnPrefixFilter extends FilterBase {
42 protected byte [] prefix = null;
43
44 public ColumnPrefixFilter(final byte [] prefix) {
45 this.prefix = prefix;
46 }
47
48 public byte[] getPrefix() {
49 return prefix;
50 }
51
52 @Override
53 public ReturnCode filterKeyValue(KeyValue kv) {
54 if (this.prefix == null || kv.getBuffer() == null) {
55 return ReturnCode.INCLUDE;
56 } else {
57 return filterColumn(kv.getBuffer(), kv.getQualifierOffset(), kv.getQualifierLength());
58 }
59 }
60
61 public ReturnCode filterColumn(byte[] buffer, int qualifierOffset, int qualifierLength) {
62 if (qualifierLength < prefix.length) {
63 int cmp = Bytes.compareTo(buffer, qualifierOffset, qualifierLength, this.prefix, 0,
64 qualifierLength);
65 if (cmp <= 0) {
66 return ReturnCode.SEEK_NEXT_USING_HINT;
67 } else {
68 return ReturnCode.NEXT_ROW;
69 }
70 } else {
71 int cmp = Bytes.compareTo(buffer, qualifierOffset, this.prefix.length, this.prefix, 0,
72 this.prefix.length);
73 if (cmp < 0) {
74 return ReturnCode.SEEK_NEXT_USING_HINT;
75 } else if (cmp > 0) {
76 return ReturnCode.NEXT_ROW;
77 } else {
78 return ReturnCode.INCLUDE;
79 }
80 }
81 }
82
83 public static Filter createFilterFromArguments(ArrayList<byte []> filterArguments) {
84 Preconditions.checkArgument(filterArguments.size() == 1,
85 "Expected 1 but got: %s", filterArguments.size());
86 byte [] columnPrefix = ParseFilter.removeQuotesFromByteArray(filterArguments.get(0));
87 return new ColumnPrefixFilter(columnPrefix);
88 }
89
90
91
92
93 public byte [] toByteArray() {
94 FilterProtos.ColumnPrefixFilter.Builder builder =
95 FilterProtos.ColumnPrefixFilter.newBuilder();
96 if (this.prefix != null) builder.setPrefix(ByteString.copyFrom(this.prefix));
97 return builder.build().toByteArray();
98 }
99
100
101
102
103
104
105
106 public static ColumnPrefixFilter parseFrom(final byte [] pbBytes)
107 throws DeserializationException {
108 FilterProtos.ColumnPrefixFilter proto;
109 try {
110 proto = FilterProtos.ColumnPrefixFilter.parseFrom(pbBytes);
111 } catch (InvalidProtocolBufferException e) {
112 throw new DeserializationException(e);
113 }
114 return new ColumnPrefixFilter(proto.getPrefix().toByteArray());
115 }
116
117
118
119
120
121
122 boolean areSerializedFieldsEqual(Filter o) {
123 if (o == this) return true;
124 if (!(o instanceof ColumnPrefixFilter)) return false;
125
126 ColumnPrefixFilter other = (ColumnPrefixFilter)o;
127 return Bytes.equals(this.getPrefix(), other.getPrefix());
128 }
129
130 public KeyValue getNextKeyHint(KeyValue kv) {
131 return KeyValue.createFirstOnRow(
132 kv.getBuffer(), kv.getRowOffset(), kv.getRowLength(), kv.getBuffer(),
133 kv.getFamilyOffset(), kv.getFamilyLength(), prefix, 0, prefix.length);
134 }
135
136 @Override
137 public String toString() {
138 return this.getClass().getSimpleName() + " " + Bytes.toStringBinary(this.prefix);
139 }
140 }