Fixed concurrency bug found by Sattam related to an unprotected read of the BTree node level.
git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_indexes@446 123451ca-8445-de46-9d55-352943316053
diff --git a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
index fa3024d..38316d3 100644
--- a/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
+++ b/hyracks-storage-am-btree/src/main/java/edu/uci/ics/hyracks/storage/am/btree/impls/BTree.java
@@ -402,6 +402,7 @@
ctx.leafFrame.setPage(node);
ctx.leafFrame.setPageTupleFieldCount(cmp.getFieldCount());
FrameOpSpaceStatus spaceStatus = ctx.leafFrame.hasSpaceInsert(tuple, cmp);
+
switch (spaceStatus) {
case SUFFICIENT_CONTIGUOUS_SPACE: {
@@ -833,12 +834,16 @@
private void performOp(int pageId, ICachedPage parent, BTreeOpContext ctx) throws Exception {
ICachedPage node = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, pageId), false);
pins++;
-
+
ctx.interiorFrame.setPage(node);
- boolean isLeaf = ctx.interiorFrame.isLeaf();
- acquireLatch(node, ctx.op, isLeaf);
+ // this check performs an unprotected read in the page
+ // the following could happen: TODO fill out
+ boolean unsafeIsLeaf = ctx.interiorFrame.isLeaf();
+ acquireLatch(node, ctx.op, unsafeIsLeaf);
boolean smFlag = ctx.interiorFrame.getSmFlag();
-
+ // re-check leafness after latching
+ boolean isLeaf = ctx.interiorFrame.isLeaf();
+
// remember trail of pageLsns, to unwind recursion in case of an ongoing
// structure modification
ctx.pageLsns.add(ctx.interiorFrame.getPageLsn());
@@ -944,7 +949,7 @@
ctx.opRestarts++;
System.out.println("ONGOING SM ON PAGE " + pageId + " AT LEVEL " + ctx.interiorFrame.getLevel()
+ ", RESTARTS: " + ctx.opRestarts);
- releaseLatch(node, ctx.op, isLeaf);
+ releaseLatch(node, ctx.op, unsafeIsLeaf);
bufferCache.unpin(node);
unpins++;
@@ -986,7 +991,7 @@
// System.out.println(e.getMessage());
// e.printStackTrace();
if (!e.getHandled()) {
- releaseLatch(node, ctx.op, isLeaf);
+ releaseLatch(node, ctx.op, unsafeIsLeaf);
bufferCache.unpin(node);
unpins++;
e.setHandled(true);
@@ -996,7 +1001,7 @@
// failure to pin a new node during a split
System.out.println("ASTERIX EXCEPTION");
e.printStackTrace();
- releaseLatch(node, ctx.op, isLeaf);
+ releaseLatch(node, ctx.op, unsafeIsLeaf);
bufferCache.unpin(node);
unpins++;
BTreeException propException = new BTreeException(e);