diff --git a/src/common/db_backend_selector.cpp b/src/common/db_backend_selector.cpp new file mode 100644 index 00000000..c284a32b --- /dev/null +++ b/src/common/db_backend_selector.cpp @@ -0,0 +1,117 @@ +// Copyright (c) 2014-2020 Zano Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "db_backend_selector.h" +#include "currency_core/currency_config.h" +#include "command_line.h" +#include "db_backend_lmdb.h" +#include "db_backend_mdbx.h" + + +#define LMDB_MAIN_FILE_NAME "data.mdb" +#define MDBX_MAIN_FILE_NAME "mdbx.dat" + +namespace tools +{ +namespace db +{ + + db_backend_selector::db_backend_selector() + : m_engine_type(db_none) + { + } + + void db_backend_selector::init_options(boost::program_options::options_description& desc) + { + command_line::add_arg(desc, command_line::arg_db_engine); + } + + bool db_backend_selector::init(const boost::program_options::variables_map& vm) + { + try + { + m_config_folder = command_line::get_arg(vm, command_line::arg_data_dir); + + if (command_line::get_arg(vm, command_line::arg_db_engine) == ARG_DB_ENGINE_LMDB) + { + m_engine_type = db_lmdb; + } + else if (command_line::get_arg(vm, command_line::arg_db_engine) == ARG_DB_ENGINE_MDBX) + { +#ifdef ENABLED_ENGINE_MDBX + m_engine_type = db_mdbx; +#else + LOG_PRINT_L0(" DB ENGINE: " << ARG_DB_ENGINE_MDBX << " is not suported by this build(see DISABLE_MDBX cmake option), STOPPING"); +#endif + } + else + { + LOG_PRINT_RED_L0("UNKNOWN DB ENGINE: " << command_line::get_arg(vm, command_line::arg_db_engine) << ", STOPPING"); + } + } + catch (std::exception& e) + { + LOG_ERROR("internal error: db_backend_selector::init failed on command-line parsing, exception: " << e.what()); + return false; + } + + if (m_engine_type == db_none) + return false; + + return true; + } + + std::string db_backend_selector::get_db_folder_path() const + { + //CHECK_AND_ASSERT_THROW_MES(m_engine_type != db_none, "db_backend_selector was no inited"); + + return m_config_folder + ("/" CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX) + get_engine_name() + CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX; + } + + std::string db_backend_selector::get_db_main_file_name() const + { + switch (m_engine_type) + { + case db_lmdb: + return LMDB_MAIN_FILE_NAME; + case db_mdbx: + return MDBX_MAIN_FILE_NAME; + default: + return ""; + } + } + + std::string db_backend_selector::get_engine_name() const + { + switch (m_engine_type) + { + case db_lmdb: + return "lmdb"; + case db_mdbx: + return "mdbx"; + default: + return "unknown"; + } + } + + std::shared_ptr db_backend_selector::create_backend() + { + switch (m_engine_type) + { + case db_lmdb: + return std::shared_ptr(new tools::db::lmdb_db_backend); + + case db_mdbx: + return std::shared_ptr(new tools::db::mdbx_db_backend); + + default: + LOG_ERROR("db_backend_selector was no inited"); + return nullptr; + } + } + + + +} // namespace db +} // namespace tools diff --git a/src/common/db_backend_selector.h b/src/common/db_backend_selector.h index cc90af76..1d2e7214 100644 --- a/src/common/db_backend_selector.h +++ b/src/common/db_backend_selector.h @@ -1,48 +1,37 @@ -// Copyright (c) 2014-2019 Zano Project -// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2014-2020 Zano Project // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once -#include "db_backend_lmdb.h" -#include "db_backend_mdbx.h" -#include "common/command_line.h" -#include "common/db_abstract_accessor.h" +#include "db_backend_base.h" namespace tools { namespace db { - inline - bool select_db_engine_from_arg(const boost::program_options::variables_map& vm, tools::db::basic_db_accessor& rdb) + enum db_engine_type { db_none = 0, db_lmdb, db_mdbx }; + + class db_backend_selector { - try - { - if (command_line::get_arg(vm, command_line::arg_db_engine) == ARG_DB_ENGINE_LMDB) - { - rdb.reset_backend(std::shared_ptr(new tools::db::lmdb_db_backend)); - return true; - } - else if (command_line::get_arg(vm, command_line::arg_db_engine) == ARG_DB_ENGINE_MDBX) - { - #ifdef ENABLED_ENGINE_MDBX - rdb.reset_backend(std::shared_ptr(new tools::db::mdbx_db_backend)); - return true; - #else - LOG_PRINT_L0(" DB ENGINE: " << ARG_DB_ENGINE_MDBX << " is not suported by this build(see DISABLE_MDBX cmake option), STOPPING"); - return false; - #endif - } - } - catch (...) - { - LOG_ERROR("internal error: arg_db_engine command-line option could not be read (exception caught)"); - return false; - } + public: + db_backend_selector(); - LOG_PRINT_RED_L0(" UNKNOWN DB ENGINE: " << command_line::get_arg(vm, command_line::arg_db_engine) << ", STOPPING"); - return false; - } - } -} + static void init_options(boost::program_options::options_description& desc); + bool init(const boost::program_options::variables_map& vm); + + std::string get_db_folder_path() const; + std::string get_db_main_file_name() const; + db_engine_type get_engine_type() const { return m_engine_type; } + std::string get_engine_name() const; + std::string get_config_folder() const { return m_config_folder; } + + std::shared_ptr create_backend(); + + private: + db_engine_type m_engine_type; + std::string m_config_folder; + }; + + } // namespace db +} // namespace tools diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 481ea09e..ccd4644b 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -152,7 +152,6 @@ void blockchain_storage::init_options(boost::program_options::options_descriptio { command_line::add_arg(desc, arg_db_cache_l1); command_line::add_arg(desc, arg_db_cache_l2); - command_line::add_arg(desc, command_line::arg_db_engine); } //------------------------------------------------------------------ uint64_t blockchain_storage::get_block_h_older_then(uint64_t timestamp) const @@ -203,14 +202,16 @@ bool blockchain_storage::validate_instance(const std::string& path) } } //------------------------------------------------------------------ -bool blockchain_storage::init(const std::string& config_folder, const boost::program_options::variables_map& vm) +bool blockchain_storage::init(const std::string& config_folder, const boost::program_options::variables_map& vm, tools::db::db_backend_selector& dbbs) { // CRITICAL_REGION_LOCAL(m_read_lock); - if (!select_db_engine_from_arg(vm, m_db)) + auto p_backend = dbbs.create_backend(); + if (!p_backend) { - LOG_PRINT_RED_L0("Failed to select db engine"); + LOG_PRINT_RED_L0("Failed to create db engine"); return false; } + m_db.reset_backend(p_backend); LOG_PRINT_L0("DB ENGINE USED BY CORE: " << m_db.get_backend()->name()); if (!validate_instance(config_folder)) @@ -236,7 +237,7 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(old_db_folder_path)); } ; - const std::string db_folder_path = m_config_folder + ("/" CURRENCY_BLOCKCHAINDATA_FOLDERNAME_PREFIX) + m_db.get_backend()->name() + CURRENCY_BLOCKCHAINDATA_FOLDERNAME_SUFFIX; + const std::string db_folder_path = dbbs.get_db_folder_path(); LOG_PRINT_L0("Loading blockchain from " << db_folder_path); bool db_opened_okay = false; diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index bc595256..e930628a 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -177,8 +177,8 @@ namespace currency ~blockchain_storage(); - bool init(const boost::program_options::variables_map& vm) { return init(tools::get_default_data_dir(), vm); } - bool init(const std::string& config_folder, const boost::program_options::variables_map& vm); + bool init(const boost::program_options::variables_map& vm, tools::db::db_backend_selector& dbbs) { return init(tools::get_default_data_dir(), vm, dbbs); } + bool init(const std::string& config_folder, const boost::program_options::variables_map& vm, tools::db::db_backend_selector& dbbs); bool deinit(); static void init_options(boost::program_options::options_description& desc); diff --git a/src/currency_core/currency_core.cpp b/src/currency_core/currency_core.cpp index ceb88406..cab606f6 100644 --- a/src/currency_core/currency_core.cpp +++ b/src/currency_core/currency_core.cpp @@ -136,17 +136,17 @@ namespace currency return m_blockchain_storage.get_alternative_blocks_count(); } //----------------------------------------------------------------------------------------------- - bool core::init(const boost::program_options::variables_map& vm) + bool core::init(const boost::program_options::variables_map& vm, tools::db::db_backend_selector& dbbs) { bool r = handle_command_line(vm); uint64_t available_space = 0; CHECK_AND_ASSERT_MES(!check_if_free_space_critically_low(&available_space), false, "free space in data folder is critically low: " << std::fixed << available_space / (1024 * 1024) << " MB"); - r = m_mempool.init(m_config_folder, vm); + r = m_mempool.init(m_config_folder, vm, dbbs); CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); - r = m_blockchain_storage.init(m_config_folder, vm); + r = m_blockchain_storage.init(m_config_folder, vm, dbbs); CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage"); r = m_miner.init(vm); diff --git a/src/currency_core/currency_core.h b/src/currency_core/currency_core.h index faeec262..ec1ae672 100644 --- a/src/currency_core/currency_core.h +++ b/src/currency_core/currency_core.h @@ -20,6 +20,7 @@ #include "currency_core/currency_stat_info.h" #include "warnings.h" #include "crypto/hash.h" +#include "common/db_backend_selector.h" PUSH_VS_WARNINGS DISABLE_VS_WARNINGS(4355) @@ -58,7 +59,7 @@ namespace currency miner& get_miner(){ return m_miner; } static void init_options(boost::program_options::options_description& desc); - bool init(const boost::program_options::variables_map& vm); + bool init(const boost::program_options::variables_map& vm, tools::db::db_backend_selector& dbbs); bool set_genesis_block(const block& b); bool deinit(); uint64_t get_current_blockchain_size() const; diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 43bde8d0..a66b75a3 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -1161,13 +1161,15 @@ namespace currency m_db.commit_transaction(); } //--------------------------------------------------------------------------------- - bool tx_memory_pool::init(const std::string& config_folder, const boost::program_options::variables_map& vm) + bool tx_memory_pool::init(const std::string& config_folder, const boost::program_options::variables_map& vm, tools::db::db_backend_selector& dbbs) { - if (!select_db_engine_from_arg(vm, m_db)) + auto p_backend = dbbs.create_backend(); + if (!p_backend) { - LOG_PRINT_RED_L0("Failed to select db engine"); + LOG_PRINT_RED_L0("Failed to create db engine"); return false; } + m_db.reset_backend(p_backend); LOG_PRINT_L0("DB ENGINE USED BY POOL: " << m_db.get_backend()->name()); m_config_folder = config_folder; diff --git a/src/currency_core/tx_pool.h b/src/currency_core/tx_pool.h index c468f57e..1e2ac504 100644 --- a/src/currency_core/tx_pool.h +++ b/src/currency_core/tx_pool.h @@ -27,6 +27,7 @@ using namespace epee; #include "crypto/hash.h" #include "common/boost_serialization_helper.h" #include "currency_protocol/currency_protocol_handler_common.h" +#include "common/db_backend_selector.h" namespace currency { @@ -116,7 +117,7 @@ namespace currency void clear(); // load/store operations - bool init(const std::string& config_folder, const boost::program_options::variables_map& vm); + bool init(const std::string& config_folder, const boost::program_options::variables_map& vm, tools::db::db_backend_selector& dbbs); bool deinit(); bool fill_block_template(block &bl, bool pos, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, size_t &total_size, uint64_t &fee, uint64_t height, const std::list& explicit_txs); bool get_transactions(std::list& txs) const; diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index f81d1a5a..4f7ec0d2 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -159,7 +159,7 @@ int main(int argc, char* argv[]) currency::miner::init_options(desc_cmd_sett); bc_services::bc_offers_service::init_options(desc_cmd_sett); currency::stratum_server::init_options(desc_cmd_sett); - + tools::db::db_backend_selector::init_options(desc_cmd_sett); po::options_description desc_options("Allowed options"); desc_options.add(desc_cmd_only).add(desc_cmd_sett); @@ -240,6 +240,8 @@ int main(int argc, char* argv[]) command_line::get_arg(vm, command_line::arg_disable_stop_on_low_free_space)); ccore.set_critical_error_handler(&cceh); + tools::db::db_backend_selector dbbs; + if (command_line::get_arg(vm, command_line::arg_enable_offers_service)) { @@ -270,8 +272,10 @@ int main(int argc, char* argv[]) LOG_PRINT_L0(generate_reference << ENDL << "----------------------------------------" << ENDL << json_rpc_reference); } - bool res = false; + res = dbbs.init(vm); + CHECK_AND_ASSERT_MES(res, EXIT_FAILURE, "db_backend_selector failed to initialize"); + //initialize objects LOG_PRINT_L0("Initializing p2p server..."); res = p2psrv.init(vm); @@ -298,7 +302,7 @@ int main(int argc, char* argv[]) //initialize core here LOG_PRINT_L0("Initializing core..."); - res = ccore.init(vm); + res = ccore.init(vm, dbbs); CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize core"); LOG_PRINT_L0("Core initialized OK"); diff --git a/src/wallet/wallets_manager.cpp b/src/wallet/wallets_manager.cpp index 2aedec2e..780ea0f2 100644 --- a/src/wallet/wallets_manager.cpp +++ b/src/wallet/wallets_manager.cpp @@ -149,6 +149,7 @@ bool wallets_manager::init(int argc, char* argv[], view::i_view* pview_handler) nodetool::node_server >::init_options(desc_cmd_sett); currency::miner::init_options(desc_cmd_sett); bc_services::bc_offers_service::init_options(desc_cmd_sett); + tools::db::db_backend_selector::init_options(desc_cmd_sett); #endif po::options_description desc_options("Allowed options"); @@ -312,12 +313,15 @@ bool wallets_manager::init_local_daemon() dsi.daemon_network_state = currency::COMMAND_RPC_GET_INFO::daemon_network_state_loading_core; m_pview->update_daemon_status(dsi); + tools::db::db_backend_selector dbbs; + bool res = dbbs.init(m_vm); + CHECK_AND_ASSERT_AND_SET_GUI(res, "Failed to initialize db_backend_selector"); //initialize core here LOG_PRINT_L0("Initializing core..."); //dsi.text_state = "Initializing core"; m_pview->update_daemon_status(dsi); - bool res = m_ccore.init(m_vm); + res = m_ccore.init(m_vm, dbbs); CHECK_AND_ASSERT_AND_SET_GUI(res, "Failed to initialize core"); LOG_PRINT_L0("Core initialized OK");