int main(int argc, char *argv[]) { /* * Add a bunch of tables so that some of the metadata ends up on * other pages and a good number of tables are available after * salvage completes. */ TABLE_INFO table_data[] = { { "file:aaa-file.SS", "key_format=S,value_format=S", false }, { "file:bbb-file.rS", "key_format=r,value_format=S", false }, { "lsm:ccc-lsm.SS", "key_format=S,value_format=S", false }, { "table:ddd-table.SS", "key_format=S,value_format=S", false }, { "table:eee-table.rS", "key_format=r,value_format=S", false }, { "file:fff-file.SS", "key_format=S,value_format=S", false }, { "file:ggg-file.rS", "key_format=r,value_format=S", false }, { "lsm:hhh-lsm.SS", "key_format=S,value_format=S", false }, { "table:iii-table.SS", "key_format=S,value_format=S", false }, { "table:jjj-table.rS", "key_format=r,value_format=S", false }, { CORRUPT, "key_format=S,value_format=S", false }, { NULL, NULL, false } }; TABLE_INFO *t; TEST_OPTS *opts, _opts; int ret; char buf[1024]; opts = &_opts; memset(opts, 0, sizeof(*opts)); testutil_check(testutil_parse_opts(argc, argv, opts)); /* * Set a global. We use this everywhere. */ home = opts->home; testutil_make_work_dir(home); testutil_check( wiredtiger_open(home, &event_handler, "create", &opts->conn)); testutil_check(opts->conn->open_session( opts->conn, NULL, NULL, &wt_session)); /* * Create a bunch of different tables. */ for (t = table_data; t->name != NULL; t++) create_data(t); /* * Take some checkpoints and add more data for out of sync testing. */ make_database_copies(table_data); testutil_check(opts->conn->close(opts->conn, NULL)); opts->conn = NULL; /* * Make copy of original directory. */ copy_database(SAVE); /* * Damage/corrupt WiredTiger.wt. */ printf("corrupt metadata\n"); corrupt_metadata(); testutil_check(__wt_snprintf(buf, sizeof(buf), "cp -p %s/WiredTiger.wt ./%s.SAVE/WiredTiger.wt.CORRUPT", home, home)); printf("copy: %s\n", buf); if ((ret = system(buf)) < 0) testutil_die(ret, "system: %s", buf); run_all_verification(NULL, &table_data[0]); out_of_sync(&table_data[0]); /* * We need to set up the string before we clean up * the structure. Then after the clean up we will * run this command. */ testutil_check(__wt_snprintf(buf, sizeof(buf), "rm -rf core* %s*", home)); testutil_cleanup(opts); /* * We've created a lot of extra directories and possibly some core * files from child process aborts. Manually clean them up. */ printf("cleanup and remove: %s\n", buf); if ((ret = system(buf)) < 0) testutil_die(ret, "system: %s", buf); return (EXIT_SUCCESS); }
int main(int argc, char *argv[]) { POP_RECORD *p; TEST_OPTS *opts, _opts; WT_CURSOR *country_cursor, *country_cursor2, *cursor, *join_cursor, *subjoin_cursor, *year_cursor; WT_SESSION *session; const char *country, *tablename; char countryuri[256], joinuri[256], yearuri[256]; uint64_t recno, population; uint16_t year; int count, ret; opts = &_opts; memset(opts, 0, sizeof(*opts)); testutil_check(testutil_parse_opts(argc, argv, opts)); testutil_make_work_dir(opts->home); tablename = strchr(opts->uri, ':'); testutil_assert(tablename != NULL); tablename++; snprintf(countryuri, sizeof(countryuri), "index:%s:country", tablename); snprintf(yearuri, sizeof(yearuri), "index:%s:year", tablename); snprintf(joinuri, sizeof(joinuri), "join:%s", opts->uri); testutil_check(wiredtiger_open(opts->home, NULL, "create,cache_size=200M", &opts->conn)); testutil_check( opts->conn->open_session(opts->conn, NULL, NULL, &session)); testutil_check(session->create(session, opts->uri, "key_format=r," "value_format=5sHQ," "columns=(id,country,year,population)")); /* Create an index with a simple key. */ testutil_check(session->create(session, countryuri, "columns=(country)")); /* Create an immutable index. */ testutil_check(session->create(session, yearuri, "columns=(year),immutable")); /* Insert the records into the table. */ testutil_check(session->open_cursor( session, opts->uri, NULL, "append", &cursor)); count = 1; for (p = pop_data; p->year != 0; p++) { cursor->set_key(cursor, count); cursor->set_value(cursor, p->country, p->year, p->population); testutil_check(cursor->insert(cursor)); count++; } testutil_check(cursor->close(cursor)); /* Open cursors needed by the join. */ testutil_check(session->open_cursor(session, joinuri, NULL, NULL, &join_cursor)); testutil_check(session->open_cursor(session, countryuri, NULL, NULL, &country_cursor)); testutil_check(session->open_cursor(session, yearuri, NULL, NULL, &year_cursor)); /* select values WHERE country == "AU" AND year > 1900 */ country_cursor->set_key(country_cursor, "AU\0\0\0"); testutil_check(country_cursor->search(country_cursor)); testutil_check(session->join(session, join_cursor, country_cursor, "compare=eq,count=10")); year_cursor->set_key(year_cursor, (uint16_t)1900); testutil_check(year_cursor->search(year_cursor)); testutil_check(session->join(session, join_cursor, year_cursor, "compare=gt,count=10,strategy=bloom")); count = 0; /* List the values that are joined */ while ((ret = join_cursor->next(join_cursor)) == 0) { testutil_check(join_cursor->get_key(join_cursor, &recno)); testutil_check(join_cursor->get_value(join_cursor, &country, &year, &population)); printf("ID %" PRIu64, recno); printf( ": country %s, year %" PRIu16 ", population %" PRIu64 "\n", country, year, population); count++; } testutil_assert(ret == WT_NOTFOUND); testutil_assert(count == 2); testutil_check(join_cursor->close(join_cursor)); testutil_check(year_cursor->close(year_cursor)); testutil_check(country_cursor->close(country_cursor)); /* Open cursors needed by the join. */ testutil_check(session->open_cursor(session, joinuri, NULL, NULL, &join_cursor)); testutil_check(session->open_cursor(session, joinuri, NULL, NULL, &subjoin_cursor)); testutil_check(session->open_cursor(session, countryuri, NULL, NULL, &country_cursor)); testutil_check(session->open_cursor(session, countryuri, NULL, NULL, &country_cursor2)); testutil_check(session->open_cursor(session, yearuri, NULL, NULL, &year_cursor)); /* * select values WHERE (country == "AU" OR country == "UK") * AND year > 1900 * * First, set up the join representing the country clause. */ country_cursor->set_key(country_cursor, "AU\0\0\0"); testutil_check(country_cursor->search(country_cursor)); testutil_check(session->join(session, subjoin_cursor, country_cursor, "operation=or,compare=eq,count=10")); country_cursor2->set_key(country_cursor2, "UK\0\0\0"); testutil_check(country_cursor2->search(country_cursor2)); testutil_check(session->join(session, subjoin_cursor, country_cursor2, "operation=or,compare=eq,count=10")); /* Join that to the top join, and add the year clause */ testutil_check(session->join(session, join_cursor, subjoin_cursor, NULL)); year_cursor->set_key(year_cursor, (uint16_t)1900); testutil_check(year_cursor->search(year_cursor)); testutil_check(session->join(session, join_cursor, year_cursor, "compare=gt,count=10,strategy=bloom")); count = 0; /* List the values that are joined */ while ((ret = join_cursor->next(join_cursor)) == 0) { testutil_check(join_cursor->get_key(join_cursor, &recno)); testutil_check(join_cursor->get_value(join_cursor, &country, &year, &population)); printf("ID %" PRIu64, recno); printf( ": country %s, year %" PRIu16 ", population %" PRIu64 "\n", country, year, population); count++; } testutil_assert(ret == WT_NOTFOUND); testutil_assert(count == 4); testutil_check(join_cursor->close(join_cursor)); testutil_check(subjoin_cursor->close(subjoin_cursor)); testutil_check(country_cursor->close(country_cursor)); testutil_check(country_cursor2->close(country_cursor2)); testutil_check(year_cursor->close(year_cursor)); testutil_check(session->close(session, NULL)); testutil_cleanup(opts); return (EXIT_SUCCESS); }
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); }
int main(int argc, char *argv[]) { TEST_OPTS *opts, _opts; WT_CURSOR *c; WT_SESSION *session; clock_t ce, cs; pthread_t id[100]; uint64_t current_value; int i; opts = &_opts; memset(opts, 0, sizeof(*opts)); opts->nthreads = 10; opts->nrecords = 1000; 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, NULL, "create," "cache_size=2G," "eviction=(threads_max=5)," "statistics=(fast)", &opts->conn)); testutil_check( opts->conn->open_session(opts->conn, NULL, NULL, &session)); testutil_check(session->create(session, opts->uri, "key_format=Q,value_format=Q," "leaf_page_max=32k,")); /* Create the single record. */ testutil_check( session->open_cursor(session, opts->uri, NULL, NULL, &c)); c->set_key(c, 1); c->set_value(c, 0); testutil_check(c->insert(c)); testutil_check(c->close(c)); cs = clock(); for (i = 0; i < (int)opts->nthreads; ++i) { testutil_check(pthread_create( &id[i], NULL, thread_insert_race, (void *)opts)); } while (--i >= 0) testutil_check(pthread_join(id[i], NULL)); testutil_check( session->open_cursor(session, opts->uri, NULL, NULL, &c)); c->set_key(c, 1); testutil_check(c->search(c)); testutil_check(c->get_value(c, ¤t_value)); if (current_value != opts->nthreads * opts->nrecords) { fprintf(stderr, "ERROR: didn't get expected number of changes\n"); fprintf(stderr, "got: %" PRIu64 ", expected: %" PRIu64 "\n", current_value, opts->nthreads * opts->nrecords); return (EXIT_FAILURE); } testutil_check(session->close(session, NULL)); ce = clock(); printf("%" PRIu64 ": %.2lf\n", opts->nrecords, (ce - cs) / (double)CLOCKS_PER_SEC); testutil_cleanup(opts); return (EXIT_SUCCESS); }
int main(int argc, char *argv[]) { TEST_OPTS *opts, _opts; WT_CURSOR *rcursor, *wcursor; WT_ITEM key, value; WT_SESSION *session, *session2; pthread_t thread; uint64_t i; char str[] = "0000000000000000"; /* * Create a clean test directory for this run of the test program if the * environment variable isn't already set (as is done by make check). */ 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=200M", &opts->conn)); testutil_check( opts->conn->open_session(opts->conn, NULL, NULL, &session)); testutil_check( opts->conn->open_session(opts->conn, NULL, NULL, &session2)); testutil_check(session->create(session, name, "key_format=Q,value_format=S")); /* Populate the table with some data. */ testutil_check(session->open_cursor( session, name, NULL, "overwrite", &wcursor)); for (i = 0; i < NUM_DOCS; i++) { wcursor->set_key(wcursor, i); rand_str(i, str); wcursor->set_value(wcursor, str); testutil_check(wcursor->insert(wcursor)); } testutil_check(wcursor->close(wcursor)); printf("%d documents inserted\n", NUM_DOCS); /* Perform some random reads */ testutil_check(session->open_cursor( session, name, NULL, "next_random=true", &rcursor)); query_docs(rcursor, false); testutil_check(rcursor->close(rcursor)); /* Setup Transaction to pin the current values */ testutil_check( session2->begin_transaction(session2, "isolation=snapshot")); testutil_check(session2->open_cursor( session2, name, NULL, "next_random=true", &rcursor)); /* Perform updates in a txn to confirm that we see only the original. */ testutil_check(session->open_cursor( session, name, NULL, "overwrite", &wcursor)); for (i = 0; i < NUM_DOCS; i++) { rand_str(i, str); str[0] = 'A'; wcursor->set_key(wcursor, i); wcursor->set_value(wcursor, str); testutil_check(wcursor->update(wcursor)); } testutil_check(wcursor->close(wcursor)); printf("%d documents set to update\n", NUM_DOCS); /* Random reads, which should see the original values */ query_docs(rcursor, false); testutil_check(rcursor->close(rcursor)); /* Finish the txn */ testutil_check(session2->rollback_transaction(session2, NULL)); /* Random reads, which should see the updated values */ testutil_check(session2->open_cursor( session2, name, NULL, "next_random=true", &rcursor)); query_docs(rcursor, true); testutil_check(rcursor->close(rcursor)); /* Setup a pre-delete txn */ testutil_check( session2->begin_transaction(session2, "isolation=snapshot")); testutil_check(session2->open_cursor( session2, name, NULL, "next_random=true", &rcursor)); /* Delete all but one document */ testutil_check(session->open_cursor( session, name, NULL, "overwrite", &wcursor)); for (i = 0; i < NUM_DOCS - 1; i++) { wcursor->set_key(wcursor, i); testutil_check(wcursor->remove(wcursor)); } testutil_check(wcursor->close(wcursor)); printf("%d documents deleted\n", NUM_DOCS - 1); /* Random reads, which should not see the deletes */ query_docs(rcursor, true); testutil_check(rcursor->close(rcursor)); /* Rollback the txn so we can see the deletes */ testutil_check(session2->rollback_transaction(session2, NULL)); /* Find the one remaining document 3 times */ testutil_check(session2->open_cursor( session2, name, NULL, "next_random=true", &rcursor)); for (i = 0; i < 3; i++) { testutil_check(rcursor->next(rcursor)); testutil_check(rcursor->get_key(rcursor, &key)); testutil_check(rcursor->get_value(rcursor, &value)); /* There should only be one value available to us */ testutil_assertfmt((uint64_t)key.data == NUM_DOCS - 1, "expected %d and got %" PRIu64, NUM_DOCS - 1, (uint64_t)key.data); check_str((uint64_t)key.data, (char *)value.data, true); } printf("Found the deleted doc 3 times\n"); testutil_check(rcursor->close(rcursor)); /* Repopulate the table for compact. */ testutil_check(session->open_cursor( session, name, NULL, "overwrite", &wcursor)); for (i = 0; i < NUM_DOCS - 1; i++) { wcursor->set_key(wcursor, i); rand_str(i, str); str[0] = 'A'; wcursor->set_value(wcursor, str); testutil_check(wcursor->insert(wcursor)); } testutil_check(wcursor->close(wcursor)); /* Run random cursor queries while compact is running */ testutil_check(session2->open_cursor( session2, name, NULL, "next_random=true", &rcursor)); testutil_check(pthread_create(&thread, NULL, compact_thread, session)); query_docs(rcursor, true); testutil_check(rcursor->close(rcursor)); testutil_check(pthread_join(thread, NULL)); /* Delete everything. Check for infinite loops */ testutil_check(session->open_cursor( session, name, NULL, "overwrite", &wcursor)); for (i = 0; i < NUM_DOCS; i++) { wcursor->set_key(wcursor, i); testutil_check(wcursor->remove(wcursor)); } testutil_check(wcursor->close(wcursor)); testutil_check(session2->open_cursor( session2, name, NULL, "next_random=true", &rcursor)); for (i = 0; i < 3; i++) testutil_assert(rcursor->next(rcursor) == WT_NOTFOUND); printf("Successfully got WT_NOTFOUND\n"); testutil_cleanup(opts); return (EXIT_SUCCESS); }
int main(int argc, char *argv[]) { TEST_OPTS *opts, _opts; WT_CURSOR *cursor; WT_SESSION *session; pthread_t thr[NR_THREADS]; size_t t; uint64_t f[NR_FIELDS], r, ts; int i, ret; char table_format[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=1G,checkpoint=(wait=30)," "eviction_trigger=80,eviction_target=64,eviction_dirty_target=65," "log=(enabled,file_max=10M)," "transaction_sync=(enabled=true,method=none)", &opts->conn)); testutil_check(opts->conn->open_session( opts->conn, NULL, NULL, &session)); sprintf(table_format, "key_format=r,value_format="); for (i = 0; i < NR_FIELDS; i++) strcat(table_format, "Q"); /* recno -> timestamp + NR_FIELDS * Q */ testutil_check(session->create( session, opts->uri, table_format)); /* timestamp -> recno */ testutil_check(session->create(session, "table:index", "key_format=Q,value_format=Q")); testutil_check(session->close(session, NULL)); for (t = 0; t < NR_THREADS; ++t) testutil_check(pthread_create( &thr[t], NULL, thread_func, (void *)opts)); for (t = 0; t < NR_THREADS; ++t) (void)pthread_join(thr[t], NULL); testutil_check(opts->conn->open_session( opts->conn, NULL, NULL, &session)); /* recno -> timestamp + NR_FIELDS * Q */ testutil_check(session->create(session, opts->uri, table_format)); testutil_check(session->open_cursor( session, opts->uri, NULL, NULL, &cursor)); while ((ret = cursor->next(cursor)) == 0) { testutil_check(cursor->get_key(cursor, &r)); testutil_check(cursor->get_value(cursor, &ts, &f[0], &f[1], &f[2], &f[3], &f[4], &f[5], &f[6], &f[7])); if (!opts->verbose) continue; printf("(%" PRIu64 ",%llu)\t\t%" PRIu64, (r >> 40), r & ((1ULL << 40) - 1), ts); for (i = 0; i < NR_FIELDS; i++) printf("\t%" PRIu64, f[i]); printf("\n"); } testutil_assert(ret == WT_NOTFOUND); testutil_cleanup(opts); return (EXIT_SUCCESS); }
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; if (testutil_disable_long_tests()) return (0); 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); }