summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/btree/bt_discard.c50
-rw-r--r--src/btree/rec_evict.c35
-rw-r--r--src/include/btmem.h5
-rw-r--r--src/include/wt_internal.h2
4 files changed, 48 insertions, 44 deletions
diff --git a/src/btree/bt_discard.c b/src/btree/bt_discard.c
index 6894bde796f..23c7f2bd199 100644
--- a/src/btree/bt_discard.c
+++ b/src/btree/bt_discard.c
@@ -94,7 +94,8 @@ __free_page_modify(WT_SESSION_IMPL *session, WT_PAGE *page)
{
WT_INSERT_HEAD *append;
WT_PAGE_MODIFY *mod;
- uint32_t i;
+ WT_REF *ref;
+ uint32_t i, j;
mod = page->modify;
@@ -119,12 +120,17 @@ __free_page_modify(WT_SESSION_IMPL *session, WT_PAGE *page)
}
/*
- * Free the split chunks; we do not have to review the individual WT_REF
- * entries in the chunks, they are discarded by walking the "final" list
- * of WT_REF entries when each internal page is discarded.
+ * Free the split chunks created when underlying pages split into this
+ * page.
*/
- for (i = 0; i < mod->splits_slots; ++i)
- __wt_free(session, mod->splits[i]);
+ for (i = 0; i < mod->splits_slots; ++i) {
+ if ((ref = mod->splits[i].refs) == NULL)
+ break;
+ for (j = mod->splits[i].entries; j > 0; ++ref, --j)
+ __wt_free_ref(session, page, ref);
+ __wt_free(session, mod->splits[i].refs);
+ }
+ __wt_free(session, mod->splits);
/* Free the reconciliation-created array of split pages. */
__wt_free(session, mod->split_ref);
@@ -152,32 +158,13 @@ __free_page_modify(WT_SESSION_IMPL *session, WT_PAGE *page)
}
/*
- * __free_page_col_var --
- * Discard a WT_PAGE_COL_VAR page.
- */
-static void
-__free_page_col_var(WT_SESSION_IMPL *session, WT_PAGE *page)
-{
- /* Free the RLE lookup array. */
- __wt_free(session, page->pu_var_repeats);
-}
-
-/*
* __free_page_int --
* Discard a WT_PAGE_ROW_INT page.
*/
static void
__free_page_int(WT_SESSION_IMPL *session, WT_PAGE *page)
{
- WT_REF *ref;
-
- /* Free the contents of any WT_REF structures. */
- if (page->pu_intl_index != NULL) {
- WT_INTL_FOREACH_BEGIN(page, ref) {
- __wt_free_ref(session, page, ref);
- } WT_INTL_FOREACH_END;
- __wt_free(session, page->pu_intl_index);
- }
+ __wt_free(session, page->pu_intl_index);
}
/*
@@ -215,6 +202,17 @@ __wt_free_ref(WT_SESSION_IMPL *session, WT_PAGE *page, WT_REF *ref)
}
/*
+ * __free_page_col_var --
+ * Discard a WT_PAGE_COL_VAR page.
+ */
+static void
+__free_page_col_var(WT_SESSION_IMPL *session, WT_PAGE *page)
+{
+ /* Free the RLE lookup array. */
+ __wt_free(session, page->pu_var_repeats);
+}
+
+/*
* __free_page_row_leaf --
* Discard a WT_PAGE_ROW_LEAF page.
*/
diff --git a/src/btree/rec_evict.c b/src/btree/rec_evict.c
index 7be75f1e5b2..aa7146b37e8 100644
--- a/src/btree/rec_evict.c
+++ b/src/btree/rec_evict.c
@@ -150,7 +150,7 @@ __rec_split_list_alloc(
uint32_t i;
for (i = 0; i < mod->splits_slots; ++i)
- if (mod->splits[i] == NULL)
+ if (mod->splits[i].refs == NULL)
break;
if (i == mod->splits_slots) {
WT_RET(__wt_realloc(session,
@@ -186,8 +186,7 @@ __rec_split_deepen(WT_SESSION_IMPL *session, WT_PAGE *page)
entries = (uint32_t)btree->split_deepen;
WT_VERBOSE_ERR(session, split,
- "page %p with %" PRIu32
- " elements, splitting in-memory into %" PRIu32 " elements",
+ "%p: %" PRIu32 " elements, splitting into %" PRIu32 " children",
page, pindex->entries, entries);
/* Allocate a new parent child-page index. */
@@ -216,7 +215,13 @@ __rec_split_deepen(WT_SESSION_IMPL *session, WT_PAGE *page)
/* Initialize the parent page reference. */
parent_ref->page = child;
parent_ref->addr = NULL;
- parent_ref->key = (*refp)->key; /* XXXKEITH stolen */
+ parent_ref->key = (*refp)->key;
+ if (page->type == WT_PAGE_ROW_INT) {
+ __wt_ref_key(page, *refp, &p, &size);
+ WT_ERR(__wt_row_ikey_incr(session,
+ page, 0, p, size, &parent_ref->key.ikey));
+ } else
+ parent_ref->key.recno = (*refp)->key.recno;
parent_ref->txnid = 0; /* XXXKEITH 0? */
parent_ref->state = WT_REF_MEM;
@@ -273,7 +278,8 @@ __rec_split_deepen(WT_SESSION_IMPL *session, WT_PAGE *page)
/* Add the WT_REF array into the page's list. */
WT_ERR(__rec_split_list_alloc(session, page->modify, &i));
- page->modify->splits[i] = alloc_ref;
+ page->modify->splits[i].refs = alloc_ref;
+ page->modify->splits[i].entries = entries;
alloc_ref = NULL;
/*
@@ -363,11 +369,13 @@ __rec_split_evict(WT_SESSION_IMPL *session, WT_REF *parent_ref, WT_PAGE *page)
* page's list.
*/
WT_ERR(__rec_split_list_alloc(session, parent_mod, &i));
- split = parent_mod->splits[i] = mod->split_ref;
+ parent_mod->splits[i].refs = mod->split_ref;
+ parent_mod->splits[i].entries = mod->split_entries;
/* Allocate a new WT_REF index array and initialize it. */
pindex = parent->pu_intl_index;
parent_entries = pindex->entries;
+ split = mod->split_ref;
split_entries = mod->split_entries;
result_entries = (parent_entries - 1) + split_entries;
WT_ERR(__wt_calloc(session, 1, sizeof(WT_PAGE_INDEX) +
@@ -406,20 +414,13 @@ __rec_split_evict(WT_SESSION_IMPL *session, WT_REF *parent_ref, WT_PAGE *page)
* blocked threads.
*/
WT_PUBLISH(parent_ref->state, WT_REF_SPLIT);
- /*
- * XXXKEITH
- * We just leaked any memory held by this WT_REF structure, we don't
- * find it when we discard the page. I suspect that the solution is
- * that discarding a page walks all of the WT_REF arrays instead of
- * walking the higher-level index, but that has problems for the code
- * that deepens the split tree, it "steals" keys from one WT_REF array
- * to another.
- */
WT_STAT_FAST_CONN_INCR(session, cache_eviction_split);
WT_VERBOSE_ERR(session, split,
- "page %p split into parent %p %" PRIu32 " -> %" PRIu32,
- page, parent, parent_entries, result_entries);
+ "%p: %s merged into %p %" PRIu32 " -> %" PRIu32
+ " (%" PRIu32 ")",
+ page, __wt_page_type_string(page->type), parent, parent_entries,
+ result_entries, result_entries - parent_entries);
/*
* We're already holding the parent page locked, see if the parent needs
diff --git a/src/include/btmem.h b/src/include/btmem.h
index f5a8b336876..00dda0af840 100644
--- a/src/include/btmem.h
+++ b/src/include/btmem.h
@@ -217,7 +217,10 @@ struct __wt_page_modify {
* XXXKEITH
* Only internal pages have these.
*/
- WT_REF **splits; /* Split child WT_REFs */
+ struct __wt_split_chunk {
+ WT_REF *refs; /* Split child WT_REFs */
+ uint32_t entries; /* Count of entries */
+ } *splits;
uint32_t splits_slots; /* Split child WT_REFs count */
/*
diff --git a/src/include/wt_internal.h b/src/include/wt_internal.h
index 2befcb70c11..7b003f8549e 100644
--- a/src/include/wt_internal.h
+++ b/src/include/wt_internal.h
@@ -203,6 +203,8 @@ struct __wt_session_impl;
typedef struct __wt_session_impl WT_SESSION_IMPL;
struct __wt_size;
typedef struct __wt_size WT_SIZE;
+struct __wt_split_chunk;
+ typedef struct __wt_split_chunk WT_SPLIT_CHUNK;
struct __wt_stats;
typedef struct __wt_stats WT_STATS;
struct __wt_table;