Compare commits

...

8 Commits

Author SHA1 Message Date
Nicholas Zolnierz
76d67ea903 SERVER-62322 Allow an empty object to be projected in $setWindowFields 2022-01-19 15:21:36 -05:00
Chenhao Qu
b3a66de850 Import wiredtiger: aab21d5814193dc1943d9f5e62fd40ad6973475a from branch mongodb-master
ref: 79c2e12ea7..aab21d5814
for: 5.3.0

WT-8610       Fix counter use
2021-12-29 02:38:56 +00:00
Chenhao Qu
2ea564e147 Import wiredtiger: 79c2e12ea706ff1653154e87b2b51fe437be79a7 from branch mongodb-master
ref: 936b411d68..79c2e12ea7
for: 5.3.0

WT-8561       Error if restoring a backup with metadata verification on
2021-12-29 02:38:56 +00:00
Chenhao Qu
107fe227b5 Import wiredtiger: 936b411d686b30f2b68d050914689ded27744ee5 from branch mongodb-master
ref: 7307e981cd..936b411d68
for: 5.3.0

WT-8600       Make recovery with no stable timestamp not drop history
2021-12-29 02:38:56 +00:00
Chenhao Qu
285766aa03 Import wiredtiger: 7307e981cd95ae93ce14862e73301ce121ceefa4 from branch mongodb-master
ref: 791e2fa364..7307e981cd
for: 5.3.0

WT-8606       Set project-level exec_timeout_secs in evergreen.yml
2021-12-29 02:38:56 +00:00
Chenhao Qu
c2f14164ba Import wiredtiger: 791e2fa364918cb072e0ff7bad199ee738449e87 from branch mongodb-master
ref: 7b3e2832d6..791e2fa364
for: 5.3.0

WT-8602       Move s_version package.spec to autoconf
2021-12-29 02:38:56 +00:00
Chenhao Qu
ae47c18fa3 Import wiredtiger: 7b3e2832d653ed8a13fb8b670cccebdfe29d8837 from branch mongodb-master
ref: c5db3e1d67..7b3e2832d6
for: 5.3.0

WT-7709       Unused variable tmp in __wt_rec_upd_select()
2021-12-29 02:38:56 +00:00
Andrew Morrow
38d13a91b4 SERVER-62235 Add an experimental VS 2022 builder in C++17 mode 2021-12-29 02:13:14 +00:00
17 changed files with 331 additions and 35 deletions

View File

@@ -8851,6 +8851,60 @@ buildvariants:
distros:
- rhel70-small
- name: enterprise-windows-msvs2022-experimental
display_name: "~ Enterprise Windows MSVS 2022"
cron: "0 12 * * *" # Every day starting at 12:00
modules:
- enterprise
run_on:
- windows-vsCurrent-2022-small
expansions:
exe: ".exe"
additional_package_targets: archive-mongocryptd archive-mongocryptd-debug msi archive-mh archive-mh-debug
content_type: application/zip
compile_flags: --ssl MONGO_DISTMOD=windows CPPPATH="c:/sasl/include c:/snmp/include" LIBPATH="c:/sasl/lib c:/snmp/lib" -j$(bc <<< "$(grep -c '^processor' /proc/cpuinfo) / 1.5") --win-version-min=win10 MSVC_VERSION=14.3
num_scons_link_jobs_available: 0.25
python: '/cygdrive/c/python/python37/python.exe'
ext: zip
scons_cache_scope: shared
jstestfuzz_num_generated_files: 35
target_resmoke_time: 20
max_sub_suites: 3
large_distro_name: windows-vsCurrent-2022-large
test_flags: *windows_common_test_excludes
exec_timeout_secs: 14400 # 3 hour timeout
tasks:
- name: compile_test_and_package_serial_TG
distros:
- windows-vsCurrent-2022-large
- name: build_variant_gen
# - name: .aggfuzzer # Disabled for FCV 5.3
- name: .aggregation !.auth !.encrypt !.unwind
- name: auth_gen
- name: causally_consistent_jscore_txns_passthrough
- name: .misc_js
# Some concurrency workloads require a lot of memory, so we use machines
# with more RAM for these suites.
- name: .concurrency !.ubsan !.no_txns !.kill_terminate !.common !.debug_only
distros:
- windows-vsCurrent-2022-large
- name: .concurrency .common
- name: disk_wiredtiger
- name: .jscore .common !.auth
- name: json_schema
- name: .jstestfuzz !.initsync !.flow_control !.stepdowns
- name: powercycle_gen
- name: .query_fuzzer
- name: .read_write_concern
- name: replica_sets_gen
- name: replica_sets_jscore_passthrough
- name: .sharding .jscore !.wo_snapshot !.multi_stmt !.multiversion
- name: .sharding .txns !.multiversion
- name: .sharding .common !.csrs !.multiversion
- name: .ssl
- name: .stitch
- name: .updatefuzzer !.multiversion
- name: enterprise-windows-debug-unoptimized
display_name: Enterprise Windows DEBUG (Unoptimized)
cron: "0 12 * * *" # Every day starting at 12:00

