Skip to content

Commit 2eaeded

Browse files
committed
refactor, dbwrapper: Add DBParams and DBOptions structs
Add DBParams and DBOptions structs to remove ArgsManager uses from dbwrapper. To reduce size of this commit, this moves references to gArgs variable out of dbwrapper.cpp to calling code in txdb.cpp. But these moves are temporary. The gArgs references in txdb.cpp are moved out to calling code in init.cpp in later commits. This commit does not change behavior.
1 parent 4f841cb commit 2eaeded

File tree

8 files changed

+115
-41
lines changed

8 files changed

+115
-41
lines changed

src/Makefile.am

+2
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ BITCOIN_CORE_H = \
206206
node/coin.h \
207207
node/connection_types.h \
208208
node/context.h \
209+
node/database_args.h \
209210
node/eviction.h \
210211
node/interface_ui.h \
211212
node/mempool_args.h \
@@ -390,6 +391,7 @@ libbitcoin_node_a_SOURCES = \
390391
node/coin.cpp \
391392
node/connection_types.cpp \
392393
node/context.cpp \
394+
node/database_args.cpp \
393395
node/eviction.cpp \
394396
node/interface_ui.cpp \
395397
node/interfaces.cpp \

src/dbwrapper.cpp

+16-16
Original file line numberDiff line numberDiff line change
@@ -127,48 +127,48 @@ static leveldb::Options GetOptions(size_t nCacheSize)
127127
return options;
128128
}
129129

