diff --git a/config/tools/CMakeLists.txt b/config/tools/CMakeLists.txt index a5d595e39..f111d13d9 100644 --- a/config/tools/CMakeLists.txt +++ b/config/tools/CMakeLists.txt @@ -1,10 +1,10 @@ project(config_gen) -include_directories(../../src ../../config/tools ../../3rdparty/secp256k1/include) +include_directories(../../src ../../3rdparty/secp256k1/include) add_library(config_generator config_generator.cpp) -add_executable(generate_config generate_configd.cpp) +add_executable(generate_config generate_config.cpp) target_link_libraries(generate_config config_generator util diff --git a/config/tools/config_generator.cpp b/config/tools/config_generator.cpp index 1e437747c..ff318899c 100644 --- a/config/tools/config_generator.cpp +++ b/config/tools/config_generator.cpp @@ -6,32 +6,32 @@ #include "config_generator.hpp" +#include "util/common/config.hpp" #include "util/common/keys.hpp" +#include "util/common/variant_overloaded.hpp" #include "util/network/tcp_listener.hpp" #include #include -#include #include #include #include // NORMAL CONFIGS -// Integer that determines if this is 2PC or Atomizer. 1 means 2PC -static constexpr auto two_phase_mode = "2pc"; -// Number of shards to be created -static constexpr auto shard_count_key = "shard_count"; -// Number of sentinels to be created -static constexpr auto sentinel_count_key = "sentinel_count"; -// Number of coordinators to be created -static constexpr auto coordinator_count_key = "coordinator_count"; -// Number of archivers to be created -static constexpr auto archiver_count_key = "archiver_count"; -// Number of atomizers to be created -static constexpr auto atomizer_count_key = "atomizer_count"; -// Number of watchtowers to be created -static constexpr auto watchtower_count_key = "watchtower_count"; +using namespace cbdc::config; + +// Using the following values from src/common/config.hpp: + +// "cbdc::config::two_phase_mode" : Name of value in config template file that +// is an integer which determines if this is 2PC or Atomizer. 1 means 2PC +// "cbdc::config::shard_count_key" : Number of shards to be created +// "cbdc::config::sentinel_count_key" : Number of sentinels to be created +// "cbdc::config::coordinator_count_key" : Number of coordinators to be created +// "cbdc::config::archiver_count_key" : Number of archivers to be created +// "cbdc::config::atomizer_count_key" : Number of atomizers to be created +// "cbdc::config::watchtower_count_key" : Number of watchtowers to be created + // Prefix of interest that denotes parameters in the file that are used // here to help generate the config file but will not be present in the // final product @@ -69,9 +69,41 @@ std::set log_levels namespace cbdc::generate_config { config_generator::config_generator(std::string& _template_config_file, - const size_t _start_port) + const size_t _start_port, + std::string _build_dir) : m_template_config_file(_template_config_file), m_current_port(_start_port) { + // Get Project root dir and build dir + std::filesystem::path build_dir = std::filesystem::current_path(); + if(_build_dir.at(_build_dir.size() - 1) == '/') { + _build_dir.erase(_build_dir.end() - 1); + } + // This config generator class assumes project root is "opencbdc-tx" + while(build_dir.has_parent_path()) { + if(build_dir.filename() == "opencbdc-tx") { + m_project_root_dir = build_dir; + std::string delimiter = "/"; + std::string tmp_str = _build_dir; + size_t pos = 0; + std::string token; + while((pos = tmp_str.find("/")) != std::string::npos) { + token = tmp_str.substr(0, pos); + build_dir = build_dir.append(token); + tmp_str.erase(0, pos + delimiter.length()); + } + token = tmp_str.substr(0, pos); + build_dir = build_dir.append(token); + tmp_str.erase(0, pos + delimiter.length()); + m_build_dir = build_dir; + std::cout << "Build directory determined to be " + << m_build_dir.string() << std::endl; + std::cout << "Project Root directory determined to be " + << m_project_root_dir.string() << std::endl; + break; + } else { + build_dir = build_dir.parent_path(); + } + } template_file_is_valid = true; if(!std::filesystem::exists(m_template_config_file)) { template_file_is_valid = false; @@ -335,7 +367,7 @@ namespace cbdc::generate_config { [[nodiscard]] auto config_generator::get_param_from_template_file( const std::string option, std::map& config_map) - -> std::variant { + -> std::variant { auto it = config_map.find(option); if(it != config_map.end()) { value_t parsed_val = parse_value(it->second, false); @@ -346,10 +378,7 @@ namespace cbdc::generate_config { } else if(std::holds_alternative(parsed_val)) { return std::get(parsed_val); } else { - std::string error_msg - = "Warning: Unrecognized type for param, " + option + "."; - std::cout << error_msg << std::endl; - return error_msg; + __builtin_unreachable(); } } else { std::string error_msg @@ -376,13 +405,12 @@ namespace cbdc::generate_config { void config_generator::set_log_level(const std::string key, std::string& log_level) { - if(find_value(key, log_level) == false) { - find_value(tmpl_universal_override_log_level, log_level); - } if(log_levels.find(log_level) == log_levels.end()) { log_level = "DEBUG"; std::cout << "Warning: Log level not recognized. Setting to DEBUG" << std::endl; + } else if(find_value(key, log_level) == false) { + find_value(tmpl_universal_override_log_level, log_level); } } @@ -642,27 +670,16 @@ namespace cbdc::generate_config { outFile.close(); } - // This method assumes project root is "opencbdc-tx" and build dir is - // "build" [[nodiscard]] auto config_generator::copy_to_build_dir(const std::string filename) -> bool { std::filesystem::path cwd = std::filesystem::current_path(); cwd.append(filename); - std::filesystem::path build_dir = std::filesystem::current_path(); - while(build_dir.has_parent_path()) { - if(build_dir.filename() == "opencbdc-tx") { - build_dir = build_dir.append("build"); - break; - } else { - build_dir = build_dir.parent_path(); - } - } if(std::filesystem::exists(filename)) { const auto copyOptions = std::filesystem::copy_options::overwrite_existing; // Copy and remove file if we are not in build currently - if(std::filesystem::current_path().filename() != "build") { - std::filesystem::copy(cwd, build_dir, copyOptions); + if(std::filesystem::current_path() != m_build_dir) { + std::filesystem::copy(cwd, m_build_dir, copyOptions); std::filesystem::remove(cwd); } return true; @@ -671,24 +688,11 @@ namespace cbdc::generate_config { } } - // This method assumes project root is "opencbdc-tx" and build dir is - // "build" void config_generator::copy_templates_to_build_dir() { - std::filesystem::path config_dir = std::filesystem::current_path(); - std::filesystem::path build_dir = std::filesystem::current_path(); - while(config_dir.has_parent_path()) { - if(config_dir.filename() == "opencbdc-tx") { - config_dir = config_dir.append("config"); - config_dir = config_dir.append("tools"); - build_dir = build_dir.append("build"); - build_dir = build_dir.append("config"); - build_dir = build_dir.append("tools"); - break; - } else { - config_dir = config_dir.parent_path(); - build_dir = build_dir.parent_path(); - } - } + std::filesystem::path config_dir = m_project_root_dir; + config_dir.append("config").append("tools"); + std::filesystem::path build_config_dir = m_build_dir; + build_config_dir.append("config").append("tools"); for(auto const& dir_entry : std::filesystem::directory_iterator{config_dir}) { std::string filename = dir_entry.path().filename(); @@ -697,7 +701,11 @@ namespace cbdc::generate_config { if(tmp_str == match_str) { const auto copyOptions = std::filesystem::copy_options::overwrite_existing; - std::filesystem::copy(dir_entry, build_dir, copyOptions); + std::filesystem::copy(dir_entry, + build_config_dir, + copyOptions); + std::cout << "Copying " << dir_entry.path().string() << " to " + << build_config_dir.string() << std::endl; } } } @@ -728,8 +736,13 @@ namespace cbdc::generate_config { std::string output_filename = "tmp.cfg"; if(!template_file_is_valid) { + std::filesystem::path temp_build_dir = m_build_dir; + temp_build_dir.append("config").append("tools"); return_msg += "File provided, " + m_template_config_file - + ", does not exist. Aborting operation. \n"; + + ", did not exist but has likely been copied to " + + temp_build_dir.string() + + ". Aborting operation. Please rerun with proper " + "template location \n"; return return_msg; } std::map config_map; @@ -757,8 +770,7 @@ namespace cbdc::generate_config { config_map_it->first, std::get(parsed_val)); } else { - return_msg += "Warning: Unrecognized type for param, " - + config_map_it->first + ". \n"; + __builtin_unreachable(); } } } @@ -794,8 +806,7 @@ namespace cbdc::generate_config { return_msg += "Warning: Two-phase mode requires at least one " "configured shard. Fix configuration template " - "and " - "rerun.\n"; + "and rerun.\n"; return return_msg; } else { create_2pc_component(shard_count_key, @@ -853,8 +864,7 @@ namespace cbdc::generate_config { return_msg += "Warning: Sentinels require at least one " "configured shard. Fix configuration template " - "and " - "rerun. \n"; + "and rerun. \n"; return return_msg; } else { create_atomizer_component( diff --git a/config/tools/config_generator.hpp b/config/tools/config_generator.hpp index 437e96a2a..2f054d1c6 100644 --- a/config/tools/config_generator.hpp +++ b/config/tools/config_generator.hpp @@ -10,6 +10,7 @@ #include "util/common/config.hpp" #include "util/common/random_source.hpp" +#include #include #include @@ -45,7 +46,8 @@ namespace cbdc::generate_config { /// \param _start_port Port to begin using and incrementing from for generated /// configuration file's endpoints config_generator(std::string& _template_config_file, - size_t _start_port); + size_t _start_port, + std::string _build_dir); ~config_generator() = default; @@ -64,6 +66,10 @@ namespace cbdc::generate_config { std::string& m_template_config_file; // Incrementing port to use in config file for all ports unsigned short m_current_port; + // Build directory + std::filesystem::path m_build_dir; + // Project root directory + std::filesystem::path m_project_root_dir; // Map with shard ranges (shard_id, (start range, end_range) std::vector shard_info; std::default_random_engine generator; @@ -115,7 +121,7 @@ namespace cbdc::generate_config { [[nodiscard]] auto get_param_from_template_file( std::string option, std::map& config_map) - -> std::variant; + -> std::variant; void set_param_to_config_file(std::string key, std::string value); void set_param_to_config_file(std::string key, size_t value); void set_param_to_config_file(std::string key, double value); diff --git a/config/tools/generate_config.cpp b/config/tools/generate_config.cpp new file mode 100644 index 000000000..dd7330b71 --- /dev/null +++ b/config/tools/generate_config.cpp @@ -0,0 +1,69 @@ +// Copyright (c) 2022 MIT Digital Currency Initiative, +// Federal Reserve Bank of Boston +// MITRE Corporation +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "config_generator.hpp" + +#include +#include + +auto main(int argc, char** argv) -> int { + auto args = cbdc::config::get_args(argc, argv); + + std::mt19937 rng; + static const auto m_random_source + = std::make_unique(cbdc::config::random_source); + + std::string build_dir = "build"; + size_t max_param_num = 4; + size_t min_param_num = 3; + if(args.size() == 2 && (args[1] == "-h" || args[1] == "--help")) { + std::cout << "Usage: " << args[0] + << " " + << std::endl; + return 0; + } else if(args.size() < min_param_num) { + std::cerr << "Usage: " << args[0] + << " " + << std::endl; + return 0; + } else if(args.size() == min_param_num) { + std::cout << "No build directory name specified as third. Using " + "default name of 'build'" + << std::endl; + } else if(args.size() == max_param_num) { + build_dir = args[max_param_num - 1]; + } else if(args.size() > max_param_num) { + std::cerr << "Too many parameters input. Usage: " << args[0] + << " " + << std::endl; + return 0; + } + + auto port_is_valid = std::isdigit(*args[2].c_str()); + if(!port_is_valid) { + std::cerr << "Port number provided, " << args[2] + << ", is not a valid number. Exiting..." << std::endl; + return 0; + } + size_t port_num = static_cast(std::stoull(args[2])); + if(port_num > MAX_PORT_NUM) { + std::cerr << "Port number provided, " << args[2] + << ", is too large. Exiting..." << std::endl; + return 0; + } + cbdc::generate_config::config_generator new_config_gen(args[1], + port_num, + build_dir); + auto cfg_or_err = new_config_gen.generate_configuration_file(); + std::cout << cfg_or_err << std::endl; + return 0; +} diff --git a/config/tools/generate_configd.cpp b/config/tools/generate_configd.cpp deleted file mode 100644 index 97314b092..000000000 --- a/config/tools/generate_configd.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2022 MIT Digital Currency Initiative, -// Federal Reserve Bank of Boston -// MITRE Corporation -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "config_generator.hpp" - -#include -#include - -auto main(int argc, char** argv) -> int { - auto args = cbdc::config::get_args(argc, argv); - - std::mt19937 rng; - static const auto m_random_source - = std::make_unique(cbdc::config::random_source); - - if(args.size() < 3) { - std::cerr << "Usage: " << args[0] - << " " - << std::endl; - return 0; - } - - auto port_is_valid = std::isdigit(*args[2].c_str()); - if(!port_is_valid) { - std::cerr << "Port number provided, " << args[2] - << ", is not a valid number. Exiting..." << std::endl; - return 0; - } - size_t port_num = static_cast(std::stoull(args[2])); - if(port_num > MAX_PORT_NUM) { - std::cerr << "Port number provided, " << args[2] - << ", is too large. Exiting..." << std::endl; - return 0; - } - cbdc::generate_config::config_generator new_config_gen(args[1], port_num); - auto cfg_or_err = new_config_gen.generate_configuration_file(); - std::cout << cfg_or_err << std::endl; - return 0; -} diff --git a/tests/unit/config_gen_test.cpp b/tests/unit/config_gen_test.cpp index b986b9a4d..a8c0f4a2f 100644 --- a/tests/unit/config_gen_test.cpp +++ b/tests/unit/config_gen_test.cpp @@ -7,6 +7,7 @@ #include "config/tools/config_generator.hpp" #include "util/common/config.hpp" +#include #include #include @@ -28,9 +29,11 @@ class config_generation_validation_test : public ::testing::Test { TEST_F(config_generation_validation_test, generate_configuration_file_atomizer_test) { + std::filesystem::path cwd = std::filesystem::current_path(); cbdc::generate_config::config_generator new_config_gen( template_file_atomizer, - port_num); + port_num, + cwd.string()); auto cfg_or_err = new_config_gen.generate_configuration_file(); ASSERT_EQ(cfg_or_err, "SUCCESS"); // TODO @@ -40,8 +43,10 @@ TEST_F(config_generation_validation_test, TEST_F(config_generation_validation_test, generate_configuration_file_two_phase_test) { + std::filesystem::path cwd = std::filesystem::current_path(); cbdc::generate_config::config_generator new_config_gen(template_file_2pc, - port_num); + port_num, + cwd.string()); auto cfg_or_err = new_config_gen.generate_configuration_file(); ASSERT_EQ(cfg_or_err, "SUCCESS"); // TODO