HBASE-14355 Scan different TimeRange for each column family - fixing memstore bug
Signed-off-by: stack <stack@apache.org>
This commit is contained in:
parent
6531b465a7
commit
0d72849581
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue