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.client;
21
22 import static org.junit.Assert.*;
23
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.List;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.apache.hadoop.hbase.*;
32 import org.apache.hadoop.hbase.filter.Filter;
33 import org.apache.hadoop.hbase.filter.TimestampsFilter;
34 import org.apache.hadoop.hbase.util.Bytes;
35 import org.junit.After;
36 import org.junit.AfterClass;
37 import org.junit.Before;
38 import org.junit.BeforeClass;
39 import org.junit.Test;
40 import org.junit.experimental.categories.Category;
41
42
43
44
45
46
47 @Category(MediumTests.class)
48 public class TestTimestampsFilter {
49 final Log LOG = LogFactory.getLog(getClass());
50 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
51
52
53
54
55 @BeforeClass
56 public static void setUpBeforeClass() throws Exception {
57 TEST_UTIL.startMiniCluster();
58 }
59
60
61
62
63 @AfterClass
64 public static void tearDownAfterClass() throws Exception {
65 TEST_UTIL.shutdownMiniCluster();
66 }
67
68
69
70
71 @Before
72 public void setUp() throws Exception {
73
74 }
75
76
77
78
79 @After
80 public void tearDown() throws Exception {
81
82 }
83
84
85
86
87
88
89
90
91
92 @Test
93 public void testTimestampsFilter() throws Exception {
94 byte [] TABLE = Bytes.toBytes("testTimestampsFilter");
95 byte [] FAMILY = Bytes.toBytes("event_log");
96 byte [][] FAMILIES = new byte[][] { FAMILY };
97 KeyValue kvs[];
98
99
100 HTable ht = TEST_UTIL.createTable(TABLE, FAMILIES, Integer.MAX_VALUE);
101
102 for (int rowIdx = 0; rowIdx < 5; rowIdx++) {
103 for (int colIdx = 0; colIdx < 5; colIdx++) {
104
105 putNVersions(ht, FAMILY, rowIdx, colIdx, 201, 300);
106
107 putNVersions(ht, FAMILY, rowIdx, colIdx, 1, 100);
108 }
109 }
110
111
112 verifyInsertedValues(ht, FAMILY);
113
114 TEST_UTIL.flush();
115
116
117 verifyInsertedValues(ht, FAMILY);
118
119
120
121 for (int rowIdx = 0; rowIdx < 5; rowIdx++) {
122 for (int colIdx = 0; colIdx < 5; colIdx++) {
123 putNVersions(ht, FAMILY, rowIdx, colIdx, 301, 400);
124 putNVersions(ht, FAMILY, rowIdx, colIdx, 101, 200);
125 }
126 }
127
128 for (int rowIdx = 0; rowIdx < 5; rowIdx++) {
129 for (int colIdx = 0; colIdx < 5; colIdx++) {
130 kvs = getNVersions(ht, FAMILY, rowIdx, colIdx,
131 Arrays.asList(505L, 5L, 105L, 305L, 205L));
132 assertEquals(4, kvs.length);
133 checkOneCell(kvs[0], FAMILY, rowIdx, colIdx, 305);
134 checkOneCell(kvs[1], FAMILY, rowIdx, colIdx, 205);
135 checkOneCell(kvs[2], FAMILY, rowIdx, colIdx, 105);
136 checkOneCell(kvs[3], FAMILY, rowIdx, colIdx, 5);
137 }
138 }
139
140
141
142 kvs = getNVersions(ht, FAMILY, 2, 2, new ArrayList<Long>());
143 assertEquals(0, kvs.length);
144
145
146
147
148
149 Result[] results = scanNVersions(ht, FAMILY, 0, 4,
150 Arrays.asList(6L, 106L, 306L));
151 assertEquals("# of rows returned from scan", 5, results.length);
152 for (int rowIdx = 0; rowIdx < 5; rowIdx++) {
153 kvs = results[rowIdx].raw();
154
155
156 assertEquals("Number of KeyValues in result for row:" + rowIdx,
157 3*5, kvs.length);
158 for (int colIdx = 0; colIdx < 5; colIdx++) {
159 int offset = colIdx * 3;
160 checkOneCell(kvs[offset + 0], FAMILY, rowIdx, colIdx, 306);
161 checkOneCell(kvs[offset + 1], FAMILY, rowIdx, colIdx, 106);
162 checkOneCell(kvs[offset + 2], FAMILY, rowIdx, colIdx, 6);
163 }
164 }
165 ht.close();
166 }
167
168 @Test
169 public void testMultiColumns() throws Exception {
170 byte [] TABLE = Bytes.toBytes("testTimestampsFilterMultiColumns");
171 byte [] FAMILY = Bytes.toBytes("event_log");
172 byte [][] FAMILIES = new byte[][] { FAMILY };
173 KeyValue kvs[];
174
175
176 HTable ht = TEST_UTIL.createTable(TABLE, FAMILIES, Integer.MAX_VALUE);
177
178 Put p = new Put(Bytes.toBytes("row"));
179 p.add(FAMILY, Bytes.toBytes("column0"), 3, Bytes.toBytes("value0-3"));
180 p.add(FAMILY, Bytes.toBytes("column1"), 3, Bytes.toBytes("value1-3"));
181 p.add(FAMILY, Bytes.toBytes("column2"), 1, Bytes.toBytes("value2-1"));
182 p.add(FAMILY, Bytes.toBytes("column2"), 2, Bytes.toBytes("value2-2"));
183 p.add(FAMILY, Bytes.toBytes("column2"), 3, Bytes.toBytes("value2-3"));
184 p.add(FAMILY, Bytes.toBytes("column3"), 2, Bytes.toBytes("value3-2"));
185 p.add(FAMILY, Bytes.toBytes("column4"), 1, Bytes.toBytes("value4-1"));
186 p.add(FAMILY, Bytes.toBytes("column4"), 2, Bytes.toBytes("value4-2"));
187 p.add(FAMILY, Bytes.toBytes("column4"), 3, Bytes.toBytes("value4-3"));
188 ht.put(p);
189
190 ArrayList timestamps = new ArrayList();
191 timestamps.add(new Long(3));
192 TimestampsFilter filter = new TimestampsFilter(timestamps);
193
194 Get g = new Get(Bytes.toBytes("row"));
195 g.setFilter(filter);
196 g.setMaxVersions();
197 g.addColumn(FAMILY, Bytes.toBytes("column2"));
198 g.addColumn(FAMILY, Bytes.toBytes("column4"));
199
200 Result result = ht.get(g);
201 for (KeyValue kv : result.list()) {
202 System.out.println("found row " + Bytes.toString(kv.getRow()) +
203 ", column " + Bytes.toString(kv.getQualifier()) + ", value "
204 + Bytes.toString(kv.getValue()));
205 }
206
207 assertEquals(result.list().size(), 2);
208 assertEquals(Bytes.toString(result.list().get(0).getValue()),
209 "value2-3");
210 assertEquals(Bytes.toString(result.list().get(1).getValue()),
211 "value4-3");
212
213 ht.close();
214 }
215
216
217
218
219
220
221 @Test
222 public void testWithVersionDeletes() throws Exception {
223
224
225 testWithVersionDeletes(false);
226
227
228 testWithVersionDeletes(true);
229 }
230
231 private void testWithVersionDeletes(boolean flushTables) throws IOException {
232 byte [] TABLE = Bytes.toBytes("testWithVersionDeletes_" +
233 (flushTables ? "flush" : "noflush"));
234 byte [] FAMILY = Bytes.toBytes("event_log");
235 byte [][] FAMILIES = new byte[][] { FAMILY };
236
237
238 HTable ht = TEST_UTIL.createTable(TABLE, FAMILIES, Integer.MAX_VALUE);
239
240
241 putNVersions(ht, FAMILY, 0, 0, 1, 5);
242
243
244 deleteOneVersion(ht, FAMILY, 0, 0, 4);
245
246 if (flushTables) {
247 TEST_UTIL.flush();
248 }
249
250
251
252 KeyValue kvs[] = getNVersions(ht, FAMILY, 0, 0, Arrays.asList(2L, 3L, 4L, 5L));
253 assertEquals(3, kvs.length);
254 checkOneCell(kvs[0], FAMILY, 0, 0, 5);
255 checkOneCell(kvs[1], FAMILY, 0, 0, 3);
256 checkOneCell(kvs[2], FAMILY, 0, 0, 2);
257
258 ht.close();
259 }
260
261 private void verifyInsertedValues(HTable ht, byte[] cf) throws IOException {
262 for (int rowIdx = 0; rowIdx < 5; rowIdx++) {
263 for (int colIdx = 0; colIdx < 5; colIdx++) {
264
265 KeyValue[] kvs = getNVersions(ht, cf, rowIdx, colIdx,
266 Arrays.asList(5L, 300L, 6L, 80L));
267 assertEquals(4, kvs.length);
268 checkOneCell(kvs[0], cf, rowIdx, colIdx, 300);
269 checkOneCell(kvs[1], cf, rowIdx, colIdx, 80);
270 checkOneCell(kvs[2], cf, rowIdx, colIdx, 6);
271 checkOneCell(kvs[3], cf, rowIdx, colIdx, 5);
272
273
274 kvs = getNVersions(ht, cf, rowIdx, colIdx,
275 Arrays.asList(101L, 102L));
276 assertEquals(0, kvs.length);
277
278
279 kvs = getNVersions(ht, cf, rowIdx, colIdx,
280 Arrays.asList(1L, 300L, 105L, 70L, 115L));
281 assertEquals(3, kvs.length);
282 checkOneCell(kvs[0], cf, rowIdx, colIdx, 300);
283 checkOneCell(kvs[1], cf, rowIdx, colIdx, 70);
284 checkOneCell(kvs[2], cf, rowIdx, colIdx, 1);
285 }
286 }
287 }
288
289
290
291
292
293 private void checkOneCell(KeyValue kv, byte[] cf,
294 int rowIdx, int colIdx, long ts) {
295
296 String ctx = "rowIdx=" + rowIdx + "; colIdx=" + colIdx + "; ts=" + ts;
297
298 assertEquals("Row mismatch which checking: " + ctx,
299 "row:"+ rowIdx, Bytes.toString(kv.getRow()));
300
301 assertEquals("ColumnFamily mismatch while checking: " + ctx,
302 Bytes.toString(cf), Bytes.toString(kv.getFamily()));
303
304 assertEquals("Column qualifier mismatch while checking: " + ctx,
305 "column:" + colIdx,
306 Bytes.toString(kv.getQualifier()));
307
308 assertEquals("Timestamp mismatch while checking: " + ctx,
309 ts, kv.getTimestamp());
310
311 assertEquals("Value mismatch while checking: " + ctx,
312 "value-version-" + ts, Bytes.toString(kv.getValue()));
313 }
314
315
316
317
318
319
320 private KeyValue[] getNVersions(HTable ht, byte[] cf, int rowIdx,
321 int colIdx, List<Long> versions)
322 throws IOException {
323 byte row[] = Bytes.toBytes("row:" + rowIdx);
324 byte column[] = Bytes.toBytes("column:" + colIdx);
325 Filter filter = new TimestampsFilter(versions);
326 Get get = new Get(row);
327 get.addColumn(cf, column);
328 get.setFilter(filter);
329 get.setMaxVersions();
330 Result result = ht.get(get);
331
332 return result.raw();
333 }
334
335
336
337
338
339 private Result[] scanNVersions(HTable ht, byte[] cf, int startRowIdx,
340 int endRowIdx, List<Long> versions)
341 throws IOException {
342 byte startRow[] = Bytes.toBytes("row:" + startRowIdx);
343 byte endRow[] = Bytes.toBytes("row:" + endRowIdx + 1);
344 Filter filter = new TimestampsFilter(versions);
345 Scan scan = new Scan(startRow, endRow);
346 scan.setFilter(filter);
347 scan.setMaxVersions();
348 ResultScanner scanner = ht.getScanner(scan);
349 return scanner.next(endRowIdx - startRowIdx + 1);
350 }
351
352
353
354
355
356 private void putNVersions(HTable ht, byte[] cf, int rowIdx, int colIdx,
357 long versionStart, long versionEnd)
358 throws IOException {
359 byte row[] = Bytes.toBytes("row:" + rowIdx);
360 byte column[] = Bytes.toBytes("column:" + colIdx);
361 Put put = new Put(row);
362 put.setWriteToWAL(false);
363
364 for (long idx = versionStart; idx <= versionEnd; idx++) {
365 put.add(cf, column, idx, Bytes.toBytes("value-version-" + idx));
366 }
367
368 ht.put(put);
369 }
370
371
372
373
374
375 private void deleteOneVersion(HTable ht, byte[] cf, int rowIdx,
376 int colIdx, long version)
377 throws IOException {
378 byte row[] = Bytes.toBytes("row:" + rowIdx);
379 byte column[] = Bytes.toBytes("column:" + colIdx);
380 Delete del = new Delete(row);
381 del.deleteColumn(cf, column, version);
382 ht.delete(del);
383 }
384
385 @org.junit.Rule
386 public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu =
387 new org.apache.hadoop.hbase.ResourceCheckerJUnitRule();
388 }
389
390