diff options
author | Luke Chen <luke.chen@mongodb.com> | 2020-06-10 16:12:22 +1000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-06-10 06:31:42 +0000 |
commit | bea79f76addfe4b754c8696db029c5b3c762041c (patch) | |
tree | 187e6f29515fcdf6b14526a76071b98d27244ae0 | |
parent | 2a20c87a57afdd20349ed35258b92f998a19603f (diff) | |
download | mongo-bea79f76addfe4b754c8696db029c5b3c762041c.tar.gz |
Import wiredtiger: 154719f3ff736872f67f2b3e9f4d8b396d2d8adf from branch mongodb-4.4r4.4.0-rc9
ref: bf1d78126c..154719f3ff
for: 4.4.0-rc9
WT-6185 Insert full updates into the history store in some corner cases and add a history store c test
WT-6257 Fix rows out-of-order in history store file
WT-6339 Stop creating snapshots for history store cursors
WT-6396 Fix wrong assert when inserting updates to the history store
27 files changed, 745 insertions, 311 deletions
diff --git a/src/third_party/wiredtiger/dist/s_string.ok b/src/third_party/wiredtiger/dist/s_string.ok index 294166060f6..23ba8dc737e 100644 --- a/src/third_party/wiredtiger/dist/s_string.ok +++ b/src/third_party/wiredtiger/dist/s_string.ok @@ -563,6 +563,8 @@ cb ccc ccr cd +ce +ceh centric cfg cfko @@ -1212,6 +1214,7 @@ rwlock sH sHQ sT +sanitizer sanitizers scalability sched diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index 942a0437e0e..7381ba0bcfe 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-4.4", - "commit": "bf1d78126c2ff448b868f199aef22b6c528dd45d" + "commit": "154719f3ff736872f67f2b3e9f4d8b396d2d8adf" } diff --git a/src/third_party/wiredtiger/src/btree/bt_curnext.c b/src/third_party/wiredtiger/src/btree/bt_curnext.c index 4b20a8fa3a2..e6047060faf 100644 --- a/src/third_party/wiredtiger/src/btree/bt_curnext.c +++ b/src/third_party/wiredtiger/src/btree/bt_curnext.c @@ -548,7 +548,8 @@ __wt_cursor_key_order_reset(WT_CURSOR_BTREE *cbt) /* * Clear the last-key returned, it doesn't apply. */ - cbt->lastkey->size = 0; + if (cbt->lastkey != NULL) + cbt->lastkey->size = 0; cbt->lastrecno = WT_RECNO_OOB; } #endif diff --git a/src/third_party/wiredtiger/src/btree/bt_debug.c b/src/third_party/wiredtiger/src/btree/bt_debug.c index dff7010448a..f5a8cf0019e 100644 --- a/src/third_party/wiredtiger/src/btree/bt_debug.c +++ b/src/third_party/wiredtiger/src/btree/bt_debug.c @@ -337,8 +337,6 @@ __wt_debug_addr(WT_SESSION_IMPL *session, const uint8_t *addr, size_t addr_size, WT_DECL_ITEM(buf); WT_DECL_RET; - WT_ASSERT(session, S2BT_SAFE(session) != NULL); - bm = S2BT(session)->bm; WT_RET(__wt_scr_alloc(session, 1024, &buf)); @@ -1022,10 +1020,10 @@ __debug_page(WT_DBG *ds, WT_REF *ref, uint32_t flags) WT_SESSION_IMPL *session; session = ds->session; + WT_RET(__wt_scr_alloc(session, 100, &ds->key)); /* Set up history store support. */ if (!WT_IS_HS(S2BT(session))) { - WT_RET(__wt_scr_alloc(session, 100, &ds->key)); WT_RET(__wt_scr_alloc(session, 0, &ds->hs_key)); WT_RET(__wt_scr_alloc(session, 0, &ds->hs_value)); if (session->hs_cursor == NULL) { diff --git a/src/third_party/wiredtiger/src/btree/row_srch.c b/src/third_party/wiredtiger/src/btree/row_srch.c index 05516281d59..75bf4b9aa44 100644 --- a/src/third_party/wiredtiger/src/btree/row_srch.c +++ b/src/third_party/wiredtiger/src/btree/row_srch.c @@ -242,9 +242,9 @@ __wt_row_search(WT_CURSOR_BTREE *cbt, WT_ITEM *srch_key, bool insert, WT_REF *le * In some cases we expect we're comparing more than a few keys with matching prefixes, so it's * faster to avoid the memory fetches by skipping over those prefixes. That's done by tracking * the length of the prefix match for the lowest and highest keys we compare as we descend the - * tree. + * tree. The high boundary is reset on each new page, the lower boundary is maintained. */ - skiphigh = skiplow = 0; + skiplow = 0; /* * If a cursor repeatedly appends to the tree, compare the search key against the last key on @@ -281,7 +281,7 @@ restart: * Discard the currently held page and restart the search from the root. */ WT_RET(__wt_page_release(session, current, 0)); - skiphigh = skiplow = 0; + skiplow = 0; } /* Search the internal pages of the tree. */ @@ -352,8 +352,7 @@ restart: * parent, the child page's key space will have been truncated, and the values from the * parent's search may be wrong for the child. We only need to reset the high count * because the split-page algorithm truncates the end of the internal page's key space, - * the low count is still correct. We also don't need to clear either count when - * transitioning to a leaf page, a leaf page's key space can't change in flight. + * the low count is still correct. */ skiphigh = 0; @@ -501,7 +500,17 @@ leaf_only: } else if (cmp == 0) goto leaf_match; } - else if (collator == NULL) + else if (collator == NULL) { + /* + * Reset the skipped prefix counts; we'd normally expect the parent's skipped prefix values + * to be larger than the child's values and so we'd only increase them as we walk down the + * tree (in other words, if we can skip N bytes on the parent, we can skip at least N bytes + * on the child). However, leaf pages at the end of the tree can be extended, causing the + * parent's search to be wrong for the child. We only need to reset the high count, the page + * can only be extended so the low count is still correct. + */ + skiphigh = 0; + for (; limit != 0; limit >>= 1) { indx = base + (limit >> 1); rip = page->pg_row + indx; @@ -518,7 +527,7 @@ leaf_only: else goto leaf_match; } - else + } else for (; limit != 0; limit >>= 1) { indx = base + (limit >> 1); rip = page->pg_row + indx; diff --git a/src/third_party/wiredtiger/src/cursor/cur_file.c b/src/third_party/wiredtiger/src/cursor/cur_file.c index e19ee8b32b0..19e69d6dc3e 100644 --- a/src/third_party/wiredtiger/src/cursor/cur_file.c +++ b/src/third_party/wiredtiger/src/cursor/cur_file.c @@ -667,7 +667,7 @@ __curfile_create(WT_SESSION_IMPL *session, WT_CURSOR *owner, const char *cfg[], __wt_cursor_dhandle_incr_use(session); if (session->dhandle->checkpoint != NULL) - F_SET(cbt, WT_CBT_NO_TXN); + F_SET(cbt, WT_CBT_NO_TXN | WT_CBT_NO_TRACKING); if (bulk) { F_SET(cursor, WT_CURSTD_BULK); diff --git a/src/third_party/wiredtiger/src/history/hs.c b/src/third_party/wiredtiger/src/history/hs.c index b55e1a77171..06ac36fc2ac 100644 --- a/src/third_party/wiredtiger/src/history/hs.c +++ b/src/third_party/wiredtiger/src/history/hs.c @@ -202,6 +202,10 @@ __wt_hs_cursor_open(WT_SESSION_IMPL *session) session, ret = __wt_open_cursor(session, WT_HS_URI, NULL, open_cursor_cfg, &cursor)); WT_RET(ret); + /* + * Set the flag to stop creating snapshots for history store cursors + */ + F_SET((WT_CURSOR_BTREE *)cursor, WT_CBT_NO_TXN); /* History store cursors should always ignore tombstones. */ F_SET(cursor, WT_CURSTD_IGNORE_TOMBSTONE); @@ -289,6 +293,9 @@ __hs_row_search(WT_CURSOR_BTREE *hs_cbt, WT_ITEM *srch_key, bool insert) WT_WITH_BTREE(CUR2S(hs_cbt), CUR2BT(hs_cbt), ret = __wt_row_search(hs_cbt, srch_key, insert, NULL, false, NULL)); +#ifdef HAVE_DIAGNOSTIC + WT_TRET(__wt_cursor_key_order_init(hs_cbt)); +#endif return (ret); } @@ -416,10 +423,7 @@ __hs_insert_record_with_btree_int(WT_SESSION_IMPL *session, WT_CURSOR *cursor, W else hs_upd = upd_local; - /* - * Search the page and insert the updates. We expect there will be no existing data: assert that - * we don't find a matching key. - */ + /* Search the page and insert the updates. */ WT_WITH_PAGE_INDEX(session, ret = __hs_row_search(cbt, &cursor->key, true)); WT_ERR(ret); WT_ERR(__wt_hs_modify(cbt, hs_upd)); @@ -503,23 +507,15 @@ __hs_insert_record_with_btree(WT_SESSION_IMPL *session, WT_CURSOR *cursor, WT_BT if (upd->start_ts != WT_TS_NONE) goto done; -/* - * If we inserted an update with no timestamp, we need to delete all history records for that key - * that are further in the history table than us (the key is lexicographically greater). For - * timestamped tables that are occasionally getting a non-timestamped update, that means that all - * timestamped updates should get removed. In the case of non-timestamped tables, that means that - * all updates with higher transaction ids will get removed (which could happen at some more relaxed - * isolation levels). - */ -#ifdef HAVE_DIAGNOSTIC /* - * We need to initialize the last searched key so that we can do key comparisons when we - * begin iterating over the history store. This needs to be done otherwise the subsequent - * "next" calls will blow up. + * If we inserted an update with no timestamp, we need to delete all history records for that + * key that are further in the history table than us (the key is lexicographically greater). For + * timestamped tables that are occasionally getting a non-timestamped update, that means that + * all timestamped updates should get removed. In the case of non-timestamped tables, that means + * that all updates with higher transaction ids will get removed (which could happen at some + * more relaxed isolation levels). We're pointing at the newly inserted update, iterate once + * more to avoid deleting it. */ - WT_ERR(__wt_cursor_key_order_init((WT_CURSOR_BTREE *)cursor)); -#endif - /* We're pointing at the newly inserted update. Iterate once more to avoid deleting it. */ WT_ERR_NOTFOUND_OK(cursor->next(cursor), true); /* No records to delete. */ @@ -560,15 +556,36 @@ __hs_insert_record(WT_SESSION_IMPL *session, WT_CURSOR *cursor, WT_BTREE *btree, } /* - * __hs_calculate_full_value -- - * Calculate the full value of an update. + * __hs_next_upd_full_value -- + * Get the next update and its full value. */ static inline int -__hs_calculate_full_value(WT_SESSION_IMPL *session, WT_ITEM *full_value, WT_UPDATE *upd, - const void *base_full_value, size_t size) +__hs_next_upd_full_value(WT_SESSION_IMPL *session, WT_MODIFY_VECTOR *modifies, + WT_ITEM *older_full_value, uint32_t btree_id, const WT_ITEM *key, WT_ITEM *full_value, + WT_UPDATE **updp) { - if (upd->type == WT_UPDATE_MODIFY) { - WT_RET(__wt_buf_set(session, full_value, base_full_value, size)); + WT_UPDATE *upd; + *updp = NULL; + __wt_modify_vector_pop(modifies, &upd); + if (upd->type == WT_UPDATE_TOMBSTONE) { + if (upd->start_ts == WT_TS_NONE) { + /* We can only delete history store entries that have timestamps. */ + WT_RET(__wt_hs_delete_key_from_ts(session, btree_id, key, 1)); + WT_STAT_CONN_INCR(session, cache_hs_key_truncate_mix_ts); + } + + if (modifies->size == 0) { + WT_ASSERT(session, older_full_value == NULL); + *updp = upd; + return (0); + } + + __wt_modify_vector_pop(modifies, &upd); + WT_ASSERT(session, upd->type == WT_UPDATE_STANDARD); + full_value->data = upd->data; + full_value->size = upd->size; + } else if (upd->type == WT_UPDATE_MODIFY) { + WT_RET(__wt_buf_set(session, full_value, older_full_value->data, older_full_value->size)); WT_RET(__wt_modify_apply_item(session, S2BT(session)->value_format, full_value, upd->data)); } else { WT_ASSERT(session, upd->type == WT_UPDATE_STANDARD); @@ -576,6 +593,7 @@ __hs_calculate_full_value(WT_SESSION_IMPL *session, WT_ITEM *full_value, WT_UPDA full_value->size = upd->size; } + *updp = upd; return (0); } @@ -599,15 +617,14 @@ __wt_hs_insert_updates(WT_SESSION_IMPL *session, WT_PAGE *page, WT_MULTI *multi) WT_MODIFY entries[MAX_REVERSE_MODIFY_NUM]; WT_MODIFY_VECTOR modifies; WT_SAVE_UPD *list; - WT_UPDATE *prev_upd, *second_older_than_prepare, *upd; + WT_UPDATE *prev_upd, *upd; WT_HS_TIME_POINT stop_time_point; wt_off_t hs_size; uint64_t insert_cnt, max_hs_size; uint32_t i; uint8_t *p; int nentries; - bool squashed, track_prepare; - uint8_t upd_count; + bool enable_reverse_modify, squashed; btree = S2BT(session); cursor = session->hs_cursor; @@ -660,9 +677,7 @@ __wt_hs_insert_updates(WT_SESSION_IMPL *session, WT_PAGE *page, WT_MULTI *multi) session, btree, upd = __wt_update_obsolete_check(session, page, list->onpage_upd, true)); __wt_free_update_list(session, &upd); upd = list->onpage_upd; - second_older_than_prepare = NULL; - track_prepare = false; - upd_count = 0; + enable_reverse_modify = true; /* * The algorithm assumes the oldest update on the update chain in memory is either a full @@ -691,67 +706,49 @@ __wt_hs_insert_updates(WT_SESSION_IMPL *session, WT_PAGE *page, WT_MULTI *multi) * tombstone. * 4) We have a single tombstone on the chain, it is simply ignored. */ - for (; upd != NULL; upd = upd->next) { + for (prev_upd = NULL; upd != NULL; prev_upd = upd, upd = upd->next) { if (upd->txnid == WT_TXN_ABORTED) continue; + WT_ERR(__wt_modify_vector_push(&modifies, upd)); /* - * If the update is the second update older than the prepared update and we haven't seen - * a tombstone. Mark the update. + * Always insert full update to the history store if we write a prepared update to the + * data store. */ - if (upd->prepare_state == WT_PREPARE_INPROGRESS) { - /* - * No normal update between prepared updates and the first prepared update cannot be - * a tombstone. - */ - WT_ASSERT(session, (track_prepare && upd_count == 0) || - (!track_prepare && upd->type != WT_UPDATE_TOMBSTONE)); - track_prepare = true; - } else if (track_prepare) { - if (upd->type == WT_UPDATE_TOMBSTONE) { - upd_count = 0; - track_prepare = false; - } else if (upd_count == 0) - ++upd_count; - else { - second_older_than_prepare = upd; - upd_count = 0; - track_prepare = false; - } - } + if (upd->prepare_state == WT_PREPARE_INPROGRESS) + enable_reverse_modify = false; + + /* Always insert full update to the history store if we need to squash the updates. */ + if (prev_upd != NULL && prev_upd->txnid == upd->txnid && + prev_upd->start_ts == upd->start_ts) + enable_reverse_modify = false; + + /* Always insert full update to the history store if the timestamps are not in order. */ + if (prev_upd != NULL && prev_upd->start_ts < upd->start_ts) + enable_reverse_modify = false; /* - * If we've reached a full update and its in the history store we don't need to continue - * as anything beyond this point won't help with calculating deltas. + * If we've reached a full update and it's in the history store we don't need to + * continue as anything beyond this point won't help with calculating deltas. */ if (upd->type == WT_UPDATE_STANDARD && F_ISSET(upd, WT_UPDATE_HS)) break; } - upd = NULL; + prev_upd = upd = NULL; /* Construct the oldest full update. */ WT_ASSERT(session, modifies.size > 0); - __wt_modify_vector_pop(&modifies, &upd); + +#ifdef HAVE_DIAGNOSTIC + __wt_modify_vector_peek(&modifies, &upd); WT_ASSERT(session, upd->type == WT_UPDATE_STANDARD || upd->type == WT_UPDATE_TOMBSTONE); - /* Skip TOMBSTONE at the end of the update chain. */ - if (upd->type == WT_UPDATE_TOMBSTONE) { - if (modifies.size > 0) { - if (upd->start_ts == WT_TS_NONE) { - /* We can only delete history store entries that have timestamps. */ - WT_ERR(__wt_hs_delete_key_from_ts(session, btree->id, key, 1)); - WT_STAT_CONN_INCR(session, cache_hs_key_truncate_mix_ts); - } - __wt_modify_vector_pop(&modifies, &upd); - } else - continue; - } +#endif - WT_ASSERT(session, upd->type == WT_UPDATE_STANDARD); - full_value->data = upd->data; - full_value->size = upd->size; + WT_ERR( + __hs_next_upd_full_value(session, &modifies, NULL, btree->id, key, full_value, &upd)); squashed = false; @@ -766,7 +763,7 @@ __wt_hs_insert_updates(WT_SESSION_IMPL *session, WT_PAGE *page, WT_MULTI *multi) upd = prev_upd) { WT_ASSERT(session, upd->type == WT_UPDATE_STANDARD || upd->type == WT_UPDATE_MODIFY); - __wt_modify_vector_pop(&modifies, &prev_upd); + __wt_modify_vector_peek(&modifies, &prev_upd); /* * For any uncommitted prepared updates written to disk, the stop timestamp of the last @@ -774,8 +771,8 @@ __wt_hs_insert_updates(WT_SESSION_IMPL *session, WT_PAGE *page, WT_MULTI *multi) * removal by checkpoint garbage collection until the data store update is committed. */ if (prev_upd->prepare_state == WT_PREPARE_INPROGRESS) { - WT_ASSERT(session, - list->onpage_upd == prev_upd || list->onpage_upd->txnid == prev_upd->txnid); + WT_ASSERT(session, list->onpage_upd->txnid == prev_upd->txnid && + list->onpage_upd->start_ts == prev_upd->start_ts); stop_time_point.durable_ts = stop_time_point.ts = WT_TS_MAX; stop_time_point.txnid = WT_TXN_MAX; } else { @@ -790,64 +787,38 @@ __wt_hs_insert_updates(WT_SESSION_IMPL *session, WT_PAGE *page, WT_MULTI *multi) stop_time_point.txnid = prev_upd->txnid; } - if (prev_upd->type == WT_UPDATE_TOMBSTONE) { - WT_ASSERT(session, modifies.size > 0); - if (prev_upd->start_ts == WT_TS_NONE) { - /* We can only delete history store entries that have timestamps. */ - WT_ERR(__wt_hs_delete_key_from_ts(session, btree->id, key, 1)); - WT_STAT_CONN_INCR(session, cache_hs_key_truncate_mix_ts); - } - __wt_modify_vector_pop(&modifies, &prev_upd); - WT_ASSERT(session, prev_upd->type == WT_UPDATE_STANDARD); - prev_full_value->data = prev_upd->data; - prev_full_value->size = prev_upd->size; - } else - WT_ERR(__hs_calculate_full_value( - session, prev_full_value, prev_upd, full_value->data, full_value->size)); + WT_ERR(__hs_next_upd_full_value( + session, &modifies, full_value, btree->id, key, prev_full_value, &prev_upd)); - /* - * Skip the updates have the same start timestamp and transaction id - * - * Modifies that have the same start time point as the onpage_upd can be squashed away. - */ - if (upd->start_ts != prev_upd->start_ts || upd->txnid != prev_upd->txnid) { - /* - * Calculate reverse delta. Insert full update for the newest historical record even - * it's a MODIFY. - * - * It is not correct to check prev_upd == list->onpage_upd as we may have aborted - * updates in the middle. - * - * We must insert the first and second updates after a prepared update as full - * values because if the prepared update is aborted, we will remove the first update - * after it from the history store to the update chain. Readers reading the older - * values need a full update as the base value for constructing reverse modifies. - */ - nentries = MAX_REVERSE_MODIFY_NUM; - if (!F_ISSET(upd, WT_UPDATE_HS)) { - if (upd->type == WT_UPDATE_MODIFY && - prev_upd->prepare_state != WT_PREPARE_INPROGRESS && - (second_older_than_prepare == NULL || upd != second_older_than_prepare) && - __wt_calc_modify(session, prev_full_value, full_value, - prev_full_value->size / 10, entries, &nentries) == 0) { - WT_ERR(__wt_modify_pack(cursor, entries, nentries, &modify_value)); - WT_ERR(__hs_insert_record(session, cursor, btree, key, upd, - WT_UPDATE_MODIFY, modify_value, &stop_time_point)); - __wt_scr_free(session, &modify_value); - } else - WT_ERR(__hs_insert_record(session, cursor, btree, key, upd, - WT_UPDATE_STANDARD, full_value, &stop_time_point)); - - /* Flag the update as now in the history store. */ - F_SET(upd, WT_UPDATE_HS); - ++insert_cnt; - if (squashed) { - WT_STAT_CONN_INCR(session, cache_hs_write_squash); - squashed = false; - } - } - } else + /* Squash the updates from the same transaction. */ + if (upd->start_ts == prev_upd->start_ts && upd->txnid == prev_upd->txnid) { squashed = true; + continue; + } + + if (F_ISSET(upd, WT_UPDATE_HS)) + continue; + + /* Calculate reverse modify. */ + nentries = MAX_REVERSE_MODIFY_NUM; + if (upd->type == WT_UPDATE_MODIFY && enable_reverse_modify && + __wt_calc_modify(session, prev_full_value, full_value, prev_full_value->size / 10, + entries, &nentries) == 0) { + WT_ERR(__wt_modify_pack(cursor, entries, nentries, &modify_value)); + WT_ERR(__hs_insert_record(session, cursor, btree, key, upd, WT_UPDATE_MODIFY, + modify_value, &stop_time_point)); + __wt_scr_free(session, &modify_value); + } else + WT_ERR(__hs_insert_record(session, cursor, btree, key, upd, WT_UPDATE_STANDARD, + full_value, &stop_time_point)); + + /* Flag the update as now in the history store. */ + F_SET(upd, WT_UPDATE_HS); + ++insert_cnt; + if (squashed) { + WT_STAT_CONN_INCR(session, cache_hs_write_squash); + squashed = false; + } } if (modifies.size > 0) diff --git a/src/third_party/wiredtiger/src/include/cursor.h b/src/third_party/wiredtiger/src/include/cursor.h index e35791e5cb9..95e5c8de1fb 100644 --- a/src/third_party/wiredtiger/src/include/cursor.h +++ b/src/third_party/wiredtiger/src/include/cursor.h @@ -214,10 +214,11 @@ struct __wt_cursor_btree { #define WT_CBT_ITERATE_PREV 0x008u /* Prev iteration configuration */ #define WT_CBT_ITERATE_RETRY_NEXT 0x010u /* Prepare conflict by next. */ #define WT_CBT_ITERATE_RETRY_PREV 0x020u /* Prepare conflict by prev. */ -#define WT_CBT_NO_TXN 0x040u /* Non-txn cursor (e.g. a checkpoint) */ -#define WT_CBT_READ_ONCE 0x080u /* Page in with WT_READ_WONT_NEED */ -#define WT_CBT_SEARCH_SMALLEST 0x100u /* Row-store: small-key insert list */ -#define WT_CBT_VAR_ONPAGE_MATCH 0x200u /* Var-store: on-page recno match */ +#define WT_CBT_NO_TRACKING 0x040u /* Non tracking cursor. */ +#define WT_CBT_NO_TXN 0x080u /* Non-txn cursor (e.g. a checkpoint) */ +#define WT_CBT_READ_ONCE 0x100u /* Page in with WT_READ_WONT_NEED */ +#define WT_CBT_SEARCH_SMALLEST 0x200u /* Row-store: small-key insert list */ +#define WT_CBT_VAR_ONPAGE_MATCH 0x400u /* Var-store: on-page recno match */ /* AUTOMATIC FLAG VALUE GENERATION STOP */ #define WT_CBT_POSITION_MASK /* Flags associated with position */ \ diff --git a/src/third_party/wiredtiger/src/include/cursor.i b/src/third_party/wiredtiger/src/include/cursor.i index 362efea63a9..99354198433 100644 --- a/src/third_party/wiredtiger/src/include/cursor.i +++ b/src/third_party/wiredtiger/src/include/cursor.i @@ -173,13 +173,9 @@ __cursor_enter(WT_SESSION_IMPL *session) static inline void __cursor_leave(WT_SESSION_IMPL *session) { - /* - * Decrement the count of active cursors in the session. When that goes to zero, there are no - * active cursors, and we can release any snapshot we're holding for read committed isolation. - */ + /* Decrement the count of active cursors in the session. */ WT_ASSERT(session, session->ncursors > 0); - if (--session->ncursors == 0) - __wt_txn_read_last(session); + --session->ncursors; } /* @@ -189,20 +185,32 @@ __cursor_leave(WT_SESSION_IMPL *session) static inline int __cursor_reset(WT_CURSOR_BTREE *cbt) { + WT_CURSOR *cursor; WT_DECL_RET; WT_SESSION_IMPL *session; + cursor = &cbt->iface; session = CUR2S(cbt); +#ifdef HAVE_DIAGNOSTIC + __wt_cursor_key_order_reset(cbt); /* Clear key-order checks. */ +#endif __cursor_pos_clear(cbt); /* If the cursor was active, deactivate it. */ if (F_ISSET(cbt, WT_CBT_ACTIVE)) { - if (!F_ISSET(cbt, WT_CBT_NO_TXN)) + if (!F_ISSET(cbt, WT_CBT_NO_TRACKING)) __cursor_leave(session); F_CLR(cbt, WT_CBT_ACTIVE); } + /* + * When the count of active cursors in the session goes to zero, there are no active cursors, + * and we can release any snapshot we're holding for read committed isolation. + */ + if (session->ncursors == 0 && !F_ISSET(cbt, WT_CBT_NO_TXN)) + __wt_txn_read_last(session); + /* If we're not holding a cursor reference, we're done. */ if (cbt->ref == NULL) return (0); @@ -223,12 +231,15 @@ __cursor_reset(WT_CURSOR_BTREE *cbt) cbt->page_deleted_count = 0; /* - * Release any page references we're holding. This can trigger eviction (e.g., forced eviction - * of big pages), so it's important to do after releasing our snapshot above. - * - * Clear the reference regardless, so we don't try the release twice. + * Release any page references we're holding. This can trigger eviction (for example, forced + * eviction of big pages), so it must happen after releasing our snapshot above. Additionally, + * there's a debug mode where an application can force the eviction in order to test or stress + * the system. Clear the reference so we never try the release twice. */ - ret = __wt_page_release(session, cbt->ref, 0); + if (F_ISSET(cursor, WT_CURSTD_DEBUG_RESET_EVICT)) + WT_TRET_BUSY_OK(__wt_page_release_evict(session, cbt->ref, 0)); + else + ret = __wt_page_release(session, cbt->ref, 0); cbt->ref = NULL; return (ret); @@ -377,12 +388,8 @@ __cursor_func_init(WT_CURSOR_BTREE *cbt, bool reenter) session = CUR2S(cbt); - if (reenter) { -#ifdef HAVE_DIAGNOSTIC - __wt_cursor_key_order_reset(cbt); -#endif + if (reenter) WT_RET(__cursor_reset(cbt)); - } /* * Any old insert position is now invalid. We rely on this being cleared to detect if a new @@ -395,7 +402,7 @@ __cursor_func_init(WT_CURSOR_BTREE *cbt, bool reenter) /* Activate the file cursor. */ if (!F_ISSET(cbt, WT_CBT_ACTIVE)) { - if (!F_ISSET(cbt, WT_CBT_NO_TXN)) + if (!F_ISSET(cbt, WT_CBT_NO_TRACKING)) WT_RET(__cursor_enter(session)); F_SET(cbt, WT_CBT_ACTIVE); } diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h index 4bc55287eef..a8b80658f05 100644 --- a/src/third_party/wiredtiger/src/include/extern.h +++ b/src/third_party/wiredtiger/src/include/extern.h @@ -1700,6 +1700,7 @@ extern void __wt_metadata_free_ckptlist(WT_SESSION *session, WT_CKPT *ckptbase) WT_GCC_FUNC_DECL_ATTRIBUTE((visibility("default"))); extern void __wt_modify_vector_free(WT_MODIFY_VECTOR *modifies); extern void __wt_modify_vector_init(WT_SESSION_IMPL *session, WT_MODIFY_VECTOR *modifies); +extern void __wt_modify_vector_peek(WT_MODIFY_VECTOR *modifies, WT_UPDATE **updp); extern void __wt_modify_vector_pop(WT_MODIFY_VECTOR *modifies, WT_UPDATE **updp); extern void __wt_optrack_flush_buffer(WT_SESSION_IMPL *s); extern void __wt_optrack_record_funcid( diff --git a/src/third_party/wiredtiger/src/include/wiredtiger.in b/src/third_party/wiredtiger/src/include/wiredtiger.in index ec40bc20e70..a3abb6c26af 100644 --- a/src/third_party/wiredtiger/src/include/wiredtiger.in +++ b/src/third_party/wiredtiger/src/include/wiredtiger.in @@ -709,22 +709,23 @@ struct __wt_cursor { #define WT_CURSTD_DEAD 0x000010u #define WT_CURSTD_DEBUG_COPY_KEY 0x000020u #define WT_CURSTD_DEBUG_COPY_VALUE 0x000040u -#define WT_CURSTD_DUMP_HEX 0x000080u -#define WT_CURSTD_DUMP_JSON 0x000100u -#define WT_CURSTD_DUMP_PRETTY 0x000200u -#define WT_CURSTD_DUMP_PRINT 0x000400u -#define WT_CURSTD_IGNORE_TOMBSTONE 0x000800u -#define WT_CURSTD_JOINED 0x001000u -#define WT_CURSTD_KEY_EXT 0x002000u /* Key points out of tree. */ -#define WT_CURSTD_KEY_INT 0x004000u /* Key points into tree. */ -#define WT_CURSTD_META_INUSE 0x008000u -#define WT_CURSTD_OPEN 0x010000u -#define WT_CURSTD_OVERWRITE 0x020000u -#define WT_CURSTD_RAW 0x040000u -#define WT_CURSTD_RAW_SEARCH 0x080000u -#define WT_CURSTD_UPDATE_LOCAL 0x100000u -#define WT_CURSTD_VALUE_EXT 0x200000u /* Value points out of tree. */ -#define WT_CURSTD_VALUE_INT 0x400000u /* Value points into tree. */ +#define WT_CURSTD_DEBUG_RESET_EVICT 0x000080u +#define WT_CURSTD_DUMP_HEX 0x000100u +#define WT_CURSTD_DUMP_JSON 0x000200u +#define WT_CURSTD_DUMP_PRETTY 0x000400u +#define WT_CURSTD_DUMP_PRINT 0x000800u +#define WT_CURSTD_IGNORE_TOMBSTONE 0x001000u +#define WT_CURSTD_JOINED 0x002000u +#define WT_CURSTD_KEY_EXT 0x004000u /* Key points out of tree. */ +#define WT_CURSTD_KEY_INT 0x008000u /* Key points into tree. */ +#define WT_CURSTD_META_INUSE 0x010000u +#define WT_CURSTD_OPEN 0x020000u +#define WT_CURSTD_OVERWRITE 0x040000u +#define WT_CURSTD_RAW 0x080000u +#define WT_CURSTD_RAW_SEARCH 0x100000u +#define WT_CURSTD_UPDATE_LOCAL 0x200000u +#define WT_CURSTD_VALUE_EXT 0x400000u /* Value points out of tree. */ +#define WT_CURSTD_VALUE_INT 0x800000u /* Value points into tree. */ /* AUTOMATIC FLAG VALUE GENERATION STOP */ #define WT_CURSTD_KEY_SET (WT_CURSTD_KEY_EXT | WT_CURSTD_KEY_INT) #define WT_CURSTD_VALUE_SET (WT_CURSTD_VALUE_EXT | WT_CURSTD_VALUE_INT) diff --git a/src/third_party/wiredtiger/src/support/modify.c b/src/third_party/wiredtiger/src/support/modify.c index e428961dfc3..7c9f2a373c3 100644 --- a/src/third_party/wiredtiger/src/support/modify.c +++ b/src/third_party/wiredtiger/src/support/modify.c @@ -505,6 +505,18 @@ __wt_modify_vector_pop(WT_MODIFY_VECTOR *modifies, WT_UPDATE **updp) } /* + * __wt_modify_vector_peek -- + * Peek an update pointer off a modify vector. + */ +void +__wt_modify_vector_peek(WT_MODIFY_VECTOR *modifies, WT_UPDATE **updp) +{ + WT_ASSERT(modifies->session, modifies->size > 0); + + *updp = modifies->listp[modifies->size - 1]; +} + +/* * __wt_modify_vector_free -- * Free any resources associated with a modify vector. If we exceeded the allowed stack space on * the vector and had to fallback to dynamic allocations, we'll be doing a free here. diff --git a/src/third_party/wiredtiger/src/txn/txn.c b/src/third_party/wiredtiger/src/txn/txn.c index 86aeabb9c29..fe92141aa98 100644 --- a/src/third_party/wiredtiger/src/txn/txn.c +++ b/src/third_party/wiredtiger/src/txn/txn.c @@ -765,8 +765,8 @@ __txn_fixup_prepared_update( * If the history update already has a stop time point and we are committing the prepared update * there is no work to do. */ + WT_ERR(__wt_upd_alloc_tombstone(session, &hs_upd, NULL)); if (commit) { - WT_ERR(__wt_upd_alloc_tombstone(session, &hs_upd, NULL)); hs_upd->start_ts = txn->commit_timestamp; hs_upd->durable_ts = txn->durable_timestamp; hs_upd->txnid = txn->id; @@ -784,9 +784,7 @@ __txn_fixup_prepared_update( hs_upd->next->durable_ts = fix_upd->durable_ts; hs_upd->next->start_ts = fix_upd->start_ts; hs_upd->next->txnid = fix_upd->txnid; - } else - /* Remove the restored update from history store. */ - WT_ERR(__wt_upd_alloc_tombstone(session, &hs_upd, NULL)); + } WT_ERR(__wt_hs_modify(hs_cbt, hs_upd)); diff --git a/src/third_party/wiredtiger/test/csuite/Makefile.am b/src/third_party/wiredtiger/test/csuite/Makefile.am index 1aa06aa2094..cf58cecc8a6 100644 --- a/src/third_party/wiredtiger/test/csuite/Makefile.am +++ b/src/third_party/wiredtiger/test/csuite/Makefile.am @@ -148,6 +148,10 @@ test_wt4891_meta_ckptlist_get_alloc_SOURCES=wt4891_meta_ckptlist_get_alloc/main. noinst_PROGRAMS += test_wt4891_meta_ckptlist_get_alloc all_TESTS += test_wt4891_meta_ckptlist_get_alloc +test_wt6185_modify_ts_SOURCES = wt6185_modify_ts/main.c +noinst_PROGRAMS += test_wt6185_modify_ts +all_TESTS += test_wt6185_modify_ts + # Run this during a "make check" smoke test. TESTS = $(all_TESTS) LOG_COMPILER = env top_builddir=$(top_builddir) top_srcdir=$(top_srcdir) $(TEST_WRAPPER) diff --git a/src/third_party/wiredtiger/test/csuite/wt6185_modify_ts/main.c b/src/third_party/wiredtiger/test/csuite/wt6185_modify_ts/main.c new file mode 100644 index 00000000000..fbcf87712e4 --- /dev/null +++ b/src/third_party/wiredtiger/test/csuite/wt6185_modify_ts/main.c @@ -0,0 +1,383 @@ +/*- + * Public Domain 2014-2020 MongoDB, Inc. + * Public Domain 2008-2014 WiredTiger, Inc. + * + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "test_util.h" + +extern int __wt_optind; +extern char *__wt_optarg; + +#define KEYNO 50 +#define MAX_MODIFY_ENTRIES 5 +#define MAX_OPS 25 +#define RUNS 250 +#define VALUE_SIZE 80 + +static WT_RAND_STATE rnd; + +static struct { /* List of repeatable operations. */ + uint64_t ts; + char *v; +} list[MAX_OPS]; +static u_int lnext; + +static char *tlist[MAX_OPS * 100]; /* List of traced operations. */ +static u_int tnext; + +static uint64_t ts; /* Current timestamp. */ + +static char key[100], modify_repl[256], tmp[4 * 1024]; + +/* + * trace -- + * Trace an operation. + */ +#define trace(fmt, ...) \ + do { \ + testutil_assert(tnext < WT_ELEMENTS(tlist)); \ + testutil_check(__wt_snprintf(tmp, sizeof(tmp), fmt, __VA_ARGS__)); \ + free(tlist[tnext]); \ + tlist[tnext] = dstrdup(tmp); \ + ++tnext; \ + } while (0) + +/* + * usage -- + * Print usage message and exit. + */ +static void usage(void) WT_GCC_FUNC_DECL_ATTRIBUTE((noreturn)); +static void +usage(void) +{ + fprintf(stderr, "usage: %s [-ce] [-h home] [-S seed]\n", progname); + exit(EXIT_FAILURE); +} + +/* + * cleanup -- + * Discard allocated memory in case it's a sanitizer run. + */ +static void +cleanup(void) +{ + u_int i; + + for (i = 0; i < WT_ELEMENTS(list); ++i) + free(list[i].v); + for (i = 0; i < WT_ELEMENTS(tlist); ++i) + free(tlist[i]); +} + +/* + * mmrand -- + * Return a random value between a min/max pair, inclusive. + */ +static inline uint32_t +mmrand(u_int min, u_int max) +{ + uint32_t v; + u_int range; + + /* + * Test runs with small row counts can easily pass a max of 0 (for example, "g.rows / 20"). + * Avoid the problem. + */ + if (max <= min) + return (min); + + v = __wt_random(&rnd); + range = (max - min) + 1; + v %= range; + v += min; + return (v); +} + +/* + * modify_repl_init -- + * Initialize the replacement information. + */ +static void +modify_repl_init(void) +{ + size_t i; + + for (i = 0; i < sizeof(modify_repl); ++i) + modify_repl[i] = "zyxwvutsrqponmlkjihgfedcba"[i % 26]; +} + +/* + * modify_build -- + * Generate a set of modify vectors. + */ +static void +modify_build(WT_MODIFY *entries, int *nentriesp, int tag) +{ + int i, nentries; + + /* Randomly select a number of byte changes, offsets and lengths. */ + nentries = (int)mmrand(1, MAX_MODIFY_ENTRIES); + for (i = 0; i < nentries; ++i) { + /* + * Take between 0 and 10 bytes from a random spot in the modify data. Replace between 0 and + * 10 bytes in a random spot in the value, but start at least 11 bytes into the buffer so we + * skip leading key information. + */ + entries[i].data.data = modify_repl + mmrand(1, sizeof(modify_repl) - 10); + entries[i].data.size = (size_t)mmrand(0, 10); + entries[i].offset = (size_t)mmrand(15, VALUE_SIZE); + entries[i].size = (size_t)mmrand(0, 10); + trace("modify %d: off=%" WT_SIZET_FMT ", size=%" WT_SIZET_FMT ", data=\"%.*s\"", tag, + entries[i].offset, entries[i].size, (int)entries[i].data.size, + (char *)entries[i].data.data); + } + + *nentriesp = (int)nentries; +} + +/* + * modify -- + * Make two modifications to a record inside a single transaction. + */ +static void +modify(WT_SESSION *session, WT_CURSOR *c) +{ + WT_MODIFY entries[MAX_MODIFY_ENTRIES]; + int cnt, loop, nentries; + const char *v; + + testutil_check(session->begin_transaction(session, "isolation=snapshot")); + + /* Set a read timestamp 90% of the time. */ + if (mmrand(1, 10) != 1) { + testutil_check(__wt_snprintf(tmp, sizeof(tmp), "read_timestamp=%" PRIx64, ts)); + testutil_check(session->timestamp_transaction(session, tmp)); + } + + /* Up to 4 modify operations, 80% chance for each. */ + for (cnt = loop = 1; loop < 5; ++cnt, ++loop) + if (mmrand(1, 10) <= 8) { + modify_build(entries, &nentries, cnt); + c->set_key(c, key); + testutil_check(c->modify(c, entries, nentries)); + } + + /* Commit 90% of the time, else rollback. */ + if (mmrand(1, 10) != 1) { + c->set_key(c, key); + testutil_check(c->search(c)); + testutil_check(c->get_value(c, &v)); + free(list[lnext].v); + list[lnext].v = dstrdup(v); + + trace("modify read-ts=%" PRIu64 ", commit-ts=%" PRIu64, ts, ts + 1); + trace("returned {%s}", v); + + testutil_check(__wt_snprintf(tmp, sizeof(tmp), "commit_timestamp=%" PRIx64, ts + 1)); + testutil_check(session->timestamp_transaction(session, tmp)); + testutil_check(session->commit_transaction(session, NULL)); + + list[lnext].ts = ts + 1; /* Reread at commit timestamp */ + ++lnext; + } else + testutil_check(session->rollback_transaction(session, NULL)); + + ++ts; +} + +/* + * repeat -- + * Reread all previously committed modifications. + */ +static void +repeat(WT_SESSION *session, WT_CURSOR *c) +{ + u_int i; + const char *v; + + for (i = 0; i < lnext; ++i) { + testutil_check(session->begin_transaction(session, "isolation=snapshot")); + testutil_check(__wt_snprintf(tmp, sizeof(tmp), "read_timestamp=%" PRIx64, list[i].ts)); + testutil_check(session->timestamp_transaction(session, tmp)); + + c->set_key(c, key); + testutil_check(c->search(c)); + testutil_check(c->get_value(c, &v)); + + trace("repeat ts=%" PRIu64, list[i].ts); + trace("expected {%s}", list[i].v); + trace(" found {%s}", v); + + testutil_assert(strcmp(v, list[i].v) == 0); + + testutil_check(session->rollback_transaction(session, NULL)); + } +} + +/* + * reset -- + * Force eviction of the underlying page. + */ +static void +evict(WT_CURSOR *c) +{ + trace("%s", "eviction"); + + c->set_key(c, key); + testutil_check(c->search(c)); + F_SET(c, WT_CURSTD_DEBUG_RESET_EVICT); + testutil_check(c->reset(c)); + F_CLR(c, WT_CURSTD_DEBUG_RESET_EVICT); +} + +/* + * trace_die -- + * Dump the trace. + */ +static void +trace_die(void) +{ + u_int i; + + fprintf(stderr, "\n"); + for (i = 0; i < tnext; ++i) + fprintf(stderr, "%s\n", tlist[i]); +} + +#define SET_VALUE(key, value) \ + do { \ + char *__p; \ + memset(value, '.', sizeof(value)); \ + value[sizeof(value) - 1] = '\0'; \ + testutil_check(__wt_snprintf(value, sizeof(value), "%010u.value", (u_int)key)); \ + for (__p = value; *__p != '\0'; ++__p) \ + ; \ + *__p = '.'; \ + } while (0) + +int +main(int argc, char *argv[]) +{ + WT_CONNECTION *conn; + WT_CURSOR *c; + WT_SESSION *session; + u_int i, j; + int ch; + char path[1024], value[VALUE_SIZE]; + const char *home, *v; + bool no_checkpoint, no_eviction; + + (void)testutil_set_progname(argv); + custom_die = trace_die; + + __wt_random_init_seed(NULL, &rnd); + modify_repl_init(); + + no_checkpoint = no_eviction = false; + home = "WT_TEST.wt6185_modify_ts"; + while ((ch = __wt_getopt(progname, argc, argv, "ceh:S:")) != EOF) + switch (ch) { + case 'c': + no_checkpoint = true; + break; + case 'e': + no_eviction = true; + break; + case 'h': + home = __wt_optarg; + break; + case 'S': + rnd.v = strtoul(__wt_optarg, NULL, 10); + break; + default: + usage(); + } + argc -= __wt_optind; + if (argc != 0) + usage(); + + testutil_work_dir_from_path(path, sizeof(path), home); + testutil_make_work_dir(path); + + /* Load 100 records. */ + testutil_check(wiredtiger_open(path, NULL, "create", &conn)); + testutil_check(conn->open_session(conn, NULL, NULL, &session)); + testutil_check(session->create(session, "file:xxx", "key_format=S,value_format=S")); + testutil_check(session->open_cursor(session, "file:xxx", NULL, NULL, &c)); + for (i = 0; i <= 100; ++i) { + testutil_check(__wt_snprintf(key, sizeof(key), "%010u.key", i)); + c->set_key(c, key); + SET_VALUE(i, value); + c->set_value(c, value); + testutil_check(c->insert(c)); + } + + /* Flush, reopen and verify a record. */ + testutil_check(conn->close(conn, NULL)); + testutil_check(wiredtiger_open(path, NULL, NULL, &conn)); + testutil_check(conn->open_session(conn, NULL, NULL, &session)); + testutil_check(session->create(session, "file:xxx", NULL)); + testutil_check(session->open_cursor(session, "file:xxx", NULL, NULL, &c)); + testutil_check(__wt_snprintf(key, sizeof(key), "%010d.key", KEYNO)); + c->set_key(c, key); + testutil_check(c->search(c)); + testutil_check(c->get_value(c, &v)); + SET_VALUE(KEYNO, value); + testutil_assert(strcmp(v, value) == 0); + + testutil_check(conn->set_timestamp(conn, "oldest_timestamp=1")); + + /* + * Loop doing N operations per loop. Each operation consists of modify operations and re-reading + * all previous committed transactions, then optional page evictions and checkpoints. + */ + for (i = 0, ts = 1; i < RUNS; ++i) { + lnext = tnext = 0; + trace("run %u, seed %" PRIu64, i, rnd.v); + + for (j = mmrand(10, MAX_OPS); j > 0; --j) { + modify(session, c); + repeat(session, c); + + /* 20% chance we evict the page. */ + if (!no_eviction && mmrand(1, 10) > 8) + evict(c); + + /* 80% chance we checkpoint. */ + if (!no_checkpoint && mmrand(1, 10) > 8) { + trace("%s", "checkpoint"); + testutil_check(session->checkpoint(session, NULL)); + } + } + testutil_assert(write(STDOUT_FILENO, ".", 1) == 1); + } + testutil_assert(write(STDOUT_FILENO, "\n", 1) == 1); + + testutil_check(conn->close(conn, NULL)); + + cleanup(); + return (EXIT_SUCCESS); +} diff --git a/src/third_party/wiredtiger/test/evergreen.yml b/src/third_party/wiredtiger/test/evergreen.yml index 07f3d98502c..f0354b089c1 100755 --- a/src/third_party/wiredtiger/test/evergreen.yml +++ b/src/third_party/wiredtiger/test/evergreen.yml @@ -1167,6 +1167,21 @@ tasks: ${test_env_vars|} $(pwd)/test/csuite/test_wt4891_meta_ckptlist_get_alloc 2>&1 + - name: csuite-wt6185-modify-ts-test + tags: ["pull_request"] + depends_on: + - name: compile + commands: + - func: "fetch artifacts" + - command: shell.exec + params: + working_dir: "wiredtiger/build_posix" + script: | + set -o errexit + set -o verbose + + ${test_env_vars|} $(pwd)/test/csuite/test_wt6185_modify_ts 2>&1 + - name: csuite-rwlock-test tags: ["pull_request"] depends_on: diff --git a/src/third_party/wiredtiger/test/format/Makefile.am b/src/third_party/wiredtiger/test/format/Makefile.am index 59dd1c8a4d4..8d0c3971494 100644 --- a/src/third_party/wiredtiger/test/format/Makefile.am +++ b/src/third_party/wiredtiger/test/format/Makefile.am @@ -4,8 +4,8 @@ AM_CPPFLAGS +=-I$(top_srcdir)/test/utility noinst_PROGRAMS = t t_SOURCES =\ - backup.c bulk.c checkpoint.c compact.c config.c config_compat.c hs.c kv.c ops.c random.c \ - rebalance.c salvage.c snap.c t.c trace.c util.c wts.c + alter.c backup.c bulk.c checkpoint.c compact.c config.c config_compat.c hs.c kv.c ops.c \ + random.c rebalance.c salvage.c snap.c t.c trace.c util.c wts.c t_LDADD = $(top_builddir)/test/utility/libtest_util.la t_LDADD +=$(top_builddir)/libwiredtiger.la diff --git a/src/third_party/wiredtiger/test/format/alter.c b/src/third_party/wiredtiger/test/format/alter.c new file mode 100644 index 00000000000..2b0d432783c --- /dev/null +++ b/src/third_party/wiredtiger/test/format/alter.c @@ -0,0 +1,76 @@ +/*- + * Public Domain 2014-2020 MongoDB, Inc. + * Public Domain 2008-2014 WiredTiger, Inc. + * + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "format.h" + +/* + * alter -- + * Periodically alter a table's metadata. + */ +WT_THREAD_RET +alter(void *arg) +{ + WT_CONNECTION *conn; + WT_DECL_RET; + WT_SESSION *session; + u_int period; + char buf[32]; + bool access_value; + + (void)(arg); + conn = g.wts_conn; + + /* + * Only alter the access pattern hint. If we alter the cache resident setting we may end up with + * a setting that fills cache and doesn't allow it to be evicted. + */ + access_value = false; + + /* Open a session */ + testutil_check(conn->open_session(conn, NULL, NULL, &session)); + + while (!g.workers_finished) { + period = mmrand(NULL, 1, 10); + + testutil_check(__wt_snprintf( + buf, sizeof(buf), "access_pattern_hint=%s", access_value ? "random" : "none")); + access_value = !access_value; + /* + * Alter can return EBUSY if concurrent with other operations. + */ + while ((ret = session->alter(session, g.uri, buf)) != 0 && ret != EBUSY) + testutil_die(ret, "session.alter"); + while (period > 0 && !g.workers_finished) { + --period; + __wt_sleep(1, 0); + } + } + + testutil_check(session->close(session, NULL)); + return (WT_THREAD_RET_VALUE); +} diff --git a/src/third_party/wiredtiger/test/format/bulk.c b/src/third_party/wiredtiger/test/format/bulk.c index e0694c3c058..02e4cd404bd 100644 --- a/src/third_party/wiredtiger/test/format/bulk.c +++ b/src/third_party/wiredtiger/test/format/bulk.c @@ -87,7 +87,7 @@ wts_load(void) testutil_check(conn->open_session(conn, NULL, NULL, &session)); - tracemsg("%s", "=============== bulk load start"); + trace_msg("%s", "=============== bulk load start"); /* * No bulk load with custom collators, the order of insertion will not match the collation @@ -134,23 +134,21 @@ wts_load(void) cursor->set_key(cursor, keyno); cursor->set_value(cursor, *(uint8_t *)value.data); if (g.trace_all) - tracemsg( - "%-10s %" PRIu32 " {0x%02" PRIx8 "}", "bulk", keyno, ((uint8_t *)value.data)[0]); + trace_msg("bulk %" PRIu32 " {0x%02" PRIx8 "}", keyno, ((uint8_t *)value.data)[0]); break; case VAR: if (!is_bulk) cursor->set_key(cursor, keyno); cursor->set_value(cursor, &value); if (g.trace_all) - tracemsg( - "%-10s %" PRIu32 " {%.*s}", "bulk", keyno, (int)value.size, (char *)value.data); + trace_msg("bulk %" PRIu32 " {%.*s}", keyno, (int)value.size, (char *)value.data); break; case ROW: cursor->set_key(cursor, &key); cursor->set_value(cursor, &value); if (g.trace_all) - tracemsg("%-10s %" PRIu32 " {%.*s}, {%.*s}", "bulk", keyno, (int)key.size, - (char *)key.data, (int)value.size, (char *)value.data); + trace_msg("bulk %" PRIu32 " {%.*s}, {%.*s}", keyno, (int)key.size, (char *)key.data, + (int)value.size, (char *)value.data); break; } @@ -199,7 +197,7 @@ wts_load(void) testutil_check(cursor->close(cursor)); - tracemsg("%s", "=============== bulk load stop"); + trace_msg("%s", "=============== bulk load stop"); testutil_check(session->close(session, NULL)); diff --git a/src/third_party/wiredtiger/test/format/format.h b/src/third_party/wiredtiger/test/format/format.h index 7f5230709fe..af5e16cc60b 100644 --- a/src/third_party/wiredtiger/test/format/format.h +++ b/src/third_party/wiredtiger/test/format/format.h @@ -345,6 +345,8 @@ typedef struct { uint64_t insert_list[256]; /* column-store inserted records */ u_int insert_list_cnt; + WT_ITEM vprint; /* Temporary buffer for printable values */ + #define TINFO_RUNNING 1 /* Running */ #define TINFO_COMPLETE 2 /* Finished */ #define TINFO_JOINED 3 /* Resolved */ diff --git a/src/third_party/wiredtiger/test/format/format.i b/src/third_party/wiredtiger/test/format/format.i index 43055bb2809..97e95c97f0c 100644 --- a/src/third_party/wiredtiger/test/format/format.i +++ b/src/third_party/wiredtiger/test/format/format.i @@ -231,7 +231,8 @@ lock_writeunlock(WT_SESSION *session, RWLOCK *lock) testutil_check(pthread_rwlock_unlock(&lock->l.pthread)); } } -#define tracemsg(fmt, ...) \ + +#define trace_msg(fmt, ...) \ do { \ if (g.trace) { \ struct timespec __ts; \ @@ -242,7 +243,7 @@ lock_writeunlock(WT_SESSION *session, RWLOCK *lock) (uintmax_t)__ts.tv_nsec / WT_THOUSAND, g.tidbuf, __VA_ARGS__)); \ } \ } while (0) -#define traceop(tinfo, fmt, ...) \ +#define trace_op(tinfo, fmt, ...) \ do { \ if (g.trace) { \ struct timespec __ts; \ @@ -253,3 +254,16 @@ lock_writeunlock(WT_SESSION *session, RWLOCK *lock) (uintmax_t)__ts.tv_nsec / WT_THOUSAND, tinfo->tidbuf, __VA_ARGS__)); \ } \ } while (0) + +/* + * trace_bytes -- + * Return a byte string formatted for display. + */ +static inline const char * +trace_bytes(TINFO *tinfo, const uint8_t *data, size_t size) +{ + testutil_check( + __wt_raw_to_esc_hex((WT_SESSION_IMPL *)tinfo->session, data, size, &tinfo->vprint)); + return (tinfo->vprint.mem); +} +#define trace_item(tinfo, buf) trace_bytes(tinfo, (buf)->data, (buf)->size) diff --git a/src/third_party/wiredtiger/test/format/ops.c b/src/third_party/wiredtiger/test/format/ops.c index 82aa22d5f40..0d4692f0472 100644 --- a/src/third_party/wiredtiger/test/format/ops.c +++ b/src/third_party/wiredtiger/test/format/ops.c @@ -154,7 +154,7 @@ operations(u_int ops_seconds, bool lastrun) } testutil_check(conn->open_session(conn, NULL, NULL, &session)); - tracemsg("%s", "=============== thread ops start"); + trace_msg("%s", "=============== thread ops start"); /* Initialize locks to single-thread backups, failures, and timestamp updates. */ lock_init(session, &g.backup_lock); @@ -277,12 +277,14 @@ operations(u_int ops_seconds, bool lastrun) lock_destroy(session, &g.backup_lock); lock_destroy(session, &g.ts_lock); - tracemsg("%s", "=============== thread ops stop"); + trace_msg("%s", "=============== thread ops stop"); testutil_check(session->close(session, NULL)); for (i = 0; i < g.c_threads; ++i) { tinfo = tinfo_list[i]; + __wt_buf_free(NULL, &tinfo->vprint); + /* * Assert records were not removed unless configured to do so, otherwise subsequent runs can * incorrectly report scan errors. @@ -334,7 +336,7 @@ begin_transaction_ts(TINFO *tinfo, u_int *iso_configp) ret = session->timestamp_transaction(session, buf); if (ret == 0) { snap_init(tinfo, ts, true); - traceop(tinfo, "begin snapshot read-ts=%" PRIu64 " (repeatable)", ts); + trace_op(tinfo, "begin snapshot read-ts=%" PRIu64 " (repeatable)", ts); return; } if (ret != EINVAL) @@ -362,7 +364,7 @@ begin_transaction_ts(TINFO *tinfo, u_int *iso_configp) lock_writeunlock(session, &g.ts_lock); snap_init(tinfo, ts, false); - traceop(tinfo, "begin snapshot read-ts=%" PRIu64 " (not repeatable)", ts); + trace_op(tinfo, "begin snapshot read-ts=%" PRIu64 " (not repeatable)", ts); } /* @@ -374,7 +376,7 @@ begin_transaction(TINFO *tinfo, u_int *iso_configp) { WT_SESSION *session; u_int v; - const char *config, *log; + const char *config; session = tinfo->session; @@ -383,18 +385,15 @@ begin_transaction(TINFO *tinfo, u_int *iso_configp) switch (v) { case 1: v = ISOLATION_READ_UNCOMMITTED; - log = "read-uncommitted"; config = "isolation=read-uncommitted"; break; case 2: v = ISOLATION_READ_COMMITTED; - log = "read-committed"; config = "isolation=read-committed"; break; case 3: default: v = ISOLATION_SNAPSHOT; - log = "snapshot"; config = "isolation=snapshot"; break; } @@ -403,7 +402,7 @@ begin_transaction(TINFO *tinfo, u_int *iso_configp) wiredtiger_begin_transaction(session, config); snap_init(tinfo, WT_TS_NONE, false); - traceop(tinfo, "begin %s", log); + trace_op(tinfo, "begin %s", config); } /* @@ -442,7 +441,7 @@ commit_transaction(TINFO *tinfo, bool prepared) /* Remember our oldest commit timestamp. */ tinfo->commit_ts = ts; - traceop( + trace_op( tinfo, "commit read-ts=%" PRIu64 ", commit-ts=%" PRIu64, tinfo->read_ts, tinfo->commit_ts); } @@ -461,7 +460,7 @@ rollback_transaction(TINFO *tinfo) testutil_check(session->rollback_transaction(session, NULL)); - traceop(tinfo, "abort read-ts=%" PRIu64, tinfo->read_ts); + trace_op(tinfo, "abort read-ts=%" PRIu64, tinfo->read_ts); } /* @@ -497,7 +496,7 @@ prepare_transaction(TINFO *tinfo) testutil_check(__wt_snprintf(buf, sizeof(buf), "prepare_timestamp=%" PRIx64, ts)); ret = session->prepare_transaction(session, buf); - traceop(tinfo, "prepare ts=%" PRIu64, ts); + trace_op(tinfo, "prepare ts=%" PRIu64, ts); lock_writeunlock(session, &g.ts_lock); @@ -1130,20 +1129,17 @@ read_row_worker( switch (g.type) { case FIX: if (tinfo == NULL && g.trace_all) - tracemsg("%-10s%" PRIu64 " {0x%02x}", "read", keyno, ((char *)value->data)[0]); + trace_msg("read %" PRIu64 " {0x%02x}", keyno, ((char *)value->data)[0]); if (tinfo != NULL) - traceop( - tinfo, "%-10s%" PRIu64 " {0x%02x}", "read", keyno, ((char *)value->data)[0]); + trace_op(tinfo, "read %" PRIu64 " {0x%02x}", keyno, ((char *)value->data)[0]); break; case ROW: case VAR: if (tinfo == NULL && g.trace_all) - tracemsg( - "%-10s%" PRIu64 " {%.*s}", "read", keyno, (int)value->size, (char *)value->data); + trace_msg("read %" PRIu64 " {%.*s}", keyno, (int)value->size, (char *)value->data); if (tinfo != NULL) - traceop(tinfo, "%-10s%" PRIu64 " {%.*s}", "read", keyno, (int)value->size, - (char *)value->data); + trace_op(tinfo, "read %" PRIu64 " {%s}", keyno, trace_item(tinfo, value)); break; } @@ -1279,15 +1275,14 @@ order_error_row: if (g.trace_all && ret == 0) switch (g.type) { case FIX: - traceop(tinfo, "%-10s%" PRIu64 " {0x%02x}", which, keyno, ((char *)value.data)[0]); + trace_op(tinfo, "%s %" PRIu64 " {0x%02x}", which, keyno, ((char *)value.data)[0]); break; case ROW: - traceop(tinfo, "%-10s%" PRIu64 " {%.*s}, {%.*s}", which, keyno, (int)key.size, - (char *)key.data, (int)value.size, (char *)value.data); + trace_op(tinfo, "%s %" PRIu64 " {%.*s}, {%s}", which, keyno, (int)key.size, + (char *)key.data, trace_item(tinfo, &value)); break; case VAR: - traceop( - tinfo, "%-10s%" PRIu64 " {%.*s}", which, keyno, (int)value.size, (char *)value.data); + trace_op(tinfo, "%s %" PRIu64 " {%s}", which, keyno, trace_item(tinfo, &value)); break; } @@ -1311,7 +1306,7 @@ row_reserve(TINFO *tinfo, WT_CURSOR *cursor, bool positioned) if ((ret = cursor->reserve(cursor)) != 0) return (ret); - traceop(tinfo, "%-10s%" PRIu64 " {%.*s}", "reserve", tinfo->keyno, (int)tinfo->key->size, + trace_op(tinfo, "reserve %" PRIu64 " {%.*s}", tinfo->keyno, (int)tinfo->key->size, (char *)tinfo->key->data); return (0); @@ -1332,7 +1327,7 @@ col_reserve(TINFO *tinfo, WT_CURSOR *cursor, bool positioned) if ((ret = cursor->reserve(cursor)) != 0) return (ret); - traceop(tinfo, "%-10s%" PRIu64, "reserve", tinfo->keyno); + trace_op(tinfo, "reserve %" PRIu64, tinfo->keyno); return (0); } @@ -1383,8 +1378,8 @@ row_modify(TINFO *tinfo, WT_CURSOR *cursor, bool positioned) testutil_check(cursor->get_value(cursor, tinfo->value)); - traceop(tinfo, "%-10s%" PRIu64 " {%.*s}, {%.*s}", "modify", tinfo->keyno, (int)tinfo->key->size, - (char *)tinfo->key->data, (int)tinfo->value->size, (char *)tinfo->value->data); + trace_op(tinfo, "modify %" PRIu64 " {%.*s}, {%s}", tinfo->keyno, (int)tinfo->key->size, + (char *)tinfo->key->data, trace_item(tinfo, tinfo->value)); return (0); } @@ -1409,8 +1404,7 @@ col_modify(TINFO *tinfo, WT_CURSOR *cursor, bool positioned) testutil_check(cursor->get_value(cursor, tinfo->value)); - traceop(tinfo, "%-10s%" PRIu64 ", {%.*s}", "modify", tinfo->keyno, (int)tinfo->value->size, - (char *)tinfo->value->data); + trace_op(tinfo, "modify %" PRIu64 ", {%s}", tinfo->keyno, trace_item(tinfo, tinfo->value)); return (0); } @@ -1457,7 +1451,7 @@ row_truncate(TINFO *tinfo, WT_CURSOR *cursor) if (ret != 0) return (ret); - traceop(tinfo, "%-10s%" PRIu64 ", %" PRIu64, "truncate", tinfo->keyno, tinfo->last); + trace_op(tinfo, "truncate %" PRIu64 ", %" PRIu64, "truncate", tinfo->keyno, tinfo->last); return (0); } @@ -1499,7 +1493,7 @@ col_truncate(TINFO *tinfo, WT_CURSOR *cursor) if (ret != 0) return (ret); - traceop(tinfo, "%-10s%" PRIu64 "-%" PRIu64, "truncate", tinfo->keyno, tinfo->last); + trace_op(tinfo, "truncate %" PRIu64 "-%" PRIu64, tinfo->keyno, tinfo->last); return (0); } @@ -1523,8 +1517,8 @@ row_update(TINFO *tinfo, WT_CURSOR *cursor, bool positioned) if ((ret = cursor->update(cursor)) != 0) return (ret); - traceop(tinfo, "%-10s%" PRIu64 " {%.*s}, {%.*s}", "update", tinfo->keyno, (int)tinfo->key->size, - (char *)tinfo->key->data, (int)tinfo->value->size, (char *)tinfo->value->data); + trace_op(tinfo, "update %" PRIu64 " {%.*s}, {%s}", tinfo->keyno, (int)tinfo->key->size, + (char *)tinfo->key->data, trace_item(tinfo, tinfo->value)); return (0); } @@ -1550,11 +1544,10 @@ col_update(TINFO *tinfo, WT_CURSOR *cursor, bool positioned) return (ret); if (g.type == FIX) - traceop(tinfo, "%-10s%" PRIu64 " {0x%02" PRIx8 "}", "update", tinfo->keyno, + trace_op(tinfo, "update %" PRIu64 " {0x%02" PRIx8 "}", tinfo->keyno, ((uint8_t *)tinfo->value->data)[0]); else - traceop(tinfo, "%-10s%" PRIu64 " {%.*s}", "update", tinfo->keyno, (int)tinfo->value->size, - (char *)tinfo->value->data); + trace_op(tinfo, "update %" PRIu64 " {%s}", tinfo->keyno, trace_item(tinfo, tinfo->value)); return (0); } @@ -1583,8 +1576,8 @@ row_insert(TINFO *tinfo, WT_CURSOR *cursor, bool positioned) return (ret); /* Log the operation */ - traceop(tinfo, "%-10s%" PRIu64 " {%.*s}, {%.*s}", "insert", tinfo->keyno, (int)tinfo->key->size, - (char *)tinfo->key->data, (int)tinfo->value->size, (char *)tinfo->value->data); + trace_op(tinfo, "insert %" PRIu64 " {%.*s}, {%s}", tinfo->keyno, (int)tinfo->key->size, + (char *)tinfo->key->data, trace_item(tinfo, tinfo->value)); return (0); } @@ -1669,11 +1662,10 @@ col_insert(TINFO *tinfo, WT_CURSOR *cursor) col_insert_add(tinfo); /* Extend the object. */ if (g.type == FIX) - traceop(tinfo, "%-10s%" PRIu64 " {0x%02" PRIx8 "}", "insert", tinfo->keyno, + trace_op(tinfo, "insert %" PRIu64 " {0x%02" PRIx8 "}", tinfo->keyno, ((uint8_t *)tinfo->value->data)[0]); else - traceop(tinfo, "%-10s%" PRIu64 " {%.*s}", "insert", tinfo->keyno, (int)tinfo->value->size, - (char *)tinfo->value->data); + trace_op(tinfo, "insert %" PRIu64 " {%s}", tinfo->keyno, trace_item(tinfo, tinfo->value)); return (0); } @@ -1699,7 +1691,7 @@ row_remove(TINFO *tinfo, WT_CURSOR *cursor, bool positioned) if (ret != 0 && ret != WT_NOTFOUND) return (ret); - traceop(tinfo, "%-10s%" PRIu64, "remove", tinfo->keyno); + trace_op(tinfo, "remove %" PRIu64, tinfo->keyno); return (ret); } @@ -1723,7 +1715,7 @@ col_remove(TINFO *tinfo, WT_CURSOR *cursor, bool positioned) if (ret != 0 && ret != WT_NOTFOUND) return (ret); - traceop(tinfo, "%-10s%" PRIu64, "remove", tinfo->keyno); + trace_op(tinfo, "remove %" PRIu64, tinfo->keyno); return (ret); } diff --git a/src/third_party/wiredtiger/test/format/snap.c b/src/third_party/wiredtiger/test/format/snap.c index 15c82a649fb..3f82e5b6499 100644 --- a/src/third_party/wiredtiger/test/format/snap.c +++ b/src/third_party/wiredtiger/test/format/snap.c @@ -101,22 +101,17 @@ snap_track(TINFO *tinfo, thread_op op) static void print_item_data(const char *tag, const uint8_t *data, size_t size) { - static const char hex[] = "0123456789abcdef"; - u_char ch; + WT_ITEM tmp; - fprintf(stderr, "%s {", tag); - if (g.type == FIX) - fprintf(stderr, "0x%02x", data[0]); - else - for (; size > 0; --size, ++data) { - ch = data[0]; - if (__wt_isprint(ch)) - fprintf(stderr, "%c", (int)ch); - else - fprintf( - stderr, "%x%x", (u_int)hex[(data[0] & 0xf0) >> 4], (u_int)hex[data[0] & 0x0f]); - } - fprintf(stderr, "}\n"); + if (g.type == FIX) { + fprintf(stderr, "%s {0x%02x}\n", tag, data[0]); + return; + } + + memset(&tmp, 0, sizeof(tmp)); + testutil_check(__wt_raw_to_esc_hex(NULL, data, size, &tmp)); + fprintf(stderr, "%s {%s}\n", tag, (char *)tmp.mem); + __wt_buf_free(NULL, &tmp); } /* @@ -481,8 +476,8 @@ snap_repeat_single(WT_CURSOR *cursor, TINFO *tinfo) ret = session->timestamp_transaction(session, buf); if (ret == 0) { - traceop(tinfo, "%-10s%" PRIu64 " ts=%" PRIu64 " {%.*s}", "repeat", snap->keyno, snap->ts, - (int)snap->vsize, (char *)snap->vdata); + trace_op(tinfo, "repeat %" PRIu64 " ts=%" PRIu64 " {%s}", snap->keyno, snap->ts, + trace_bytes(tinfo, snap->vdata, snap->vsize)); /* The only expected error is rollback. */ ret = snap_verify(cursor, tinfo, snap); diff --git a/src/third_party/wiredtiger/test/format/t.c b/src/third_party/wiredtiger/test/format/t.c index 65eb53eb2ac..47748d3efd2 100644 --- a/src/third_party/wiredtiger/test/format/t.c +++ b/src/third_party/wiredtiger/test/format/t.c @@ -404,7 +404,7 @@ usage(void) "\t-q run quietly\n" "\t-R run on an existing database\n" "\t-T all|local\n" - "\t-t log operations\n"); + "\t-t trace operations\n"); config_error(); exit(EXIT_FAILURE); diff --git a/src/third_party/wiredtiger/test/format/util.c b/src/third_party/wiredtiger/test/format/util.c index c8be232e1d5..787488c15b7 100644 --- a/src/third_party/wiredtiger/test/format/util.c +++ b/src/third_party/wiredtiger/test/format/util.c @@ -230,53 +230,6 @@ timestamp(void *arg) } /* - * alter -- - * Periodically alter a table's metadata. - */ -WT_THREAD_RET -alter(void *arg) -{ - WT_CONNECTION *conn; - WT_DECL_RET; - WT_SESSION *session; - u_int period; - char buf[32]; - bool access_value; - - (void)(arg); - conn = g.wts_conn; - - /* - * Only alter the access pattern hint. If we alter the cache resident setting we may end up with - * a setting that fills cache and doesn't allow it to be evicted. - */ - access_value = false; - - /* Open a session */ - testutil_check(conn->open_session(conn, NULL, NULL, &session)); - - while (!g.workers_finished) { - period = mmrand(NULL, 1, 10); - - testutil_check(__wt_snprintf( - buf, sizeof(buf), "access_pattern_hint=%s", access_value ? "random" : "none")); - access_value = !access_value; - /* - * Alter can return EBUSY if concurrent with other operations. - */ - while ((ret = session->alter(session, g.uri, buf)) != 0 && ret != EBUSY) - testutil_die(ret, "session.alter"); - while (period > 0 && !g.workers_finished) { - --period; - __wt_sleep(1, 0); - } - } - - testutil_check(session->close(session, NULL)); - return (WT_THREAD_RET_VALUE); -} - -/* * lock_init -- * Initialize abstract lock that can use either pthread of wt reader-writer locks. */ diff --git a/src/third_party/wiredtiger/test/format/wts.c b/src/third_party/wiredtiger/test/format/wts.c index 9fc7e9be2f5..cc27ec32213 100644 --- a/src/third_party/wiredtiger/test/format/wts.c +++ b/src/third_party/wiredtiger/test/format/wts.c @@ -497,7 +497,7 @@ wts_verify(WT_CONNECTION *conn, const char *tag) track("verify", 0ULL, NULL); testutil_check(conn->open_session(conn, NULL, NULL, &session)); - tracemsg("%s", "=============== verify start"); + trace_msg("%s", "=============== verify start"); /* * Verify can return EBUSY if the handle isn't available. Don't yield and retry, in the case of @@ -506,7 +506,7 @@ wts_verify(WT_CONNECTION *conn, const char *tag) ret = session->verify(session, g.uri, "strict"); testutil_assertfmt(ret == 0 || ret == EBUSY, "session.verify: %s: %s", g.uri, tag); - tracemsg("%s", "=============== verify stop"); + trace_msg("%s", "=============== verify stop"); testutil_check(session->close(session, NULL)); } diff --git a/src/third_party/wiredtiger/test/suite/test_hs08.py b/src/third_party/wiredtiger/test/suite/test_hs08.py index 905cc84db1a..9899842d529 100644 --- a/src/third_party/wiredtiger/test/suite/test_hs08.py +++ b/src/third_party/wiredtiger/test/suite/test_hs08.py @@ -140,7 +140,7 @@ class test_hs08(wttest.WiredTigerTestCase): # Call checkpoint again. self.session.checkpoint('use_timestamp=true') - # Validate that we squashed two modifies. Note that we cant count the exact number + # Validate that we squashed two modifies. Note we can't count the exact number # we squashed, just that we did squash. hs_writes = self.get_stat(stat.conn.cache_write_hs) squashed_write = self.get_stat(stat.conn.cache_hs_write_squash) |