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.KeyValueUtil;
import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.client.Scan; 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.ByteRange;
import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.ClassSize; 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 * 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 * @return False if the key definitely does not exist in this Memstore
*/ */
public boolean shouldSeek(Scan scan, long oldestUnexpiredTS) { public boolean shouldSeek(Scan scan, Store store, long oldestUnexpiredTS) {
return (timeRangeTracker.includesTimeRange(scan.getTimeRange()) || byte[] cf = store.getFamily().getName();
snapshotTimeRangeTracker.includesTimeRange(scan.getTimeRange())) TimeRange timeRange = scan.getColumnFamilyTimeRange().get(cf);
if (timeRange == null) {
timeRange = scan.getTimeRange();
}
return (timeRangeTracker.includesTimeRange(timeRange) ||
snapshotTimeRangeTracker.includesTimeRange(timeRange))
&& (Math.max(timeRangeTracker.getMaximumTimestamp(), && (Math.max(timeRangeTracker.getMaximumTimestamp(),
snapshotTimeRangeTracker.getMaximumTimestamp()) >= snapshotTimeRangeTracker.getMaximumTimestamp()) >=
oldestUnexpiredTS); oldestUnexpiredTS);
@ -828,7 +836,7 @@ public class DefaultMemStore implements MemStore {
@Override @Override
public boolean shouldUseScanner(Scan scan, Store store, long oldestUnexpiredTS) { 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, public ScanQueryMatcher(Scan scan, ScanInfo scanInfo, NavigableSet<byte[]> columns,
ScanType scanType, long readPointToUse, long earliestPutTs, long oldestUnexpiredTS, ScanType scanType, long readPointToUse, long earliestPutTs, long oldestUnexpiredTS,
long now, RegionCoprocessorHost regionCoprocessorHost) throws IOException { 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.rowComparator = scanInfo.getComparator();
this.regionCoprocessorHost = regionCoprocessorHost; this.regionCoprocessorHost = regionCoprocessorHost;
this.deletes = instantiateDeleteTracker(); this.deletes = instantiateDeleteTracker();
@ -275,7 +280,7 @@ public class ScanQueryMatcher {
* caused by a data corruption. * caused by a data corruption.
*/ */
public MatchCode match(Cell cell) throws IOException { public MatchCode match(Cell cell) throws IOException {
if (filter != null && filter.filterAllRemaining()) { if (filter != null && filter.filterAllRemaining()) {
return MatchCode.DONE_SCAN; return MatchCode.DONE_SCAN;
} }
int ret = this.rowComparator.compareRows(curCell, cell); 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.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/** memstore test case */ /** memstore test case */
@Category({RegionServerTests.class, MediumTests.class}) @Category({RegionServerTests.class, MediumTests.class})
public class TestDefaultMemStore extends TestCase { public class TestDefaultMemStore extends TestCase {
@ -745,29 +748,32 @@ public class TestDefaultMemStore extends TestCase {
/** /**
* Test to ensure correctness when using Memstore with multiple timestamps * 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}; long[] timestamps = new long[] {20,10,5,1};
Scan scan = new Scan(); Scan scan = new Scan();
for (long timestamp: timestamps) for (long timestamp: timestamps)
addRows(memstore,timestamp); addRows(memstore,timestamp);
scan.setTimeRange(0, 2); byte[] fam = Bytes.toBytes("fam");
assertTrue(memstore.shouldSeek(scan, Long.MIN_VALUE)); 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); scan.setColumnFamilyTimeRange(fam, 20, 82);
assertTrue(memstore.shouldSeek(scan, Long.MIN_VALUE)); assertTrue(memstore.shouldSeek(scan, store, Long.MIN_VALUE));
scan.setTimeRange(10, 20); scan.setColumnFamilyTimeRange(fam, 10, 20);
assertTrue(memstore.shouldSeek(scan, Long.MIN_VALUE)); assertTrue(memstore.shouldSeek(scan, store, Long.MIN_VALUE));
scan.setTimeRange(8, 12); scan.setColumnFamilyTimeRange(fam, 8, 12);
assertTrue(memstore.shouldSeek(scan, Long.MIN_VALUE)); assertTrue(memstore.shouldSeek(scan, store, Long.MIN_VALUE));
/*This test is not required for correctness but it should pass when scan.setColumnFamilyTimeRange(fam, 28, 42);
* timestamp range optimization is on*/ assertTrue(!memstore.shouldSeek(scan, store, Long.MIN_VALUE));
//scan.setTimeRange(28, 42);
//assertTrue(!memstore.shouldSeek(scan));
} }
//////////////////////////////////// ////////////////////////////////////