View File

@@ -213,8 +213,7 @@ assert.commandWorked(run({
}));
// Not every accumulator is automatically a window function.
var err = assert.commandFailedWithCode(run({$setWindowFields: {output: {a: {b: {$sum: "$a"}}}}}),
let err = assert.commandFailedWithCode(run({$setWindowFields: {output: {a: {b: {$sum: "$a"}}}}}),
ErrorCodes.FailedToParse);
assert.includes(err.errmsg, 'Expected a $-prefixed window function, b');
@@ -250,4 +249,14 @@ err = assert.commandFailedWithCode(
}),
ErrorCodes.FailedToParse);
assert.includes(err.errmsg, 'Unrecognized window function, $summ');
// Test that an empty object is a valid projected field.
assert.commandWorked(coll.insert({}));
assert.commandWorked(run({$setWindowFields: {output: {v: {$max: {mergeObjects: {}}}}}}));
// However conflicting field paths is always an error.
err = assert.commandFailedWithCode(
run({$setWindowFields: {output: {a: {$sum: 1}, 'a.b': {$sum: 1}}}}), 40176);
assert.includes(err.errmsg, 'specification contains two conflicting paths');
})();

View File

@@ -461,10 +461,12 @@ DocumentSource::GetNextResult DocumentSourceInternalSetWindowFields::doGetNext()
MutableDocument addFieldsSpec;
for (auto&& [fieldName, function] : _executableOutputs) {
try {
// Wrap the projected value in a $literal since there are limitations on a user-facing
// $addFields that we don't want to enforce here (e.g. empty object).
addFieldsSpec.addField(fieldName, Value(DOC("$literal" << function->getNext())));
} catch (const DBException&) {
// If we hit a uassert while evaluating expressions on user data, delete the temporary
// table before aborting the operation.
addFieldsSpec.addField(fieldName, function->getNext());
} catch (const DBException&) {
_iterator.finalize();
throw;
}
@@ -506,6 +508,7 @@ DocumentSource::GetNextResult DocumentSourceInternalSetWindowFields::doGetNext()
_iterator.finalize();
break;
}
auto projExec = projection_executor::AddFieldsProjectionExecutor::create(
pExpCtx, addFieldsSpec.freeze().toBson());

View File

