aboutsummaryrefslogtreecommitdiff
path: root/src/dbwrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dbwrapper.cpp')
-rw-r--r--src/dbwrapper.cpp89
1 files changed, 78 insertions, 11 deletions
diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp
index 94ebedeb72..dfc90f3ab9 100644
--- a/src/dbwrapper.cpp
+++ b/src/dbwrapper.cpp
@@ -4,16 +4,74 @@
#include "dbwrapper.h"
+#include "fs.h"
#include "util.h"
#include "random.h"
-#include <boost/filesystem.hpp>
-
#include <leveldb/cache.h>
#include <leveldb/env.h>
#include <leveldb/filter_policy.h>
#include <memenv.h>
#include <stdint.h>
+#include <algorithm>
+
+class CBitcoinLevelDBLogger : public leveldb::Logger {
+public:
+ // This code is adapted from posix_logger.h, which is why it is using vsprintf.
+ // Please do not do this in normal code
+ void Logv(const char * format, va_list ap) override {
+ if (!LogAcceptCategory(BCLog::LEVELDB)) {
+ return;
+ }
+ char buffer[500];
+ for (int iter = 0; iter < 2; iter++) {
+ char* base;
+ int bufsize;
+ if (iter == 0) {
+ bufsize = sizeof(buffer);
+ base = buffer;
+ }
+ else {
+ bufsize = 30000;
+ base = new char[bufsize];
+ }
+ char* p = base;
+ char* limit = base + bufsize;
+
+ // Print the message
+ if (p < limit) {
+ va_list backup_ap;
+ va_copy(backup_ap, ap);
+ // Do not use vsnprintf elsewhere in bitcoin source code, see above.
+ p += vsnprintf(p, limit - p, format, backup_ap);
+ va_end(backup_ap);
+ }
+
+ // Truncate to available space if necessary
+ if (p >= limit) {
+ if (iter == 0) {
+ continue; // Try again with larger buffer
+ }
+ else {
+ p = limit - 1;
+ }
+ }
+
+ // Add newline if necessary
+ if (p == base || p[-1] != '\n') {
+ *p++ = '\n';
+ }
+
+ assert(p <= limit);
+ base[std::min(bufsize - 1, (int)(p - base))] = '\0';
+ LogPrintStr(base);
+ if (base != buffer) {
+ delete[] base;
+ }
+ break;
+ }
+ }
+};
static leveldb::Options GetOptions(size_t nCacheSize)
{
@@ -23,6 +81,7 @@ static leveldb::Options GetOptions(size_t nCacheSize)
options.filter_policy = leveldb::NewBloomFilterPolicy(10);
options.compression = leveldb::kNoCompression;
options.max_open_files = 64;
+ options.info_log = new CBitcoinLevelDBLogger();
if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) {
// LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error
// on corruption in later versions.
@@ -31,9 +90,9 @@ static leveldb::Options GetOptions(size_t nCacheSize)
return options;
}
-CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate)
+CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate)
{
- penv = NULL;
+ penv = nullptr;
readoptions.verify_checksums = true;
iteroptions.verify_checksums = true;
iteroptions.fill_cache = false;
@@ -49,13 +108,19 @@ CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, b
leveldb::Status result = leveldb::DestroyDB(path.string(), options);
dbwrapper_private::HandleError(result);
}
- TryCreateDirectory(path);
+ TryCreateDirectories(path);
LogPrintf("Opening LevelDB in %s\n", path.string());
}
leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
dbwrapper_private::HandleError(status);
LogPrintf("Opened LevelDB successfully\n");
+ if (gArgs.GetBoolArg("-forcecompactdb", false)) {
+ LogPrintf("Starting database compaction of %s\n", path.string());
+ pdb->CompactRange(nullptr, nullptr);
+ LogPrintf("Finished database compaction of %s\n", path.string());
+ }
+
// The base-case obfuscation key, which is a noop.
obfuscate_key = std::vector<unsigned char>(OBFUSCATE_KEY_NUM_BYTES, '\000');
@@ -79,13 +144,15 @@ CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, b
CDBWrapper::~CDBWrapper()
{
delete pdb;
- pdb = NULL;
+ pdb = nullptr;
delete options.filter_policy;
- options.filter_policy = NULL;
+ options.filter_policy = nullptr;
+ delete options.info_log;
+ options.info_log = nullptr;
delete options.block_cache;
- options.block_cache = NULL;
+ options.block_cache = nullptr;
delete penv;
- options.env = NULL;
+ options.env = nullptr;
}
bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync)
@@ -123,7 +190,7 @@ bool CDBWrapper::IsEmpty()
}
CDBIterator::~CDBIterator() { delete piter; }
-bool CDBIterator::Valid() { return piter->Valid(); }
+bool CDBIterator::Valid() const { return piter->Valid(); }
void CDBIterator::SeekToFirst() { piter->SeekToFirst(); }
void CDBIterator::Next() { piter->Next(); }
@@ -148,4 +215,4 @@ const std::vector<unsigned char>& GetObfuscateKey(const CDBWrapper &w)
return w.obfuscate_key;
}
-};
+} // namespace dbwrapper_private