#include "src/common/constants.h" #include "src/common/logger.h" #include "src/common/random_generator.h" #include "src/common/thread_manager.h" #include "src/storage/connection_manager.h" #include #include extern "C" { #include "wiredtiger.h" #include "test_util.h" } using namespace test_harness; /* Declarations to avoid the error raised by -Werror=missing-prototypes. */ void insert_op(WT_CURSOR *cursor, int key_size, int value_size); bool do_inserts = false; int num_inserts = 0; void insert_op(WT_CURSOR *cursor, int key_size, int value_size) { logger::log_msg(LOG_INFO, "called insert_op"); /* Insert random data. */ std::string key, value; while (do_inserts) { key = random_generator::instance().generate_random_string(key_size); value = random_generator::instance().generate_random_string(value_size); cursor->set_key(cursor, key.c_str()); // Check if the key already exists. int ret = cursor->search(cursor); testutil_assert(ret == 0 || ret == WT_NOTFOUND); if (ret == WT_NOTFOUND) ++num_inserts; // Insert/update. cursor->set_key(cursor, key.c_str()); cursor->set_value(cursor, value.c_str()); testutil_check(cursor->insert(cursor)); } } int main(int argc, char *argv[]) { /* Set the program name for error messages. */ const std::string progname = testutil_set_progname(argv); /* Set the tracing level for the logger component. */ logger::trace_level = LOG_INFO; /* Printing some messages. */ logger::log_msg(LOG_INFO, "Starting " + progname); /* Create a connection, set the cache size and specify the home directory. */ const std::string conn_config = CONNECTION_CREATE + ",cache_size=500MB"; const std::string home_dir = std::string(DEFAULT_DIR) + '_' + progname; /* Create connection. */ connection_manager::instance().create(conn_config, home_dir); WT_CONNECTION *conn = connection_manager::instance().get_connection(); /* Open different sessions. */ WT_SESSION *insert_session, *read_session; testutil_check(conn->open_session(conn, nullptr, nullptr, &insert_session)); testutil_check(conn->open_session(conn, nullptr, nullptr, &read_session)); /* Random seed. */ __wt_random_init_seed( (WT_SESSION_IMPL *)insert_session, &((WT_SESSION_IMPL *)insert_session)->rnd); /* Create a collection. */ const std::string collection_name = "table:my_collection"; testutil_check(insert_session->create( insert_session, collection_name.c_str(), DEFAULT_FRAMEWORK_SCHEMA.c_str())); /* Open different cursors. */ WT_CURSOR *insert_cursor, *read_cursor; const std::string cursor_config = ""; testutil_check(insert_session->open_cursor( insert_session, collection_name.c_str(), nullptr, cursor_config.c_str(), &insert_cursor)); testutil_check(read_session->open_cursor( read_session, collection_name.c_str(), nullptr, cursor_config.c_str(), &read_cursor)); /* Store cursors. */ std::vector cursors; cursors.push_back(insert_cursor); cursors.push_back(read_cursor); /* Insert some data. */ std::string key = "zz"; const std::string value = "b"; insert_cursor->set_key(insert_cursor, key.c_str()); insert_cursor->set_value(insert_cursor, value.c_str()); testutil_check(insert_cursor->insert(insert_cursor)); /* Read some data. */ read_cursor->set_key(read_cursor, key.c_str()); testutil_check(read_cursor->search(read_cursor)); /* If we leave the cursor positioned, this seems to bias the random cursor! */ // testutil_check(read_cursor->reset(read_cursor)); /* Create a thread manager and spawn some threads that will work. */ thread_manager t; int key_size = 2, value_size = 2; do_inserts = true; t.add_thread(insert_op, insert_cursor, key_size, value_size); /* Sleep for the test duration. */ int test_duration_s = 5; std::this_thread::sleep_for(std::chrono::seconds(test_duration_s)); /* Stop the threads. */ do_inserts = false; t.join(); /* Close cursors. */ for (auto c : cursors) testutil_check(c->close(c)); /* Another message. */ logger::log_msg(LOG_INFO, "End of test."); // Use a random cursor and go through what we have. WT_CURSOR *random_cursor; // Random cursors config. const std::string random_config("next_random=true"); // const std::string random_config("next_random=true,next_random_sample_size=1000"); testutil_check(insert_session->open_cursor( insert_session, collection_name.c_str(), nullptr, random_config.c_str(), &random_cursor)); // Map of seen elements. std::map seen; int sample_size = 10000; for (int i = 0; i < sample_size; ++i) { const char *my_key; testutil_check(random_cursor->next(random_cursor)); testutil_check(random_cursor->get_key(random_cursor, &my_key)); seen[my_key]++; } for (const auto &elem : seen) { std::cout << elem.first << " " << elem.second << std::endl; } std::cout << "Number of elements seen: " << seen.size() << " vs num inserts " << num_inserts << ". " << (seen.size() * 100 / num_inserts) << "% of the dataset covered." << std::endl; return (0); }