130-
CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate)
131-
: m_name{fs::PathToString(path.stem())}, m_path{path}, m_is_memory{fMemory}
130+
CDBWrapper::CDBWrapper(const DBParams& params)
131+
: m_name{fs::PathToString(params.path.stem())}, m_path{params.path}, m_is_memory{params.memory_only}
132132
{
133133
penv = nullptr;
134134
readoptions.verify_checksums = true;
135135
iteroptions.verify_checksums = true;
136136
iteroptions.fill_cache = false;
137137
syncoptions.sync = true;
138-
options = GetOptions(nCacheSize);
138+
options = GetOptions(params.cache_bytes);
139139
options.create_if_missing = true;
140-
if (fMemory) {
140+
if (params.memory_only) {
141141
penv = leveldb::NewMemEnv(leveldb::Env::Default());
142142
options.env = penv;
143143
} else {
144-
if (fWipe) {
145-
LogPrintf("Wiping LevelDB in %s\n", fs::PathToString(path));
146-
leveldb::Status result = leveldb::DestroyDB(fs::PathToString(path), options);
144+
if (params.wipe_data) {
145+
LogPrintf("Wiping LevelDB in %s\n", fs::PathToString(params.path));
146+
leveldb::Status result = leveldb::DestroyDB(fs::PathToString(params.path), options);
147147
dbwrapper_private::HandleError(result);
148148
}
149-
TryCreateDirectories(path);
150-
LogPrintf("Opening LevelDB in %s\n", fs::PathToString(path));
149+
TryCreateDirectories(params.path);
150+
LogPrintf("Opening LevelDB in %s\n", fs::PathToString(params.path));
151151
}
152152
// PathToString() return value is safe to pass to leveldb open function,
153153
// because on POSIX leveldb passes the byte string directly to ::open(), and
154154
// on Windows it converts from UTF-8 to UTF-16 before calling ::CreateFileW
155155
// (see env_posix.cc and env_windows.cc).
156-
leveldb::Status status = leveldb::DB::Open(options, fs::PathToString(path), &pdb);
156+
leveldb::Status status = leveldb::DB::Open(options, fs::PathToString(params.path), &pdb);
157157
dbwrapper_private::HandleError(status);
158158
LogPrintf("Opened LevelDB successfully\n");
159159

160-
if (gArgs.GetBoolArg("-forcecompactdb", false)) {
161-
LogPrintf("Starting database compaction of %s\n", fs::PathToString(path));
160+
if (params.options.force_compact) {
161+
LogPrintf("Starting database compaction of %s\n", fs::PathToString(params.path));
162162
pdb->CompactRange(nullptr, nullptr);
163-
LogPrintf("Finished database compaction of %s\n", fs::PathToString(path));
163+
LogPrintf("Finished database compaction of %s\n", fs::PathToString(params.path));
164164
}
165165

166166
// The base-case obfuscation key, which is a noop.
167167
obfuscate_key = std::vector<unsigned char>(OBFUSCATE_KEY_NUM_BYTES, '\000');
168168

169169
bool key_exists = Read(OBFUSCATE_KEY_KEY, obfuscate_key);
170170

171-
if (!key_exists && obfuscate && IsEmpty()) {
171+
if (!key_exists && params.obfuscate && IsEmpty()) {
172172
// Initialize non-degenerate obfuscation if it won't upset
173173
// existing, non-obfuscated data.
174174
std::vector<unsigned char> new_key = CreateObfuscateKey();
@@ -177,10 +177,10 @@ CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bo
177177
Write(OBFUSCATE_KEY_KEY, new_key);
178178
obfuscate_key = new_key;
179179

180-
LogPrintf("Wrote new obfuscate key for %s: %s\n", fs::PathToString(path), HexStr(obfuscate_key));
180+
LogPrintf("Wrote new obfuscate key for %s: %s\n", fs::PathToString(params.path), HexStr(obfuscate_key));
181181
}
182182

183-
LogPrintf("Using obfuscation key for %s: %s\n", fs::PathToString(path), HexStr(obfuscate_key));
183+
LogPrintf("Using obfuscation key for %s: %s\n", fs::PathToString(params.path), HexStr(obfuscate_key));
184184
}
185185

186186
CDBWrapper::~CDBWrapper()

src/dbwrapper.h

+24-9
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,29 @@ class Env;
3131
static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64;
3232
static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024;
3333

34+
//! User-controlled performance and debug options.
35+
struct DBOptions {
36+
//! Compact database on startup.
37+
bool force_compact = false;
38+
};
39+
40+
//! Application-specific storage settings.
41+
struct DBParams {
42+
//! Location in the filesystem where leveldb data will be stored.
43+
fs::path path;
44+
//! Configures various leveldb cache settings.
45+
size_t cache_bytes;
46+
//! If true, use leveldb's memory environment.
47+
bool memory_only = false;
48+
//! If true, remove all existing data.
49+
bool wipe_data = false;
50+
//! If true, store data obfuscated via simple XOR. If false, XOR with a
51+
//! zero'd byte array.
52+
bool obfuscate = false;
53+
//! Passed-through options.
54+
DBOptions options{};
55+
};
56+
3457
class dbwrapper_error : public std::runtime_error
3558
{
3659
public:
@@ -230,15 +253,7 @@ class CDBWrapper
230253
bool m_is_memory;
231254

232255
public:
233-
/**
234-
* @param[in] path Location in the filesystem where leveldb data will be stored.
235-
* @param[in] nCacheSize Configures various leveldb cache settings.
236-
* @param[in] fMemory If true, use leveldb's memory environment.
237-
* @param[in] fWipe If true, remove all existing data.
238-
* @param[in] obfuscate If true, store data obfuscated via simple XOR. If false, XOR
239-
* with a zero'd byte array.
240-
*/
241-
CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool obfuscate = false);
256+
CDBWrapper(const DBParams& params);
242257
~CDBWrapper();
243258

244259
CDBWrapper(const CDBWrapper&) = delete;

src/index/base.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <kernel/chain.h>
99
#include <node/blockstorage.h>
1010
#include <node/context.h>
11+
#include <node/database_args.h>
1112
#include <node/interface_ui.h>
1213
#include <shutdown.h>
1314
#include <tinyformat.h>
@@ -48,7 +49,13 @@ CBlockLocator GetLocator(interfaces::Chain& chain, const uint256& block_hash)
4849
}
4950

5051
BaseIndex::DB::DB(const fs::path& path, size_t n_cache_size, bool f_memory, bool f_wipe, bool f_obfuscate) :
51-
CDBWrapper(path, n_cache_size, f_memory, f_wipe, f_obfuscate)
52+
CDBWrapper{DBParams{
53+
.path = path,
54+
.cache_bytes = n_cache_size,
55+
.memory_only = f_memory,
56+
.wipe_data = f_wipe,
57+
.obfuscate = f_obfuscate,
58+
.options = [] { DBOptions options; node::ReadDatabaseArgs(gArgs, options); return options; }()}}
5259
{}
5360

5461
bool BaseIndex::DB::ReadBestBlock(CBlockLocator& locator) const

src/node/database_args.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) 2022 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <node/database_args.h>
6+
7+
#include <dbwrapper.h>
8+
#include <util/system.h>
9+
10+
namespace node {
11+
void ReadDatabaseArgs(const ArgsManager& args, DBOptions& options)
12+
{
13+
// Settings here apply to all databases (chainstate, blocks, and index
14+
// databases), but it'd be easy to parse database-specific options by adding
15+
// a database_type string or enum parameter to this function.
16+
if (auto value = args.GetBoolArg("-forcecompactdb")) options.force_compact = *value;
17+
}
18+
} // namespace node

src/node/database_args.h

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) 2022 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_NODE_DATABASE_ARGS_H
6+
#define BITCOIN_NODE_DATABASE_ARGS_H
7+
8+
class ArgsManager;
9+
struct DBOptions;
10+
11+
namespace node {
12+
void ReadDatabaseArgs(const ArgsManager& args, DBOptions& options);
13+
} // namespace node
14+
15+
#endif // BITCOIN_NODE_DATABASE_ARGS_H

src/test/dbwrapper_tests.cpp

+11-11
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper)
2828
// Perform tests both obfuscated and non-obfuscated.
2929
for (const bool obfuscate : {false, true}) {
3030
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_obfuscate_true" : "dbwrapper_obfuscate_false");
31-
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
31+
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = obfuscate});
3232
uint8_t key{'k'};
3333
uint256 in = InsecureRand256();
3434
uint256 res;
@@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_basic_data)
4747
// Perform tests both obfuscated and non-obfuscated.
4848
for (bool obfuscate : {false, true}) {
4949
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_1_obfuscate_true" : "dbwrapper_1_obfuscate_false");
50-
CDBWrapper dbw(ph, (1 << 20), false, true, obfuscate);
50+
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = false, .wipe_data = true, .obfuscate = obfuscate});
5151

