Any projects which want to use Hush code from now on will need to be licensed as GPLv3 or we will send the lawyers: https://www.softwarefreedom.org/ Notably, Komodo (KMD) is licensed as GPLv2 and is no longer compatible to receive code changes, without causing legal issues. MIT projects, such as Zcash, also cannot pull in changes from the Hush Full Node without permission from The Hush Developers, which may in some circumstances grant an MIT license on a case-by-case basis.
110 lines
3.6 KiB
C++
110 lines
3.6 KiB
C++
// Copyright (c) 2012-2014 The Bitcoin Core developers
|
|
// Copyright (c) 2019-2020 The Hush developers
|
|
// Distributed under the GPLv3 software license, see the accompanying
|
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
|
|
#include "dbwrapper.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include <boost/filesystem.hpp>
|
|
|
|
#include <leveldb/cache.h>
|
|
#include <leveldb/env.h>
|
|
#include <leveldb/filter_policy.h>
|
|
#include <memenv.h>
|
|
#include <stdint.h>
|
|
|
|
static leveldb::Options GetOptions(size_t nCacheSize, bool compression, int maxOpenFiles)
|
|
{
|
|
leveldb::Options options;
|
|
options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
|
|
options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously
|
|
options.filter_policy = leveldb::NewBloomFilterPolicy(10);
|
|
options.compression = compression ? leveldb::kSnappyCompression : leveldb::kNoCompression;
|
|
options.max_open_files = maxOpenFiles;
|
|
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.
|
|
options.paranoid_checks = true;
|
|
}
|
|
return options;
|
|
}
|
|
|
|
CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool compression, int maxOpenFiles)
|
|
{
|
|
penv = NULL;
|
|
readoptions.verify_checksums = true;
|
|
iteroptions.verify_checksums = true;
|
|
iteroptions.fill_cache = false;
|
|
syncoptions.sync = true;
|
|
options = GetOptions(nCacheSize, compression, maxOpenFiles);
|
|
options.create_if_missing = true;
|
|
if (fMemory) {
|
|
penv = leveldb::NewMemEnv(leveldb::Env::Default());
|
|
options.env = penv;
|
|
} else {
|
|
if (fWipe) {
|
|
LogPrintf("Wiping LevelDB in %s\n", path.string());
|
|
leveldb::Status result = leveldb::DestroyDB(path.string(), options);
|
|
dbwrapper_private::HandleError(result);
|
|
}
|
|
TryCreateDirectory(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");
|
|
}
|
|
|
|
CDBWrapper::~CDBWrapper()
|
|
{
|
|
delete pdb;
|
|
pdb = NULL;
|
|
delete options.filter_policy;
|
|
options.filter_policy = NULL;
|
|
delete options.block_cache;
|
|
options.block_cache = NULL;
|
|
delete penv;
|
|
options.env = NULL;
|
|
}
|
|
|
|
bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync)
|
|
{
|
|
leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
|
|
dbwrapper_private::HandleError(status);
|
|
return true;
|
|
}
|
|
|
|
bool CDBWrapper::IsEmpty()
|
|
{
|
|
boost::scoped_ptr<CDBIterator> it(NewIterator());
|
|
it->SeekToFirst();
|
|
return !(it->Valid());
|
|
}
|
|
|
|
CDBIterator::~CDBIterator() { delete piter; }
|
|
bool CDBIterator::Valid() { return piter->Valid(); }
|
|
void CDBIterator::SeekToFirst() { piter->SeekToFirst(); }
|
|
void CDBIterator::SeekToLast() { piter->SeekToLast(); }
|
|
void CDBIterator::Next() { piter->Next(); }
|
|
void CDBIterator::Prev() { piter->Prev(); }
|
|
|
|
namespace dbwrapper_private {
|
|
|
|
void HandleError(const leveldb::Status& status)
|
|
{
|
|
if (status.ok())
|
|
return;
|
|
LogPrintf("%s\n", status.ToString());
|
|
if (status.IsCorruption())
|
|
throw dbwrapper_error("Database corrupted");
|
|
if (status.IsIOError())
|
|
throw dbwrapper_error("Database I/O error");
|
|
if (status.IsNotFound())
|
|
throw dbwrapper_error("Database entry missing");
|
|
throw dbwrapper_error("Unknown database error");
|
|
}
|
|
|
|
};
|