Import wiredtiger: 43475153dc5ed0320b821d22502bd74e5cabc833 from branch mongodb-master (#45033)

Co-authored-by: wt-vendoring-bot <wt-vendoring-bot@mongodb.com>
GitOrigin-RevId: 9b5633edd85a3cb96925e1d9bf186ffa6a43a3ea
This commit is contained in:
wt-vendoring-bot[bot] 2025-12-10 14:43:47 +11:00 committed by MongoDB Bot
parent fc6839b16c
commit 70aa245660
43 changed files with 1385 additions and 1250 deletions

View File

@ -1,11 +1,11 @@
{
"CHECKS": {
"regexp": "^(Revert \")?WT-[0-9]+ ",
"regexp": "^(Revert \")?WT-[0-9]+ [ -~]+$",
"alwaysPassCI": false
},
"MESSAGES": {
"success": "All OK",
"failure": "PR title does not match the regex: \"^(Revert \")?WT-[0-9]+ \"",
"failure": "PR title does not match the regex: \"^(Revert \")?WT-[0-9]+ \" or contains non-ASCII characters",
"notice": ""
}
}

View File

@ -227,6 +227,16 @@ lsm_config = [
removed option, preserved to allow parsing old metadata''', undoc=True),
Config('chunk_size', 'none', r'''
removed option, preserved to allow parsing old metadata''', undoc=True),
Config('merge_custom', '', r'''
removed option, preserved to allow parsing old metadata''',
type='category', undoc=True, subconfig=[
Config('prefix', '', r'''
removed option, preserved to allow parsing old metadata''', undoc=True),
Config('start_generation', '', r'''
removed option, preserved to allow parsing old metadata''', undoc=True),
Config('suffix', '', r'''
removed option, preserved to allow parsing old metadata''', undoc=True),
]),
Config('merge_max', 'none', r'''
removed option, preserved to allow parsing old metadata''', undoc=True),
Config('merge_min', 'none', r'''

View File

@ -59,9 +59,6 @@ WT_CONN_CHECK_PANIC
WT_DEADLOCK
WT_DEBUG_BYTE
WT_DHANDLE_TYPE_NUM
WT_DIAGNOSTIC_DISABLE_ZERO_SIZED_ARRAY
WT_DIAGNOSTIC_POP
WT_DIAGNOSTIC_PUSH
WT_ERR_ASSERT
WT_ERR_ERROR_OK
WT_EXT_FOREACH_OFF

View File

@ -925,7 +925,6 @@ keyedness
keyid
keyids
keylen
keysp
keyv
kp
kv

View File

@ -109,11 +109,14 @@ stat_config = range_config + [
component_config = throttle_config
thread_worker_config = [
transaction_config = [
Config('ops_per_transaction', '', r'''
Defines how many operations a transaction can perform, the range is defined with a minimum
and a maximum and a random number is chosen between the two using a linear distribution.''',
type='category', subconfig=range_config),
]
thread_count = [
Config('thread_count', 0, r'''
Specifies the number of threads that will be used to perform a certain function.''', min=0)
]
@ -134,10 +137,10 @@ background_compact_thread_config = throttle_config + [
Config('free_space_target_mb', '20', r'''
Minimum amount of space in MB recoverable for compaction to proceed.''')
]
custom_operation_thread_config = thread_worker_config + throttle_config + record_config
read_thread_config = thread_worker_config + throttle_config + record_config
remove_thread_config = thread_worker_config + throttle_config
update_insert_thread_config = thread_worker_config + throttle_config + record_config
custom_operation_thread_config = thread_count + transaction_config + throttle_config + record_config
read_thread_config = thread_count + throttle_config + transaction_config + record_config
remove_thread_config = thread_count + transaction_config + throttle_config
update_insert_thread_config = thread_count + transaction_config + throttle_config + record_config
#
# Configuration that applies to the runtime monitor component, this should be a list of statistics

View File

@ -53,7 +53,7 @@ typedef struct {
/* This example stores a fixed size blob in the key provider struct. It is not required. */
MY_CRYPT_DATA *encryption_data;
uint64_t returned_lsn;
uint64_t checkpoint_lsn;
} MY_KEY_PROVIDER;
/*
@ -61,7 +61,7 @@ typedef struct {
* A simple example of set_key call.
*/
static int
my_load_key(WT_KEY_PROVIDER *kp, WT_SESSION *session, const WT_CRYPT_KEYS *keys)
my_load_key(WT_KEY_PROVIDER *kp, WT_SESSION *session, const WT_CRYPT_KEYS *crypt)
{
WT_UNUSED(session);
MY_KEY_PROVIDER *my_kp = (MY_KEY_PROVIDER *)kp;
@ -75,8 +75,10 @@ my_load_key(WT_KEY_PROVIDER *kp, WT_SESSION *session, const WT_CRYPT_KEYS *keys)
free(my_kp->encryption_data);
/* Assign new encryption data. */
memcpy((uint8_t *)encryption_data, keys->data, keys->size);
memcpy((uint8_t *)encryption_data, crypt->keys.data, crypt->keys.size);
my_kp->encryption_data = encryption_data;
my_kp->checkpoint_lsn = crypt->r.lsn;
return (0);
}
@ -85,23 +87,25 @@ my_load_key(WT_KEY_PROVIDER *kp, WT_SESSION *session, const WT_CRYPT_KEYS *keys)
* An simple example of key rotation done on get_key call.
*/
static int
my_get_key(WT_KEY_PROVIDER *kp, WT_SESSION *session, WT_CRYPT_KEYS **keysp)
my_get_key(WT_KEY_PROVIDER *kp, WT_SESSION *session, WT_CRYPT_KEYS *crypt)
{
WT_UNUSED(session);
MY_KEY_PROVIDER *my_kp = (MY_KEY_PROVIDER *)kp;
if ((*keysp = calloc(1, sizeof(WT_CRYPT_KEYS) + sizeof(MY_CRYPT_DATA))) == NULL)
return (ENOMEM);
if (crypt->keys.data == NULL) {
/* First call to get_key: return required size. */
crypt->keys.size = sizeof(MY_CRYPT_DATA);
/* Populate the data field in the WT_CRYPT_KEYS structure. */
MY_CRYPT_DATA *crypt_data = (MY_CRYPT_DATA *)(*keysp)->data;
return (0);
}
/* Second call to get_key: return the new key. */
MY_CRYPT_DATA *crypt_data = (MY_CRYPT_DATA *)crypt->keys.data;
/* Set fields in the MY_CRYPT_DATA structure. */
crypt_data->data = my_kp->encryption_data->data;
crypt_data->id = my_kp->encryption_data->id;
/* Set the WT_CRYPT_KEYS size field to match the allocation. */
(*keysp)->size = sizeof(MY_CRYPT_DATA);
return (0);
}
@ -110,21 +114,31 @@ my_get_key(WT_KEY_PROVIDER *kp, WT_SESSION *session, WT_CRYPT_KEYS **keysp)
* A simple example of on_key_update call.
*/
static int
my_on_key_update(WT_KEY_PROVIDER *kp, WT_SESSION *session, WT_CRYPT_KEYS *keys)
my_on_key_update(WT_KEY_PROVIDER *kp, WT_SESSION *session, const WT_CRYPT_KEYS *crypt)
{
MY_KEY_PROVIDER *my_kp = (MY_KEY_PROVIDER *)kp;
WT_EXTENSION_API *wtext = my_kp->wtext;
/* Check size field to determine that the key was successfully persisted. */
if (keys->size != 0)
my_kp->returned_lsn = keys->r.lsn;
if (crypt->keys.size != 0)
my_kp->checkpoint_lsn = crypt->r.lsn;
else
/* Handle error */
(void)wtext->err_printf(
wtext, session, "on_key_update: %s", wtext->strerror(wtext, session, keys->r.error));
wtext, session, "on_key_update: %s", wtext->strerror(wtext, session, crypt->r.error));
/* Free the allocated key. */
free(keys);
return (0);
}
static int
my_terminate(WT_KEY_PROVIDER *kp, WT_SESSION *session)
{
WT_UNUSED(session);
MY_KEY_PROVIDER *my_kp = (MY_KEY_PROVIDER *)kp;
/* Free any allocated encryption data. */
free(my_kp->encryption_data);
free(my_kp);
return (0);
}
@ -153,6 +167,7 @@ set_my_key_provider(WT_CONNECTION *conn, WT_CONFIG_ARG *config)
kp->load_key = my_load_key;
kp->get_key = my_get_key;
kp->on_key_update = my_on_key_update;
kp->terminate = my_terminate;
error_check(conn->set_key_provider(conn, (WT_KEY_PROVIDER *)my_kp, NULL));
return (0);

View File

@ -275,7 +275,6 @@ resize_item(WT_ITEM *item, size_t new_size)
static void
fill_item(WT_ITEM *item, const void *data, size_t size)
{
memset(item, 0, sizeof(WT_ITEM));
resize_item(item, size);
if (size > 0 && data != nullptr)
memcpy(item->mem, data, size);

View File

@ -2,5 +2,5 @@
"vendor": "wiredtiger",
"github": "wiredtiger/wiredtiger",
"branch": "mongodb-master",
"commit": "f3516cab8124355b74b3cbe10d2bcc3d26187b9e"
"commit": "43475153dc5ed0320b821d22502bd74e5cabc833"
}

View File

@ -105,10 +105,11 @@ __wt_blkcache_read(WT_SESSION_IMPL *session, WT_ITEM *buf, WT_PAGE_BLOCK_META *b
WT_BTREE *btree;
WT_COMPRESSOR *compressor;
WT_DECL_ITEM(etmp);
WT_DECL_ITEM(ip);
WT_DECL_ITEM(ip_orig);
WT_DECL_ITEM(tmp);
WT_DECL_RET;
WT_ENCRYPTOR *encryptor;
WT_ITEM *ip, *ip_orig;
WT_ITEM results[WT_DELTA_LIMIT + 1];
WT_PAGE_BLOCK_META block_meta_tmp;
const WT_PAGE_HEADER *dsk;
@ -125,6 +126,7 @@ __wt_blkcache_read(WT_SESSION_IMPL *session, WT_ITEM *buf, WT_PAGE_BLOCK_META *b
encryptor = btree->kencryptor == NULL ? NULL : btree->kencryptor->encryptor;
blkcache_found = found = false;
skip_cache_put = (blkcache->type == WT_BLKCACHE_UNCONFIGURED);
memset(results, 0, sizeof(results));
results_count = 0;
WT_ASSERT_ALWAYS(session, session->dhandle != NULL, "The block cache requires a dhandle");

View File

@ -613,10 +613,8 @@ __page_merge_deltas_common_merge_loop(WT_SESSION_IMPL *session, WT_CELL_UNPACK_A
hdr = (WT_PAGE_HEADER *)new_image->data;
memset(hdr, 0, sizeof(WT_PAGE_HEADER));
hdr->u.entries = entry_count;
if (row_internal_page) {
if (row_internal_page)
F_SET(hdr, WT_PAGE_FT_UPDATE);
WT_STAT_CONN_DSRC_INCR(session, cache_read_internal_delta);
}
/* Compute final on-disk image size using pointer difference. */
new_image->size = WT_PTRDIFF(p_ptr, new_image->mem);

View File

@ -8,6 +8,11 @@
#include "wt_internal.h"
/*
* Define functions that increment histogram statistics for reconstruction of pages with deltas.
*/
WT_STAT_USECS_HIST_INCR_FUNC(internal_reconstruct, perf_hist_internal_reconstruct_latency)
/*
* __evict_force_check --
* Check if a page matches the criteria for forced eviction.
@ -149,6 +154,7 @@ __page_read_build_full_disk_image(WT_SESSION_IMPL *session, WT_REF *ref, WT_ITEM
WT_DECL_RET;
WT_REF **refs;
size_t refs_entries, incr, i;
uint64_t time_start, time_stop;
WT_PAGE_HEADER *base_dsk = (WT_PAGE_HEADER *)base_image_addr;
refs = NULL;
@ -159,9 +165,15 @@ __page_read_build_full_disk_image(WT_SESSION_IMPL *session, WT_REF *ref, WT_ITEM
if (base_dsk->type == WT_PAGE_ROW_LEAF)
WT_ERR(__wti_page_merge_deltas_with_base_image_leaf(
session, deltas, delta_size, new_image, base_dsk));
else
else {
time_start = __wt_clock(session);
WT_ERR(__wti_page_merge_deltas_with_base_image_int(session, ref, deltas, delta_size, &refs,
&refs_entries, &incr, new_image, base_image_addr));
time_stop = __wt_clock(session);
__wt_stat_usecs_hist_incr_internal_reconstruct(
session, WT_CLOCKDIFF_US(time_stop, time_start));
WT_STAT_CONN_DSRC_INCR(session, cache_read_internal_delta);
}
/* Merge deltas directly with the base image in a single pass. */

File diff suppressed because it is too large Load Diff

View File

@ -244,6 +244,7 @@ __clayered_configure_random(
static int
__clayered_open_stable(WT_CURSOR_LAYERED *clayered, bool leader)
{
WT_CURSOR *c;
WT_DECL_ITEM(random_config);
WT_DECL_ITEM(stable_uri_buf);
WT_DECL_RET;
@ -253,6 +254,7 @@ __clayered_open_stable(WT_CURSOR_LAYERED *clayered, bool leader)
const char *checkpoint_name, *stable_uri;
session = CUR2S(clayered);
c = &clayered->iface;
layered = (WT_LAYERED_TABLE *)clayered->dhandle;
stable_uri = layered->stable_uri;
checkpoint_name = NULL;
@ -300,7 +302,7 @@ __clayered_open_stable(WT_CURSOR_LAYERED *clayered, bool leader)
}
}
ret = __wt_open_cursor(session, stable_uri, &clayered->iface, cfg, &clayered->stable_cursor);
ret = __wt_open_cursor(session, stable_uri, c, cfg, &clayered->stable_cursor);
/* Opening a cursor can return both of these, unfortunately. FIXME-WT-15816. */
if ((ret == ENOENT || ret == WT_NOTFOUND) && !leader)
/*
@ -315,6 +317,9 @@ __clayered_open_stable(WT_CURSOR_LAYERED *clayered, bool leader)
/* Layered cursor is not compatible with cursor_copy config. */
F_CLR(clayered->stable_cursor, WT_CURSTD_DEBUG_COPY_KEY | WT_CURSTD_DEBUG_COPY_VALUE);
if (F_ISSET(c, WT_CURSTD_DEBUG_RESET_EVICT))
F_SET(clayered->stable_cursor, WT_CURSTD_DEBUG_RESET_EVICT);
}
err:
@ -562,12 +567,15 @@ __clayered_open_cursors(WT_SESSION_IMPL *session, WT_CURSOR_LAYERED *clayered, b
if (random_config->size > 0)
ckpt_cfg[1] = random_config->data;
WT_ERR(__wt_open_cursor(
session, layered->ingest_uri, &clayered->iface, ckpt_cfg, &clayered->ingest_cursor));
WT_ERR(
__wt_open_cursor(session, layered->ingest_uri, c, ckpt_cfg, &clayered->ingest_cursor));
F_SET(clayered->ingest_cursor, WT_CURSTD_OVERWRITE | WT_CURSTD_RAW);
/* Layered cursor is not compatible with cursor_copy config. */
F_CLR(clayered->ingest_cursor, WT_CURSTD_DEBUG_COPY_KEY | WT_CURSTD_DEBUG_COPY_VALUE);
if (F_ISSET(c, WT_CURSTD_DEBUG_RESET_EVICT))
F_SET(clayered->ingest_cursor, WT_CURSTD_DEBUG_RESET_EVICT);
}
if (clayered->stable_cursor == NULL) {

View File

@ -97,7 +97,7 @@ __wt_cache_dirty_inuse(WT_CACHE *cache)
uint64_t dirty_inuse;
dirty_inuse = __wt_atomic_load_uint64_relaxed(&cache->bytes_dirty_intl) +
__wt_atomic_load_uint64_relaxed(&cache->bytes_dirty_leaf);
return (__wt_cache_bytes_plus_overhead(cache, __wt_atomic_load_uint64_relaxed(&dirty_inuse)));
return (__wt_cache_bytes_plus_overhead(cache, dirty_inuse));
}
/*
@ -110,8 +110,7 @@ __wt_cache_dirty_inuse_ingest(WT_CACHE *cache)
uint64_t dirty_inuse_ingest;
dirty_inuse_ingest = __wt_atomic_load_uint64_relaxed(&cache->bytes_dirty_intl_ingest) +
__wt_atomic_load_uint64_relaxed(&cache->bytes_dirty_leaf_ingest);
return (
__wt_cache_bytes_plus_overhead(cache, __wt_atomic_load_uint64_relaxed(&dirty_inuse_ingest)));
return (__wt_cache_bytes_plus_overhead(cache, dirty_inuse_ingest));
}
/*
@ -124,8 +123,7 @@ __wt_cache_dirty_inuse_stable(WT_CACHE *cache)
uint64_t dirty_inuse_stable;
dirty_inuse_stable = __wt_atomic_load_uint64_relaxed(&cache->bytes_dirty_intl_stable) +
__wt_atomic_load_uint64_relaxed(&cache->bytes_dirty_leaf_stable);
return (
__wt_cache_bytes_plus_overhead(cache, __wt_atomic_load_uint64_relaxed(&dirty_inuse_stable)));
return (__wt_cache_bytes_plus_overhead(cache, dirty_inuse_stable));
}
/*

View File

@ -165,7 +165,7 @@ WT_CONF_API_DECLARE(WT_SESSION, begin_transaction, 2, 12);
WT_CONF_API_DECLARE(WT_SESSION, checkpoint, 3, 12);
WT_CONF_API_DECLARE(WT_SESSION, commit_transaction, 1, 4);
WT_CONF_API_DECLARE(WT_SESSION, compact, 1, 6);
WT_CONF_API_DECLARE(WT_SESSION, create, 8, 86);
WT_CONF_API_DECLARE(WT_SESSION, create, 9, 90);
WT_CONF_API_DECLARE(WT_SESSION, drop, 1, 5);
WT_CONF_API_DECLARE(WT_SESSION, log_flush, 1, 1);
WT_CONF_API_DECLARE(WT_SESSION, open_cursor, 4, 35);

View File

@ -16,54 +16,55 @@
* API configuration keys: BEGIN
*/
#define WT_CONF_ID_Assert 1ULL
#define WT_CONF_ID_Block_cache 190ULL
#define WT_CONF_ID_Checkpoint 205ULL
#define WT_CONF_ID_Checkpoint_cleanup 208ULL
#define WT_CONF_ID_Chunk_cache 211ULL
#define WT_CONF_ID_Compatibility 213ULL
#define WT_CONF_ID_Debug 125ULL
#define WT_CONF_ID_Debug_mode 215ULL
#define WT_CONF_ID_Block_cache 194ULL
#define WT_CONF_ID_Checkpoint 209ULL
#define WT_CONF_ID_Checkpoint_cleanup 212ULL
#define WT_CONF_ID_Chunk_cache 215ULL
#define WT_CONF_ID_Compatibility 217ULL
#define WT_CONF_ID_Debug 129ULL
#define WT_CONF_ID_Debug_mode 219ULL
#define WT_CONF_ID_Disaggregated 20ULL
#define WT_CONF_ID_Dump_version 127ULL
#define WT_CONF_ID_Dump_version 131ULL
#define WT_CONF_ID_Encryption 22ULL
#define WT_CONF_ID_Eviction 237ULL
#define WT_CONF_ID_File_manager 256ULL
#define WT_CONF_ID_Flush_tier 178ULL
#define WT_CONF_ID_Hash 325ULL
#define WT_CONF_ID_Heuristic_controls 261ULL
#define WT_CONF_ID_History_store 265ULL
#define WT_CONF_ID_Eviction 241ULL
#define WT_CONF_ID_File_manager 260ULL
#define WT_CONF_ID_Flush_tier 182ULL
#define WT_CONF_ID_Hash 329ULL
#define WT_CONF_ID_Heuristic_controls 265ULL
#define WT_CONF_ID_History_store 269ULL
#define WT_CONF_ID_Import 99ULL
#define WT_CONF_ID_Incremental 135ULL
#define WT_CONF_ID_Io_capacity 267ULL
#define WT_CONF_ID_Incremental 139ULL
#define WT_CONF_ID_Io_capacity 271ULL
#define WT_CONF_ID_Live_restore 64ULL
#define WT_CONF_ID_Log 40ULL
#define WT_CONF_ID_Lsm 105ULL
#define WT_CONF_ID_Operation_tracking 277ULL
#define WT_CONF_ID_Page_delta 279ULL
#define WT_CONF_ID_Prefetch 305ULL
#define WT_CONF_ID_Prefetch1 307ULL
#define WT_CONF_ID_Rollback_to_stable 285ULL
#define WT_CONF_ID_Roundup_timestamps 169ULL
#define WT_CONF_ID_Shared_cache 287ULL
#define WT_CONF_ID_Statistics_log 291ULL
#define WT_CONF_ID_Merge_custom 115ULL
#define WT_CONF_ID_Operation_tracking 281ULL
#define WT_CONF_ID_Page_delta 283ULL
#define WT_CONF_ID_Prefetch 309ULL
#define WT_CONF_ID_Prefetch1 311ULL
#define WT_CONF_ID_Rollback_to_stable 289ULL
#define WT_CONF_ID_Roundup_timestamps 173ULL
#define WT_CONF_ID_Shared_cache 291ULL
#define WT_CONF_ID_Statistics_log 295ULL
#define WT_CONF_ID_Tiered_storage 51ULL
#define WT_CONF_ID_Transaction_sync 345ULL
#define WT_CONF_ID_Transaction_sync 349ULL
#define WT_CONF_ID_access_pattern_hint 12ULL
#define WT_CONF_ID_action 88ULL
#define WT_CONF_ID_allocation_size 13ULL
#define WT_CONF_ID_app_eviction_min_cache_fill_ratio 243ULL
#define WT_CONF_ID_app_eviction_min_cache_fill_ratio 247ULL
#define WT_CONF_ID_app_metadata 0ULL
#define WT_CONF_ID_append 85ULL
#define WT_CONF_ID_archive 271ULL
#define WT_CONF_ID_archive 275ULL
#define WT_CONF_ID_auth_token 52ULL
#define WT_CONF_ID_auto_throttle 106ULL
#define WT_CONF_ID_available 337ULL
#define WT_CONF_ID_available 341ULL
#define WT_CONF_ID_background 92ULL
#define WT_CONF_ID_background_compact 216ULL
#define WT_CONF_ID_backup 182ULL
#define WT_CONF_ID_backup_restore_target 308ULL
#define WT_CONF_ID_background_compact 220ULL
#define WT_CONF_ID_backup 186ULL
#define WT_CONF_ID_backup_restore_target 312ULL
#define WT_CONF_ID_bitmap 65ULL
#define WT_CONF_ID_blkcache_eviction_aggression 193ULL
#define WT_CONF_ID_blkcache_eviction_aggression 197ULL
#define WT_CONF_ID_block_allocation 14ULL
#define WT_CONF_ID_block_compressor 15ULL
#define WT_CONF_ID_block_manager 16ULL
@ -75,147 +76,147 @@
#define WT_CONF_ID_bound 89ULL
#define WT_CONF_ID_bucket 53ULL
#define WT_CONF_ID_bucket_prefix 54ULL
#define WT_CONF_ID_buckets 326ULL
#define WT_CONF_ID_buffer_alignment 309ULL
#define WT_CONF_ID_builtin_extension_config 310ULL
#define WT_CONF_ID_bulk 123ULL
#define WT_CONF_ID_cache 183ULL
#define WT_CONF_ID_cache_cursors 301ULL
#define WT_CONF_ID_buckets 330ULL
#define WT_CONF_ID_buffer_alignment 313ULL
#define WT_CONF_ID_builtin_extension_config 314ULL
#define WT_CONF_ID_bulk 127ULL
#define WT_CONF_ID_cache 187ULL
#define WT_CONF_ID_cache_cursors 305ULL
#define WT_CONF_ID_cache_directory 55ULL
#define WT_CONF_ID_cache_max_wait_ms 201ULL
#define WT_CONF_ID_cache_on_checkpoint 191ULL
#define WT_CONF_ID_cache_on_writes 192ULL
#define WT_CONF_ID_cache_overhead 202ULL
#define WT_CONF_ID_cache_max_wait_ms 205ULL
#define WT_CONF_ID_cache_on_checkpoint 195ULL
#define WT_CONF_ID_cache_on_writes 196ULL
#define WT_CONF_ID_cache_overhead 206ULL
#define WT_CONF_ID_cache_resident 17ULL
#define WT_CONF_ID_cache_size 203ULL
#define WT_CONF_ID_cache_stuck_timeout_ms 204ULL
#define WT_CONF_ID_cache_tolerance_for_app_eviction 244ULL
#define WT_CONF_ID_capacity 312ULL
#define WT_CONF_ID_cache_size 207ULL
#define WT_CONF_ID_cache_stuck_timeout_ms 208ULL
#define WT_CONF_ID_cache_tolerance_for_app_eviction 248ULL
#define WT_CONF_ID_capacity 316ULL
#define WT_CONF_ID_checkpoint 60ULL
#define WT_CONF_ID_checkpoint_backup_info 61ULL
#define WT_CONF_ID_checkpoint_cleanup 175ULL
#define WT_CONF_ID_checkpoint_cleanup_obsolete_tw_pages_dirty_max 262ULL
#define WT_CONF_ID_checkpoint_crash_point 176ULL
#define WT_CONF_ID_checkpoint_fail_before_turtle_update 302ULL
#define WT_CONF_ID_checkpoint_cleanup 179ULL
#define WT_CONF_ID_checkpoint_cleanup_obsolete_tw_pages_dirty_max 266ULL
#define WT_CONF_ID_checkpoint_crash_point 180ULL
#define WT_CONF_ID_checkpoint_fail_before_turtle_update 306ULL
#define WT_CONF_ID_checkpoint_lsn 62ULL
#define WT_CONF_ID_checkpoint_meta 74ULL
#define WT_CONF_ID_checkpoint_read_timestamp 126ULL
#define WT_CONF_ID_checkpoint_retention 218ULL
#define WT_CONF_ID_checkpoint_sync 311ULL
#define WT_CONF_ID_checkpoint_use_history 124ULL
#define WT_CONF_ID_checkpoint_wait 117ULL
#define WT_CONF_ID_checkpoint_read_timestamp 130ULL
#define WT_CONF_ID_checkpoint_retention 222ULL
#define WT_CONF_ID_checkpoint_sync 315ULL
#define WT_CONF_ID_checkpoint_use_history 128ULL
#define WT_CONF_ID_checkpoint_wait 121ULL
#define WT_CONF_ID_checksum 18ULL
#define WT_CONF_ID_chunk 288ULL
#define WT_CONF_ID_chunk_cache 269ULL
#define WT_CONF_ID_chunk_cache_evict_trigger 313ULL
#define WT_CONF_ID_chunk 292ULL
#define WT_CONF_ID_chunk_cache 273ULL
#define WT_CONF_ID_chunk_cache_evict_trigger 317ULL
#define WT_CONF_ID_chunk_count_limit 112ULL
#define WT_CONF_ID_chunk_max 113ULL
#define WT_CONF_ID_chunk_size 114ULL
#define WT_CONF_ID_claim_prepared_id 163ULL
#define WT_CONF_ID_close_handle_minimum 257ULL
#define WT_CONF_ID_close_idle_time 258ULL
#define WT_CONF_ID_close_scan_interval 259ULL
#define WT_CONF_ID_claim_prepared_id 167ULL
#define WT_CONF_ID_close_handle_minimum 261ULL
#define WT_CONF_ID_close_idle_time 262ULL
#define WT_CONF_ID_close_scan_interval 263ULL
#define WT_CONF_ID_colgroups 81ULL
#define WT_CONF_ID_collator 6ULL
#define WT_CONF_ID_columns 7ULL
#define WT_CONF_ID_commit_timestamp 2ULL
#define WT_CONF_ID_compare_timestamp 100ULL
#define WT_CONF_ID_compile_configuration_count 318ULL
#define WT_CONF_ID_compressor 330ULL
#define WT_CONF_ID_config 297ULL
#define WT_CONF_ID_config_base 319ULL
#define WT_CONF_ID_configuration 219ULL
#define WT_CONF_ID_consolidate 136ULL
#define WT_CONF_ID_corruption_abort 217ULL
#define WT_CONF_ID_create 320ULL
#define WT_CONF_ID_cross_key 132ULL
#define WT_CONF_ID_cursor_copy 220ULL
#define WT_CONF_ID_cursor_reposition 221ULL
#define WT_CONF_ID_cursors 184ULL
#define WT_CONF_ID_default 338ULL
#define WT_CONF_ID_delta_pct 280ULL
#define WT_CONF_ID_dhandle_buckets 327ULL
#define WT_CONF_ID_compile_configuration_count 322ULL
#define WT_CONF_ID_compressor 334ULL
#define WT_CONF_ID_config 301ULL
#define WT_CONF_ID_config_base 323ULL
#define WT_CONF_ID_configuration 223ULL
#define WT_CONF_ID_consolidate 140ULL
#define WT_CONF_ID_corruption_abort 221ULL
#define WT_CONF_ID_create 324ULL
#define WT_CONF_ID_cross_key 136ULL
#define WT_CONF_ID_cursor_copy 224ULL
#define WT_CONF_ID_cursor_reposition 225ULL
#define WT_CONF_ID_cursors 188ULL
#define WT_CONF_ID_default 342ULL
#define WT_CONF_ID_delta_pct 284ULL
#define WT_CONF_ID_dhandle_buckets 331ULL
#define WT_CONF_ID_dictionary 19ULL
#define WT_CONF_ID_direct_io 321ULL
#define WT_CONF_ID_disagg_address_cookie_optional_field 223ULL
#define WT_CONF_ID_disagg_address_cookie_upgrade 222ULL
#define WT_CONF_ID_do_not_clear_txn_id 151ULL
#define WT_CONF_ID_drop 177ULL
#define WT_CONF_ID_direct_io 325ULL
#define WT_CONF_ID_disagg_address_cookie_optional_field 227ULL
#define WT_CONF_ID_disagg_address_cookie_upgrade 226ULL
#define WT_CONF_ID_do_not_clear_txn_id 155ULL
#define WT_CONF_ID_drop 181ULL
#define WT_CONF_ID_dryrun 93ULL
#define WT_CONF_ID_dump 134ULL
#define WT_CONF_ID_dump_address 152ULL
#define WT_CONF_ID_dump_all_data 153ULL
#define WT_CONF_ID_dump_blocks 154ULL
#define WT_CONF_ID_dump_key_data 155ULL
#define WT_CONF_ID_dump_layout 156ULL
#define WT_CONF_ID_dump_offsets 157ULL
#define WT_CONF_ID_dump_pages 158ULL
#define WT_CONF_ID_dump_tree_shape 159ULL
#define WT_CONF_ID_dump 138ULL
#define WT_CONF_ID_dump_address 156ULL
#define WT_CONF_ID_dump_all_data 157ULL
#define WT_CONF_ID_dump_blocks 158ULL
#define WT_CONF_ID_dump_key_data 159ULL
#define WT_CONF_ID_dump_layout 160ULL
#define WT_CONF_ID_dump_offsets 161ULL
#define WT_CONF_ID_dump_pages 162ULL
#define WT_CONF_ID_dump_tree_shape 163ULL
#define WT_CONF_ID_durable_timestamp 3ULL
#define WT_CONF_ID_early_load 298ULL
#define WT_CONF_ID_early_load 302ULL
#define WT_CONF_ID_enabled 41ULL
#define WT_CONF_ID_entry 299ULL
#define WT_CONF_ID_error_prefix 236ULL
#define WT_CONF_ID_evict_sample_inmem 240ULL
#define WT_CONF_ID_evict_use_softptr 241ULL
#define WT_CONF_ID_eviction 224ULL
#define WT_CONF_ID_eviction_checkpoint_target 248ULL
#define WT_CONF_ID_eviction_checkpoint_ts_ordering 235ULL
#define WT_CONF_ID_eviction_dirty_target 249ULL
#define WT_CONF_ID_eviction_dirty_trigger 250ULL
#define WT_CONF_ID_eviction_obsolete_tw_pages_dirty_max 263ULL
#define WT_CONF_ID_eviction_target 251ULL
#define WT_CONF_ID_eviction_trigger 252ULL
#define WT_CONF_ID_eviction_updates_target 253ULL
#define WT_CONF_ID_eviction_updates_trigger 254ULL
#define WT_CONF_ID_entry 303ULL
#define WT_CONF_ID_error_prefix 240ULL
#define WT_CONF_ID_evict_sample_inmem 244ULL
#define WT_CONF_ID_evict_use_softptr 245ULL
#define WT_CONF_ID_eviction 228ULL
#define WT_CONF_ID_eviction_checkpoint_target 252ULL
#define WT_CONF_ID_eviction_checkpoint_ts_ordering 239ULL
#define WT_CONF_ID_eviction_dirty_target 253ULL
#define WT_CONF_ID_eviction_dirty_trigger 254ULL
#define WT_CONF_ID_eviction_obsolete_tw_pages_dirty_max 267ULL
#define WT_CONF_ID_eviction_target 255ULL
#define WT_CONF_ID_eviction_trigger 256ULL
#define WT_CONF_ID_eviction_updates_target 257ULL
#define WT_CONF_ID_eviction_updates_trigger 258ULL
#define WT_CONF_ID_exclude 94ULL
#define WT_CONF_ID_exclusive 98ULL
#define WT_CONF_ID_exclusive_refreshed 91ULL
#define WT_CONF_ID_extensions 323ULL
#define WT_CONF_ID_extra_diagnostics 255ULL
#define WT_CONF_ID_extensions 327ULL
#define WT_CONF_ID_extra_diagnostics 259ULL
#define WT_CONF_ID_extractor 70ULL
#define WT_CONF_ID_file 137ULL
#define WT_CONF_ID_file_extend 324ULL
#define WT_CONF_ID_file_max 266ULL
#define WT_CONF_ID_file 141ULL
#define WT_CONF_ID_file_extend 328ULL
#define WT_CONF_ID_file_max 270ULL
#define WT_CONF_ID_file_metadata 101ULL
#define WT_CONF_ID_file_wait_ms 210ULL
#define WT_CONF_ID_final_flush 180ULL
#define WT_CONF_ID_flatten_leaf_page_delta 281ULL
#define WT_CONF_ID_file_wait_ms 214ULL
#define WT_CONF_ID_final_flush 184ULL
#define WT_CONF_ID_flatten_leaf_page_delta 285ULL
#define WT_CONF_ID_flush_time 72ULL
#define WT_CONF_ID_flush_timestamp 73ULL
#define WT_CONF_ID_flushed_data_cache_insertion 315ULL
#define WT_CONF_ID_force 118ULL
#define WT_CONF_ID_force_stop 138ULL
#define WT_CONF_ID_force_write_wait 331ULL
#define WT_CONF_ID_flushed_data_cache_insertion 319ULL
#define WT_CONF_ID_force 122ULL
#define WT_CONF_ID_force_stop 142ULL
#define WT_CONF_ID_force_write_wait 335ULL
#define WT_CONF_ID_format 25ULL
#define WT_CONF_ID_free_space_target 95ULL
#define WT_CONF_ID_full_target 194ULL
#define WT_CONF_ID_generation_drain_timeout_ms 260ULL
#define WT_CONF_ID_get 150ULL
#define WT_CONF_ID_granularity 139ULL
#define WT_CONF_ID_handles 185ULL
#define WT_CONF_ID_hashsize 196ULL
#define WT_CONF_ID_hazard_max 328ULL
#define WT_CONF_ID_full_target 198ULL
#define WT_CONF_ID_generation_drain_timeout_ms 264ULL
#define WT_CONF_ID_get 154ULL
#define WT_CONF_ID_granularity 143ULL
#define WT_CONF_ID_handles 189ULL
#define WT_CONF_ID_hashsize 200ULL
#define WT_CONF_ID_hazard_max 332ULL
#define WT_CONF_ID_huffman_key 26ULL
#define WT_CONF_ID_huffman_value 27ULL
#define WT_CONF_ID_id 63ULL
#define WT_CONF_ID_ignore_cache_size 304ULL
#define WT_CONF_ID_ignore_cache_size 308ULL
#define WT_CONF_ID_ignore_in_memory_cache_size 28ULL
#define WT_CONF_ID_ignore_prepare 164ULL
#define WT_CONF_ID_ignore_prepare 168ULL
#define WT_CONF_ID_immutable 71ULL
#define WT_CONF_ID_in_memory 29ULL
#define WT_CONF_ID_inclusive 90ULL
#define WT_CONF_ID_incremental_app_eviction 245ULL
#define WT_CONF_ID_incremental_app_eviction 249ULL
#define WT_CONF_ID_ingest 79ULL
#define WT_CONF_ID_internal_item_max 30ULL
#define WT_CONF_ID_internal_key_max 31ULL
#define WT_CONF_ID_internal_key_truncate 32ULL
#define WT_CONF_ID_internal_page_delta 282ULL
#define WT_CONF_ID_internal_page_delta 286ULL
#define WT_CONF_ID_internal_page_max 33ULL
#define WT_CONF_ID_interval 344ULL
#define WT_CONF_ID_isolation 165ULL
#define WT_CONF_ID_json 292ULL
#define WT_CONF_ID_json_output 270ULL
#define WT_CONF_ID_interval 348ULL
#define WT_CONF_ID_isolation 169ULL
#define WT_CONF_ID_json 296ULL
#define WT_CONF_ID_json_output 274ULL
#define WT_CONF_ID_key_format 34ULL
#define WT_CONF_ID_key_gap 35ULL
#define WT_CONF_ID_keyid 24ULL
@ -223,150 +224,153 @@
#define WT_CONF_ID_last_materialized_lsn 75ULL
#define WT_CONF_ID_leaf_item_max 36ULL
#define WT_CONF_ID_leaf_key_max 37ULL
#define WT_CONF_ID_leaf_page_delta 283ULL
#define WT_CONF_ID_leaf_page_delta 287ULL
#define WT_CONF_ID_leaf_page_max 38ULL
#define WT_CONF_ID_leaf_value_max 39ULL
#define WT_CONF_ID_leak_memory 181ULL
#define WT_CONF_ID_legacy_page_visit_strategy 242ULL
#define WT_CONF_ID_leak_memory 185ULL
#define WT_CONF_ID_legacy_page_visit_strategy 246ULL
#define WT_CONF_ID_local_files_action 76ULL
#define WT_CONF_ID_local_retention 56ULL
#define WT_CONF_ID_lock_wait 119ULL
#define WT_CONF_ID_log 186ULL
#define WT_CONF_ID_log_retention 225ULL
#define WT_CONF_ID_log_size 206ULL
#define WT_CONF_ID_lock_wait 123ULL
#define WT_CONF_ID_log 190ULL
#define WT_CONF_ID_log_retention 229ULL
#define WT_CONF_ID_log_size 210ULL
#define WT_CONF_ID_lose_all_my_data 77ULL
#define WT_CONF_ID_max_consecutive_delta 284ULL
#define WT_CONF_ID_max_percent_overhead 197ULL
#define WT_CONF_ID_max_consecutive_delta 288ULL
#define WT_CONF_ID_max_percent_overhead 201ULL
#define WT_CONF_ID_memory_page_image_max 42ULL
#define WT_CONF_ID_memory_page_max 43ULL
#define WT_CONF_ID_merge_max 115ULL
#define WT_CONF_ID_merge_min 116ULL
#define WT_CONF_ID_metadata 187ULL
#define WT_CONF_ID_merge_max 119ULL
#define WT_CONF_ID_merge_min 120ULL
#define WT_CONF_ID_metadata 191ULL
#define WT_CONF_ID_metadata_file 102ULL
#define WT_CONF_ID_method 209ULL
#define WT_CONF_ID_mmap 333ULL
#define WT_CONF_ID_mmap_all 334ULL
#define WT_CONF_ID_multiprocess 335ULL
#define WT_CONF_ID_method 213ULL
#define WT_CONF_ID_mmap 337ULL
#define WT_CONF_ID_mmap_all 338ULL
#define WT_CONF_ID_multiprocess 339ULL
#define WT_CONF_ID_name 23ULL
#define WT_CONF_ID_nbits 66ULL
#define WT_CONF_ID_next_random 142ULL
#define WT_CONF_ID_next_random_sample_size 143ULL
#define WT_CONF_ID_next_random_seed 144ULL
#define WT_CONF_ID_no_timestamp 166ULL
#define WT_CONF_ID_nvram_path 198ULL
#define WT_CONF_ID_next_random 146ULL
#define WT_CONF_ID_next_random_sample_size 147ULL
#define WT_CONF_ID_next_random_seed 148ULL
#define WT_CONF_ID_no_timestamp 170ULL
#define WT_CONF_ID_nvram_path 202ULL
#define WT_CONF_ID_object_target_size 57ULL
#define WT_CONF_ID_obsolete_tw_btree_max 264ULL
#define WT_CONF_ID_obsolete_tw_btree_max 268ULL
#define WT_CONF_ID_oldest 83ULL
#define WT_CONF_ID_oldest_timestamp 306ULL
#define WT_CONF_ID_on_close 293ULL
#define WT_CONF_ID_operation_timeout_ms 167ULL
#define WT_CONF_ID_oldest_timestamp 310ULL
#define WT_CONF_ID_on_close 297ULL
#define WT_CONF_ID_operation_timeout_ms 171ULL
#define WT_CONF_ID_os_cache_dirty_max 44ULL
#define WT_CONF_ID_os_cache_dirty_pct 272ULL
#define WT_CONF_ID_os_cache_dirty_pct 276ULL
#define WT_CONF_ID_os_cache_max 45ULL
#define WT_CONF_ID_overwrite 86ULL
#define WT_CONF_ID_page_history 226ULL
#define WT_CONF_ID_page_history 230ULL
#define WT_CONF_ID_page_log 21ULL
#define WT_CONF_ID_panic_corrupt 103ULL
#define WT_CONF_ID_path 278ULL
#define WT_CONF_ID_percent_file_in_dram 199ULL
#define WT_CONF_ID_pinned 212ULL
#define WT_CONF_ID_prealloc 273ULL
#define WT_CONF_ID_prealloc_init_count 274ULL
#define WT_CONF_ID_precise_checkpoint 336ULL
#define WT_CONF_ID_prefer_scrub_eviction 246ULL
#define WT_CONF_ID_path 282ULL
#define WT_CONF_ID_percent_file_in_dram 203ULL
#define WT_CONF_ID_pinned 216ULL
#define WT_CONF_ID_prealloc 277ULL
#define WT_CONF_ID_prealloc_init_count 278ULL
#define WT_CONF_ID_precise_checkpoint 340ULL
#define WT_CONF_ID_prefer_scrub_eviction 250ULL
#define WT_CONF_ID_prefix 116ULL
#define WT_CONF_ID_prefix_compression 46ULL
#define WT_CONF_ID_prefix_compression_min 47ULL
#define WT_CONF_ID_prefix_search 87ULL
#define WT_CONF_ID_prepare_timestamp 172ULL
#define WT_CONF_ID_prepared 170ULL
#define WT_CONF_ID_prepared_id 173ULL
#define WT_CONF_ID_preserve_prepared 339ULL
#define WT_CONF_ID_priority 168ULL
#define WT_CONF_ID_quota 289ULL
#define WT_CONF_ID_raw 145ULL
#define WT_CONF_ID_raw_key_value 131ULL
#define WT_CONF_ID_read 171ULL
#define WT_CONF_ID_read_corrupt 160ULL
#define WT_CONF_ID_read_once 146ULL
#define WT_CONF_ID_read_size 329ULL
#define WT_CONF_ID_prepare_timestamp 176ULL
#define WT_CONF_ID_prepared 174ULL
#define WT_CONF_ID_prepared_id 177ULL
#define WT_CONF_ID_preserve_prepared 343ULL
#define WT_CONF_ID_priority 172ULL
#define WT_CONF_ID_quota 293ULL
#define WT_CONF_ID_raw 149ULL
#define WT_CONF_ID_raw_key_value 135ULL
#define WT_CONF_ID_read 175ULL
#define WT_CONF_ID_read_corrupt 164ULL
#define WT_CONF_ID_read_once 150ULL
#define WT_CONF_ID_read_size 333ULL
#define WT_CONF_ID_read_timestamp 4ULL
#define WT_CONF_ID_readonly 67ULL
#define WT_CONF_ID_realloc_exact 227ULL
#define WT_CONF_ID_realloc_malloc 228ULL
#define WT_CONF_ID_recover 332ULL
#define WT_CONF_ID_release 214ULL
#define WT_CONF_ID_release_evict 133ULL
#define WT_CONF_ID_release_evict_page 303ULL
#define WT_CONF_ID_remove 275ULL
#define WT_CONF_ID_remove_files 120ULL
#define WT_CONF_ID_remove_shared 121ULL
#define WT_CONF_ID_realloc_exact 231ULL
#define WT_CONF_ID_realloc_malloc 232ULL
#define WT_CONF_ID_recover 336ULL
#define WT_CONF_ID_release 218ULL
#define WT_CONF_ID_release_evict 137ULL
#define WT_CONF_ID_release_evict_page 307ULL
#define WT_CONF_ID_remove 279ULL
#define WT_CONF_ID_remove_files 124ULL
#define WT_CONF_ID_remove_shared 125ULL
#define WT_CONF_ID_repair 104ULL
#define WT_CONF_ID_require_max 316ULL
#define WT_CONF_ID_require_min 317ULL
#define WT_CONF_ID_reserve 290ULL
#define WT_CONF_ID_require_max 320ULL
#define WT_CONF_ID_require_min 321ULL
#define WT_CONF_ID_reserve 294ULL
#define WT_CONF_ID_role 78ULL
#define WT_CONF_ID_rollback_error 229ULL
#define WT_CONF_ID_rollback_timestamp 174ULL
#define WT_CONF_ID_rollback_error 233ULL
#define WT_CONF_ID_rollback_timestamp 178ULL
#define WT_CONF_ID_run_once 96ULL
#define WT_CONF_ID_salvage 340ULL
#define WT_CONF_ID_secretkey 322ULL
#define WT_CONF_ID_session_max 341ULL
#define WT_CONF_ID_session_scratch_max 342ULL
#define WT_CONF_ID_session_table_cache 343ULL
#define WT_CONF_ID_sessions 188ULL
#define WT_CONF_ID_salvage 344ULL
#define WT_CONF_ID_secretkey 326ULL
#define WT_CONF_ID_session_max 345ULL
#define WT_CONF_ID_session_scratch_max 346ULL
#define WT_CONF_ID_session_table_cache 347ULL
#define WT_CONF_ID_sessions 192ULL
#define WT_CONF_ID_shared 58ULL
#define WT_CONF_ID_size 195ULL
#define WT_CONF_ID_skip_sort_check 147ULL
#define WT_CONF_ID_skip_update_obsolete_check 247ULL
#define WT_CONF_ID_slow_checkpoint 230ULL
#define WT_CONF_ID_size 199ULL
#define WT_CONF_ID_skip_sort_check 151ULL
#define WT_CONF_ID_skip_update_obsolete_check 251ULL
#define WT_CONF_ID_slow_checkpoint 234ULL
#define WT_CONF_ID_source 8ULL
#define WT_CONF_ID_sources 294ULL
#define WT_CONF_ID_sources 298ULL
#define WT_CONF_ID_split_deepen_min_child 48ULL
#define WT_CONF_ID_split_deepen_per_child 49ULL
#define WT_CONF_ID_split_pct 50ULL
#define WT_CONF_ID_src_id 140ULL
#define WT_CONF_ID_src_id 144ULL
#define WT_CONF_ID_stable 80ULL
#define WT_CONF_ID_stable_timestamp 161ULL
#define WT_CONF_ID_start_timestamp 129ULL
#define WT_CONF_ID_statistics 148ULL
#define WT_CONF_ID_storage_path 314ULL
#define WT_CONF_ID_stress_skiplist 231ULL
#define WT_CONF_ID_strict 162ULL
#define WT_CONF_ID_sync 122ULL
#define WT_CONF_ID_system_ram 200ULL
#define WT_CONF_ID_table_logging 232ULL
#define WT_CONF_ID_target 149ULL
#define WT_CONF_ID_terminate 300ULL
#define WT_CONF_ID_this_id 141ULL
#define WT_CONF_ID_threads 286ULL
#define WT_CONF_ID_threads_max 238ULL
#define WT_CONF_ID_threads_min 239ULL
#define WT_CONF_ID_tiered_flush_error_continue 233ULL
#define WT_CONF_ID_stable_timestamp 165ULL
#define WT_CONF_ID_start_generation 117ULL
#define WT_CONF_ID_start_timestamp 133ULL
#define WT_CONF_ID_statistics 152ULL
#define WT_CONF_ID_storage_path 318ULL
#define WT_CONF_ID_stress_skiplist 235ULL
#define WT_CONF_ID_strict 166ULL
#define WT_CONF_ID_suffix 118ULL
#define WT_CONF_ID_sync 126ULL
#define WT_CONF_ID_system_ram 204ULL
#define WT_CONF_ID_table_logging 236ULL
#define WT_CONF_ID_target 153ULL
#define WT_CONF_ID_terminate 304ULL
#define WT_CONF_ID_this_id 145ULL
#define WT_CONF_ID_threads 290ULL
#define WT_CONF_ID_threads_max 242ULL
#define WT_CONF_ID_threads_min 243ULL
#define WT_CONF_ID_tiered_flush_error_continue 237ULL
#define WT_CONF_ID_tiered_object 68ULL
#define WT_CONF_ID_tiers 84ULL
#define WT_CONF_ID_timeout 97ULL
#define WT_CONF_ID_timestamp 295ULL
#define WT_CONF_ID_timestamp_order 130ULL
#define WT_CONF_ID_timing_stress_for_test 296ULL
#define WT_CONF_ID_total 268ULL
#define WT_CONF_ID_txn 189ULL
#define WT_CONF_ID_timestamp 299ULL
#define WT_CONF_ID_timestamp_order 134ULL
#define WT_CONF_ID_timing_stress_for_test 300ULL
#define WT_CONF_ID_total 272ULL
#define WT_CONF_ID_txn 193ULL
#define WT_CONF_ID_type 9ULL
#define WT_CONF_ID_update_restore_evict 234ULL
#define WT_CONF_ID_use_environment 346ULL
#define WT_CONF_ID_use_environment_priv 347ULL
#define WT_CONF_ID_use_timestamp 179ULL
#define WT_CONF_ID_update_restore_evict 238ULL
#define WT_CONF_ID_use_environment 350ULL
#define WT_CONF_ID_use_environment_priv 351ULL
#define WT_CONF_ID_use_timestamp 183ULL
#define WT_CONF_ID_value_format 59ULL
#define WT_CONF_ID_verbose 10ULL
#define WT_CONF_ID_verify_metadata 348ULL
#define WT_CONF_ID_verify_metadata 352ULL
#define WT_CONF_ID_version 69ULL
#define WT_CONF_ID_visible_only 128ULL
#define WT_CONF_ID_wait 207ULL
#define WT_CONF_ID_write_through 349ULL
#define WT_CONF_ID_visible_only 132ULL
#define WT_CONF_ID_wait 211ULL
#define WT_CONF_ID_write_through 353ULL
#define WT_CONF_ID_write_timestamp 5ULL
#define WT_CONF_ID_write_timestamp_usage 11ULL
#define WT_CONF_ID_zero_fill 276ULL
#define WT_CONF_ID_zero_fill 280ULL
#define WT_CONF_ID_COUNT 350
#define WT_CONF_ID_COUNT 354
/*
* API configuration keys: END
*/
@ -540,6 +544,11 @@ static const struct {
uint64_t zero_fill;
} Log;
struct {
struct {
uint64_t prefix;
uint64_t start_generation;
uint64_t suffix;
} Merge_custom;
uint64_t auto_throttle;
uint64_t bloom;
uint64_t bloom_bit_count;
@ -946,6 +955,11 @@ static const struct {
WT_CONF_ID_Log | (WT_CONF_ID_zero_fill << 16),
},
{
{
WT_CONF_ID_Lsm | (WT_CONF_ID_Merge_custom << 16) | (WT_CONF_ID_prefix << 32),
WT_CONF_ID_Lsm | (WT_CONF_ID_Merge_custom << 16) | (WT_CONF_ID_start_generation << 32),
WT_CONF_ID_Lsm | (WT_CONF_ID_Merge_custom << 16) | (WT_CONF_ID_suffix << 32),
},
WT_CONF_ID_Lsm | (WT_CONF_ID_auto_throttle << 16),
WT_CONF_ID_Lsm | (WT_CONF_ID_bloom << 16),
WT_CONF_ID_Lsm | (WT_CONF_ID_bloom_bit_count << 16),

View File

@ -210,9 +210,8 @@ __txn_apply_prepare_state_update(WT_SESSION_IMPL *session, WT_UPDATE *upd, bool
*/
__wt_tsan_suppress_store_uint8_v(&upd->prepare_state, WT_PREPARE_LOCKED);
WT_RELEASE_BARRIER();
/* FIXME-WT-15884: data race around accesses to upd_start_ts and upd_durable_ts */
__wt_tsan_suppress_store_uint64(&upd->upd_start_ts, txn->commit_timestamp);
__wt_tsan_suppress_store_uint64(&upd->upd_durable_ts, txn->durable_timestamp);
__wt_atomic_store_uint64_relaxed(&upd->upd_start_ts, txn->commit_timestamp);
__wt_atomic_store_uint64_relaxed(&upd->upd_durable_ts, txn->durable_timestamp);
__wt_atomic_store_uint8_v_release(&upd->prepare_state, WT_PREPARE_RESOLVED);
} else {
/* Set prepare timestamp and id. */
@ -1364,10 +1363,9 @@ __wt_txn_upd_visible_type(WT_SESSION_IMPL *session, WT_UPDATE *upd)
upd->type == WT_UPDATE_STANDARD))
return (WT_VISIBLE_TRUE);
/* FIXME-WT-15884: data race around accesses to upd_start_ts and upd_durable_ts */
upd_visible =
__wt_txn_visible(session, upd->txnid, __wt_tsan_suppress_load_uint64(&upd->upd_start_ts),
__wt_tsan_suppress_load_uint64(&upd->upd_durable_ts));
__wt_txn_visible(session, upd->txnid, __wt_atomic_load_uint64_relaxed(&upd->upd_start_ts),
__wt_atomic_load_uint64_relaxed(&upd->upd_durable_ts));
/*
* The visibility check is only valid if the update does not change state. If the state does

View File

@ -53,17 +53,6 @@ typedef int64_t wt_off_t;
#define WT_ATTRIBUTE_LIBRARY_VISIBLE __attribute__((visibility("default")))
#endif
#if defined(_MSC_VER)
#define WT_DIAGNOSTIC_PUSH __pragma(warning(push))
#define WT_DIAGNOSTIC_POP __pragma(warning(pop))
/* Disable MSVC warning C4200: nonstandard extension used: zero-sized array in struct/union */
#define WT_DIAGNOSTIC_DISABLE_ZERO_SIZED_ARRAY __pragma(warning(disable : 4200))
#else
#define WT_DIAGNOSTIC_PUSH
#define WT_DIAGNOSTIC_POP
#define WT_DIAGNOSTIC_DISABLE_ZERO_SIZED_ARRAY
#endif
/*!
* @defgroup wt WiredTiger API
* The functions, handles and methods applications use to access and manage
@ -5726,8 +5715,6 @@ struct __wt_page_log {
};
#ifndef SWIG
WT_DIAGNOSTIC_PUSH
WT_DIAGNOSTIC_DISABLE_ZERO_SIZED_ARRAY
/*
* A structure that represents encrypted keys stored by WiredTiger.
*
@ -5744,10 +5731,8 @@ struct __wt_crypt_keys {
uint64_t lsn; /* Returns checkpoint LSN upon success. */
int error; /* Returns error code on failure. */
} r;
size_t size; /* Size of encrypted key data field. */
uint8_t data[]; /* Encrypted keys. */
WT_ITEM keys; /* Encrypted keys. */
};
WT_DIAGNOSTIC_POP
/*!
* Interface for custom key provider services used by applications.
@ -5764,20 +5749,27 @@ struct __wt_key_provider {
*
* @param kp the WT_KEY_PROVIDER instance.
* @param session the current WiredTiger session.
* @param keys the WT_CRYPT_KEYS to hold persisted key information.
* @param crypt the WT_CRYPT_KEYS to hold persisted key information.
*/
int (*load_key)(WT_KEY_PROVIDER *kp, WT_SESSION *session, const WT_CRYPT_KEYS *keys);
int (*load_key)(WT_KEY_PROVIDER *kp, WT_SESSION *session, const WT_CRYPT_KEYS *crypt);
/*!
* Fetch the latest key for checkpoint writes.
*
* The WT_CRYPT_KEYS argument should be set to zero if the key has not changed.
* WiredTiger calls this function with an empty WT_CRYPT_KEYS::keys field to
* fetch the required size of the keys data.
* The WT_CRYPT_KEYS::keys::size member should be set to zero if the key has not changed
* or the valid key size otherwise.
*
* When the key has changed, WiredTiger will allocate the required memory and call this
* function again to fetch the new key. The extension should copy the new key into the
* WT_CRYPT_KEYS::keys::data field up to WT_CRYPT_KEYS::keys::size.
*
* @param kp the WT_KEY_PROVIDER instance.
* @param session the current WiredTiger session.
* @param keysp the WT_CRYPT_KEYS to hold the new key (if changed).
* @param[out] crypt the WT_CRYPT_KEYS to hold the new key (if changed).
*/
int (*get_key)(WT_KEY_PROVIDER *kp, WT_SESSION *session, WT_CRYPT_KEYS **keysp);
int (*get_key)(WT_KEY_PROVIDER *kp, WT_SESSION *session, WT_CRYPT_KEYS *crypt);
/*!
* Callback function indicating that whether the key has been persisted.
@ -5787,9 +5779,24 @@ struct __wt_key_provider {
*
* @param kp the WT_KEY_PROVIDER instance.
* @param session the current WiredTiger session.
* @param keys the WT_CRYPT_KEYS information to confirm key persistence.
* @param crypt the WT_CRYPT_KEYS information to confirm key persistence.
*/
int (*on_key_update)(WT_KEY_PROVIDER *kp, WT_SESSION *session, WT_CRYPT_KEYS *keys);
int (*on_key_update)(WT_KEY_PROVIDER *kp, WT_SESSION *session, const WT_CRYPT_KEYS *crypt);
/*!
* A callback performed when the key provider is closed and will no
* longer be accessed by the WiredTiger database.
*
* This method is not required and should be set to NULL when not
* required by the key provider.
*
* The WT_KEY_PROVIDER::terminate callback is intended to allow cleanup;
* the handle will not be subsequently accessed by WiredTiger.
*
* @param kp the WT_KEY_PROVIDER instance.
* @param session the current WiredTiger session.
*/
int (*terminate)(WT_KEY_PROVIDER *key_provider, WT_SESSION *session);
};
#endif

View File

@ -90,6 +90,18 @@ class WTVersion:
else:
return True
def __ge__(self, other: "WTVersion"):
if self < other:
return False
else:
return True
def __le__(self, other: "WTVersion"):
if self > other:
return False
else:
return True
# Hash is used to support set collection, make it able to remove redundant
def __hash__(self):
return hash(self.name)

View File

@ -0,0 +1,90 @@
#!/usr/bin/env python
#
# Public Domain 2014-present 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.
import compatibility_test, compatibility_version, wiredtiger, errno
class test_flcs_deprecate(compatibility_test.CompatibilityTestCase):
'''
Test FLCS deprecation handling during database upgrade.
'''
build_config = {'standalone': 'true'}
conn_config = ''
create_config = 'key_format=r,value_format=8t'
uri = 'table:test_flcs_deprecate'
nrows = 100
def test_flcs_deprecate(self):
flcs_deprecated_version = compatibility_version.WTVersion("mongodb-8.3")
# Test FLCS table creation fails on FLCS deprecated version
if self.older_branch >= flcs_deprecated_version:
self.run_method_on_branch(self.newer_branch, 'flcs_table_creation_unsupported')
return
# Only run this test for older branch where FLCS is still available and newer branch where FLCS is deprecated.
if self.older_branch < flcs_deprecated_version and self.newer_branch >= flcs_deprecated_version:
# Run the older-branch part (create the FLCS table and populate it)
self.run_method_on_branch(self.older_branch, 'on_older_branch')
# Run the newer-branch part (attempt to open and expect failure)
self.run_method_on_branch(self.newer_branch, 'on_newer_branch')
def flcs_table_creation_unsupported(self):
# Test that FLCS table creation is unsupported on branches later than the deprecation version.
try:
conn = wiredtiger.wiredtiger_open('.', 'create,' + self.conn_config)
session = conn.open_session()
session.create(self.uri, self.create_config)
assert False
except wiredtiger.WiredTigerError as e:
assert str(e) in wiredtiger.wiredtiger_strerror(errno.ENOTSUP)
def on_older_branch(self):
# This runs in the older branch to create a FLCS table and populate it.
conn = wiredtiger.wiredtiger_open('.', 'create,' + self.conn_config)
session = conn.open_session()
session.create(self.uri, self.create_config)
c = session.open_cursor(self.uri)
for i in range(1, self.nrows + 1):
c[i] = i
c.close()
session.close()
conn.close()
def on_newer_branch(self):
# Expect opening the FLCS table to fail because FLCS is deprecated.
try:
wiredtiger.wiredtiger_open('.', self.conn_config)
assert False
except wiredtiger.WiredTigerError as e:
assert str(e) in wiredtiger.wiredtiger_strerror(wiredtiger.WT_PANIC)

View File

@ -1,87 +0,0 @@
/*-
* Public Domain 2014-present 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.
*/
#pragma once
#include "src/storage/scoped_cursor.h"
#include "transaction.h"
extern "C" {
#include "wiredtiger.h"
}
namespace test_harness {
namespace crud {
inline bool
insert(scoped_cursor &cursor, transaction &txn, const std::string &key, const std::string &value)
{
cursor->set_key(cursor.get(), key.c_str());
cursor->set_value(cursor.get(), value.c_str());
int ret = cursor->insert(cursor.get());
if (ret != 0) {
if (ret == WT_ROLLBACK) {
txn.set_needs_rollback();
return (false);
} else
testutil_die(ret, "unhandled error while trying to insert a key");
}
return (true);
}
inline bool
update(scoped_cursor &cursor, transaction &txn, const std::string &key, const std::string &value)
{
cursor->set_key(cursor.get(), key.c_str());
cursor->set_value(cursor.get(), value.c_str());
int ret = cursor->update(cursor.get());
if (ret != 0) {
if (ret == WT_ROLLBACK) {
txn.set_needs_rollback();
return (false);
} else
testutil_die(ret, "unhandled error while trying to update a key");
}
return (true);
}
inline bool
remove(scoped_cursor &cursor, transaction &txn, const std::string &key)
{
cursor->set_key(cursor.get(), key.c_str());
int ret = cursor->remove(cursor.get());
if (ret != 0) {
if (ret == WT_ROLLBACK) {
txn.set_needs_rollback();
return (false);
} else
testutil_die(ret, "unhandled error while trying to remove a key");
}
return (true);
}
}; // namespace crud
} // namespace test_harness

View File

@ -41,9 +41,11 @@ database::build_collection_name(const uint64_t id)
}
void
database::add_collection(scoped_session &session, uint64_t key_count)
database::add_collection(uint64_t key_count)
{
std::lock_guard<std::mutex> lg(_mtx);
if (_session.get() == nullptr)
_session = connection_manager::instance().create_session();
if (_collection_create_config.empty())
testutil_die(EINVAL, "database: no collection create config specified!");
uint64_t next_id = _next_collection_id++;
@ -52,7 +54,7 @@ database::add_collection(scoped_session &session, uint64_t key_count)
_collections.emplace(std::piecewise_construct, std::forward_as_tuple(next_id),
std::forward_as_tuple(next_id, key_count, collection_name));
testutil_check(
session->create(session.get(), collection_name.c_str(), _collection_create_config.c_str()));
_session->create(_session.get(), collection_name.c_str(), _collection_create_config.c_str()));
_operation_tracker->save_schema_operation(
tracking_operation::CREATE_COLLECTION, next_id, _tsm->get_next_ts());
}

View File

@ -48,7 +48,7 @@ public:
/*
* Add a new collection, this will create the underlying collection in the database.
*/
void add_collection(scoped_session &session, uint64_t key_count = 0);
void add_collection(uint64_t key_count = 0);
/* Get a collection using the id of the collection. */
collection &get_collection(uint64_t id);
@ -72,6 +72,7 @@ public:
private:
std::string _collection_create_config = "";
scoped_session _session;
timestamp_manager *_tsm = nullptr;
operation_tracker *_operation_tracker = nullptr;
uint64_t _next_collection_id = 0;

View File

@ -57,15 +57,15 @@ populate_worker(thread_worker *tc)
scoped_cursor cursor = tc->session.open_scoped_cursor(coll.name);
uint64_t j = 0;
while (j < tc->key_count) {
tc->begin();
tc->txn.begin();
auto key = tc->pad_string(std::to_string(j), tc->key_size);
auto value = random_generator::instance().generate_pseudo_random_string(tc->value_size);
if (tc->insert(cursor, coll.id, key, value)) {
if (tc->commit()) {
if (tc->txn.commit()) {
++j;
}
} else {
tc->rollback();
tc->txn.rollback();
}
}
}
@ -96,13 +96,12 @@ database_operation::populate(
LOG_INFO, "Populate: creating " + std::to_string(collection_count) + " collections.");
/* Create n collections as per the configuration. */
scoped_session session = connection_manager::instance().create_session();
for (int64_t i = 0; i < collection_count; ++i)
/*
* The database model will call into the API and create the collection, with its own
* session.
*/
database.add_collection(session, key_count);
database.add_collection(key_count);
logger::log_msg(
LOG_INFO, "Populate: " + std::to_string(collection_count) + " collections created.");
@ -205,21 +204,21 @@ database_operation::insert_operation(thread_worker *tc)
while (tc->running()) {
uint64_t start_key = ccv[counter].coll.get_key_count();
uint64_t added_count = 0;
tc->begin();
tc->txn.begin();
/* Collection cursor. */
auto &cc = ccv[counter];
while (tc->active() && tc->running()) {
while (tc->txn.active() && tc->running()) {
/* Insert a key value pair, rolling back the transaction if required. */
auto key = tc->pad_string(std::to_string(start_key + added_count), tc->key_size);
auto value = random_generator::instance().generate_pseudo_random_string(tc->value_size);
if (!tc->insert(cc.cursor, cc.coll.id, key, value)) {
added_count = 0;
tc->rollback();
tc->txn.rollback();
} else {
added_count++;
if (tc->can_commit()) {
if (tc->commit()) {
if (tc->txn.can_commit()) {
if (tc->txn.commit()) {
/*
* We need to inform the database model that we've added these keys as some
* other thread may rely on the key_count data. Only do so if we
@ -243,7 +242,7 @@ database_operation::insert_operation(thread_worker *tc)
testutil_assert(counter < tc_collection_count);
}
/* Make sure the last transaction is rolled back now the work is finished. */
tc->try_rollback();
tc->txn.try_rollback();
}
void
@ -263,29 +262,29 @@ database_operation::read_operation(thread_worker *tc)
/* Do a second lookup now that we know it exists. */
auto &cursor = cursors[coll.id];
tc->begin();
while (tc->active() && tc->running()) {
tc->txn.begin();
while (tc->txn.active() && tc->running()) {
auto ret = cursor->next(cursor.get());
if (ret != 0) {
if (ret == WT_NOTFOUND) {
testutil_check(cursor->reset(cursor.get()));
} else if (ret == WT_ROLLBACK) {
tc->rollback();
tc->txn.rollback();
tc->sleep();
continue;
} else
testutil_die(ret, "Unexpected error returned from cursor->next()");
}
tc->add_op();
if (tc->get_op_count() >= tc->get_target_op_count())
tc->rollback();
tc->txn.add_op();
if (tc->txn.get_op_count() >= tc->txn.get_target_op_count())
tc->txn.rollback();
tc->sleep();
}
/* Reset our cursor to avoid pinning content. */
testutil_check(cursor->reset(cursor.get()));
}
/* Make sure the last transaction is rolled back now the work is finished. */
tc->try_rollback();
tc->txn.try_rollback();
}
void
@ -326,7 +325,7 @@ database_operation::remove_operation(thread_worker *tc)
}
/* Start a transaction if possible. */
tc->try_begin();
tc->txn.try_begin();
/* Get the cursor associated with the collection. */
scoped_cursor &rnd_cursor = rnd_cursors[coll.id];
@ -342,9 +341,9 @@ database_operation::remove_operation(thread_worker *tc)
* one.
*/
if (ret == WT_NOTFOUND) {
testutil_ignore_ret_bool(tc->commit());
testutil_ignore_ret_bool(tc->txn.commit());
} else if (ret == WT_ROLLBACK) {
tc->rollback();
tc->txn.rollback();
} else {
testutil_die(ret, "Unexpected error returned from cursor->next()");
}
@ -355,7 +354,7 @@ database_operation::remove_operation(thread_worker *tc)
const char *key_str;
testutil_check(rnd_cursor->get_key(rnd_cursor.get(), &key_str));
if (!tc->remove(cursor, coll.id, key_str)) {
tc->rollback();
tc->txn.rollback();
}
/* Reset our cursors to avoid pinning content. */
@ -363,12 +362,12 @@ database_operation::remove_operation(thread_worker *tc)
testutil_check(rnd_cursor->reset(rnd_cursor.get()));
/* Commit the current transaction if we're able to. */
if (tc->can_commit())
testutil_ignore_ret_bool(tc->commit());
if (tc->txn.can_commit())
testutil_ignore_ret_bool(tc->txn.commit());
}
/* Make sure the last operation is rolled back now the work is finished. */
tc->try_rollback();
tc->txn.try_rollback();
}
void
@ -403,7 +402,7 @@ database_operation::update_operation(thread_worker *tc)
}
/* Start a transaction if possible. */
tc->try_begin();
tc->txn.try_begin();
/* Get the cursor associated with the collection. */
scoped_cursor &cursor = cursors[coll.id];
@ -415,19 +414,19 @@ database_operation::update_operation(thread_worker *tc)
auto key = tc->pad_string(std::to_string(key_id), tc->key_size);
auto value = random_generator::instance().generate_pseudo_random_string(tc->value_size);
if (!tc->update(cursor, coll.id, key, value)) {
tc->rollback();
tc->txn.rollback();
}
/* Reset our cursor to avoid pinning content. */
testutil_check(cursor->reset(cursor.get()));
/* Commit the current transaction if we're able to. */
if (tc->can_commit())
testutil_ignore_ret_bool(tc->commit());
if (tc->txn.can_commit())
testutil_ignore_ret_bool(tc->txn.commit());
}
/* Make sure the last operation is rolled back now the work is finished. */
tc->try_rollback();
tc->txn.try_rollback();
}
void

View File

@ -33,7 +33,6 @@
#include "src/common/constants.h"
#include "src/common/logger.h"
#include "src/common/random_generator.h"
#include "crud.h"
#include "transaction.h"
namespace test_harness {
@ -78,19 +77,13 @@ thread_worker::thread_worker(uint64_t id, thread_type type, configuration *confi
key_size(config->get_optional_int(KEY_SIZE, 1)),
value_size(config->get_optional_int(VALUE_SIZE, 1)),
thread_count(config->get_int(THREAD_COUNT)), type(type), id(id), db(dbase),
session(std::move(created_session)), tsm(timestamp_manager), op_tracker(op_tracker),
session(std::move(created_session)), tsm(timestamp_manager),
txn(transaction(config, timestamp_manager, session.get())), op_tracker(op_tracker),
_sleep_time_ms(std::chrono::milliseconds(config->get_throttle_ms())), _barrier(barrier_ptr)
{
if (op_tracker->enabled())
op_track_cursor = session.open_scoped_cursor(op_tracker->get_operation_table_name());
/* Use optional here as our populate threads don't define this configuration. */
configuration *ops_config = config->get_optional_subconfig(OPS_PER_TRANSACTION);
if (ops_config != nullptr) {
_min_op_count = ops_config->get_optional_int(MIN, 1);
_max_op_count = ops_config->get_optional_int(MAX, 1);
delete ops_config;
}
testutil_assert(key_size > 0 && value_size > 0);
}
@ -118,23 +111,32 @@ thread_worker::update(
testutil_assert(cursor.get() != nullptr);
wt_timestamp_t ts = tsm->get_next_ts();
ret = set_commit_timestamp(ts);
ret = txn.set_commit_timestamp(ts);
testutil_assert(ret == 0 || ret == EINVAL);
if (ret != 0) {
_txn.set_needs_rollback();
txn.set_needs_rollback(true);
return (false);
}
if (crud::update(cursor, _txn, key, value) == false)
return (false);
cursor->set_key(cursor.get(), key.c_str());
cursor->set_value(cursor.get(), value.c_str());
ret = cursor->update(cursor.get());
if (ret != 0) {
if (ret == WT_ROLLBACK) {
txn.set_needs_rollback(true);
return (false);
} else
testutil_die(ret, "unhandled error while trying to update a key");
}
ret = op_tracker->save_operation(
session.get(), tracking_operation::INSERT, collection_id, key, value, ts, op_track_cursor);
if (ret == 0)
add_op();
txn.add_op();
else if (ret == WT_ROLLBACK)
_txn.set_needs_rollback();
txn.set_needs_rollback(true);
else
testutil_die(ret, "unhandled error while trying to save an update to the tracking table");
return (ret == 0);
@ -150,23 +152,32 @@ thread_worker::insert(
testutil_assert(cursor.get() != nullptr);
wt_timestamp_t ts = tsm->get_next_ts();
ret = set_commit_timestamp(ts);
ret = txn.set_commit_timestamp(ts);
testutil_assert(ret == 0 || ret == EINVAL);
if (ret != 0) {
_txn.set_needs_rollback();
txn.set_needs_rollback(true);
return (false);
}
if (crud::insert(cursor, _txn, key, value) == false)
return (false);
cursor->set_key(cursor.get(), key.c_str());
cursor->set_value(cursor.get(), value.c_str());
ret = cursor->insert(cursor.get());
if (ret != 0) {
if (ret == WT_ROLLBACK) {
txn.set_needs_rollback(true);
return (false);
} else
testutil_die(ret, "unhandled error while trying to insert a key");
}
ret = op_tracker->save_operation(
session.get(), tracking_operation::INSERT, collection_id, key, value, ts, op_track_cursor);
if (ret == 0)
add_op();
txn.add_op();
else if (ret == WT_ROLLBACK)
_txn.set_needs_rollback();
txn.set_needs_rollback(true);
else
testutil_die(ret, "unhandled error while trying to save an insert to the tracking table");
return (ret == 0);
@ -180,23 +191,30 @@ thread_worker::remove(scoped_cursor &cursor, uint64_t collection_id, const std::
testutil_assert(cursor.get() != nullptr);
wt_timestamp_t ts = tsm->get_next_ts();
ret = set_commit_timestamp(ts);
ret = txn.set_commit_timestamp(ts);
testutil_assert(ret == 0 || ret == EINVAL);
if (ret != 0) {
_txn.set_needs_rollback();
txn.set_needs_rollback(true);
return (false);
}
if (crud::remove(cursor, _txn, key) == false)
return (false);
cursor->set_key(cursor.get(), key.c_str());
ret = cursor->remove(cursor.get());
if (ret != 0) {
if (ret == WT_ROLLBACK) {
txn.set_needs_rollback(true);
return (false);
} else
testutil_die(ret, "unhandled error while trying to remove a key");
}
ret = op_tracker->save_operation(
session.get(), tracking_operation::DELETE_KEY, collection_id, key, "", ts, op_track_cursor);
if (ret == 0)
add_op();
txn.add_op();
else if (ret == WT_ROLLBACK)
_txn.set_needs_rollback();
txn.set_needs_rollback(true);
else
testutil_die(ret, "unhandled error while trying to save a remove to the tracking table");
return (ret == 0);
@ -215,10 +233,10 @@ thread_worker::truncate(uint64_t collection_id, std::optional<std::string> start
int ret = 0;
wt_timestamp_t ts = tsm->get_next_ts();
ret = set_commit_timestamp(ts);
ret = txn.set_commit_timestamp(ts);
testutil_assert(ret == 0 || ret == EINVAL);
if (ret != 0) {
_txn.set_needs_rollback();
txn.set_needs_rollback(true);
return (false);
}
@ -238,7 +256,7 @@ thread_worker::truncate(uint64_t collection_id, std::optional<std::string> start
if (ret != 0) {
if (ret == WT_ROLLBACK) {
_txn.set_needs_rollback();
txn.set_needs_rollback(true);
return (false);
} else
testutil_die(ret, "unhandled error while trying to truncate a key range");
@ -298,96 +316,4 @@ thread_worker::get_assigned_collection_count() const
uint64_t collection_count = db.get_collection_count();
return collection_count / thread_count + (collection_count % thread_count > id);
}
/*
* Returns true if a transaction can be committed as determined by the op count and the state of the
* transaction.
*/
bool
thread_worker::can_commit()
{
return (!_txn.needs_rollback() && _txn.active() && get_op_count() >= get_target_op_count());
};
/* Get the current number of operations executed. */
int64_t
thread_worker::get_op_count() const
{
return _op_count;
}
/* Get the number of operations this transaction needs before it can commit */
int64_t
thread_worker::get_target_op_count() const
{
return _target_op_count;
}
bool
thread_worker::active() const
{
return _txn.active();
}
void
thread_worker::add_op()
{
_op_count++;
}
void
thread_worker::begin(const std::string &config)
{
/* This randomizes the number of operations to be executed in one transaction. */
_target_op_count =
random_generator::instance().generate_integer<int64_t>(_min_op_count, _max_op_count);
_op_count = 0;
_txn.begin(session, config);
}
/* Begin a transaction if we are not currently in one. */
void
thread_worker::try_begin(const std::string &config)
{
_txn.try_begin(session, config);
}
/*
* Commit a transaction and return true if the commit was successful.
*/
bool
thread_worker::commit(const std::string &config)
{
_op_count = 0;
return _txn.commit(session, config);
}
/* Rollback a transaction, failure will abort the test. */
void
thread_worker::rollback(const std::string &config)
{
_op_count = 0;
_txn.rollback(session, config);
}
/* Attempt to rollback the transaction given the requirements are met. */
void
thread_worker::try_rollback(const std::string &config)
{
_txn.try_rollback(session, config);
}
/*
* FIXME: WT-9198 We're concurrently doing a transaction that contains a bunch of operations while
* moving the stable timestamp. Eat the occasional EINVAL from the transaction's first commit
* timestamp being earlier than the stable timestamp.
*/
int
thread_worker::set_commit_timestamp(wt_timestamp_t ts)
{
if (!tsm->enabled())
return (0);
const std::string config = COMMIT_TS + "=" + timestamp_manager::decimal_to_hex(ts);
return session->timestamp_transaction(session.get(), config.c_str());
}
} // namespace test_harness

View File

@ -108,33 +108,6 @@ public:
/* Get the number of collections assigned to the thread worker */
uint64_t get_assigned_collection_count() const;
/* Add an operation to the current work item. */
void add_op();
/* Get the current number of operations executed. */
int64_t get_op_count() const;
/* Get the number of operations this work item needs before it can commit */
int64_t get_target_op_count() const;
/*
* Returns true if our transaction can be committed as determined by the op count and the state
* of the transaction.
*/
bool can_commit();
/* Returns whether there is an active transaction. */
bool active() const;
/* Begins a transaction. */
void begin(const std::string &config = "");
/* Begin a transaction if we are not currently in one. */
void try_begin(const std::string &config = "");
/* Commit a transaction and return true if the commit was successful. */
bool commit(const std::string &config = "");
/* Rollback a transaction, failure will abort the test. */
void rollback(const std::string &config = "");
/* Attempt to rollback the transaction given the requirements are met. */
void try_rollback(const std::string &config = "");
/* Set a commit timestamp. */
int set_commit_timestamp(wt_timestamp_t ts);
public:
const int64_t collection_count;
const int64_t free_space_target_mb;
@ -149,25 +122,12 @@ public:
scoped_cursor op_track_cursor;
scoped_cursor stat_cursor;
timestamp_manager *tsm;
transaction txn;
operation_tracker *op_tracker;
private:
std::shared_ptr<barrier> _barrier = nullptr;
bool _running = true;
std::chrono::milliseconds _sleep_time_ms;
transaction _txn;
/*
* _min_op_count and _max_op_count are the minimum and maximum number of operations within one
* transaction.
*/
int64_t _max_op_count = INT64_MAX;
int64_t _min_op_count = 0;
/*
* op_count is the current number of operations that have been executed in the current
* transaction.
*/
int64_t _op_count = 0;
int64_t _target_op_count = 0;
};
} // namespace test_harness

View File

@ -30,12 +30,23 @@
#include "src/common/constants.h"
#include "src/common/logger.h"
#include "src/storage/scoped_session.h"
extern "C" {
#include "test_util.h"
}
#include "src/common/random_generator.h"
namespace test_harness {
transaction::transaction(
configuration *config, timestamp_manager *timestamp_manager, WT_SESSION *session)
: _timestamp_manager(timestamp_manager), _session(session)
{
/* Use optional here as our populate threads don't define this configuration. */
configuration *transaction_config = config->get_optional_subconfig(OPS_PER_TRANSACTION);
if (transaction_config != nullptr) {
_min_op_count = transaction_config->get_optional_int(MIN, 1);
_max_op_count = transaction_config->get_optional_int(MAX, 1);
delete transaction_config;
}
}
bool
transaction::active() const
{
@ -43,20 +54,30 @@ transaction::active() const
}
void
transaction::begin(scoped_session &session, const std::string &config)
transaction::add_op()
{
_op_count++;
}
void
transaction::begin(const std::string &config)
{
testutil_assert(!_in_txn);
testutil_check(
session->begin_transaction(session.get(), config.empty() ? nullptr : config.c_str()));
_session->begin_transaction(_session, config.empty() ? nullptr : config.c_str()));
/* This randomizes the number of operations to be executed in one transaction. */
_target_op_count =
random_generator::instance().generate_integer<int64_t>(_min_op_count, _max_op_count);
_op_count = 0;
_in_txn = true;
_needs_rollback = false;
}
void
transaction::try_begin(scoped_session &session, const std::string &config)
transaction::try_begin(const std::string &config)
{
if (!_in_txn)
begin(session, config);
begin(config);
}
/*
@ -64,12 +85,12 @@ transaction::try_begin(scoped_session &session, const std::string &config)
* transaction internally.
*/
bool
transaction::commit(scoped_session &session, const std::string &config)
transaction::commit(const std::string &config)
{
int ret = 0;
testutil_assert(_in_txn && !_needs_rollback);
ret = session->commit_transaction(session.get(), config.empty() ? nullptr : config.c_str());
ret = _session->commit_transaction(_session, config.empty() ? nullptr : config.c_str());
/*
* FIXME-WT-9198 Now we are accepting the error code EINVAL because of possible invalid
* timestamps as we know it can happen due to the nature of the framework. The framework may set
@ -82,36 +103,65 @@ transaction::commit(scoped_session &session, const std::string &config)
if (ret != 0)
logger::log_msg(LOG_WARN,
"Failed to commit transaction in commit, received error code: " + std::to_string(ret));
_op_count = 0;
_in_txn = false;
return (ret == 0);
}
void
transaction::rollback(scoped_session &session, const std::string &config)
transaction::rollback(const std::string &config)
{
testutil_assert(_in_txn);
testutil_check(
session->rollback_transaction(session.get(), config.empty() ? nullptr : config.c_str()));
_session->rollback_transaction(_session, config.empty() ? nullptr : config.c_str()));
_needs_rollback = false;
_op_count = 0;
_in_txn = false;
}
void
transaction::try_rollback(scoped_session &session, const std::string &config)
transaction::try_rollback(const std::string &config)
{
if (_in_txn)
rollback(session, config);
rollback(config);
}
int64_t
transaction::get_op_count() const
{
return _op_count;
}
int64_t
transaction::get_target_op_count() const
{
return _target_op_count;
}
/*
* FIXME: WT-9198 We're concurrently doing a transaction that contains a bunch of operations while
* moving the stable timestamp. Eat the occasional EINVAL from the transaction's first commit
* timestamp being earlier than the stable timestamp.
*/
int
transaction::set_commit_timestamp(wt_timestamp_t ts)
{
/* We don't want to set zero timestamps on transactions if we're not using timestamps. */
if (!_timestamp_manager->enabled())
return 0;
const std::string config = COMMIT_TS + "=" + timestamp_manager::decimal_to_hex(ts);
return _session->timestamp_transaction(_session, config.c_str());
}
void
transaction::set_needs_rollback()
transaction::set_needs_rollback(bool rollback)
{
_needs_rollback = true;
_needs_rollback = rollback;
}
bool
transaction::needs_rollback()
transaction::can_commit()
{
return _needs_rollback;
return (!_needs_rollback && _in_txn && _op_count >= _target_op_count);
}
} // namespace test_harness

View File

@ -30,7 +30,9 @@
#include <string>
#include "src/storage/scoped_session.h"
#include "src/main/configuration.h"
#include "src/component/timestamp_manager.h"
extern "C" {
#include "wiredtiger.h"
}
@ -39,26 +41,55 @@ namespace test_harness {
class transaction {
public:
transaction(configuration *config, timestamp_manager *timestamp_manager, WT_SESSION *session);
bool active() const;
void begin(scoped_session &session, const std::string &config = "");
void add_op();
void begin(const std::string &config = "");
/* Begin a transaction if we are not currently in one. */
void try_begin(scoped_session &session, const std::string &config = "");
void try_begin(const std::string &config = "");
/*
* Commit a transaction and return true if the commit was successful.
*/
bool commit(scoped_session &session, const std::string &config = "");
bool commit(const std::string &config = "");
/* Rollback a transaction, failure will abort the test. */
void rollback(scoped_session &session, const std::string &config = "");
void rollback(const std::string &config = "");
/* Attempt to rollback the transaction given the requirements are met. */
void try_rollback(scoped_session &session, const std::string &config = "");
void try_rollback(const std::string &config = "");
/* Set a commit timestamp. */
int set_commit_timestamp(wt_timestamp_t ts);
/* Set that the transaction needs to be rolled back. */
void set_needs_rollback();
/* Return whether the transaction needs to be rolled back.*/
bool needs_rollback();
void set_needs_rollback(bool rollback);
/*
* Returns true if a transaction can be committed as determined by the op count and the state of
* the transaction.
*/
bool can_commit();
/* Get the current number of operations executed. */
int64_t get_op_count() const;
/* Get the number of operations this transaction needs before it can commit */
int64_t get_target_op_count() const;
private:
bool _in_txn = false;
bool _needs_rollback = false;
/*
* _min_op_count and _max_op_count are the minimum and maximum number of operations within one
* transaction. is the current maximum number of operations that can be executed in the current
* transaction.
*/
int64_t _max_op_count = INT64_MAX;
int64_t _min_op_count = 0;
/*
* op_count is the current number of operations that have been executed in the current
* transaction.
*/
int64_t _op_count = 0;
int64_t _target_op_count = 0;
timestamp_manager *_timestamp_manager = nullptr;
WT_SESSION *_session = nullptr;
};
} // namespace test_harness

View File

@ -138,7 +138,7 @@ public:
const uint64_t MAX_RETRIES = 100;
while (tw->running() && keys_truncated < n_keys_to_truncate && retries < MAX_RETRIES) {
/* Start a transaction if possible. */
tw->try_begin();
tw->txn.try_begin();
/* Choose a random key to delete. */
int ret = rnd_cursor->next(rnd_cursor.get());
@ -150,9 +150,9 @@ public:
* starting a new one.
*/
if (ret == WT_NOTFOUND)
testutil_ignore_ret_bool(tw->commit());
testutil_ignore_ret_bool(tw->txn.commit());
else if (ret == WT_ROLLBACK)
tw->rollback();
tw->txn.rollback();
else
testutil_die(ret, "Unexpected error returned from cursor->next()");
@ -173,7 +173,7 @@ public:
* If we generate an invalid range or our truncate fails rollback the transaction.
*/
if (end_key == first_key || !tw->truncate(coll.id, first_key, end_key, "")) {
tw->rollback();
tw->txn.rollback();
if (end_key == first_key)
logger::log_msg(
LOG_TRACE, log_prefix + "truncate failed because of an invalid range");
@ -183,7 +183,7 @@ public:
continue;
}
if (tw->commit()) {
if (tw->txn.commit()) {
logger::log_msg(LOG_TRACE,
log_prefix + " committed truncation of " + std::to_string(truncate_range) +
" records.");
@ -211,7 +211,7 @@ public:
}
/* Make sure the last operation is rolled back now the work is finished. */
tw->try_rollback();
tw->txn.try_rollback();
}
void
@ -257,22 +257,22 @@ public:
uint64_t start_key = ccv[counter].coll.get_key_count();
uint64_t added_count = 0;
tw->begin();
tw->txn.begin();
/* Collection cursor. */
auto &cc = ccv[counter];
while (tw->active() && tw->running()) {
while (tw->txn.active() && tw->running()) {
/* Insert a key value pair, rolling back the transaction if required. */
auto key = tw->pad_string(std::to_string(start_key + added_count), tw->key_size);
auto value =
random_generator::instance().generate_pseudo_random_string(tw->value_size);
if (!tw->insert(cc.cursor, cc.coll.id, key, value)) {
added_count = 0;
tw->rollback();
tw->txn.rollback();
} else {
added_count++;
if (tw->can_commit()) {
if (tw->commit())
if (tw->txn.can_commit()) {
if (tw->txn.commit())
/*
* We need to inform the database model that we've added these keys as
* some other thread may rely on the key_count data. Only do so if we
@ -295,7 +295,7 @@ public:
testutil_assert(counter < tw_collection_count);
}
/* Make sure the last transaction is rolled back now the work is finished. */
tw->try_rollback();
tw->txn.try_rollback();
}
void

View File

@ -120,7 +120,7 @@ public:
collection &coll = tc->db.get_collection(tc->id);
scoped_cursor cursor = tc->session.open_scoped_cursor(coll.name);
for (uint64_t count = 0; count < tc->key_count; ++count) {
tc->begin();
tc->txn.begin();
/*
* Generate the prefix key, and append a random generated key string based on the key
* size configuration.
@ -128,9 +128,9 @@ public:
prefix_key = random_generator::instance().generate_random_string(tc->key_size);
testutil_assert(cursor.get() != nullptr);
if (perform_unique_index_insertions(tc, cursor, coll, prefix_key)) {
tc->commit();
tc->txn.commit();
} else {
tc->rollback();
tc->txn.rollback();
++rollback_retries;
if (count > 0)
--count;
@ -169,13 +169,12 @@ public:
", key size: " + std::to_string(key_size));
/* Create n collections as per the configuration. */
scoped_session session = connection_manager::instance().create_session();
for (uint64_t i = 0; i < collection_count; ++i)
/*
* The database model will call into the API and create the collection, with its own
* session.
*/
database.add_collection(session);
database.add_collection();
/* Spawn a populate thread for each collection in the database. */
for (uint64_t i = 0; i < collection_count; ++i) {
@ -200,6 +199,7 @@ public:
* traverse through each collection using a cursor to collect the prefix and push it into a
* 2D vector.
*/
scoped_session session = connection_manager::instance().create_session();
const char *key_tmp;
int ret = 0;
for (uint64_t i = 0; i < database.get_collection_count(); i++) {
@ -243,7 +243,7 @@ public:
/* Do a second lookup now that we know it exists. */
auto &cursor = cursors[coll.id];
tc->begin();
tc->txn.begin();
/*
* Grab a random existing prefix and perform unique index insertion. We expect it to
* fail to insert, because it should already exist.
@ -258,7 +258,7 @@ public:
".");
testutil_assert(!perform_unique_index_insertions(tc, cursor, coll, prefix_key));
testutil_check(cursor->reset(cursor.get()));
tc->rollback();
tc->txn.rollback();
}
}
@ -273,7 +273,7 @@ public:
* Each read thread will count the number of keys in each collection, and will double check
* if the size of the table hasn't changed.
*/
tc->begin();
tc->txn.begin();
while (tc->running()) {
for (int i = 0; i < tc->db.get_collection_count(); i++) {
collection &coll = tc->db.get_collection(i);
@ -298,6 +298,6 @@ public:
}
key_count = 0;
}
tc->rollback();
tc->txn.rollback();
}
};

View File

@ -61,9 +61,8 @@ public:
logger::log_msg(
LOG_INFO, "Populate: " + std::to_string(collection_count) + " creating collections.");
scoped_session session = connection_manager::instance().create_session();
for (uint64_t i = 0; i < collection_count; ++i)
database.add_collection(session);
database.add_collection();
logger::log_msg(LOG_INFO, "Populate: finished.");
}
@ -108,9 +107,9 @@ public:
while (tc->running()) {
auto &cc = ccv[counter];
tc->begin();
tc->txn.begin();
while (tc->active() && tc->running()) {
while (tc->txn.active() && tc->running()) {
/* Generate a random key/value pair. */
std::string key = random_generator::instance().generate_random_string(tc->key_size);
@ -119,15 +118,15 @@ public:
/* Insert a key value pair. */
if (tc->insert(cc.cursor, cc.coll.id, key, value)) {
if (tc->can_commit()) {
if (tc->txn.can_commit()) {
/* We are not checking the result of commit as it is not necessary. */
if (tc->commit())
if (tc->txn.commit())
rollback_retries = 0;
else
++rollback_retries;
}
} else {
tc->rollback();
tc->txn.rollback();
++rollback_retries;
}
testutil_assert(rollback_retries < MAX_ROLLBACKS);
@ -137,7 +136,7 @@ public:
}
/* Rollback any transaction that could not commit before the end of the test. */
tc->try_rollback();
tc->txn.try_rollback();
/* Reset our cursor to avoid pinning content. */
testutil_check(cc.cursor->reset(cc.cursor.get()));
@ -179,10 +178,10 @@ public:
* The oldest timestamp might move ahead and the reading timestamp might become invalid.
* To tackle this issue, we round the timestamp to the oldest timestamp value.
*/
tc->begin(
tc->txn.begin(
"roundup_timestamps=(read=true),read_timestamp=" + tc->tsm->decimal_to_hex(ts));
while (tc->active() && tc->running()) {
while (tc->txn.active() && tc->running()) {
/*
* Generate a random prefix. For this, we start by generating a random size and then
* its value.
@ -212,15 +211,15 @@ public:
validate_prefix_search_near(
ret, exact_prefix, key_prefix_str, cursor_default, generated_prefix);
tc->add_op();
if (tc->get_op_count() >= tc->get_target_op_count())
tc->rollback();
tc->txn.add_op();
if (tc->txn.get_op_count() >= tc->txn.get_target_op_count())
tc->txn.rollback();
tc->sleep();
}
testutil_check(cursor_prefix->reset(cursor_prefix.get()));
}
/* Roll back the last transaction if still active now the work is finished. */
tc->try_rollback();
tc->txn.try_rollback();
}
private:

View File

@ -71,7 +71,7 @@ class bounded_cursor_prefix_stat : public test {
for (uint64_t j = 0; j < ALPHABET.size(); ++j) {
for (uint64_t k = 0; k < ALPHABET.size(); ++k) {
for (uint64_t count = 0; count < tc->key_count; ++count) {
tc->begin();
tc->txn.begin();
/*
* Generate the prefix key, and append a random generated key string based
* on the key size configuration.
@ -86,14 +86,14 @@ class bounded_cursor_prefix_stat : public test {
if (!tc->insert(cursor, coll.id, prefix_key, value)) {
testutil_assert(rollback_retries < MAX_ROLLBACKS);
/* We failed to insert, rollback our transaction and retry. */
tc->rollback();
tc->txn.rollback();
++rollback_retries;
if (count > 0)
--count;
} else {
/* Commit txn at commit timestamp 100. */
testutil_assert(
tc->commit("commit_timestamp=" + tc->tsm->decimal_to_hex(100)));
tc->txn.commit("commit_timestamp=" + tc->tsm->decimal_to_hex(100)));
rollback_retries = 0;
}
}
@ -131,13 +131,12 @@ public:
" number of collections: " + std::to_string(collection_count));
/* Create n collections as per the configuration. */
scoped_session session = connection_manager::instance().create_session();
for (uint64_t i = 0; i < collection_count; ++i)
/*
* The database model will call into the API and create the collection, with its own
* session.
*/
database.add_collection(session);
database.add_collection();
/* Spawn 26 threads to populate the database. */
for (uint64_t i = 0; i < ALPHABET.size(); ++i) {
@ -159,6 +158,7 @@ public:
/* Force evict all the populated keys in all of the collections. */
int cmpp;
scoped_session session = connection_manager::instance().create_session();
for (uint64_t count = 0; count < collection_count; ++count) {
collection &coll = database.get_collection(count);
scoped_cursor evict_cursor =
@ -200,7 +200,7 @@ public:
* bounded search near, we expect the search to early exit out of its prefix key range and
* return WT_NOTFOUND.
*/
tc->begin("read_timestamp=" + tc->tsm->decimal_to_hex(10));
tc->txn.begin("read_timestamp=" + tc->tsm->decimal_to_hex(10));
cursor->set_key(cursor.get(), srch_key.c_str());
bound_set prefix_bounds = bound_set(srch_key);
prefix_bounds.apply(cursor);
@ -220,7 +220,7 @@ public:
*/
if (srch_key == "z" || srch_key == "zz" || srch_key == "zzz")
++z_key_searches;
tc->rollback();
tc->txn.rollback();
}
void

View File

@ -383,9 +383,9 @@ public:
collection &coll = tc->db.get_random_collection();
scoped_cursor cursor = tc->session.open_scoped_cursor(coll.name);
tc->try_begin();
tc->txn.try_begin();
while (tc->active() && tc->running()) {
while (tc->txn.active() && tc->running()) {
/* Generate a random key. */
auto key = random_generator::instance().generate_random_string(tc->key_size);
@ -393,15 +393,15 @@ public:
random_generator::instance().generate_pseudo_random_string(tc->value_size);
/* Insert a key/value pair. */
if (tc->insert(cursor, coll.id, key, value)) {
if (tc->can_commit()) {
if (tc->txn.can_commit()) {
/* We are not checking the result of commit as it is not necessary. */
if (tc->commit())
if (tc->txn.commit())
rollback_retries = 0;
else
++rollback_retries;
}
} else {
tc->rollback();
tc->txn.rollback();
++rollback_retries;
}
testutil_assert(rollback_retries < MAX_ROLLBACKS);
@ -414,7 +414,7 @@ public:
testutil_check(cursor->reset(cursor.get()));
}
/* Rollback any transaction that could not commit before the end of the test. */
tc->try_rollback();
tc->txn.try_rollback();
}
void
@ -431,9 +431,9 @@ public:
scoped_cursor cursor = tc->session.open_scoped_cursor(coll.name);
scoped_cursor rnd_cursor =
tc->session.open_scoped_cursor(coll.name, "next_random=true");
tc->try_begin();
tc->txn.try_begin();
while (tc->active() && tc->running()) {
while (tc->txn.active() && tc->running()) {
int ret = rnd_cursor->next(rnd_cursor.get());
/* It is possible not to find anything if the collection is empty. */
@ -443,7 +443,7 @@ public:
* If we cannot find any record, finish the current transaction as we might be
* able to see new records after starting a new one.
*/
testutil_ignore_ret_bool(tc->commit());
testutil_ignore_ret_bool(tc->txn.commit());
continue;
} else if (ret == WT_ROLLBACK)
break;
@ -455,15 +455,15 @@ public:
auto value =
random_generator::instance().generate_pseudo_random_string(tc->value_size);
if (tc->update(cursor, coll.id, key, value)) {
if (tc->can_commit()) {
if (tc->txn.can_commit()) {
/* We are not checking the result of commit as it is not necessary. */
if (tc->commit())
if (tc->txn.commit())
rollback_retries = 0;
else
++rollback_retries;
}
} else {
tc->rollback();
tc->txn.rollback();
++rollback_retries;
}
testutil_assert(rollback_retries < MAX_ROLLBACKS);
@ -478,7 +478,7 @@ public:
}
/* Rollback any transaction that could not commit before the end of the test. */
tc->try_rollback();
tc->txn.try_rollback();
}
void
@ -511,9 +511,9 @@ public:
* The oldest timestamp might move ahead and the reading timestamp might become invalid.
* To tackle this issue, we round the timestamp to the oldest timestamp value.
*/
tc->try_begin(
tc->txn.try_begin(
"roundup_timestamps=(read=true),read_timestamp=" + tc->tsm->decimal_to_hex(ts));
while (tc->active() && tc->running()) {
while (tc->txn.active() && tc->running()) {
/* Generate a random string. */
auto key_size = random_generator::instance().generate_integer(
static_cast<int64_t>(1), tc->key_size);
@ -552,16 +552,16 @@ public:
validate_bound_search(ret, bounded_cursor, range_key_copy, bound_pair);
}
tc->add_op();
if (tc->can_commit())
tc->commit();
tc->txn.add_op();
if (tc->txn.can_commit())
tc->txn.commit();
tc->sleep();
}
bounded_cursor->reset(bounded_cursor.get());
normal_cursor->reset(normal_cursor.get());
}
/* Roll back the last transaction if still active now the work is finished. */
tc->try_rollback();
tc->txn.try_rollback();
}
/*
@ -745,9 +745,9 @@ public:
* The oldest timestamp might move ahead and the reading timestamp might become invalid.
* To tackle this issue, we round the timestamp to the oldest timestamp value.
*/
tc->begin(
tc->txn.begin(
"roundup_timestamps=(read=true),read_timestamp=" + tc->tsm->decimal_to_hex(ts));
while (tc->active() && tc->running()) {
while (tc->txn.active() && tc->running()) {
int ret = cursor_traversal(bounded_cursor, normal_cursor, bound_pair.get_lower(),
bound_pair.get_upper(), true);
if (ret != 0)
@ -766,14 +766,14 @@ public:
bound_pair.get_upper(), false);
testutil_assert(ret == 0 || ret == WT_ROLLBACK);
}
tc->add_op();
if (tc->get_op_count() >= tc->get_target_op_count())
tc->rollback();
tc->txn.add_op();
if (tc->txn.get_op_count() >= tc->txn.get_target_op_count())
tc->txn.rollback();
tc->sleep();
}
normal_cursor->reset(normal_cursor.get());
}
/* Roll back the last transaction if still active now the work is finished. */
tc->try_rollback();
tc->txn.try_rollback();
}
};

View File

@ -96,13 +96,13 @@ public:
while (tc->running() &&
std::chrono::system_clock::now() - burst_start <
std::chrono::seconds(_burst_duration)) {
tc->try_begin();
tc->txn.try_begin();
auto key = tc->pad_string(std::to_string(start_key + added_count), tc->key_size);
/* A return value of true implies the insert was successful. */
auto value =
random_generator::instance().generate_pseudo_random_string(tc->value_size);
if (!tc->insert(cc.write_cursor, cc.coll.id, key, value)) {
tc->rollback();
tc->txn.rollback();
added_count = 0;
continue;
}
@ -114,7 +114,7 @@ public:
if (ret == WT_NOTFOUND) {
testutil_check(cc.read_cursor->reset(cc.read_cursor.get()));
} else if (ret == WT_ROLLBACK) {
tc->rollback();
tc->txn.rollback();
added_count = 0;
continue;
} else {
@ -122,17 +122,17 @@ public:
}
}
if (tc->can_commit()) {
if (tc->commit()) {
if (tc->txn.can_commit()) {
if (tc->txn.commit()) {
cc.coll.increase_key_count(added_count);
start_key = cc.coll.get_key_count();
}
added_count = 0;
}
}
/* Close out our current */
if (tc->active()) {
if (tc->commit()) {
/* Close out our current txn. */
if (tc->txn.active()) {
if (tc->txn.commit()) {
logger::log_msg(LOG_TRACE,
"Committed an insertion of " + std::to_string(added_count) + " keys.");
cc.coll.increase_key_count(added_count);
@ -148,7 +148,7 @@ public:
tc->sleep();
}
/* Make sure the last transaction is rolled back now the work is finished. */
tc->try_rollback();
tc->txn.try_rollback();
}
private:

View File

@ -113,19 +113,19 @@ public:
const std::string value = std::to_string(new_cache_size);
/* Save the change of cache size in the tracking table. */
tc->begin();
tc->txn.begin();
int ret = tc->op_tracker->save_operation(tc->session.get(), tracking_operation::CUSTOM,
collection_id, key, value, tc->tsm->get_next_ts(), tc->op_track_cursor);
if (ret == 0)
testutil_assert(tc->commit());
testutil_assert(tc->txn.commit());
else {
/* Due to the cache pressure, it is possible to fail when saving the operation. */
testutil_assert(ret == WT_ROLLBACK);
logger::log_msg(LOG_WARN,
"The cache size reconfiguration could not be saved in the tracking table, ret: " +
std::to_string(ret));
tc->rollback();
tc->txn.rollback();
}
increase_cache = !increase_cache;
}
@ -149,21 +149,21 @@ public:
((WT_CONNECTION_IMPL *)connection_manager::instance().get_connection())->cache_size;
const std::string value = std::to_string(cache_size);
tc->try_begin();
tc->txn.try_begin();
if (!tc->insert(cursor, coll.id, key, value)) {
tc->rollback();
} else if (tc->can_commit()) {
tc->txn.rollback();
} else if (tc->txn.can_commit()) {
/*
* The transaction can fit in the current cache size and is ready to be committed.
* This means the tracking table will contain a new record to represent this
* transaction which will be used during the validation stage.
*/
testutil_assert(tc->commit());
testutil_assert(tc->txn.commit());
}
}
/* Make sure the last transaction is rolled back now the work is finished. */
tc->try_rollback();
tc->txn.try_rollback();
}
void

View File

@ -69,14 +69,14 @@ public:
tc->sleep();
/* Start a transaction if possible. */
tc->try_begin();
tc->txn.try_begin();
auto ret = cursor->next(cursor.get());
if (ret != 0) {
if (ret == WT_NOTFOUND)
testutil_check(cursor->reset(cursor.get()));
else if (ret == WT_ROLLBACK)
tc->rollback();
tc->txn.rollback();
else
testutil_die(ret, "Unexpected error returned from cursor->next()");
continue;
@ -93,19 +93,19 @@ public:
std::string value =
random_generator::instance().generate_pseudo_random_string(tc->value_size);
if (tc->update(cursor, coll.id, key_tmp, value)) {
if (tc->can_commit()) {
if (tc->commit())
if (tc->txn.can_commit()) {
if (tc->txn.commit())
rollback_retries = 0;
else
++rollback_retries;
}
} else {
tc->rollback();
tc->txn.rollback();
++rollback_retries;
}
testutil_assert(rollback_retries < MAX_ROLLBACKS);
}
/* Ensure our last transaction is resolved. */
tc->try_rollback();
tc->txn.try_rollback();
}
};

View File

@ -70,10 +70,10 @@ public:
while (tc->running()) {
testutil_check(write_cursor->reset(write_cursor.get()));
tc->begin();
tc->txn.begin();
int ret = write_cursor->next(write_cursor.get());
if (ret != 0) {
tc->rollback();
tc->txn.rollback();
continue;
}
const char *key;
@ -87,10 +87,10 @@ public:
std::string end_key = tc->pad_string(std::to_string(end_key_id), tc->key_size);
/* If we generate an invalid range or our truncate fails rollback the transaction. */
if (min_key_id == end_key_id || !tc->truncate(coll.id, key_str, end_key, "")) {
tc->rollback();
tc->txn.rollback();
continue;
}
if (tc->commit())
if (tc->txn.commit())
logger::log_msg(LOG_TRACE,
"thread {" + std::to_string(tc->id) + "} committed truncation of " +
std::to_string(end_key_id - min_key_id) + " records.");
@ -111,7 +111,7 @@ public:
tc->sync();
}
/* Make sure the last transaction is rolled back now the work is finished. */
tc->try_rollback();
tc->txn.try_rollback();
}
};
} // namespace test_harness

View File

@ -1126,6 +1126,25 @@ functions:
content_type: application/tar
display_name: ${artifacts_name|Artifacts}
remote_file: wiredtiger/${build_variant}/${revision}/artifacts/${task_name}_${build_id}${postfix|}.tgz
"upload wtperf test artifact":
- command: archive.targz_pack
type: setup
params:
target: ${upload_filename|wt_test.tgz}
source_dir: ${upload_source_dir|wiredtiger/cmake_build/bench/wtperf/WT_TEST_0_0/}
include:
- "./**"
- command: s3.put
type: setup
params:
aws_secret: ${aws_secret}
aws_key: ${aws_key}
local_file: ${upload_filename|wt_test.tgz}
bucket: build_external
permissions: public-read
content_type: application/tar
display_name: ${artifacts_name|WT_TEST}
remote_file: wiredtiger/${build_variant}/${revision}/artifacts/${task_name}_${build_id}${postfix|}.tgz
"upload endian format artifacts":
- command: s3.put
type: setup
@ -1586,16 +1605,6 @@ variables:
# Stress tests that validate disagg behavior in leader, follower, and switch modes. #
#########################################################################################
- &format-stress-test-disagg-leader-palm
depends_on:
- name: compile
commands:
- func: "fetch artifacts"
- func: "format test disagg"
vars:
format_args: disagg.page_log=palm disagg.mode=leader runs.rows=100000 runs.ops=100000
times: 5
- &format-stress-test-disagg-leader-verify
depends_on:
- name: compile
@ -1645,6 +1654,7 @@ variables:
- func: "format test script"
vars:
format_test_script_args: -t 180 -c ../../../test/format/CONFIG.disagg -- disagg.mode=follower runs.timer=5:10
num_jobs: 1 # Follower requires a larger cache; parallel execution may limit available cache and cause stalls.
- func: "format test disagg"
vars:
format_args: disagg.mode=follower runs.timer=5:10
@ -1660,6 +1670,18 @@ variables:
format_args: disagg.mode=switch runs.timer=10:15
times: 5
# FIXME-WT-16113: Consolidate this logic in test/format itself.
- &format-stress-test-disagg-switch-data-validation
depends_on:
- name: compile
commands:
- func: "fetch artifacts"
- func: "format test disagg"
vars:
# Validate data with a non-layered table.
format_args: disagg.mode=switch ops.verify=1 runs.mirror=1 table1.runs.source=table table1.disagg.enabled=0 runs.timer=5:10
times: 5
#######################################
# Tasks #
#######################################
@ -4548,9 +4570,6 @@ tasks:
# Stress tests for Disagg #
#####################################
- <<: *format-stress-test-disagg-leader-palm
name: format-stress-test-disagg-leader-palm
tags: ["stress-test-disagg"]
- <<: *format-stress-test-disagg-leader
name: format-stress-test-disagg-leader-1
tags: ["stress-test-disagg"]
@ -4581,6 +4600,15 @@ tasks:
- <<: *format-stress-test-disagg-switch
name: format-stress-test-disagg-switch-3
tags: ["stress-test-disagg-fail"]
- <<: *format-stress-test-disagg-switch-data-validation
name: format-stress-test-disagg-switch-data-validation-1
tags: ["stress-test-disagg-fail"]
- <<: *format-stress-test-disagg-switch-data-validation
name: format-stress-test-disagg-switch-data-validation-2
tags: ["stress-test-disagg-fail"]
- <<: *format-stress-test-disagg-switch-data-validation
name: format-stress-test-disagg-switch-data-validation-3
tags: ["stress-test-disagg-fail"]
- name: format-stress-disagg-leader-pull-request-test
tags: ["pull_request"]
@ -5530,6 +5558,7 @@ tasks:
- func: "upload stats to evergreen"
vars:
test-name: cache_dirty_trigger_read-10_write-90.py
- func: "upload wtperf test artifact"
- name: perf-cache_dirty_trigger_read-25_write-75
tags: ["evict-perf"]
@ -5551,6 +5580,7 @@ tasks:
- func: "upload stats to evergreen"
vars:
test-name: cache_dirty_trigger_read-25_write-75.py
- func: "upload wtperf test artifact"
- name: perf-cache_dirty_trigger_read-50_write-50
tags: ["evict-perf"]
@ -5572,6 +5602,7 @@ tasks:
- func: "upload stats to evergreen"
vars:
test-name: cache_dirty_trigger_read-50_write-50.py
- func: "upload wtperf test artifact"
- name: perf-cache_dirty_trigger_read-75_write-25
tags: ["evict-perf"]
@ -5593,6 +5624,7 @@ tasks:
- func: "upload stats to evergreen"
vars:
test-name: cache_dirty_trigger_read-75_write-25.py
- func: "upload wtperf test artifact"
- name: perf-cache_dirty_trigger_read-90_write-10
tags: ["evict-perf"]
@ -5614,6 +5646,7 @@ tasks:
- func: "upload stats to evergreen"
vars:
test-name: cache_dirty_trigger_read-90_write-10.py
- func: "upload wtperf test artifact"
- name: perf-cache_update_trigger_read-10_write-90
tags: ["evict-perf"]
@ -5635,6 +5668,7 @@ tasks:
- func: "upload stats to evergreen"
vars:
test-name: cache_update_trigger_read-10_write-90.py
- func: "upload wtperf test artifact"
- name: perf-cache_update_trigger_read-25_write-75
tags: ["evict-perf"]
@ -5656,6 +5690,7 @@ tasks:
- func: "upload stats to evergreen"
vars:
test-name: cache_update_trigger_read-25_write-75.py
- func: "upload wtperf test artifact"
- name: perf-cache_update_trigger_read-50_write-50
tags: ["evict-perf"]
@ -5677,6 +5712,7 @@ tasks:
- func: "upload stats to evergreen"
vars:
test-name: cache_update_trigger_read-50_write-50.py
- func: "upload wtperf test artifact"
- name: perf-cache_update_trigger_read-75_write-25
tags: ["evict-perf"]
@ -5698,6 +5734,7 @@ tasks:
- func: "upload stats to evergreen"
vars:
test-name: cache_update_trigger_read-75_write-25.py
- func: "upload wtperf test artifact"
- name: perf-cache_update_trigger_read-90_write-10
tags: ["evict-perf"]
@ -5719,6 +5756,7 @@ tasks:
- func: "upload stats to evergreen"
vars:
test-name: cache_update_trigger_read-90_write-10.py
- func: "upload wtperf test artifact"
###########################################
# Performance Tests for log consolidation #
@ -5897,10 +5935,7 @@ tasks:
- func: "upload stats to evergreen"
vars:
test-name: 500m-btree-populate.wtperf
- func: "upload artifact"
vars:
upload_filename: WT_TEST.tgz
upload_source_dir: wiredtiger/cmake_build/bench/wtperf/WT_TEST_0_0/
- func: "upload wtperf test artifact"
# Now take and upload a backup. We use this as the source in our live restore perf tests.
- command: shell.exec
params:

View File

@ -3,5 +3,3 @@
leak:InitModule
# ARM64 python leaks memory from an unclear source. This suppresses that one leak.
leak:PyObject_Malloc
# FIXME-WT-16126 : Temporarily suppression until the underlying issue is resolved.
leak:__wti_block_disagg_addr_string

View File

@ -1519,12 +1519,12 @@ config_disagg_storage(void)
else
g.disagg_leader = strcmp(mode, "leader") == 0;
/* FIXME WT-15189 For non-leader modes, random cursors are problematic. */
if (strcmp(mode, "leader") != 0) {
if (config_explicit(NULL, "ops.random_cursor"))
WARN("%s", "turning off ops.random_cursor to work with disagg non-leader modes");
config_off(NULL, "ops.random_cursor");
}
/* FIXME WT-15189 For disagg, random cursors are problematic. */
if (config_explicit(NULL, "ops.random_cursor"))
WARN("%s",
"turning off ops.random_cursor with disagg as they are currently problematic and can "
"cause stalls");
config_off(NULL, "ops.random_cursor");
/* Disaggregated storage requires timestamps. */
config_off(NULL, "transaction.implicit");

View File

@ -164,4 +164,7 @@ disagg_switch_roles(void)
if (!g.disagg_leader)
follower_read_latest_checkpoint();
/* After every switch, verify the contents of each table */
wts_verify_mirrors(g.wts_conn, NULL, NULL);
}

View File

@ -48,7 +48,12 @@ class test_checkpoint09(wttest.WiredTigerTestCase):
scenarios = make_scenarios(format_values, ckpt_precision)
def conn_config(self):
return 'cache_size=50MB,statistics=(all),' + self.ckpt_config
config = 'cache_size=50MB,statistics=(all),' + self.ckpt_config
if self.runningHook('disagg'):
# Disable leaf page deltas for disaggregated testing as the test expects we write full pages.
return config + ',page_delta=(leaf_page_delta=false)'
else:
return config
def get_stat(self, stat):
stat_cursor = self.session.open_cursor('statistics:')
@ -123,7 +128,7 @@ class test_checkpoint09(wttest.WiredTigerTestCase):
# Pin oldest timestamp to 10 and stable timestamp to 20.
self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(10) +
',stable_timestamp=' + self.timestamp_str(20))
self.session.checkpoint(None)
self.session.checkpoint()
val = self.get_stat(stat.conn.rec_time_window_start_ts)
self.assertEqual(val, nrows + nrows/10)

View File

@ -324,3 +324,35 @@ class test_config04(wttest.WiredTigerTestCase):
def test_transactional(self):
# Note: this will have functional tests in the future.
self.common_test('')
def test_removed_metadata_config(self):
'''
We still need to support all the removed configurations that may remain in the metadata, as
removing them could cause issues when upgrading to a newer version.
'''
self.conn = self.wiredtiger_open('.', 'create,statistics=(fast)')
self.session = self.conn.open_session(None)
create_args_base = 'key_format=S,value_format=S'
config_variants = [
',lsm=(auto_throttle=)',
',lsm=(bloom=)',
',lsm=(bloom_bit_count=)',
',lsm=(bloom_config=)',
',lsm=(bloom_hash_count=)',
',lsm=(bloom_oldest=)',
',lsm=(chunk_count_limit=)',
',lsm=(chunk_max=)',
',lsm=(chunk_size=)',
',lsm=(merge_custom=(prefix=))',
',lsm=(merge_custom=(start_generation=))',
',lsm=(merge_custom=(suffix=))',
',lsm=(merge_max=)',
',lsm=(merge_min=)',
]
table_idx = 1
for config_variant in config_variants:
self.session.create("table:" + self.table_name1 + str(table_idx),
create_args_base + config_variant)
table_idx += 1