summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/btree/bt_split.c51
1 files changed, 22 insertions, 29 deletions
diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c
index 94c73106d70..519452b8253 100644
--- a/src/btree/bt_split.c
+++ b/src/btree/bt_split.c
@@ -257,13 +257,12 @@ __split_ovfl_key_cleanup(WT_SESSION_IMPL *session, WT_PAGE *page, WT_REF *ref)
}
/*
- * __split_ref_deepen_move --
- * Move a WT_REF from a parent to a child in service of a split to deepen
- * the tree, including updating the accounting information.
+ * __split_ref_instantiate --
+ * Instantiate key/address pairs in memory in service of a split.
*/
static int
-__split_ref_deepen_move(WT_SESSION_IMPL *session,
- WT_PAGE *parent, WT_REF *ref, size_t *parent_decrp, size_t *child_incrp)
+__split_ref_instantiate(WT_SESSION_IMPL *session,
+ WT_PAGE *page, WT_REF *ref, size_t *parent_decrp, size_t *child_incrp)
{
WT_ADDR *addr;
WT_CELL_UNPACK unpack;
@@ -280,6 +279,8 @@ __split_ref_deepen_move(WT_SESSION_IMPL *session,
* of child pages, and so we can no longer reference the block image
* that remains with the page being split.
*
+ * Track how much memory the parent is losing and the child gaining.
+ *
* No locking is required to update the WT_REF structure because we're
* the only thread splitting the parent page, and there's no way for
* readers to race with our updates of single pointers. The changes
@@ -288,13 +289,13 @@ __split_ref_deepen_move(WT_SESSION_IMPL *session,
*
* Row-store keys, first.
*/
- if (parent->type == WT_PAGE_ROW_INT) {
+ if (page->type == WT_PAGE_ROW_INT) {
if ((ikey = __wt_ref_key_instantiated(ref)) == NULL) {
- __wt_ref_key(parent, ref, &key, &size);
+ __wt_ref_key(page, ref, &key, &size);
WT_RET(__wt_row_ikey(session, 0, key, size, &ikey));
ref->key.ikey = ikey;
} else {
- WT_RET(__split_ovfl_key_cleanup(session, parent, ref));
+ WT_RET(__split_ovfl_key_cleanup(session, page, ref));
WT_MEMSIZE_ADD(*parent_decrp,
sizeof(WT_IKEY) + ikey->size);
}
@@ -306,8 +307,12 @@ __split_ref_deepen_move(WT_SESSION_IMPL *session,
* address has been instantiated, there's no work to do. Otherwise,
* get the address from the on-page cell.
*/
- addr = ref->addr;
- if (addr != NULL && !__wt_off_page(parent, addr)) {
+ if ((addr = ref->addr) == NULL)
+ return (0);
+ if (__wt_off_page(page, addr))
+ WT_MEMSIZE_TRANSFER(*parent_decrp, *child_incrp,
+ sizeof(WT_ADDR) + addr->size);
+ else {
__wt_cell_unpack((WT_CELL *)ref->addr, &unpack);
WT_RET(__wt_calloc_one(session, &addr));
if ((ret = __wt_strndup(
@@ -319,11 +324,8 @@ __split_ref_deepen_move(WT_SESSION_IMPL *session,
addr->type =
unpack.raw == WT_CELL_ADDR_INT ? WT_ADDR_INT : WT_ADDR_LEAF;
ref->addr = addr;
+ WT_MEMSIZE_ADD(*child_incrp, sizeof(WT_ADDR) + addr->size);
}
-
- /* And finally, the WT_REF itself. */
- WT_MEMSIZE_TRANSFER(*parent_decrp, *child_incrp, sizeof(WT_REF));
-
return (0);
}
@@ -500,9 +502,12 @@ __split_deepen(WT_SESSION_IMPL *session, WT_PAGE *parent, uint32_t children)
child_incr = 0;
child_pindex = WT_INTL_INDEX_COPY(child);
for (child_refp = child_pindex->index, j = 0; j < slots; ++j) {
- WT_ERR(__split_ref_deepen_move(session,
+ WT_ERR(__split_ref_instantiate(session,
parent, *parent_refp, &parent_decr, &child_incr));
*child_refp++ = *parent_refp++;
+
+ WT_MEMSIZE_TRANSFER(
+ parent_decr, child_incr, sizeof(WT_REF));
}
__wt_cache_page_inmem_incr(session, child, child_incr);
}
@@ -598,7 +603,6 @@ __split_deepen(WT_SESSION_IMPL *session, WT_PAGE *parent, uint32_t children)
WT_ERR(__split_safe_free(session, 0, pindex, size));
WT_MEMSIZE_ADD(parent_decr, size);
-#if 0
/*
* Adjust the parent's memory footprint. This may look odd, but we
* have already taken the allocation overhead into account, and an
@@ -607,19 +611,6 @@ __split_deepen(WT_SESSION_IMPL *session, WT_PAGE *parent, uint32_t children)
*/
__wt_cache_page_inmem_incr(session, parent, parent_incr);
__wt_cache_page_inmem_decr(session, parent, parent_decr);
-#else
- /*
- * XXX
- * The code to track page sizes is fundamentally flawed in the face of
- * splits: for example, we don't add in an overhead allocation constant
- * when allocating WT_REF structures as pages are created, but the
- * calculations during split assume that correction. For now, ignore
- * our carefully calculated values and force the internal page size to
- * 5% of its current value.
- */
- size = parent->memory_footprint - (parent->memory_footprint / 20);
- __wt_cache_page_inmem_decr(session, parent, size);
-#endif
if (0) {
err: __wt_free_ref_index(session, parent, alloc_index, 1);
@@ -783,11 +774,13 @@ __wt_multi_to_ref(WT_SESSION_IMPL *session,
* the confusion.
*/
WT_RET(__wt_calloc_one(session, &addr));
+ WT_MEMSIZE_ADD(incr, sizeof(WT_ADDR));
ref->addr = addr;
addr->size = multi->addr.size;
addr->type = multi->addr.type;
WT_RET(__wt_strndup(session,
multi->addr.addr, addr->size, &addr->addr));
+ WT_MEMSIZE_ADD(incr, addr->size);
} else
WT_RET(__split_multi_inmem(session, page, ref, multi));