diff options
5 files changed, 32 insertions, 15 deletions
diff --git a/src/third_party/wiredtiger/bench/workgen/workgen.cpp b/src/third_party/wiredtiger/bench/workgen/workgen.cpp index 50334f97d44..224e4be151c 100644 --- a/src/third_party/wiredtiger/bench/workgen/workgen.cpp +++ b/src/third_party/wiredtiger/bench/workgen/workgen.cpp @@ -394,8 +394,12 @@ WorkloadRunner::start_tables_create(WT_CONNECTION *conn) uri += rand_chars; // Check if a table with this name already exists. Skip if it does. - if (icontext->_tint.count(uri) > 0 || icontext->_dyn_tint.count(uri) > 0) - continue; + // Use a shared lock to read the dynamic tables structures. + { + const std::shared_lock lock(*icontext->_dyn_mutex); + if (icontext->_tint.count(uri) > 0 || icontext->_dyn_tint.count(uri) > 0) + continue; + } /* * Create the table. Mark the table as part of the dynamic set by storing extra @@ -411,7 +415,7 @@ WorkloadRunner::start_tables_create(WT_CONNECTION *conn) // The data structures for the dynamic table set are protected by a mutex. { - const std::lock_guard<std::mutex> lock(*icontext->_dyn_mutex); + const std::lock_guard<std::shared_mutex> lock(*icontext->_dyn_mutex); // Add the table into the list of dynamic set. tint_t tint = icontext->_dyn_tint_last; @@ -489,7 +493,7 @@ WorkloadRunner::start_tables_drop(WT_CONNECTION *conn) std::vector<std::string> drop_files; // Files ready to be dropped. // The data structures for the dynamic table set are protected by a mutex. { - const std::lock_guard<std::mutex> lock(*icontext->_dyn_mutex); + const std::lock_guard<std::shared_mutex> lock(*icontext->_dyn_mutex); /* * When dropping, consider how many dynamic tables we have left and how many are already @@ -512,6 +516,8 @@ WorkloadRunner::start_tables_drop(WT_CONNECTION *conn) VERBOSE(*_workload, "Marking pending removal for: " << it->first); icontext->_dyn_table_runtime[it->second]._pending_delete = true; + ASSERT(std::find(pending_delete.begin(), pending_delete.end(), it->first) == + pending_delete.end()); pending_delete.push_back(it->first); ++drops; } @@ -732,7 +738,8 @@ Context::operator=(const Context &other) ContextInternal::ContextInternal() : _tint(), _table_names(), _table_runtime(), _tint_last(0), _dyn_tint(), _dyn_table_names(), - _dyn_table_runtime(), _dyn_tint_last(0), _context_count(0), _dyn_mutex(new std::mutex()) + _dyn_table_runtime(), _dyn_tint_last(0), _context_count(0), + _dyn_mutex(new std::shared_mutex()) { uint32_t count = workgen_atomic_add32(&context_count, 1); @@ -785,7 +792,8 @@ ContextInternal::create_all(WT_CONNECTION *conn) if (std::string(value).find(DYN_TABLE_APP_METADATA) != std::string::npos && WT_PREFIX_MATCH(key, "table:")) { - // Add the table into the list of dynamic set. + // Add the table into the list of dynamic set. We are single threaded here and hence + // do not yet need to protect the dynamic table structures with a lock. _dyn_tint[key] = _dyn_tint_last; _dyn_table_names[_dyn_tint_last] = key; _dyn_table_runtime[_dyn_tint_last] = TableRuntime(); @@ -1292,7 +1300,7 @@ ThreadRunner::op_get_key_recno(Operation *op, uint64_t range, tint_t tint) recno_count = range; else { if (op->_random_table) { - const std::lock_guard<std::mutex> lock(*_icontext->_dyn_mutex); + const std::shared_lock lock(*_icontext->_dyn_mutex); recno_count = _icontext->_dyn_table_runtime.at(tint)._max_recno; } else recno_count = _icontext->_table_runtime[tint]._max_recno; @@ -1347,7 +1355,7 @@ ThreadRunner::op_run(Operation *op) // Find a table to operate on. if (op->_random_table) { - const std::lock_guard<std::mutex> lock(*_icontext->_dyn_mutex); + const std::shared_lock lock(*_icontext->_dyn_mutex); size_t num_tables = _icontext->_dyn_table_names.size(); if (num_tables == 0) @@ -1363,7 +1371,8 @@ ThreadRunner::op_run(Operation *op) if (!marked_deleted) { table_uri = uri; tint = _icontext->_dyn_tint[uri]; - ++_icontext->_dyn_table_runtime[tint]._in_use; + // Use atomic here as we can race with another thread that acquires the shared lock. + (void)workgen_atomic_add32(&_icontext->_dyn_table_runtime[tint]._in_use, 1); } else { goto err; } @@ -1389,7 +1398,7 @@ ThreadRunner::op_run(Operation *op) track = &_stats.insert; if (op->_key._keytype == Key::KEYGEN_APPEND || op->_key._keytype == Key::KEYGEN_AUTO) { if (op->_random_table) { - const std::lock_guard<std::mutex> lock(*_icontext->_dyn_mutex); + const std::shared_lock lock(*_icontext->_dyn_mutex); recno = workgen_atomic_add64(&_icontext->_dyn_table_runtime.at(tint)._max_recno, 1); } else { recno = workgen_atomic_add64(&_icontext->_table_runtime[tint]._max_recno, 1); @@ -1592,9 +1601,10 @@ err: // For operations on random tables, if a table has been selected, decrement the reference // counter. if (op->_random_table && !table_uri.empty()) { - const std::lock_guard<std::mutex> lock(*_icontext->_dyn_mutex); + const std::shared_lock lock(*_icontext->_dyn_mutex); ASSERT(_icontext->_dyn_table_runtime[tint]._in_use > 0); - --_icontext->_dyn_table_runtime[tint]._in_use; + // Use atomic here as we can race with another thread that acquires the shared lock. + (void)workgen_atomic_sub32(&_icontext->_dyn_table_runtime[tint]._in_use, 1); } return (ret); diff --git a/src/third_party/wiredtiger/bench/workgen/workgen_func.c b/src/third_party/wiredtiger/bench/workgen/workgen_func.c index 7480a3d8fa2..d85b8cab7b8 100644 --- a/src/third_party/wiredtiger/bench/workgen/workgen_func.c +++ b/src/third_party/wiredtiger/bench/workgen/workgen_func.c @@ -56,6 +56,12 @@ workgen_atomic_add64(uint64_t *vp, uint64_t v) return (__wt_atomic_add64(vp, v)); } +uint32_t +workgen_atomic_sub32(uint32_t *vp, uint32_t v) +{ + return (__wt_atomic_sub32(vp, v)); +} + void workgen_clock(uint64_t *clockp) { diff --git a/src/third_party/wiredtiger/bench/workgen/workgen_func.h b/src/third_party/wiredtiger/bench/workgen/workgen_func.h index dfabc9dc85d..5471f9bbb31 100644 --- a/src/third_party/wiredtiger/bench/workgen/workgen_func.h +++ b/src/third_party/wiredtiger/bench/workgen/workgen_func.h @@ -29,6 +29,7 @@ struct workgen_random_state; extern uint32_t workgen_atomic_add32(uint32_t *vp, uint32_t v); extern uint64_t workgen_atomic_add64(uint64_t *vp, uint64_t v); +extern uint32_t workgen_atomic_sub32(uint32_t *vp, uint32_t v); extern void workgen_clock(uint64_t *tsp); extern void workgen_epoch(struct timespec *tsp); extern uint32_t workgen_random(struct workgen_random_state volatile *rnd_state); diff --git a/src/third_party/wiredtiger/bench/workgen/workgen_int.h b/src/third_party/wiredtiger/bench/workgen/workgen_int.h index c08759ec802..c2f41ae0d64 100644 --- a/src/third_party/wiredtiger/bench/workgen/workgen_int.h +++ b/src/third_party/wiredtiger/bench/workgen/workgen_int.h @@ -27,7 +27,7 @@ */ #include <map> #include <memory> -#include <mutex> +#include <shared_mutex> #include <ostream> #include <set> #include <string> @@ -222,7 +222,7 @@ struct ContextInternal { std::map<tint_t, TableRuntime> _dyn_table_runtime; tint_t _dyn_tint_last; // This mutex should be used to protect the access to the dynamic tables set. - std::mutex* _dyn_mutex; + std::shared_mutex* _dyn_mutex; // unique id per context, to work with multiple contexts, starts at 1. uint32_t _context_count; diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index 94a0cbb9de1..c33156bd0a7 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -2,5 +2,5 @@ "vendor": "wiredtiger", "github": "wiredtiger/wiredtiger.git", "branch": "mongodb-master", - "commit": "0f4ca11ba5ee921490a6c728ae23864459fabfaf" + "commit": "39c85567caebe0f52ac8120fb0437599bbd40ba5" } |