diff options
author | Ramon Fernandez <ramon@mongodb.com> | 2016-08-26 18:28:48 -0400 |
---|---|---|
committer | Ramon Fernandez <ramon@mongodb.com> | 2016-08-26 18:28:48 -0400 |
commit | f2a613a41d6ad7b5a1b66087e386380d38e50599 (patch) | |
tree | 4843fb7b6a835e72046142046e9364f7d7dda992 /src/third_party/wiredtiger/test | |
parent | 7614c0eb2449eb4ec22d21b677177124d61f1888 (diff) | |
download | mongo-f2a613a41d6ad7b5a1b66087e386380d38e50599.tar.gz |
Import wiredtiger: 2566118fc68b0124187e806bed52eb7cdbcb1be0 from branch mongodb-3.4
ref: 34182ad..2566118fc6
for: 3.3.12
WT-2631 nullptr is passed for parameters marked with attribute non-null
WT-2638 ftruncate may not be supported
WT-2645 wt dump: push the complexity of collecting metadata into a dump cursor
WT-2678 The metadata should not imply that an empty value is true
WT-2695 Integrate s390x accelerated crc32c support
WT-2719 add fuzz testing for WiredTiger options and reconfiguration.
WT-2734 Improve documentation of eviction behavior
WT-2766 Don't count eviction of lookaside file pages for the purpose of checking stuck cache
WT-2783 wtperf multi-btree.wtperf dumps core on Mac
WT-2787 Include src/include/wiredtiger_ext.h is problematic
WT-2795 Update documentation around read-only configuration
WT-2807 Switch Jenkins performance tests to tcmalloc
WT-2813 small cache usage stuck even with large cache
WT-2814 Enhance wtperf to support single-op truncate mode
WT-2816 Improve WiredTiger eviction performance
WT-2817 Investigate performance regression in develop, add workload to wtperf/runners
WT-2818 The page visibility check when queuing pages for eviction is overly restrictive
WT-2820 add gcc warn_unused_result attribute
WT-2822 panic mutex and other functions that cannot fail
WT-2823 support file handles without a truncate method
WT-2826 clang38 false positive on uninitialized variable.
WT-2827 checkpoint log_size configuration improvements
WT-2828 Make long wtperf tests reflect mongoDB usage
WT-2829 Switch automated testing to use enable-strict configure option
WT-2832 Python test uses hard-coded temporary directory
WT-2834 Join cursor: discrepancy with bloom filters
WT-2835 WT_CONNECTION.leak-memory can skip memory map and cache cleanup
WT-2838 Don't free session handles on close if leak memory is configured
WT-2839 lint: Ignoring return value of function
WT-2840 clang analysis: garbage values
WT-2841 Jenkins Valgrind runner is reporting errors in test wt2719_reconfig
WT-2843 Fix a bug in recovery if there is no filesystem truncate support
WT-2846 Several bugs related to reconfiguring eviction server at runtime
WT-2847 Merge fair locks into read/write locks.
WT-2850 clang 4.1 attribute warnings when building
WT-2853 Multi threaded reader writer example shows temporary slowdown or lockup
WT-2857 POSIX ftruncate calls should be #ifdef'd HAVE_FTRUNCATE
WT-2862 Fix lint error in test case for forced eviction with multiple cursors
WT-2863 Support UTF-8 paths on Windows
Diffstat (limited to 'src/third_party/wiredtiger/test')
20 files changed, 1157 insertions, 40 deletions
diff --git a/src/third_party/wiredtiger/test/csuite/Makefile.am b/src/third_party/wiredtiger/test/csuite/Makefile.am index f842bc1316f..097468f0e85 100644 --- a/src/third_party/wiredtiger/test/csuite/Makefile.am +++ b/src/third_party/wiredtiger/test/csuite/Makefile.am @@ -1,5 +1,6 @@ AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \ - -I$(top_srcdir)/test/utility + -I$(top_srcdir)/test/utility \ + -DCRC_PATH="\"$(top_srcdir)/src/checksum/x86/checksum.c\"" LDADD = $(top_builddir)/test/utility/libtest_util.la \ $(top_builddir)/libwiredtiger.la AM_LDFLAGS = -static @@ -16,9 +17,21 @@ noinst_PROGRAMS += test_wt2535_insert_race test_wt2447_join_main_table_SOURCES = wt2447_join_main_table/main.c noinst_PROGRAMS += test_wt2447_join_main_table +test_wt2695_checksum_SOURCES = wt2695_checksum/main.c wt2695_checksum/sw.c +noinst_PROGRAMS += test_wt2695_checksum + test_wt2592_join_schema_SOURCES = wt2592_join_schema/main.c noinst_PROGRAMS += test_wt2592_join_schema +test_wt2719_reconfig_SOURCES = wt2719_reconfig/main.c +noinst_PROGRAMS += test_wt2719_reconfig + +test_wt2834_join_bloom_fix_SOURCES = wt2834_join_bloom_fix/main.c +noinst_PROGRAMS += test_wt2834_join_bloom_fix + +test_wt2853_perf_SOURCES = wt2853_perf/main.c +noinst_PROGRAMS += test_wt2853_perf + # Run this during a "make check" smoke test. TESTS = $(noinst_PROGRAMS) LOG_COMPILER = $(TEST_WRAPPER) diff --git a/src/third_party/wiredtiger/test/csuite/wt1965_col_efficiency/main.c b/src/third_party/wiredtiger/test/csuite/wt1965_col_efficiency/main.c index 2882ce9cdf5..0dc367c0611 100644 --- a/src/third_party/wiredtiger/test/csuite/wt1965_col_efficiency/main.c +++ b/src/third_party/wiredtiger/test/csuite/wt1965_col_efficiency/main.c @@ -181,6 +181,5 @@ main(int argc, char *argv[]) testutil_assert(ret == WT_NOTFOUND); testutil_cleanup(opts); - - return (0); + return (EXIT_SUCCESS); } diff --git a/src/third_party/wiredtiger/test/csuite/wt2246_col_append/main.c b/src/third_party/wiredtiger/test/csuite/wt2246_col_append/main.c index 798970cbb6d..69683707d16 100644 --- a/src/third_party/wiredtiger/test/csuite/wt2246_col_append/main.c +++ b/src/third_party/wiredtiger/test/csuite/wt2246_col_append/main.c @@ -152,7 +152,5 @@ main(int argc, char *argv[]) (ce - cs) / (double)CLOCKS_PER_SEC); testutil_cleanup(opts); - /* NOTREACHED */ - - return (0); + return (EXIT_SUCCESS); } diff --git a/src/third_party/wiredtiger/test/csuite/wt2447_join_main_table/main.c b/src/third_party/wiredtiger/test/csuite/wt2447_join_main_table/main.c index a6f19cb0858..bbae61e7ed5 100644 --- a/src/third_party/wiredtiger/test/csuite/wt2447_join_main_table/main.c +++ b/src/third_party/wiredtiger/test/csuite/wt2447_join_main_table/main.c @@ -184,6 +184,5 @@ main(int argc, char *argv[]) testutil_assert(maincount == 2); testutil_cleanup(opts); - - return (0); + return (EXIT_SUCCESS); } diff --git a/src/third_party/wiredtiger/test/csuite/wt2695_checksum/main.c b/src/third_party/wiredtiger/test/csuite/wt2695_checksum/main.c new file mode 100644 index 00000000000..dc6f5b5cd87 --- /dev/null +++ b/src/third_party/wiredtiger/test/csuite/wt2695_checksum/main.c @@ -0,0 +1,136 @@ +/*- + * Public Domain 2014-2016 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-2695 + * Test case description: Smoke-test the CRC. + */ + +void (*custom_die)(void) = NULL; + +uint32_t cksum_sw(const void *, size_t); + +static inline void +check(uint32_t hw, uint32_t sw, size_t len, const char *msg) +{ + testutil_checkfmt(hw == sw ? 0 : 1, + "%s checksum mismatch of %" WT_SIZET_FMT " bytes: %#08x != %#08x\n", + msg, len, hw, sw); +} + +#define DATASIZE (128 * 1024) +int +main(void) +{ + WT_RAND_STATE rnd; + size_t len; + uint32_t hw, sw; + u_int i, j; + uint8_t *data; + + /* Allocate aligned memory for the data. */ + data = dcalloc(DATASIZE, sizeof(uint8_t)); + + /* Initialize the RNG. */ + testutil_check(__wt_random_init_seed(NULL, &rnd)); + + /* Initialize the WiredTiger library checksum functions. */ + __wt_cksum_init(); + + /* + * Some simple known checksums. + */ + len = 1; + hw = __wt_cksum(data, len); + check(hw, (uint32_t)0x527d5351, len, "nul x1: hardware"); + sw = cksum_sw(data, len); + check(sw, (uint32_t)0x527d5351, len, "nul x1: software"); + + len = 2; + hw = __wt_cksum(data, len); + check(hw, (uint32_t)0xf16177d2, len, "nul x2: hardware"); + sw = cksum_sw(data, len); + check(sw, (uint32_t)0xf16177d2, len, "nul x2: software"); + + len = 3; + hw = __wt_cksum(data, len); + check(hw, (uint32_t)0x6064a37a, len, "nul x3: hardware"); + sw = cksum_sw(data, len); + check(sw, (uint32_t)0x6064a37a, len, "nul x3: software"); + + len = 4; + hw = __wt_cksum(data, len); + check(hw, (uint32_t)0x48674bc7, len, "nul x4: hardware"); + sw = cksum_sw(data, len); + check(sw, (uint32_t)0x48674bc7, len, "nul x4: software"); + + len = strlen("123456789"); + memcpy(data, "123456789", len); + hw = __wt_cksum(data, len); + check(hw, (uint32_t)0xe3069283, len, "known string #1: hardware"); + sw = cksum_sw(data, len); + check(sw, (uint32_t)0xe3069283, len, "known string #1: software"); + + len = strlen("The quick brown fox jumps over the lazy dog"); + memcpy(data, "The quick brown fox jumps over the lazy dog", len); + hw = __wt_cksum(data, len); + check(hw, (uint32_t)0x22620404, len, "known string #2: hardware"); + sw = cksum_sw(data, len); + check(sw, (uint32_t)0x22620404, len, "known string #2: software"); + + /* + * Checksums of power-of-two data chunks. + */ + for (i = 0, len = 512; i < 1000; ++i) { + for (j = 0; j < len; ++j) + data[j] = __wt_random(&rnd) & 0xff; + hw = __wt_cksum(data, len); + sw = cksum_sw(data, len); + check(hw, sw, len, "random power-of-two"); + + len *= 2; + if (len > DATASIZE) + len = 512; + } + + /* + * Checksums of random data chunks. + */ + for (i = 0; i < 1000; ++i) { + len = __wt_random(&rnd) % DATASIZE; + for (j = 0; j < len; ++j) + data[j] = __wt_random(&rnd) & 0xff; + hw = __wt_cksum(data, len); + sw = cksum_sw(data, len); + check(hw, sw, len, "random"); + } + + free(data); + return (EXIT_SUCCESS); +} diff --git a/src/third_party/wiredtiger/test/csuite/wt2695_checksum/sw.c b/src/third_party/wiredtiger/test/csuite/wt2695_checksum/sw.c new file mode 100644 index 00000000000..892d9480bf3 --- /dev/null +++ b/src/third_party/wiredtiger/test/csuite/wt2695_checksum/sw.c @@ -0,0 +1,49 @@ +/*- + * Public Domain 2014-2016 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" + +/* + * Build the software version of the CRC code. + */ +#define __wt_cksum __wt_cksum_notused +uint32_t __wt_cksum_notused(const void *, size_t); +#define __wt_cksum_init __wt_cksum_init_notused +void __wt_cksum_init_notused(void); + +#include CRC_PATH + +/* + * cksum_sw -- + * Checksum in software. + */ +uint32_t cksum_sw(const void *, size_t); +uint32_t +cksum_sw(const void *chunk, size_t len) +{ + return (__wt_cksum_sw(chunk, len)); +} diff --git a/src/third_party/wiredtiger/test/csuite/wt2719_reconfig/main.c b/src/third_party/wiredtiger/test/csuite/wt2719_reconfig/main.c new file mode 100644 index 00000000000..4ec213c85ea --- /dev/null +++ b/src/third_party/wiredtiger/test/csuite/wt2719_reconfig/main.c @@ -0,0 +1,283 @@ +/*- + * Public Domain 2014-2016 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-2719 + * Test case description: Fuzz testing for WiredTiger reconfiguration. + */ + +void (*custom_die)(void) = NULL; + +static const char *list[] = { + ",async=(enabled=0)", + ",async=(enabled=1)", + ",async=(ops_max=2048)", + ",async=(ops_max=2348)", + ",async=(ops_max=1790)", + ",async=(threads=10)", + ",async=(threads=7)", + ",async=(threads=17)", + + ",cache_overhead=13", + ",cache_overhead=27", + ",cache_overhead=8", + + ",cache_size=75MB", + ",cache_size=214MB", + ",cache_size=37MB", + + ",checkpoint=(log_size=104857600)", /* 100MB */ + ",checkpoint=(log_size=1073741824)", /* 1GB */ + ",checkpoint=(log_size=2)", + ",checkpoint=(log_size=0)", + ",checkpoint=(wait=100)", + ",checkpoint=(wait=10000)", + ",checkpoint=(wait=2)", + ",checkpoint=(wait=0)", + + ",error_prefix=\"prefix\"", + + ",eviction=(threads_min=7,threads_max=10)", + ",eviction=(threads_min=17,threads_max=18)", + ",eviction=(threads_min=3,threads_max=7)", + ",eviction=(threads_max=12,threads_min=10)", + ",eviction=(threads_max=18,threads_min=16)", + ",eviction=(threads_max=10,threads_min=9)", + + ",eviction_dirty_target=45", + ",eviction_dirty_target=87", + ",eviction_dirty_target=8", + + ",eviction_dirty_trigger=37", + ",eviction_dirty_trigger=98", + ",eviction_dirty_trigger=7", + + ",eviction_target=22", + ",eviction_target=84", + ",eviction_target=30", + + ",eviction_trigger=75", + ",eviction_trigger=95", + ",eviction_trigger=66", + + ",file_manager=(close_handle_minimum=200)", + ",file_manager=(close_handle_minimum=137)", + ",file_manager=(close_handle_minimum=226)", + ",file_manager=(close_idle_time=10000)", + ",file_manager=(close_idle_time=12000)", + ",file_manager=(close_idle_time=7)", + ",file_manager=(close_idle_time=0)", + ",file_manager=(close_scan_interval=50000)", + ",file_manager=(close_scan_interval=59000)", + ",file_manager=(close_scan_interval=3)", + + ",log=(archive=0)", + ",log=(archive=1)", + ",log=(prealloc=0)", + ",log=(prealloc=1)", + ",log=(zero_fill=0)", + ",log=(zero_fill=1)", + + ",lsm_manager=(merge=0)", + ",lsm_manager=(merge=1)", + ",lsm_manager=(worker_thread_max=5)", + ",lsm_manager=(worker_thread_max=18)", + ",lsm_manager=(worker_thread_max=3)", + + ",shared_cache=(chunk=20MB)", + ",shared_cache=(chunk=30MB)", + ",shared_cache=(chunk=5MB)", + ",shared_cache=(name=\"shared\")", + ",shared_cache=(name=\"none\")", + ",shared_cache=(quota=20MB)", + ",shared_cache=(quota=30MB)", + ",shared_cache=(quota=5MB)", + ",shared_cache=(quota=0)", + ",shared_cache=(reserve=20MB)", + ",shared_cache=(reserve=30MB)", + ",shared_cache=(reserve=5MB)", + ",shared_cache=(reserve=0)", + ",shared_cache=(size=100MB)", + ",shared_cache=(size=1GB)", + ",shared_cache=(size=75MB)", + + ",statistics=(\"all\")", + ",statistics=(\"fast\")", + ",statistics=(\"none\")", + ",statistics=(\"clear\")", + + ",statistics_log=(json=0)", + ",statistics_log=(json=1)", + ",statistics_log=(on_close=0)", + ",statistics_log=(on_close=1)", + ",statistics_log=(sources=(\"file:\"))", + ",statistics_log=(sources=())", + ",statistics_log=(timestamp=\"%b:%S\")", + ",statistics_log=(timestamp=\"%H:%M\")", + ",statistics_log=(wait=60)", + ",statistics_log=(wait=76)", + ",statistics_log=(wait=37)", + ",statistics_log=(wait=0)", + +#ifdef HAVE_VERBOSE + ",verbose=(\"api\")", + ",verbose=(\"block\")", + ",verbose=(\"checkpoint\")", + ",verbose=(\"compact\")", + ",verbose=(\"evict\")", + ",verbose=(\"evictserver\")", + ",verbose=(\"fileops\")", + ",verbose=(\"handleops\")", + ",verbose=(\"log\")", + ",verbose=(\"lsm\")", + ",verbose=(\"lsm_manager\")", + ",verbose=(\"metadata\")", + ",verbose=(\"mutex\")", + ",verbose=(\"overflow\")", + ",verbose=(\"read\")", + ",verbose=(\"rebalance\")", + ",verbose=(\"reconcile\")", + ",verbose=(\"recovery\")", + ",verbose=(\"salvage\")", + ",verbose=(\"shared_cache\")", + ",verbose=(\"split\")", + ",verbose=(\"temporary\")", + ",verbose=(\"transaction\")", + ",verbose=(\"verify\")", + ",verbose=(\"version\")", + ",verbose=(\"write\")", + ",verbose=()" +#endif +}; + +static int +handle_message(WT_EVENT_HANDLER *handler, + WT_SESSION *session, const char *message) +{ + (void)(handler); + (void)(session); + (void)(message); + + /* We configure verbose output, so just ignore. */ + return (0); +} + +static WT_EVENT_HANDLER event_handler = { NULL, handle_message, NULL, NULL }; + +int +main(int argc, char *argv[]) +{ + enum { CACHE_SHARED, CACHE_SET, CACHE_NONE } cache; + TEST_OPTS *opts, _opts; + WT_RAND_STATE rnd; + WT_SESSION *session; + size_t len; + u_int i, j; + int ret; + const char *p; + char *config; + + opts = &_opts; + memset(opts, 0, sizeof(*opts)); + opts->table_type = TABLE_ROW; + testutil_check(testutil_parse_opts(argc, argv, opts)); + testutil_make_work_dir(opts->home); + + testutil_check( + wiredtiger_open(opts->home, &event_handler, "create", &opts->conn)); + + /* Open an LSM file so the LSM reconfiguration options make sense. */ + testutil_check( + opts->conn->open_session(opts->conn, NULL, NULL, &session)); + testutil_check(session->create( + session, opts->uri, "type=lsm,key_format=S,value_format=S")); + + /* Initialize the RNG. */ + testutil_check(__wt_random_init_seed(NULL, &rnd)); + + /* Allocate memory for the config. */ + len = WT_ELEMENTS(list) * 64; + config = dmalloc(len); + + /* A linear pass through the list. */ + for (i = 0; i < WT_ELEMENTS(list); ++i) + if ((ret = opts->conn->reconfigure(opts->conn, list[i])) != 0) { + fprintf(stderr, "%s: %s\n", + list[i], session->strerror(session, ret)); + return (EXIT_FAILURE); + } + + /* + * A linear pass through the list, adding random elements. + * + * WiredTiger configurations are usually "the last one set wins", but + * "shared_cache" and "cache_set" options aren't allowed in the same + * configuration string. + */ + for (i = 0; i < WT_ELEMENTS(list); ++i) { + p = list[i]; + cache = CACHE_NONE; + if (WT_PREFIX_MATCH(p, ",shared_cache")) + cache = CACHE_SHARED; + else if (WT_PREFIX_MATCH(p, ",cache_size")) + cache = CACHE_SET; + strcpy(config, p); + + for (j = + (__wt_random(&rnd) % WT_ELEMENTS(list)) + 1; j > 0; --j) { + p = list[__wt_random(&rnd) % WT_ELEMENTS(list)]; + if (WT_PREFIX_MATCH(p, ",shared_cache")) { + if (cache == CACHE_SET) + continue; + cache = CACHE_SHARED; + } else if (WT_PREFIX_MATCH(p, ",cache_size")) { + if (cache == CACHE_SHARED) + continue; + cache = CACHE_SET; + } + strcat(config, p); + } + if ((ret = opts->conn->reconfigure(opts->conn, config)) != 0) { + fprintf(stderr, "%s: %s\n", + config, session->strerror(session, ret)); + return (EXIT_FAILURE); + } + } + + /* + * Turn on-close statistics off, if on-close is on and statistics were + * randomly turned off during the run, close would fail. + */ + testutil_check(opts->conn->reconfigure( + opts->conn, "statistics_log=(on_close=0)")); + + free(config); + testutil_cleanup(opts); + return (EXIT_SUCCESS); +} diff --git a/src/third_party/wiredtiger/test/csuite/wt2834_join_bloom_fix/main.c b/src/third_party/wiredtiger/test/csuite/wt2834_join_bloom_fix/main.c new file mode 100644 index 00000000000..1e2d919d3c7 --- /dev/null +++ b/src/third_party/wiredtiger/test/csuite/wt2834_join_bloom_fix/main.c @@ -0,0 +1,199 @@ +/*- + * Public Domain 2014-2016 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-2834 + * Test case description: We are creating bank 'account' records, each + * having a postal_code, balance, and an 'overdrawn' flag. We insert + * records with various balances, and only set the overdrawn flag when the + * balance is negative. Then we set up a join to simulate this: + * + * select (*) from account where account.postal_code = '54321' and + * account.balance < 0 and not account.overdrawn + * + * Failure mode: We get results back from our join. + */ +void (*custom_die)(void) = NULL; + +#define N_RECORDS 100000 +#define N_INSERT 1000000 + +void populate(TEST_OPTS *opts); + +int +main(int argc, char *argv[]) +{ + TEST_OPTS *opts, _opts; + WT_CURSOR *maincur; + WT_CURSOR *postcur, *balancecur, *flagcur, *joincur; + WT_SESSION *session; + int balance, count, flag, key, key2, post, ret; + char cfg[128]; + const char *tablename; + char posturi[256]; + char balanceuri[256]; + char flaguri[256]; + char joinuri[256]; + + opts = &_opts; + memset(opts, 0, sizeof(*opts)); + + testutil_check(testutil_parse_opts(argc, argv, opts)); + testutil_make_work_dir(opts->home); + + testutil_check(wiredtiger_open(opts->home, NULL, + "create,cache_size=250M", &opts->conn)); + testutil_check( + opts->conn->open_session(opts->conn, NULL, NULL, &session)); + /* + * Note: repeated primary key 'id' as 'id2'. This makes + * it easier to dump an index and know which record we're + * looking at. + */ + testutil_check(session->create(session, opts->uri, + "key_format=i,value_format=iiii," + "columns=(id,post,balance,flag,id2)")); + + tablename = strchr(opts->uri, ':'); + testutil_assert(tablename != NULL); + tablename++; + snprintf(posturi, sizeof(posturi), "index:%s:post", tablename); + snprintf(balanceuri, sizeof(balanceuri), "index:%s:balance", tablename); + snprintf(flaguri, sizeof(flaguri), "index:%s:flag", tablename); + snprintf(joinuri, sizeof(joinuri), "join:%s", opts->uri); + + testutil_check(session->create(session, posturi, "columns=(post)")); + testutil_check(session->create(session, balanceuri, + "columns=(balance)")); + testutil_check(session->create(session, flaguri, "columns=(flag)")); + + /* + * Insert a single record with all items we are search for, + * this makes our logic easier. + */ + testutil_check(session->open_cursor(session, opts->uri, NULL, NULL, + &maincur)); + maincur->set_key(maincur, N_RECORDS); + maincur->set_value(maincur, 54321, 0, "", 0, N_RECORDS); + maincur->insert(maincur); + maincur->close(maincur); + testutil_check(session->close(session, NULL)); + + populate(opts); + + testutil_check(opts->conn->open_session( + opts->conn, NULL, NULL, &session)); + + testutil_check(session->open_cursor(session, + posturi, NULL, NULL, &postcur)); + testutil_check(session->open_cursor(session, + balanceuri, NULL, NULL, &balancecur)); + testutil_check(session->open_cursor(session, + flaguri, NULL, NULL, &flagcur)); + testutil_check(session->open_cursor(session, + joinuri, NULL, NULL, &joincur)); + + postcur->set_key(postcur, 54321); + testutil_check(postcur->search(postcur)); + testutil_check(session->join(session, joincur, postcur, + "compare=eq")); + + balancecur->set_key(balancecur, 0); + testutil_check(balancecur->search(balancecur)); + sprintf(cfg, "compare=lt,strategy=bloom,count=%d", + N_RECORDS / 100); + testutil_check(session->join(session, joincur, balancecur, cfg)); + + flagcur->set_key(flagcur, 0); + testutil_check(flagcur->search(flagcur)); + sprintf(cfg, "compare=eq,strategy=bloom,count=%d", + N_RECORDS / 100); + testutil_check(session->join(session, joincur, flagcur, cfg)); + + /* Expect no values returned */ + count = 0; + while ((ret = joincur->next(joincur)) == 0) { + /* + * The values may already have been changed, but + * print them for informational purposes. + */ + testutil_check(joincur->get_key(joincur, &key)); + testutil_check(joincur->get_value(joincur, &post, + &balance, &flag, &key2)); + fprintf(stderr, "FAIL: " + "key=%d/%d, postal_code=%d, balance=%d, flag=%d\n", + key, key2, post, balance, flag); + count++; + } + testutil_assert(count == 0); + + testutil_cleanup(opts); + /* NOTREACHED */ + + return (0); +} + +void populate(TEST_OPTS *opts) +{ + WT_CURSOR *maincur; + WT_SESSION *session; + uint32_t key; + int balance, i, flag, post; + WT_RAND_STATE rnd; + + testutil_check(__wt_random_init_seed(NULL, &rnd)); + + testutil_check(opts->conn->open_session( + opts->conn, NULL, NULL, &session)); + + testutil_check(session->open_cursor(session, opts->uri, NULL, NULL, + &maincur)); + + for (i = 0; i < N_INSERT; i++) { + testutil_check(session->begin_transaction(session, NULL)); + key = (__wt_random(&rnd) % (N_RECORDS)); + maincur->set_key(maincur, key); + if (__wt_random(&rnd) % 11 == 0) + post = 54321; + else + post = i % 100000; + if (__wt_random(&rnd) % 4 == 0) { + balance = -100; + flag = 1; + } else { + balance = 100 * (i + 1); + flag = 0; + } + maincur->set_value(maincur, post, balance, flag, key); + testutil_check(maincur->insert(maincur)); + testutil_check(session->commit_transaction(session, NULL)); + } + maincur->close(maincur); + session->close(session, NULL); +} diff --git a/src/third_party/wiredtiger/test/csuite/wt2853_perf/main.c b/src/third_party/wiredtiger/test/csuite/wt2853_perf/main.c new file mode 100644 index 00000000000..c57d5ba056c --- /dev/null +++ b/src/third_party/wiredtiger/test/csuite/wt2853_perf/main.c @@ -0,0 +1,325 @@ +/*- + * Public Domain 2014-2016 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-2853 + * + * Test case description: create two threads: one is populating/updating + * records in a table with a few indices, the other is reading from table and + * indices. The test is adapted from one that uses cursor joins, this test + * does not, but simulates some of the access patterns. + * + * Failure mode: after a second or two of progress by both threads, they both + * appear to slow dramatically, almost locking up. After some time (I've + * observed from a half minute to a few minutes), the lock up ends and both + * threads seem to be inserting and reading at a normal fast pace. That + * continues until the test ends (~30 seconds). + */ + +void (*custom_die)(void) = NULL; + +static void *thread_insert(void *); +static void *thread_get(void *); + +#define BLOOM false +#define N_RECORDS 10000 +#define N_INSERT 1000000 +#define N_INSERT_THREAD 1 +#define N_GET_THREAD 1 +#define S64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789::" +#define S1024 (S64 S64 S64 S64 S64 S64 S64 S64 S64 S64 S64 S64 S64 S64 S64 S64) + +typedef struct { + char posturi[256]; + char baluri[256]; + char flaguri[256]; + bool bloom; +} SHARED_OPTS; + +typedef struct { + TEST_OPTS *testopts; + SHARED_OPTS *sharedopts; + int threadnum; + int nthread; + int done; + int njoins; + int nfail; +} THREAD_ARGS; + +int +main(int argc, char *argv[]) +{ + SHARED_OPTS *sharedopts, _sharedopts; + TEST_OPTS *opts, _opts; + THREAD_ARGS get_args[N_GET_THREAD], insert_args[N_INSERT_THREAD]; + WT_CURSOR *maincur; + WT_SESSION *session; + pthread_t get_tid[N_GET_THREAD], insert_tid[N_INSERT_THREAD]; + int i, nfail; + const char *tablename; + + opts = &_opts; + sharedopts = &_sharedopts; + memset(opts, 0, sizeof(*opts)); + memset(sharedopts, 0, sizeof(*sharedopts)); + memset(insert_args, 0, sizeof(insert_args)); + memset(get_args, 0, sizeof(get_args)); + nfail = 0; + + sharedopts->bloom = BLOOM; + testutil_check(testutil_parse_opts(argc, argv, opts)); + testutil_make_work_dir(opts->home); + + testutil_check(wiredtiger_open(opts->home, NULL, + "create,cache_size=1G", &opts->conn)); + + testutil_check( + opts->conn->open_session(opts->conn, NULL, NULL, &session)); + + /* + * Note: id is repeated as id2. This makes it easier to + * identify the primary key in dumps of the index files. + */ + testutil_check(session->create(session, opts->uri, + "key_format=i,value_format=iiSii," + "columns=(id,post,bal,extra,flag,id2)")); + + tablename = strchr(opts->uri, ':'); + testutil_assert(tablename != NULL); + tablename++; + snprintf(sharedopts->posturi, sizeof(sharedopts->posturi), + "index:%s:post", tablename); + snprintf(sharedopts->baluri, sizeof(sharedopts->baluri), + "index:%s:bal", tablename); + snprintf(sharedopts->flaguri, sizeof(sharedopts->flaguri), + "index:%s:flag", tablename); + + testutil_check(session->create(session, sharedopts->posturi, + "columns=(post)")); + testutil_check(session->create(session, sharedopts->baluri, + "columns=(bal)")); + testutil_check(session->create(session, sharedopts->flaguri, + "columns=(flag)")); + + /* + * Insert a single record with all items we need to + * call search() on, this makes our join logic easier. + */ + testutil_check(session->open_cursor(session, opts->uri, NULL, NULL, + &maincur)); + maincur->set_key(maincur, N_RECORDS); + maincur->set_value(maincur, 54321, 0, "", 0, N_RECORDS); + testutil_check(maincur->insert(maincur)); + testutil_check(maincur->close(maincur)); + testutil_check(session->close(session, NULL)); + + for (i = 0; i < N_INSERT_THREAD; ++i) { + insert_args[i].threadnum = i; + insert_args[i].nthread = N_INSERT_THREAD; + insert_args[i].testopts = opts; + insert_args[i].sharedopts = sharedopts; + testutil_check(pthread_create(&insert_tid[i], NULL, + thread_insert, (void *)&insert_args[i])); + } + + for (i = 0; i < N_GET_THREAD; ++i) { + get_args[i].threadnum = i; + get_args[i].nthread = N_GET_THREAD; + get_args[i].testopts = opts; + get_args[i].sharedopts = sharedopts; + testutil_check(pthread_create(&get_tid[i], NULL, + thread_get, (void *)&get_args[i])); + } + + /* + * Wait for insert threads to finish. When they + * are done, signal get threads to complete. + */ + for (i = 0; i < N_INSERT_THREAD; ++i) + testutil_check(pthread_join(insert_tid[i], NULL)); + + for (i = 0; i < N_GET_THREAD; ++i) + get_args[i].done = 1; + + for (i = 0; i < N_GET_THREAD; ++i) + testutil_check(pthread_join(get_tid[i], NULL)); + + fprintf(stderr, "\n"); + for (i = 0; i < N_GET_THREAD; ++i) { + fprintf(stderr, " thread %d did %d joins (%d fails)\n", i, + get_args[i].njoins, get_args[i].nfail); + nfail += get_args[i].nfail; + } + + testutil_assert(nfail == 0); + testutil_cleanup(opts); + + return (0); +} + +static void *thread_insert(void *arg) +{ + TEST_OPTS *opts; + THREAD_ARGS *threadargs; + WT_CURSOR *maincur; + WT_RAND_STATE rnd; + WT_SESSION *session; + double elapsed; + time_t prevtime, curtime; /* 1 second resolution is okay */ + int bal, i, flag, key, post; + const char *extra = S1024; + + threadargs = (THREAD_ARGS *)arg; + opts = threadargs->testopts; + testutil_check(__wt_random_init_seed(NULL, &rnd)); + (void)time(&prevtime); + + testutil_check(opts->conn->open_session( + opts->conn, NULL, NULL, &session)); + + testutil_check(session->open_cursor(session, opts->uri, NULL, NULL, + &maincur)); + + for (i = 0; i < N_INSERT; i++) { + /* + * Insert threads may stomp on each other's records; + * that's okay. + */ + key = (int)(__wt_random(&rnd) % N_RECORDS); + testutil_check(session->begin_transaction(session, NULL)); + maincur->set_key(maincur, key); + if (__wt_random(&rnd) % 2 == 0) + post = 54321; + else + post = i % 100000; + if (__wt_random(&rnd) % 2 == 0) { + bal = -100; + flag = 1; + } else { + bal = 100 * (i + 1); + flag = 0; + } + maincur->set_value(maincur, post, bal, extra, flag, key); + testutil_check(maincur->insert(maincur)); + testutil_check(maincur->reset(maincur)); + testutil_check(session->commit_transaction(session, NULL)); + if (i % 1000 == 0 && i != 0) { + if (i % 10000 == 0) + fprintf(stderr, "*"); + else + fprintf(stderr, "."); + (void)time(&curtime); + if ((elapsed = difftime(curtime, prevtime)) > 5.0) { + fprintf(stderr, "\n" + "GAP: %.0f secs after %d inserts\n", + elapsed, i); + threadargs->nfail++; + } + prevtime = curtime; + } + } + testutil_check(maincur->close(maincur)); + testutil_check(session->close(session, NULL)); + return (NULL); +} + +static void *thread_get(void *arg) +{ + SHARED_OPTS *sharedopts; + TEST_OPTS *opts; + THREAD_ARGS *threadargs; + WT_CURSOR *maincur, *postcur; + WT_SESSION *session; + double elapsed; + time_t prevtime, curtime; /* 1 second resolution is okay */ + int bal, flag, key, key2, post, bal2, flag2, post2; + char *extra; + + threadargs = (THREAD_ARGS *)arg; + opts = threadargs->testopts; + sharedopts = threadargs->sharedopts; + (void)time(&prevtime); + + testutil_check(opts->conn->open_session( + opts->conn, NULL, NULL, &session)); + testutil_check(session->open_cursor(session, opts->uri, NULL, NULL, + &maincur)); + + testutil_check(session->open_cursor( + session, sharedopts->posturi, NULL, NULL, &postcur)); + + for (threadargs->njoins = 0; threadargs->done == 0; + threadargs->njoins++) { + testutil_check(session->begin_transaction(session, NULL)); + postcur->set_key(postcur, 54321); + testutil_check(postcur->search(postcur)); + while (postcur->next(postcur) == 0) { + testutil_check(postcur->get_key(postcur, &post)); + testutil_check(postcur->get_value(postcur, &post2, + &bal, &extra, &flag, &key)); + testutil_assert(post == post2); + if (post != 54321) + break; + + maincur->set_key(maincur, key); + testutil_check(maincur->search(maincur)); + testutil_check(maincur->get_value(maincur, &post2, + &bal2, &extra, &flag2, &key2)); + testutil_check(maincur->reset(maincur)); + testutil_assert(key == key2); + testutil_assert(post == post2); + testutil_assert(bal == bal2); + testutil_assert(flag == flag2); + + testutil_assert((flag2 > 0 && bal2 < 0) || + (flag2 == 0 && bal2 >= 0)); + } + /* + * Reset the cursors, potentially allowing the insert + * threads to proceed. + */ + testutil_check(postcur->reset(postcur)); + if (threadargs->njoins % 100 == 0) + fprintf(stderr, "G"); + testutil_check(session->rollback_transaction(session, NULL)); + + (void)time(&curtime); + if ((elapsed = difftime(curtime, prevtime)) > 5.0) { + fprintf(stderr, "\n" + "GAP: %.0f secs after %d gets\n", + elapsed, threadargs->njoins); + threadargs->nfail++; + } + prevtime = curtime; + } + testutil_check(postcur->close(postcur)); + testutil_check(maincur->close(maincur)); + testutil_check(session->close(session, NULL)); + return (NULL); +} diff --git a/src/third_party/wiredtiger/test/format/bdb.c b/src/third_party/wiredtiger/test/format/bdb.c index e56281f2c3e..8b61573fdf9 100644 --- a/src/third_party/wiredtiger/test/format/bdb.c +++ b/src/third_party/wiredtiger/test/format/bdb.c @@ -186,6 +186,7 @@ bdb_remove(uint64_t keyno, int *notfoundp) size_t size; int ret; + size = 0; key_gen(&keyitem, keyno); key.data = (void *)keyitem.data; key.size = (u_int32_t)keyitem.size; diff --git a/src/third_party/wiredtiger/test/format/format.h b/src/third_party/wiredtiger/test/format/format.h index ad5f408ac30..ece30601cf0 100644 --- a/src/third_party/wiredtiger/test/format/format.h +++ b/src/third_party/wiredtiger/test/format/format.h @@ -29,6 +29,13 @@ #include "test_util.h" #ifdef BDB +/* + * Berkeley DB has an #ifdef we need to provide a value for, we'll see an + * undefined error if it's unset during a strict compile. + */ +#ifndef DB_DBM_HSEARCH +#define DB_DBM_HSEARCH 0 +#endif #include <assert.h> #include <db.h> #endif @@ -69,12 +76,6 @@ #define FORMAT_OPERATION_REPS 3 /* 3 thread operations sets */ -#ifndef _WIN32 -#define SIZET_FMT "%zu" /* size_t format string */ -#else -#define SIZET_FMT "%Iu" /* size_t format string */ -#endif - typedef struct { char *progname; /* Program name */ diff --git a/src/third_party/wiredtiger/test/format/salvage.c b/src/third_party/wiredtiger/test/format/salvage.c index 8274c556364..69805fb1018 100644 --- a/src/third_party/wiredtiger/test/format/salvage.c +++ b/src/third_party/wiredtiger/test/format/salvage.c @@ -107,7 +107,7 @@ found: if (fstat(fd, &sb) == -1) if ((fp = fopen(buf, "w")) == NULL) testutil_die(errno, "salvage-corrupt: open: %s", buf); (void)fprintf(fp, - "salvage-corrupt: offset %" PRIuMAX ", length " SIZET_FMT "\n", + "salvage-corrupt: offset %" PRIuMAX ", length %" WT_SIZET_FMT "\n", (uintmax_t)offset, len); fclose_and_clear(&fp); diff --git a/src/third_party/wiredtiger/test/format/t.c b/src/third_party/wiredtiger/test/format/t.c index 2eb2b078804..12258af8e51 100644 --- a/src/third_party/wiredtiger/test/format/t.c +++ b/src/third_party/wiredtiger/test/format/t.c @@ -44,7 +44,7 @@ int main(int argc, char *argv[]) { time_t start; - int ch, i, onerun, reps; + int ch, onerun, reps; const char *config, *home; config = NULL; @@ -114,14 +114,8 @@ main(int argc, char *argv[]) argc -= __wt_optind; argv += __wt_optind; - /* - * Initialize the global RNG. Start with the standard seeds, and then - * use seconds since the Epoch modulo a prime to run the RNG for some - * number of steps, so we don't start with the same values every time. - */ - __wt_random_init(&g.rnd); - for (i = (int)time(NULL) % 10007; i > 0; --i) - (void)__wt_random(&g.rnd); + /* Initialize the global RNG. */ + testutil_check(__wt_random_init_seed(NULL, &g.rnd)); /* Set up paths. */ path_setup(home); diff --git a/src/third_party/wiredtiger/test/format/wts.c b/src/third_party/wiredtiger/test/format/wts.c index 69195abc3d4..9acca409d6e 100644 --- a/src/third_party/wiredtiger/test/format/wts.c +++ b/src/third_party/wiredtiger/test/format/wts.c @@ -154,6 +154,11 @@ wts_open(const char *home, bool set_api, WT_CONNECTION **connp) ",lsm_manager=(worker_thread_max=%" PRIu32 "),", g.c_lsm_worker_threads); + if (DATASOURCE("lsm") || g.c_cache < 20) { + p += snprintf(p, REMAIN(p, end), + ",eviction_dirty_target=80,eviction_dirty_trigger=95"); + } + /* Eviction worker configuration. */ if (g.c_evict_max != 0) p += snprintf(p, REMAIN(p, end), diff --git a/src/third_party/wiredtiger/test/mciproject.yml b/src/third_party/wiredtiger/test/mciproject.yml index 8825bb65052..ff58d1839cf 100644 --- a/src/third_party/wiredtiger/test/mciproject.yml +++ b/src/third_party/wiredtiger/test/mciproject.yml @@ -109,7 +109,7 @@ tasks: set -o errexit set -o verbose - scons.bat ${smp_command|} "CFLAGS=/Gv /wd4090 /wd4996 /we4047 /we4024 /TC /we4100" wiredtiger.dll libwiredtiger.lib + scons.bat ${smp_command|} "CFLAGS=/Gv /wd4090 /wd4996 /we4047 /we4024 /TC /we4100 /w4133" wiredtiger.dll libwiredtiger.lib - name: fops depends_on: diff --git a/src/third_party/wiredtiger/test/recovery/truncated-log.c b/src/third_party/wiredtiger/test/recovery/truncated-log.c index a7509c27566..c0effa85e95 100644 --- a/src/third_party/wiredtiger/test/recovery/truncated-log.c +++ b/src/third_party/wiredtiger/test/recovery/truncated-log.c @@ -45,11 +45,86 @@ static const char * const uri = "table:main"; "create,log=(file_max=100K,archive=false,enabled)," \ "transaction_sync=(enabled,method=none)" #define ENV_CONFIG_REC "log=(recover=on)" + #define LOG_FILE_1 "WiredTigerLog.0000000001" #define K_SIZE 16 #define V_SIZE 256 +/* + * Write a new log record into the log via log print, then open up a log + * cursor and walk the log to make sure we can read it. The reason for this + * test is that if there is a partial log record at the end of the previous + * log file and truncate does not exist, this tests that we can still read + * past that record. + */ +static void write_and_read_new(WT_SESSION *); +static void +write_and_read_new(WT_SESSION *session) +{ + WT_CURSOR *logc; + WT_ITEM logrec_key, logrec_value; + uint64_t txnid; + uint32_t fileid, log_file, log_offset, opcount, optype, rectype; + int ret; + bool saw_msg; + + /* + * Write a log record and force it to disk so we can read it. + */ + printf("Write log_printf record and verify.\n"); + if ((ret = session->log_printf(session, "Test Log Record")) != 0) + testutil_die(ret, "log_printf"); + if ((ret = session->log_flush(session, "sync=on")) != 0) + testutil_die(ret, "log_flush"); + if ((ret = session->open_cursor( + session, "log:", NULL, NULL, &logc)) != 0) + testutil_die(ret, "open_cursor: log"); + if ((ret = session->open_cursor( + session, "log:", NULL, NULL, &logc)) != 0) + testutil_die(ret, "open_cursor: log"); + saw_msg = false; + while ((ret = logc->next(logc)) == 0) { + /* + * We don't really need to get the key, but in case we want + * the LSN for some message, get it. + */ + if ((ret = logc->get_key(logc, + &log_file, &log_offset, &opcount)) != 0) + testutil_die(errno, "get_key"); + if ((ret = logc->get_value(logc, &txnid, &rectype, + &optype, &fileid, &logrec_key, &logrec_value)) != 0) + testutil_die(errno, "get_value"); + /* + * We should never see a record from log file 2. We wrote + * a record there, but then the record in log file 1 was + * truncated to be a partial record, ending the log there. + * So everything after that, including everything in log + * file 2, is invalid until we get to log file 3 which is where + * the post-recovery records will be written. + */ + if (log_file == 2) + testutil_die(EINVAL, "Found LSN in Log 2"); +#if 0 + printf("LSN [%" PRIu32 "][%" PRIu32 "].%" PRIu32 + ": record type %" PRIu32 " optype %" PRIu32 + " txnid %" PRIu64 " fileid %" PRIu32 "\n", + log_file, log_offset, opcount, + rectype, optype, txnid, fileid); +#endif + if (rectype == WT_LOGREC_MESSAGE) { + saw_msg = true; + printf("Application Record: %s\n", + (char *)logrec_value.data); + break; + } + } + if ((ret = logc->close(logc)) != 0) + testutil_die(ret, "log cursor close"); + if (!saw_msg) + testutil_die(EINVAL, "Did not traverse log printf record"); +} + static void usage(void) WT_GCC_FUNC_DECL_ATTRIBUTE((noreturn)); static void @@ -127,6 +202,10 @@ fill_db(void) if ((ret = cursor->insert(cursor)) != 0) testutil_die(ret, "WT_CURSOR.insert"); + /* + * Walking the ever growing log can be slow, so only start + * looking for the cross into log file 2 after a minimum. + */ if (i > min_key) { if ((ret = session->open_cursor( session, "log:", NULL, NULL, &logc)) != 0) @@ -135,15 +214,26 @@ fill_db(void) logc->set_key(logc, save_lsn.l.file, save_lsn.l.offset, 0); if ((ret = logc->search(logc)) != 0) - testutil_die(errno, "search"); + testutil_die(ret, "search"); } while ((ret = logc->next(logc)) == 0) { if ((ret = logc->get_key(logc, &lsn.l.file, &lsn.l.offset, &unused)) != 0) - testutil_die(errno, "get_key"); + testutil_die(ret, "get_key"); + /* + * Save the LSN so that we know the offset + * of the last LSN in log file 1 later. + */ if (lsn.l.file < 2) save_lsn = lsn; else { + /* + * If this is the first time through + * that the key is larger than the + * minimum key and we're already in + * log file 2 then we did not calculate + * correctly and the test should fail. + */ if (first) testutil_die(EINVAL, "min_key too high"); @@ -155,6 +245,8 @@ fill_db(void) } } first = false; + if ((ret = logc->close(logc)) != 0) + testutil_die(ret, "log cursor close"); } } if (fclose(fp) != 0) @@ -243,7 +335,9 @@ main(int argc, char *argv[]) if (offset > UINT64_MAX - V_SIZE) testutil_die(ERANGE, "offset"); new_offset = offset + V_SIZE; - printf("Parent: Truncate to %" PRIu64 "\n", new_offset); + printf("Parent: Log file 1: Key %" PRIu32 " at %" PRIu64 "\n", + max_key, offset); + printf("Parent: Truncate mid-record to %" PRIu64 "\n", new_offset); if ((ret = truncate(LOG_FILE_1, (wt_off_t)new_offset)) != 0) testutil_die(errno, "truncate"); @@ -263,13 +357,24 @@ main(int argc, char *argv[]) count = 0; while ((ret = cursor->next(cursor)) == 0) ++count; - if ((ret = conn->close(conn, NULL)) != 0) - testutil_die(ret, "WT_CONNECTION:close"); + /* + * The max key in the saved file is the key we truncated, but the + * key space starts at 0 and we're counting the records here, so we + * expect the max key number of records. + */ if (count > max_key) { printf("expected %" PRIu32 " records found %" PRIu32 "\n", max_key, count); return (EXIT_FAILURE); } printf("%" PRIu32 " records verified\n", count); + + /* + * Write a log record and then walk the log to make sure we can + * read that log record that is beyond the truncated record. + */ + write_and_read_new(session); + if ((ret = conn->close(conn, NULL)) != 0) + testutil_die(ret, "WT_CONNECTION:close"); return (EXIT_SUCCESS); } diff --git a/src/third_party/wiredtiger/test/suite/test_config04.py b/src/third_party/wiredtiger/test/suite/test_config04.py index dffa7479f1b..204aa7e27d5 100644 --- a/src/third_party/wiredtiger/test/suite/test_config04.py +++ b/src/third_party/wiredtiger/test/suite/test_config04.py @@ -197,7 +197,7 @@ class test_config04(wttest.WiredTigerTestCase): # Test an absolute path directory. if os.name == 'posix': - logdir = '/tmp/logdir' + logdir = os.path.abspath('absolutelogdir') os.mkdir(logdir) confstr = 'path=' + logdir self.common_log_test(confstr, logdir) diff --git a/src/third_party/wiredtiger/test/suite/test_reconfig03.py b/src/third_party/wiredtiger/test/suite/test_reconfig03.py index c667a5c7d9d..e9d39ea5a76 100644 --- a/src/third_party/wiredtiger/test/suite/test_reconfig03.py +++ b/src/third_party/wiredtiger/test/suite/test_reconfig03.py @@ -54,5 +54,13 @@ class test_reconfig03(wttest.WiredTigerTestCase): time.sleep(1) self.conn.reconfigure("shared_cache=(chunk=11MB, name=bar, reserve=12MB, size=1G)") + def test_reconfig03_log_size(self): + # + # Reconfigure checkpoint based on log size. + # + self.conn.reconfigure("checkpoint=(log_size=20)") + self.conn.reconfigure("checkpoint=(log_size=1M)") + self.conn.reconfigure("checkpoint=(log_size=0)") + if __name__ == '__main__': wttest.run() diff --git a/src/third_party/wiredtiger/test/suite/test_txn07.py b/src/third_party/wiredtiger/test/suite/test_txn07.py index 8dd8238343d..f9577bad7f2 100644 --- a/src/third_party/wiredtiger/test/suite/test_txn07.py +++ b/src/third_party/wiredtiger/test/suite/test_txn07.py @@ -217,6 +217,13 @@ class test_txn07(wttest.WiredTigerTestCase, suite_subprocess): # Check the state after each commit/rollback. self.check_all(current, committed) + # + # Run printlog and make sure it exits with zero status. This should be + # run as soon as we can after the crash to try and conflict with the + # journal file read. + # + + self.runWt(['-h', self.backup_dir, 'printlog'], outfilename='printlog.out') stat_cursor = self.session.open_cursor('statistics:', None, None) clen = stat_cursor[stat.conn.log_compress_len][2] @@ -239,10 +246,5 @@ class test_txn07(wttest.WiredTigerTestCase, suite_subprocess): self.assertEqual(cwrites > 0, True) self.assertEqual((cfails > 0 or csmall > 0), True) - # - # Run printlog and make sure it exits with zero status. - # - self.runWt(['-h', self.backup_dir, 'printlog'], outfilename='printlog.out') - if __name__ == '__main__': wttest.run() diff --git a/src/third_party/wiredtiger/test/thread/rw.c b/src/third_party/wiredtiger/test/thread/rw.c index 10f13b9eb04..c6107a06c49 100644 --- a/src/third_party/wiredtiger/test/thread/rw.c +++ b/src/third_party/wiredtiger/test/thread/rw.c @@ -175,8 +175,8 @@ reader_op(WT_SESSION *session, WT_CURSOR *cursor, INFO *s) if ((ret = cursor->search(cursor)) != 0 && ret != WT_NOTFOUND) testutil_die(ret, "cursor.search"); if (log_print) - (void)session->log_printf(session, - "Reader Thread %p key %017u", pthread_self(), keyno); + testutil_check(session->log_printf(session, + "Reader Thread %p key %017u", pthread_self(), keyno)); } /* @@ -276,8 +276,8 @@ writer_op(WT_SESSION *session, WT_CURSOR *cursor, INFO *s) testutil_die(ret, "cursor.update"); } if (log_print) - (void)session->log_printf(session, - "Writer Thread %p key %017u", pthread_self(), keyno); + testutil_check(session->log_printf(session, + "Writer Thread %p key %017u", pthread_self(), keyno)); } /* |