diff options
author | Michael Cahill <michael.cahill@wiredtiger.com> | 2012-11-16 18:19:48 +1100 |
---|---|---|
committer | Michael Cahill <michael.cahill@wiredtiger.com> | 2012-11-16 18:19:48 +1100 |
commit | c7258fd32736db32a01981c12625213d0b865310 (patch) | |
tree | bb97e79a99644cad2342df69cfd6d9c3fe491e53 | |
parent | d98d02ecc03d6dbc7b342c05d4b3e9953a8af119 (diff) | |
download | mongo-c7258fd32736db32a01981c12625213d0b865310.tar.gz |
Don't automatically fail inserts if the write generation check fails: compare keys instead.
-rw-r--r-- | dist/serial.py | 2 | ||||
-rw-r--r-- | src/btree/bt_curnext.c | 2 | ||||
-rw-r--r-- | src/btree/bt_curprev.c | 8 | ||||
-rw-r--r-- | src/btree/col_modify.c | 20 | ||||
-rw-r--r-- | src/btree/col_srch.c | 8 | ||||
-rw-r--r-- | src/btree/row_modify.c | 38 | ||||
-rw-r--r-- | src/btree/row_srch.c | 43 | ||||
-rw-r--r-- | src/include/cache.i | 2 | ||||
-rw-r--r-- | src/include/column.i | 25 | ||||
-rw-r--r-- | src/include/cursor.h | 3 | ||||
-rw-r--r-- | src/include/serial_funcs.i | 36 | ||||
-rw-r--r-- | src/lsm/lsm_worker.c | 4 |
12 files changed, 129 insertions, 62 deletions
diff --git a/dist/serial.py b/dist/serial.py index 8772c4bd6bc..46ebc86d0c2 100644 --- a/dist/serial.py +++ b/dist/serial.py @@ -20,6 +20,7 @@ Serial('col_append', [ SerialArg('uint32_t', 'write_gen'), SerialArg('WT_INSERT_HEAD **', 'insheadp'), SerialArg('WT_INSERT ***', 'ins_stack'), + SerialArg('WT_INSERT **', 'next_stack'), SerialArg('WT_INSERT_HEAD **', 'new_inslist', 1), SerialArg('WT_INSERT_HEAD *', 'new_inshead', 1), SerialArg('WT_INSERT *', 'new_ins', 1), @@ -31,6 +32,7 @@ Serial('insert', [ SerialArg('uint32_t', 'write_gen'), SerialArg('WT_INSERT_HEAD **', 'inshead'), SerialArg('WT_INSERT ***', 'ins_stack'), + SerialArg('WT_INSERT **', 'next_stack'), SerialArg('WT_INSERT_HEAD **', 'new_inslist', 1), SerialArg('WT_INSERT_HEAD *', 'new_inshead', 1), SerialArg('WT_INSERT *', 'new_ins', 1), diff --git a/src/btree/bt_curnext.c b/src/btree/bt_curnext.c index d08f113fd90..6bfc4a8ad89 100644 --- a/src/btree/bt_curnext.c +++ b/src/btree/bt_curnext.c @@ -100,7 +100,7 @@ __cursor_fix_next(WT_CURSOR_BTREE *cbt, int newpage) new_page: /* Check any insert list for a matching record. */ cbt->ins_head = WT_COL_UPDATE_SINGLE(cbt->page); cbt->ins = __col_insert_search( - cbt->ins_head, cbt->ins_stack, cbt->recno); + cbt->ins_head, cbt->ins_stack, cbt->next_stack, cbt->recno); if (cbt->ins != NULL && cbt->recno != WT_INSERT_RECNO(cbt->ins)) cbt->ins = NULL; diff --git a/src/btree/bt_curprev.c b/src/btree/bt_curprev.c index 650f09f1a87..e836615c4bc 100644 --- a/src/btree/bt_curprev.c +++ b/src/btree/bt_curprev.c @@ -54,7 +54,8 @@ restart: session, cbt, cbt->ins_head, &key)); } else cbt->ins = __col_insert_search(cbt->ins_head, - cbt->ins_stack, WT_INSERT_RECNO(current)); + cbt->ins_stack, cbt->next_stack, + WT_INSERT_RECNO(current)); } /* @@ -83,6 +84,7 @@ restart: if (ins == NULL || ins == current) for (; i >= 0; i--) { cbt->ins_stack[i] = NULL; + cbt->next_stack[i] = NULL; ins = cbt->ins_head->head[i]; if (ins != NULL && ins != current) break; @@ -96,12 +98,14 @@ restart: */ if (ins == NULL) { cbt->ins_stack[0] = NULL; + cbt->next_stack[0] = NULL; goto restart; } if (ins->next[i] != current) /* Stay at this level */ ins = ins->next[i]; else { /* Drop down a level */ cbt->ins_stack[i] = &ins->next[i]; + cbt->next_stack[i] = ins->next[i]; --i; } } @@ -231,7 +235,7 @@ __cursor_fix_prev(WT_CURSOR_BTREE *cbt, int newpage) new_page: /* Check any insert list for a matching record. */ cbt->ins_head = WT_COL_UPDATE_SINGLE(cbt->page); cbt->ins = __col_insert_search( - cbt->ins_head, cbt->ins_stack, cbt->recno); + cbt->ins_head, cbt->ins_stack, cbt->next_stack, cbt->recno); if (cbt->ins != NULL && cbt->recno != WT_INSERT_RECNO(cbt->ins)) cbt->ins = NULL; diff --git a/src/btree/col_modify.c b/src/btree/col_modify.c index 7035ccdc74b..fbe7898dc40 100644 --- a/src/btree/col_modify.c +++ b/src/btree/col_modify.c @@ -134,8 +134,10 @@ __wt_col_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, int op) if (*inshead == NULL) { new_inshead_size = sizeof(WT_INSERT_HEAD); WT_ERR(__wt_calloc_def(session, 1, &new_inshead)); - for (i = 0; i < WT_SKIP_MAXDEPTH; i++) + for (i = 0; i < WT_SKIP_MAXDEPTH; i++) { cbt->ins_stack[i] = &new_inshead->head[i]; + cbt->next_stack[i] = NULL; + } cbt->ins_head = new_inshead; } @@ -164,7 +166,8 @@ __wt_col_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, int op) ins_copy = ins; WT_ERR(__wt_col_append_serial(session, - page, cbt->write_gen, inshead, cbt->ins_stack, + page, cbt->write_gen, inshead, + cbt->ins_stack, cbt->next_stack, &new_inslist, new_inslist_size, &new_inshead, new_inshead_size, &ins, ins_size, skipdepth)); @@ -173,8 +176,8 @@ __wt_col_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, int op) cbt->recno = WT_INSERT_RECNO(ins_copy); } else WT_ERR(__wt_insert_serial(session, - page, cbt->write_gen, - inshead, cbt->ins_stack, + page, cbt->write_gen, inshead, + cbt->ins_stack, cbt->next_stack, &new_inslist, new_inslist_size, &new_inshead, new_inshead_size, &ins, ins_size, skipdepth)); @@ -230,7 +233,7 @@ int __wt_col_append_serial_func(WT_SESSION_IMPL *session, void *args) { WT_BTREE *btree; - WT_INSERT *ins, *new_ins, ***ins_stack; + WT_INSERT *ins, *new_ins, ***ins_stack, **next_stack; WT_INSERT_HEAD *inshead, **insheadp, **new_inslist, *new_inshead; WT_PAGE *page; uint64_t recno; @@ -239,8 +242,9 @@ __wt_col_append_serial_func(WT_SESSION_IMPL *session, void *args) btree = session->btree; - __wt_col_append_unpack(args, &page, &write_gen, &insheadp, - &ins_stack, &new_inslist, &new_inshead, &new_ins, &skipdepth); + __wt_col_append_unpack(args, + &page, &write_gen, &insheadp, &ins_stack, &next_stack, + &new_inslist, &new_inshead, &new_ins, &skipdepth); /* Check the page's write-generation. */ WT_RET(__wt_page_write_gen_check(session, page, write_gen)); @@ -259,7 +263,7 @@ __wt_col_append_serial_func(WT_SESSION_IMPL *session, void *args) if ((recno = WT_INSERT_RECNO(new_ins)) == 0) recno = WT_INSERT_RECNO(new_ins) = ++btree->last_recno; - ins = __col_insert_search(inshead, ins_stack, recno); + ins = __col_insert_search(inshead, ins_stack, next_stack, recno); /* If we find the record number, there's been a race. */ if (ins != NULL && WT_INSERT_RECNO(ins) == recno) diff --git a/src/btree/col_srch.c b/src/btree/col_srch.c index c2fbf80c2e2..ffcca036cab 100644 --- a/src/btree/col_srch.c +++ b/src/btree/col_srch.c @@ -117,8 +117,8 @@ __wt_col_search(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, int is_modify) * For that reason, don't set the cursor's WT_INSERT_HEAD/WT_INSERT pair * until we know we have a useful entry. */ - if ((ins = - __col_insert_search(ins_head, cbt->ins_stack, recno)) != NULL) + if ((ins = __col_insert_search( + ins_head, cbt->ins_stack, cbt->next_stack, recno)) != NULL) if (recno == WT_INSERT_RECNO(ins)) { cbt->ins_head = ins_head; cbt->ins = ins; @@ -135,8 +135,8 @@ past_end: * past the end of the table. */ cbt->ins_head = WT_COL_APPEND(page); - if ((cbt->ins = - __col_insert_search(cbt->ins_head, cbt->ins_stack, recno)) == NULL) + if ((cbt->ins = __col_insert_search( + cbt->ins_head, cbt->ins_stack, cbt->next_stack, recno)) == NULL) cbt->compare = -1; else { cbt->recno = WT_INSERT_RECNO(cbt->ins); diff --git a/src/btree/row_modify.c b/src/btree/row_modify.c index 2ad6947d6de..64123bc53e5 100644 --- a/src/btree/row_modify.c +++ b/src/btree/row_modify.c @@ -121,8 +121,10 @@ __wt_row_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, int is_remove) if (*inshead == NULL) { new_inshead_size = sizeof(WT_INSERT_HEAD); WT_ERR(__wt_calloc_def(session, 1, &new_inshead)); - for (i = 0; i < WT_SKIP_MAXDEPTH; i++) + for (i = 0; i < WT_SKIP_MAXDEPTH; i++) { cbt->ins_stack[i] = &new_inshead->head[i]; + cbt->next_stack[i] = NULL; + } cbt->ins_head = new_inshead; } @@ -144,7 +146,7 @@ __wt_row_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, int is_remove) /* Insert the WT_INSERT structure. */ WT_ERR(__wt_insert_serial(session, page, cbt->write_gen, - inshead, cbt->ins_stack, + inshead, cbt->ins_stack, cbt->next_stack, &new_inslist, new_inslist_size, &new_inshead, new_inshead_size, &ins, ins_size, skipdepth)); @@ -205,17 +207,38 @@ __wt_row_insert_alloc(WT_SESSION_IMPL *session, int __wt_insert_serial_func(WT_SESSION_IMPL *session, void *args) { - WT_INSERT *new_ins, ***ins_stack; + WT_INSERT *new_ins, ***ins_stack, **next_stack; WT_INSERT_HEAD *inshead, **insheadp, **new_inslist, *new_inshead; WT_PAGE *page; uint32_t write_gen; u_int i, skipdepth; __wt_insert_unpack(args, &page, &write_gen, &insheadp, - &ins_stack, &new_inslist, &new_inshead, &new_ins, &skipdepth); + &ins_stack, &next_stack, + &new_inslist, &new_inshead, &new_ins, &skipdepth); - /* Check the page's write-generation. */ - WT_RET(__wt_page_write_gen_check(session, page, write_gen)); + if ((inshead = *insheadp) == NULL) + inshead = new_inshead; + + /* + * Check the page's write-generation: if that fails, check whether we + * are still in the expected position, and no item has been added where + * our insert belongs. + */ + if (page->modify->write_gen + 1 == page->modify->disk_gen) + return (WT_RESTART); + + if (page->modify->write_gen != write_gen) { + for (i = 0; i < skipdepth; i++) { + if (ins_stack[i] == NULL || + *ins_stack[i] != next_stack[i]) + return (WT_RESTART); + if (next_stack[i] == NULL && + inshead->tail[i] != NULL && + ins_stack[i] != &inshead->tail[i]->next[i]) + return (WT_RESTART); + } + } /* * Publish: First, point the new WT_INSERT item's skiplist references @@ -223,10 +246,9 @@ __wt_insert_serial_func(WT_SESSION_IMPL *session, void *args) * update the skiplist elements that reference the new WT_INSERT item, * this ensures the list is never inconsistent. */ - if ((inshead = *insheadp) == NULL) - inshead = new_inshead; for (i = 0; i < skipdepth; i++) new_ins->next[i] = *ins_stack[i]; + WT_WRITE_BARRIER(); for (i = 0; i < skipdepth; i++) { if (inshead->tail[i] == NULL || diff --git a/src/btree/row_srch.c b/src/btree/row_srch.c index 885979bffbf..f005db24a1e 100644 --- a/src/btree/row_srch.c +++ b/src/btree/row_srch.c @@ -16,27 +16,39 @@ __wt_search_insert(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, WT_INSERT_HEAD *inshead, WT_ITEM *srch_key) { WT_BTREE *btree; - WT_INSERT **insp, *ret_ins; + WT_INSERT **insp, *last_ins, *ret_ins; WT_ITEM insert_key; int cmp, i; + btree = session->btree; + /* If there's no insert chain to search, we're done. */ if ((ret_ins = WT_SKIP_LAST(inshead)) == NULL) { cbt->ins = NULL; + cbt->next_stack[0] = NULL; return (0); } - btree = session->btree; - /* Fast-path appends. */ insert_key.data = WT_INSERT_KEY(ret_ins); insert_key.size = WT_INSERT_KEY_SIZE(ret_ins); (void)WT_BTREE_CMP(session, btree, srch_key, &insert_key, cmp); if (cmp >= 0) { - for (i = WT_SKIP_MAXDEPTH - 1; i >= 0; i--) - cbt->ins_stack[i] = (inshead->tail[i] != NULL) ? - &inshead->tail[i]->next[i] : - &inshead->head[i]; + /* + * XXX We may race with another appending thread. + * + * To catch that case, rely on the atomic pointer read above + * and set the next stack to NULL here. If we have raced with + * another thread, one of the next pointers will not be NULL by + * the time they are checked against the next stack inside the + * serialized insert function. + */ + for (i = WT_SKIP_MAXDEPTH - 1; i >= 0; i--) { + cbt->ins_stack[i] = (i == 0) ? &ret_ins->next[0] : + (inshead->tail[i] != NULL) ? + &inshead->tail[i]->next[i] : &inshead->head[i]; + cbt->next_stack[i] = NULL; + } cbt->compare = -cmp; cbt->ins = ret_ins; return (0); @@ -46,9 +58,10 @@ __wt_search_insert(WT_SESSION_IMPL *session, * The insert list is a skip list: start at the highest skip level, then * go as far as possible at each level before stepping down to the next. */ - ret_ins = NULL; + last_ins = ret_ins = NULL; for (i = WT_SKIP_MAXDEPTH - 1, insp = &inshead->head[i]; i >= 0;) { - if (*insp == NULL) { + if ((ret_ins = *insp) == NULL) { + cbt->next_stack[i] = NULL; cbt->ins_stack[i--] = insp--; continue; } @@ -57,8 +70,8 @@ __wt_search_insert(WT_SESSION_IMPL *session, * Comparisons may be repeated as we drop down skiplist levels; * don't repeat comparisons, they might be expensive. */ - if (ret_ins != *insp) { - ret_ins = *insp; + if (ret_ins != last_ins) { + last_ins = ret_ins; insert_key.data = WT_INSERT_KEY(ret_ins); insert_key.size = WT_INSERT_KEY_SIZE(ret_ins); WT_RET(WT_BTREE_CMP( @@ -68,10 +81,14 @@ __wt_search_insert(WT_SESSION_IMPL *session, if (cmp > 0) /* Keep going at this level */ insp = &ret_ins->next[i]; else if (cmp == 0) - for (; i >= 0; i--) + for (; i >= 0; i--) { + cbt->next_stack[i] = ret_ins->next[i]; cbt->ins_stack[i] = &ret_ins->next[i]; - else /* Drop down a level */ + } + else { /* Drop down a level */ + cbt->next_stack[i] = ret_ins; cbt->ins_stack[i--] = insp--; + } } /* diff --git a/src/include/cache.i b/src/include/cache.i index 4312304d968..5ecc0c11701 100644 --- a/src/include/cache.i +++ b/src/include/cache.i @@ -55,7 +55,7 @@ __wt_cache_full_check(WT_SESSION_IMPL *session) for (wake = 0;; wake = (wake + 1) % 100) { __wt_eviction_check(session, &lockout, wake == 0); if (!lockout || F_ISSET(session, - WT_SESSION_NO_CACHE_CHECK | WT_SESSION_SCHEMA_LOCKED)) + WT_SESSION_NO_CACHE_CHECK | WT_SESSION_SCHEMA_LOCKED)) return (0); if ((btree = session->btree) != NULL && F_ISSET(btree, WT_BTREE_BULK | WT_BTREE_NO_CACHE | WT_BTREE_NO_EVICTION)) diff --git a/src/include/column.i b/src/include/column.i index 83b2783dbf0..0cf83a6d2e9 100644 --- a/src/include/column.i +++ b/src/include/column.i @@ -58,8 +58,8 @@ __col_insert_search_match(WT_INSERT_HEAD *inshead, uint64_t recno) * Search a column-store insert list, creating a skiplist stack as we go. */ static inline WT_INSERT * -__col_insert_search( - WT_INSERT_HEAD *inshead, WT_INSERT ***ins_stack, uint64_t recno) +__col_insert_search(WT_INSERT_HEAD *inshead, + WT_INSERT ***ins_stack, WT_INSERT **next_stack, uint64_t recno) { WT_INSERT **insp, *ret_ins; uint64_t ins_recno; @@ -71,9 +71,12 @@ __col_insert_search( /* Fast path appends. */ if (recno >= WT_INSERT_RECNO(ret_ins)) { - for (i = 0; i < WT_SKIP_MAXDEPTH; i++) - ins_stack[i] = (inshead->tail[i] != NULL) ? + for (i = 0; i < WT_SKIP_MAXDEPTH; i++) { + ins_stack[i] = (i == 0) ? &ret_ins->next[0] : + (inshead->tail[i] != NULL) ? &inshead->tail[i]->next[i] : &inshead->head[i]; + next_stack[i] = NULL; + } return (ret_ins); } @@ -82,22 +85,26 @@ __col_insert_search( * go as far as possible at each level before stepping down to the next. */ for (i = WT_SKIP_MAXDEPTH - 1, insp = &inshead->head[i]; i >= 0; ) { - if (*insp == NULL) { + if ((ret_ins = *insp) == NULL) { + next_stack[i] = NULL; ins_stack[i--] = insp--; continue; } - ret_ins = *insp; ins_recno = WT_INSERT_RECNO(ret_ins); cmp = (recno == ins_recno) ? 0 : (recno < ins_recno) ? -1 : 1; if (cmp > 0) /* Keep going at this level */ - insp = &(*insp)->next[i]; + insp = &ret_ins->next[i]; else if (cmp == 0) /* Exact match: return */ - for (; i >= 0; i--) + for (; i >= 0; i--) { + next_stack[i] = ret_ins->next[i]; ins_stack[i] = &ret_ins->next[i]; - else /* Drop down a level */ + } + else { /* Drop down a level */ + next_stack[i] = ret_ins; ins_stack[i--] = insp--; + } } return (ret_ins); } diff --git a/src/include/cursor.h b/src/include/cursor.h index 3afc5a8ea7c..85c61076b75 100644 --- a/src/include/cursor.h +++ b/src/include/cursor.h @@ -36,6 +36,9 @@ struct __wt_cursor_btree { /* Search stack */ WT_INSERT **ins_stack[WT_SKIP_MAXDEPTH]; + /* Next item(s) found during search */ + WT_INSERT *next_stack[WT_SKIP_MAXDEPTH]; + uint64_t recno; /* Record number */ uint32_t write_gen; /* Saved leaf page's write generation */ diff --git a/src/include/serial_funcs.i b/src/include/serial_funcs.i index bbddf47042b..4b39b877088 100644 --- a/src/include/serial_funcs.i +++ b/src/include/serial_funcs.i @@ -5,6 +5,7 @@ typedef struct { uint32_t write_gen; WT_INSERT_HEAD **insheadp; WT_INSERT ***ins_stack; + WT_INSERT **next_stack; WT_INSERT_HEAD **new_inslist; size_t new_inslist_size; int new_inslist_taken; @@ -20,10 +21,10 @@ typedef struct { static inline int __wt_col_append_serial( WT_SESSION_IMPL *session, WT_PAGE *page, uint32_t write_gen, - WT_INSERT_HEAD **insheadp, WT_INSERT ***ins_stack, WT_INSERT_HEAD - ***new_inslistp, size_t new_inslist_size, WT_INSERT_HEAD - **new_insheadp, size_t new_inshead_size, WT_INSERT **new_insp, size_t - new_ins_size, u_int skipdepth) + WT_INSERT_HEAD **insheadp, WT_INSERT ***ins_stack, WT_INSERT + **next_stack, WT_INSERT_HEAD ***new_inslistp, size_t new_inslist_size, + WT_INSERT_HEAD **new_insheadp, size_t new_inshead_size, WT_INSERT + **new_insp, size_t new_ins_size, u_int skipdepth) { __wt_col_append_args _args, *args = &_args; WT_DECL_RET; @@ -36,6 +37,8 @@ __wt_col_append_serial( args->ins_stack = ins_stack; + args->next_stack = next_stack; + if (new_inslistp == NULL) args->new_inslist = NULL; else { @@ -81,9 +84,9 @@ __wt_col_append_serial( static inline void __wt_col_append_unpack( void *untyped_args, WT_PAGE **pagep, uint32_t *write_genp, - WT_INSERT_HEAD ***insheadpp, WT_INSERT ****ins_stackp, WT_INSERT_HEAD - ***new_inslistp, WT_INSERT_HEAD **new_insheadp, WT_INSERT **new_insp, - u_int *skipdepthp) + WT_INSERT_HEAD ***insheadpp, WT_INSERT ****ins_stackp, WT_INSERT + ***next_stackp, WT_INSERT_HEAD ***new_inslistp, WT_INSERT_HEAD + **new_insheadp, WT_INSERT **new_insp, u_int *skipdepthp) { __wt_col_append_args *args = (__wt_col_append_args *)untyped_args; @@ -91,6 +94,7 @@ __wt_col_append_unpack( *write_genp = args->write_gen; *insheadpp = args->insheadp; *ins_stackp = args->ins_stack; + *next_stackp = args->next_stack; *new_inslistp = args->new_inslist; *new_insheadp = args->new_inshead; *new_insp = args->new_ins; @@ -138,6 +142,7 @@ typedef struct { uint32_t write_gen; WT_INSERT_HEAD **inshead; WT_INSERT ***ins_stack; + WT_INSERT **next_stack; WT_INSERT_HEAD **new_inslist; size_t new_inslist_size; int new_inslist_taken; @@ -153,10 +158,10 @@ typedef struct { static inline int __wt_insert_serial( WT_SESSION_IMPL *session, WT_PAGE *page, uint32_t write_gen, - WT_INSERT_HEAD **inshead, WT_INSERT ***ins_stack, WT_INSERT_HEAD - ***new_inslistp, size_t new_inslist_size, WT_INSERT_HEAD - **new_insheadp, size_t new_inshead_size, WT_INSERT **new_insp, size_t - new_ins_size, u_int skipdepth) + WT_INSERT_HEAD **inshead, WT_INSERT ***ins_stack, WT_INSERT + **next_stack, WT_INSERT_HEAD ***new_inslistp, size_t new_inslist_size, + WT_INSERT_HEAD **new_insheadp, size_t new_inshead_size, WT_INSERT + **new_insp, size_t new_ins_size, u_int skipdepth) { __wt_insert_args _args, *args = &_args; WT_DECL_RET; @@ -169,6 +174,8 @@ __wt_insert_serial( args->ins_stack = ins_stack; + args->next_stack = next_stack; + if (new_inslistp == NULL) args->new_inslist = NULL; else { @@ -214,9 +221,9 @@ __wt_insert_serial( static inline void __wt_insert_unpack( void *untyped_args, WT_PAGE **pagep, uint32_t *write_genp, - WT_INSERT_HEAD ***insheadp, WT_INSERT ****ins_stackp, WT_INSERT_HEAD - ***new_inslistp, WT_INSERT_HEAD **new_insheadp, WT_INSERT **new_insp, - u_int *skipdepthp) + WT_INSERT_HEAD ***insheadp, WT_INSERT ****ins_stackp, WT_INSERT + ***next_stackp, WT_INSERT_HEAD ***new_inslistp, WT_INSERT_HEAD + **new_insheadp, WT_INSERT **new_insp, u_int *skipdepthp) { __wt_insert_args *args = (__wt_insert_args *)untyped_args; @@ -224,6 +231,7 @@ __wt_insert_unpack( *write_genp = args->write_gen; *insheadp = args->inshead; *ins_stackp = args->ins_stack; + *next_stackp = args->next_stack; *new_inslistp = args->new_inslist; *new_insheadp = args->new_inshead; *new_insp = args->new_ins; diff --git a/src/lsm/lsm_worker.c b/src/lsm/lsm_worker.c index 429c38d39ed..647d79a3897 100644 --- a/src/lsm/lsm_worker.c +++ b/src/lsm/lsm_worker.c @@ -186,11 +186,11 @@ __wt_lsm_checkpoint_worker(void *arg) } ++j; - __wt_spin_lock(session, &lsm_tree->lock); + __wt_writelock(session, lsm_tree->rwlock); F_SET(chunk, WT_LSM_CHUNK_ONDISK); ++lsm_tree->dsk_gen; ret = __wt_lsm_meta_write(session, lsm_tree); - __wt_spin_unlock(session, &lsm_tree->lock); + __wt_rwunlock(session, lsm_tree->rwlock); if (ret != 0) { (void)__wt_err(session, ret, |