diff options
author | Alexander Gorrod <alexander.gorrod@mongodb.com> | 2015-05-08 05:34:43 +0000 |
---|---|---|
committer | Alexander Gorrod <alexander.gorrod@mongodb.com> | 2015-05-08 05:34:43 +0000 |
commit | cddb4b8f5a193e32d1400963cd177fe47c8570df (patch) | |
tree | dade044e688956af69505fc796244f229d40241c /src/third_party/wiredtiger/src/reconcile | |
parent | 3a8bcdfb23ab85b57e5da308fb4d3c607ce77a49 (diff) | |
download | mongo-cddb4b8f5a193e32d1400963cd177fe47c8570df.tar.gz |
Import wiredtiger-wiredtiger-2.5.3-486-g4f9aa1c.tar.gz from wiredtiger branch mongodb-3.2
Diffstat (limited to 'src/third_party/wiredtiger/src/reconcile')
-rw-r--r-- | src/third_party/wiredtiger/src/reconcile/rec_write.c | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/src/third_party/wiredtiger/src/reconcile/rec_write.c b/src/third_party/wiredtiger/src/reconcile/rec_write.c index 5bef5cd2d2d..76d61642bfd 100644 --- a/src/third_party/wiredtiger/src/reconcile/rec_write.c +++ b/src/third_party/wiredtiger/src/reconcile/rec_write.c @@ -483,6 +483,7 @@ __rec_root_write(WT_SESSION_IMPL *session, WT_PAGE *page, uint32_t flags) switch (F_ISSET(mod, WT_PM_REC_MASK)) { case WT_PM_REC_EMPTY: /* Page is empty */ case WT_PM_REC_REPLACE: /* 1-for-1 page swap */ + case WT_PM_REC_REWRITE: /* Rewrite */ return (0); case WT_PM_REC_MULTIBLOCK: /* Multiple blocks */ break; @@ -3229,6 +3230,18 @@ __rec_col_int(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) WT_RET(__rec_split_init( session, r, page, page->pg_intl_recno, btree->maxintlpage)); + /* + * We need to mark this page as splitting, as this may be an in-memory + * split during a checkpoint. + */ + for (;;) { + F_CAS_ATOMIC(page, WT_PAGE_SPLIT_LOCKED, ret); + if (ret == 0) { + break; + } + __wt_yield(); + } + /* For each entry in the in-memory page... */ WT_INTL_FOREACH_BEGIN(session, page, ref) { /* Update the starting record number in case we split. */ @@ -3271,6 +3284,8 @@ __rec_col_int(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) case WT_PM_REC_REPLACE: addr = &child->modify->mod_replace; break; + case WT_PM_REC_REWRITE: + break; WT_ILLEGAL_VALUE_ERR(session); } } else @@ -3309,6 +3324,8 @@ __rec_col_int(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) __rec_copy_incr(session, r, val); } WT_INTL_FOREACH_END; + F_CLR_ATOMIC(page, WT_PAGE_SPLIT_LOCKED); + /* Write the remnant page. */ return (__rec_split_finish(session, r)); @@ -4041,6 +4058,18 @@ __rec_row_int(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) */ r->cell_zero = 1; + /* + * We need to mark this page as splitting in order to ensure we don't + * deadlock when performing an in-memory split during a checkpoint. + */ + for (;;) { + F_CAS_ATOMIC(page, WT_PAGE_SPLIT_LOCKED, ret); + if (ret == 0) { + break; + } + __wt_yield(); + } + /* For each entry in the in-memory page... */ WT_INTL_FOREACH_BEGIN(session, page, ref) { /* @@ -4199,6 +4228,8 @@ __rec_row_int(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) __rec_key_state_update(r, ovfl_key); } WT_INTL_FOREACH_END; + F_CLR_ATOMIC(page, WT_PAGE_SPLIT_LOCKED); + /* Write the remnant page. */ return (__rec_split_finish(session, r)); @@ -4836,6 +4867,7 @@ __rec_write_wrapup(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) case WT_PM_REC_EMPTY: /* Page deleted */ break; case WT_PM_REC_MULTIBLOCK: /* Multiple blocks */ + case WT_PM_REC_REWRITE: /* Rewrite */ /* * Discard the multiple replacement blocks. */ @@ -4914,7 +4946,7 @@ __rec_write_wrapup(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) bnd->dsk = NULL; mod->mod_multi_entries = 1; - F_SET(mod, WT_PM_REC_MULTIBLOCK); + F_SET(mod, WT_PM_REC_REWRITE); break; } @@ -5064,10 +5096,14 @@ __rec_write_wrapup_err(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) * information (otherwise we might think the backing block is being * reused on a subsequent reconciliation where we want to free it). */ - if (F_ISSET(mod, WT_PM_REC_MASK) == WT_PM_REC_MULTIBLOCK) + switch (F_ISSET(mod, WT_PM_REC_MASK)) { + case WT_PM_REC_MULTIBLOCK: + case WT_PM_REC_REWRITE: for (multi = mod->mod_multi, i = 0; i < mod->mod_multi_entries; ++multi, ++i) multi->addr.reuse = 0; + break; + } /* * On error, discard blocks we've written, they're unreferenced by the |