HBASE-2740 NPE in ReadWriteConsistencyControl
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@955784 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7aedf3a36f
commit
0beea3751b
|
@ -394,6 +394,7 @@ Release 0.21.0 - Unreleased
|
|||
HBASE-2738 TestTimeRangeMapRed updated now that we keep multiple cells with
|
||||
same timestamp in MemStore
|
||||
HBASE-2725 Shutdown hook management is gone in trunk; restore
|
||||
HBASE-2740 NPE in ReadWriteConsistencyControl
|
||||
|
||||
IMPROVEMENTS
|
||||
HBASE-1760 Cleanup TODOs in HTable
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.util.List;
|
|||
import java.util.NavigableSet;
|
||||
|
||||
/**
|
||||
* Scanner scans both the memstore and the HStore. Coaleace KeyValue stream
|
||||
* Scanner scans both the memstore and the HStore. Coalesce KeyValue stream
|
||||
* into List<KeyValue> for a single row.
|
||||
*/
|
||||
class StoreScanner implements KeyValueScanner, InternalScanner, ChangedReadersObserver {
|
||||
|
@ -194,6 +194,8 @@ class StoreScanner implements KeyValueScanner, InternalScanner, ChangedReadersOb
|
|||
this.store.deleteChangedReaderObserver(this);
|
||||
if (this.heap != null)
|
||||
this.heap.close();
|
||||
this.heap = null; // CLOSED!
|
||||
this.lastTop = null; // If both are null, we are closed.
|
||||
}
|
||||
|
||||
public synchronized boolean seek(KeyValue key) throws IOException {
|
||||
|
@ -298,6 +300,13 @@ class StoreScanner implements KeyValueScanner, InternalScanner, ChangedReadersOb
|
|||
public synchronized void updateReaders() throws IOException {
|
||||
if (this.closing) return;
|
||||
|
||||
// All public synchronized API calls will call 'checkReseek' which will cause
|
||||
// the scanner stack to reseek if this.heap==null && this.lastTop != null.
|
||||
// But if two calls to updateReaders() happen without a 'next' or 'peek' then we
|
||||
// will end up calling this.peek() which would cause a reseek in the middle of a updateReaders
|
||||
// which is NOT what we want, not to mention could cause an NPE. So we early out here.
|
||||
if (this.heap == null) return;
|
||||
|
||||
// this could be null.
|
||||
this.lastTop = this.peek();
|
||||
|
||||
|
|
|
@ -109,7 +109,6 @@ public class TestStoreScanner extends TestCase {
|
|||
results = new ArrayList<KeyValue>();
|
||||
assertEquals(true, scan.next(results));
|
||||
assertEquals(3, results.size());
|
||||
|
||||
}
|
||||
|
||||
public void testScanSameTimestamp() throws IOException {
|
||||
|
@ -285,6 +284,7 @@ public class TestStoreScanner extends TestCase {
|
|||
assertEquals(kvs[0], results.get(0));
|
||||
assertEquals(kvs[1], results.get(1));
|
||||
}
|
||||
|
||||
public void testWildCardScannerUnderDeletes() throws IOException {
|
||||
KeyValue [] kvs = new KeyValue [] {
|
||||
KeyValueTestUtil.create("R1", "cf", "a", 2, KeyValue.Type.Put, "dont-care"), // inc
|
||||
|
@ -317,6 +317,7 @@ public class TestStoreScanner extends TestCase {
|
|||
assertEquals(kvs[6], results.get(3));
|
||||
assertEquals(kvs[7], results.get(4));
|
||||
}
|
||||
|
||||
public void testDeleteFamily() throws IOException {
|
||||
KeyValue [] kvs = new KeyValue[] {
|
||||
KeyValueTestUtil.create("R1", "cf", "a", 100, KeyValue.Type.DeleteFamily, "dont-care"),
|
||||
|
@ -363,8 +364,7 @@ public class TestStoreScanner extends TestCase {
|
|||
assertEquals(kvs[3], results.get(0));
|
||||
}
|
||||
|
||||
public void testSkipColumn() throws IOException {
|
||||
KeyValue [] kvs = new KeyValue[] {
|
||||
private static final KeyValue [] kvs = new KeyValue[] {
|
||||
KeyValueTestUtil.create("R1", "cf", "a", 11, KeyValue.Type.Put, "dont-care"),
|
||||
KeyValueTestUtil.create("R1", "cf", "b", 11, KeyValue.Type.Put, "dont-care"),
|
||||
KeyValueTestUtil.create("R1", "cf", "c", 11, KeyValue.Type.Put, "dont-care"),
|
||||
|
@ -376,7 +376,11 @@ public class TestStoreScanner extends TestCase {
|
|||
KeyValueTestUtil.create("R1", "cf", "i", 11, KeyValue.Type.Put, "dont-care"),
|
||||
KeyValueTestUtil.create("R2", "cf", "a", 11, KeyValue.Type.Put, "dont-care"),
|
||||
};
|
||||
List<KeyValueScanner> scanners = scanFixture(kvs);
|
||||
|
||||
public void testSkipColumn() throws IOException {
|
||||
KeyValueScanner [] scanners = new KeyValueScanner[] {
|
||||
new KeyValueScanFixture(KeyValue.COMPARATOR, kvs)
|
||||
};
|
||||
StoreScanner scan =
|
||||
new StoreScanner(new Scan(), CF, Long.MAX_VALUE, KeyValue.COMPARATOR,
|
||||
getCols("a", "d"), scanners);
|
||||
|
@ -395,9 +399,9 @@ public class TestStoreScanner extends TestCase {
|
|||
results.clear();
|
||||
assertEquals(false, scan.next(results));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test expiration of KeyValues in combination with a configured TTL for
|
||||
* 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 {
|
||||
|
@ -435,6 +439,24 @@ public class TestStoreScanner extends TestCase {
|
|||
|
||||
assertEquals(false, scanner.next(results));
|
||||
}
|
||||
|
||||
public void testScannerReseekDoesntNPE() throws Exception {
|
||||
KeyValueScanner [] scanners = new KeyValueScanner[] {
|
||||
new KeyValueScanFixture(KeyValue.COMPARATOR, kvs)
|
||||
};
|
||||
StoreScanner scan =
|
||||
new StoreScanner(new Scan(), CF, Long.MAX_VALUE, KeyValue.COMPARATOR,
|
||||
getCols("a", "d"), scanners);
|
||||
|
||||
|
||||
// Previously a updateReaders twice in a row would cause an NPE. In test this would also
|
||||
// normally cause an NPE because scan.store is null. So as long as we get through these
|
||||
// two calls we are good and the bug was quashed.
|
||||
|
||||
scan.updateReaders();
|
||||
|
||||
scan.updateReaders();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue