diff options
author | Luke Chen <luke.chen@mongodb.com> | 2022-06-28 11:40:33 +1000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-06-28 02:10:18 +0000 |
commit | a5382fb01bb2d023c80c2eb1af807eca1f145c43 (patch) | |
tree | 1958ffe25dcfd72df571cab5e60c4417d6d74b1d | |
parent | 6bdcb2bd96e5a58c49aa28e367036b9c94f5c88b (diff) | |
download | mongo-a5382fb01bb2d023c80c2eb1af807eca1f145c43.tar.gz |
Import wiredtiger: 4a101bb595e70d47dce5333be5a32f3d02f810cc from branch mongodb-master
ref: 5f18c68f3e..4a101bb595
for: 6.1.0-rc0
WT-9417 Update assertions in reconciliation code to be enabled in release builds where appropriate
-rw-r--r-- | src/third_party/wiredtiger/dist/s_string.ok | 1 | ||||
-rw-r--r-- | src/third_party/wiredtiger/import.data | 2 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/btree/bt_discard.c | 6 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/include/error.h | 12 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/reconcile/rec_child.c | 4 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/reconcile/rec_col.c | 2 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/reconcile/rec_row.c | 3 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/reconcile/rec_track.c | 3 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/reconcile/rec_visibility.c | 114 | ||||
-rw-r--r-- | src/third_party/wiredtiger/src/reconcile/rec_write.c | 46 |
10 files changed, 114 insertions, 79 deletions
diff --git a/src/third_party/wiredtiger/dist/s_string.ok b/src/third_party/wiredtiger/dist/s_string.ok index 3377d0354e4..28fb3fe8f76 100644 --- a/src/third_party/wiredtiger/dist/s_string.ok +++ b/src/third_party/wiredtiger/dist/s_string.ok @@ -1501,6 +1501,7 @@ tokname tokstart toktype tolower +tombstoned toolchain toplevel totalsec diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index df4357c933a..aa29dd370c5 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -2,5 +2,5 @@ "vendor": "wiredtiger", "github": "wiredtiger/wiredtiger.git", "branch": "mongodb-master", - "commit": "5f18c68f3e5d57e368192ef715dbd4e80d8316eb" + "commit": "4a101bb595e70d47dce5333be5a32f3d02f810cc" } diff --git a/src/third_party/wiredtiger/src/btree/bt_discard.c b/src/third_party/wiredtiger/src/btree/bt_discard.c index 9a0d1f8630c..af5c1c523c9 100644 --- a/src/third_party/wiredtiger/src/btree/bt_discard.c +++ b/src/third_party/wiredtiger/src/btree/bt_discard.c @@ -73,9 +73,9 @@ __wt_page_out(WT_SESSION_IMPL *session, WT_PAGE **pagep) if (F_ISSET(session->dhandle, WT_DHANDLE_DEAD) || F_ISSET(S2C(session), WT_CONN_CLOSING)) __wt_page_modify_clear(session, page); - /* Assert we never discard a dirty page or a page queue for eviction. */ - WT_ASSERT(session, !__wt_page_is_modified(page)); - WT_ASSERT(session, !F_ISSET_ATOMIC_16(page, WT_PAGE_EVICT_LRU)); + WT_ASSERT_ALWAYS(session, !__wt_page_is_modified(page), "Attempting to discard dirty page"); + WT_ASSERT_ALWAYS(session, !F_ISSET_ATOMIC_16(page, WT_PAGE_EVICT_LRU), + "Attempting to discard page queued for eviction"); /* * If a root page split, there may be one or more pages linked from the page; walk the list, diff --git a/src/third_party/wiredtiger/src/include/error.h b/src/third_party/wiredtiger/src/include/error.h index a59b0c51c6e..0500f957944 100644 --- a/src/third_party/wiredtiger/src/include/error.h +++ b/src/third_party/wiredtiger/src/include/error.h @@ -176,3 +176,15 @@ WT_RET_PANIC(session, v, __VA_ARGS__); \ } while (0) #endif + +/* + * WT_ASSERT_ALWAYS + * Assert an expression, abort in both diagnostic and release mode if it fails. + */ +#define WT_ASSERT_ALWAYS(session, exp, failure_reason) \ + do { \ + if (!(exp)) { \ + __wt_errx(session, "Assertion '%s' failed: %s", #exp, failure_reason); \ + __wt_abort(session); \ + } \ + } while (0) diff --git a/src/third_party/wiredtiger/src/reconcile/rec_child.c b/src/third_party/wiredtiger/src/reconcile/rec_child.c index afdf3f5ad78..68ba5a363fd 100644 --- a/src/third_party/wiredtiger/src/reconcile/rec_child.c +++ b/src/third_party/wiredtiger/src/reconcile/rec_child.c @@ -72,7 +72,8 @@ __rec_child_deleted(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_REF *ref, */ WT_ORDERED_READ(prepare_state, page_del->prepare_state); if (prepare_state == WT_PREPARE_INPROGRESS || prepare_state == WT_PREPARE_LOCKED) { - WT_ASSERT(session, !F_ISSET(r, WT_REC_EVICT)); + WT_ASSERT_ALWAYS(session, !F_ISSET(r, WT_REC_EVICT), + "In progress prepares should never be seen in eviction"); cmsp->state = WT_CHILD_ORIGINAL; r->leave_dirty = true; @@ -145,6 +146,7 @@ __wt_rec_child_modify( switch (r->tested_ref_state = ref->state) { case WT_REF_DISK: /* On disk, not modified by definition. */ + // 9417 IGNORE WT_ASSERT(session, ref->addr != NULL); /* DISK pages do not have fast-truncate info. */ WT_ASSERT(session, ref->ft_info.del == NULL); diff --git a/src/third_party/wiredtiger/src/reconcile/rec_col.c b/src/third_party/wiredtiger/src/reconcile/rec_col.c index bda288d7b00..cb0474c1036 100644 --- a/src/third_party/wiredtiger/src/reconcile/rec_col.c +++ b/src/third_party/wiredtiger/src/reconcile/rec_col.c @@ -8,6 +8,8 @@ #include "wt_internal.h" +// 9417 IGNORE asserts in this file. Column store is not related to BF-25011 + /* * __rec_col_fix_bulk_insert_split_check -- * Check if a bulk-loaded fixed-length column store page needs to split. diff --git a/src/third_party/wiredtiger/src/reconcile/rec_row.c b/src/third_party/wiredtiger/src/reconcile/rec_row.c index 87654b4bb5a..1c73bd6a8b1 100644 --- a/src/third_party/wiredtiger/src/reconcile/rec_row.c +++ b/src/third_party/wiredtiger/src/reconcile/rec_row.c @@ -414,7 +414,8 @@ __wt_rec_row_int(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) * information in the address cell, be sure to propagate the original fast-truncate * information. */ - WT_ASSERT(session, cms.state == WT_CHILD_ORIGINAL); + WT_ASSERT_ALWAYS(session, cms.state == WT_CHILD_ORIGINAL, + "Not propagating the original fast-truncate information"); __wt_cell_unpack_addr(session, page->dsk, ref->addr, vpack); if (F_ISSET(vpack, WT_CELL_UNPACK_TIME_WINDOW_CLEARED)) { page_del = vpack->type == WT_CELL_ADDR_DEL ? &vpack->page_del : NULL; diff --git a/src/third_party/wiredtiger/src/reconcile/rec_track.c b/src/third_party/wiredtiger/src/reconcile/rec_track.c index 72d2e2388ab..895566584b4 100644 --- a/src/third_party/wiredtiger/src/reconcile/rec_track.c +++ b/src/third_party/wiredtiger/src/reconcile/rec_track.c @@ -336,7 +336,8 @@ __ovfl_reuse_wrapup(WT_SESSION_IMPL *session, WT_PAGE *page) } *e = reuse->next[0]; - WT_ASSERT(session, !F_ISSET(reuse, WT_OVFL_REUSE_JUST_ADDED)); + WT_ASSERT_ALWAYS(session, !F_ISSET(reuse, WT_OVFL_REUSE_JUST_ADDED), + "Attempting to reuse dirty overflow record"); if (WT_VERBOSE_ISSET(session, WT_VERB_OVERFLOW)) WT_RET(__ovfl_reuse_verbose(session, page, reuse, "free")); diff --git a/src/third_party/wiredtiger/src/reconcile/rec_visibility.c b/src/third_party/wiredtiger/src/reconcile/rec_visibility.c index 9c40e3e5af1..913a0d949fd 100644 --- a/src/third_party/wiredtiger/src/reconcile/rec_visibility.c +++ b/src/third_party/wiredtiger/src/reconcile/rec_visibility.c @@ -18,12 +18,12 @@ __rec_update_save(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_INSERT *ins, WT_ { WT_SAVE_UPD *supd; - /* If nothing is committed, we must restore the update chain. */ - WT_ASSERT(session, onpage_upd != NULL || supd_restore); - /* We can only write a standard update or a modify to the data store. */ - WT_ASSERT(session, + WT_ASSERT_ALWAYS(session, onpage_upd != NULL || supd_restore, + "If nothing is committed the update chain must be restored"); + WT_ASSERT_ALWAYS(session, onpage_upd == NULL || onpage_upd->type == WT_UPDATE_STANDARD || - onpage_upd->type == WT_UPDATE_MODIFY); + onpage_upd->type == WT_UPDATE_MODIFY, + "Only a standard update or a modify can be written to the data store"); /* For columns, ins is never null, so rip == NULL implies ins != NULL. */ WT_ASSERT(session, rip != NULL || ins != NULL); @@ -55,8 +55,9 @@ __rec_append_orig_value( size_t size, total_size; bool tombstone_globally_visible; - WT_ASSERT( - session, upd != NULL && unpack != NULL && unpack->type != WT_CELL_DEL && !unpack->tw.prepare); + WT_ASSERT_ALWAYS(session, + upd != NULL && unpack != NULL && unpack->type != WT_CELL_DEL && !unpack->tw.prepare, + "__rec_append_orig_value requires an onpage, non-prepared update"); append = oldest_upd = tombstone = NULL; total_size = 0; @@ -107,7 +108,7 @@ __rec_append_orig_value( * because we have to do a search for the prepared updates, which can not proceed until eviction * finishes. */ - WT_ASSERT(session, oldest_upd != NULL); + WT_ASSERT_ALWAYS(session, oldest_upd != NULL, "No older updates found on update chain"); /* * Additionally, we need to append a tombstone before the onpage value we're about to append to @@ -313,7 +314,8 @@ __rec_validate_upd_chain(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_UPDATE *s * of the selected update. */ if (select_tw->stop_ts < select_tw->start_ts) { - WT_ASSERT(session, select_tw->stop_ts == WT_TS_NONE); + WT_ASSERT_ALWAYS( + session, select_tw->stop_ts == WT_TS_NONE, "No stop timestamp found for selected update"); WT_STAT_CONN_DATA_INCR(session, cache_eviction_blocked_no_ts_checkpoint_race_2); return (EBUSY); } @@ -337,14 +339,15 @@ __rec_validate_upd_chain(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_UPDATE *s if (upd->txnid == WT_TXN_ABORTED) continue; - /* If we have a prepared update, durable timestamp cannot be out of order. */ - WT_ASSERT(session, + WT_ASSERT_ALWAYS(session, prev_upd->prepare_state == WT_PREPARE_INPROGRESS || - prev_upd->start_ts == prev_upd->durable_ts || prev_upd->durable_ts >= upd->durable_ts); + prev_upd->start_ts == prev_upd->durable_ts || prev_upd->durable_ts >= upd->durable_ts, + "Durable timestamps cannot be out of order for prepared updates"); /* Validate that the updates older than us have older timestamps. */ if (prev_upd->start_ts < upd->start_ts) { - WT_ASSERT(session, prev_upd->start_ts == WT_TS_NONE); + WT_ASSERT_ALWAYS( + session, prev_upd->start_ts == WT_TS_NONE, "Previous update missing start timestamp"); WT_STAT_CONN_DATA_INCR(session, cache_eviction_blocked_no_ts_checkpoint_race_4); return (EBUSY); } @@ -376,15 +379,16 @@ __rec_validate_upd_chain(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_UPDATE *s * reconciliations ondisk value that we will be comparing against. */ if (vpack != NULL && !vpack->tw.prepare) { - /* If we have a prepared update, durable timestamp cannot be out of order. */ - WT_ASSERT(session, + WT_ASSERT_ALWAYS(session, prev_upd->prepare_state == WT_PREPARE_INPROGRESS || prev_upd->start_ts == prev_upd->durable_ts || - prev_upd->durable_ts >= vpack->tw.durable_start_ts); - WT_ASSERT(session, + prev_upd->durable_ts >= vpack->tw.durable_start_ts, + "Durable timestamps cannot be out of order for prepared updates"); + WT_ASSERT_ALWAYS(session, prev_upd->prepare_state == WT_PREPARE_INPROGRESS || prev_upd->start_ts == prev_upd->durable_ts || !WT_TIME_WINDOW_HAS_STOP(&vpack->tw) || - prev_upd->durable_ts >= vpack->tw.durable_stop_ts); + prev_upd->durable_ts >= vpack->tw.durable_stop_ts, + "Durable timestamps cannot be out of order for prepared updates"); if (prev_upd->start_ts < vpack->tw.start_ts || (WT_TIME_WINDOW_HAS_STOP(&vpack->tw) && prev_upd->start_ts < vpack->tw.stop_ts)) { WT_ASSERT(session, prev_upd->start_ts == WT_TS_NONE); @@ -433,17 +437,13 @@ __rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_UPDATE *first_upd wt_timestamp_t max_ts; uint64_t max_txn, session_txnid, txnid; bool is_hs_page; -#ifdef HAVE_DIAGNOSTIC bool seen_prepare; -#endif max_ts = WT_TS_NONE; max_txn = WT_TXN_NONE; is_hs_page = F_ISSET(session->dhandle, WT_DHANDLE_HS); session_txnid = WT_SESSION_TXN_SHARED(session)->id; -#ifdef HAVE_DIAGNOSTIC seen_prepare = false; -#endif for (upd = first_upd; upd != NULL; upd = upd->next) { if ((txnid = upd->txnid) == WT_TXN_ABORTED) @@ -495,7 +495,8 @@ __rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_UPDATE *first_upd * can't discard the uncommitted updates. */ if (upd_select->upd != NULL) { - WT_ASSERT(session, WT_IS_METADATA(session->dhandle)); + WT_ASSERT_ALWAYS(session, WT_IS_METADATA(session->dhandle), + "Uncommitted update followed by committed update in a non-metadata file"); return (__wt_set_return(session, EBUSY)); } @@ -507,28 +508,30 @@ __rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_UPDATE *first_upd /* Ignore prepared updates if it is checkpoint. */ if (upd->prepare_state == WT_PREPARE_LOCKED || upd->prepare_state == WT_PREPARE_INPROGRESS) { - WT_ASSERT(session, upd_select->upd == NULL || upd_select->upd->txnid == upd->txnid); + WT_ASSERT_ALWAYS(session, + upd_select->upd == NULL || upd_select->upd->txnid == upd->txnid, + "Cannot have two different prepared transactions active on the same key"); if (F_ISSET(r, WT_REC_CHECKPOINT)) { *upd_memsizep += WT_UPDATE_MEMSIZE(upd); *has_newer_updatesp = true; if (upd->start_ts > max_ts) max_ts = upd->start_ts; -#ifdef HAVE_DIAGNOSTIC seen_prepare = true; -#endif continue; } else { /* * For prepared updates written to the date store in salvage, we write the same - * prepared value to the date store. If there is still content for that key left in + * prepared value to the data store. If there is still content for that key left in * the history store, rollback to stable will bring it back to the data store. * Otherwise, it removes the key. */ - WT_ASSERT(session, + WT_ASSERT_ALWAYS(session, F_ISSET(r, WT_REC_EVICT) || (F_ISSET(r, WT_REC_VISIBILITY_ERR) && - F_ISSET(upd, WT_UPDATE_PREPARE_RESTORED_FROM_DS))); - WT_ASSERT(session, upd->prepare_state == WT_PREPARE_INPROGRESS); + F_ISSET(upd, WT_UPDATE_PREPARE_RESTORED_FROM_DS)), + "rec_upd_select found an in-progress prepared update"); + WT_ASSERT_ALWAYS(session, upd->prepare_state == WT_PREPARE_INPROGRESS, + "rec_upd_select found an in-progress prepared update"); } } @@ -566,10 +569,11 @@ __rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_UPDATE *first_upd * writes the update that is older than a prepared update or we need to first delete the update * from the history store. */ - WT_ASSERT(session, + WT_ASSERT_ALWAYS(session, upd_select->upd == NULL || !F_ISSET(upd_select->upd, WT_UPDATE_HS) || F_ISSET(upd_select->upd, WT_UPDATE_TO_DELETE_FROM_HS) || - (!F_ISSET(r, WT_REC_EVICT) && seen_prepare)); + (!F_ISSET(r, WT_REC_EVICT) && seen_prepare), + "Selected update that has already been written to the history store"); return (0); } @@ -622,7 +626,8 @@ __rec_fill_tw_from_upd_select( WT_ASSERT(session, upd->next == NULL || upd->next->txnid != WT_TXN_ABORTED); upd_select->upd = upd = upd->next; /* We should not see multiple consecutive tombstones. */ - WT_ASSERT(session, upd == NULL || upd->type != WT_UPDATE_TOMBSTONE); + WT_ASSERT_ALWAYS(session, upd == NULL || upd->type != WT_UPDATE_TOMBSTONE, + "Consecutive tombstones found on the update chain"); } } @@ -630,11 +635,10 @@ __rec_fill_tw_from_upd_select( /* The beginning of the validity window is the selected update's time point. */ WT_TIME_WINDOW_SET_START(select_tw, upd); else if (select_tw->stop_ts != WT_TS_NONE || select_tw->stop_txn != WT_TXN_NONE) { - /* We only have a tombstone on the update list. */ - WT_ASSERT(session, tombstone != NULL); - - /* We must have an ondisk value and it can't be a prepared update. */ - WT_ASSERT(session, vpack != NULL && vpack->type != WT_CELL_DEL && !vpack->tw.prepare); + WT_ASSERT_ALWAYS( + session, tombstone != NULL, "The only contents of the update list is a single tombstone"); + WT_ASSERT_ALWAYS(session, vpack != NULL && vpack->type != WT_CELL_DEL && !vpack->tw.prepare, + "No ondisk values found that are not prepared updates"); /* Move the pointer to the last update on the update chain. */ for (last_upd = tombstone; last_upd->next != NULL; last_upd = last_upd->next) @@ -664,10 +668,12 @@ __rec_fill_tw_from_upd_select( * globally visible. In this case, the on page value is not appended. Verify that. */ if (last_upd->next != NULL) { - WT_ASSERT(session, + WT_ASSERT_ALWAYS(session, last_upd->next->txnid == vpack->tw.start_txn && last_upd->next->start_ts == vpack->tw.start_ts && - last_upd->next->type == WT_UPDATE_STANDARD && last_upd->next->next == NULL); + last_upd->next->type == WT_UPDATE_STANDARD && last_upd->next->next == NULL, + "Tombstone is globally visible, but the tombstoned update is on the update " + "chain"); upd_select->upd = last_upd->next; WT_TIME_WINDOW_SET_START(select_tw, last_upd->next); } else { @@ -679,9 +685,11 @@ __rec_fill_tw_from_upd_select( * If the tombstone is aborted concurrently, we should still have appended the * onpage value. */ - WT_ASSERT(session, + WT_ASSERT_ALWAYS(session, tombstone->txnid != WT_TXN_ABORTED && - __wt_txn_upd_visible_all(session, tombstone) && upd_select->upd == NULL); + __wt_txn_upd_visible_all(session, tombstone) && upd_select->upd == NULL, + "Tombstone has been aborted, but the previously tombstoned update is not on " + "the update chain"); upd_select->upd = tombstone; } } else @@ -689,9 +697,10 @@ __rec_fill_tw_from_upd_select( * If the tombstone is restored from the disk or history store, it must have already * been written to the disk image in the previous eviction. */ - WT_ASSERT(session, + WT_ASSERT_ALWAYS(session, upd_select->upd == NULL && vpack->tw.durable_stop_ts == tombstone->durable_ts && - vpack->tw.stop_txn == tombstone->txnid); + vpack->tw.stop_txn == tombstone->txnid, + "Tombstone is restored from disk or history store, but is not in the disk image"); } return (0); @@ -745,22 +754,24 @@ __wt_rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_INSERT *ins, W /* Keep track of the selected update. */ upd = upd_select->upd; - /* Reconciliation should never see an aborted or reserved update. */ - WT_ASSERT( - session, upd == NULL || (upd->txnid != WT_TXN_ABORTED && upd->type != WT_UPDATE_RESERVE)); + WT_ASSERT_ALWAYS(session, + upd == NULL || (upd->txnid != WT_TXN_ABORTED && upd->type != WT_UPDATE_RESERVE), + "Reconciliation should never see an aborted or reserved update"); /* * The checkpoint transaction is special. Make sure we never write metadata updates from a * checkpoint in a concurrent session. */ - WT_ASSERT(session, + WT_ASSERT_ALWAYS(session, !WT_IS_METADATA(session->dhandle) || upd == NULL || upd->txnid == WT_TXN_NONE || upd->txnid != S2C(session)->txn_global.checkpoint_txn_shared.id || - WT_SESSION_IS_CHECKPOINT(session)); + WT_SESSION_IS_CHECKPOINT(session), + "Metadata updates written from a checkpoint in a concurrent session"); /* If all of the updates were aborted, quit. */ if (first_txn_upd == NULL) { - WT_ASSERT(session, upd == NULL); + WT_ASSERT_ALWAYS(session, upd == NULL, + "__wt_rec_upd_select has selected an update when none are present on the update chain"); return (0); } @@ -874,7 +885,8 @@ __wt_rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_INSERT *ins, W /* * Paranoia: check that we didn't choose an update that has since been rolled back. */ - WT_ASSERT(session, upd_select->upd == NULL || upd_select->upd->txnid != WT_TXN_ABORTED); + WT_ASSERT_ALWAYS(session, upd_select->upd == NULL || upd_select->upd->txnid != WT_TXN_ABORTED, + "Updated selected that has since been rolled back"); /* * Returning an update means the original on-page value might be lost, and that's a problem if diff --git a/src/third_party/wiredtiger/src/reconcile/rec_write.c b/src/third_party/wiredtiger/src/reconcile/rec_write.c index 65a7412e03a..0a6a4e7027b 100644 --- a/src/third_party/wiredtiger/src/reconcile/rec_write.c +++ b/src/third_party/wiredtiger/src/reconcile/rec_write.c @@ -51,9 +51,10 @@ __wt_reconcile(WT_SESSION_IMPL *session, WT_REF *ref, WT_SALVAGE_COOKIE *salvage * doesn't apply to checkpoints: there are (rare) cases where we write data at read-uncommitted * isolation. */ - WT_ASSERT(session, + WT_ASSERT_ALWAYS(session, !LF_ISSET(WT_REC_EVICT) || LF_ISSET(WT_REC_VISIBLE_ALL) || - F_ISSET(session->txn, WT_TXN_HAS_SNAPSHOT)); + F_ISSET(session->txn, WT_TXN_HAS_SNAPSHOT), + "Attempting an eviction with transaction visibility and no snapshot"); /* Can't do history store eviction for history store itself or for metadata. */ WT_ASSERT(session, @@ -222,9 +223,7 @@ __reconcile(WT_SESSION_IMPL *session, WT_REF *ref, WT_SALVAGE_COOKIE *salvage, u WT_DECL_RET; WT_PAGE *page; WT_RECONCILE *r; -#ifdef HAVE_DIAGNOSTIC void *addr; -#endif btree = S2BT(session); page = ref->page; @@ -280,9 +279,7 @@ __reconcile(WT_SESSION_IMPL *session, WT_REF *ref, WT_SALVAGE_COOKIE *salvage, u F_ISSET(r, WT_REC_CALL_URGENT) && !r->update_used && r->cache_write_restore) ret = __wt_set_return(session, EBUSY); -#ifdef HAVE_DIAGNOSTIC addr = ref->addr; -#endif /* * If we fail the reconciliation prior to calling __rec_write_wrapup then we can clean up our @@ -292,8 +289,8 @@ __reconcile(WT_SESSION_IMPL *session, WT_REF *ref, WT_SALVAGE_COOKIE *salvage, u * inserting updates to the history store and then failing can leave us in a bad state. */ if (ret != 0) { - /* Make sure that reconciliation doesn't free the page that has been written to disk. */ - WT_ASSERT(session, addr == NULL || ref->addr != NULL); + WT_ASSERT_ALWAYS(session, addr == NULL || ref->addr != NULL, + "Reconciliation trying to free the page that has been written to disk"); WT_IGNORE_RET(__rec_write_err(session, r, page)); WT_IGNORE_RET(__reconcile_post_wrapup(session, r, page, flags, page_lockedp)); /* @@ -408,7 +405,8 @@ __rec_write_page_status(WT_SESSION_IMPL *session, WT_RECONCILE *r) if (__wt_atomic_cas32(&mod->page_state, WT_PAGE_DIRTY_FIRST, WT_PAGE_CLEAN)) __wt_cache_dirty_decr(session, page); else - WT_ASSERT(session, !F_ISSET(r, WT_REC_EVICT)); + WT_ASSERT_ALWAYS( + session, !F_ISSET(r, WT_REC_EVICT), "Page state has been modified during eviction"); } } @@ -468,8 +466,10 @@ __rec_root_write(WT_SESSION_IMPL *session, WT_PAGE *page, uint32_t flags) * There's special error handling required when re-instantiating pages in memory; it's not * needed here, asserted for safety. */ - WT_ASSERT(session, mod->mod_multi[i].supd == NULL); - WT_ASSERT(session, mod->mod_multi[i].disk_image == NULL); + WT_ASSERT_ALWAYS( + session, mod->mod_multi[i].supd == NULL, "Applying unnecessary error handling"); + WT_ASSERT_ALWAYS( + session, mod->mod_multi[i].disk_image == NULL, "Applying unnecessary error handling"); WT_ERR( __wt_multi_to_ref(session, next, &mod->mod_multi[i], &pindex->index[i], NULL, false)); @@ -589,7 +589,8 @@ __rec_init(WT_SESSION_IMPL *session, WT_REF *ref, uint32_t flags, WT_SALVAGE_COO r->last_running = ckpt_txn; } /* When operating on the history store table, we should never try history store eviction. */ - WT_ASSERT(session, !F_ISSET(btree->dhandle, WT_DHANDLE_HS) || !LF_ISSET(WT_REC_HS)); + WT_ASSERT_ALWAYS(session, !F_ISSET(btree->dhandle, WT_DHANDLE_HS) || !LF_ISSET(WT_REC_HS), + "Attempting history store eviction while operating on the history store table"); /* * History store table eviction is configured when eviction gets aggressive, adjust the flags @@ -1538,8 +1539,8 @@ __wt_rec_split_crossing_bnd(WT_SESSION_IMPL *session, WT_RECONCILE *r, size_t ne WT_RET(__rec_split_row_promote(session, r, &r->cur_ptr->min_key, r->page->type)); WT_TIME_AGGREGATE_COPY(&r->cur_ptr->ta_min, &r->cur_ptr->ta); - /* Assert we're not re-entering this code. */ - WT_ASSERT(session, r->cur_ptr->min_offset == 0); + WT_ASSERT_ALWAYS( + session, r->cur_ptr->min_offset == 0, "Trying to re-enter __wt_rec_split_crossing_bnd"); r->cur_ptr->min_offset = WT_PTRDIFF(r->first_free, r->cur_ptr->image.mem); /* All page boundaries reset the dictionary. */ @@ -1569,7 +1570,7 @@ __rec_split_finish_process_prev(WT_SESSION_IMPL *session, WT_RECONCILE *r) size_t combined_size, len_to_move; uint8_t *cur_dsk_start; - WT_ASSERT(session, r->prev_ptr != NULL); + WT_ASSERT_ALWAYS(session, r->prev_ptr != NULL, "Attempting to merge with non-existing chunk"); btree = S2BT(session); cur_ptr = r->cur_ptr; @@ -1990,7 +1991,7 @@ __rec_compression_adjust(WT_SESSION_IMPL *session, uint32_t max, size_t compress * race, minor trickiness so we only read and write the value once. */ WT_ORDERED_READ(current, *adjustp); - WT_ASSERT(session, current >= max); + WT_ASSERT_ALWAYS(session, current >= max, "Writing beyond the max page size"); if (compressed_size > max) { /* @@ -2119,7 +2120,8 @@ __rec_split_write(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_REC_CHUNK *chunk * the wrapup code, and we don't have a code path from here to there.) */ if (last_block && r->multi_next == 1 && __rec_is_checkpoint(session, r)) { - WT_ASSERT(session, r->supd_next == 0); + WT_ASSERT_ALWAYS( + session, r->supd_next == 0, "Attempting to write final block but further updates found"); if (compressed_image == NULL) r->wrapup_checkpoint = &chunk->image; @@ -2151,7 +2153,7 @@ __rec_split_write(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_REC_CHUNK *chunk if (multi->supd_restore) goto copy_image; - WT_ASSERT(session, chunk->entries > 0); + WT_ASSERT_ALWAYS(session, chunk->entries > 0, "Trying to write an empty chunk"); } /* @@ -2504,9 +2506,10 @@ __rec_write_wrapup(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_PAGE *page) * splits can. */ if (F_ISSET(r, WT_REC_IN_MEMORY) || r->multi->supd_restore) { - WT_ASSERT(session, + WT_ASSERT_ALWAYS(session, F_ISSET(r, WT_REC_IN_MEMORY) || - (F_ISSET(r, WT_REC_EVICT) && r->leave_dirty && r->multi->supd_entries != 0)); + (F_ISSET(r, WT_REC_EVICT) && r->leave_dirty && r->multi->supd_entries != 0), + "Attempting a 1-for-1 page swap when there are still updates to write"); goto split; } @@ -2623,7 +2626,8 @@ __rec_hs_wrapup(WT_SESSION_IMPL *session, WT_RECONCILE *r) * Sanity check: Can't insert updates into history store from the history store itself or from * the metadata file. */ - WT_ASSERT(session, !WT_IS_HS(btree->dhandle) && !WT_IS_METADATA(btree->dhandle)); + WT_ASSERT_ALWAYS(session, !WT_IS_HS(btree->dhandle) && !WT_IS_METADATA(btree->dhandle), + "Attempting to write updates from the history store or metadata file into the history store"); /* Flag as unused for non diagnostic builds. */ WT_UNUSED(btree); |