34
34
35
35
static auto CharCast (const std::byte* data) { return reinterpret_cast <const char *>(data); }
36
36
37
- bool DestroyDB (const std::string& path_str)
37
+ bool CDBWrapper:: DestroyDB (const std::string& path_str)
38
38
{
39
39
return leveldb::DestroyDB (path_str, {}).ok ();
40
40
}
41
41
42
+ struct CDBWrapper ::StatusImpl
43
+ {
44
+ const leveldb::Status status;
45
+ };
46
+
42
47
/* * Handle database error by throwing dbwrapper_error exception.
43
48
*/
44
- static void HandleError (const leveldb::Status& status )
49
+ void CDBWrapper:: HandleError (const CDBWrapper::StatusImpl& _status )
45
50
{
51
+ const leveldb::Status& status = _status.status ;
46
52
if (status.ok ())
47
53
return ;
48
54
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 " );
51
57
throw dbwrapper_error (errmsg);
52
58
}
53
59
@@ -155,23 +161,17 @@ struct CDBBatch::WriteBatchImpl {
155
161
leveldb::WriteBatch batch;
156
162
};
157
163
158
- CDBBatch::CDBBatch (const CDBWrapper & _parent)
159
- : parent{ _parent} ,
164
+ CDBBatch::CDBBatch (const CDBWrapperBase & _parent)
165
+ : CDBBatchBase( _parent) ,
160
166
m_impl_batch{std::make_unique<CDBBatch::WriteBatchImpl>()} {};
161
167
162
168
CDBBatch::~CDBBatch () = default ;
163
169
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)
171
171
{
172
172
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 ());
175
175
m_impl_batch->batch .Put (slKey, slValue);
176
176
// LevelDB serializes writes as:
177
177
// - byte: header
@@ -219,7 +219,8 @@ struct LevelDBContext {
219
219
};
220
220
221
221
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>()}
223
224
{
224
225
DBContext ().penv = nullptr ;
225
226
DBContext ().readoptions .verify_checksums = true ;
@@ -234,7 +235,7 @@ CDBWrapper::CDBWrapper(const DBParams& params)
234
235
} else {
235
236
if (params.wipe_data ) {
236
237
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 )} ;
238
239
HandleError (result);
239
240
}
240
241
TryCreateDirectories (params.path );
@@ -244,7 +245,7 @@ CDBWrapper::CDBWrapper(const DBParams& params)
244
245
// because on POSIX leveldb passes the byte string directly to ::open(), and
245
246
// on Windows it converts from UTF-8 to UTF-16 before calling ::CreateFileW
246
247
// (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 )} ;
248
249
HandleError (status);
249
250
LogPrintf (" Opened LevelDB successfully\n " );
250
251
@@ -253,25 +254,10 @@ CDBWrapper::CDBWrapper(const DBParams& params)
253
254
DBContext ().pdb ->CompactRange (nullptr , nullptr );
254
255
LogPrintf (" Finished database compaction of %s\n " , fs::PathToString (params.path ));
255
256
}
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));
272
259
}
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 ()));
275
261
}
276
262
277
263
CDBWrapper::~CDBWrapper ()
@@ -288,14 +274,15 @@ CDBWrapper::~CDBWrapper()
288
274
DBContext ().options .env = nullptr ;
289
275
}
290
276
291
- bool CDBWrapper::WriteBatch (CDBBatch& batch , bool fSync )
277
+ bool CDBWrapper::WriteBatch (CDBBatchBase& _batch , bool fSync )
292
278
{
279
+ CDBBatch& batch = static_cast <CDBBatch&>(_batch);
293
280
const bool log_memory = LogAcceptCategory (BCLog::LEVELDB, BCLog::Level::Debug);
294
281
double mem_before = 0 ;
295
282
if (log_memory) {
296
283
mem_before = DynamicMemoryUsage () / 1024.0 / 1024 ;
297
284
}
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 )} ;
299
286
HandleError (status);
300
287
if (log_memory) {
301
288
double mem_after = DynamicMemoryUsage () / 1024.0 / 1024 ;
@@ -320,21 +307,44 @@ size_t CDBWrapper::DynamicMemoryUsage() const
320
307
//
321
308
// We must use a string constructor which specifies length so that we copy
322
309
// past the null-terminator.
323
- const std::string CDBWrapper ::OBFUSCATE_KEY_KEY (" \000 obfuscate_key" , 14 );
310
+ const std::string CDBWrapperBase ::OBFUSCATE_KEY_KEY (" \000 obfuscate_key" , 14 );
324
311
325
- const unsigned int CDBWrapper ::OBFUSCATE_KEY_NUM_BYTES = 8 ;
312
+ const unsigned int CDBWrapperBase ::OBFUSCATE_KEY_NUM_BYTES = 8 ;
326
313
327
314
/* *
328
315
* Returns a string (consisting of 8 random bytes) suitable for use as an
329
316
* obfuscating XOR key.
330
317
*/
331
- std::vector<unsigned char > CDBWrapper ::CreateObfuscateKey () const
318
+ std::vector<unsigned char > CDBWrapperBase ::CreateObfuscateKey () const
332
319
{
333
320
std::vector<uint8_t > ret (OBFUSCATE_KEY_NUM_BYTES);
334
321
GetRandBytes (ret);
335
322
return ret;
336
323
}
337
324
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
+
338
348
std::optional<std::string> CDBWrapper::ReadImpl (Span<const std::byte> key) const
339
349
{
340
350
leveldb::Slice slKey (CharCast (key.data ()), key.size ());
@@ -344,7 +354,7 @@ std::optional<std::string> CDBWrapper::ReadImpl(Span<const std::byte> key) const
344
354
if (status.IsNotFound ())
345
355
return std::nullopt;
346
356
LogPrintf (" LevelDB read failure: %s\n " , status.ToString ());
347
- HandleError (status);
357
+ HandleError (StatusImpl{ status} );
348
358
}
349
359
return strValue;
350
360
}
@@ -359,7 +369,7 @@ bool CDBWrapper::ExistsImpl(Span<const std::byte> key) const
359
369
if (status.IsNotFound ())
360
370
return false ;
361
371
LogPrintf (" LevelDB read failure: %s\n " , status.ToString ());
362
- HandleError (status);
372
+ HandleError (StatusImpl{ status} );
363
373
}
364
374
return true ;
365
375
}
@@ -374,9 +384,10 @@ size_t CDBWrapper::EstimateSizeImpl(Span<const std::byte> key1, Span<const std::
374
384
return size;
375
385
}
376
386
387
+ // TODO: IsEmpty shouldn't be virtual in CDBWrapperBase
377
388
bool CDBWrapper::IsEmpty ()
378
389
{
379
- std::unique_ptr<CDBIterator> it (NewIterator ());
390
+ std::unique_ptr<CDBIterator> it (static_cast <CDBIterator*>( CDBWrapper:: NewIterator () ));
380
391
it->SeekToFirst ();
381
392
return !(it->Valid ());
382
393
}
@@ -387,10 +398,10 @@ struct CDBIterator::IteratorImpl {
387
398
explicit IteratorImpl (leveldb::Iterator* _iter) : iter{_iter} {}
388
399
};
389
400
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),
391
402
m_impl_iter(std::move(_piter)) {}
392
403
393
- CDBIterator * CDBWrapper::NewIterator ()
404
+ CDBIteratorBase * CDBWrapper::NewIterator ()
394
405
{
395
406
return new CDBIterator{*this , std::make_unique<CDBIterator::IteratorImpl>(DBContext ().pdb ->NewIterator (DBContext ().iteroptions ))};
396
407
}
@@ -423,4 +434,7 @@ const std::vector<unsigned char>& GetObfuscateKey(const CDBWrapper &w)
423
434
return w.obfuscate_key ;
424
435
}
425
436
426
- } // namespace dbwrapper_private
437
+ const std::vector<unsigned char >& CDBWrapperBase::GetObfuscateKey () const
438
+ {
439
+ return obfuscate_key;
440
+ }
0 commit comments