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