diff options
Diffstat (limited to 'src/dbwrapper.cpp')
| -rw-r--r-- | src/dbwrapper.cpp | 89 |
1 files changed, 78 insertions, 11 deletions
diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 94ebedeb7..dfc90f3ab 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 |