diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/node/coins_view_args.cpp | 16 | ||||
-rw-r--r-- | src/node/coins_view_args.h | 15 | ||||
-rw-r--r-- | src/test/coins_tests.cpp | 4 | ||||
-rw-r--r-- | src/txdb.cpp | 34 | ||||
-rw-r--r-- | src/txdb.h | 18 | ||||
-rw-r--r-- | src/validation.cpp | 21 | ||||
-rw-r--r-- | src/validation.h | 2 |
8 files changed, 72 insertions, 40 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 6d5f2eebd3..7b9ffe427d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -204,6 +204,7 @@ BITCOIN_CORE_H = \ node/chainstate.h \ node/chainstatemanager_args.h \ node/coin.h \ + node/coins_view_args.h \ node/connection_types.h \ node/context.h \ node/database_args.h \ @@ -389,6 +390,7 @@ libbitcoin_node_a_SOURCES = \ node/chainstate.cpp \ node/chainstatemanager_args.cpp \ node/coin.cpp \ + node/coins_view_args.cpp \ node/connection_types.cpp \ node/context.cpp \ node/database_args.cpp \ diff --git a/src/node/coins_view_args.cpp b/src/node/coins_view_args.cpp new file mode 100644 index 0000000000..67c9b8dbac --- /dev/null +++ b/src/node/coins_view_args.cpp @@ -0,0 +1,16 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <node/coins_view_args.h> + +#include <txdb.h> +#include <util/system.h> + +namespace node { +void ReadCoinsViewArgs(const ArgsManager& args, CoinsViewOptions& options) +{ + if (auto value = args.GetIntArg("-dbbatchsize")) options.batch_write_bytes = *value; + if (auto value = args.GetIntArg("-dbcrashratio")) options.simulate_crash_ratio = *value; +} +} // namespace node diff --git a/src/node/coins_view_args.h b/src/node/coins_view_args.h new file mode 100644 index 0000000000..71a7a671fd --- /dev/null +++ b/src/node/coins_view_args.h @@ -0,0 +1,15 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_NODE_COINS_VIEW_ARGS_H +#define BITCOIN_NODE_COINS_VIEW_ARGS_H + +class ArgsManager; +struct CoinsViewOptions; + +namespace node { +void ReadCoinsViewArgs(const ArgsManager& args, CoinsViewOptions& options); +} // namespace node + +#endif // BITCOIN_NODE_COINS_VIEW_ARGS_H diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 55ecd41af1..eb33e0028e 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) CCoinsViewTest base; SimulationTest(&base, false); - CCoinsViewDB db_base{"test", /*nCacheSize=*/1 << 23, /*fMemory=*/true, /*fWipe=*/false}; + CCoinsViewDB db_base{{.path = "test", .cache_bytes = 1 << 23, .memory_only = true}, {}}; SimulationTest(&db_base, true); } @@ -1064,7 +1064,7 @@ void TestFlushBehavior( BOOST_AUTO_TEST_CASE(ccoins_flush_behavior) { // Create two in-memory caches atop a leveldb view. - CCoinsViewDB base{"test", /*nCacheSize=*/ 1 << 23, /*fMemory=*/ true, /*fWipe=*/ false}; + CCoinsViewDB base{{.path = "test", .cache_bytes = 1 << 23, .memory_only = true}, {}}; std::vector<std::unique_ptr<CCoinsViewCacheTest>> caches; caches.push_back(std::make_unique<CCoinsViewCacheTest>(&base)); caches.push_back(std::make_unique<CCoinsViewCacheTest>(caches.back().get())); diff --git a/src/txdb.cpp b/src/txdb.cpp index 697eaa926d..5803bc7b31 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -71,32 +71,22 @@ struct CoinEntry { } // namespace -CCoinsViewDB::CCoinsViewDB(fs::path ldb_path, size_t nCacheSize, bool fMemory, bool fWipe) : - m_db{std::make_unique<CDBWrapper>(DBParams{ - .path = ldb_path, - .cache_bytes = nCacheSize, - .memory_only = fMemory, - .wipe_data = fWipe, - .obfuscate = true, - .options = [] { DBOptions options; node::ReadDatabaseArgs(gArgs, options); return options; }()})}, - m_ldb_path(ldb_path), - m_is_memory(fMemory) { } +CCoinsViewDB::CCoinsViewDB(DBParams db_params, CoinsViewOptions options) : + m_db_params{std::move(db_params)}, + m_options{std::move(options)}, + m_db{std::make_unique<CDBWrapper>(m_db_params)} { } void CCoinsViewDB::ResizeCache(size_t new_cache_size) { // We can't do this operation with an in-memory DB since we'll lose all the coins upon // reset. - if (!m_is_memory) { + if (!m_db_params.memory_only) { // Have to do a reset first to get the original `m_db` state to release its // filesystem lock. m_db.reset(); - m_db = std::make_unique<CDBWrapper>(DBParams{ - .path = m_ldb_path, - .cache_bytes = new_cache_size, - .memory_only = m_is_memory, - .wipe_data = false, - .obfuscate = true, - .options = [] { DBOptions options; node::ReadDatabaseArgs(gArgs, options); return options; }()}); + m_db_params.cache_bytes = new_cache_size; + m_db_params.wipe_data = false; + m_db = std::make_unique<CDBWrapper>(m_db_params); } } @@ -127,8 +117,6 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, boo CDBBatch batch(*m_db); size_t count = 0; size_t changed = 0; - size_t batch_size = (size_t)gArgs.GetIntArg("-dbbatchsize", nDefaultDbBatchSize); - int crash_simulate = gArgs.GetIntArg("-dbcrashratio", 0); assert(!hashBlock.IsNull()); uint256 old_tip = GetBestBlock(); @@ -159,13 +147,13 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, boo } count++; it = erase ? mapCoins.erase(it) : std::next(it); - if (batch.SizeEstimate() > batch_size) { + if (batch.SizeEstimate() > m_options.batch_write_bytes) { LogPrint(BCLog::COINDB, "Writing partial batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0)); m_db->WriteBatch(batch); batch.Clear(); - if (crash_simulate) { + if (m_options.simulate_crash_ratio) { static FastRandomContext rng; - if (rng.randrange(crash_simulate) == 0) { + if (rng.randrange(m_options.simulate_crash_ratio) == 0) { LogPrintf("Simulating a crash. Goodbye.\n"); _Exit(0); } diff --git a/src/txdb.h b/src/txdb.h index e3422846c0..bfbfab57a4 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -45,18 +45,24 @@ static const int64_t max_filter_index_cache = 1024; //! Max memory allocated to coin DB specific cache (MiB) static const int64_t nMaxCoinsDBCache = 8; +//! User-controlled performance and debug options. +struct CoinsViewOptions { + //! Maximum database write batch size in bytes. + size_t batch_write_bytes = nDefaultDbBatchSize; + //! If non-zero, randomly exit when the database is flushed with (1/ratio) + //! probability. + int simulate_crash_ratio = 0; +}; + /** CCoinsView backed by the coin database (chainstate/) */ class CCoinsViewDB final : public CCoinsView { protected: + DBParams m_db_params; + CoinsViewOptions m_options; std::unique_ptr<CDBWrapper> m_db; - fs::path m_ldb_path; - bool m_is_memory; public: - /** - * @param[in] ldb_path Location in the filesystem where leveldb data will be stored. - */ - explicit CCoinsViewDB(fs::path ldb_path, size_t nCacheSize, bool fMemory, bool fWipe); + explicit CCoinsViewDB(DBParams db_params, CoinsViewOptions options); bool GetCoin(const COutPoint &outpoint, Coin &coin) const override; bool HaveCoin(const COutPoint &outpoint) const override; diff --git a/src/validation.cpp b/src/validation.cpp index f0ffb748dd..971eb346a4 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -28,6 +28,8 @@ #include <node/blockstorage.h> #include <node/interface_ui.h> #include <node/utxo_snapshot.h> +#include <node/coins_view_args.h> +#include <node/database_args.h> #include <policy/policy.h> #include <policy/rbf.h> #include <policy/settings.h> @@ -1511,13 +1513,9 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) return nSubsidy; } -CoinsViews::CoinsViews( - fs::path ldb_name, - size_t cache_size_bytes, - bool in_memory, - bool should_wipe) : m_dbview( - gArgs.GetDataDirNet() / ldb_name, cache_size_bytes, in_memory, should_wipe), - m_catcherview(&m_dbview) {} +CoinsViews::CoinsViews(DBParams db_params, CoinsViewOptions options) + : m_dbview{std::move(db_params), std::move(options)}, + m_catcherview(&m_dbview) {} void CoinsViews::InitCache() { @@ -1546,7 +1544,14 @@ void Chainstate::InitCoinsDB( } m_coins_views = std::make_unique<CoinsViews>( - leveldb_name, cache_size_bytes, in_memory, should_wipe); + DBParams{ + .path = gArgs.GetDataDirNet() / leveldb_name, + .cache_bytes = cache_size_bytes, + .memory_only = in_memory, + .wipe_data = should_wipe, + .obfuscate = true, + .options = [] { DBOptions options; node::ReadDatabaseArgs(gArgs, options); return options; }()}, + [] { CoinsViewOptions options; node::ReadCoinsViewArgs(gArgs, options); return options; }()); } void Chainstate::InitCoinsCache(size_t cache_size_bytes) diff --git a/src/validation.h b/src/validation.h index 7170467b00..13a59d32dd 100644 --- a/src/validation.h +++ b/src/validation.h @@ -408,7 +408,7 @@ public: //! state to disk, which should not be done until the health of the database is verified. //! //! All arguments forwarded onto CCoinsViewDB. - CoinsViews(fs::path ldb_name, size_t cache_size_bytes, bool in_memory, bool should_wipe); + CoinsViews(DBParams db_params, CoinsViewOptions options); //! Initialize the CCoinsViewCache member. void InitCache() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); |