diff options
author | Luke Chen <luke.chen@mongodb.com> | 2018-06-14 14:30:37 +1000 |
---|---|---|
committer | Luke Chen <luke.chen@mongodb.com> | 2018-06-14 14:30:37 +1000 |
commit | 637de7eb8646122684bc9a56a16a977debcfb454 (patch) | |
tree | 117c7335a5dbb12652d221ca47cd77e274ca30a1 | |
parent | 9aa2a05618d984b1cb23783ab9ebc49b8cfc654a (diff) | |
download | mongo-637de7eb8646122684bc9a56a16a977debcfb454.tar.gz |
Import wiredtiger: 7d3e691fd4d5ba7810647c317692129fea694602 from branch mongodb-4.0
ref: d16557c82c..7d3e691fd4
for: 4.1.1
WT-4071 Run unit tests with timestamps disabled
WT-4115 Valgrind error in est_wt4105_large_doc_small_upd
WT-4116 Coverity #1393311 Copy-paste error
WT-4117 Expose WiredTiger crc32c function
WT-4120 Enhance test/format to dump the cache when timing out
WT-4122 Ensure compatibility downgrade cleans up old log files
WT-4127 Add common prefix for compatibility version errors
WT-4128 Skip checkpoints while stable timestamp doesn't change
34 files changed, 542 insertions, 131 deletions
diff --git a/src/third_party/wiredtiger/build_win/wiredtiger.def b/src/third_party/wiredtiger/build_win/wiredtiger.def index 25e7a01e0d9..3ee9f6b6a9d 100644 --- a/src/third_party/wiredtiger/build_win/wiredtiger.def +++ b/src/third_party/wiredtiger/build_win/wiredtiger.def @@ -1,5 +1,6 @@ LIBRARY WIREDTIGER EXPORTS + wiredtiger_checksum_crc32c wiredtiger_config_parser_open wiredtiger_config_validate wiredtiger_open diff --git a/src/third_party/wiredtiger/dist/s_export.list b/src/third_party/wiredtiger/dist/s_export.list index c7f088bc2d5..72ce553ac9b 100644 --- a/src/third_party/wiredtiger/dist/s_export.list +++ b/src/third_party/wiredtiger/dist/s_export.list @@ -1,4 +1,5 @@ # List of OK external symbols. +wiredtiger_checksum_crc32c wiredtiger_config_parser_open wiredtiger_config_validate wiredtiger_open diff --git a/src/third_party/wiredtiger/dist/s_funcs.list b/src/third_party/wiredtiger/dist/s_funcs.list index 95c568a19ff..eed29e91fc1 100644 --- a/src/third_party/wiredtiger/dist/s_funcs.list +++ b/src/third_party/wiredtiger/dist/s_funcs.list @@ -33,6 +33,7 @@ __wt_stat_join_aggregate __wt_stat_join_clear_all __wt_stream_set_no_buffer __wt_try_readlock +wiredtiger_checksum_crc32c wiredtiger_config_parser_open wiredtiger_config_validate wiredtiger_pack_int diff --git a/src/third_party/wiredtiger/dist/stat_data.py b/src/third_party/wiredtiger/dist/stat_data.py index 32927b56625..c1b43ac6b2d 100644 --- a/src/third_party/wiredtiger/dist/stat_data.py +++ b/src/third_party/wiredtiger/dist/stat_data.py @@ -370,7 +370,7 @@ connection_stats = [ LogStat('log_compress_write_fails', 'log records not compressed'), LogStat('log_compress_writes', 'log records compressed'), LogStat('log_flush', 'log flush operations'), - LogStat('log_force_ckpt_sleep', 'force checkpoint calls slept'), + LogStat('log_force_archive_sleep', 'force archive time sleeping (usecs)'), LogStat('log_force_write', 'log force write operations'), LogStat('log_force_write_skip', 'log force write operations skipped'), LogStat('log_max_filesize', 'maximum log file size', 'no_clear,no_scale,size'), diff --git a/src/third_party/wiredtiger/examples/c/ex_all.c b/src/third_party/wiredtiger/examples/c/ex_all.c index 1aa648f01c0..139f39fe673 100644 --- a/src/third_party/wiredtiger/examples/c/ex_all.c +++ b/src/third_party/wiredtiger/examples/c/ex_all.c @@ -1352,5 +1352,15 @@ main(int argc, char *argv[]) /*! [Get the WiredTiger library version #2] */ } + { + const char *buffer = "some string"; + size_t len = strlen(buffer); + /*! [Checksum a buffer] */ + uint32_t crc32c; + crc32c = wiredtiger_checksum_crc32c(buffer, len); + /*! [Checksum a buffer] */ + (void)crc32c; + } + return (EXIT_SUCCESS); } diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index 7a2886a3fe1..702b2430339 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -1,5 +1,5 @@ { - "commit": "d16557c82ca66ff220238299d0f7c9a182d1720e", + "commit": "7d3e691fd4d5ba7810647c317692129fea694602", "github": "wiredtiger/wiredtiger.git", "vendor": "wiredtiger", "branch": "mongodb-4.0" diff --git a/src/third_party/wiredtiger/src/checksum/arm64/crc32-arm64.c b/src/third_party/wiredtiger/src/checksum/arm64/crc32-arm64.c index d0c989fd757..01740dcd953 100644 --- a/src/third_party/wiredtiger/src/checksum/arm64/crc32-arm64.c +++ b/src/third_party/wiredtiger/src/checksum/arm64/crc32-arm64.c @@ -90,6 +90,7 @@ __wt_checksum_hw(const void *chunk, size_t len) */ void __wt_checksum_init(void) + WT_GCC_FUNC_ATTRIBUTE((cold)) { #if defined(__linux__) && defined(HAVE_CRC32_HARDWARE) unsigned long caps = getauxval(AT_HWCAP); diff --git a/src/third_party/wiredtiger/src/checksum/power8/crc32_wrapper.c b/src/third_party/wiredtiger/src/checksum/power8/crc32_wrapper.c index a9be9ced1c6..8626fa42136 100644 --- a/src/third_party/wiredtiger/src/checksum/power8/crc32_wrapper.c +++ b/src/third_party/wiredtiger/src/checksum/power8/crc32_wrapper.c @@ -86,6 +86,7 @@ __wt_checksum_hw(const void *chunk, size_t len) */ void __wt_checksum_init(void) + WT_GCC_FUNC_ATTRIBUTE((cold)) { #if defined(HAVE_CRC32_HARDWARE) __wt_process.checksum = __wt_checksum_hw; diff --git a/src/third_party/wiredtiger/src/checksum/x86/crc32-x86.c b/src/third_party/wiredtiger/src/checksum/x86/crc32-x86.c index 8de987d4fc9..73199018a7d 100644 --- a/src/third_party/wiredtiger/src/checksum/x86/crc32-x86.c +++ b/src/third_party/wiredtiger/src/checksum/x86/crc32-x86.c @@ -124,6 +124,7 @@ __wt_checksum_hw(const void *chunk, size_t len) */ void __wt_checksum_init(void) + WT_GCC_FUNC_ATTRIBUTE((cold)) { #if defined(HAVE_CRC32_HARDWARE) #if (defined(__amd64) || defined(__x86_64)) diff --git a/src/third_party/wiredtiger/src/checksum/zseries/crc32-s390x.c b/src/third_party/wiredtiger/src/checksum/zseries/crc32-s390x.c index ae024391ff7..ec7adb02cba 100644 --- a/src/third_party/wiredtiger/src/checksum/zseries/crc32-s390x.c +++ b/src/third_party/wiredtiger/src/checksum/zseries/crc32-s390x.c @@ -98,6 +98,7 @@ __wt_checksum_hw(const void *chunk, size_t len) */ void __wt_checksum_init(void) + WT_GCC_FUNC_ATTRIBUTE((cold)) { #if defined(__linux__) && defined(HAVE_CRC32_HARDWARE) unsigned long caps = getauxval(AT_HWCAP); diff --git a/src/third_party/wiredtiger/src/conn/conn_api.c b/src/third_party/wiredtiger/src/conn/conn_api.c index a413e31d1c9..d322caac04a 100644 --- a/src/third_party/wiredtiger/src/conn/conn_api.c +++ b/src/third_party/wiredtiger/src/conn/conn_api.c @@ -2748,3 +2748,15 @@ err: /* Discard the scratch buffers. */ return (ret); } + +/* + * wiredtiger_checksum_crc32c -- + * CRC32C checksum function entry point. + */ +uint32_t +wiredtiger_checksum_crc32c(const void *buffer, size_t len) +{ + if (__wt_process.checksum == NULL) + __wt_checksum_init(); + return (__wt_process.checksum(buffer, len)); +} diff --git a/src/third_party/wiredtiger/src/conn/conn_ckpt.c b/src/third_party/wiredtiger/src/conn/conn_ckpt.c index d302a59c928..8691a72cc47 100644 --- a/src/third_party/wiredtiger/src/conn/conn_ckpt.c +++ b/src/third_party/wiredtiger/src/conn/conn_ckpt.c @@ -83,6 +83,7 @@ __ckpt_server(void *arg) WT_DECL_RET; WT_SESSION *wt_session; WT_SESSION_IMPL *session; + uint64_t checkpoint_gen; session = arg; conn = S2C(session); @@ -101,37 +102,27 @@ __ckpt_server(void *arg) if (!__ckpt_server_run_chk(session)) break; + checkpoint_gen = __wt_gen(session, WT_GEN_CHECKPOINT); + WT_ERR(wt_session->checkpoint(wt_session, NULL)); + /* - * Checkpoint the database if the connection is marked dirty. - * A connection is marked dirty whenever a btree gets marked - * dirty, which reflects upon a change in the database that - * needs to be checkpointed. Said that, there can be short - * instances when a btree gets marked dirty and the connection - * is yet to be. We might skip a checkpoint in that short - * instance, which is okay because by the next time we get to - * checkpoint, the connection would have been marked dirty and - * hence the checkpoint will not be skipped this time. + * Reset the log file size counters if the checkpoint wasn't + * skipped. */ - if (conn->modified) { - WT_ERR(wt_session->checkpoint(wt_session, NULL)); - - /* Reset. */ - if (conn->ckpt_logsize) { - __wt_log_written_reset(session); - conn->ckpt_signalled = false; - - /* - * In case we crossed the log limit during the - * checkpoint and the condition variable was - * already signalled, do a tiny wait to clear - * it so we don't do another checkpoint - * immediately. - */ - __wt_cond_wait( - session, conn->ckpt_cond, 1, NULL); - } - } else - WT_STAT_CONN_INCR(session, txn_checkpoint_skipped); + if (checkpoint_gen != __wt_gen(session, WT_GEN_CHECKPOINT) && + conn->ckpt_logsize) { + __wt_log_written_reset(session); + conn->ckpt_signalled = false; + + /* + * In case we crossed the log limit during the + * checkpoint and the condition variable was + * already signalled, do a tiny wait to clear + * it so we don't do another checkpoint + * immediately. + */ + __wt_cond_wait(session, conn->ckpt_cond, 1, NULL); + } } if (0) { diff --git a/src/third_party/wiredtiger/src/conn/conn_log.c b/src/third_party/wiredtiger/src/conn/conn_log.c index 0599d491ccb..d8eb095d6d2 100644 --- a/src/third_party/wiredtiger/src/conn/conn_log.c +++ b/src/third_party/wiredtiger/src/conn/conn_log.c @@ -40,24 +40,25 @@ __logmgr_sync_cfg(WT_SESSION_IMPL *session, const char **cfg) } /* - * __logmgr_force_ckpt -- - * Force a checkpoint out, waiting for the checkpoint LSN in the log - * is up to the given log number. + * __logmgr_force_archive -- + * Force a checkpoint out and then force an archive, waiting for the + * first log to be archived up to the given log number. */ static int -__logmgr_force_ckpt(WT_SESSION_IMPL *session, uint32_t lognum) +__logmgr_force_archive(WT_SESSION_IMPL *session, uint32_t lognum) { WT_CONNECTION_IMPL *conn; WT_LOG *log; WT_SESSION_IMPL *tmp_session; - int yield; + uint64_t sleep_usecs, yield_cnt; conn = S2C(session); log = conn->log; - yield = 0; + sleep_usecs = yield_cnt = 0; + WT_RET(__wt_open_internal_session(conn, "compatibility-reconfig", true, 0, &tmp_session)); - while (log->ckpt_lsn.l.file < lognum) { + while (log->first_lsn.l.file < lognum) { /* * Force a checkpoint to be written in the new log file and * force the archiving of all previous log files. We do the @@ -69,15 +70,16 @@ __logmgr_force_ckpt(WT_SESSION_IMPL *session, uint32_t lognum) */ WT_RET(tmp_session->iface.checkpoint( &tmp_session->iface, "force=1")); - WT_RET(WT_SESSION_CHECK_PANIC(tmp_session)); /* - * Only sleep in the rare case that we had to come through - * this loop more than once. + * It's reasonable to start the back off prior to trying at all + * because the backoff is very gradual. */ - if (yield++) { - WT_STAT_CONN_INCR(session, log_force_ckpt_sleep); - __wt_sleep(0, WT_THOUSAND); - } + __wt_spin_backoff(&yield_cnt, &sleep_usecs); + WT_STAT_CONN_INCRV(session, + log_force_archive_sleep, sleep_usecs); + + WT_RET(WT_SESSION_CHECK_PANIC(tmp_session)); + WT_RET(__wt_log_truncate_files(tmp_session, NULL, true)); } WT_RET(tmp_session->iface.close(&tmp_session->iface, NULL)); return (0); @@ -105,6 +107,10 @@ __logmgr_version(WT_SESSION_IMPL *session, bool reconfig) * Set the log file format versions based on compatibility versions * set in the connection. We must set this before we call log_open * to open or create a log file. + * + * Note: downgrade in this context means the new version is not the + * latest possible version. It does not mean the direction of change + * from the release we may be running currently. */ if (conn->compat_major < WT_LOG_V2_MAJOR) { new_version = 1; @@ -167,7 +173,7 @@ __logmgr_version(WT_SESSION_IMPL *session, bool reconfig) WT_RET(__wt_log_set_version(session, new_version, first_record, downgrade, reconfig, &lognum)); if (reconfig && FLD_ISSET(conn->log_flags, WT_CONN_LOG_DOWNGRADED)) - WT_RET(__logmgr_force_ckpt(session, lognum)); + WT_RET(__logmgr_force_archive(session, lognum)); return (0); } diff --git a/src/third_party/wiredtiger/src/conn/conn_reconfig.c b/src/third_party/wiredtiger/src/conn/conn_reconfig.c index ae774ae58c0..8672e824579 100644 --- a/src/third_party/wiredtiger/src/conn/conn_reconfig.c +++ b/src/third_party/wiredtiger/src/conn/conn_reconfig.c @@ -31,10 +31,12 @@ __conn_compat_parse(WT_SESSION_IMPL *session, "illegal compatibility release"); if (*majorp > WIREDTIGER_VERSION_MAJOR) WT_RET_MSG(session, ENOTSUP, + WT_COMPAT_MSG_PREFIX "unsupported major version"); if (*majorp == WIREDTIGER_VERSION_MAJOR && *minorp > WIREDTIGER_VERSION_MINOR) WT_RET_MSG(session, ENOTSUP, + WT_COMPAT_MSG_PREFIX "unsupported minor version"); return (0); } @@ -115,6 +117,7 @@ __wt_conn_compat_config( (max_major < rel_major || (max_major == rel_major && max_minor < rel_minor))) WT_RET_MSG(session, ENOTSUP, + WT_COMPAT_MSG_PREFIX "required max of %" PRIu16 ".%" PRIu16 "cannot be smaller than compatibility release %" PRIu16 ".%" PRIu16, @@ -130,6 +133,7 @@ __wt_conn_compat_config( (min_major > rel_major || (min_major == rel_major && min_minor > rel_minor))) WT_RET_MSG(session, ENOTSUP, + WT_COMPAT_MSG_PREFIX "required min of %" PRIu16 ".%" PRIu16 "cannot be larger than compatibility release %" PRIu16 ".%" PRIu16, @@ -144,6 +148,7 @@ __wt_conn_compat_config( (conn->req_max_major == rel_major && conn->req_max_minor < rel_minor))) WT_RET_MSG(session, ENOTSUP, + WT_COMPAT_MSG_PREFIX "required max of %" PRIu16 ".%" PRIu16 "cannot be smaller than requested compatibility release %" PRIu16 ".%" PRIu16, @@ -159,6 +164,7 @@ __wt_conn_compat_config( (conn->req_min_major == rel_major && conn->req_min_minor > rel_minor))) WT_RET_MSG(session, ENOTSUP, + WT_COMPAT_MSG_PREFIX "required min of %" PRIu16 ".%" PRIu16 "cannot be larger than requested compatibility release %" PRIu16 ".%" PRIu16, @@ -202,6 +208,7 @@ __wt_conn_compat_config( (max_major < rel_major || (max_major == rel_major && max_minor < rel_minor))) WT_ERR_MSG(session, ENOTSUP, + WT_COMPAT_MSG_PREFIX "required max of %" PRIu16 ".%" PRIu16 "cannot be larger than saved release %" PRIu16 ".%" PRIu16, @@ -210,6 +217,7 @@ __wt_conn_compat_config( (min_major > rel_major || (min_major == rel_major && min_minor > rel_minor))) WT_ERR_MSG(session, ENOTSUP, + WT_COMPAT_MSG_PREFIX "required min of %" PRIu16 ".%" PRIu16 "cannot be larger than saved release %" PRIu16 ".%" PRIu16, diff --git a/src/third_party/wiredtiger/src/include/error.h b/src/third_party/wiredtiger/src/include/error.h index 601d99ac251..f94c3d7b880 100644 --- a/src/third_party/wiredtiger/src/include/error.h +++ b/src/third_party/wiredtiger/src/include/error.h @@ -5,6 +5,7 @@ * * See the file LICENSE for redistribution information. */ +#define WT_COMPAT_MSG_PREFIX "Version incompatibility detected: " #define WT_DEBUG_POINT ((void *)(uintptr_t)0xdeadbeef) #define WT_DEBUG_BYTE (0xab) diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h index 004c3fcd2e3..7e2d4a4786d 100644 --- a/src/third_party/wiredtiger/src/include/extern.h +++ b/src/third_party/wiredtiger/src/include/extern.h @@ -216,7 +216,7 @@ extern int __wt_las_remove_block(WT_SESSION_IMPL *session, uint64_t pageid, bool extern int __wt_las_save_dropped(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern int __wt_las_sweep(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern uint32_t __wt_checksum_sw(const void *chunk, size_t len) WT_GCC_FUNC_DECL_ATTRIBUTE((visibility("default"))); -extern void __wt_checksum_init(void); +extern void __wt_checksum_init(void) WT_GCC_FUNC_DECL_ATTRIBUTE((cold)); extern void __wt_config_initn(WT_SESSION_IMPL *session, WT_CONFIG *conf, const char *str, size_t len); extern void __wt_config_init(WT_SESSION_IMPL *session, WT_CONFIG *conf, const char *str); extern void __wt_config_subinit(WT_SESSION_IMPL *session, WT_CONFIG *conf, WT_CONFIG_ITEM *item); diff --git a/src/third_party/wiredtiger/src/include/stat.h b/src/third_party/wiredtiger/src/include/stat.h index a4e28e59826..77e0fa85b0f 100644 --- a/src/third_party/wiredtiger/src/include/stat.h +++ b/src/third_party/wiredtiger/src/include/stat.h @@ -508,7 +508,7 @@ struct __wt_connection_stats { int64_t lock_txn_global_read_count; int64_t lock_txn_global_write_count; int64_t log_slot_switch_busy; - int64_t log_force_ckpt_sleep; + int64_t log_force_archive_sleep; int64_t log_bytes_payload; int64_t log_bytes_written; int64_t log_zero_fills; diff --git a/src/third_party/wiredtiger/src/include/wiredtiger.in b/src/third_party/wiredtiger/src/include/wiredtiger.in index 9e0b5d4f02c..2991d6f74e3 100644 --- a/src/third_party/wiredtiger/src/include/wiredtiger.in +++ b/src/third_party/wiredtiger/src/include/wiredtiger.in @@ -3518,10 +3518,33 @@ struct __wt_config_parser { const char *key, WT_CONFIG_ITEM *value); }; -#endif /* !defined(SWIG) */ /*! @} */ /*! + * @name Support functions + * @anchor support_functions + * @{ + */ + +/*! + * Return a buffer's CRC32C checksum. + * + * The WiredTiger library CRC32C checksum function uses hardware support where + * available, else it falls back to a software implementation. + * + * @snippet ex_all.c Checksum a buffer + * + * @param buffer a pointer to a buffer + * @param len the number of valid bytes in the buffer + * @returns the buffer's CRC32C checksum + */ +uint32_t wiredtiger_checksum_crc32c(const void *buffer, size_t len) + WT_ATTRIBUTE_LIBRARY_VISIBLE; + +/*! @} */ +#endif /* !defined(SWIG) */ + +/*! * Get version information. * * @snippet ex_all.c Get the WiredTiger library version #1 @@ -5326,8 +5349,8 @@ extern int wiredtiger_extension_terminate(WT_CONNECTION *connection); #define WT_STAT_CONN_LOCK_TXN_GLOBAL_WRITE_COUNT 1193 /*! log: busy returns attempting to switch slots */ #define WT_STAT_CONN_LOG_SLOT_SWITCH_BUSY 1194 -/*! log: force checkpoint calls slept */ -#define WT_STAT_CONN_LOG_FORCE_CKPT_SLEEP 1195 +/*! log: force archive time sleeping (usecs) */ +#define WT_STAT_CONN_LOG_FORCE_ARCHIVE_SLEEP 1195 /*! log: log bytes of payload data */ #define WT_STAT_CONN_LOG_BYTES_PAYLOAD 1196 /*! log: log bytes written */ diff --git a/src/third_party/wiredtiger/src/log/log.c b/src/third_party/wiredtiger/src/log/log.c index 8dfd0c0d153..6ce26e03c5d 100644 --- a/src/third_party/wiredtiger/src/log/log.c +++ b/src/third_party/wiredtiger/src/log/log.c @@ -975,12 +975,13 @@ __log_open_verify(WT_SESSION_IMPL *session, uint32_t id, WT_FH **fhp, WT_LOG_VERSION, desc->version); /* - * We error if the log version is less than the required minimum - * or larger than the required maximum. + * We error if the log version is less than the required minimum or + * larger than the required maximum. */ if (conn->req_max_major != WT_CONN_COMPAT_NONE && desc->version > conn->log_req_max) WT_ERR_MSG(session, WT_ERROR, + WT_COMPAT_MSG_PREFIX "unsupported WiredTiger file version: this build" " requires a maximum version of %" PRIu16 "," " and the file is version %" PRIu16, @@ -989,13 +990,14 @@ __log_open_verify(WT_SESSION_IMPL *session, uint32_t id, WT_FH **fhp, if (conn->req_min_major != WT_CONN_COMPAT_NONE && desc->version < conn->log_req_min) WT_ERR_MSG(session, WT_ERROR, + WT_COMPAT_MSG_PREFIX "unsupported WiredTiger file version: this build" " requires a minimum version of %" PRIu16 "," " and the file is version %" PRIu16, conn->log_req_min, desc->version); /* - * Set up the return values if the magic number is valid. + * Set up the return values since the header is valid. */ if (versionp != NULL) *versionp = desc->version; diff --git a/src/third_party/wiredtiger/src/support/stat.c b/src/third_party/wiredtiger/src/support/stat.c index 4edafcbb8ce..749564c2464 100644 --- a/src/third_party/wiredtiger/src/support/stat.c +++ b/src/third_party/wiredtiger/src/support/stat.c @@ -942,7 +942,7 @@ static const char * const __stats_connection_desc[] = { "lock: txn global read lock acquisitions", "lock: txn global write lock acquisitions", "log: busy returns attempting to switch slots", - "log: force checkpoint calls slept", + "log: force archive time sleeping (usecs)", "log: log bytes of payload data", "log: log bytes written", "log: log files manually zero-filled", @@ -1339,7 +1339,7 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats) stats->lock_txn_global_read_count = 0; stats->lock_txn_global_write_count = 0; stats->log_slot_switch_busy = 0; - stats->log_force_ckpt_sleep = 0; + stats->log_force_archive_sleep = 0; stats->log_bytes_payload = 0; stats->log_bytes_written = 0; stats->log_zero_fills = 0; @@ -1807,7 +1807,8 @@ __wt_stat_connection_aggregate( to->lock_txn_global_write_count += WT_STAT_READ(from, lock_txn_global_write_count); to->log_slot_switch_busy += WT_STAT_READ(from, log_slot_switch_busy); - to->log_force_ckpt_sleep += WT_STAT_READ(from, log_force_ckpt_sleep); + to->log_force_archive_sleep += + WT_STAT_READ(from, log_force_archive_sleep); to->log_bytes_payload += WT_STAT_READ(from, log_bytes_payload); to->log_bytes_written += WT_STAT_READ(from, log_bytes_written); to->log_zero_fills += WT_STAT_READ(from, log_zero_fills); diff --git a/src/third_party/wiredtiger/src/txn/txn_ckpt.c b/src/third_party/wiredtiger/src/txn/txn_ckpt.c index dd5eb99750b..10af61caeaf 100644 --- a/src/third_party/wiredtiger/src/txn/txn_ckpt.c +++ b/src/third_party/wiredtiger/src/txn/txn_ckpt.c @@ -126,7 +126,7 @@ __checkpoint_update_generation(WT_SESSION_IMPL *session) */ static int __checkpoint_apply_all(WT_SESSION_IMPL *session, const char *cfg[], - int (*op)(WT_SESSION_IMPL *, const char *[]), bool *fullp) + int (*op)(WT_SESSION_IMPL *, const char *[])) { WT_CONFIG targetconf; WT_CONFIG_ITEM cval, k, v; @@ -196,9 +196,6 @@ __checkpoint_apply_all(WT_SESSION_IMPL *session, const char *cfg[], __wt_conn_btree_apply(session, NULL, op, NULL, cfg)); } - if (fullp != NULL) - *fullp = !target_list; - err: __wt_scr_free(session, &tmp); return (ret); } @@ -767,11 +764,101 @@ __checkpoint_prepare( */ WT_ASSERT(session, session->ckpt_handle_next == 0); WT_WITH_TABLE_READ_LOCK(session, ret = __checkpoint_apply_all( - session, cfg, __wt_checkpoint_get_handles, NULL)); + session, cfg, __wt_checkpoint_get_handles)); return (ret); } /* + * __txn_checkpoint_can_skip -- + * Determine whether it's safe to skip taking a checkpoint. + */ +static int +__txn_checkpoint_can_skip(WT_SESSION_IMPL *session, + const char *cfg[], bool *fullp, bool *use_timestampp, bool *can_skipp) +{ + WT_CONFIG targetconf; + WT_CONFIG_ITEM cval, k, v; + WT_CONNECTION_IMPL *conn; + WT_TXN_GLOBAL *txn_global; + bool full, use_timestamp; + + /* + * Default to not skipping - also initialize the other output + * parameters - even though they will always be initialized unless + * there is an error and callers need to ignore the results on error. + */ + *can_skipp = *fullp = *use_timestampp = false; + + conn = S2C(session); + txn_global = &conn->txn_global; + + /* + * This function also parses out some configuration options and hands + * them back to the caller - make sure it does that parsing regardless + * of the result. + * + * Determine if this is going to be a full checkpoint, that is a + * checkpoint that applies to all data tables in a database. + */ + WT_RET(__wt_config_gets(session, cfg, "target", &cval)); + __wt_config_subinit(session, &targetconf, &cval); + full = __wt_config_next(&targetconf, &k, &v) != 0; + if (fullp != NULL) + *fullp = full; + + WT_RET(__wt_config_gets(session, cfg, "use_timestamp", &cval)); + use_timestamp = cval.val != 0; + if (use_timestampp != NULL) + *use_timestampp = use_timestamp; + + /* Never skip non-full checkpoints */ + if (!full) + return (0); + + /* Never skip if force is configured. */ + WT_RET(__wt_config_gets_def(session, cfg, "force", 0, &cval)); + if (cval.val != 0) + return (0); + + /* Never skip named checkpoints. */ + WT_RET(__wt_config_gets(session, cfg, "name", &cval)); + if (cval.val != 0) + return (0); + + /* + * Skip checkpointing the database if nothing has been dirtied since + * the last checkpoint. That said there can be short instances when a + * btree gets marked dirty and the connection is yet to be. We might + * skip a checkpoint in that short instance, which is okay because by + * the next time we get to checkpoint, the connection would have been + * marked dirty and hence the checkpoint will not be skipped again. + */ + if (!conn->modified) { + *can_skipp = true; + return (0); + } + +#ifdef HAVE_TIMESTAMPS + /* + * If the checkpoint is using timestamps, and the stable timestamp + * hasn't been updated since the last checkpoint there is nothing + * more that could be written. + */ + if (use_timestamp && txn_global->has_stable_timestamp && + !__wt_timestamp_iszero(&txn_global->last_ckpt_timestamp) && + __wt_timestamp_cmp(&txn_global->last_ckpt_timestamp, + &txn_global->stable_timestamp) == 0) { + *can_skipp = true; + return (0); + } +#else + WT_UNUSED(txn_global); +#endif + + return (0); +} + +/* * __txn_checkpoint -- * Checkpoint a database or a list of objects in the database. */ @@ -787,7 +874,7 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[]) WT_TXN_ISOLATION saved_isolation; uint64_t fsync_duration_usecs, generation, time_start, time_stop; u_int i; - bool failed, full, idle, logging, tracking; + bool can_skip, failed, full, idle, logging, tracking, use_timestamp; void *saved_meta_next; conn = S2C(session); @@ -795,15 +882,22 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[]) txn = &session->txn; txn_global = &conn->txn_global; saved_isolation = session->isolation; - full = idle = logging = tracking = false; + full = idle = logging = tracking = use_timestamp = false; + + /* Avoid doing work if possible. */ + WT_RET(__txn_checkpoint_can_skip(session, + cfg, &full, &use_timestamp, &can_skip)); + if (can_skip) { + WT_STAT_CONN_INCR(session, txn_checkpoint_skipped); + return (0); + } /* * Do a pass over the configuration arguments and figure out what kind * of checkpoint this is. */ - WT_RET(__checkpoint_apply_all(session, cfg, NULL, &full)); + WT_RET(__checkpoint_apply_all(session, cfg, NULL)); - /* Configure logging only if doing a full checkpoint. */ logging = FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED); /* Reset the maximum page size seen by eviction. */ @@ -994,8 +1088,17 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[]) if (full) { __checkpoint_stats(session); #ifdef HAVE_TIMESTAMPS - __wt_timestamp_set( - &conn->txn_global.last_ckpt_timestamp, &ckpt_tmp_ts); + /* + * If timestamps were used to define the content of the + * checkpoint update the saved last checkpoint timestamp, + * otherwise leave it alone. If a checkpoint is taken without + * timestamps, it's likely a bug, but we don't want to clear + * the saved last checkpoint timestamp regardless. + */ + if (use_timestamp) + __wt_timestamp_set( + &conn->txn_global.last_ckpt_timestamp, + &ckpt_tmp_ts); #endif } diff --git a/src/third_party/wiredtiger/src/txn/txn_recover.c b/src/third_party/wiredtiger/src/txn/txn_recover.c index c2a1c7d3b27..ac656047e62 100644 --- a/src/third_party/wiredtiger/src/txn/txn_recover.c +++ b/src/third_party/wiredtiger/src/txn/txn_recover.c @@ -704,6 +704,13 @@ done: WT_ERR(__recovery_set_checkpoint_timestamp(&r)); * archiving. */ WT_ERR(session->iface.checkpoint(&session->iface, "force=1")); + + /* + * If we're downgrading and have newer log files, force an archive, + * no matter what the archive setting is. + */ + if (FLD_ISSET(conn->log_flags, WT_CONN_LOG_FORCE_DOWNGRADE)) + WT_ERR(__wt_log_truncate_files(session, NULL, true)); FLD_SET(conn->log_flags, WT_CONN_LOG_RECOVER_DONE); err: WT_TRET(__recovery_free(&r)); diff --git a/src/third_party/wiredtiger/test/csuite/Makefile.am b/src/third_party/wiredtiger/test/csuite/Makefile.am index 1981b3e6831..b3dde5ec628 100644 --- a/src/third_party/wiredtiger/test/csuite/Makefile.am +++ b/src/third_party/wiredtiger/test/csuite/Makefile.am @@ -11,6 +11,10 @@ test_random_abort_SOURCES = random_abort/main.c noinst_PROGRAMS += test_random_abort all_TESTS += random_abort/smoke.sh +test_rwlock_SOURCES = rwlock/main.c +noinst_PROGRAMS += test_rwlock +all_TESTS += test_rwlock + test_scope_SOURCES = scope/main.c noinst_PROGRAMS += test_scope all_TESTS += test_scope @@ -99,14 +103,14 @@ test_wt3874_pad_byte_collator_SOURCES = wt3874_pad_byte_collator/main.c noinst_PROGRAMS += test_wt3874_pad_byte_collator all_TESTS += test_wt3874_pad_byte_collator -test_rwlock_SOURCES = rwlock/main.c -noinst_PROGRAMS += test_rwlock -all_TESTS += test_rwlock - test_wt4105_large_doc_small_upd_SOURCES = wt4105_large_doc_small_upd/main.c noinst_PROGRAMS += test_wt4105_large_doc_small_upd all_TESTS += test_wt4105_large_doc_small_upd +test_wt4117_checksum_SOURCES = wt4117_checksum/main.c +noinst_PROGRAMS += test_wt4117_checksum +all_TESTS += test_wt4117_checksum + # Run this during a "make check" smoke test. TESTS = $(all_TESTS) LOG_COMPILER = $(TEST_WRAPPER) diff --git a/src/third_party/wiredtiger/test/csuite/wt4105_large_doc_small_upd/main.c b/src/third_party/wiredtiger/test/csuite/wt4105_large_doc_small_upd/main.c index 75ee0ade1cb..1efe22c1816 100644 --- a/src/third_party/wiredtiger/test/csuite/wt4105_large_doc_small_upd/main.c +++ b/src/third_party/wiredtiger/test/csuite/wt4105_large_doc_small_upd/main.c @@ -46,7 +46,7 @@ on_alarm(int signo) /* NOTREACHED */ } -static int ignore_errors; +static int ignore_errors = 0; static int handle_error(WT_EVENT_HANDLER *handler, @@ -82,9 +82,8 @@ main(int argc, char *argv[]) WT_ITEM value; WT_MODIFY modify_entry; WT_SESSION *session, *session2; - - char *large_doc; uint64_t i, j, offset; + char *large_doc; opts = &_opts; memset(opts, 0, sizeof(*opts)); @@ -106,7 +105,7 @@ main(int argc, char *argv[]) session->open_cursor(session, uri, NULL, NULL, &c)); /* Value is initialized with 'v' and has not significance to it. */ - large_doc = (char *)malloc(DATASIZE); + large_doc = dmalloc(DATASIZE); memset(large_doc, 'v', DATASIZE); value.data = large_doc; value.size = DATASIZE; @@ -132,8 +131,7 @@ main(int argc, char *argv[]) /* Start another session to perform small updates. */ testutil_check( opts->conn->open_session(opts->conn, NULL, NULL, &session2)); - testutil_check( - session->open_cursor(session2, uri, NULL, NULL, &c)); + testutil_check(session2->open_cursor(session2, uri, NULL, NULL, &c)); j = offset = 0; while (++j < MODIFY_COUNT) { @@ -159,6 +157,7 @@ main(int argc, char *argv[]) printf("modify count %" PRIu64"\n", j * NUM_DOCS); } + free(large_doc); testutil_cleanup(opts); return (EXIT_SUCCESS); diff --git a/src/third_party/wiredtiger/test/csuite/wt4117_checksum/main.c b/src/third_party/wiredtiger/test/csuite/wt4117_checksum/main.c new file mode 100644 index 00000000000..9a786e5d222 --- /dev/null +++ b/src/third_party/wiredtiger/test/csuite/wt4117_checksum/main.c @@ -0,0 +1,108 @@ +/*- + * Public Domain 2014-2018 MongoDB, Inc. + * Public Domain 2008-2014 WiredTiger, Inc. + * + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "test_util.h" + +/* + * JIRA ticket reference: WT-4117 + * Test case description: Smoke-test the CRC32C external API. + */ + +static inline void +check(uint32_t crc32c, uint32_t expected, size_t len, const char *msg) +{ + testutil_checkfmt(crc32c == expected ? 0 : 1, + "%s checksum mismatch of %" WT_SIZET_FMT " bytes: %#08x != %#08x\n", + msg, len, crc32c, expected); +} + +static void +run(void) +{ + size_t len; + uint32_t crc32c; + uint8_t *data; + + /* Allocate aligned memory for the data. */ + data = dcalloc(100, sizeof(uint8_t)); + + /* + * Some simple known checksums. + */ + len = 1; + crc32c = wiredtiger_checksum_crc32c(data, len); + check(crc32c, (uint32_t)0x527d5351, len, "nul x1"); + + len = 2; + crc32c = wiredtiger_checksum_crc32c(data, len); + check(crc32c, (uint32_t)0xf16177d2, len, "nul x2"); + + len = 3; + crc32c = wiredtiger_checksum_crc32c(data, len); + check(crc32c, (uint32_t)0x6064a37a, len, "nul x3"); + + len = 4; + crc32c = wiredtiger_checksum_crc32c(data, len); + check(crc32c, (uint32_t)0x48674bc7, len, "nul x4"); + + len = strlen("123456789"); + memcpy(data, "123456789", len); + crc32c = wiredtiger_checksum_crc32c(data, len); + check(crc32c, (uint32_t)0xe3069283, len, "known string #1"); + + len = strlen("The quick brown fox jumps over the lazy dog"); + memcpy(data, "The quick brown fox jumps over the lazy dog", len); + crc32c = wiredtiger_checksum_crc32c(data, len); + check(crc32c, (uint32_t)0x22620404, len, "known string #2"); + + free(data); +} + +int +main(int argc, char *argv[]) +{ + TEST_OPTS *opts, _opts; + + opts = &_opts; + memset(opts, 0, sizeof(*opts)); + testutil_check(testutil_parse_opts(argc, argv, opts)); + testutil_make_work_dir(opts->home); + + /* + * The external API should work before the library configures itself, + * run before and after calling wiredtiger_open(). + */ + run(); + + testutil_check( + wiredtiger_open(opts->home, NULL, "create", &opts->conn)); + + run(); + + testutil_cleanup(opts); + return (EXIT_SUCCESS); +} diff --git a/src/third_party/wiredtiger/test/format/ops.c b/src/third_party/wiredtiger/test/format/ops.c index 0d3e9892962..7d08dbd8bd8 100644 --- a/src/third_party/wiredtiger/test/format/ops.c +++ b/src/third_party/wiredtiger/test/format/ops.c @@ -127,7 +127,7 @@ wts_ops(int lastrun) if (!SINGLETHREADED) g.rand_log_stop = true; - /* Open a session. */ + /* Logging requires a session. */ if (g.logging != 0) { testutil_check(conn->open_session(conn, NULL, NULL, &session)); (void)g.wt_api->msg_printf(g.wt_api, session, @@ -241,6 +241,10 @@ wts_ops(int lastrun) fprintf(stderr, "%s\n", "format run exceeded 15 minutes past the maximum " "time, aborting the process."); + + (void)conn->debug_info(conn, "txn"); + (void)conn->debug_info(conn, "cache"); + abort(); } } diff --git a/src/third_party/wiredtiger/test/suite/test_compat01.py b/src/third_party/wiredtiger/test/suite/test_compat01.py index 696e24f4569..f9131331640 100644 --- a/src/third_party/wiredtiger/test/suite/test_compat01.py +++ b/src/third_party/wiredtiger/test/suite/test_compat01.py @@ -47,28 +47,25 @@ class test_compat01(wttest.WiredTigerTestCase, suite_subprocess): # Log version 2 introduced that record. # Log version 3 continues to have that record. min_logv = 2 + latest_logv = 3 # The API uses only the major and minor numbers but accepts with # and without the patch number. Test both. start_compat = [ ('def', dict(compat1='none', logv1=3)), ('31', dict(compat1="3.1", logv1=3)), - ('31_patch', dict(compat1="3.1.0", logv1=3)), ('30', dict(compat1="3.0", logv1=2)), ('30_patch', dict(compat1="3.0.0", logv1=2)), ('26', dict(compat1="2.6", logv1=1)), - ('26_patch', dict(compat1="2.6.1", logv1=1)), ('old', dict(compat1="1.8", logv1=1)), ('old_patch', dict(compat1="1.8.1", logv1=1)), ] restart_compat = [ ('def2', dict(compat2='none', logv2=3)), - ('31.2', dict(compat2="3.1", logv2=3)), - ('31_patch2', dict(compat2="3.1.0", logv2=3)), - ('30.2', dict(compat2="3.0", logv2=2)), + ('31_2', dict(compat2="3.1", logv2=3)), + ('30_2', dict(compat2="3.0", logv2=2)), ('30_patch2', dict(compat2="3.0.0", logv2=2)), - ('26.2', dict(compat2="2.6", logv2=1)), - ('26_patch2', dict(compat2="2.6.1", logv2=1)), + ('26_2', dict(compat2="2.6", logv2=1)), ('old2', dict(compat2="1.8", logv2=1)), ('old_patch2', dict(compat2="1.8.1", logv2=1)), ] @@ -91,7 +88,7 @@ class test_compat01(wttest.WiredTigerTestCase, suite_subprocess): self.pr("Conn config:" + log_str + compat_str) return log_str + compat_str - def check_prev_lsn(self, conn_close, prev_lsn_count): + def check_prev_lsn(self, exists, conn_close): # # Run printlog and look for the prev_lsn log record. Verify its # existence with the passed in expected result. We don't use @@ -100,30 +97,30 @@ class test_compat01(wttest.WiredTigerTestCase, suite_subprocess): # the entire file if needed and set a boolean for comparison. # self.runWt(['printlog'], outfilename='printlog.out', closeconn=conn_close) - pstr = str(prev_lsn_count) - self.pr("CHECK PREV: Looking for " + pstr + " prev LSN entries") - contains = 0 + contains = False with open('printlog.out') as logfile: for line in logfile: if 'optype' in line and 'prev_lsn' in line: - contains += 1 - self.assertEqual(prev_lsn_count, contains) + contains = True + break + self.assertEqual(exists, contains) def check_log(self, reconfig): orig_logs = fnmatch.filter(os.listdir('.'), "*gerLog*") compat_str = self.make_compat_str(False) - if self.logv1 >= self.min_logv: - prev_lsn_logs = len(orig_logs) - else: - prev_lsn_logs = 0 - pstr = str(prev_lsn_logs) - self.pr("CHECK LOG: Orig " + pstr + " prev LSN log files") if not reconfig: # - # Close and open the connection to force recovery and reset the - # compatibility string on startup. + # Close and open the connection to force recovery and log archiving + # even if archive is turned off (in some circumstances). If we are + # downgrading we must archive newer logs. Verify the log files + # have or have not been archived. # + exist = True + if self.logv1 < self.min_logv: + exist = False + self.check_prev_lsn(exist, True) + self.conn.close() log_str = 'log=(enabled,file_max=%s,archive=false),' % self.logmax restart_config = log_str + compat_str @@ -134,31 +131,30 @@ class test_compat01(wttest.WiredTigerTestCase, suite_subprocess): conn = self.wiredtiger_open('.', restart_config) conn.close() check_close = False - # - # If the version was upgraded we'll see a new log file containing - # the new log record no matter what the original setting was. - # - if self.logv2 > 1: - prev_lsn_logs += 1 else: self.pr("Reconfigure: " + compat_str) self.conn.reconfigure(compat_str) check_close = True + # - # If we're reconfiguring, we'll see another new log file - # when transitioning between log version numbers. Staying - # at the same version has no effect. We'll only see another - # new log file with the prevlsn if the new version supports it. + # Archiving is turned off explicitly. # - if self.logv1 != self.logv2 and self.logv2 >= self.min_logv: - prev_lsn_logs += 1 + # Check logs. The original logs should have been archived only if + # we downgraded. In all other cases the original logs should be there. + # Downgrade means not running the latest possible log version, not + # the difference between original and current. + cur_logs = fnmatch.filter(os.listdir('.'), "*Log*") + log_present = True + if self.logv1 != self.logv2 and self.logv2 != self.latest_logv: + log_present = False + for o in orig_logs: + self.assertEqual(log_present, o in cur_logs) # Run printlog and verify the new record does or does not exist. - # Need to check count of log files that should and should not have - # the prev_lsn record based on the count of log files that exist - # before and after. Pass that into this function and check the - # number of prev_lsn records we see. - self.check_prev_lsn(check_close, prev_lsn_logs) + exist = True + if self.logv2 < self.min_logv: + exist = False + self.check_prev_lsn(exist, check_close) def run_test(self, reconfig): # If reconfiguring with the empty string there is nothing to do. diff --git a/src/third_party/wiredtiger/test/suite/test_compat02.py b/src/third_party/wiredtiger/test/suite/test_compat02.py index 15d6a58e84f..1b6c2dd2889 100644 --- a/src/third_party/wiredtiger/test/suite/test_compat02.py +++ b/src/third_party/wiredtiger/test/suite/test_compat02.py @@ -49,9 +49,9 @@ class test_compat02(wttest.WiredTigerTestCase, suite_subprocess): min_logv = 2 # Test detecting a not-yet-existing log version. This should - # hold us for a couple years. - future_logv = 5 - future_rel = "5.0" + # hold us for many years. + future_logv = 20 + future_rel = "20.0" # The API uses only the major and minor numbers but accepts with # and without the patch number. Test one on release and the @@ -150,10 +150,9 @@ class test_compat02(wttest.WiredTigerTestCase, suite_subprocess): expect_err = False if (expect_err == True): - self.pr("EXPECT ERROR") - with self.expectedStderrPattern(''): - self.assertRaisesException(wiredtiger.WiredTigerError, - lambda: self.wiredtiger_open('.', restart_config)) + msg = '/Version incompatibility detected:/' + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda: self.wiredtiger_open('.', restart_config), msg) else: self.pr("EXPECT SUCCESS") conn = self.wiredtiger_open('.', restart_config) diff --git a/src/third_party/wiredtiger/test/suite/test_compat03.py b/src/third_party/wiredtiger/test/suite/test_compat03.py index e6b8ead50a6..caf8a4bc4e8 100644 --- a/src/third_party/wiredtiger/test/suite/test_compat03.py +++ b/src/third_party/wiredtiger/test/suite/test_compat03.py @@ -49,9 +49,9 @@ class test_compat03(wttest.WiredTigerTestCase, suite_subprocess): min_logv = 2 # Test detecting a not-yet-existing log version. This should - # hold us for a couple years. - future_logv = 5 - future_rel = "5.0" + # hold us for many years. + future_logv = 20 + future_rel = "20.0" # The API uses only the major and minor numbers but accepts with # and without the patch number. Test one on release and the @@ -122,10 +122,9 @@ class test_compat03(wttest.WiredTigerTestCase, suite_subprocess): expect_err = False if (expect_err == True): - self.pr("EXPECT ERROR") - with self.expectedStderrPattern(''): - self.assertRaisesException(wiredtiger.WiredTigerError, - lambda: self.wiredtiger_open(testdir, config_str)) + msg = '/Version incompatibility detected:/' + self.assertRaisesWithMessage(wiredtiger.WiredTigerError, + lambda: self.wiredtiger_open(testdir, config_str), msg) else: self.pr("EXPECT SUCCESS") conn = self.wiredtiger_open(testdir, config_str) diff --git a/src/third_party/wiredtiger/test/suite/test_compat04.py b/src/third_party/wiredtiger/test/suite/test_compat04.py new file mode 100644 index 00000000000..409a0bd1b76 --- /dev/null +++ b/src/third_party/wiredtiger/test/suite/test_compat04.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# +# Public Domain 2014-2018 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. +# +# test_compat04.py +# Check compatibility API + +import fnmatch, os +import wiredtiger, wttest +from suite_subprocess import suite_subprocess +from wtdataset import SimpleDataSet, simple_key +from wtscenario import make_scenarios + +class test_compat04(wttest.WiredTigerTestCase, suite_subprocess): + # Add enough entries and use a small log size to generate more than + # one log file. + entries = 2000 + logmax = "100K" + tablename = 'test_compat04' + uri = 'table:' + tablename + # Declare the log versions that do and do not have prevlsn. + # Log version 1 does not have the prevlsn record. + # Log version 2 introduced that record. + # Log version 3 continues to have that record. + min_logv = 2 + + # The outline of this test is that we create the database at the + # create release value. Then we reconfigure the release to the + # reconfig release value. Then we close and reopen the database with + # a release and compatibility maximum of that release value. This + # should be successful for all directions. + # + create_release = [ + ('def_rel', dict(create_rel='none', log_crrel=3)), + ('31_rel', dict(create_rel="3.1", log_crrel=3)), + ('30_rel', dict(create_rel="3.0", log_crrel=2)), + ('26_rel', dict(create_rel="2.6", log_crrel=1)), + ] + reconfig_release = [ + ('31_rel', dict(rel="3.1", log_rel=3)), + ('30_rel', dict(rel="3.0", log_rel=2)), + ('300_rel', dict(rel="3.0.0", log_rel=2)), + ('26_rel', dict(rel="2.6", log_rel=1)), + ] + base_config = [ + ('basecfg_true', dict(basecfg='true')), + ('basecfg_false', dict(basecfg='false')), + ] + scenarios = make_scenarios(create_release, reconfig_release, base_config) + + # This test creates scenarios that lead to errors. This is different + # than compat02 because it is testing errors (or success) using the + # compatibility settings on the initial database creation. + def conn_config(self): + config_str = 'create,config_base=%s,' % self.basecfg + log_str = 'log=(archive=false,enabled,file_max=%s),' % self.logmax + compat_str = '' + if (self.create_rel != 'none'): + compat_str += 'compatibility=(release="%s"),' % self.create_rel + config_str += log_str + compat_str + self.pr("Conn config:" + config_str) + return config_str + + def test_compat04(self): + # + # Create initial database at the compatibility level requested + # and a table with some data. + # + self.session.create(self.uri, 'key_format=i,value_format=i') + c = self.session.open_cursor(self.uri, None) + # + # Add some entries to generate log files. + # + for i in range(self.entries): + c[i] = i + 1 + c.close() + + # Reconfigure and close the connection. Then reopen with that release. + # We expect success. + config_str = 'compatibility=(release=%s)' % self.rel + self.conn.reconfigure(config_str) + self.conn.close() + + config_str = 'compatibility=(release=%s,require_max=%s)' % (self.rel, self.rel) + conn = self.wiredtiger_open('.', config_str) + conn.close() + +if __name__ == '__main__': + wttest.run() + +if __name__ == '__main__': + wttest.run() diff --git a/src/third_party/wiredtiger/test/suite/test_las01.py b/src/third_party/wiredtiger/test/suite/test_las01.py index fd4dea87c35..8b6132f8418 100644 --- a/src/third_party/wiredtiger/test/suite/test_las01.py +++ b/src/third_party/wiredtiger/test/suite/test_las01.py @@ -92,6 +92,9 @@ class test_las01(wttest.WiredTigerTestCase): conn.close() def test_las(self): + if not wiredtiger.timestamp_build(): + self.skipTest('requires a timestamp build') + # Create a small table. uri = "table:test_las01" nrows = 100 diff --git a/src/third_party/wiredtiger/test/suite/test_las02.py b/src/third_party/wiredtiger/test/suite/test_las02.py index af089d6c19e..7291214fe7e 100644 --- a/src/third_party/wiredtiger/test/suite/test_las02.py +++ b/src/third_party/wiredtiger/test/suite/test_las02.py @@ -62,6 +62,9 @@ class test_las02(wttest.WiredTigerTestCase): self.assertEqual(count, nrows) def test_las(self): + if not wiredtiger.timestamp_build(): + self.skipTest('requires a timestamp build') + nrows = 10000 # Create a table without logging to ensure we get "skew_newest" lookaside eviction behavior. diff --git a/src/third_party/wiredtiger/test/suite/test_prepare01.py b/src/third_party/wiredtiger/test/suite/test_prepare01.py index 20615ab836c..d88fdff9fd6 100644 --- a/src/third_party/wiredtiger/test/suite/test_prepare01.py +++ b/src/third_party/wiredtiger/test/suite/test_prepare01.py @@ -103,6 +103,9 @@ class test_prepare01(wttest.WiredTigerTestCase): # Loop through a set of inserts, periodically committing; before each # commit, verify the number of visible records matches the expected value. def test_visibility(self): + if not wiredtiger.timestamp_build(): + self.skipTest('requires a timestamp build') + self.session.create(self.uri, 'key_format=' + self.key_format + ',value_format=' + self.value_format) @@ -148,6 +151,9 @@ class test_read_committed_default(wttest.WiredTigerTestCase): return count def test_read_committed_default(self): + if not wiredtiger.timestamp_build(): + self.skipTest('requires a timestamp build') + self.session.create(self.uri, 'key_format=S,value_format=S') cursor = self.session.open_cursor(self.uri, None) self.session.begin_transaction() diff --git a/src/third_party/wiredtiger/test/suite/test_prepare03.py b/src/third_party/wiredtiger/test/suite/test_prepare03.py index 974a9d09b1c..870d62bb790 100644 --- a/src/third_party/wiredtiger/test/suite/test_prepare03.py +++ b/src/third_party/wiredtiger/test/suite/test_prepare03.py @@ -74,6 +74,9 @@ class test_prepare03(wttest.WiredTigerTestCase): # Create the table and test cursor operations. def test_prepare_cursor(self): + if not wiredtiger.timestamp_build(): + self.skipTest('requires a timestamp build') + tablearg = self.uri + ':' + self.table_name create_args = self.format preparemsg = "/ not permitted in a prepared transaction/" |