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 java.io.DataInput;
23 import java.io.DataOutput;
24 import java.io.IOException;
25 import java.util.HashSet;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Set;
29 import java.util.ArrayList;
30
31 import org.apache.hadoop.hbase.KeyValue;
32 import org.apache.hadoop.hbase.util.Bytes;
33
34 import com.google.common.base.Preconditions;
35
36
37
38
39
40
41
42
43 public class DependentColumnFilter extends CompareFilter {
44
45 protected byte[] columnFamily;
46 protected byte[] columnQualifier;
47 protected boolean dropDependentColumn;
48
49 protected Set<Long> stampSet = new HashSet<Long>();
50
51
52
53
54 public DependentColumnFilter() {
55 }
56
57
58
59
60
61
62
63
64
65
66
67
68
69 public DependentColumnFilter(final byte [] family, final byte[] qualifier,
70 final boolean dropDependentColumn, final CompareOp valueCompareOp,
71 final WritableByteArrayComparable valueComparator) {
72
73 super(valueCompareOp, valueComparator);
74 this.columnFamily = family;
75 this.columnQualifier = qualifier;
76 this.dropDependentColumn = dropDependentColumn;
77 }
78
79
80
81
82
83
84
85
86
87 public DependentColumnFilter(final byte [] family, final byte [] qualifier) {
88 this(family, qualifier, false);
89 }
90
91
92
93
94
95
96
97
98
99
100 public DependentColumnFilter(final byte [] family, final byte [] qualifier,
101 final boolean dropDependentColumn) {
102 this(family, qualifier, dropDependentColumn, CompareOp.NO_OP, null);
103 }
104
105
106
107
108 public byte[] getFamily() {
109 return this.columnFamily;
110 }
111
112
113
114
115 public byte[] getQualifier() {
116 return this.columnQualifier;
117 }
118
119
120
121
122 public boolean dropDependentColumn() {
123 return this.dropDependentColumn;
124 }
125
126 public boolean getDropDependentColumn() {
127 return this.dropDependentColumn;
128 }
129
130 @Override
131 public boolean filterAllRemaining() {
132 return false;
133 }
134
135 @Override
136 public ReturnCode filterKeyValue(KeyValue v) {
137
138 if (!v.matchingColumn(this.columnFamily, this.columnQualifier)) {
139
140 return ReturnCode.INCLUDE;
141 }
142
143 if(comparator != null && doCompare(compareOp, comparator, v.getValue(), 0, v.getValueLength()))
144 return ReturnCode.SKIP;
145
146 stampSet.add(v.getTimestamp());
147 if(dropDependentColumn) {
148 return ReturnCode.SKIP;
149 }
150 return ReturnCode.INCLUDE;
151 }
152
153 @Override
154 public void filterRow(List<KeyValue> kvs) {
155 Iterator<KeyValue> it = kvs.iterator();
156 KeyValue kv;
157 while(it.hasNext()) {
158 kv = it.next();
159 if(!stampSet.contains(kv.getTimestamp())) {
160 it.remove();
161 }
162 }
163 }
164
165 @Override
166 public boolean hasFilterRow() {
167 return true;
168 }
169
170 @Override
171 public boolean filterRow() {
172 return false;
173 }
174
175 @Override
176 public boolean filterRowKey(byte[] buffer, int offset, int length) {
177 return false;
178 }
179 @Override
180 public void reset() {
181 stampSet.clear();
182 }
183
184 public static Filter createFilterFromArguments(ArrayList<byte []> filterArguments) {
185 Preconditions.checkArgument(filterArguments.size() == 2 ||
186 filterArguments.size() == 3 ||
187 filterArguments.size() == 5,
188 "Expected 2, 3 or 5 but got: %s", filterArguments.size());
189 if (filterArguments.size() == 2) {
190 byte [] family = ParseFilter.removeQuotesFromByteArray(filterArguments.get(0));
191 byte [] qualifier = ParseFilter.removeQuotesFromByteArray(filterArguments.get(1));
192 return new DependentColumnFilter(family, qualifier);
193
194 } else if (filterArguments.size() == 3) {
195 byte [] family = ParseFilter.removeQuotesFromByteArray(filterArguments.get(0));
196 byte [] qualifier = ParseFilter.removeQuotesFromByteArray(filterArguments.get(1));
197 boolean dropDependentColumn = ParseFilter.convertByteArrayToBoolean(filterArguments.get(2));
198 return new DependentColumnFilter(family, qualifier, dropDependentColumn);
199
200 } else if (filterArguments.size() == 5) {
201 byte [] family = ParseFilter.removeQuotesFromByteArray(filterArguments.get(0));
202 byte [] qualifier = ParseFilter.removeQuotesFromByteArray(filterArguments.get(1));
203 boolean dropDependentColumn = ParseFilter.convertByteArrayToBoolean(filterArguments.get(2));
204 CompareOp compareOp = ParseFilter.createCompareOp(filterArguments.get(3));
205 WritableByteArrayComparable comparator = ParseFilter.createComparator(
206 ParseFilter.removeQuotesFromByteArray(filterArguments.get(4)));
207 return new DependentColumnFilter(family, qualifier, dropDependentColumn,
208 compareOp, comparator);
209 } else {
210 throw new IllegalArgumentException("Expected 2, 3 or 5 but got: " + filterArguments.size());
211 }
212 }
213
214 @Override
215 public void readFields(DataInput in) throws IOException {
216 super.readFields(in);
217 this.columnFamily = Bytes.readByteArray(in);
218 if(this.columnFamily.length == 0) {
219 this.columnFamily = null;
220 }
221
222 this.columnQualifier = Bytes.readByteArray(in);
223 if(this.columnQualifier.length == 0) {
224 this.columnQualifier = null;
225 }
226
227 this.dropDependentColumn = in.readBoolean();
228 }
229
230 @Override
231 public void write(DataOutput out) throws IOException {
232 super.write(out);
233 Bytes.writeByteArray(out, this.columnFamily);
234 Bytes.writeByteArray(out, this.columnQualifier);
235 out.writeBoolean(this.dropDependentColumn);
236 }
237
238 }