Fixed a BTree concurrency bug where a restarting operation sometimes did not re-pin and re-latch it's page which was released during latch coupling downwards.
git-svn-id: https://hyracks.googlecode.com/svn/branches/hyracks_lsm_tree@1115 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 7d5e87f..07a52be 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
@@ -309,6 +309,10 @@
}
private boolean performLeafSplit(int pageId, ITupleReference tuple, BTreeOpContext ctx) throws Exception {
+ // We must never hold a latch on a page while waiting to obtain the tree
+ // latch, because it this could lead to a latch-deadlock.
+ // If we can't get the tree latch, we return, release our page latches,
+ // and restart the operation from one level above.
// Lock is released in unsetSmPages(), after sm has fully completed.
if (!treeLatch.writeLock().tryLock()) {
return true;
@@ -529,11 +533,13 @@
if (!ctx.pageLsns.isEmpty() && ctx.pageLsns.getLast() == RESTART_OP) {
// Pop the restart op indicator.
- ctx.pageLsns.removeLast();
+ ctx.pageLsns.removeLast();
if (isConsistent(pageId, ctx)) {
- // Don't unpin and unlatch node again in recursive call.
- node = null;
- // Descend the tree again.
+ // Pin and latch page again, since it was unpinned and unlatched in call to performOp (passed as parent).
+ node = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, pageId), false);
+ node.acquireReadLatch();
+ ctx.interiorFrame.setPage(node);
+ // Descend the tree again.
continue;
} else {
// Pop pageLsn of this page (version seen by this op during descent).
diff --git a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeMultiThreadTest.java b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeMultiThreadTest.java
index 15d4d73..c7e13f7 100644
--- a/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeMultiThreadTest.java
+++ b/hyracks-tests/hyracks-storage-am-btree-test/src/test/java/edu/uci/ics/hyracks/storage/am/btree/multithread/BTreeMultiThreadTest.java
@@ -37,6 +37,7 @@
public class BTreeMultiThreadTest {
private final int PAGE_SIZE = 8192;
+ //private final int PAGE_SIZE = 64;
private final int NUM_PAGES = 1000;
private final int MAX_OPEN_FILES = 10;
private final int HYRACKS_FRAME_SIZE = 32768;
@@ -71,8 +72,7 @@
TreeIndexMultiThreadTestDriver driver = new TreeIndexMultiThreadTestDriver(btree, workerFactory, fieldSerdes, ops, opProbs);
- //driver.run(10, 1, 10000000, 1000);
- driver.run(6, 1, 10000000, 1000);
+ driver.run(10, 1, 10000000, 1000);
btree.close();
}