diff options
author | Keith Bostic <keith@wiredtiger.com> | 2015-11-17 07:50:39 -0500 |
---|---|---|
committer | Keith Bostic <keith@wiredtiger.com> | 2015-11-17 07:50:39 -0500 |
commit | 846125e815935fec7d574b857d603835bd680629 (patch) | |
tree | a964b9df23db85b497b4d7eaaff8149cf4c5af44 | |
parent | 07a0a7197f4adcd0cbfca64e3a18b480e7aafe7b (diff) | |
download | mongo-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.c | 19 |
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) |