Skip to content

Commit cacf405

Browse files
committed
create abstract class, CDBWrapperBase
create abstract class for CDBWrapperBase leveldb implementation is now CDBWrapper this is a bit confusing naming wise, but keeps this diff small make all the indexes to use cdbwrapperbase
1 parent 45dd943 commit cacf405

12 files changed

+247
-166
lines changed

src/dbwrapper.cpp

+61-47
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,26 @@
3434

3535
static auto CharCast(const std::byte* data) { return reinterpret_cast<const char*>(data); }
3636

37-
bool DestroyDB(const std::string& path_str)
37+
bool CDBWrapper::DestroyDB(const std::string& path_str)
3838
{
3939
return leveldb::DestroyDB(path_str, {}).ok();
4040
}
4141

42+
struct CDBWrapper::StatusImpl
43+
{
44+
const leveldb::Status status;
45+
};
46+
4247
/** Handle database error by throwing dbwrapper_error exception.
4348
*/
44-
static void HandleError(const leveldb::Status& status)
49+
void CDBWrapper::HandleError(const CDBWrapper::StatusImpl& _status)
4550
{
51+
const leveldb::Status& status = _status.status;
4652
if (status.ok())
4753
return;
4854
const std::string errmsg = "Fatal LevelDB error: " + status.ToString();
49-
LogPrintf("%s\n", errmsg);
50-
LogPrintf("You can use -debug=leveldb to get more complete diagnostic messages\n");
55+
LogWarning("%s\n", errmsg);
56+
LogWarning("You can use -debug=leveldb to get more complete diagnostic messages\n");
5157
throw dbwrapper_error(errmsg);
5258
}
5359

@@ -155,23 +161,17 @@ struct CDBBatch::WriteBatchImpl {
155161
leveldb::WriteBatch batch;
156162
};
157163

158-
CDBBatch::CDBBatch(const CDBWrapper& _parent)
159-
: parent{_parent},
164+
CDBBatch::CDBBatch(const CDBWrapperBase& _parent)
165+
: CDBBatchBase(_parent),
160166
m_impl_batch{std::make_unique<CDBBatch::WriteBatchImpl>()} {};
161167

162168
CDBBatch::~CDBBatch() = default;
163169

164-
void CDBBatch::Clear()
165-
{
166-
m_impl_batch->batch.Clear();
167-
size_estimate = 0;
168-
}
169-
170-
void CDBBatch::WriteImpl(Span<const std::byte> key, DataStream& ssValue)
170+
void CDBBatch::WriteImpl(Span<const std::byte> key, DataStream& value)
171171
{
172172
leveldb::Slice slKey(CharCast(key.data()), key.size());
173-
ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent));
174-
leveldb::Slice slValue(CharCast(ssValue.data()), ssValue.size());
173+
value.Xor(m_parent.GetObfuscateKey());
174+
leveldb::Slice slValue(CharCast(value.data()), value.size());
175175
m_impl_batch->batch.Put(slKey, slValue);
176176
// LevelDB serializes writes as:
177177
// - byte: header
@@ -219,7 +219,8 @@ struct LevelDBContext {
219219
};
220220

