HBASE-14497 Reverse Scan threw StackOverflow caused by readPt checking (Yerui Sun)
This commit is contained in:
parent
aeb3a62459
commit
5e2db42d68
|
@ -969,7 +969,10 @@ public class DefaultMemStore implements MemStore {
|
||||||
* specified key, then seek to the first KeyValue of previous row
|
* specified key, then seek to the first KeyValue of previous row
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean seekToPreviousRow(Cell key) {
|
public synchronized boolean seekToPreviousRow(Cell originalKey) {
|
||||||
|
boolean keepSeeking = false;
|
||||||
|
Cell key = originalKey;
|
||||||
|
do {
|
||||||
Cell firstKeyOnRow = KeyValueUtil.createFirstOnRow(key.getRowArray(), key.getRowOffset(),
|
Cell firstKeyOnRow = KeyValueUtil.createFirstOnRow(key.getRowArray(), key.getRowOffset(),
|
||||||
key.getRowLength());
|
key.getRowLength());
|
||||||
SortedSet<Cell> cellHead = cellSetAtCreation.headSet(firstKeyOnRow);
|
SortedSet<Cell> cellHead = cellSetAtCreation.headSet(firstKeyOnRow);
|
||||||
|
@ -990,8 +993,13 @@ public class DefaultMemStore implements MemStore {
|
||||||
this.stopSkippingCellsIfNextRow = false;
|
this.stopSkippingCellsIfNextRow = false;
|
||||||
if (peek() == null
|
if (peek() == null
|
||||||
|| comparator.compareRows(peek(), firstKeyOnPreviousRow) > 0) {
|
|| comparator.compareRows(peek(), firstKeyOnPreviousRow) > 0) {
|
||||||
return seekToPreviousRow(lastCellBeforeRow);
|
keepSeeking = true;
|
||||||
|
key = firstKeyOnPreviousRow;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
keepSeeking = false;
|
||||||
}
|
}
|
||||||
|
} while (keepSeeking);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -437,9 +437,12 @@ public class StoreFileScanner implements KeyValueScanner {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public boolean seekToPreviousRow(Cell key) throws IOException {
|
public boolean seekToPreviousRow(Cell originalKey) throws IOException {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
|
boolean keepSeeking = false;
|
||||||
|
Cell key = originalKey;
|
||||||
|
do {
|
||||||
KeyValue seekKey = KeyValueUtil.createFirstOnRow(key.getRowArray(), key.getRowOffset(),
|
KeyValue seekKey = KeyValueUtil.createFirstOnRow(key.getRowArray(), key.getRowOffset(),
|
||||||
key.getRowLength());
|
key.getRowLength());
|
||||||
if (seekCount != null) seekCount.incrementAndGet();
|
if (seekCount != null) seekCount.incrementAndGet();
|
||||||
|
@ -467,9 +470,13 @@ public class StoreFileScanner implements KeyValueScanner {
|
||||||
}
|
}
|
||||||
if (!resultOfSkipKVs
|
if (!resultOfSkipKVs
|
||||||
|| getComparator().compareRows(cur, firstKeyOfPreviousRow) > 0) {
|
|| getComparator().compareRows(cur, firstKeyOfPreviousRow) > 0) {
|
||||||
return seekToPreviousRow(firstKeyOfPreviousRow);
|
keepSeeking = true;
|
||||||
|
key = firstKeyOfPreviousRow;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
keepSeeking = false;
|
||||||
}
|
}
|
||||||
|
} while (keepSeeking);
|
||||||
return true;
|
return true;
|
||||||
} finally {
|
} finally {
|
||||||
realSeekDone = true;
|
realSeekDone = true;
|
||||||
|
@ -478,7 +485,7 @@ public class StoreFileScanner implements KeyValueScanner {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
throw new IOException("Could not seekToPreviousRow " + this + " to key "
|
throw new IOException("Could not seekToPreviousRow " + this + " to key "
|
||||||
+ key, ioe);
|
+ originalKey, ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5748,6 +5748,62 @@ public class TestHRegion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for HBASE-14497: Reverse Scan threw StackOverflow caused by readPt checking
|
||||||
|
*/
|
||||||
|
@Test (timeout = 60000)
|
||||||
|
public void testReverseScanner_StackOverflow() throws IOException {
|
||||||
|
byte[] cf1 = Bytes.toBytes("CF1");
|
||||||
|
byte[][] families = {cf1};
|
||||||
|
byte[] col = Bytes.toBytes("C");
|
||||||
|
String method = this.getName();
|
||||||
|
HBaseConfiguration conf = new HBaseConfiguration();
|
||||||
|
this.region = initHRegion(tableName, method, conf, families);
|
||||||
|
try {
|
||||||
|
// setup with one storefile and one memstore, to create scanner and get an earlier readPt
|
||||||
|
Put put = new Put(Bytes.toBytes("19998"));
|
||||||
|
put.add(cf1, col, Bytes.toBytes("val"));
|
||||||
|
region.put(put);
|
||||||
|
region.flushcache(true, true);
|
||||||
|
Put put2 = new Put(Bytes.toBytes("19997"));
|
||||||
|
put2.add(cf1, col, Bytes.toBytes("val"));
|
||||||
|
region.put(put2);
|
||||||
|
|
||||||
|
Scan scan = new Scan(Bytes.toBytes("19998"));
|
||||||
|
scan.setReversed(true);
|
||||||
|
InternalScanner scanner = region.getScanner(scan);
|
||||||
|
|
||||||
|
// create one storefile contains many rows will be skipped
|
||||||
|
// to check StoreFileScanner.seekToPreviousRow
|
||||||
|
for (int i = 10000; i < 20000; i++) {
|
||||||
|
Put p = new Put(Bytes.toBytes("" + i));
|
||||||
|
p.add(cf1, col, Bytes.toBytes("" + i));
|
||||||
|
region.put(p);
|
||||||
|
}
|
||||||
|
region.flushcache(true, true);
|
||||||
|
|
||||||
|
// create one memstore contains many rows will be skipped
|
||||||
|
// to check MemStoreScanner.seekToPreviousRow
|
||||||
|
for (int i = 10000; i < 20000; i++) {
|
||||||
|
Put p = new Put(Bytes.toBytes("" + i));
|
||||||
|
p.add(cf1, col, Bytes.toBytes("" + i));
|
||||||
|
region.put(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Cell> currRow = new ArrayList<>();
|
||||||
|
boolean hasNext;
|
||||||
|
do {
|
||||||
|
hasNext = scanner.next(currRow);
|
||||||
|
} while (hasNext);
|
||||||
|
assertEquals(2, currRow.size());
|
||||||
|
assertArrayEquals(Bytes.toBytes("19998"), currRow.get(0).getRow());
|
||||||
|
assertArrayEquals(Bytes.toBytes("19997"), currRow.get(1).getRow());
|
||||||
|
} finally {
|
||||||
|
HBaseTestingUtility.closeRegionAndWAL(this.region);
|
||||||
|
this.region = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test (timeout=60000)
|
@Test (timeout=60000)
|
||||||
public void testSplitRegionWithReverseScan() throws IOException {
|
public void testSplitRegionWithReverseScan() throws IOException {
|
||||||
byte [] tableName = Bytes.toBytes("testSplitRegionWithReverseScan");
|
byte [] tableName = Bytes.toBytes("testSplitRegionWithReverseScan");
|
||||||
|
|
Loading…
Reference in New Issue