5252
uint256 res;
5353
uint32_t res_uint_32;
@@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch)
128128
// Perform tests both obfuscated and non-obfuscated.
129129
for (const bool obfuscate : {false, true}) {
130130
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_batch_obfuscate_true" : "dbwrapper_batch_obfuscate_false");
131-
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
131+
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = obfuscate});
132132

133133
uint8_t key{'i'};
134134
uint256 in = InsecureRand256();
@@ -164,7 +164,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
164164
// Perform tests both obfuscated and non-obfuscated.
165165
for (const bool obfuscate : {false, true}) {
166166
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_iterator_obfuscate_true" : "dbwrapper_iterator_obfuscate_false");
167-
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
167+
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = obfuscate});
168168

169169
// The two keys are intentionally chosen for ordering
170170
uint8_t key{'j'};
@@ -207,7 +207,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
207207
fs::create_directories(ph);
208208

209209
// Set up a non-obfuscated wrapper to write some initial data.
210-
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false);
210+
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(DBParams{.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = false, .obfuscate = false});
211211
uint8_t key{'k'};
212212
uint256 in = InsecureRand256();
213213
uint256 res;
@@ -220,7 +220,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
220220
dbw.reset();
221221

222222
// Now, set up another wrapper that wants to obfuscate the same directory
223-
CDBWrapper odbw(ph, (1 << 10), false, false, true);
223+
CDBWrapper odbw({.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = false, .obfuscate = true});
224224

225225
// Check that the key/val we wrote with unobfuscated wrapper exists and
226226
// is readable.
@@ -248,7 +248,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
248248
fs::create_directories(ph);
249249

250250
// Set up a non-obfuscated wrapper to write some initial data.
251-
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false);
251+
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(DBParams{.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = false, .obfuscate = false});
252252
uint8_t key{'k'};
253253
uint256 in = InsecureRand256();
254254
uint256 res;
@@ -261,7 +261,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
261261
dbw.reset();
262262

263263
// Simulate a -reindex by wiping the existing data store
264-
CDBWrapper odbw(ph, (1 << 10), false, true, true);
264+
CDBWrapper odbw({.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = true, .obfuscate = true});
265265

