@@ -68,6 +68,7 @@ class Experiment {
6868 public:
6969 virtual ~Experiment () = default ;
7070
71+ virtual std::string AdditionalDdlStatement () = 0;
7172 virtual Status SetUp (Config const & config, cs::Database const & database) = 0;
7273 virtual Status TearDown (Config const & config,
7374 cs::Database const & database) = 0;
@@ -123,7 +124,17 @@ int main(int argc, char* argv[]) {
123124 std::cout << config << std::flush;
124125
125126 cs::DatabaseAdminClient admin_client;
126- auto created = admin_client.CreateDatabase (database, {});
127+ std::vector<std::string> additional_statements = [&available, generator] {
128+ std::vector<std::string> statements;
129+ for (auto const & kv : available) {
130+ auto experiment = kv.second (generator);
131+ auto s = experiment->AdditionalDdlStatement ();
132+ if (s.empty ()) continue ;
133+ statements.push_back (std::move (s));
134+ }
135+ return statements;
136+ }();
137+ auto created = admin_client.CreateDatabase (database, additional_statements);
127138 std::cout << " # Waiting for database creation to complete " << std::flush;
128139 for (;;) {
129140 auto status = created.wait_for (std::chrono::seconds (1 ));
@@ -294,37 +305,19 @@ class ExperimentImpl {
294305
295306 static int constexpr kColumnCount = 10 ;
296307
297- Status CreateTable (Config const &, cs::Database const & database,
298- std::string const & table_name) {
308+ std::string CreateTableStatement (std::string const & table_name) {
299309 std::string statement = " CREATE TABLE " + table_name;
300310 statement += " (Key INT64 NOT NULL,\n " ;
301311 for (int i = 0 ; i != kColumnCount ; ++i) {
302312 statement +=
303313 " Data" + std::to_string (i) + " " + Traits::SpannerDataType () + " ,\n " ;
304314 }
305315 statement += " ) PRIMARY KEY (Key)" ;
306- cs::DatabaseAdminClient admin_client;
307- auto created = admin_client.UpdateDatabase (database, {statement});
308- std::cout << " # Waiting for table creation to complete " << std::flush;
309- for (;;) {
310- auto status = created.wait_for (std::chrono::seconds (1 ));
311- if (status == std::future_status::ready) break ;
312- std::cout << ' .' << std::flush;
313- }
314- std::cout << " DONE\n " ;
315- auto db = created.get ();
316- if (!db) {
317- std::cerr << " Error creating table: " << db.status () << " \n " ;
318- return std::move (db).status ();
319- }
320- return {};
316+ return statement;
321317 }
322318
323319 Status FillTable (Config const & config, cs::Database const & database,
324320 std::string const & table_name) {
325- auto status = CreateTable (config, database, table_name);
326- if (!status.ok ()) return status;
327-
328321 // We need to populate some data or all the requests to read will fail.
329322 cs::Client client (cs::MakeConnection (database));
330323 std::cout << " # Populating database " << std::flush;
@@ -424,6 +417,24 @@ class ExperimentImpl {
424417 std::cout << " # " << s << std::endl;
425418 }
426419
420+ std::pair<std::vector<cs::Client>,
421+ std::vector<std::shared_ptr<cs::internal::SpannerStub>>>
422+ CreateClientsAndStubs (Config const & config, cs::Database const & database) {
423+ std::vector<cs::Client> clients;
424+ std::vector<std::shared_ptr<cs::internal::SpannerStub>> stubs;
425+ std::cout << " # Creating clients and stubs " << std::flush;
426+ for (int i = 0 ; i != config.maximum_clients ; ++i) {
427+ auto options = cs::ConnectionOptions ().set_channel_pool_domain (
428+ " task:" + std::to_string (i));
429+ clients.emplace_back (cs::Client (cs::MakeConnection (database, options)));
430+ stubs.emplace_back (
431+ cs::internal::CreateDefaultSpannerStub (options, /* channel_id=*/ 0 ));
432+ std::cout << ' .' << std::flush;
433+ }
434+ std::cout << " DONE\n " ;
435+ return {clients, stubs};
436+ }
437+
427438 private:
428439 Status FillTableTask (Config const & config, cs::Client client,
429440 std::string const & table_name, int task_count,
@@ -446,7 +457,7 @@ class ExperimentImpl {
446457 auto mutation = cs::InsertOrUpdateMutationBuilder (table_name, column_names);
447458 int current_mutations = 0 ;
448459
449- auto maybe_flush = [&, this ](bool force) -> Status {
460+ auto maybe_flush = [&](bool force) -> Status {
450461 if (current_mutations == 0 ) {
451462 return {};
452463 }
@@ -458,7 +469,7 @@ class ExperimentImpl {
458469 [&m](cs::Transaction const &) { return cs::Mutations{m}; });
459470 if (!result) {
460471 std::lock_guard<std::mutex> lk (mu_);
461- std::cerr << " # Error in Commit() " << result.status () << " \n " ;
472+ std::cout << " # Error in Commit() " << result.status () << " \n " ;
462473 return std::move (result).status ();
463474 }
464475 mutation = cs::InsertOrUpdateMutationBuilder (table_name, column_names);
@@ -475,6 +486,7 @@ class ExperimentImpl {
475486 if (key % task_count != task_id) continue ;
476487 // Have one of the threads report progress about 50 times.
477488 if (task_id == 0 && key % report_period == 0 ) {
489+ std::lock_guard<std::mutex> lk (mu_);
478490 std::cout << ' .' << std::flush;
479491 }
480492 mutation.EmplaceRow (key, value0, value1, value2, value3, value4, value5,
@@ -510,6 +522,10 @@ class ReadExperiment : public Experiment {
510522 : impl_(generator),
511523 table_name_(" ReadExperiment_" + Traits::TableSuffix()) {}
512524
525+ std::string AdditionalDdlStatement () override {
526+ return impl_.CreateTableStatement (table_name_);
527+ }
528+
513529 Status SetUp (Config const & config, cs::Database const & database) override {
514530 return impl_.FillTable (config, database, table_name_);
515531 }
@@ -520,16 +536,7 @@ class ReadExperiment : public Experiment {
520536 // Create enough clients and stubs for the worst case
521537 std::vector<cs::Client> clients;
522538 std::vector<std::shared_ptr<cs::internal::SpannerStub>> stubs;
523- std::cout << " # Creating clients and stubs " << std::flush;
524- for (int i = 0 ; i != config.maximum_clients ; ++i) {
525- auto options = cs::ConnectionOptions ().set_channel_pool_domain (
526- " task:" + std::to_string (i));
527- clients.emplace_back (cs::Client (cs::MakeConnection (database, options)));
528- stubs.emplace_back (
529- cs::internal::CreateDefaultSpannerStub (options, /* channel_id=*/ 0 ));
530- std::cout << ' .' << std::flush;
531- }
532- std::cout << " DONE\n " ;
539+ std::tie (clients, stubs) = impl_.CreateClientsAndStubs (config, database);
533540
534541 // Capture some overall getrusage() statistics as comments.
535542 SimpleTimer overall;
@@ -593,7 +600,7 @@ class ReadExperiment : public Experiment {
593600 if (!session) {
594601 std::ostringstream os;
595602 os << " SESSION ERROR = " << session.status ();
596- impl_.LogError (os .str ());
603+ impl_.LogError (std::move (os) .str ());
597604 return {};
598605 }
599606
@@ -733,26 +740,20 @@ class SelectExperiment : public Experiment {
733740 : impl_(generator),
734741 table_name_(" SelectExperiment_" + Traits::TableSuffix()) {}
735742
743+ std::string AdditionalDdlStatement () override {
744+ return impl_.CreateTableStatement (table_name_);
745+ }
746+
736747 Status SetUp (Config const & config, cs::Database const & database) override {
737748 return impl_.FillTable (config, database, table_name_);
738749 }
739750
740751 Status TearDown (Config const &, cs::Database const &) override { return {}; }
741752
742753 Status Run (Config const & config, cs::Database const & database) override {
743- // Create enough clients and stubs for the worst case
744754 std::vector<cs::Client> clients;
745755 std::vector<std::shared_ptr<cs::internal::SpannerStub>> stubs;
746- std::cout << " # Creating clients and stubs " << std::flush;
747- for (int i = 0 ; i != config.maximum_clients ; ++i) {
748- auto options = cs::ConnectionOptions ().set_channel_pool_domain (
749- " task:" + std::to_string (i));
750- clients.emplace_back (cs::Client (cs::MakeConnection (database, options)));
751- stubs.emplace_back (
752- cs::internal::CreateDefaultSpannerStub (options, /* channel_id=*/ 0 ));
753- std::cout << ' .' << std::flush;
754- }
755- std::cout << " DONE\n " ;
756+ std::tie (clients, stubs) = impl_.CreateClientsAndStubs (config, database);
756757
757758 // Capture some overall getrusage() statistics as comments.
758759 SimpleTimer overall;
@@ -816,7 +817,7 @@ class SelectExperiment : public Experiment {
816817 if (!session) {
817818 std::ostringstream os;
818819 os << " SESSION ERROR = " << session.status ();
819- impl_.LogError (os .str ());
820+ impl_.LogError (std::move (os) .str ());
820821 return {};
821822 }
822823
@@ -973,26 +974,20 @@ class UpdateExperiment : public Experiment {
973974 : impl_(generator),
974975 table_name_(" UpdateExperiment_" + Traits::TableSuffix()) {}
975976
977+ std::string AdditionalDdlStatement () override {
978+ return impl_.CreateTableStatement (table_name_);
979+ }
980+
976981 Status SetUp (Config const & config, cs::Database const & database) override {
977982 return impl_.FillTable (config, database, table_name_);
978983 }
979984
980985 Status TearDown (Config const &, cs::Database const &) override { return {}; }
981986
982987 Status Run (Config const & config, cs::Database const & database) override {
983- // Create enough clients and stubs for the worst case
984988 std::vector<cs::Client> clients;
985989 std::vector<std::shared_ptr<cs::internal::SpannerStub>> stubs;
986- std::cout << " # Creating clients and stubs " << std::flush;
987- for (int i = 0 ; i != config.maximum_clients ; ++i) {
988- auto options = cs::ConnectionOptions ().set_channel_pool_domain (
989- " task:" + std::to_string (i));
990- clients.emplace_back (cs::Client (cs::MakeConnection (database, options)));
991- stubs.emplace_back (
992- cs::internal::CreateDefaultSpannerStub (options, /* channel_id=*/ 0 ));
993- std::cout << ' .' << std::flush;
994- }
995- std::cout << " DONE\n " ;
990+ std::tie (clients, stubs) = impl_.CreateClientsAndStubs (config, database);
996991
997992 // Capture some overall getrusage() statistics as comments.
998993 SimpleTimer overall;
@@ -1058,7 +1053,7 @@ class UpdateExperiment : public Experiment {
10581053 if (!session) {
10591054 std::ostringstream os;
10601055 os << " SESSION ERROR = " << session.status ();
1061- impl_.LogError (os .str ());
1056+ impl_.LogError (std::move (os) .str ());
10621057 return {};
10631058 }
10641059
@@ -1240,26 +1235,18 @@ class MutationExperiment : public Experiment {
12401235 : impl_(generator),
12411236 table_name_(" MutationExperiment_" + Traits::TableSuffix()) {}
12421237
1243- Status SetUp (Config const & config, cs::Database const & database ) override {
1244- return impl_.CreateTable (config, database, table_name_);
1238+ std::string AdditionalDdlStatement ( ) override {
1239+ return impl_.CreateTableStatement ( table_name_);
12451240 }
12461241
1242+ Status SetUp (Config const &, cs::Database const &) override { return {}; }
1243+
12471244 Status TearDown (Config const &, cs::Database const &) override { return {}; }
12481245
12491246 Status Run (Config const & config, cs::Database const & database) override {
1250- // Create enough clients and stubs for the worst case
12511247 std::vector<cs::Client> clients;
12521248 std::vector<std::shared_ptr<cs::internal::SpannerStub>> stubs;
1253- std::cout << " # Creating clients and stubs " << std::flush;
1254- for (int i = 0 ; i != config.maximum_clients ; ++i) {
1255- auto options = cs::ConnectionOptions ().set_channel_pool_domain (
1256- " task:" + std::to_string (i));
1257- clients.emplace_back (cs::Client (cs::MakeConnection (database, options)));
1258- stubs.emplace_back (
1259- cs::internal::CreateDefaultSpannerStub (options, /* channel_id=*/ 0 ));
1260- std::cout << ' .' << std::flush;
1261- }
1262- std::cout << " DONE\n " ;
1249+ std::tie (clients, stubs) = impl_.CreateClientsAndStubs (config, database);
12631250
12641251 random_keys_.resize (config.table_size );
12651252 std::iota (random_keys_.begin (), random_keys_.end (), 0 );
@@ -1332,7 +1319,7 @@ class MutationExperiment : public Experiment {
13321319 if (!session) {
13331320 std::ostringstream os;
13341321 os << " SESSION ERROR = " << session.status ();
1335- impl_.LogError (os .str ());
1322+ impl_.LogError (std::move (os) .str ());
13361323 return {};
13371324 }
13381325
@@ -1473,13 +1460,15 @@ class RunAllExperiment : public Experiment {
14731460 public:
14741461 explicit RunAllExperiment (google::cloud::internal::DefaultPRNG generator)
14751462 : generator_(generator) {}
1463+
1464+ std::string AdditionalDdlStatement () override { return {}; }
14761465 Status SetUp (Config const &, cs::Database const &) override { return {}; }
14771466 Status TearDown (Config const &, cs::Database const &) override { return {}; }
14781467
1479- Status Run (Config const & cfg, cs::Database const & /* database*/ ) override {
1468+ Status Run (Config const & cfg, cs::Database const & database) override {
14801469 // Smoke test all the experiments by running a very small version of each.
14811470
1482- std::vector<std::future<google::cloud:: Status>> tasks ;
1471+ Status last_error ;
14831472 for (auto & kv : AvailableExperiments ()) {
14841473 // Do not recurse, skip this experiment.
14851474 if (kv.first == " run-all" ) continue ;
@@ -1496,42 +1485,22 @@ class RunAllExperiment : public Experiment {
14961485
14971486 auto experiment = kv.second (generator_);
14981487
1499- // TODO(#1119) - tests disabled until we can stay within admin op quota
1500- #if 0
1501- tasks.push_back(std::async(
1502- std::launch::async,
1503- [](Config config, cs::Database const& database,
1504- std::mutex& mu, std::unique_ptr<Experiment> experiment) {
1505- {
1506- std::lock_guard<std::mutex> lk(mu);
1507- std::cout << "# Smoke test for experiment\n";
1508- std::cout << config << "\n" << std::flush;
1509- }
1510- auto status = experiment->SetUp(config, database);
1511- if (!status.ok()) {
1512- std::lock_guard<std::mutex> lk(mu);
1513- std::cout << "# ERROR in SetUp: " << status << "\n";
1514- return status;
1515- }
1516- config.use_only_clients = true;
1517- experiment->Run(config, database);
1518- config.use_only_stubs = true;
1519- experiment->Run(config, database);
1520- experiment->TearDown(config, database);
1521- return google::cloud::Status();
1522- },
1523- config, database, std::ref(mu_), std::move(experiment)));
1524- #endif
1525- }
1526-
1527- Status status;
1528- for (auto & task : tasks) {
1529- auto s = task.get ();
1530- if (!s.ok ()) {
1531- status = std::move (s);
1488+ std::cout << " # Smoke test for experiment\n " ;
1489+ std::cout << config << " \n " << std::flush;
1490+ auto status = experiment->SetUp (config, database);
1491+ if (!status.ok ()) {
1492+ std::cout << " # ERROR in SetUp: " << status << " \n " ;
1493+ last_error = status;
1494+ continue ;
15321495 }
1496+ config.use_only_clients = true ;
1497+ experiment->Run (config, database);
1498+ config.use_only_stubs = true ;
1499+ experiment->Run (config, database);
1500+ experiment->TearDown (config, database);
15331501 }
1534- return status;
1502+
1503+ return last_error;
15351504 }
15361505
15371506 private:
0 commit comments