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