View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.regionserver;
21  
22  import static org.apache.hadoop.hbase.regionserver.KeyValueScanFixture.scanFixture;
23  
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.List;
28  import java.util.NavigableSet;
29  import java.util.TreeSet;
30  
31  import junit.framework.TestCase;
32  
33  import org.apache.hadoop.hbase.Cell;
34  import org.apache.hadoop.hbase.HConstants;
35  import org.apache.hadoop.hbase.KeepDeletedCells;
36  import org.apache.hadoop.hbase.KeyValue;
37  import org.apache.hadoop.hbase.KeyValueTestUtil;
38  import org.apache.hadoop.hbase.client.Scan;
39  import org.apache.hadoop.hbase.testclassification.MediumTests;
40  import org.apache.hadoop.hbase.util.Bytes;
41  import org.apache.hadoop.hbase.util.EnvironmentEdge;
42  import org.apache.hadoop.hbase.util.EnvironmentEdgeManagerTestHelper;
43  import org.junit.experimental.categories.Category;
44  
45  // Can't be small as it plays with EnvironmentEdgeManager
46  @Category(MediumTests.class)
47  public class TestStoreScanner extends TestCase {
48    private static final String CF_STR = "cf";
49    final byte [] CF = Bytes.toBytes(CF_STR);
50    private ScanInfo scanInfo = new ScanInfo(CF, 0, Integer.MAX_VALUE,
51        Long.MAX_VALUE, KeepDeletedCells.FALSE, 0, KeyValue.COMPARATOR);
52    private ScanType scanType = ScanType.USER_SCAN;
53  
54    public void setUp() throws Exception {
55      super.setUp();
56    }
57  
58    /*
59     * Test utility for building a NavigableSet for scanners.
60     * @param strCols
61     * @return
62     */
63    NavigableSet<byte[]> getCols(String ...strCols) {
64      NavigableSet<byte[]> cols = new TreeSet<byte[]>(Bytes.BYTES_COMPARATOR);
65      for (String col : strCols) {
66        byte[] bytes = Bytes.toBytes(col);
67        cols.add(bytes);
68      }
69      return cols;
70    }
71  
72    public void testScanTimeRange() throws IOException {
73      String r1 = "R1";
74      // returns only 1 of these 2 even though same timestamp
75      KeyValue [] kvs = new KeyValue[] {
76          KeyValueTestUtil.create(r1, CF_STR, "a", 1, KeyValue.Type.Put, "dont-care"),
77          KeyValueTestUtil.create(r1, CF_STR, "a", 2, KeyValue.Type.Put, "dont-care"),
78          KeyValueTestUtil.create(r1, CF_STR, "a", 3, KeyValue.Type.Put, "dont-care"),
79          KeyValueTestUtil.create(r1, CF_STR, "a", 4, KeyValue.Type.Put, "dont-care"),
80          KeyValueTestUtil.create(r1, CF_STR, "a", 5, KeyValue.Type.Put, "dont-care"),
81      };
82      List<KeyValueScanner> scanners = Arrays.<KeyValueScanner>asList(
83          new KeyValueScanner[] {
84              new KeyValueScanFixture(KeyValue.COMPARATOR, kvs)
85      });
86      Scan scanSpec = new Scan(Bytes.toBytes(r1));
87      scanSpec.setTimeRange(0, 6);
88      scanSpec.setMaxVersions();
89      StoreScanner scan = new StoreScanner(scanSpec, scanInfo, scanType,
90          getCols("a"), scanners);
91      List<Cell> results = new ArrayList<Cell>();
92      assertEquals(true, scan.next(results));
93      assertEquals(5, results.size());
94      assertEquals(kvs[kvs.length - 1], results.get(0));
95      // Scan limited TimeRange
96      scanSpec = new Scan(Bytes.toBytes(r1));
97      scanSpec.setTimeRange(1, 3);
98      scanSpec.setMaxVersions();
99      scan = new StoreScanner(scanSpec, scanInfo, scanType, getCols("a"),
100         scanners);
101     results = new ArrayList<Cell>();
102     assertEquals(true, scan.next(results));
103     assertEquals(2, results.size());
104     // Another range.
105     scanSpec = new Scan(Bytes.toBytes(r1));
106     scanSpec.setTimeRange(5, 10);
107     scanSpec.setMaxVersions();
108     scan = new StoreScanner(scanSpec, scanInfo, scanType, getCols("a"),
109         scanners);
110     results = new ArrayList<Cell>();
111     assertEquals(true, scan.next(results));
112     assertEquals(1, results.size());
113     // See how TimeRange and Versions interact.
114     // Another range.
115     scanSpec = new Scan(Bytes.toBytes(r1));
116     scanSpec.setTimeRange(0, 10);
117     scanSpec.setMaxVersions(3);
118     scan = new StoreScanner(scanSpec, scanInfo, scanType, getCols("a"),
119         scanners);
120     results = new ArrayList<Cell>();
121     assertEquals(true, scan.next(results));
122     assertEquals(3, results.size());
123   }
124 
125   public void testScanSameTimestamp() throws IOException {
126     // returns only 1 of these 2 even though same timestamp
127     KeyValue [] kvs = new KeyValue[] {
128         KeyValueTestUtil.create("R1", "cf", "a", 1, KeyValue.Type.Put, "dont-care"),
129         KeyValueTestUtil.create("R1", "cf", "a", 1, KeyValue.Type.Put, "dont-care"),
130     };
131     List<KeyValueScanner> scanners = Arrays.asList(
132         new KeyValueScanner[] {
133             new KeyValueScanFixture(KeyValue.COMPARATOR, kvs)
134         });
135 
136     Scan scanSpec = new Scan(Bytes.toBytes("R1"));
137     // this only uses maxVersions (default=1) and TimeRange (default=all)
138     StoreScanner scan = new StoreScanner(scanSpec, scanInfo, scanType,
139         getCols("a"), scanners);
140 
141     List<Cell> results = new ArrayList<Cell>();
142     assertEquals(true, scan.next(results));
143     assertEquals(1, results.size());
144     assertEquals(kvs[0], results.get(0));
145   }
146 
147   /*
148    * Test test shows exactly how the matcher's return codes confuses the StoreScanner
149    * and prevent it from doing the right thing.  Seeking once, then nexting twice
150    * should return R1, then R2, but in this case it doesnt.
151    * TODO this comment makes no sense above. Appears to do the right thing.
152    * @throws IOException
153    */
154   public void testWontNextToNext() throws IOException {
155     // build the scan file:
156     KeyValue [] kvs = new KeyValue[] {
157         KeyValueTestUtil.create("R1", "cf", "a", 2, KeyValue.Type.Put, "dont-care"),
158         KeyValueTestUtil.create("R1", "cf", "a", 1, KeyValue.Type.Put, "dont-care"),
159         KeyValueTestUtil.create("R2", "cf", "a", 1, KeyValue.Type.Put, "dont-care")
160     };
161     List<KeyValueScanner> scanners = scanFixture(kvs);
162 
163     Scan scanSpec = new Scan(Bytes.toBytes("R1"));
164     // this only uses maxVersions (default=1) and TimeRange (default=all)
165     StoreScanner scan = new StoreScanner(scanSpec, scanInfo, scanType,
166         getCols("a"), scanners);
167 
168     List<Cell> results = new ArrayList<Cell>();
169     scan.next(results);
170     assertEquals(1, results.size());
171     assertEquals(kvs[0], results.get(0));
172     // should be ok...
173     // now scan _next_ again.
174     results.clear();
175     scan.next(results);
176     assertEquals(1, results.size());
177     assertEquals(kvs[2], results.get(0));
178 
179     results.clear();
180     scan.next(results);
181     assertEquals(0, results.size());
182 
183   }
184 
185 
186   public void testDeleteVersionSameTimestamp() throws IOException {
187     KeyValue [] kvs = new KeyValue [] {
188         KeyValueTestUtil.create("R1", "cf", "a", 1, KeyValue.Type.Put, "dont-care"),
189         KeyValueTestUtil.create("R1", "cf", "a", 1, KeyValue.Type.Delete, "dont-care"),
190     };
191     List<KeyValueScanner> scanners = scanFixture(kvs);
192     Scan scanSpec = new Scan(Bytes.toBytes("R1"));
193     StoreScanner scan = new StoreScanner(scanSpec, scanInfo, scanType,
194         getCols("a"), scanners);
195 
196     List<Cell> results = new ArrayList<Cell>();
197     assertFalse(scan.next(results));
198     assertEquals(0, results.size());
199   }
200 
201   /*
202    * Test the case where there is a delete row 'in front of' the next row, the scanner
203    * will move to the next row.
204    */
205   public void testDeletedRowThenGoodRow() throws IOException {
206     KeyValue [] kvs = new KeyValue [] {
207         KeyValueTestUtil.create("R1", "cf", "a", 1, KeyValue.Type.Put, "dont-care"),
208         KeyValueTestUtil.create("R1", "cf", "a", 1, KeyValue.Type.Delete, "dont-care"),
209         KeyValueTestUtil.create("R2", "cf", "a", 20, KeyValue.Type.Put, "dont-care")
210     };
211     List<KeyValueScanner> scanners = scanFixture(kvs);
212     Scan scanSpec = new Scan(Bytes.toBytes("R1"));
213     StoreScanner scan = new StoreScanner(scanSpec, scanInfo, scanType,
214         getCols("a"), scanners);
215 
216     List<Cell> results = new ArrayList<Cell>();
217     assertEquals(true, scan.next(results));
218     assertEquals(0, results.size());
219 
220     assertEquals(true, scan.next(results));
221     assertEquals(1, results.size());
222     assertEquals(kvs[2], results.get(0));
223 
224     assertEquals(false, scan.next(results));
225   }
226 
227   public void testDeleteVersionMaskingMultiplePuts() throws IOException {
228     long now = System.currentTimeMillis();
229     KeyValue [] kvs1 = new KeyValue[] {
230         KeyValueTestUtil.create("R1", "cf", "a", now, KeyValue.Type.Put, "dont-care"),
231         KeyValueTestUtil.create("R1", "cf", "a", now, KeyValue.Type.Delete, "dont-care")
232     };
233     KeyValue [] kvs2 = new KeyValue[] {
234         KeyValueTestUtil.create("R1", "cf", "a", now-500, KeyValue.Type.Put, "dont-care"),
235         KeyValueTestUtil.create("R1", "cf", "a", now-100, KeyValue.Type.Put, "dont-care"),
236         KeyValueTestUtil.create("R1", "cf", "a", now, KeyValue.Type.Put, "dont-care")
237     };
238     List<KeyValueScanner> scanners = scanFixture(kvs1, kvs2);
239 
240     StoreScanner scan = new StoreScanner(new Scan(Bytes.toBytes("R1")),
241         scanInfo, scanType, getCols("a"), scanners);
242     List<Cell> results = new ArrayList<Cell>();
243     // the two put at ts=now will be masked by the 1 delete, and
244     // since the scan default returns 1 version we'll return the newest
245     // key, which is kvs[2], now-100.
246     assertEquals(true, scan.next(results));
247     assertEquals(1, results.size());
248     assertEquals(kvs2[1], results.get(0));
249   }
250   public void testDeleteVersionsMixedAndMultipleVersionReturn() throws IOException {
251     long now = System.currentTimeMillis();
252     KeyValue [] kvs1 = new KeyValue[] {
253         KeyValueTestUtil.create("R1", "cf", "a", now, KeyValue.Type.Put, "dont-care"),
254         KeyValueTestUtil.create("R1", "cf", "a", now, KeyValue.Type.Delete, "dont-care")
255     };
256     KeyValue [] kvs2 = new KeyValue[] {
257         KeyValueTestUtil.create("R1", "cf", "a", now-500, KeyValue.Type.Put, "dont-care"),
258         KeyValueTestUtil.create("R1", "cf", "a", now+500, KeyValue.Type.Put, "dont-care"),
259         KeyValueTestUtil.create("R1", "cf", "a", now, KeyValue.Type.Put, "dont-care"),
260         KeyValueTestUtil.create("R2", "cf", "z", now, KeyValue.Type.Put, "dont-care")
261     };
262     List<KeyValueScanner> scanners = scanFixture(kvs1, kvs2);
263 
264     Scan scanSpec = new Scan(Bytes.toBytes("R1")).setMaxVersions(2);
265     StoreScanner scan = new StoreScanner(scanSpec, scanInfo, scanType,
266         getCols("a"), scanners);
267     List<Cell> results = new ArrayList<Cell>();
268     assertEquals(true, scan.next(results));
269     assertEquals(2, results.size());
270     assertEquals(kvs2[1], results.get(0));
271     assertEquals(kvs2[0], results.get(1));
272   }
273 
274   public void testWildCardOneVersionScan() throws IOException {
275     KeyValue [] kvs = new KeyValue [] {
276         KeyValueTestUtil.create("R1", "cf", "a", 2, KeyValue.Type.Put, "dont-care"),
277         KeyValueTestUtil.create("R1", "cf", "b", 1, KeyValue.Type.Put, "dont-care"),
278         KeyValueTestUtil.create("R1", "cf", "a", 1, KeyValue.Type.DeleteColumn, "dont-care"),
279     };
280     List<KeyValueScanner> scanners = scanFixture(kvs);
281     StoreScanner scan = new StoreScanner(new Scan(Bytes.toBytes("R1")),
282         scanInfo, scanType, null, scanners);
283     List<Cell> results = new ArrayList<Cell>();
284     assertEquals(true, scan.next(results));
285     assertEquals(2, results.size());
286     assertEquals(kvs[0], results.get(0));
287     assertEquals(kvs[1], results.get(1));
288   }
289 
290   public void testWildCardScannerUnderDeletes() throws IOException {
291     KeyValue [] kvs = new KeyValue [] {
292         KeyValueTestUtil.create("R1", "cf", "a", 2, KeyValue.Type.Put, "dont-care"), // inc
293         // orphaned delete column.
294         KeyValueTestUtil.create("R1", "cf", "a", 1, KeyValue.Type.DeleteColumn, "dont-care"),
295         // column b
296         KeyValueTestUtil.create("R1", "cf", "b", 2, KeyValue.Type.Put, "dont-care"), // inc
297         KeyValueTestUtil.create("R1", "cf", "b", 1, KeyValue.Type.Put, "dont-care"), // inc
298         // column c
299         KeyValueTestUtil.create("R1", "cf", "c", 10, KeyValue.Type.Delete, "dont-care"),
300         KeyValueTestUtil.create("R1", "cf", "c", 10, KeyValue.Type.Put, "dont-care"), // no
301         KeyValueTestUtil.create("R1", "cf", "c", 9, KeyValue.Type.Put, "dont-care"),  // inc
302         // column d
303         KeyValueTestUtil.create("R1", "cf", "d", 11, KeyValue.Type.Put, "dont-care"), // inc
304         KeyValueTestUtil.create("R1", "cf", "d", 10, KeyValue.Type.DeleteColumn, "dont-care"),
305         KeyValueTestUtil.create("R1", "cf", "d", 9, KeyValue.Type.Put, "dont-care"),  // no
306         KeyValueTestUtil.create("R1", "cf", "d", 8, KeyValue.Type.Put, "dont-care"),  // no
307 
308     };
309     List<KeyValueScanner> scanners = scanFixture(kvs);
310     StoreScanner scan = new StoreScanner(new Scan().setMaxVersions(2),
311         scanInfo, scanType, null, scanners);
312     List<Cell> results = new ArrayList<Cell>();
313     assertEquals(true, scan.next(results));
314     assertEquals(5, results.size());
315     assertEquals(kvs[0], results.get(0));
316     assertEquals(kvs[2], results.get(1));
317     assertEquals(kvs[3], results.get(2));
318     assertEquals(kvs[6], results.get(3));
319     assertEquals(kvs[7], results.get(4));
320   }
321 
322   public void testDeleteFamily() throws IOException {
323     KeyValue [] kvs = new KeyValue[] {
324         KeyValueTestUtil.create("R1", "cf", "a", 100, KeyValue.Type.DeleteFamily, "dont-care"),
325         KeyValueTestUtil.create("R1", "cf", "b", 11, KeyValue.Type.Put, "dont-care"),
326         KeyValueTestUtil.create("R1", "cf", "c", 11, KeyValue.Type.Put, "dont-care"),
327         KeyValueTestUtil.create("R1", "cf", "d", 11, KeyValue.Type.Put, "dont-care"),
328         KeyValueTestUtil.create("R1", "cf", "e", 11, KeyValue.Type.Put, "dont-care"),
329         KeyValueTestUtil.create("R1", "cf", "e", 11, KeyValue.Type.DeleteColumn, "dont-care"),
330         KeyValueTestUtil.create("R1", "cf", "f", 11, KeyValue.Type.Put, "dont-care"),
331         KeyValueTestUtil.create("R1", "cf", "g", 11, KeyValue.Type.Put, "dont-care"),
332         KeyValueTestUtil.create("R1", "cf", "g", 11, KeyValue.Type.Delete, "dont-care"),
333         KeyValueTestUtil.create("R1", "cf", "h", 11, KeyValue.Type.Put, "dont-care"),
334         KeyValueTestUtil.create("R1", "cf", "i", 11, KeyValue.Type.Put, "dont-care"),
335         KeyValueTestUtil.create("R2", "cf", "a", 11, KeyValue.Type.Put, "dont-care"),
336     };
337     List<KeyValueScanner> scanners = scanFixture(kvs);
338     StoreScanner scan = new StoreScanner(
339         new Scan().setMaxVersions(Integer.MAX_VALUE), scanInfo, scanType, null,
340         scanners);
341     List<Cell> results = new ArrayList<Cell>();
342     assertEquals(true, scan.next(results));
343     assertEquals(0, results.size());
344     assertEquals(true, scan.next(results));
345     assertEquals(1, results.size());
346     assertEquals(kvs[kvs.length-1], results.get(0));
347 
348     assertEquals(false, scan.next(results));
349   }
350 
351   public void testDeleteColumn() throws IOException {
352     KeyValue [] kvs = new KeyValue[] {
353         KeyValueTestUtil.create("R1", "cf", "a", 10, KeyValue.Type.DeleteColumn, "dont-care"),
354         KeyValueTestUtil.create("R1", "cf", "a", 9, KeyValue.Type.Delete, "dont-care"),
355         KeyValueTestUtil.create("R1", "cf", "a", 8, KeyValue.Type.Put, "dont-care"),
356         KeyValueTestUtil.create("R1", "cf", "b", 5, KeyValue.Type.Put, "dont-care")
357     };
358     List<KeyValueScanner> scanners = scanFixture(kvs);
359     StoreScanner scan = new StoreScanner(new Scan(), scanInfo, scanType, null,
360         scanners);
361     List<Cell> results = new ArrayList<Cell>();
362     assertEquals(true, scan.next(results));
363     assertEquals(1, results.size());
364     assertEquals(kvs[3], results.get(0));
365   }
366 
367   private static final  KeyValue [] kvs = new KeyValue[] {
368         KeyValueTestUtil.create("R1", "cf", "a", 11, KeyValue.Type.Put, "dont-care"),
369         KeyValueTestUtil.create("R1", "cf", "b", 11, KeyValue.Type.Put, "dont-care"),
370         KeyValueTestUtil.create("R1", "cf", "c", 11, KeyValue.Type.Put, "dont-care"),
371         KeyValueTestUtil.create("R1", "cf", "d", 11, KeyValue.Type.Put, "dont-care"),
372         KeyValueTestUtil.create("R1", "cf", "e", 11, KeyValue.Type.Put, "dont-care"),
373         KeyValueTestUtil.create("R1", "cf", "f", 11, KeyValue.Type.Put, "dont-care"),
374         KeyValueTestUtil.create("R1", "cf", "g", 11, KeyValue.Type.Put, "dont-care"),
375         KeyValueTestUtil.create("R1", "cf", "h", 11, KeyValue.Type.Put, "dont-care"),
376         KeyValueTestUtil.create("R1", "cf", "i", 11, KeyValue.Type.Put, "dont-care"),
377         KeyValueTestUtil.create("R2", "cf", "a", 11, KeyValue.Type.Put, "dont-care"),
378     };
379 
380   public void testSkipColumn() throws IOException {
381     List<KeyValueScanner> scanners = scanFixture(kvs);
382     StoreScanner scan = new StoreScanner(new Scan(), scanInfo, scanType,
383         getCols("a", "d"), scanners);
384 
385     List<Cell> results = new ArrayList<Cell>();
386     assertEquals(true, scan.next(results));
387     assertEquals(2, results.size());
388     assertEquals(kvs[0], results.get(0));
389     assertEquals(kvs[3], results.get(1));
390     results.clear();
391 
392     assertEquals(true, scan.next(results));
393     assertEquals(1, results.size());
394     assertEquals(kvs[kvs.length-1], results.get(0));
395 
396     results.clear();
397     assertEquals(false, scan.next(results));
398   }
399 
400   /*
401    * Test expiration of KeyValues in combination with a configured TTL for
402    * a column family (as should be triggered in a major compaction).
403    */
404   public void testWildCardTtlScan() throws IOException {
405     long now = System.currentTimeMillis();
406     KeyValue [] kvs = new KeyValue[] {
407         KeyValueTestUtil.create("R1", "cf", "a", now-1000, KeyValue.Type.Put, "dont-care"),
408         KeyValueTestUtil.create("R1", "cf", "b", now-10, KeyValue.Type.Put, "dont-care"),
409         KeyValueTestUtil.create("R1", "cf", "c", now-200, KeyValue.Type.Put, "dont-care"),
410         KeyValueTestUtil.create("R1", "cf", "d", now-10000, KeyValue.Type.Put, "dont-care"),
411         KeyValueTestUtil.create("R2", "cf", "a", now, KeyValue.Type.Put, "dont-care"),
412         KeyValueTestUtil.create("R2", "cf", "b", now-10, KeyValue.Type.Put, "dont-care"),
413         KeyValueTestUtil.create("R2", "cf", "c", now-200, KeyValue.Type.Put, "dont-care"),
414         KeyValueTestUtil.create("R2", "cf", "c", now-1000, KeyValue.Type.Put, "dont-care")
415     };
416     List<KeyValueScanner> scanners = scanFixture(kvs);
417     Scan scan = new Scan();
418     scan.setMaxVersions(1);
419     ScanInfo scanInfo = new ScanInfo(CF, 0, 1, 500, KeepDeletedCells.FALSE, 0,
420         KeyValue.COMPARATOR);
421     ScanType scanType = ScanType.USER_SCAN;
422     StoreScanner scanner =
423       new StoreScanner(scan, scanInfo, scanType,
424           null, scanners);
425 
426     List<Cell> results = new ArrayList<Cell>();
427     assertEquals(true, scanner.next(results));
428     assertEquals(2, results.size());
429     assertEquals(kvs[1], results.get(0));
430     assertEquals(kvs[2], results.get(1));
431     results.clear();
432 
433     assertEquals(true, scanner.next(results));
434     assertEquals(3, results.size());
435     assertEquals(kvs[4], results.get(0));
436     assertEquals(kvs[5], results.get(1));
437     assertEquals(kvs[6], results.get(2));
438     results.clear();
439 
440     assertEquals(false, scanner.next(results));
441   }
442 
443   public void testScannerReseekDoesntNPE() throws Exception {
444     List<KeyValueScanner> scanners = scanFixture(kvs);
445     StoreScanner scan = new StoreScanner(new Scan(), scanInfo, scanType,
446         getCols("a", "d"), scanners);
447 
448     // Previously a updateReaders twice in a row would cause an NPE.  In test this would also
449     // normally cause an NPE because scan.store is null.  So as long as we get through these
450     // two calls we are good and the bug was quashed.
451 
452     scan.updateReaders();
453 
454     scan.updateReaders();
455 
456     scan.peek();
457   }
458 
459 
460   /**
461    * TODO this fails, since we don't handle deletions, etc, in peek
462    */
463   public void SKIP_testPeek() throws Exception {
464     KeyValue [] kvs = new KeyValue [] {
465         KeyValueTestUtil.create("R1", "cf", "a", 1, KeyValue.Type.Put, "dont-care"),
466         KeyValueTestUtil.create("R1", "cf", "a", 1, KeyValue.Type.Delete, "dont-care"),
467     };
468     List<KeyValueScanner> scanners = scanFixture(kvs);
469     Scan scanSpec = new Scan(Bytes.toBytes("R1"));
470     StoreScanner scan = new StoreScanner(scanSpec, scanInfo, scanType,
471         getCols("a"), scanners);
472     assertNull(scan.peek());
473   }
474 
475   /**
476    * Ensure that expired delete family markers don't override valid puts
477    */
478   public void testExpiredDeleteFamily() throws Exception {
479     long now = System.currentTimeMillis();
480     KeyValue [] kvs = new KeyValue[] {
481         new KeyValue(Bytes.toBytes("R1"), Bytes.toBytes("cf"), null, now-1000,
482             KeyValue.Type.DeleteFamily),
483         KeyValueTestUtil.create("R1", "cf", "a", now-10, KeyValue.Type.Put,
484             "dont-care"),
485     };
486     List<KeyValueScanner> scanners = scanFixture(kvs);
487     Scan scan = new Scan();
488     scan.setMaxVersions(1);
489     // scanner with ttl equal to 500
490     ScanInfo scanInfo = new ScanInfo(CF, 0, 1, 500, KeepDeletedCells.FALSE, 0,
491         KeyValue.COMPARATOR);
492     ScanType scanType = ScanType.USER_SCAN;
493     StoreScanner scanner =
494         new StoreScanner(scan, scanInfo, scanType, null, scanners);
495 
496     List<Cell> results = new ArrayList<Cell>();
497     assertEquals(true, scanner.next(results));
498     assertEquals(1, results.size());
499     assertEquals(kvs[1], results.get(0));
500     results.clear();
501 
502     assertEquals(false, scanner.next(results));
503   }
504 
505   public void testDeleteMarkerLongevity() throws Exception {
506     try {
507       final long now = System.currentTimeMillis();
508       EnvironmentEdgeManagerTestHelper.injectEdge(new EnvironmentEdge() {
509         public long currentTime() {
510           return now;
511         }
512       });
513       KeyValue[] kvs = new KeyValue[]{
514         /*0*/ new KeyValue(Bytes.toBytes("R1"), Bytes.toBytes("cf"), null,
515         now - 100, KeyValue.Type.DeleteFamily), // live
516         /*1*/ new KeyValue(Bytes.toBytes("R1"), Bytes.toBytes("cf"), null,
517         now - 1000, KeyValue.Type.DeleteFamily), // expired
518         /*2*/ KeyValueTestUtil.create("R1", "cf", "a", now - 50,
519         KeyValue.Type.Put, "v3"), // live
520         /*3*/ KeyValueTestUtil.create("R1", "cf", "a", now - 55,
521         KeyValue.Type.Delete, "dontcare"), // live
522         /*4*/ KeyValueTestUtil.create("R1", "cf", "a", now - 55,
523         KeyValue.Type.Put, "deleted-version v2"), // deleted
524         /*5*/ KeyValueTestUtil.create("R1", "cf", "a", now - 60,
525         KeyValue.Type.Put, "v1"), // live
526         /*6*/ KeyValueTestUtil.create("R1", "cf", "a", now - 65,
527         KeyValue.Type.Put, "v0"), // max-version reached
528         /*7*/ KeyValueTestUtil.create("R1", "cf", "a",
529         now - 100, KeyValue.Type.DeleteColumn, "dont-care"), // max-version
530         /*8*/ KeyValueTestUtil.create("R1", "cf", "b", now - 600,
531         KeyValue.Type.DeleteColumn, "dont-care"), //expired
532         /*9*/ KeyValueTestUtil.create("R1", "cf", "b", now - 70,
533         KeyValue.Type.Put, "v2"), //live
534         /*10*/ KeyValueTestUtil.create("R1", "cf", "b", now - 750,
535         KeyValue.Type.Put, "v1"), //expired
536         /*11*/ KeyValueTestUtil.create("R1", "cf", "c", now - 500,
537         KeyValue.Type.Delete, "dontcare"), //expired
538         /*12*/ KeyValueTestUtil.create("R1", "cf", "c", now - 600,
539         KeyValue.Type.Put, "v1"), //expired
540         /*13*/ KeyValueTestUtil.create("R1", "cf", "c", now - 1000,
541         KeyValue.Type.Delete, "dontcare"), //expired
542         /*14*/ KeyValueTestUtil.create("R1", "cf", "d", now - 60,
543         KeyValue.Type.Put, "expired put"), //live
544         /*15*/ KeyValueTestUtil.create("R1", "cf", "d", now - 100,
545         KeyValue.Type.Delete, "not-expired delete"), //live
546       };
547       List<KeyValueScanner> scanners = scanFixture(kvs);
548       Scan scan = new Scan();
549       scan.setMaxVersions(2);
550       ScanInfo scanInfo = new ScanInfo(Bytes.toBytes("cf"),
551         0 /* minVersions */,
552         2 /* maxVersions */, 500 /* ttl */,
553         KeepDeletedCells.FALSE /* keepDeletedCells */,
554         200, /* timeToPurgeDeletes */
555         KeyValue.COMPARATOR);
556       StoreScanner scanner =
557         new StoreScanner(scan, scanInfo,
558           ScanType.COMPACT_DROP_DELETES, null, scanners,
559           HConstants.OLDEST_TIMESTAMP);
560       List<Cell> results = new ArrayList<Cell>();
561       results = new ArrayList<Cell>();
562       assertEquals(true, scanner.next(results));
563       assertEquals(kvs[0], results.get(0));
564       assertEquals(kvs[2], results.get(1));
565       assertEquals(kvs[3], results.get(2));
566       assertEquals(kvs[5], results.get(3));
567       assertEquals(kvs[9], results.get(4));
568       assertEquals(kvs[14], results.get(5));
569       assertEquals(kvs[15], results.get(6));
570       assertEquals(7, results.size());
571       scanner.close();
572     }finally{
573     EnvironmentEdgeManagerTestHelper.reset();
574     }
575   }
576 
577 }
578