// Copyright 2023 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace DB::PS::tests { LoggerPtr StressEnv::buildLogger(bool enable_color) { Poco::AutoPtr channel = new Poco::ConsoleChannel(std::cerr); Poco::AutoPtr formatter; if (enable_color) formatter = new DB::UnifiedLogFormatter(); else formatter = new DB::UnifiedLogFormatter(); Poco::AutoPtr formatting_channel(new Poco::FormattingChannel(formatter, channel)); Poco::Logger::root().setChannel(formatting_channel); Poco::Logger::root().setLevel("trace"); return Logger::get(); } StressEnv StressEnv::parse(int argc, char ** argv) { namespace po = boost::program_options; using po::value; po::options_description desc("Allowed options"); desc.add_options()("help,h", "produce help message") // ("write_concurrency,W", value()->default_value(4), "number of write threads") // ("read_concurrency,R", value()->default_value(16), "number of read threads") // ("dropdata", value()->default_value(true), "drop data before running") // ("init_pages", value()->default_value(false), "init pages if not exist before running") // ("timeout,T", value()->default_value(600), "maximum run time (seconds). 0 means run infinitely") // ("writer_slots", value()->default_value(4), "number of PageStorage writer slots (for V2)") // ("read_delay_ms", value()->default_value(0), "millionseconds of read delay") // ("avg_page_size", value()->default_value(2 * 1024 * 1024), "avg size for each page(bytes). 2 MiB by default") // ("paths,P", value>(), "store path(s)") // ("failpoints", value>(), "failpoint(s) to enable") // ("gc_interval", value()->default_value(30), "GC interval(seconds). 0 means no gc") // ("status_interval", value()->default_value(5), "Status statistics interval(seconds). 0 means no statistics") // ("situation_mask,M", value()->default_value(0), "Run special tests sequentially, example -M 2") // ("verify", value()->default_value(true), "Run special tests sequentially with verify.") // ("running_ps_version,V", value()->default_value(3), "Select a version of PageStorage. 2 or 3 can used") // ("color", value()->default_value(true), "enable color output"); po::variables_map options; po::store(po::parse_command_line(argc, argv, desc), options); po::notify(options); if (options.count("help") > 0) { std::cerr << desc << std::endl; std::cerr << PageWorkloadFactory::getInstance().toDebugStirng() << std::endl; exit(0); } StressEnv opt; opt.num_writers = options["write_concurrency"].as(); opt.num_readers = options["read_concurrency"].as(); opt.init_pages = options["init_pages"].as(); opt.dropdata = options["dropdata"].as(); opt.timeout_s = options["timeout"].as(); opt.read_delay_ms = options["read_delay_ms"].as(); opt.num_writer_slots = options["writer_slots"].as(); opt.avg_page_size = options["avg_page_size"].as(); opt.gc_interval_s = options["gc_interval"].as(); opt.status_interval = options["status_interval"].as(); opt.situation_mask = options["situation_mask"].as(); opt.verify = options["verify"].as(); opt.running_ps_version = options["running_ps_version"].as(); opt.logger = buildLogger(options["color"].as()); if (opt.running_ps_version != 2 && opt.running_ps_version != 3) { std::cerr << "Invalid running_ps_version, this arg should be 2 or 3." << std::endl; std::cerr << desc << std::endl; exit(0); } RUNTIME_CHECK(opt.avg_page_size > 0); if (options.count("paths")) opt.paths = options["paths"].as>(); else opt.paths = {"./stress"}; if (options.count("failpoints")) opt.failpoints = options["failpoints"].as>(); return opt; } void setupSignal() { signal(SIGINT, [](int /*signal*/) { LOG_INFO(Logger::get(), "Receive finish signal. Wait for the threads finish"); StressEnvStatus::getInstance().setStat(STATUS_INTERRUPT); PageWorkloadFactory::getInstance().stopWorkload(); }); } void StressEnv::setup() { CurrentMemoryTracker::disableThreshold(); #ifdef FIU_ENABLE fiu_init(0); #endif for (const auto & fp : failpoints) { DB::FailPointHelper::enableFailPoint(fp); } // drop dir if exists bool all_directories_not_exist = true; for (const auto & path : paths) { if (Poco::File file(path); file.exists()) { all_directories_not_exist = false; if (dropdata) { file.remove(true); } } } if (dropdata) LOG_INFO(logger, "All pages have been drop."); if (dropdata || all_directories_not_exist) init_pages = true; setupSignal(); } } // namespace DB::PS::tests