@@ -1287,7 +1287,8 @@ wiredtiger_open_common =\
choices=['dsync', 'fsync', 'none']),
]),
Config('verify_metadata', 'false', r'''
open connection and verify any WiredTiger metadata. This API
open connection and verify any WiredTiger metadata. Not compatible when
opening a connection from a backup. This API
allows verification and detection of corruption in WiredTiger metadata.''',
type='boolean'),
Config('write_through', '', r'''

View File

@@ -55,6 +55,10 @@ GenAutoconfVersion(){
VERSION_NOPATCH=${WIREDTIGER_VERSION_MAJOR}.${WIREDTIGER_VERSION_MINOR}
AC_SUBST(VERSION_NOPATCH)
END
echo "Building $rpmspec"
sed -e "s/Version: .*/Version: ${dotted_version}/" $rpmspec \
> $tmp_file && mv $tmp_file $rpmspec
}
GenCmakeVersion(){
@@ -79,7 +83,3 @@ GenCmakeVersion(){
GenAutoconfVersion
GenCmakeVersion
echo "Building $rpmspec"
sed -e "s/Version: .*/Version: ${dotted_version}/" $rpmspec \
> $tmp_file && mv $tmp_file $rpmspec

View File

@@ -2,5 +2,5 @@
"vendor": "wiredtiger",
"github": "wiredtiger/wiredtiger.git",
"branch": "mongodb-master",
"commit": "c5db3e1d6752826db91c41026bd4eed3c04e32a0"
"commit": "aab21d5814193dc1943d9f5e62fd40ad6973475a"
}

View File

@@ -2949,9 +2949,9 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler, const char *c
* THE TURTLE FILE MUST BE THE LAST FILE CREATED WHEN INITIALIZING THE DATABASE HOME, IT'S WHAT
* WE USE TO DECIDE IF WE'RE CREATING OR NOT.
*/
WT_ERR(__wt_turtle_init(session));
WT_ERR(__wt_config_gets(session, cfg, "verify_metadata", &cval));
verify_meta = cval.val;
WT_ERR(__wt_turtle_init(session, verify_meta));
/* Verify the metadata file. */
if (verify_meta) {

View File

@@ -1537,7 +1537,7 @@ extern int __wt_try_writelock(WT_SESSION_IMPL *session, WT_RWLOCK *l)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_turtle_exists(WT_SESSION_IMPL *session, bool *existp)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_turtle_init(WT_SESSION_IMPL *session)
extern int __wt_turtle_init(WT_SESSION_IMPL *session, bool verify_meta)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_turtle_read(WT_SESSION_IMPL *session, const char *key, char **valuep)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));

View File

@@ -3138,9 +3138,9 @@ struct __wt_connection {
* "read"\, \c "reconcile"\, \c "recovery"\, \c "recovery_progress"\, \c "rts"\, \c "salvage"\, \c
* "shared_cache"\, \c "split"\, \c "temporary"\, \c "thread_group"\, \c "tiered"\, \c "timestamp"\,
* \c "transaction"\, \c "verify"\, \c "version"\, \c "write"; default \c [].}
* @config{verify_metadata, open connection and verify any WiredTiger metadata. This API allows
* verification and detection of corruption in WiredTiger metadata., a boolean flag; default \c
* false.}
* @config{verify_metadata, open connection and verify any WiredTiger metadata. Not compatible when
* opening a connection from a backup. This API allows verification and detection of corruption in
* WiredTiger metadata., a boolean flag; default \c false.}
* @config{write_through, Use \c FILE_FLAG_WRITE_THROUGH on Windows to write to files. Ignored on
* non-Windows systems. Options are given as a list\, such as <code>"write_through=[data]"</code>.
* Configuring \c write_through requires care\, see @ref tuning_system_buffer_cache_direct_io for

View File

@@ -223,7 +223,7 @@ __wt_turtle_exists(WT_SESSION_IMPL *session, bool *existp)
* Check the turtle file and create if necessary.
*/
int
__wt_turtle_init(WT_SESSION_IMPL *session)
__wt_turtle_init(WT_SESSION_IMPL *session, bool verify_meta)
{
WT_DECL_RET;
char *metaconf, *unused_value;
@@ -307,6 +307,15 @@ __wt_turtle_init(WT_SESSION_IMPL *session)
if (exist_incr)
F_SET(S2C(session), WT_CONN_WAS_BACKUP);
/*
* Verifying the metadata is incompatible with restarting from a backup because the verify
* call will rewrite the metadata's checkpoint and could lead to skipping recovery. Test
* here before creating the metadata file and reading in the backup file.
*/
if (verify_meta && exist_backup)
WT_RET_MSG(
session, EINVAL, "restoring a backup is incompatible with metadata verification");
/* Create the metadata file. */
WT_RET(__metadata_init(session));

View File

@@ -398,8 +398,6 @@ int
__wt_rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_INSERT *ins, WT_ROW *rip,
WT_CELL_UNPACK_KV *vpack, WT_UPDATE_SELECT *upd_select)
{
WT_DECL_ITEM(tmp);
WT_DECL_RET;
WT_PAGE *page;
WT_TIME_WINDOW *select_tw;
WT_UPDATE *first_txn_upd, *first_upd, *onpage_upd, *upd, *last_upd, *tombstone;
@@ -651,7 +649,7 @@ __wt_rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_INSERT *ins, W
* freed when it is written to the disk image in the previous eviction.
*/
if (!F_ISSET(tombstone, WT_UPDATE_RESTORED_FROM_DS | WT_UPDATE_RESTORED_FROM_HS)) {
WT_ERR(__rec_append_orig_value(session, page, tombstone, vpack));
WT_RET(__rec_append_orig_value(session, page, tombstone, vpack));
/*
* We may have updated the global transaction concurrently and the tombstone is now
@@ -710,7 +708,7 @@ __wt_rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_INSERT *ins, W
upd_select->upd;
/* Check the update chain for conditions that could prevent it's eviction. */
WT_ERR(__rec_validate_upd_chain(session, r, onpage_upd, select_tw, vpack));
WT_RET(__rec_validate_upd_chain(session, r, onpage_upd, select_tw, vpack));
/*
* Fixup any out of order timestamps, assert that checkpoint wasn't running when this round of
@@ -724,7 +722,7 @@ __wt_rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_INSERT *ins, W
/* Catch this case in diagnostic builds. */
WT_STAT_CONN_DATA_INCR(session, cache_eviction_blocked_ooo_checkpoint_race_3);
WT_ASSERT(session, false);
WT_ERR(EBUSY);
WT_RET(EBUSY);
}
/*
@@ -742,7 +740,7 @@ __wt_rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_INSERT *ins, W
supd_restore = F_ISSET(r, WT_REC_EVICT) &&
(has_newer_updates || F_ISSET(S2C(session), WT_CONN_IN_MEMORY));
WT_ERR(__rec_update_save(session, r, ins, rip, onpage_upd, supd_restore, upd_memsize));
WT_RET(__rec_update_save(session, r, ins, rip, onpage_upd, supd_restore, upd_memsize));
/*
* Mark the selected update (and potentially the tombstone preceding it) as being destined
@@ -788,10 +786,9 @@ __wt_rec_upd_select(WT_SESSION_IMPL *session, WT_RECONCILE *r, WT_INSERT *ins, W
*/
if (upd_select->upd != NULL && vpack != NULL && vpack->type != WT_CELL_DEL &&
!vpack->tw.prepare && (upd_saved || F_ISSET(vpack, WT_CELL_UNPACK_OVERFLOW)))
WT_ERR(__rec_append_orig_value(session, page, upd_select->upd, vpack));
WT_RET(__rec_append_orig_value(session, page, upd_select->upd, vpack));
__wt_rec_time_window_clear_obsolete(session, upd_select, NULL, r);
err:
__wt_scr_free(session, &tmp);
return (ret);
return (0);
}

View File

@@ -1438,9 +1438,15 @@ __rollback_to_stable_hs_final_pass(WT_SESSION_IMPL *session, wt_timestamp_t roll
/*
* The rollback operation should be performed on the history store file when the checkpoint
* durable start/stop timestamp is greater than the rollback timestamp.
* durable start/stop timestamp is greater than the rollback timestamp. But skip if there is no
* stable timestamp.
*
* Note that the corresponding code in __rollback_to_stable_btree_apply also checks whether
* there _are_ timestamped updates by checking max_durable_ts; that check is redundant here for
* several reasons, the most immediate being that max_durable_ts cannot be none (zero) because
* it's greater than rollback_timestamp, which is itself greater than zero.
*/
if (max_durable_ts > rollback_timestamp) {
if (max_durable_ts > rollback_timestamp && rollback_timestamp != WT_TS_NONE) {
__wt_verbose_multi(session, WT_VERB_RECOVERY_RTS(session),
"tree rolled back with durable timestamp: %s",
__wt_timestamp_to_string(max_durable_ts, ts_string[0]));
@@ -1494,7 +1500,6 @@ __rollback_to_stable_btree_apply(
WT_CONFIG ckptconf;
WT_CONFIG_ITEM cval, value, key;
WT_DECL_RET;
WT_TXN_GLOBAL *txn_global;
wt_timestamp_t max_durable_ts, newest_start_durable_ts, newest_stop_durable_ts;
size_t addr_size;
uint64_t rollback_txnid, write_gen;
@@ -1507,7 +1512,6 @@ __rollback_to_stable_btree_apply(
if (!WT_BTREE_PREFIX(uri) || strcmp(uri, WT_HS_URI) == 0 || strcmp(uri, WT_METAFILE_URI) == 0)
return (0);
txn_global = &S2C(session)->txn_global;
addr_size = 0;
rollback_txnid = 0;
write_gen = 0;
@@ -1574,8 +1578,7 @@ __rollback_to_stable_btree_apply(
*/
if ((F_ISSET(S2C(session), WT_CONN_RECOVERING) ||
F_ISSET(S2C(session), WT_CONN_CLOSING_TIMESTAMP)) &&
(addr_size == 0 ||
(txn_global->stable_timestamp == WT_TS_NONE && max_durable_ts != WT_TS_NONE))) {
(addr_size == 0 || (rollback_timestamp == WT_TS_NONE && max_durable_ts != WT_TS_NONE))) {
__wt_verbose_multi(session, WT_VERB_RECOVERY_RTS(session),
"skip rollback to stable on file %s because %s", uri,
addr_size == 0 ? "its checkpoint address length is 0" :

View File

@@ -243,7 +243,7 @@ thread_flush_run(void *arg)
*/
(void)unlink(sentinel_file);
testutil_check(td->conn->open_session(td->conn, NULL, NULL, &session));
for (i = 0;; ++i) {
for (i = 0;;) {
sleep_time = __wt_random(&rnd) % MAX_FLUSH_INVL;
sleep(sleep_time);
testutil_check(td->conn->query_timestamp(td->conn, ts_string, "get=last_checkpoint"));
@@ -264,7 +264,7 @@ thread_flush_run(void *arg)
* Create the sentinel file so that the parent process knows the desired number of
* flush_tier calls have finished and can start its timer.
*/
if (i == flush_calls) {
if (++i == flush_calls) {
testutil_assert_errno((fp = fopen(sentinel_file, "w")) != NULL);
testutil_assert_errno(fclose(fp) == 0);
}

View File

@@ -19,6 +19,7 @@ post:
- func: "cleanup"
timeout:
- func: "run wt hang analyzer"
exec_timeout_secs: 21600 # 6 hrs
#######################################
# Functions #

View File

@@ -65,7 +65,7 @@ check_copy(void)
/* Now setup and open the path for real. */
testutil_check(__wt_snprintf(path, len, "%s/BACKUP", g.home));
wts_open(path, &conn, &session, true);
wts_open(path, &conn, &session, false);
/* Verify the objects. */
tables_apply(wts_verify, conn);

View File

@@ -0,0 +1,101 @@
#!/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.
from helper import copy_wiredtiger_home
from suite_subprocess import suite_subprocess
import os
import shutil
import wiredtiger, wttest
# test_backup.py
# Test error message if verifying metadata on a backup restore.
class test_backup23(wttest.WiredTigerTestCase, suite_subprocess):
'''Test backup, verifying metadata and an error opening the backup'''
#conn_config = 'config_base=false,log=(archive=false,enabled),verbose=(recovery,log)'
conn_config = 'config_base=false,log=(archive=false,enabled)'
conn_config_err = 'config_base=false,log=(archive=false,enabled),verify_metadata=true'
#conn_config_err = 'config_base=false,log=(archive=false,enabled),verify_metadata=true,verbose=(recovery,log)'
dir='backup.dir'
nentries = 10
uri = 'file:backup.wt'
def take_full_backup(self, dir):
# Open up the backup cursor, and copy the files. Do a full backup.
cursor = self.session.open_cursor('backup:', None, None)
self.pr('Full backup to ' + dir + ': ')
os.mkdir(dir)
while True:
ret = cursor.next()
if ret != 0:
break
bkup_file = cursor.get_key()
sz = os.path.getsize(bkup_file)
self.pr('Copy from: ' + bkup_file + ' (' + str(sz) + ') to ' + dir)
shutil.copy(bkup_file, dir)
self.assertEqual(ret, wiredtiger.WT_NOTFOUND)
cursor.close()
def test_backup23(self):
'''Test backup, verifying metadata and an error opening the backup'''
self.session.create(self.uri, 'key_format=i,value_format=i')
c = self.session.open_cursor(self.uri)
self.session.begin_transaction()
for i in range(self.nentries):
c[i] = i
self.session.commit_transaction()
self.session.checkpoint()
# Add more entries after the check point. They should be recovered.
self.session.begin_transaction()
for i in range(self.nentries):
c[i + self.nentries] = i
self.session.commit_transaction()
c.close()
orig_data = list(self.session.open_cursor(self.uri))
# Take a full backup.
self.take_full_backup(self.dir)
self.close_conn()
msg = '/restoring a backup is incompatible/'
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.wiredtiger_open(self.dir, self.conn_config_err), msg)
self.pr('try opening error directory with correct config')
# After getting the error we should be able to open the error backup directory with the
# correct setting and then also see our data.
self.conn = self.wiredtiger_open(self.dir, self.conn_config)
session = self.conn.open_session()
bkup_data = list(session.open_cursor(self.uri))
self.assertEqual(orig_data, bkup_data)
if __name__ == '__main__':
wttest.run()

View File

@@ -0,0 +1,118 @@
#!/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.
from test_rollback_to_stable01 import test_rollback_to_stable_base
from helper import simulate_crash_restart
from wtdataset import SimpleDataSet
from wtscenario import make_scenarios
# test_rollback_to_stable31.py
# Check what happens with RTS if you never set the stable timestamp.
class test_rollback_to_stable31(test_rollback_to_stable_base):
session_config = 'isolation=snapshot'
format_values = [
('column', dict(key_format='r', value_format='S')),
('column_fix', dict(key_format='r', value_format='8t')),
('integer_row', dict(key_format='i', value_format='S')),
]
checkpoint_modes = [
('no-checkpoint', dict(checkpoint=False)),
('checkpoint', dict(checkpoint=True)),
]
rollback_modes = [
('runtime', dict(crash=False)),
('recovery', dict(crash=True)),
]
scenarios = make_scenarios(format_values, checkpoint_modes, rollback_modes)
def test_rollback_to_stable(self):
nrows = 10
# Create a table without logging.
uri = "table:rollback_to_stable31"
ds = SimpleDataSet(
self, uri, 0, key_format=self.key_format, value_format=self.value_format,
config='log=(enabled=false)')
ds.populate()
if self.value_format == '8t':
value_a = 97
value_b = 98
value_c = 99
else:
value_a = "aaaaa" * 10
value_b = "bbbbb" * 10
value_c = "ccccc" * 10
# Do not set stable. (Don't set oldest either as it can't be later than stable.)
# Write aaaaaa to all the keys at time 10.
self.large_updates(uri, value_a, ds, nrows, False, 10)
# Write bbbbbb to all the keys at time 20.
self.large_updates(uri, value_b, ds, nrows, False, 20)
# Write cccccc to all the keys at time 30.
self.large_updates(uri, value_c, ds, nrows, False, 30)
# Optionally checkpoint.
if self.checkpoint:
self.session.checkpoint()
# Roll back, either via crashing or by explicit RTS.
if self.crash:
simulate_crash_restart(self, ".", "RESTART")
else:
self.conn.rollback_to_stable()
if self.crash:
if self.checkpoint:
# Recovery-time RTS does nothing when no stable timestamp is set.
self.check(0, uri, 0, nrows, 5)
self.check(value_a, uri, nrows, 0, 15)
self.check(value_b, uri, nrows, 0, 25)
self.check(value_c, uri, nrows, 0, 35)
else:
# If we crashed without a checkpoint, everything should disappear entirely.
self.check(0, uri, 0, 0, 5)
self.check(value_a, uri, 0, 0, 15)
self.check(value_b, uri, 0, 0, 25)
self.check(value_c, uri, 0, 0, 35)
else:
# With an explicit runtime RTS we roll back to 0, but the end of the FLCS table
# still moves forward.
self.check(0, uri, 0, nrows, 5)
self.check(value_a, uri, 0, nrows, 15)
self.check(value_b, uri, 0, nrows, 25)
self.check(value_c, uri, 0, nrows, 35)
if __name__ == '__main__':
wttest.run()