14#include <leveldb/cache.h>
15#include <leveldb/db.h>
16#include <leveldb/env.h>
17#include <leveldb/filter_policy.h>
18#include <leveldb/helpers/memenv/memenv.h>
19#include <leveldb/slice.h>
20#include <leveldb/write_batch.h>
31 return reinterpret_cast<const char *
>(data);
43 const std::string errmsg =
"Fatal LevelDB error: " + status.ToString();
45 LogPrintf(
"You can use -debug=leveldb to get more complete diagnostic "
60 for (
int iter = 0; iter < 2; iter++) {
64 bufsize =
sizeof(buffer);
68 base =
new char[bufsize];
71 char *limit = base + bufsize;
76 va_copy(backup_ap, ap);
79 p += vsnprintf(p, limit - p,
format, backup_ap);
93 if (p == base || p[-1] !=
'\n') {
98 base[std::min(bufsize - 1, (
int)(p - base))] =
'\0';
101 if (base != buffer) {
124 int default_open_files = options->max_open_files;
126 if (
sizeof(
void *) < 8) {
127 options->max_open_files = 64;
131 options->max_open_files, default_open_files);
135 leveldb::Options options;
136 options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
138 options.write_buffer_size = nCacheSize / 4;
139 options.filter_policy = leveldb::NewBloomFilterPolicy(10);
140 options.compression = leveldb::kNoCompression;
142 if (leveldb::kMajorVersion > 1 ||
143 (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) {
146 options.paranoid_checks =
true;
148 options.max_file_size =
182 (slValue.size() > 127) + slValue.size();
222 m_name{
fs::
PathToString(params.path.stem())}, m_path{params.path},
223 m_is_memory{params.memory_only} {
225 DBContext().readoptions.verify_checksums =
true;
226 DBContext().iteroptions.verify_checksums =
true;
227 DBContext().iteroptions.fill_cache =
false;
230 DBContext().options.create_if_missing =
true;
232 DBContext().penv = leveldb::NewMemEnv(leveldb::Env::Default());
248 leveldb::Status status = leveldb::DB::Open(
251 LogPrintf(
"Opened LevelDB successfully\n");
254 LogPrintf(
"Starting database compaction of %s\n",
256 DBContext().pdb->CompactRange(
nullptr,
nullptr);
257 LogPrintf(
"Finished database compaction of %s\n",
275 LogPrintf(
"Wrote new obfuscate key for %s: %s\n",
279 LogPrintf(
"Using obfuscation key for %s: %s\n",
286 delete DBContext().options.filter_policy;
287 DBContext().options.filter_policy =
nullptr;
291 DBContext().options.block_cache =
nullptr;
297 const bool log_memory =
299 double mem_before = 0;
303 leveldb::Status status =
DBContext().pdb->Write(
311 "WriteBatch memory usage: db=%s, before=%.1fMiB, after=%.1fMiB\n",
312 m_name, mem_before, mem_after);
318 std::optional<size_t> parsed;
319 if (!
DBContext().pdb->GetProperty(
"leveldb.approximate-memory-usage",
321 !(parsed = ToIntegral<size_t>(memory))) {
323 "Failed to get approximate-memory-usage property\n");
326 return parsed.value();
347std::optional<std::string>
350 std::string strValue;
351 leveldb::Status status =
354 if (status.IsNotFound()) {
357 LogPrintf(
"LevelDB read failure: %s\n", status.ToString());
366 std::string strValue;
367 leveldb::Status status =
370 if (status.IsNotFound()) {
373 LogPrintf(
"LevelDB read failure: %s\n", status.ToString());
384 leveldb::Range range(slKey1, slKey2);
385 DBContext().pdb->GetApproximateSizes(&range, 1, &size);
392 return !(it->Valid());
396 const std::unique_ptr<leveldb::Iterator>
iter;
402 std::unique_ptr<IteratorImpl> _piter)
403 : parent(_parent), m_impl_iter(
std::move(_piter)) {}
407 *
this, std::make_unique<CDBIterator::IteratorImpl>(
void Logv(const char *format, va_list ap) override
Batch of changes queued to be written to a CDBWrapper.
const std::unique_ptr< WriteBatchImpl > m_impl_batch
CDBBatch(const CDBWrapper &_parent)
void WriteImpl(Span< const std::byte > key, DataStream &ssValue_)
const CDBWrapper & parent
void EraseImpl(Span< const std::byte > key)
Span< const std::byte > GetKeyImpl() const
CDBIterator(const CDBWrapper &_parent, std::unique_ptr< IteratorImpl > _piter)
const std::unique_ptr< IteratorImpl > m_impl_iter
Span< const std::byte > GetValueImpl() const
void SeekImpl(Span< const std::byte > key)
size_t DynamicMemoryUsage() const
bool Read(const K &key, V &value) const
std::vector< uint8_t > CreateObfuscateKey() const
Returns a string (consisting of 8 random bytes) suitable for use as an obfuscating XOR key.
CDBIterator * NewIterator()
std::string m_name
the name of this database
std::vector< uint8_t > obfuscate_key
a key used for optional XOR-obfuscation of the database
CDBWrapper(const DBParams ¶ms)
static const unsigned int OBFUSCATE_KEY_NUM_BYTES
the length of the obfuscate key in number of bytes
static const std::string OBFUSCATE_KEY_KEY
the key under which the obfuscation key is stored
void WriteBatch(CDBBatch &batch, bool fSync=false)
std::optional< std::string > ReadImpl(Span< const std::byte > key) const
void Write(const K &key, const V &value, bool fSync=false)
auto & DBContext() const LIFETIMEBOUND
bool ExistsImpl(Span< const std::byte > key) const
bool IsEmpty()
Return true if the database managed by this class contains no entries.
size_t EstimateSizeImpl(Span< const std::byte > key1, Span< const std::byte > key2) const
Double ended buffer combining vector and stream-like interfaces.
void Xor(const std::vector< uint8_t > &key)
XOR the contents of this stream with a certain key.
A Span is an object that can refer to a contiguous sequence of objects.
constexpr std::size_t size() const noexcept
constexpr C * data() const noexcept
static leveldb::Options GetOptions(size_t nCacheSize)
static auto CharCast(const std::byte *data)
bool DestroyDB(const std::string &path_str)
static void SetMaxOpenFiles(leveldb::Options *options)
static void HandleError(const leveldb::Status &status)
Handle database error by throwing dbwrapper_error exception.
static const size_t DBWRAPPER_MAX_FILE_SIZE
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
#define LogPrintLevelToBeContinued
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
#define LogDebug(category,...)
These should be considered an implementation detail of the specific database.
const std::vector< uint8_t > & GetObfuscateKey(const CDBWrapper &w)
Work around circular dependency, as well as for testing in dbwrapper_tests.
Filesystem operations and types.
static std::string PathToString(const path &path)
Convert path object to byte string.
Implement std::hash so RCUPtr can be used as a key for maps or sets.
void GetRandBytes(Span< uint8_t > bytes) noexcept
================== BASE RANDOMNESS GENERATION FUNCTIONS ====================
Span< const std::byte > MakeByteSpan(V &&v) noexcept
leveldb::WriteBatch batch
IteratorImpl(leveldb::Iterator *_iter)
const std::unique_ptr< leveldb::Iterator > iter
bool force_compact
Compact database on startup.
Application-specific storage settings.
DBOptions options
Passed-through options.
bool obfuscate
If true, store data obfuscated via simple XOR.
bool wipe_data
If true, remove all existing data.
size_t cache_bytes
Configures various leveldb cache settings.
fs::path path
Location in the filesystem where leveldb data will be stored.
bool memory_only
If true, use leveldb's memory environment.
leveldb::Env * penv
custom environment this database is using (may be nullptr in case of default environment)
leveldb::ReadOptions iteroptions
options used when iterating over values of the database
leveldb::ReadOptions readoptions
options used when reading from the database
leveldb::Options options
database options used
leveldb::DB * pdb
the database itself
leveldb::WriteOptions syncoptions
options used when sync writing to the database
leveldb::WriteOptions writeoptions
options used when writing to the database