diff options
Diffstat (limited to 'test/utility/thread.c')
-rw-r--r-- | test/utility/thread.c | 282 |
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); +} |