HBASE-2474 Bug in HBASE-2248 - mixed version reads (not allowed by spec)

git-svn-id: https://svn.apache.org/repos/asf/hadoop/hbase/trunk@944532 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Ryan Rawson 2010-05-15 00:20:53 +00:00
parent adbcfc3846
commit f65e61c7ab
4 changed files with 56 additions and 23 deletions

View File

@ -1921,7 +1921,7 @@ public class HRegion implements HConstants, HeapSize { // , Writable{
* It is used to combine scanners from multiple Stores (aka column families). * It is used to combine scanners from multiple Stores (aka column families).
*/ */
class RegionScanner implements InternalScanner { class RegionScanner implements InternalScanner {
private final KeyValueHeap storeHeap; private KeyValueHeap storeHeap = null;
private final byte [] stopRow; private final byte [] stopRow;
private Filter filter; private Filter filter;
private List<KeyValue> results = new ArrayList<KeyValue>(); private List<KeyValue> results = new ArrayList<KeyValue>();
@ -1929,11 +1929,11 @@ public class HRegion implements HConstants, HeapSize { // , Writable{
private int batch; private int batch;
// Doesn't need to be volatile, always accessed under a sync'ed method // Doesn't need to be volatile, always accessed under a sync'ed method
private boolean filterClosed = false; private boolean filterClosed = false;
private Scan theScan = null;
private List<KeyValueScanner> extraScanners = null;
RegionScanner(Scan scan, List<KeyValueScanner> additionalScanners) { RegionScanner(Scan scan, List<KeyValueScanner> additionalScanners) {
ReadWriteConsistencyControl.resetThreadReadPoint(rwcc); //DebugPrint.println("HRegionScanner.<init>");
//DebugPrint.println("HRegionScanner.<init>, threadpoint = " + ReadWriteConsistencyControl.getThreadReadPoint());
this.filter = scan.getFilter(); this.filter = scan.getFilter();
this.batch = scan.getBatch(); this.batch = scan.getBatch();
@ -1945,24 +1945,30 @@ public class HRegion implements HConstants, HeapSize { // , Writable{
// If we are doing a get, we want to be [startRow,endRow] normally // If we are doing a get, we want to be [startRow,endRow] normally
// it is [startRow,endRow) and if startRow=endRow we get nothing. // it is [startRow,endRow) and if startRow=endRow we get nothing.
this.isScan = scan.isGetScan() ? -1 : 0; this.isScan = scan.isGetScan() ? -1 : 0;
this.theScan = scan;
List<KeyValueScanner> scanners = new ArrayList<KeyValueScanner>(); this.extraScanners = additionalScanners;
if (additionalScanners != null) {
scanners.addAll(additionalScanners);
}
for (Map.Entry<byte[], NavigableSet<byte[]>> entry :
scan.getFamilyMap().entrySet()) {
Store store = stores.get(entry.getKey());
scanners.add(store.getScanner(scan, entry.getValue()));
}
this.storeHeap =
new KeyValueHeap(scanners.toArray(new KeyValueScanner[0]), comparator);
} }
RegionScanner(Scan scan) { RegionScanner(Scan scan) {
this(scan, null); this(scan, null);
} }
void initHeap() {
List<KeyValueScanner> scanners = new ArrayList<KeyValueScanner>();
if (extraScanners != null) {
scanners.addAll(extraScanners);
}
for (Map.Entry<byte[], NavigableSet<byte[]>> entry :
theScan.getFamilyMap().entrySet()) {
Store store = stores.get(entry.getKey());
scanners.add(store.getScanner(theScan, entry.getValue()));
}
this.storeHeap =
new KeyValueHeap(scanners.toArray(new KeyValueScanner[0]), comparator);
}
private void resetFilters() { private void resetFilters() {
if (filter != null) { if (filter != null) {
filter.reset(); filter.reset();
@ -1987,6 +1993,11 @@ public class HRegion implements HConstants, HeapSize { // , Writable{
// This could be a new thread from the last time we called next(). // This could be a new thread from the last time we called next().
ReadWriteConsistencyControl.resetThreadReadPoint(rwcc); ReadWriteConsistencyControl.resetThreadReadPoint(rwcc);
// lazy init the store heap.
if (storeHeap == null) {
initHeap();
}
results.clear(); results.clear();
boolean returnResult = nextInternal(limit); boolean returnResult = nextInternal(limit);
if (!returnResult && filter != null && filter.filterRow()) { if (!returnResult && filter != null && filter.filterRow()) {

View File

@ -672,4 +672,14 @@ public abstract class HBaseTestCase extends TestCase {
Bytes.toString(actual) + ">"); Bytes.toString(actual) + ">");
} }
} }
public static void assertEquals(byte[] expected,
byte[] actual) {
if (Bytes.compareTo(expected, actual) != 0) {
throw new AssertionFailedError("expected:<" +
Bytes.toStringBinary(expected) + "> but was:<" +
Bytes.toStringBinary(actual) + ">");
}
}
} }

View File

@ -1025,19 +1025,21 @@ public class TestHRegion extends HBaseTestCase {
region.put(put); region.put(put);
Scan scan = null; Scan scan = null;
InternalScanner is = null; HRegion.RegionScanner is = null;
//Testing to see how many scanners that is produced by getScanner, starting //Testing to see how many scanners that is produced by getScanner, starting
//with known number, 2 - current = 1 //with known number, 2 - current = 1
scan = new Scan(); scan = new Scan();
scan.addFamily(fam2); scan.addFamily(fam2);
scan.addFamily(fam4); scan.addFamily(fam4);
is = region.getScanner(scan); is = (RegionScanner) region.getScanner(scan);
is.initHeap(); // i dont like this test
assertEquals(1, ((RegionScanner)is).getStoreHeap().getHeap().size()); assertEquals(1, ((RegionScanner)is).getStoreHeap().getHeap().size());
scan = new Scan(); scan = new Scan();
is = region.getScanner(scan); is = (RegionScanner) region.getScanner(scan);
assertEquals(families.length -1, is.initHeap();
assertEquals(families.length -1,
((RegionScanner)is).getStoreHeap().getHeap().size()); ((RegionScanner)is).getStoreHeap().getHeap().size());
} }
@ -2185,6 +2187,15 @@ public class TestHRegion extends HBaseTestCase {
} }
Assert.assertTrue(timestamp >= prevTimestamp); Assert.assertTrue(timestamp >= prevTimestamp);
prevTimestamp = timestamp; prevTimestamp = timestamp;
byte [] gotValue = null;
for (KeyValue kv : result.raw()) {
byte [] thisValue = kv.getValue();
if (gotValue != null) {
assertEquals(gotValue, thisValue);
}
gotValue = thisValue;
}
} }
} }

View File

@ -298,6 +298,7 @@ public class TestMemStore extends TestCase {
rwcc.completeMemstoreInsert(w); rwcc.completeMemstoreInsert(w);
// Assert that we can read back // Assert that we can read back
ReadWriteConsistencyControl.resetThreadReadPoint(rwcc);
KeyValueScanner s = this.memstore.getScanners()[0]; KeyValueScanner s = this.memstore.getScanners()[0];
s.seek(kv); s.seek(kv);
@ -310,7 +311,7 @@ public class TestMemStore extends TestCase {
} }
} }
public void no_testReadOwnWritesUnderConcurrency() throws Throwable { public void testReadOwnWritesUnderConcurrency() throws Throwable {
int NUM_THREADS = 8; int NUM_THREADS = 8;