HBASE-14355 Scan different TimeRange for each column family - fixing memstore bug

Signed-off-by: stack <stack@apache.org>
This commit is contained in:
rahulgidwani 2015-11-25 14:43:12 -08:00 committed by stack
parent 6531b465a7
commit 0d72849581
3 changed files with 39 additions and 20 deletions

View File

@ -40,6 +40,7 @@ import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.KeyValueUtil;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.TimeRange;
import org.apache.hadoop.hbase.util.ByteRange;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.ClassSize;
@ -550,12 +551,19 @@ public class DefaultMemStore implements MemStore {
/**
* Check if this memstore may contain the required keys
* @param scan
* @param scan scan
* @param store holds reference to cf
* @param oldestUnexpiredTS
* @return False if the key definitely does not exist in this Memstore
*/
public boolean shouldSeek(Scan scan, long oldestUnexpiredTS) {
return (timeRangeTracker.includesTimeRange(scan.getTimeRange()) ||
snapshotTimeRangeTracker.includesTimeRange(scan.getTimeRange()))
public boolean shouldSeek(Scan scan, Store store, long oldestUnexpiredTS) {
byte[] cf = store.getFamily().getName();
TimeRange timeRange = scan.getColumnFamilyTimeRange().get(cf);
if (timeRange == null) {
timeRange = scan.getTimeRange();
}
return (timeRangeTracker.includesTimeRange(timeRange) ||
snapshotTimeRangeTracker.includesTimeRange(timeRange))
&& (Math.max(timeRangeTracker.getMaximumTimestamp(),
snapshotTimeRangeTracker.getMaximumTimestamp()) >=
oldestUnexpiredTS);
@ -828,7 +836,7 @@ public class DefaultMemStore implements MemStore {
@Override
public boolean shouldUseScanner(Scan scan, Store store, long oldestUnexpiredTS) {
return shouldSeek(scan, oldestUnexpiredTS);
return shouldSeek(scan, store, oldestUnexpiredTS);
}
/**

View File

@ -160,7 +160,12 @@ public class ScanQueryMatcher {
public ScanQueryMatcher(Scan scan, ScanInfo scanInfo, NavigableSet<byte[]> columns,
ScanType scanType, long readPointToUse, long earliestPutTs, long oldestUnexpiredTS,
long now, RegionCoprocessorHost regionCoprocessorHost) throws IOException {
this.tr = scan.getTimeRange();
TimeRange timeRange = scan.getColumnFamilyTimeRange().get(scanInfo.getFamily());
if (timeRange == null) {
this.tr = scan.getTimeRange();
} else {
this.tr = timeRange;
}
this.rowComparator = scanInfo.getComparator();
this.regionCoprocessorHost = regionCoprocessorHost;
this.deletes = instantiateDeleteTracker();
@ -275,7 +280,7 @@ public class ScanQueryMatcher {
* caused by a data corruption.
*/
public MatchCode match(Cell cell) throws IOException {
if (filter != null && filter.filterAllRemaining()) {
if (filter != null && filter.filterAllRemaining()) {
return MatchCode.DONE_SCAN;
}
int ret = this.rowComparator.compareRows(curCell, cell);

View File

@ -61,6 +61,9 @@ import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/** memstore test case */
@Category({RegionServerTests.class, MediumTests.class})
public class TestDefaultMemStore extends TestCase {
@ -745,29 +748,32 @@ public class TestDefaultMemStore extends TestCase {
/**
* Test to ensure correctness when using Memstore with multiple timestamps
*/
public void testMultipleTimestamps() throws IOException {
public void testMultipleTimestamps() throws Exception {
long[] timestamps = new long[] {20,10,5,1};
Scan scan = new Scan();
for (long timestamp: timestamps)
addRows(memstore,timestamp);
scan.setTimeRange(0, 2);
assertTrue(memstore.shouldSeek(scan, Long.MIN_VALUE));
byte[] fam = Bytes.toBytes("fam");
HColumnDescriptor hcd = mock(HColumnDescriptor.class);
when(hcd.getName()).thenReturn(fam);
Store store = mock(Store.class);
when(store.getFamily()).thenReturn(hcd);
scan.setColumnFamilyTimeRange(fam, 0, 2);
assertTrue(memstore.shouldSeek(scan, store, Long.MIN_VALUE));
scan.setTimeRange(20, 82);
assertTrue(memstore.shouldSeek(scan, Long.MIN_VALUE));
scan.setColumnFamilyTimeRange(fam, 20, 82);
assertTrue(memstore.shouldSeek(scan, store, Long.MIN_VALUE));
scan.setTimeRange(10, 20);
assertTrue(memstore.shouldSeek(scan, Long.MIN_VALUE));
scan.setColumnFamilyTimeRange(fam, 10, 20);
assertTrue(memstore.shouldSeek(scan, store, Long.MIN_VALUE));
scan.setTimeRange(8, 12);
assertTrue(memstore.shouldSeek(scan, Long.MIN_VALUE));
scan.setColumnFamilyTimeRange(fam, 8, 12);
assertTrue(memstore.shouldSeek(scan, store, Long.MIN_VALUE));
/*This test is not required for correctness but it should pass when
* timestamp range optimization is on*/
//scan.setTimeRange(28, 42);
//assertTrue(!memstore.shouldSeek(scan));
scan.setColumnFamilyTimeRange(fam, 28, 42);
assertTrue(!memstore.shouldSeek(scan, store, Long.MIN_VALUE));
}
////////////////////////////////////