diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index a6774a25c..01a59e079 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -33,6 +33,19 @@ #include "profile_tools.h" #include "ringct/rctOps.h" +#include "lmdb/db_lmdb.h" +#ifdef BERKELEY_DB +#include "berkeleydb/db_bdb.h" +#endif + +static const char *db_types[] = { + "lmdb", +#ifdef BERKELEY_DB + "berkeley", +#endif + NULL +}; + #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "blockchain.db" @@ -41,6 +54,41 @@ using epee::string_tools::pod_to_hex; namespace cryptonote { +bool blockchain_valid_db_type(const std::string& db_type) +{ + int i; + for (i=0; db_types[i]; i++) + { + if (db_types[i] == db_type) + return true; + } + return false; +} + +std::string blockchain_db_types(const std::string& sep) +{ + int i; + std::string ret = ""; + for (i=0; db_types[i]; i++) + { + if (i) + ret += sep; + ret += db_types[i]; + } + return ret; +} + +BlockchainDB *new_db(const std::string& db_type) +{ + if (db_type == "lmdb") + return new BlockchainLMDB(); +#if defined(BERKELEY_DB) + if (db_type == "berkeley") + return new BlockchainBDB(); +#endif + return NULL; +} + void BlockchainDB::pop_block() { block blk; diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 27e63801d..3efb8c3c3 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -145,6 +145,12 @@ struct txpool_tx_meta_t uint8_t padding[77]; // till 192 bytes }; +#define DBF_SAFE 1 +#define DBF_FAST 2 +#define DBF_FASTEST 4 +#define DBF_RDONLY 8 +#define DBF_SALVAGE 0x10 + /*********************************** * Exception Definitions ***********************************/ @@ -1491,6 +1497,7 @@ public: }; // class BlockchainDB +BlockchainDB *new_db(const std::string& db_type); } // namespace cryptonote diff --git a/src/blockchain_db/db_types.h b/src/blockchain_db/db_types.h index 6c21b029e..8e2f58a61 100644 --- a/src/blockchain_db/db_types.h +++ b/src/blockchain_db/db_types.h @@ -31,9 +31,6 @@ namespace cryptonote { - - const std::unordered_set blockchain_db_types = - { "lmdb" - }; - + bool blockchain_valid_db_type(const std::string& db_type); + std::string blockchain_db_types(const std::string& sep); } // namespace cryptonote diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 4441c7578..a756c04c6 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1083,9 +1083,10 @@ BlockchainLMDB::BlockchainLMDB(bool batch_transactions) m_hardfork = nullptr; } -void BlockchainLMDB::open(const std::string& filename, const int mdb_flags) +void BlockchainLMDB::open(const std::string& filename, const int db_flags) { int result; + int mdb_flags = MDB_NORDAHEAD; LOG_PRINT_L3("BlockchainLMDB::" << __func__); @@ -1124,6 +1125,15 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags) size_t mapsize = DEFAULT_MAPSIZE; + if (db_flags & DBF_FAST) + mdb_flags |= MDB_NOSYNC; + if (db_flags & DBF_FASTEST) + mdb_flags |= MDB_NOSYNC | MDB_WRITEMAP | MDB_MAPASYNC; + if (db_flags & DBF_RDONLY) + mdb_flags = MDB_RDONLY; + if (db_flags & DBF_SALVAGE) + mdb_flags |= MDB_PREVSNAPSHOT; + if (auto result = mdb_env_open(m_env, filename.c_str(), mdb_flags, 0644)) throw0(DB_ERROR(lmdb_error("Failed to open lmdb environment: ", result).c_str())); diff --git a/src/blockchain_utilities/blockchain_export.cpp b/src/blockchain_utilities/blockchain_export.cpp index f145bc107..20eca09f2 100644 --- a/src/blockchain_utilities/blockchain_export.cpp +++ b/src/blockchain_utilities/blockchain_export.cpp @@ -31,10 +31,6 @@ #include "common/command_line.h" #include "cryptonote_core/tx_pool.h" #include "blockchain_db/blockchain_db.h" -#include "blockchain_db/lmdb/db_lmdb.h" -#if defined(BERKELEY_DB) -#include "blockchain_db/berkeleydb/db_bdb.h" -#endif #include "blockchain_db/db_types.h" #include "version.h" @@ -44,17 +40,6 @@ namespace po = boost::program_options; using namespace epee; -std::string join_set_strings(const std::unordered_set& db_types_all, const char* delim) -{ - std::string result; - std::ostringstream s; - std::copy(db_types_all.begin(), db_types_all.end(), std::ostream_iterator(s, delim)); - result = s.str(); - if (result.length() > 0) - result.erase(result.end()-strlen(delim), result.end()); - return result; -} - int main(int argc, char* argv[]) { TRY_ENTRY(); @@ -63,10 +48,7 @@ int main(int argc, char* argv[]) std::string default_db_type = "lmdb"; - std::unordered_set db_types_all = cryptonote::blockchain_db_types; - db_types_all.insert("memory"); - - std::string available_dbs = join_set_strings(db_types_all, ", "); + std::string available_dbs = cryptonote::blockchain_db_types(", "); available_dbs = "available: " + available_dbs; uint32_t log_level = 0; @@ -144,18 +126,11 @@ int main(int argc, char* argv[]) m_config_folder = command_line::get_arg(vm, data_dir_arg); std::string db_type = command_line::get_arg(vm, arg_database); - if (db_types_all.count(db_type) == 0) + if (!cryptonote::blockchain_valid_db_type(db_type)) { std::cerr << "Invalid database type: " << db_type << std::endl; return 1; } -#if !defined(BERKELEY_DB) - if (db_type == "berkeley") - { - LOG_ERROR("BerkeleyDB support disabled."); - return false; - } -#endif if (command_line::has_arg(vm, arg_output_file)) output_file_path = boost::filesystem::path(command_line::get_arg(vm, arg_output_file)); @@ -179,19 +154,8 @@ int main(int argc, char* argv[]) tx_memory_pool m_mempool(*core_storage); core_storage = new Blockchain(m_mempool); - int db_flags = 0; - - BlockchainDB* db = nullptr; - if (db_type == "lmdb") - { - db_flags |= MDB_RDONLY; - db = new BlockchainLMDB(); - } -#if defined(BERKELEY_DB) - else if (db_type == "berkeley") - db = new BlockchainBDB(); -#endif - else + BlockchainDB* db = new_db(db_type); + if (db == NULL) { LOG_ERROR("Attempted to use non-existent database type: " << db_type); throw std::runtime_error("Attempting to use non-existent database type"); @@ -205,7 +169,7 @@ int main(int argc, char* argv[]) LOG_PRINT_L0("Loading blockchain from folder " << filename << " ..."); try { - db->open(filename, db_flags); + db->open(filename, DBF_RDONLY); } catch (const std::exception& e) { diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 6f908c799..ded854ca4 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -42,8 +42,6 @@ #include "blockchain_db/db_types.h" #include "cryptonote_core/cryptonote_core.h" -#include // for db flag arguments - #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "bcutil" @@ -78,40 +76,16 @@ namespace po = boost::program_options; using namespace cryptonote; using namespace epee; - -std::string join_set_strings(const std::unordered_set& db_types_all, const char* delim) -{ - std::string result; - std::ostringstream s; - std::copy(db_types_all.begin(), db_types_all.end(), std::ostream_iterator(s, delim)); - result = s.str(); - if (result.length() > 0) - result.erase(result.end()-strlen(delim), result.end()); - return result; -} - -// db_type: lmdb, berkeley // db_mode: safe, fast, fastest -int get_db_flags_from_mode(const std::string& db_type, const std::string& db_mode) +int get_db_flags_from_mode(const std::string& db_mode) { - uint64_t BDB_FAST_MODE = 0; - uint64_t BDB_FASTEST_MODE = 0; - uint64_t BDB_SAFE_MODE = 0; - -#if defined(BERKELEY_DB) - BDB_FAST_MODE = DB_TXN_WRITE_NOSYNC; - BDB_FASTEST_MODE = DB_TXN_NOSYNC; - BDB_SAFE_MODE = DB_TXN_SYNC; -#endif - int db_flags = 0; - bool islmdb = db_type == "lmdb"; if (db_mode == "safe") - db_flags = islmdb ? MDB_NORDAHEAD : BDB_SAFE_MODE; + db_flags = DBF_SAFE; else if (db_mode == "fast") - db_flags = islmdb ? MDB_NOMETASYNC | MDB_NOSYNC | MDB_NORDAHEAD : BDB_FAST_MODE; + db_flags = DBF_FAST; else if (db_mode == "fastest") - db_flags = islmdb ? MDB_WRITEMAP | MDB_MAPASYNC | MDB_NORDAHEAD | MDB_NOMETASYNC | MDB_NOSYNC : BDB_FASTEST_MODE; + db_flags = DBF_FASTEST; return db_flags; } @@ -132,14 +106,6 @@ int parse_db_arguments(const std::string& db_arg_str, std::string& db_type, int& return 1; } -#if !defined(BERKELEY_DB) - if (db_type == "berkeley") - { - MFATAL("BerkeleyDB support disabled."); - return false; - } -#endif - std::string db_arg_str2 = db_args[1]; boost::split(db_args, db_arg_str2, boost::is_any_of(",")); @@ -155,51 +121,7 @@ int parse_db_arguments(const std::string& db_arg_str, std::string& db_type, int& } if (! db_mode.empty()) { - db_flags = get_db_flags_from_mode(db_type, db_mode); - } - else - { - for (auto& it : db_args) - { - boost::algorithm::trim(it); - if (it.empty()) - continue; - if (db_type == "lmdb") - { - MINFO("LMDB flag: " << it); - if (it == "nosync") - db_flags |= MDB_NOSYNC; - else if (it == "nometasync") - db_flags |= MDB_NOMETASYNC; - else if (it == "writemap") - db_flags |= MDB_WRITEMAP; - else if (it == "mapasync") - db_flags |= MDB_MAPASYNC; - else if (it == "nordahead") - db_flags |= MDB_NORDAHEAD; - else - { - std::cerr << "unrecognized database flag: " << it << ENDL; - return 1; - } - } -#if defined(BERKELEY_DB) - else if (db_type == "berkeley") - { - if (it == "txn_write_nosync") - db_flags = DB_TXN_WRITE_NOSYNC; - else if (it == "txn_nosync") - db_flags = DB_TXN_NOSYNC; - else if (it == "txn_sync") - db_flags = DB_TXN_SYNC; - else - { - std::cerr << "unrecognized database flag: " << it << ENDL; - return 1; - } - } -#endif - } + db_flags = get_db_flags_from_mode(db_mode); } return 0; } @@ -580,12 +502,8 @@ int main(int argc, char* argv[]) epee::string_tools::set_module_name_and_folder(argv[0]); std::string default_db_type = "lmdb"; - std::string default_db_engine_compiled = "blockchain_db"; - std::unordered_set db_types_all = cryptonote::blockchain_db_types; - db_types_all.insert("memory"); - - std::string available_dbs = join_set_strings(db_types_all, ", "); + std::string available_dbs = cryptonote::blockchain_db_types(", "); available_dbs = "available: " + available_dbs; uint32_t log_level = 0; @@ -731,7 +649,6 @@ int main(int argc, char* argv[]) std::string db_type; - std::string db_engine_compiled; int db_flags = 0; int res = 0; res = parse_db_arguments(db_arg_str, db_type, db_flags); @@ -741,25 +658,12 @@ int main(int argc, char* argv[]) return 1; } - if (db_types_all.count(db_type) == 0) + if (!cryptonote::blockchain_valid_db_type(db_type)) { std::cerr << "Invalid database type: " << db_type << std::endl; return 1; } - if ((db_type == "lmdb") -#if defined(BERKELEY_DB) - || (db_type == "berkeley") -#endif - ) - { - db_engine_compiled = "blockchain_db"; - } - else - { - db_engine_compiled = "memory"; - } - MINFO("database: " << db_type); MINFO("database flags: " << db_flags); MINFO("verify: " << std::boolalpha << opt_verify << std::noboolalpha); @@ -788,16 +692,6 @@ int main(int argc, char* argv[]) // properties to do so. Both ways work, but fake core isn't necessary in that // circumstance. - if (db_type != "lmdb" -#if defined(BERKELEY_DB) - && db_type != "berkeley" -#endif - ) - { - std::cerr << "database type unrecognized" << ENDL; - return 1; - } - cryptonote::cryptonote_protocol_stub pr; //TODO: stub only for this kind of test, make real validation of relayed objects cryptonote::core core(&pr); core.disable_dns_checkpoints(true); diff --git a/src/blockchain_utilities/blocksdat_file.h b/src/blockchain_utilities/blocksdat_file.h index 4e9d8173b..0a5913058 100644 --- a/src/blockchain_utilities/blocksdat_file.h +++ b/src/blockchain_utilities/blocksdat_file.h @@ -38,7 +38,6 @@ #include "cryptonote_basic/cryptonote_boost_serialization.h" #include "cryptonote_core/blockchain.h" #include "blockchain_db/blockchain_db.h" -#include "blockchain_db/lmdb/db_lmdb.h" #include #include diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index 925d8ff3b..ad66b2009 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -96,7 +96,7 @@ namespace command_line , "checkpoints from DNS server will be enforced" , false }; - std::string arg_db_type_description = "Specify database type, available: " + boost::algorithm::join(cryptonote::blockchain_db_types, ", "); + std::string arg_db_type_description = "Specify database type, available: " + cryptonote::blockchain_db_types(", "); const command_line::arg_descriptor arg_db_type = { "db-type" , arg_db_type_description.c_str() diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 98569b46b..a7f6ca36c 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -48,10 +48,6 @@ using namespace epee; #include "cryptonote_basic/checkpoints.h" #include "ringct/rctTypes.h" #include "blockchain_db/blockchain_db.h" -#include "blockchain_db/lmdb/db_lmdb.h" -#if defined(BERKELEY_DB) -#include "blockchain_db/berkeleydb/db_bdb.h" -#endif #include "ringct/rctSigs.h" #undef MONERO_DEFAULT_LOG_CATEGORY @@ -314,20 +310,8 @@ namespace cryptonote // folder might not be a directory, etc, etc catch (...) { } - BlockchainDB* db = nullptr; - uint64_t DBS_FAST_MODE = 0; - uint64_t DBS_FASTEST_MODE = 0; - uint64_t DBS_SAFE_MODE = 0; - uint64_t DBS_SALVAGE = 0; - if (db_type == "lmdb") - { - db = new BlockchainLMDB(); - DBS_SAFE_MODE = MDB_NORDAHEAD; - DBS_FAST_MODE = MDB_NORDAHEAD | MDB_NOSYNC; - DBS_FASTEST_MODE = MDB_NORDAHEAD | MDB_NOSYNC | MDB_WRITEMAP | MDB_MAPASYNC; - DBS_SALVAGE = MDB_PREVSNAPSHOT; - } - else + BlockchainDB* db = new_db(db_type); + if (db == NULL) { LOG_ERROR("Attempted to use non-existent database type"); return false; @@ -353,7 +337,7 @@ namespace cryptonote MDEBUG("option: " << option); // default to fast:async:1 - uint64_t DEFAULT_FLAGS = DBS_FAST_MODE; + uint64_t DEFAULT_FLAGS = DBF_FAST; if(options.size() == 0) { @@ -367,14 +351,14 @@ namespace cryptonote if(options[0] == "safe") { safemode = true; - db_flags = DBS_SAFE_MODE; + db_flags = DBF_SAFE; sync_mode = db_nosync; } else if(options[0] == "fast") - db_flags = DBS_FAST_MODE; + db_flags = DBF_FAST; else if(options[0] == "fastest") { - db_flags = DBS_FASTEST_MODE; + db_flags = DBF_FASTEST; blocks_per_sync = 1000; // default to fastest:async:1000 } else @@ -398,7 +382,7 @@ namespace cryptonote } if (db_salvage) - db_flags |= DBS_SALVAGE; + db_flags |= DBF_SALVAGE; db->open(filename, db_flags); if(!db->m_open) diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index 19dd02171..456eeee64 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -145,13 +145,10 @@ int main(int argc, char const * argv[]) std::string db_type = command_line::get_arg(vm, command_line::arg_db_type); // verify that blockchaindb type is valid - if(cryptonote::blockchain_db_types.count(db_type) == 0) + if(!cryptonote::blockchain_valid_db_type(db_type)) { - std::cout << "Invalid database type (" << db_type << "), available types are:" << std::endl; - for (const auto& type : cryptonote::blockchain_db_types) - { - std::cout << "\t" << type << std::endl; - } + std::cout << "Invalid database type (" << db_type << "), available types are: " << + cryptonote::blockchain_db_types(", ") << std::endl; return 0; } diff --git a/src/debug_utilities/CMakeLists.txt b/src/debug_utilities/CMakeLists.txt index 99198dc57..e6d49fd61 100644 --- a/src/debug_utilities/CMakeLists.txt +++ b/src/debug_utilities/CMakeLists.txt @@ -37,6 +37,7 @@ monero_add_executable(cn_deserialize target_link_libraries(cn_deserialize LINK_PRIVATE cryptonote_core + common blockchain_db p2p epee diff --git a/tests/core_proxy/CMakeLists.txt b/tests/core_proxy/CMakeLists.txt index d22fecc9c..680e34911 100644 --- a/tests/core_proxy/CMakeLists.txt +++ b/tests/core_proxy/CMakeLists.txt @@ -39,6 +39,8 @@ target_link_libraries(core_proxy PRIVATE cryptonote_core cryptonote_protocol + common + blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt index 853d46a12..cb77f8f56 100644 --- a/tests/fuzz/CMakeLists.txt +++ b/tests/fuzz/CMakeLists.txt @@ -30,6 +30,8 @@ add_executable(block_fuzz_tests block.cpp fuzzer.cpp) target_link_libraries(block_fuzz_tests PRIVATE cryptonote_core + common + blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} @@ -42,6 +44,8 @@ add_executable(transaction_fuzz_tests transaction.cpp fuzzer.cpp) target_link_libraries(transaction_fuzz_tests PRIVATE cryptonote_core + common + blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} @@ -55,6 +59,8 @@ target_link_libraries(signature_fuzz_tests PRIVATE wallet cryptonote_core + common + blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} @@ -68,6 +74,8 @@ target_link_libraries(cold-outputs_fuzz_tests PRIVATE wallet cryptonote_core + common + blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} @@ -81,6 +89,8 @@ target_link_libraries(cold-transaction_fuzz_tests PRIVATE wallet cryptonote_core + common + blockchain_db p2p epee ${CMAKE_THREAD_LIBS_INIT} diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index febf8b2f7..598b3b7b2 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -31,7 +31,7 @@ #include #include "gtest/gtest.h" -#include "blockchain_db/lmdb/db_lmdb.h" +#include "blockchain_db/blockchain_db.h" #include "cryptonote_basic/cryptonote_format_utils.h" #include "cryptonote_basic/hardfork.h"