1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.filter;
19
20 import com.google.common.base.Preconditions;
21 import com.google.protobuf.InvalidProtocolBufferException;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.TreeSet;
26
27 import org.apache.hadoop.hbase.Cell;
28 import org.apache.hadoop.hbase.KeyValueUtil;
29 import org.apache.hadoop.hbase.classification.InterfaceAudience;
30 import org.apache.hadoop.hbase.classification.InterfaceStability;
31 import org.apache.hadoop.hbase.exceptions.DeserializationException;
32 import org.apache.hadoop.hbase.protobuf.generated.FilterProtos;
33
34
35
36
37
38
39
40
41
42
43 @InterfaceAudience.Public
44 @InterfaceStability.Stable
45 public class TimestampsFilter extends FilterBase {
46
47 private final boolean canHint;
48 TreeSet<Long> timestamps;
49 private static final int MAX_LOG_TIMESTAMPS = 5;
50
51
52
53 long minTimeStamp = Long.MAX_VALUE;
54
55
56
57
58
59 public TimestampsFilter(List<Long> timestamps) {
60 this(timestamps, false);
61 }
62
63
64
65
66
67
68
69
70
71
72
73
74 public TimestampsFilter(List<Long> timestamps, boolean canHint) {
75 for (Long timestamp : timestamps) {
76 Preconditions.checkArgument(timestamp >= 0, "must be positive %s", timestamp);
77 }
78 this.canHint = canHint;
79 this.timestamps = new TreeSet<Long>(timestamps);
80 init();
81 }
82
83
84
85
86 public List<Long> getTimestamps() {
87 List<Long> list = new ArrayList<Long>(timestamps.size());
88 list.addAll(timestamps);
89 return list;
90 }
91
92 private void init() {
93 if (this.timestamps.size() > 0) {
94 minTimeStamp = this.timestamps.first();
95 }
96 }
97
98
99
100
101
102 public long getMin() {
103 return minTimeStamp;
104 }
105
106 @Override
107 public ReturnCode filterKeyValue(Cell v) {
108 if (this.timestamps.contains(v.getTimestamp())) {
109 return ReturnCode.INCLUDE;
110 } else if (v.getTimestamp() < minTimeStamp) {
111
112
113 return ReturnCode.NEXT_COL;
114 }
115 return canHint ? ReturnCode.SEEK_NEXT_USING_HINT : ReturnCode.SKIP;
116 }
117
118
119
120
121
122
123
124
125
126
127 public Cell getNextCellHint(Cell currentCell) throws IOException {
128 if (!canHint) {
129 return null;
130 }
131
132 Long nextTimestampObject = timestamps.lower(currentCell.getTimestamp());
133
134 if (nextTimestampObject == null) {
135
136
137
138
139
140
141
142 return KeyValueUtil.createLastOnRowCol(currentCell);
143 }
144
145
146
147
148 long nextTimestamp = nextTimestampObject;
149 return KeyValueUtil.createFirstOnRowColTS(currentCell, nextTimestamp);
150 }
151
152 public static Filter createFilterFromArguments(ArrayList<byte []> filterArguments) {
153 ArrayList<Long> timestamps = new ArrayList<Long>();
154 for (int i = 0; i<filterArguments.size(); i++) {
155 long timestamp = ParseFilter.convertByteArrayToLong(filterArguments.get(i));
156 timestamps.add(timestamp);
157 }
158 return new TimestampsFilter(timestamps);
159 }
160
161
162
163
164 public byte[] toByteArray() {
165 FilterProtos.TimestampsFilter.Builder builder =
166 FilterProtos.TimestampsFilter.newBuilder();
167 builder.addAllTimestamps(this.timestamps);
168 builder.setCanHint(canHint);
169 return builder.build().toByteArray();
170 }
171
172
173
174
175
176
177
178 public static TimestampsFilter parseFrom(final byte[] pbBytes)
179 throws DeserializationException {
180 FilterProtos.TimestampsFilter proto;
181 try {
182 proto = FilterProtos.TimestampsFilter.parseFrom(pbBytes);
183 } catch (InvalidProtocolBufferException e) {
184 throw new DeserializationException(e);
185 }
186 return new TimestampsFilter(proto.getTimestampsList(),
187 proto.hasCanHint() && proto.getCanHint());
188 }
189
190
191
192
193
194
195 boolean areSerializedFieldsEqual(Filter o) {
196 if (o == this) return true;
197 if (!(o instanceof TimestampsFilter)) return false;
198
199 TimestampsFilter other = (TimestampsFilter)o;
200 return this.getTimestamps().equals(other.getTimestamps());
201 }
202
203 @Override
204 public String toString() {
205 return toString(MAX_LOG_TIMESTAMPS);
206 }
207
208 protected String toString(int maxTimestamps) {
209 StringBuilder tsList = new StringBuilder();
210
211 int count = 0;
212 for (Long ts : this.timestamps) {
213 if (count >= maxTimestamps) {
214 break;
215 }
216 ++count;
217 tsList.append(ts.toString());
218 if (count < this.timestamps.size() && count < maxTimestamps) {
219 tsList.append(", ");
220 }
221 }
222
223 return String.format("%s (%d/%d): [%s] canHint: [%b]", this.getClass().getSimpleName(),
224 count, this.timestamps.size(), tsList.toString(), canHint);
225 }
226 }