21#include <leveldb/cache.h>
22#include <leveldb/db.h>
23#include <leveldb/env.h>
24#include <leveldb/filter_policy.h>
25#include <leveldb/helpers/memenv/memenv.h>
26#include <leveldb/iterator.h>
27#include <leveldb/options.h>
28#include <leveldb/slice.h>
29#include <leveldb/status.h>
30#include <leveldb/write_batch.h>
35static auto CharCast(
const std::byte*
data) {
return reinterpret_cast<const char*
>(
data); }
48 const std::string errmsg =
"Fatal LevelDB error: " + status.ToString();
50 LogPrintf(
"You can use -debug=leveldb to get more complete diagnostic messages\n");
63 for (
int iter = 0; iter < 2; iter++) {
67 bufsize =
sizeof(buffer);
72 base =
new char[bufsize];
75 char* limit = base + bufsize;
80 va_copy(backup_ap, ap);
82 p += vsnprintf(p, limit - p,
format, backup_ap);
97 if (p == base || p[-1] !=
'\n') {
102 base[std::min(bufsize - 1, (
int)(p - base))] =
'\0';
104 if (base != buffer) {
127 int default_open_files = options->max_open_files;
129 if (
sizeof(
void*) < 8) {
130 options->max_open_files = 64;
134 options->max_open_files, default_open_files);
139 leveldb::Options options;
140 options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
141 options.write_buffer_size = nCacheSize / 4;
142 options.filter_policy = leveldb::NewBloomFilterPolicy(10);
143 options.compression = leveldb::kNoCompression;
145 if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) {
148 options.paranoid_checks =
true;
184 size_estimate += 3 + (slKey.size() > 127) + slKey.size() + (slValue.size() > 127) + slValue.size();
226 DBContext().readoptions.verify_checksums =
true;
227 DBContext().iteroptions.verify_checksums =
true;
228 DBContext().iteroptions.fill_cache =
false;
231 DBContext().options.create_if_missing =
true;
233 DBContext().penv = leveldb::NewMemEnv(leveldb::Env::Default());
250 LogPrintf(
"Opened LevelDB successfully\n");
254 DBContext().pdb->CompactRange(
nullptr,
nullptr);
282 delete DBContext().options.filter_policy;
283 DBContext().options.filter_policy =
nullptr;
287 DBContext().options.block_cache =
nullptr;
295 double mem_before = 0;
304 m_name, mem_before, mem_after);
312 std::optional<size_t> parsed;
313 if (!
DBContext().pdb->GetProperty(
"leveldb.approximate-memory-usage", &memory) || !(parsed = ToIntegral<size_t>(memory))) {
317 return parsed.value();
342 std::string strValue;
343 leveldb::Status status =
DBContext().pdb->Get(
DBContext().readoptions, slKey, &strValue);
345 if (status.IsNotFound())
347 LogPrintf(
"LevelDB read failure: %s\n", status.ToString());
357 std::string strValue;
358 leveldb::Status status =
DBContext().pdb->Get(
DBContext().readoptions, slKey, &strValue);
360 if (status.IsNotFound())
362 LogPrintf(
"LevelDB read failure: %s\n", status.ToString());
373 leveldb::Range range(slKey1, slKey2);
374 DBContext().pdb->GetApproximateSizes(&range, 1, &size);
382 return !(it->Valid());
386 const std::unique_ptr<leveldb::Iterator>
iter;
392 m_impl_iter(
std::move(_piter)) {}
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 WriteBatch(CDBBatch &batch, bool fSync=false)
bool Read(const K &key, V &value) const
CDBIterator * NewIterator()
std::string m_name
the name of this database
bool Write(const K &key, const V &value, bool fSync=false)
std::vector< unsigned char > 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
std::optional< std::string > ReadImpl(Span< const std::byte > key) const
std::vector< unsigned char > CreateObfuscateKey() const
Returns a string (consisting of 8 random bytes) suitable for use as an obfuscating XOR key.
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< unsigned char > &key)
XOR the contents of this stream with a certain key.
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.
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< unsigned char > & 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 a byte string.
std::string_view RemoveSuffixView(std::string_view str, std::string_view suffix)
void GetRandBytes(Span< unsigned char > bytes) noexcept
Generate random data via the internal PRNG.
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