From 5180afa39dfd7bfa8597fffb4b7b759163a13613 Mon Sep 17 00:00:00 2001 From: Wesley Shillingford Date: Sun, 1 Sep 2019 10:45:44 +0100 Subject: [PATCH] Add RocksDB config option to conditionally enable (#2266) --- nano/core_test/block_store.cpp | 32 +++++++++++++++++++++++++++ nano/core_test/core_test_main.cc | 4 ++++ nano/core_test/toml.cpp | 9 ++++++++ nano/lib/CMakeLists.txt | 2 ++ nano/lib/rocksdbconfig.cpp | 14 ++++++++++++ nano/lib/rocksdbconfig.hpp | 18 ++++++++++++++++ nano/lib/walletconfig.cpp | 3 ++- nano/lib/walletconfig.hpp | 4 +--- nano/nano_node/daemon.cpp | 4 +++- nano/node/node.cpp | 37 +++++++++++++++++++++++++++----- nano/node/nodeconfig.cpp | 11 ++++++++++ nano/node/nodeconfig.hpp | 3 +++ nano/secure/blockstore.hpp | 2 +- 13 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 nano/lib/rocksdbconfig.cpp create mode 100644 nano/lib/rocksdbconfig.hpp diff --git a/nano/core_test/block_store.cpp b/nano/core_test/block_store.cpp index e0682d0c..b6b143de 100644 --- a/nano/core_test/block_store.cpp +++ b/nano/core_test/block_store.cpp @@ -5,10 +5,16 @@ #include #include +#if NANO_ROCKSDB +#include +#endif + #include #include +#include + namespace { void modify_account_info_to_v13 (nano::mdb_store & store, nano::transaction const & transaction_a, nano::account const & account_a); @@ -1840,6 +1846,32 @@ TEST (block_store, reset_renew_existing_transaction) ASSERT_NE (nullptr, block_existing); } +TEST (block_store, rocksdb_force_test_env_variable) +{ + nano::logger_mt logger; + + // Set environment variable + constexpr auto env_var = "TEST_USE_ROCKSDB"; + auto value = std::getenv (env_var); + + auto store = nano::make_store (logger, nano::unique_path ()); + + auto mdb_cast = dynamic_cast (store.get ()); + +#if NANO_ROCKSDB + if (value && boost::lexical_cast (value) == 1) + { + ASSERT_NE (boost::polymorphic_downcast (store.get ()), nullptr); + } + else + { + ASSERT_NE (mdb_cast, nullptr); + } +#else + ASSERT_NE (mdb_cast, nullptr); +#endif +} + namespace { // These functions take the latest account_info and create a legacy one so that upgrade tests can be emulated more easily. diff --git a/nano/core_test/core_test_main.cc b/nano/core_test/core_test_main.cc index 4de016a3..d9c606b4 100644 --- a/nano/core_test/core_test_main.cc +++ b/nano/core_test/core_test_main.cc @@ -1,6 +1,7 @@ #include "gtest/gtest.h" #include +#include namespace nano { @@ -13,6 +14,9 @@ GTEST_API_ int main (int argc, char ** argv) printf ("Running main() from core_test_main.cc\n"); nano::force_nano_test_network (); nano::node_singleton_memory_pool_purge_guard memory_pool_cleanup_guard; + // Setting up logging so that there aren't any piped to standard output. + nano::logging logging; + logging.init (nano::unique_path ()); testing::InitGoogleTest (&argc, argv); auto res = RUN_ALL_TESTS (); nano::cleanup_test_directories_on_exit (); diff --git a/nano/core_test/toml.cpp b/nano/core_test/toml.cpp index f8f72b2a..cee64e67 100644 --- a/nano/core_test/toml.cpp +++ b/nano/core_test/toml.cpp @@ -120,6 +120,7 @@ TEST (toml, daemon_config_deserialize_defaults) [node.statistics.log] [node.statistics.sampling] [node.websocket] + [node.rocksdb] [opencl] [rpc] [rpc.child_process] @@ -235,6 +236,8 @@ TEST (toml, daemon_config_deserialize_defaults) ASSERT_EQ (conf.node.stat_config.log_headers, defaults.node.stat_config.log_headers); ASSERT_EQ (conf.node.stat_config.log_counters_filename, defaults.node.stat_config.log_counters_filename); ASSERT_EQ (conf.node.stat_config.log_samples_filename, defaults.node.stat_config.log_samples_filename); + + ASSERT_EQ (conf.node.rocksdb_config.enable, defaults.node.rocksdb_config.enable); } TEST (toml, optional_child) @@ -466,6 +469,9 @@ TEST (toml, daemon_config_deserialize_no_defaults) enable = true port = 999 + [node.rocksdb] + enable = true + [opencl] device = 999 enable = true @@ -592,6 +598,8 @@ TEST (toml, daemon_config_deserialize_no_defaults) ASSERT_NE (conf.node.stat_config.log_headers, defaults.node.stat_config.log_headers); ASSERT_NE (conf.node.stat_config.log_counters_filename, defaults.node.stat_config.log_counters_filename); ASSERT_NE (conf.node.stat_config.log_samples_filename, defaults.node.stat_config.log_samples_filename); + + ASSERT_NE (conf.node.rocksdb_config.enable, defaults.node.rocksdb_config.enable); } /** There should be no required values **/ @@ -610,6 +618,7 @@ TEST (toml, daemon_config_no_required) [node.statistics.log] [node.statistics.sampling] [node.websocket] + [node.rocksdb] [opencl] [rpc] [rpc.child_process] diff --git a/nano/lib/CMakeLists.txt b/nano/lib/CMakeLists.txt index 5e008f8b..114b9e09 100644 --- a/nano/lib/CMakeLists.txt +++ b/nano/lib/CMakeLists.txt @@ -40,6 +40,8 @@ add_library (nano_lib numbers.cpp rep_weights.hpp rep_weights.cpp + rocksdbconfig.hpp + rocksdbconfig.cpp rpc_handler_interface.hpp rpcconfig.hpp rpcconfig.cpp diff --git a/nano/lib/rocksdbconfig.cpp b/nano/lib/rocksdbconfig.cpp new file mode 100644 index 00000000..34955cd9 --- /dev/null +++ b/nano/lib/rocksdbconfig.cpp @@ -0,0 +1,14 @@ +#include +#include + +nano::error nano::rocksdb_config::serialize_toml (nano::tomlconfig & toml) const +{ + toml.put ("enable", enable, "Whether to use the RocksDB backend for the ledger database\ntype:bool"); + return toml.get_error (); +} + +nano::error nano::rocksdb_config::deserialize_toml (nano::tomlconfig & toml) +{ + toml.get_optional ("enable", enable); + return toml.get_error (); +} diff --git a/nano/lib/rocksdbconfig.hpp b/nano/lib/rocksdbconfig.hpp new file mode 100644 index 00000000..a02ff749 --- /dev/null +++ b/nano/lib/rocksdbconfig.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace nano +{ +class tomlconfig; + +/** Configuration options for RocksDB */ +class rocksdb_config final +{ +public: + nano::error serialize_toml (nano::tomlconfig & toml_a) const; + nano::error deserialize_toml (nano::tomlconfig & toml_a); + + bool enable{ false }; +}; +} diff --git a/nano/lib/walletconfig.cpp b/nano/lib/walletconfig.cpp index b1c24697..e3f91a64 100644 --- a/nano/lib/walletconfig.cpp +++ b/nano/lib/walletconfig.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -7,7 +8,7 @@ nano::wallet_config::wallet_config () assert (!wallet.is_zero ()); } -nano::error nano::wallet_config::parse (std::string wallet_a, std::string account_a) +nano::error nano::wallet_config::parse (std::string const & wallet_a, std::string const & account_a) { nano::error error; if (wallet.decode_hex (wallet_a)) diff --git a/nano/lib/walletconfig.hpp b/nano/lib/walletconfig.hpp index f191d186..267e261b 100644 --- a/nano/lib/walletconfig.hpp +++ b/nano/lib/walletconfig.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include @@ -8,7 +7,6 @@ namespace nano { -class jsonconfig; class tomlconfig; /** Configuration options for the Qt wallet */ @@ -17,7 +15,7 @@ class wallet_config final public: wallet_config (); /** Update this instance by parsing the given wallet and account */ - nano::error parse (std::string wallet_a, std::string account_a); + nano::error parse (std::string const & wallet_a, std::string const & account_a); nano::error serialize_toml (nano::tomlconfig & toml_a) const; nano::error deserialize_toml (nano::tomlconfig & toml_a); nano::uint256_union wallet; diff --git a/nano/nano_node/daemon.cpp b/nano/nano_node/daemon.cpp index 6f81f19a..1f9eb5cc 100644 --- a/nano/nano_node/daemon.cpp +++ b/nano/nano_node/daemon.cpp @@ -59,10 +59,12 @@ void nano_daemon::daemon::run (boost::filesystem::path const & data_path, nano:: auto node (std::make_shared (io_ctx, data_path, alarm, config.node, opencl_work, flags)); if (!node->init_error ()) { + auto database_backend = dynamic_cast (node->store_impl.get ()) ? "LMDB" : "RocksDB"; auto network_label = node->network_params.network.get_current_network_as_string (); std::cout << "Network: " << network_label << ", version: " << NANO_VERSION_STRING << "\n" << "Path: " << node->application_path.string () << "\n" - << "Build Info: " << BUILD_INFO << std::endl; + << "Build Info: " << BUILD_INFO << "\n" + << "Database backend: " << database_backend << std::endl; node->start (); nano::ipc::ipc_server ipc_server (*node, config.rpc); diff --git a/nano/node/node.cpp b/nano/node/node.cpp index 2997511b..3fb0ac97 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -123,7 +123,7 @@ alarm (alarm_a), work (work_a), distributed_work (*this), logger (config_a.logging.min_time_between_log_output), -store_impl (nano::make_store (logger, application_path_a, flags.read_only, true, config_a.diagnostics_config.txn_tracking, config_a.block_processor_batch_max_time, config_a.lmdb_max_dbs, flags.sideband_batch_size, config_a.backup_before_upgrade)), +store_impl (nano::make_store (logger, application_path_a, flags.read_only, true, config_a.diagnostics_config.txn_tracking, config_a.block_processor_batch_max_time, config_a.lmdb_max_dbs, flags.sideband_batch_size, config_a.backup_before_upgrade, config_a.rocksdb_config.enable)), store (*store_impl), wallets_store_impl (std::make_unique (application_path_a / "wallets.ldb", config_a.lmdb_max_dbs)), wallets_store (*wallets_store_impl), @@ -1350,11 +1350,38 @@ nano::node_flags const & nano::inactive_node_flag_defaults () return node_flags; } -std::unique_ptr nano::make_store (nano::logger_mt & logger, boost::filesystem::path const & path, bool read_only, bool add_db_postfix, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, int lmdb_max_dbs, size_t batch_size, bool backup_before_upgrade) +std::unique_ptr nano::make_store (nano::logger_mt & logger, boost::filesystem::path const & path, bool read_only, bool add_db_postfix, nano::txn_tracking_config const & txn_tracking_config_a, std::chrono::milliseconds block_processor_batch_max_time_a, int lmdb_max_dbs, size_t batch_size, bool backup_before_upgrade, bool use_rocksdb_backend) { #if NANO_ROCKSDB - return std::make_unique (logger, add_db_postfix ? path / "rocksdb" : path, read_only); -#else - return std::make_unique (logger, add_db_postfix ? path / "data.ldb" : path, txn_tracking_config_a, block_processor_batch_max_time_a, lmdb_max_dbs, batch_size, backup_before_upgrade); + auto make_rocksdb = [&logger, add_db_postfix, &path, read_only]() { + return std::make_unique (logger, add_db_postfix ? path / "rocksdb" : path, read_only); + }; #endif + + if (use_rocksdb_backend) + { +#if NANO_ROCKSDB + return make_rocksdb (); +#else + // Can only use the rocksdb_store if the node has been build with rocksdb support + release_assert (false); + return nullptr; +#endif + } + else + { +#if NANO_ROCKSDB + /** To use RocksDB in tests make sure the node is built with the cmake variable -DNANO_ROCKSDB=ON and the environment variable TEST_USE_ROCKSDB=1 is set */ + static nano::network_constants network_constants; + if (auto use_rocksdb_str = std::getenv ("TEST_USE_ROCKSDB") && network_constants.is_test_network ()) + { + if (boost::lexical_cast (use_rocksdb_str) == 1) + { + return make_rocksdb (); + } + } +#endif + } + + return std::make_unique (logger, add_db_postfix ? path / "data.ldb" : path, txn_tracking_config_a, block_processor_batch_max_time_a, lmdb_max_dbs, batch_size, backup_before_upgrade); } diff --git a/nano/node/nodeconfig.cpp b/nano/node/nodeconfig.cpp index 76103947..dfd51976 100644 --- a/nano/node/nodeconfig.cpp +++ b/nano/node/nodeconfig.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -144,6 +145,10 @@ nano::error nano::node_config::serialize_toml (nano::tomlconfig & toml) const stat_config.serialize_toml (stat_l); toml.put_child ("statistics", stat_l); + nano::tomlconfig rocksdb_l; + rocksdb_config.serialize_toml (rocksdb_l); + toml.put_child ("rocksdb", rocksdb_l); + return toml.get_error (); } @@ -189,6 +194,12 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml) stat_config.deserialize_toml (stat_config_l); } + if (toml.has_key ("rocksdb")) + { + auto rocksdb_config_l (toml.get_required_child ("rocksdb")); + rocksdb_config.deserialize_toml (rocksdb_config_l); + } + if (toml.has_key ("work_peers")) { work_peers.clear (); diff --git a/nano/node/nodeconfig.hpp b/nano/node/nodeconfig.hpp index 6a82337e..5195a635 100644 --- a/nano/node/nodeconfig.hpp +++ b/nano/node/nodeconfig.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -93,6 +94,8 @@ public: std::chrono::seconds work_watcher_period{ std::chrono::seconds (5) }; double max_work_generate_multiplier{ 64. }; uint64_t max_work_generate_difficulty{ nano::network_constants::publish_full_threshold }; + nano::rocksdb_config rocksdb_config; + nano::frontiers_confirmation_mode frontiers_confirmation{ nano::frontiers_confirmation_mode::automatic }; std::string serialize_frontiers_confirmation (nano::frontiers_confirmation_mode) const; nano::frontiers_confirmation_mode deserialize_frontiers_confirmation (std::string const &); diff --git a/nano/secure/blockstore.hpp b/nano/secure/blockstore.hpp index f6d269ae..edeb3901 100644 --- a/nano/secure/blockstore.hpp +++ b/nano/secure/blockstore.hpp @@ -695,7 +695,7 @@ public: virtual nano::read_transaction tx_begin_read () = 0; }; -std::unique_ptr make_store (nano::logger_mt & logger, boost::filesystem::path const & path, bool open_read_only = false, bool add_db_postfix = false, nano::txn_tracking_config const & txn_tracking_config_a = nano::txn_tracking_config{}, std::chrono::milliseconds block_processor_batch_max_time_a = std::chrono::milliseconds (5000), int lmdb_max_dbs = 128, size_t batch_size = 512, bool backup_before_upgrade = false); +std::unique_ptr make_store (nano::logger_mt & logger, boost::filesystem::path const & path, bool open_read_only = false, bool add_db_postfix = false, nano::txn_tracking_config const & txn_tracking_config_a = nano::txn_tracking_config{}, std::chrono::milliseconds block_processor_batch_max_time_a = std::chrono::milliseconds (5000), int lmdb_max_dbs = 128, size_t batch_size = 512, bool backup_before_upgrade = false, bool rocksdb_backend = false); } namespace std