221221
CDBWrapper::CDBWrapper(const DBParams& params)
222-
: m_db_context{std::make_unique<LevelDBContext>()}, m_name{fs::PathToString(params.path.stem())}, m_path{params.path}, m_is_memory{params.memory_only}
222+
: CDBWrapperBase(params),
223+
m_db_context{std::make_unique<LevelDBContext>()}
223224
{
224225
DBContext().penv = nullptr;
225226
DBContext().readoptions.verify_checksums = true;
@@ -234,7 +235,7 @@ CDBWrapper::CDBWrapper(const DBParams& params)
234235
} else {
235236
if (params.wipe_data) {
236237
LogPrintf("Wiping LevelDB in %s\n", fs::PathToString(params.path));
237-
leveldb::Status result = leveldb::DestroyDB(fs::PathToString(params.path), DBContext().options);
238+
StatusImpl result{leveldb::DestroyDB(fs::PathToString(params.path), DBContext().options)};
238239
HandleError(result);
239240
}
240241
TryCreateDirectories(params.path);
@@ -244,7 +245,7 @@ CDBWrapper::CDBWrapper(const DBParams& params)
244245
// because on POSIX leveldb passes the byte string directly to ::open(), and
245246
// on Windows it converts from UTF-8 to UTF-16 before calling ::CreateFileW
246247
// (see env_posix.cc and env_windows.cc).
247-
leveldb::Status status = leveldb::DB::Open(DBContext().options, fs::PathToString(params.path), &DBContext().pdb);
248+
StatusImpl status{leveldb::DB::Open(DBContext().options, fs::PathToString(params.path), &DBContext().pdb)};
248249
HandleError(status);
249250
LogPrintf("Opened LevelDB successfully\n");
250251

@@ -253,25 +254,10 @@ CDBWrapper::CDBWrapper(const DBParams& params)
253254
DBContext().pdb->CompactRange(nullptr, nullptr);
254255
LogPrintf("Finished database compaction of %s\n", fs::PathToString(params.path));
255256
}
256-
257-
// The base-case obfuscation key, which is a noop.
258-
obfuscate_key = std::vector<unsigned char>(OBFUSCATE_KEY_NUM_BYTES, '\000');
259-
260-
bool key_exists = Read(OBFUSCATE_KEY_KEY, obfuscate_key);
261-
262-
if (!key_exists && params.obfuscate && IsEmpty()) {
263-
// Initialize non-degenerate obfuscation if it won't upset
264-
// existing, non-obfuscated data.
265-
std::vector<unsigned char> new_key = CreateObfuscateKey();
266-
267-
// Write `new_key` so we don't obfuscate the key with itself
268-
Write(OBFUSCATE_KEY_KEY, new_key);
269-
obfuscate_key = new_key;
270-
271-
LogPrintf("Wrote new obfuscate key for %s: %s\n", fs::PathToString(params.path), HexStr(obfuscate_key));
257+
if(params.obfuscate && WriteObfuscateKeyIfNotExists()){
258+
LogInfo("Wrote new obfuscate key for %s: %s\n", fs::PathToString(params.path), HexStr(obfuscate_key));
272259
}
273-
274-
LogPrintf("Using obfuscation key for %s: %s\n", fs::PathToString(params.path), HexStr(obfuscate_key));
260+
LogInfo("Using obfuscation key for %s: %s\n", fs::PathToString(params.path), HexStr(GetObfuscateKey()));
275261
}
276262

277263
CDBWrapper::~CDBWrapper()
@@ -288,14 +274,15 @@ CDBWrapper::~CDBWrapper()
288274
DBContext().options.env = nullptr;
289275
}
290276

