Index: src/test/org/apache/hadoop/hbase/regionserver/TestStoreScanner.java =================================================================== --- src/test/org/apache/hadoop/hbase/regionserver/TestStoreScanner.java (revision 832905) +++ src/test/org/apache/hadoop/hbase/regionserver/TestStoreScanner.java (working copy) @@ -354,4 +354,46 @@ results.clear(); assertEquals(false, scan.next(results)); } + + /** + * Test expiration of KeyValues in combination with a configured TTL for + * a column family (as should be triggered in a major compaction). + */ + public void testWildCardTtlScan() throws IOException { + long now = System.currentTimeMillis(); + KeyValue [] kvs = new KeyValue[] { + KeyValueTestUtil.create("R1", "cf", "a", now-1000, KeyValue.Type.Put, "dont-care"), + KeyValueTestUtil.create("R1", "cf", "b", now-10, KeyValue.Type.Put, "dont-care"), + KeyValueTestUtil.create("R1", "cf", "c", now-200, KeyValue.Type.Put, "dont-care"), + KeyValueTestUtil.create("R1", "cf", "d", now-10000, KeyValue.Type.Put, "dont-care"), + KeyValueTestUtil.create("R2", "cf", "a", now, KeyValue.Type.Put, "dont-care"), + KeyValueTestUtil.create("R2", "cf", "b", now-10, KeyValue.Type.Put, "dont-care"), + KeyValueTestUtil.create("R2", "cf", "c", now-200, KeyValue.Type.Put, "dont-care"), + KeyValueTestUtil.create("R2", "cf", "c", now-1000, KeyValue.Type.Put, "dont-care") + }; + KeyValueScanner [] scanners = new KeyValueScanner[] { + new KeyValueScanFixture(KeyValue.COMPARATOR, kvs) + }; + Scan scan = new Scan(); + scan.setMaxVersions(1); + StoreScanner scanner = + new StoreScanner(scan, CF, 500, KeyValue.COMPARATOR, + null, scanners); + + List results = new ArrayList(); + assertEquals(true, scanner.next(results)); + assertEquals(2, results.size()); + assertEquals(kvs[1], results.get(0)); + assertEquals(kvs[2], results.get(1)); + results.clear(); + + assertEquals(true, scanner.next(results)); + assertEquals(3, results.size()); + assertEquals(kvs[4], results.get(0)); + assertEquals(kvs[5], results.get(1)); + assertEquals(kvs[6], results.get(2)); + results.clear(); + + assertEquals(false, scanner.next(results)); + } } Index: src/test/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java =================================================================== --- src/test/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java (revision 832905) +++ src/test/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java (working copy) @@ -27,6 +27,7 @@ import org.apache.hadoop.hbase.HBaseTestCase; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.KeyValueTestUtil; import org.apache.hadoop.hbase.KeyValue.KeyComparator; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.regionserver.QueryMatcher.MatchCode; @@ -163,4 +164,103 @@ } } + + /** + * Verify that {@link QueryMatcher} only skips expired KeyValue + * instances and does not exit early from the row (skipping + * later non-expired KeyValues). This version mimics a Get with + * explicitly specified column qualifiers. + * + * @throws IOException + */ + public void testMatch_ExpiredExplicit() + throws IOException { + + long testTTL = 1000; + MatchCode [] expected = new MatchCode[] { + MatchCode.SKIP, + MatchCode.INCLUDE, + MatchCode.SKIP, + MatchCode.INCLUDE, + MatchCode.SKIP, + MatchCode.NEXT + }; + + QueryMatcher qm = new QueryMatcher(get, fam2, + get.getFamilyMap().get(fam2), testTTL, rowComparator, 1); + + long now = System.currentTimeMillis(); + KeyValue [] kvs = new KeyValue[] { + new KeyValue(row1, fam2, col1, now-100, data), + new KeyValue(row1, fam2, col2, now-50, data), + new KeyValue(row1, fam2, col3, now-5000, data), + new KeyValue(row1, fam2, col4, now-500, data), + new KeyValue(row1, fam2, col5, now-10000, data), + new KeyValue(row2, fam1, col1, now-10, data) + }; + + List actual = new ArrayList(kvs.length); + for (KeyValue kv : kvs) { + actual.add( qm.match(kv) ); + } + + assertEquals(expected.length, actual.size()); + for (int i=0; i actual = new ArrayList(kvs.length); + for (KeyValue kv : kvs) { + actual.add( qm.match(kv) ); + } + + assertEquals(expected.length, actual.size()); + for (int i=0; i