summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2015-11-17 07:50:39 -0500
committerKeith Bostic <keith@wiredtiger.com>2015-11-17 07:50:39 -0500
commit846125e815935fec7d574b857d603835bd680629 (patch)
treea964b9df23db85b497b4d7eaaff8149cf4c5af44
parent07a0a7197f4adcd0cbfca64e3a18b480e7aafe7b (diff)
downloadmongo-846125e815935fec7d574b857d603835bd680629.tar.gz
WT-2182: don't leave child refs locked; when we hit the result_entries
== 0 case in __split_parent, we will give up on the split but return 0. The cleanup path in __split_parent used to flip the child ref to WT_REF_DELETED but this branch has removed that code, and I don't think the code here can know whether the ref was unlocked. Change __split_parent to return EBUSY, but without the verbose error messages, in this case.
-rw-r--r--src/btree/bt_split.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c
index fb4b5e3a1ef..eaeac683f9a 100644
--- a/src/btree/bt_split.c
+++ b/src/btree/bt_split.c
@@ -702,14 +702,14 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
uint64_t split_gen;
uint32_t i, j;
uint32_t deleted_entries, parent_entries, result_entries;
- bool complete;
+ bool complete, empty_parent;
parent = ref->home;
alloc_index = pindex = NULL;
parent_decr = 0;
parent_entries = 0;
- complete = false;
+ complete = empty_parent = false;
/* The parent page will be marked dirty, make sure that will succeed. */
WT_RET(__wt_page_modify_init(session, parent));
@@ -745,11 +745,12 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
result_entries = (parent_entries + new_entries) - (deleted_entries + 1);
/*
- * If the entire (sub)tree is empty, give up: we can't leave an empty
- * internal page. Mark it to be evicted soon and clean up any
- * references that have changed state.
+ * If there are no remaining entries on the parent, give up, we can't
+ * leave an empty internal page. Mark it to be evicted soon and clean
+ * up any references that have changed state.
*/
if (result_entries == 0) {
+ empty_parent = true;
__wt_page_evict_soon(parent);
goto err;
}
@@ -918,6 +919,14 @@ err: /*
}
__wt_free_ref_index(session, NULL, alloc_index, false);
+
+ /*
+ * The split couldn't proceed because the parent would be empty,
+ * return EBUSY so our caller knows to unlock the WT_REF that's
+ * being deleted, but don't be noisy, there's nothing wrong.
+ */
+ if (empty_parent)
+ return (EBUSY);
}
if (ret != 0 && ret != WT_PANIC)