291-
bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync)
277+
bool CDBWrapper::WriteBatch(CDBBatchBase& _batch, bool fSync)
292278
{
279+
CDBBatch& batch = static_cast<CDBBatch&>(_batch);
293280
const bool log_memory = LogAcceptCategory(BCLog::LEVELDB, BCLog::Level::Debug);
294281
double mem_before = 0;
295282
if (log_memory) {
296283
mem_before = DynamicMemoryUsage() / 1024.0 / 1024;
297284
}
298-
leveldb::Status status = DBContext().pdb->Write(fSync ? DBContext().syncoptions : DBContext().writeoptions, &batch.m_impl_batch->batch);
285+
StatusImpl status{DBContext().pdb->Write(fSync ? DBContext().syncoptions : DBContext().writeoptions, &batch.m_impl_batch->batch)};
299286
HandleError(status);
300287
if (log_memory) {
301288
double mem_after = DynamicMemoryUsage() / 1024.0 / 1024;
@@ -320,21 +307,44 @@ size_t CDBWrapper::DynamicMemoryUsage() const
320307
//
321308
// We must use a string constructor which specifies length so that we copy
322309
// past the null-terminator.
323-
const std::string CDBWrapper::OBFUSCATE_KEY_KEY("\000obfuscate_key", 14);
310+
const std::string CDBWrapperBase::OBFUSCATE_KEY_KEY("\000obfuscate_key", 14);
324311

325-
const unsigned int CDBWrapper::OBFUSCATE_KEY_NUM_BYTES = 8;
312+
const unsigned int CDBWrapperBase::OBFUSCATE_KEY_NUM_BYTES = 8;
326313

327314
/**
328315
* Returns a string (consisting of 8 random bytes) suitable for use as an
329316
* obfuscating XOR key.
330317
*/
331-
std::vector<unsigned char> CDBWrapper::CreateObfuscateKey() const
318+
std::vector<unsigned char> CDBWrapperBase::CreateObfuscateKey() const
332319
{
333320
std::vector<uint8_t> ret(OBFUSCATE_KEY_NUM_BYTES);
334321
GetRandBytes(ret);
335322
return ret;
336323
}
337324

325+
bool CDBWrapperBase::WriteObfuscateKeyIfNotExists()
326+
{
327+
// The base-case obfuscation key, which is a noop.
328+
obfuscate_key = std::vector<unsigned char>(OBFUSCATE_KEY_NUM_BYTES, '\000');
329+
330+
bool key_exists = Read(OBFUSCATE_KEY_KEY, obfuscate_key);
331+
332+
if (!key_exists && IsEmpty()) {
333+
// Initialize non-degenerate obfuscation if it won't upset
334+
// existing, non-obfuscated data.
335+
std::vector<unsigned char> new_key = CreateObfuscateKey();
336+
337+
// Write `new_key` so we don't obfuscate the key with itself
338+
Write(OBFUSCATE_KEY_KEY, new_key);
339+
obfuscate_key = new_key;
340+
return true;
341+
}
342+
else {
343+
return false;
344+
}
345+
}
346+
347+
338348
std::optional<std::string> CDBWrapper::ReadImpl(Span<const std::byte> key) const
339349
{
340350
leveldb::Slice slKey(CharCast(key.data()), key.size());
@@ -344,7 +354,7 @@ std::optional<std::string> CDBWrapper::ReadImpl(Span<const std::byte> key) const
344354
if (status.IsNotFound())
345355
return std::nullopt;
346356
LogPrintf("LevelDB read failure: %s\n", status.ToString());
347-
HandleError(status);
357+
HandleError(StatusImpl{status});
348358
}
349359
return strValue;
350360
}
@@ -359,7 +369,7 @@ bool CDBWrapper::ExistsImpl(Span<const std::byte> key) const
359369
if (status.IsNotFound())
360370
return false;
361371
LogPrintf("LevelDB read failure: %s\n", status.ToString());
362-
HandleError(status);
372+
HandleError(StatusImpl{status});
363373
}
364374
return true;
365375
}
@@ -374,9 +384,10 @@ size_t CDBWrapper::EstimateSizeImpl(Span<const std::byte> key1, Span<const std::
374384
return size;
375385
}
376386

387+
// TODO: IsEmpty shouldn't be virtual in CDBWrapperBase
377388
bool CDBWrapper::IsEmpty()
378389
{
379-
std::unique_ptr<CDBIterator> it(NewIterator());
390+
std::unique_ptr<CDBIterator> it(static_cast<CDBIterator*>(CDBWrapper::NewIterator()));
380391
it->SeekToFirst();
381392
return !(it->Valid());
382393
}
@@ -387,10 +398,10 @@ struct CDBIterator::IteratorImpl {
387398
explicit IteratorImpl(leveldb::Iterator* _iter) : iter{_iter} {}
388399
};
389400

390-
CDBIterator::CDBIterator(const CDBWrapper& _parent, std::unique_ptr<IteratorImpl> _piter) : parent(_parent),
401+
CDBIterator::CDBIterator(const CDBWrapperBase& _parent, std::unique_ptr<IteratorImpl> _piter): CDBIteratorBase(_parent),
391402
m_impl_iter(std::move(_piter)) {}
392403

393-
CDBIterator* CDBWrapper::NewIterator()
404+
CDBIteratorBase* CDBWrapper::NewIterator()
394405
{
395406
return new CDBIterator{*this, std::make_unique<CDBIterator::IteratorImpl>(DBContext().pdb->NewIterator(DBContext().iteroptions))};
396407
}
@@ -423,4 +434,7 @@ const std::vector<unsigned char>& GetObfuscateKey(const CDBWrapper &w)
423434
return w.obfuscate_key;
424435
}
425436

426-
} // namespace dbwrapper_private
437+
const std::vector<unsigned char>& CDBWrapperBase::GetObfuscateKey() const
438+
{
439+
return obfuscate_key;
440+
}

0 commit comments

Comments
 (0)