diff options
Diffstat (limited to 'src/btree/bt_split.c')
-rw-r--r-- | src/btree/bt_split.c | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c index 2bae34b620b..9a3186a0015 100644 --- a/src/btree/bt_split.c +++ b/src/btree/bt_split.c @@ -812,9 +812,10 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new, WT_DECL_RET; WT_PAGE *parent; WT_PAGE_INDEX *alloc_index, *pindex; - WT_REF **alloc_refp, *parent_ref; + WT_REF **alloc_refp, *next_ref, *parent_ref; size_t size; - uint32_t children, i, j, parent_entries, result_entries; + uint32_t children, i, j; + uint32_t deleted_entries, parent_entries, result_entries; int complete, hazard, locked; parent = NULL; /* -Wconditional-uninitialized */ @@ -861,7 +862,22 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new, pindex = WT_INTL_INDEX_COPY(parent); parent_entries = pindex->entries; - result_entries = (parent_entries - 1) + new_entries; + + /* + * Remove any refs to deleted pages while we are splitting, we have + * the internal page locked down, and are copying the refs into a new + * array anyway. + */ + for (i = 0, deleted_entries = 0; i < parent_entries; ++i) + if (pindex->index[i]->state == WT_REF_DELETED) + deleted_entries++; + + /* + * The final entry count consists of: The original count, plus any + * new pages, less any refs we are removing because they only + * contained deleted items, less 1 for the page being replaced. + */ + result_entries = (parent_entries + new_entries) - (deleted_entries + 1); /* * Allocate and initialize a new page index array for the parent, then @@ -873,8 +889,9 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new, WT_MEMSIZE_ADD(parent_incr, size); alloc_index->index = (WT_REF **)(alloc_index + 1); alloc_index->entries = result_entries; - for (alloc_refp = alloc_index->index, i = 0; i < parent_entries; ++i) - if (pindex->index[i] == ref) + for (alloc_refp = alloc_index->index, i = 0; i < parent_entries; ++i) { + next_ref = pindex->index[i]; + if (next_ref == ref) for (j = 0; j < new_entries; ++j) { ref_new[j]->home = parent; *alloc_refp++ = ref_new[j]; @@ -886,8 +903,9 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new, */ ref_new[j] = NULL; } - else - *alloc_refp++ = pindex->index[i]; + else if (next_ref->state != WT_REF_DELETED) + *alloc_refp++ = next_ref; + } /* * Update the parent page's index: this update makes the split visible |