summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/test/csuite/wt4803_cache_overflow_abort/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/test/csuite/wt4803_cache_overflow_abort/main.c')
-rw-r--r--src/third_party/wiredtiger/test/csuite/wt4803_cache_overflow_abort/main.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/third_party/wiredtiger/test/csuite/wt4803_cache_overflow_abort/main.c b/src/third_party/wiredtiger/test/csuite/wt4803_cache_overflow_abort/main.c
new file mode 100644
index 00000000000..7d9b0baf132
--- /dev/null
+++ b/src/third_party/wiredtiger/test/csuite/wt4803_cache_overflow_abort/main.c
@@ -0,0 +1,239 @@
+/*-
+ * Public Domain 2014-2019 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"
+
+#include <signal.h>
+#include <sys/wait.h>
+
+/*
+ * JIRA ticket reference: WT-4803
+ * Test case description: This test is checking the functionality of the
+ * lookaside file_max configuration. When the size of the lookaside file exceeds
+ * this value, we expect to panic.
+ * Failure mode: If we receive a panic in the test cases we weren't expecting to
+ * and vice versa.
+ */
+
+#define NUM_KEYS 2000
+
+/*
+ * This is a global flag that should be set before running test_las_workload.
+ * It lets the child process know whether it should be expecting a panic or not
+ * so that it can adjust its exit code as needed.
+ */
+static bool expect_panic;
+
+static int
+handle_message(WT_EVENT_HANDLER *handler,
+ WT_SESSION *session, int error, const char *message)
+{
+ WT_UNUSED(handler);
+ WT_UNUSED(session);
+
+ (void)fprintf(
+ stderr, "%s: %s\n", message, session->strerror(session, error));
+
+ if (error == WT_PANIC &&
+ strstr(message, "exceeds maximum size") != NULL) {
+ fprintf(stderr, "Got cache overflow error (expect_panic=%s)\n",
+ expect_panic ? "true" : "false");
+
+ /*
+ * If we're expecting a panic, exit with zero to indicate to the
+ * parent that this test was successful.
+ *
+ * If not, don't intercept. We'll naturally exit with non-zero
+ * if we're terminating due to panic.
+ */
+ if (expect_panic)
+ exit(EXIT_SUCCESS);
+ }
+
+ return (0);
+}
+
+static WT_EVENT_HANDLER event_handler = {
+ handle_message,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void
+las_workload(TEST_OPTS *opts, const char *las_file_max)
+{
+ WT_CURSOR *cursor;
+ WT_SESSION *other_session, *session;
+ int i;
+ char buf[WT_MEGABYTE], open_config[128];
+
+ testutil_check(__wt_snprintf(open_config, sizeof(open_config),
+ "create,cache_size=50MB,cache_overflow=(file_max=%s)",
+ las_file_max));
+
+ testutil_check(wiredtiger_open(
+ opts->home, &event_handler, open_config, &opts->conn));
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+ testutil_check(
+ session->create(session, opts->uri, "key_format=i,value_format=S"));
+ testutil_check(
+ session->open_cursor(session, opts->uri, NULL, NULL, &cursor));
+
+ memset(buf, 0xA, WT_MEGABYTE);
+ buf[WT_MEGABYTE - 1] = '\0';
+
+ /* Populate the table. */
+ for (i = 0; i < NUM_KEYS; ++i) {
+ cursor->set_key(cursor, i);
+ cursor->set_value(cursor, buf);
+ testutil_check(cursor->insert(cursor));
+ }
+
+ /*
+ * Open a snapshot isolation transaction in another session. This forces
+ * the cache to retain all previous values. Then update all keys with a
+ * new value in the original session while keeping that snapshot
+ * transaction open. With the large value buffer, small cache and lots
+ * of keys, this will force a lot of lookaside usage.
+ *
+ * When the file_max setting is small, the maximum size should easily be
+ * reached and we should panic. When the maximum size is large or not
+ * set, then we should succeed.
+ */
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &other_session));
+ testutil_check(other_session->begin_transaction(
+ other_session, "isolation=snapshot"));
+
+ memset(buf, 0xB, WT_MEGABYTE);
+ buf[WT_MEGABYTE - 1] = '\0';
+
+ for (i = 0; i < NUM_KEYS; ++i) {
+ cursor->set_key(cursor, i);
+ cursor->set_value(cursor, buf);
+ testutil_check(cursor->update(cursor));
+ }
+
+ /*
+ * Cleanup.
+ * We do not get here when the file_max size is small because we will
+ * have already hit the maximum and exited. This code only executes on
+ * the successful path.
+ */
+ testutil_check(
+ other_session->rollback_transaction(other_session, NULL));
+ testutil_check(other_session->close(other_session, NULL));
+
+ testutil_check(cursor->close(cursor));
+ testutil_check(session->close(session, NULL));
+}
+
+static int
+test_las_workload(TEST_OPTS *opts, const char *las_file_max)
+{
+ pid_t pid;
+ int status;
+
+ /*
+ * We're going to run this workload for different configurations of
+ * file_max. So clean out the work directory each time.
+ */
+ testutil_make_work_dir(opts->home);
+
+ /*
+ * Since it's possible that the workload will panic and abort, we will
+ * fork the process and execute the workload in the child process.
+ *
+ * This way, we can safely check the exit code of the child process and
+ * confirm that it is what we expected.
+ */
+ pid = fork();
+ if (pid < 0)
+ /* Failed fork. */
+ testutil_die(errno, "fork");
+ else if (pid == 0) {
+ /* Child process from here. */
+ las_workload(opts, las_file_max);
+
+ /*
+ * If we're expecting a panic during the workload, we shouldn't
+ * get to this point. Exit with non-zero to indicate to parent
+ * that we should fail this test.
+ */
+ fprintf(stderr,
+ "Successfully completed workload (expect_panic=%s)\n",
+ expect_panic ? "true" : "false");
+
+ if (expect_panic)
+ exit(EXIT_FAILURE);
+ else
+ exit(EXIT_SUCCESS);
+ }
+
+ /* Parent process from here. */
+ if (waitpid(pid, &status, 0) == -1)
+ testutil_die(errno, "waitpid");
+
+ return (status);
+}
+
+int
+main(int argc, char **argv)
+{
+ TEST_OPTS opts;
+
+ memset(&opts, 0x0, sizeof(opts));
+ testutil_check(testutil_parse_opts(argc, argv, &opts));
+
+ /*
+ * The lookaside is unbounded.
+ * We don't expect any failure since we can use as much as needed.
+ */
+ expect_panic = false;
+ testutil_check(test_las_workload(&opts, "0"));
+
+ /*
+ * The lookaside is limited to 5GB.
+ * This is more than enough for this workload so we don't expect any
+ * failure.
+ */
+ expect_panic = false;
+ testutil_check(test_las_workload(&opts, "5GB"));
+
+ /*
+ * The lookaside is limited to 100MB.
+ * This is insufficient for this workload so we're expecting a failure.
+ */
+ expect_panic = true;
+ testutil_check(test_las_workload(&opts, "100MB"));
+
+ testutil_cleanup(&opts);
+
+ return (0);
+}