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