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:
Ryan Rawson 2010-06-17 23:20:40 +00:00
parent 7aedf3a36f
commit 0beea3751b
3 changed files with 39 additions and 7 deletions

View File

@ -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

View File

@ -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();

View File

@ -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();
}
/**