summaryrefslogtreecommitdiff
path: root/test/utility/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/utility/thread.c')
-rw-r--r--test/utility/thread.c282
1 files changed, 282 insertions, 0 deletions
diff --git a/test/utility/thread.c b/test/utility/thread.c
index 08f49c54c5e..4c5202016a5 100644
--- a/test/utility/thread.c
+++ b/test/utility/thread.c
@@ -140,3 +140,285 @@ thread_prev(void *arg)
testutil_check(session->close(session, NULL));
return (NULL);
}
+
+/*
+ * Below are a series of functions originally designed for test/fops. These
+ * threads perform a series of simple API access calls, such as opening and
+ * closing sessions and cursors. These functions require use of the
+ * TEST_PER_THREAD_OPTS structure in test_util.h. Additionally there are two
+ * event handler functions that should be used to suppress "expected" errors
+ * that these functions generate. An example of the use of these functions and
+ * structures is in the csuite test wt3363_checkpoint_op_races.
+ */
+
+/*
+ * Handle errors that generated by series of functions below that we can safely
+ * ignore.
+ */
+int
+handle_op_error(WT_EVENT_HANDLER *handler,
+ WT_SESSION *session, int error, const char *errmsg)
+{
+ (void)(handler);
+ (void)(session);
+
+ /*
+ * Ignore complaints about missing files. It's unlikely but possible
+ * that checkpoints and cursor open operations can return this due to
+ * the sequencing of the various ops.
+ */
+ if (error == ENOENT)
+ return (0);
+
+ /* Ignore complaints about failure to open bulk cursors. */
+ if (strstr(
+ errmsg, "bulk-load is only supported on newly created") != NULL)
+ return (0);
+
+ return (fprintf(stderr, "%s\n", errmsg) < 0 ? -1 : 0);
+}
+
+/*
+ * Handle messages generated by the functions below that we can safely ignore.
+ */
+int
+handle_op_message(WT_EVENT_HANDLER *handler,
+ WT_SESSION *session, const char *message)
+{
+ (void)(handler);
+ (void)(session);
+
+ /* Ignore messages about failing to create forced checkpoints. */
+ if (strstr(message, "forced or named checkpoint") != NULL)
+ return (0);
+
+ return (printf("%s\n", message) < 0 ? -1 : 0);
+}
+
+/*
+ * Create a table and open a bulk cursor on it.
+ */
+void *
+op_bulk(void *arg)
+{
+ TEST_OPTS *opts;
+ TEST_PER_THREAD_OPTS *args;
+ WT_CURSOR *c;
+ WT_SESSION *session;
+ int ret;
+
+ args = (TEST_PER_THREAD_OPTS *)arg;
+ opts = args->testopts;
+
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+
+ if ((ret = session->create(session, opts->uri, NULL)) != 0)
+ if (ret != EEXIST && ret != EBUSY)
+ testutil_die(ret, "session.create");
+
+ if (ret == 0) {
+ __wt_yield();
+ if ((ret = session->open_cursor(session,
+ opts->uri, NULL, "bulk,checkpoint_wait=false", &c)) == 0) {
+ testutil_check(c->close(c));
+ } else if (ret != ENOENT && ret != EBUSY && ret != EINVAL)
+ testutil_die(ret, "session.open_cursor bulk");
+ }
+
+ testutil_check(session->close(session, NULL));
+ args->thread_counter++;
+
+ return (NULL);
+}
+
+/*
+ * Create a guaranteed unique table and open and close a bulk cursor on it.
+ */
+void *
+op_bulk_unique(void *arg)
+{
+ TEST_OPTS *opts;
+ TEST_PER_THREAD_OPTS *args;
+ WT_CURSOR *c;
+ WT_RAND_STATE rnd;
+ WT_SESSION *session;
+ int ret;
+ char new_uri[64];
+
+ args = (TEST_PER_THREAD_OPTS *)arg;
+ opts = args->testopts;
+ __wt_random_init_seed(NULL, &rnd);
+
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+
+ /* Generate a unique object name. */
+ testutil_check(__wt_snprintf(
+ new_uri, sizeof(new_uri), "%s.%u",
+ opts->uri, __wt_atomic_add64(&opts->unique_id, 1)));
+ testutil_check(session->create(session, new_uri, NULL));
+
+ __wt_yield();
+
+ /*
+ * Opening a bulk cursor may have raced with a forced checkpoint
+ * which created a checkpoint of the empty file, and triggers an EINVAL.
+ */
+ if ((ret = session->open_cursor(
+ session, new_uri, NULL, "bulk,checkpoint_wait=false", &c)) == 0) {
+ testutil_check(c->close(c));
+ } else if (ret != EINVAL && ret != EBUSY)
+ testutil_die(ret,
+ "session.open_cursor bulk unique: %s", new_uri);
+
+ while ((ret = session->drop(session, new_uri, __wt_random(&rnd) & 1 ?
+ "force,checkpoint_wait=false" : "checkpoint_wait=false")) != 0)
+ if (ret != EBUSY)
+ testutil_die(ret, "session.drop: %s", new_uri);
+ else
+ /*
+ * The EBUSY is expected when we run with
+ * checkpoint_wait set to false, so we increment the
+ * counter while in this loop to avoid false positives.
+ */
+ args->thread_counter++;
+
+ testutil_check(session->close(session, NULL));
+ args->thread_counter++;
+
+ return (NULL);
+}
+
+/*
+ * Open and close cursor on a table.
+ */
+void *
+op_cursor(void *arg)
+{
+ TEST_OPTS *opts;
+ TEST_PER_THREAD_OPTS *args;
+ WT_SESSION *session;
+ WT_CURSOR *cursor;
+ int ret;
+
+ args = (TEST_PER_THREAD_OPTS *)arg;
+ opts = args->testopts;
+
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+
+ if ((ret = session->open_cursor(
+ session, opts->uri, NULL, NULL, &cursor)) != 0) {
+ if (ret != ENOENT && ret != EBUSY)
+ testutil_die(ret, "session.open_cursor");
+ } else
+ testutil_check(cursor->close(cursor));
+
+ testutil_check(session->close(session, NULL));
+ args->thread_counter++;
+
+ return (NULL);
+}
+
+/*
+ * Create a table.
+ */
+void *
+op_create(void *arg)
+{
+ TEST_OPTS *opts;
+ TEST_PER_THREAD_OPTS *args;
+ WT_SESSION *session;
+ int ret;
+
+ args = (TEST_PER_THREAD_OPTS *)arg;
+ opts = args->testopts;
+
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+
+ if ((ret = session->create(session, opts->uri, NULL)) != 0)
+ if (ret != EEXIST && ret != EBUSY)
+ testutil_die(ret, "session.create");
+
+ testutil_check(session->close(session, NULL));
+ args->thread_counter++;
+
+ return (NULL);
+}
+
+/*
+ * Create and drop a unique guaranteed table.
+ */
+void *
+op_create_unique(void *arg)
+{
+ TEST_OPTS *opts;
+ TEST_PER_THREAD_OPTS *args;
+ WT_RAND_STATE rnd;
+ WT_SESSION *session;
+ int ret;
+ char new_uri[64];
+
+ args = (TEST_PER_THREAD_OPTS *)arg;
+ opts = args->testopts;
+ __wt_random_init_seed(NULL, &rnd);
+
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+
+ /* Generate a unique object name. */
+ testutil_check(__wt_snprintf(
+ new_uri, sizeof(new_uri), "%s.%u",
+ opts->uri, __wt_atomic_add64(&opts->unique_id, 1)));
+ testutil_check(session->create(session, new_uri, NULL));
+
+ __wt_yield();
+ while ((ret = session->drop(session, new_uri, __wt_random(&rnd) & 1 ?
+ "force,checkpoint_wait=false" : "checkpoint_wait=false")) != 0)
+ if (ret != EBUSY)
+ testutil_die(ret, "session.drop: %s", new_uri);
+ else
+ /*
+ * The EBUSY is expected when we run with
+ * checkpoint_wait set to false, so we increment the
+ * counter while in this loop to avoid false positives.
+ */
+ args->thread_counter++;
+
+ testutil_check(session->close(session, NULL));
+ args->thread_counter++;
+
+ return (NULL);
+}
+
+/*
+ * Drop a table.
+ */
+void *
+op_drop(void *arg)
+{
+ TEST_PER_THREAD_OPTS *args;
+ TEST_OPTS *opts;
+ WT_RAND_STATE rnd;
+ WT_SESSION *session;
+ int ret;
+
+ args = (TEST_PER_THREAD_OPTS *)arg;
+ opts = args->testopts;
+ __wt_random_init_seed(NULL, &rnd);
+
+ testutil_check(
+ opts->conn->open_session(opts->conn, NULL, NULL, &session));
+
+ if ((ret = session->drop(session, opts->uri, __wt_random(&rnd) & 1 ?
+ "force,checkpoint_wait=false" : "checkpoint_wait=false")) != 0)
+ if (ret != ENOENT && ret != EBUSY)
+ testutil_die(ret, "session.drop");
+
+ testutil_check(session->close(session, NULL));
+ args->thread_counter++;
+
+ return (NULL);
+}