Skip to content

Commit ec131e8

Browse files
ruby-oujoEvergreen Agent
authored andcommitted
Import wiredtiger: 5b5f12635bdc5ce6f1c68bc58fbae13ec6a042fd from branch mongodb-master
ref: c1dde2389d..5b5f12635b for: 7.2.0-rc0 WT-11045 Create the mirror table before its base in Workgen
1 parent 6f9b82e commit ec131e8

File tree

3 files changed

+111
-73
lines changed

3 files changed

+111
-73
lines changed

src/third_party/wiredtiger/bench/workgen/workgen.cpp

Lines changed: 107 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ thread_runner_main(void *arg)
132132
runner->_errno = runner->run();
133133
} catch (WorkgenException &wge) {
134134
runner->_exception = wge;
135+
std::cerr << "Exception in runner->run(): " << wge._str << std::endl;
136+
ASSERT(false);
135137
}
136138
return (nullptr);
137139
}
@@ -148,6 +150,7 @@ thread_workload(void *arg)
148150
runner->increment_timestamp(connection);
149151
} catch (WorkgenException &wge) {
150152
std::cerr << "Exception while incrementing timestamp: " << wge._str << std::endl;
153+
ASSERT(false);
151154
}
152155

153156
return (nullptr);
@@ -164,6 +167,7 @@ thread_idle_table_cycle_workload(void *arg)
164167
runner->start_table_idle_cycle(connection);
165168
} catch (WorkgenException &wge) {
166169
std::cerr << "Exception while create/drop tables: " << wge._str << std::endl;
170+
ASSERT(false);
167171
}
168172

169173
return (nullptr);
@@ -180,6 +184,7 @@ thread_tables_create_workload(void *arg)
180184
runner->start_tables_create(connection);
181185
} catch (WorkgenException &wge) {
182186
std::cerr << "Exception while creating tables: " << wge._str << std::endl;
187+
ASSERT(false);
183188
}
184189

185190
return (nullptr);
@@ -196,6 +201,7 @@ thread_tables_drop_workload(void *arg)
196201
runner->start_tables_drop(connection);
197202
} catch (WorkgenException &wge) {
198203
std::cerr << "Exception while dropping tables: " << wge._str << std::endl;
204+
ASSERT(false);
199205
}
200206

