diff options
Diffstat (limited to 'src/third_party/wiredtiger/test/thread')
-rw-r--r-- | src/third_party/wiredtiger/test/thread/Makefile.am | 12 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/thread/file.c | 118 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/thread/rw.c | 356 | ||||
-rwxr-xr-x | src/third_party/wiredtiger/test/thread/smoke.sh | 13 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/thread/stats.c | 86 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/thread/t.c | 304 | ||||
-rw-r--r-- | src/third_party/wiredtiger/test/thread/thread.h | 61 |
7 files changed, 950 insertions, 0 deletions
diff --git a/src/third_party/wiredtiger/test/thread/Makefile.am b/src/third_party/wiredtiger/test/thread/Makefile.am new file mode 100644 index 00000000000..a58f019b513 --- /dev/null +++ b/src/third_party/wiredtiger/test/thread/Makefile.am @@ -0,0 +1,12 @@ +AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include \ + -I$(top_srcdir)/test/utility + +noinst_PROGRAMS = t +t_LDADD = $(top_builddir)/libwiredtiger.la +t_SOURCES = thread.h file.c rw.c stats.c t.c +t_LDFLAGS = -static + +TESTS = smoke.sh + +clean-local: + rm -rf WiredTiger* wt.* *.core __stats diff --git a/src/third_party/wiredtiger/test/thread/file.c b/src/third_party/wiredtiger/test/thread/file.c new file mode 100644 index 00000000000..81ec6ad44f8 --- /dev/null +++ b/src/third_party/wiredtiger/test/thread/file.c @@ -0,0 +1,118 @@ +/*- + * 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 "thread.h" + +static void +file_create(const char *name) +{ + WT_SESSION *session; + int ret; + char *p, *end, config[128]; + + if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) + testutil_die(ret, "conn.session"); + + p = config; + end = config + sizeof(config); + p += snprintf(p, (size_t)(end - p), + "key_format=%s," + "internal_page_max=%d," + "leaf_page_max=%d,", + ftype == ROW ? "u" : "r", 16 * 1024, 128 * 1024); + if (ftype == FIX) + (void)snprintf(p, (size_t)(end - p), ",value_format=3t"); + + if ((ret = session->create(session, name, config)) != 0) + if (ret != EEXIST) + testutil_die(ret, "session.create"); + + if ((ret = session->close(session, NULL)) != 0) + testutil_die(ret, "session.close"); +} + +void +load(const char *name) +{ + WT_CURSOR *cursor; + WT_ITEM *key, _key, *value, _value; + WT_SESSION *session; + char keybuf[64], valuebuf[64]; + u_int keyno; + int ret; + + file_create(name); + + if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) + testutil_die(ret, "conn.session"); + + if ((ret = + session->open_cursor(session, name, NULL, "bulk", &cursor)) != 0) + testutil_die(ret, "cursor.open"); + + key = &_key; + value = &_value; + for (keyno = 1; keyno <= nkeys; ++keyno) { + if (ftype == ROW) { + key->data = keybuf; + key->size = (uint32_t) + snprintf(keybuf, sizeof(keybuf), "%017u", keyno); + cursor->set_key(cursor, key); + } else + cursor->set_key(cursor, (uint32_t)keyno); + value->data = valuebuf; + if (ftype == FIX) + cursor->set_value(cursor, 0x01); + else { + value->size = (uint32_t) + snprintf(valuebuf, sizeof(valuebuf), "%37u", keyno); + cursor->set_value(cursor, value); + } + if ((ret = cursor->insert(cursor)) != 0) + testutil_die(ret, "cursor.insert"); + } + + if ((ret = session->close(session, NULL)) != 0) + testutil_die(ret, "session.close"); +} + +void +verify(const char *name) +{ + WT_SESSION *session; + int ret; + + if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) + testutil_die(ret, "conn.session"); + + if ((ret = session->verify(session, name, NULL)) != 0) + testutil_die(ret, "session.create"); + + if ((ret = session->close(session, NULL)) != 0) + testutil_die(ret, "session.close"); +} diff --git a/src/third_party/wiredtiger/test/thread/rw.c b/src/third_party/wiredtiger/test/thread/rw.c new file mode 100644 index 00000000000..913fa6e6c25 --- /dev/null +++ b/src/third_party/wiredtiger/test/thread/rw.c @@ -0,0 +1,356 @@ +/*- + * 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 "thread.h" + +static void print_stats(u_int); +static void *reader(void *); +static void *writer(void *); + +typedef struct { + char *name; /* object name */ + u_int nops; /* Thread op count */ + + WT_RAND_STATE rnd; /* RNG */ + + int remove; /* cursor.remove */ + int update; /* cursor.update */ + int reads; /* cursor.search */ +} INFO; + +static INFO *run_info; + +int +rw_start(u_int readers, u_int writers) +{ + struct timeval start, stop; + double seconds; + pthread_t *tids; + u_int i, name_index, offset, total_nops; + int ret; + void *thread_ret; + + tids = NULL; /* Keep GCC 4.1 happy. */ + total_nops = 0; + + /* Create per-thread structures. */ + if ((run_info = calloc( + (size_t)(readers + writers), sizeof(*run_info))) == NULL || + (tids = calloc((size_t)(readers + writers), sizeof(*tids))) == NULL) + testutil_die(errno, "calloc"); + + /* Create the files and load the initial records. */ + for (i = 0; i < writers; ++i) { + if (i == 0 || multiple_files) { + if ((run_info[i].name = malloc(64)) == NULL) + testutil_die(errno, "malloc"); + snprintf(run_info[i].name, 64, FNAME, i); + + /* Vary by orders of magnitude */ + if (vary_nops) + run_info[i].nops = WT_MAX(1000, max_nops >> i); + load(run_info[i].name); + } else + run_info[i].name = run_info[0].name; + + /* Setup op count if not varying ops. */ + if (run_info[i].nops == 0) + run_info[i].nops = max_nops; + total_nops += run_info[i].nops; + } + + /* Setup the reader configurations */ + for (i = 0; i < readers; ++i) { + offset = i + writers; + if (multiple_files) { + if ((run_info[offset].name = malloc(64)) == NULL) + testutil_die(errno, "malloc"); + /* Have readers read from tables with writes. */ + name_index = i % writers; + snprintf( + run_info[offset].name, 64, FNAME, name_index); + + /* Vary by orders of magnitude */ + if (vary_nops) + run_info[offset].nops = + WT_MAX(1000, max_nops >> name_index); + } else + run_info[offset].name = run_info[0].name; + + /* Setup op count if not varying ops. */ + if (run_info[offset].nops == 0) + run_info[offset].nops = max_nops; + total_nops += run_info[offset].nops; + } + + (void)gettimeofday(&start, NULL); + + /* Create threads. */ + for (i = 0; i < readers; ++i) + if ((ret = pthread_create( + &tids[i], NULL, reader, (void *)(uintptr_t)i)) != 0) + testutil_die(ret, "pthread_create"); + for (; i < readers + writers; ++i) { + if ((ret = pthread_create( + &tids[i], NULL, writer, (void *)(uintptr_t)i)) != 0) + testutil_die(ret, "pthread_create"); + } + + /* Wait for the threads. */ + for (i = 0; i < readers + writers; ++i) + (void)pthread_join(tids[i], &thread_ret); + + (void)gettimeofday(&stop, NULL); + seconds = (stop.tv_sec - start.tv_sec) + + (stop.tv_usec - start.tv_usec) * 1e-6; + fprintf(stderr, "timer: %.2lf seconds (%d ops/second)\n", + seconds, (int)(((readers + writers) * total_nops) / seconds)); + + /* Verify the files. */ + for (i = 0; i < readers + writers; ++i) { + verify(run_info[i].name); + if (!multiple_files) + break; + } + + /* Output run statistics. */ + print_stats(readers + writers); + + /* Free allocated memory. */ + for (i = 0; i < readers + writers; ++i) { + free(run_info[i].name); + if (!multiple_files) + break; + } + + free(run_info); + free(tids); + + return (0); +} + +/* + * reader_op -- + * Read operation. + */ +static inline void +reader_op(WT_SESSION *session, WT_CURSOR *cursor, INFO *s) +{ + WT_ITEM *key, _key; + u_int keyno; + int ret; + char keybuf[64]; + + key = &_key; + + keyno = __wt_random(&s->rnd) % nkeys + 1; + if (ftype == ROW) { + key->data = keybuf; + key->size = (uint32_t) + snprintf(keybuf, sizeof(keybuf), "%017u", keyno); + cursor->set_key(cursor, key); + } else + cursor->set_key(cursor, (uint32_t)keyno); + 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); +} + +/* + * reader -- + * Reader thread start function. + */ +static void * +reader(void *arg) +{ + INFO *s; + WT_CURSOR *cursor; + WT_SESSION *session; + u_int i; + int id, ret; + char tid[128]; + + id = (int)(uintptr_t)arg; + s = &run_info[id]; + __wt_thread_id(tid, sizeof(tid)); + __wt_random_init(&s->rnd); + + printf(" read thread %2d starting: tid: %s, file: %s\n", + id, tid, s->name); + + __wt_yield(); /* Get all the threads created. */ + + if (session_per_op) { + for (i = 0; i < s->nops; ++i, ++s->reads, __wt_yield()) { + if ((ret = conn->open_session( + conn, NULL, NULL, &session)) != 0) + testutil_die(ret, "conn.open_session"); + if ((ret = session->open_cursor( + session, s->name, NULL, NULL, &cursor)) != 0) + testutil_die(ret, "session.open_cursor"); + reader_op(session, cursor, s); + if ((ret = session->close(session, NULL)) != 0) + testutil_die(ret, "session.close"); + } + } else { + if ((ret = conn->open_session( + conn, NULL, NULL, &session)) != 0) + testutil_die(ret, "conn.open_session"); + if ((ret = session->open_cursor( + session, s->name, NULL, NULL, &cursor)) != 0) + testutil_die(ret, "session.open_cursor"); + for (i = 0; i < s->nops; ++i, ++s->reads, __wt_yield()) + reader_op(session, cursor, s); + if ((ret = session->close(session, NULL)) != 0) + testutil_die(ret, "session.close"); + } + + printf(" read thread %2d stopping: tid: %s, file: %s\n", + id, tid, s->name); + + return (NULL); +} + +/* + * writer_op -- + * Write operation. + */ +static inline void +writer_op(WT_SESSION *session, WT_CURSOR *cursor, INFO *s) +{ + WT_ITEM *key, _key, *value, _value; + u_int keyno; + int ret; + char keybuf[64], valuebuf[64]; + + key = &_key; + value = &_value; + + keyno = __wt_random(&s->rnd) % nkeys + 1; + if (ftype == ROW) { + key->data = keybuf; + key->size = (uint32_t) + snprintf(keybuf, sizeof(keybuf), "%017u", keyno); + cursor->set_key(cursor, key); + } else + cursor->set_key(cursor, (uint32_t)keyno); + if (keyno % 5 == 0) { + ++s->remove; + if ((ret = + cursor->remove(cursor)) != 0 && ret != WT_NOTFOUND) + testutil_die(ret, "cursor.remove"); + } else { + ++s->update; + value->data = valuebuf; + if (ftype == FIX) + cursor->set_value(cursor, 0x10); + else { + value->size = (uint32_t)snprintf( + valuebuf, sizeof(valuebuf), "XXX %37u", keyno); + cursor->set_value(cursor, value); + } + if ((ret = cursor->update(cursor)) != 0) + testutil_die(ret, "cursor.update"); + } + if (log_print) + (void)session->log_printf(session, + "Writer Thread %p key %017u", pthread_self(), keyno); +} + +/* + * writer -- + * Writer thread start function. + */ +static void * +writer(void *arg) +{ + INFO *s; + WT_CURSOR *cursor; + WT_SESSION *session; + u_int i; + int id, ret; + char tid[128]; + + id = (int)(uintptr_t)arg; + s = &run_info[id]; + __wt_thread_id(tid, sizeof(tid)); + __wt_random_init(&s->rnd); + + printf("write thread %2d starting: tid: %s, file: %s\n", + id, tid, s->name); + + __wt_yield(); /* Get all the threads created. */ + + if (session_per_op) { + for (i = 0; i < s->nops; ++i, __wt_yield()) { + if ((ret = conn->open_session( + conn, NULL, NULL, &session)) != 0) + testutil_die(ret, "conn.open_session"); + if ((ret = session->open_cursor( + session, s->name, NULL, NULL, &cursor)) != 0) + testutil_die(ret, "session.open_cursor"); + writer_op(session, cursor, s); + if ((ret = session->close(session, NULL)) != 0) + testutil_die(ret, "session.close"); + } + } else { + if ((ret = conn->open_session( + conn, NULL, NULL, &session)) != 0) + testutil_die(ret, "conn.open_session"); + if ((ret = session->open_cursor( + session, s->name, NULL, NULL, &cursor)) != 0) + testutil_die(ret, "session.open_cursor"); + for (i = 0; i < s->nops; ++i, __wt_yield()) + writer_op(session, cursor, s); + if ((ret = session->close(session, NULL)) != 0) + testutil_die(ret, "session.close"); + } + + printf("write thread %2d stopping: tid: %s, file: %s\n", + id, tid, s->name); + + return (NULL); +} + +/* + * print_stats -- + * Display reader/writer thread stats. + */ +static void +print_stats(u_int nthreads) +{ + INFO *s; + u_int id; + + s = run_info; + for (id = 0; id < nthreads; ++id, ++s) + printf("%3d: read %6d, remove %6d, update %6d\n", + id, s->reads, s->remove, s->update); +} diff --git a/src/third_party/wiredtiger/test/thread/smoke.sh b/src/third_party/wiredtiger/test/thread/smoke.sh new file mode 100755 index 00000000000..9a235b1d8e9 --- /dev/null +++ b/src/third_party/wiredtiger/test/thread/smoke.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +set -e + +# Smoke-test format as part of running "make check". +$TEST_WRAPPER ./t -t f +$TEST_WRAPPER ./t -S -F -t f + +$TEST_WRAPPER ./t -t r +$TEST_WRAPPER ./t -S -F -t r + +$TEST_WRAPPER ./t -t v +$TEST_WRAPPER ./t -S -F -t v diff --git a/src/third_party/wiredtiger/test/thread/stats.c b/src/third_party/wiredtiger/test/thread/stats.c new file mode 100644 index 00000000000..67a2c02719b --- /dev/null +++ b/src/third_party/wiredtiger/test/thread/stats.c @@ -0,0 +1,86 @@ +/*- + * 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 "thread.h" + +/* + * stats + * Dump the database/file statistics. + */ +void +stats(void) +{ + FILE *fp; + WT_CURSOR *cursor; + WT_SESSION *session; + uint64_t v; + int ret; + char name[64]; + const char *pval, *desc; + + if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) + testutil_die(ret, "conn.session"); + + if ((fp = fopen(FNAME_STAT, "w")) == NULL) + testutil_die(errno, "fopen " FNAME_STAT); + + /* Connection statistics. */ + if ((ret = session->open_cursor(session, + "statistics:", NULL, NULL, &cursor)) != 0) + testutil_die(ret, "session.open_cursor"); + + while ((ret = cursor->next(cursor)) == 0 && + (ret = cursor->get_value(cursor, &desc, &pval, &v)) == 0) + (void)fprintf(fp, "%s=%s\n", desc, pval); + + if (ret != WT_NOTFOUND) + testutil_die(ret, "cursor.next"); + if ((ret = cursor->close(cursor)) != 0) + testutil_die(ret, "cursor.close"); + + /* File statistics. */ + if (!multiple_files) { + (void)snprintf(name, sizeof(name), "statistics:" FNAME, 0); + if ((ret = session->open_cursor( + session, name, NULL, NULL, &cursor)) != 0) + testutil_die(ret, "session.open_cursor"); + + while ((ret = cursor->next(cursor)) == 0 && + (ret = cursor->get_value(cursor, &desc, &pval, &v)) == 0) + (void)fprintf(fp, "%s=%s\n", desc, pval); + + if (ret != WT_NOTFOUND) + testutil_die(ret, "cursor.next"); + if ((ret = cursor->close(cursor)) != 0) + testutil_die(ret, "cursor.close"); + + if ((ret = session->close(session, NULL)) != 0) + testutil_die(ret, "session.close"); + } + (void)fclose(fp); +} diff --git a/src/third_party/wiredtiger/test/thread/t.c b/src/third_party/wiredtiger/test/thread/t.c new file mode 100644 index 00000000000..e72b54bf62a --- /dev/null +++ b/src/third_party/wiredtiger/test/thread/t.c @@ -0,0 +1,304 @@ +/*- + * 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 "thread.h" + +WT_CONNECTION *conn; /* WiredTiger connection */ +__ftype ftype; /* File type */ +u_int nkeys, max_nops; /* Keys, Operations */ +int vary_nops; /* Vary operations by thread */ +int log_print; /* Log print per operation */ +int multiple_files; /* File per thread */ +int session_per_op; /* New session per operation */ + +static char home[512]; /* Program working dir */ +static char *progname; /* Program name */ +static FILE *logfp; /* Log file */ + +static int handle_error(WT_EVENT_HANDLER *, WT_SESSION *, int, const char *); +static int handle_message(WT_EVENT_HANDLER *, WT_SESSION *, const char *); +static void onint(int); +static void shutdown(void); +static int usage(void); +static void wt_connect(char *); +static void wt_shutdown(void); + +extern int __wt_optind; +extern char *__wt_optarg; + +int +main(int argc, char *argv[]) +{ + u_int readers, writers; + int ch, cnt, runs; + char *config_open, *working_dir; + + if ((progname = strrchr(argv[0], DIR_DELIM)) == NULL) + progname = argv[0]; + else + ++progname; + + config_open = NULL; + working_dir = NULL; + ftype = ROW; + log_print = 0; + multiple_files = 0; + nkeys = 1000; + max_nops = 10000; + readers = 10; + runs = 1; + session_per_op = 0; + vary_nops = 0; + writers = 10; + + while ((ch = __wt_getopt( + progname, argc, argv, "C:Fk:h:Ll:n:R:r:St:vW:")) != EOF) + switch (ch) { + case 'C': /* wiredtiger_open config */ + config_open = __wt_optarg; + break; + case 'F': /* multiple files */ + multiple_files = 1; + break; + case 'h': + working_dir = __wt_optarg; + break; + case 'k': /* rows */ + nkeys = (u_int)atoi(__wt_optarg); + break; + case 'L': /* log print per operation */ + log_print = 1; + break; + case 'l': /* log */ + if ((logfp = fopen(__wt_optarg, "w")) == NULL) { + fprintf(stderr, + "%s: %s\n", __wt_optarg, strerror(errno)); + return (EXIT_FAILURE); + } + break; + case 'n': /* operations */ + max_nops = (u_int)atoi(__wt_optarg); + break; + case 'R': + readers = (u_int)atoi(__wt_optarg); + break; + case 'r': /* runs */ + runs = atoi(__wt_optarg); + break; + case 'S': /* new session per operation */ + session_per_op = 1; + break; + case 't': + switch (__wt_optarg[0]) { + case 'f': + ftype = FIX; + break; + case 'r': + ftype = ROW; + break; + case 'v': + ftype = VAR; + break; + default: + return (usage()); + } + break; + case 'v': /* vary operation count */ + vary_nops = 1; + break; + case 'W': + writers = (u_int)atoi(__wt_optarg); + break; + default: + return (usage()); + } + + argc -= __wt_optind; + argv += __wt_optind; + if (argc != 0) + return (usage()); + + testutil_work_dir_from_path(home, 512, working_dir); + + if (vary_nops && !multiple_files) { + fprintf(stderr, + "Variable op counts only supported with multiple tables\n"); + return (usage()); + } + + /* Clean up on signal. */ + (void)signal(SIGINT, onint); + + printf("%s: process %" PRIu64 "\n", progname, (uint64_t)getpid()); + for (cnt = 1; runs == 0 || cnt <= runs; ++cnt) { + printf( + " %d: %u readers, %u writers\n", cnt, readers, writers); + + shutdown(); /* Clean up previous runs */ + + wt_connect(config_open); /* WiredTiger connection */ + + if (rw_start(readers, writers)) /* Loop operations */ + return (EXIT_FAILURE); + + stats(); /* Statistics */ + + wt_shutdown(); /* WiredTiger shut down */ + } + return (0); +} + +/* + * wt_connect -- + * Configure the WiredTiger connection. + */ +static void +wt_connect(char *config_open) +{ + static WT_EVENT_HANDLER event_handler = { + handle_error, + handle_message, + NULL, + NULL /* Close handler. */ + }; + int ret; + char config[512]; + size_t print_count; + + testutil_clean_work_dir(home); + testutil_make_work_dir(home); + + print_count = (size_t)snprintf(config, sizeof(config), + "create,statistics=(all),error_prefix=\"%s\",%s%s", + progname, + config_open == NULL ? "" : ",", + config_open == NULL ? "" : config_open); + + if (print_count >= sizeof(config)) + testutil_die(EINVAL, "Config string too long"); + + if ((ret = wiredtiger_open(home, &event_handler, config, &conn)) != 0) + testutil_die(ret, "wiredtiger_open"); +} + +/* + * wt_shutdown -- + * Flush the file to disk and shut down the WiredTiger connection. + */ +static void +wt_shutdown(void) +{ + WT_SESSION *session; + int ret; + + if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) + testutil_die(ret, "conn.session"); + + if ((ret = session->checkpoint(session, NULL)) != 0) + testutil_die(ret, "session.checkpoint"); + + if ((ret = conn->close(conn, NULL)) != 0) + testutil_die(ret, "conn.close"); +} + +/* + * shutdown -- + * Clean up from previous runs. + */ +static void +shutdown(void) +{ + testutil_clean_work_dir(home); +} + +static int +handle_error(WT_EVENT_HANDLER *handler, + WT_SESSION *session, int error, const char *errmsg) +{ + (void)(handler); + (void)(session); + (void)(error); + + return (fprintf(stderr, "%s\n", errmsg) < 0 ? -1 : 0); +} + +static int +handle_message(WT_EVENT_HANDLER *handler, + WT_SESSION *session, const char *message) +{ + (void)(handler); + (void)(session); + + if (logfp != NULL) + return (fprintf(logfp, "%s\n", message) < 0 ? -1 : 0); + + return (printf("%s\n", message) < 0 ? -1 : 0); +} + +/* + * onint -- + * Interrupt signal handler. + */ +static void +onint(int signo) +{ + (void)(signo); + + shutdown(); + + fprintf(stderr, "\n"); + exit(EXIT_FAILURE); +} + +/* + * usage -- + * Display usage statement and exit failure. + */ +static int +usage(void) +{ + fprintf(stderr, + "usage: %s " + "[-FLSv] [-C wiredtiger-config] [-k keys] [-l log]\n\t" + "[-n ops] [-R readers] [-r runs] [-t f|r|v] [-W writers]\n", + progname); + fprintf(stderr, "%s", + "\t-C specify wiredtiger_open configuration arguments\n" + "\t-F create a file per thread\n" + "\t-k set number of keys to load\n" + "\t-L log print per operation\n" + "\t-l specify a log file\n" + "\t-n set number of operations each thread does\n" + "\t-R set number of reading threads\n" + "\t-r set number of runs (0 for continuous)\n" + "\t-S open/close a session on every operation\n" + "\t-t set a file type (fix | row | var)\n" + "\t-v do a different number of operations on different tables\n" + "\t-W set number of writing threads\n"); + return (EXIT_FAILURE); +} diff --git a/src/third_party/wiredtiger/test/thread/thread.h b/src/third_party/wiredtiger/test/thread/thread.h new file mode 100644 index 00000000000..36cdbebd210 --- /dev/null +++ b/src/third_party/wiredtiger/test/thread/thread.h @@ -0,0 +1,61 @@ +/*- + * 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 <sys/types.h> +#include <sys/time.h> + +#include <errno.h> +#include <inttypes.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "test_util.i" + +#define FNAME "file:wt.%03d" /* File name */ +#define FNAME_STAT "__stats" /* File name for statistics */ + +extern WT_CONNECTION *conn; /* WiredTiger connection */ + +typedef enum { FIX, ROW, VAR } __ftype; /* File type */ +extern __ftype ftype; + +extern int log_print; /* Log print per operation */ +extern int multiple_files; /* File per thread */ +extern u_int nkeys; /* Keys to load */ +extern u_int max_nops; /* Operations per thread */ +extern int vary_nops; /* Operations per thread */ +extern int session_per_op; /* New session per operation */ + +void load(const char *); +int rw_start(u_int, u_int); +void stats(void); +void verify(const char *); |