diff options
-rw-r--r-- | src/btree/bt_discard.c | 50 | ||||
-rw-r--r-- | src/btree/rec_evict.c | 35 | ||||
-rw-r--r-- | src/include/btmem.h | 5 | ||||
-rw-r--r-- | src/include/wt_internal.h | 2 |
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; |