201207
return (nullptr);
@@ -353,42 +359,104 @@ gen_random_table_name(char *name, workgen_random_state volatile *rand_state)
353359
* fails.
354360
*/
355361
int
356-
WorkloadRunner::create_table(WT_SESSION *session, const std::string &config, const std::string &uri,
357-
const std::string &mirror_uri, const bool is_base)
362+
WorkloadRunner::create_table(
363+
WT_SESSION *session, const std::string &config, const std::string &uri, bool mirror_enabled)
358364
{
359-
// Check if a table with this name already exists. Return if it does. Use a shared lock to
360-
// read the dynamic table structure.
365+
const std::string mirror_uri(mirror_enabled ? uri + _workload->options.mirror_suffix : "");
366+
367+
// Return if a table with the same name already exists. If mirror is enabled, make sure it does
368+
// not exist either.
361369
ContextInternal *icontext = _workload->_context->_internal;
362370
{
371+
// Use a shared lock to read the dynamic table structure.
363372
const std::shared_lock lock(*icontext->_dyn_mutex);
364373
if (icontext->_tint.count(uri) > 0 || icontext->_dyn_tint.count(uri) > 0)
365374
return EEXIST;
375+
if (mirror_enabled &&
376+
(icontext->_tint.count(mirror_uri) > 0 || icontext->_dyn_tint.count(mirror_uri) > 0))
377+
return EEXIST;
366378
}
367379

368-
// Create the table.
369-
WT_DECL_RET;
370-
if ((ret = session->create(session, uri.c_str(), config.c_str())) != 0) {
371-
if (ret != EBUSY)
372-
THROW("Failed to create table '" << uri << "'.");
380+
/*
381+
* When mirror is enabled, create the mirror first and then the base. If we create the base
382+
* first, threads may start working on the base while the mirror is not fully created.
383+
*
384+
* The config has to be updated with the following information:
385+
* - The name of the table's mirror if mirroring is enabled.
386+
* - If this table is a base table or a mirror.
387+
*
388+
* See below an example when creating the table 'a' with mirror enabled:
389+
* - Configuration expected for the mirror:
390+
* app_metadata="workgen_dynamic_table=true,workgen_table_mirror=table:a,workgen_base_table=false"
391+
* - Configuration expected for the base:
392+
* app_metadata="workgen_dynamic_table=true,workgen_table_mirror=table:a_mirror,workgen_base_table=true"
393+
*
394+
* Without mirror enabled:
395+
* app_metadata="workgen_dynamic_table=true,workgen_base_table=true"
396+
*
397+
*/
398+
std::string mirror_config;
399+
if (mirror_enabled) {
400+
mirror_config = config + "," + MIRROR_TABLE_APP_METADATA + uri + "," +
401+
BASE_TABLE_APP_METADATA + "false\"";
402+
int ret = session->create(session, mirror_uri.c_str(), mirror_config.c_str());
403+
if (ret != 0) {
404+
VERBOSE(*_workload, "Failed to create mirror table '" << mirror_uri << "'");
405+
return ret;
406+
}
407+
// This will be used when creating the base table.
408+
mirror_config = MIRROR_TABLE_APP_METADATA + mirror_uri + ",";
409+
}
410+
411+
// If mirror is enabled, we don't want to fail when creating the base. Getting spurious EBUSY
412+
// errors is ok though, retry in that case.
413+
const std::string base_config(
414+
config + "," + mirror_config + BASE_TABLE_APP_METADATA + "true\"");
415+
int ret, retries = 0;
416+
417+
do {
418+
ret = session->create(session, uri.c_str(), base_config.c_str());
419+
} while (ret != 0 && ret == EBUSY && mirror_enabled && ++retries < TABLE_MAX_RETRIES);
420+
421+
if (ret != 0) {
422+
const std::string err_msg("Failed to create table '" + uri + "'");
423+
VERBOSE(*_workload, err_msg);
424+
// Fail if we have failed at creating the base of a mirror.
425+
if (mirror_enabled)
426+
THROW_ERRNO(ret, err_msg);
373427
return ret;
374428
}
375429

376-
// The data structures for the dynamic table set are protected by a mutex.
430+
// All the required tables have been created, update the data structures for the dynamic tables
431+
// which are protected by a mutex.
377432
{
378433
const std::lock_guard<std::shared_mutex> lock(*icontext->_dyn_mutex);
379-
380-
// Add the table into the list of dynamic set.
381-
tint_t tint = icontext->_dyn_tint_last;
382-
icontext->_dyn_tint[uri] = tint;
383-
icontext->_dyn_table_names[tint] = uri;
384-
icontext->_dyn_table_runtime[tint] = TableRuntime(is_base, mirror_uri);
385-
++icontext->_dyn_tint_last;
386-
VERBOSE(*_workload, "Created table and added to the dynamic set: " << uri);
434+
update_dyn_struct_locked(uri, true, mirror_uri);
435+
if (mirror_enabled)
436+
update_dyn_struct_locked(mirror_uri, false, uri);
387437
}
388438

389439
return 0;
390440
}
391441

442+
/*
443+
* Update the structures dedicated to tables that can be created or removed during the workload. The
444+
* caller should hold the mutex that protects those structures.
445+
*/
446+
void
447+
WorkloadRunner::update_dyn_struct_locked(
448+
const std::string &uri, bool is_base, const std::string &mirror_uri)
449+
{
450+
ContextInternal *icontext = _workload->_context->_internal;
451+
452+
// This should be safe as we are supposed to be under a lock.
453+
tint_t tint = icontext->_dyn_tint_last++;
454+
icontext->_dyn_tint[uri] = tint;
455+
icontext->_dyn_table_names[tint] = uri;
456+
icontext->_dyn_table_runtime[tint] = TableRuntime(is_base, mirror_uri);
457+
VERBOSE(*_workload, "Created table and added to the dynamic set: " << uri);
458+
}
459+
392460
/*
393461
* This function creates one or more tables at regular intervals, where the interval length and
394462
* number of tables are specified in the workload options. It also monitors the database size and
@@ -415,25 +483,6 @@ WorkloadRunner::start_tables_create(WT_CONNECTION *conn)
415483
creating = db_size < _workload->options.create_target;
416484
}
417485

418-
std::string uri;
419-
std::string mirror_uri = std::string();
420-
int creates, retries, status;
421-
char rand_chars[DYNAMIC_TABLE_LEN];
422-
423-
/*
424-
* Add app_metadata to the config to indicate the table was created dynamically (can be selected
425-
* for random deletion), the name of the table's mirror if mirroring is enabled, and if this
426-
* table is a base table or a mirror. We want these settings to persist over restarts.
427-
*/
428-
std::string base_config =
429-
"key_format=S,value_format=S,app_metadata=\"" + DYN_TABLE_APP_METADATA;
430-
if (_workload->options.mirror_tables) {
431-
base_config += "," + MIRROR_TABLE_APP_METADATA;
432-
} else {
433-
base_config += "," + BASE_TABLE_APP_METADATA + "true\"";
434-
}
435-
std::string config = base_config;
436-
437486
while (!stopping) {
438487
/*
439488
* When managing the database size: If we are creating tables, continue until we reach the
@@ -465,40 +514,27 @@ WorkloadRunner::start_tables_create(WT_CONNECTION *conn)
465514
continue;
466515
}
467516

468-
retries = 0;
469-
creates = 0;
470-
while (creates < _workload->options.create_count) {
517+
// Add app_metadata to the config to indicate the table was created dynamically which means
518+
// it can be selected for random deletion. We want this information to persist over restart.
519+
const std::string config(
520+
"key_format=S,value_format=S,app_metadata=\"" + DYN_TABLE_APP_METADATA);
471521

522+
int creates = 0, retries = 0;
523+
while (
524+
!stopping && creates < _workload->options.create_count && retries < TABLE_MAX_RETRIES) {
472525
// Generate a table name from the user specified prefix and a random alphanumeric
473526
// sequence.
527+
char rand_chars[DYNAMIC_TABLE_LEN];
474528
gen_random_table_name(rand_chars, _rand_state);
475-
uri = "table:";
476-
uri += _workload->options.create_prefix;
477-
uri += rand_chars;
478-
479-
if (_workload->options.mirror_tables) {
480-
// The mirror table name is the table name with the user specified suffix.
481-
mirror_uri = uri + _workload->options.mirror_suffix;
482-
config = base_config + mirror_uri + "," + BASE_TABLE_APP_METADATA + "true\"";
483-
}
529+
const std::string uri("table:" + _workload->options.create_prefix + rand_chars);
484530

485-
// Create the table. Simply continue on failure.
486-
if (create_table(session, config, uri, mirror_uri, true) == 0) {
487-
VERBOSE(*_workload, "Created base table '" << uri << "'");
488-
if (_workload->options.mirror_tables) {
489-
// Create the mirror. Retry on failure and throw an exception after
490-
// making too many retry attempts.
491-
config = base_config + uri + "," + BASE_TABLE_APP_METADATA + "false\"";
492-
do
493-
status = create_table(session, config, mirror_uri, uri, false);
494-
while (status == EBUSY && ++retries < TABLE_MAX_RETRIES);
495-
if (status != 0)
496-
THROW_ERRNO(
497-
status, "Failed to create mirror table '" << mirror_uri << "'.");
498-
VERBOSE(*_workload, "Created mirror table '" << mirror_uri << "'");
499-
}
531+
// Create the table and its mirror if enabled.
532+
int ret = create_table(session, config, uri, _workload->options.mirror_tables);
533+
ASSERT(ret == 0 || ret == EBUSY || ret == EEXIST);
534+
if (ret == 0)
500535
++creates;
501-
}
536+
else
537+
++retries;
502538
}
503539
sleep(_workload->options.create_interval);
504540
}
@@ -709,6 +745,8 @@ monitor_main(void *arg)
709745
monitor->_errno = monitor->run();
710746
} catch (WorkgenException &wge) {
711747
monitor->_exception = wge;
748+
std::cerr << "Exception in monitor->run(): " << wge._str << std::endl;
749+
ASSERT(false);
712750
}
713751
return (nullptr);
714752
}
@@ -1478,7 +1516,7 @@ ThreadRunner::op_get_table(Operation *op) const
14781516

14791517
std::string uri = op->_tables[_number];
14801518
tint_t tint = 0;
1481-
if (uri != std::string()) {
1519+
if (!uri.empty()) {
14821520
const std::shared_lock lock(*_icontext->_dyn_mutex);
14831521
tint = _icontext->_dyn_tint[uri];
14841522
}
@@ -1612,13 +1650,12 @@ ThreadRunner::op_run_setup(Operation *op)
16121650
std::advance(itr, random_value() % num_tables);
16131651

16141652
if (_icontext->_dyn_table_runtime[itr->second]._is_base &&
1615-
!_icontext->_dyn_table_runtime[itr->second]._pending_delete) {
1653+
!_icontext->_dyn_table_runtime[itr->second]._pending_delete)
16161654
break;
1617-
}
16181655
}
1619-
if (num_tables == 0 || retries >= TABLE_MAX_RETRIES) { // Try again next time.
1656+
// Try again next time.
1657+
if (num_tables == 0 || retries >= TABLE_MAX_RETRIES)
16201658
return 0;
1621-
}
16221659

16231660
std::string op_uri = itr->first; // Get the table name.
16241661
tint_t op_tint = itr->second; // Get the tint.

src/third_party/wiredtiger/bench/workgen/workgen_int.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,8 @@ struct WorkloadRunner {
341341
private:
342342
int close_all();
343343
int create_all(WT_CONNECTION *conn, Context *context);
344-
int create_table(WT_SESSION *session, const std::string &config, const std::string &uri,
345-
const std::string &mirror_uri, const bool is_base);
344+
int create_table(
345+
WT_SESSION *session, const std::string &config, const std::string &uri, bool mirror_enabled);
346346
void final_report(timespec &);
347347
void schedule_table_for_drop(const std::map<std::string, tint_t>::iterator &itr,
348348
std::vector<std::string> &pending_delete);
@@ -352,6 +352,7 @@ struct WorkloadRunner {
352352
void report(time_t, time_t, Stats *stats);
353353
int run_all(WT_CONNECTION *conn);
354354
int select_table_for_drop(std::vector<std::string> &pending_delete);
355+
void update_dyn_struct_locked(const std::string &uri, bool is_base, const std::string &mirror_uri);
355356

356357
WorkloadRunner(const WorkloadRunner &); // disallowed
357358
WorkloadRunner& operator=(const WorkloadRunner &other); // disallowed

src/third_party/wiredtiger/import.data

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"vendor": "wiredtiger",
33
"github": "wiredtiger/wiredtiger.git",
44
"branch": "mongodb-master",
5-
"commit": "c1dde2389d34cf4bc0ccfbc5e6e1136f3dbc8ae9"
5+
"commit": "5b5f12635bdc5ce6f1c68bc58fbae13ec6a042fd"
66
}

0 commit comments

Comments
 (0)