266266
// Check that the key/val we wrote with unobfuscated wrapper doesn't exist
267267
uint256 res2;
@@ -280,7 +280,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
280280
BOOST_AUTO_TEST_CASE(iterator_ordering)
281281
{
282282
fs::path ph = m_args.GetDataDirBase() / "iterator_ordering";
283-
CDBWrapper dbw(ph, (1 << 20), true, false, false);
283+
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = false});
284284
for (int x=0x00; x<256; ++x) {
285285
uint8_t key = x;
286286
uint32_t value = x*x;
@@ -348,7 +348,7 @@ struct StringContentsSerializer {
348348
BOOST_AUTO_TEST_CASE(iterator_string_ordering)
349349
{
350350
fs::path ph = m_args.GetDataDirBase() / "iterator_string_ordering";
351-
CDBWrapper dbw(ph, (1 << 20), true, false, false);
351+
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = false});
352352
for (int x = 0; x < 10; ++x) {
353353
for (int y = 0; y < 10; ++y) {
354354
std::string key{ToString(x)};
@@ -390,7 +390,7 @@ BOOST_AUTO_TEST_CASE(unicodepath)
390390
// the ANSI CreateDirectoryA call and the code page isn't UTF8.
391391
// It will succeed if created with CreateDirectoryW.
392392
fs::path ph = m_args.GetDataDirBase() / "test_runner_₿_🏃_20191128_104644";
393-
CDBWrapper dbw(ph, (1 << 20));
393+
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20});
394394

395395
fs::path lockPath = ph / "LOCK";
396396
BOOST_CHECK(fs::exists(lockPath));

src/txdb.cpp

+21-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <txdb.h>
77

88
#include <chain.h>
9+
#include <node/database_args.h>
910
#include <pow.h>
1011
#include <random.h>
1112
#include <shutdown.h>
@@ -71,7 +72,13 @@ struct CoinEntry {
7172
} // namespace
7273

7374
CCoinsViewDB::CCoinsViewDB(fs::path ldb_path, size_t nCacheSize, bool fMemory, bool fWipe) :
74-
m_db(std::make_unique<CDBWrapper>(ldb_path, nCacheSize, fMemory, fWipe, true)),
75+
m_db{std::make_unique<CDBWrapper>(DBParams{
76+
.path = ldb_path,
77+
.cache_bytes = nCacheSize,
78+
.memory_only = fMemory,
79+
.wipe_data = fWipe,
80+
.obfuscate = true,
81+
.options = [] { DBOptions options; node::ReadDatabaseArgs(gArgs, options); return options; }()})},
7582
m_ldb_path(ldb_path),
7683
m_is_memory(fMemory) { }
7784

@@ -83,8 +90,13 @@ void CCoinsViewDB::ResizeCache(size_t new_cache_size)
8390
// Have to do a reset first to get the original `m_db` state to release its
8491
// filesystem lock.
8592
m_db.reset();
86-
m_db = std::make_unique<CDBWrapper>(
87-
m_ldb_path, new_cache_size, m_is_memory, /*fWipe=*/false, /*obfuscate=*/true);
93+
m_db = std::make_unique<CDBWrapper>(DBParams{
94+
.path = m_ldb_path,
95+
.cache_bytes = new_cache_size,
96+
.memory_only = m_is_memory,
97+
.wipe_data = false,
98+
.obfuscate = true,
99+
.options = [] { DBOptions options; node::ReadDatabaseArgs(gArgs, options); return options; }()});
88100
}
89101
}
90102

@@ -176,7 +188,12 @@ size_t CCoinsViewDB::EstimateSize() const
176188
return m_db->EstimateSize(DB_COIN, uint8_t(DB_COIN + 1));
177189
}
178190

179-
CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(gArgs.GetDataDirNet() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
191+
CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper{DBParams{
192+
.path = gArgs.GetDataDirNet() / "blocks" / "index",
193+
.cache_bytes = nCacheSize,
194+
.memory_only = fMemory,
195+
.wipe_data = fWipe,
196+
.options = [] { DBOptions options; node::ReadDatabaseArgs(gArgs, options); return options; }()}} {
180197
}
181198

182199
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {

0 commit comments

Comments
 (0)