Files
thehub/hub/server/dbwrapper.h
T

256 lines
7.0 KiB
C++
Raw Permalink Normal View History

2017-11-09 19:34:51 +01:00
/*
* This file is part of the Flowee project
* Copyright (C) 2012-2015 The Bitcoin Core developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2018-01-16 10:47:52 +00:00
#ifndef FLOWEE_DBWRAPPER_H
#define FLOWEE_DBWRAPPER_H
2012-09-03 19:05:30 +02:00
#include "clientversion.h"
2012-09-03 19:05:30 +02:00
#include "serialize.h"
#include "streaming/streams.h"
#include "utilstrencodings.h"
2012-09-03 19:05:30 +02:00
#include <boost/filesystem/path.hpp>
2014-09-14 12:43:56 +02:00
2013-04-13 00:13:08 -05:00
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
2012-09-03 19:05:30 +02:00
class dbwrapper_error : public std::runtime_error
2013-01-29 01:44:19 +01:00
{
public:
dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {}
2013-01-29 01:44:19 +01:00
};
void HandleError(const leveldb::Status& status) throw(dbwrapper_error);
2013-01-29 01:44:19 +01:00
/** Batch of changes queued to be written to a CDBWrapper */
class CDBBatch
2012-09-03 19:05:30 +02:00
{
friend class CDBWrapper;
2012-09-03 19:05:30 +02:00
private:
leveldb::WriteBatch batch;
public:
template <typename K, typename V>
void Write(const K& key, const V& value)
{
2012-09-03 19:05:30 +02:00
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(ssKey.GetSerializeSize(key));
ssKey << key;
leveldb::Slice slKey(&ssKey[0], ssKey.size());
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
ssValue.reserve(ssValue.GetSerializeSize(value));
ssValue << value;
leveldb::Slice slValue(&ssValue[0], ssValue.size());
batch.Put(slKey, slValue);
}
template <typename K>
void Erase(const K& key)
{
2012-09-03 19:05:30 +02:00
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(ssKey.GetSerializeSize(key));
ssKey << key;
leveldb::Slice slKey(&ssKey[0], ssKey.size());
batch.Delete(slKey);
}
};
class CDBIterator
2015-10-07 17:12:24 -07:00
{
private:
leveldb::Iterator *piter;
2012-09-03 19:05:30 +02:00
2015-10-07 17:12:24 -07:00
public:
2015-10-08 00:44:10 -07:00
/**
* @param[in] piterIn The original leveldb iterator.
*/
2018-11-02 20:42:45 +01:00
CDBIterator(leveldb::Iterator *piterIn) : piter(piterIn) { }
~CDBIterator();
2015-10-07 17:12:24 -07:00
bool Valid();
void SeekToFirst();
template<typename K> void Seek(const K& key) {
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(ssKey.GetSerializeSize(key));
ssKey << key;
leveldb::Slice slKey(&ssKey[0], ssKey.size());
piter->Seek(slKey);
}
void Next();
template<typename K> bool GetKey(K& key) {
leveldb::Slice slKey = piter->key();
try {
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
ssKey >> key;
2015-10-27 17:39:42 +01:00
} catch (const std::exception&) {
2015-10-07 17:12:24 -07:00
return false;
}
return true;
}
unsigned int GetKeySize() {
return piter->key().size();
}
template<typename V> bool GetValue(V& value) {
leveldb::Slice slValue = piter->value();
try {
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
ssValue >> value;
2015-10-27 17:39:42 +01:00
} catch (const std::exception&) {
2015-10-07 17:12:24 -07:00
return false;
}
return true;
}
unsigned int GetValueSize() {
return piter->value().size();
}
};
class CDBWrapper
2012-09-03 19:05:30 +02:00
{
private:
//! custom environment this database is using (may be NULL in case of default environment)
leveldb::Env* penv;
2012-09-03 19:05:30 +02:00
//! database options used
2012-09-03 19:05:30 +02:00
leveldb::Options options;
//! options used when reading from the database
2012-09-03 19:05:30 +02:00
leveldb::ReadOptions readoptions;
//! options used when iterating over values of the database
2012-09-03 19:05:30 +02:00
leveldb::ReadOptions iteroptions;
//! options used when writing to the database
2012-09-03 19:05:30 +02:00
leveldb::WriteOptions writeoptions;
//! options used when sync writing to the database
2012-09-03 19:05:30 +02:00
leveldb::WriteOptions syncoptions;
//! the database itself
leveldb::DB* pdb;
2012-09-03 19:05:30 +02:00
public:
/**
* @param[in] path Location in the filesystem where leveldb data will be stored.
* @param[in] nCacheSize Configures various leveldb cache settings.
* @param[in] fMemory If true, use leveldb's memory environment.
* @param[in] fWipe If true, remove all existing data.
*/
2018-11-02 20:42:45 +01:00
CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
~CDBWrapper();
2012-09-03 19:05:30 +02:00
template <typename K, typename V>
bool Read(const K& key, V& value) const throw(dbwrapper_error)
{
2012-09-03 19:05:30 +02:00
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(ssKey.GetSerializeSize(key));
ssKey << key;
leveldb::Slice slKey(&ssKey[0], ssKey.size());
std::string strValue;
leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
if (!status.ok()) {
if (status.IsNotFound())
return false;
2019-08-24 13:20:37 +02:00
logCritical(Log::DB) << "LevelDB read failure:" << status.ToString();
2013-01-29 01:44:19 +01:00
HandleError(status);
2012-09-03 19:05:30 +02:00
}
try {
CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
ssValue >> value;
} catch (const std::exception&) {
2012-09-03 19:05:30 +02:00
return false;
}
return true;
}
template <typename K, typename V>
bool Write(const K& key, const V& value, bool fSync = false) throw(dbwrapper_error)
{
2018-11-02 20:42:45 +01:00
CDBBatch batch;
2012-09-03 19:05:30 +02:00
batch.Write(key, value);
return WriteBatch(batch, fSync);
}
template <typename K>
bool Exists(const K& key) const throw(dbwrapper_error)
{
2012-09-03 19:05:30 +02:00
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(ssKey.GetSerializeSize(key));
ssKey << key;
leveldb::Slice slKey(&ssKey[0], ssKey.size());
std::string strValue;
leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
if (!status.ok()) {
if (status.IsNotFound())
return false;
2019-08-24 13:20:37 +02:00
logCritical(Log::DB) << "LevelDB read failure:" << status.ToString();
2013-01-29 01:44:19 +01:00
HandleError(status);
2012-09-03 19:05:30 +02:00
}
return true;
}
template <typename K>
bool Erase(const K& key, bool fSync = false) throw(dbwrapper_error)
{
2018-11-02 20:42:45 +01:00
CDBBatch batch;
2012-09-03 19:05:30 +02:00
batch.Erase(key);
return WriteBatch(batch, fSync);
}
bool WriteBatch(CDBBatch& batch, bool fSync = false) throw(dbwrapper_error);
2012-09-03 19:05:30 +02:00
// not available for LevelDB; provide for compatibility with BDB
bool Flush()
{
2012-09-03 19:05:30 +02:00
return true;
}
bool Sync() throw(dbwrapper_error)
{
2018-11-02 20:42:45 +01:00
CDBBatch batch;
2012-09-03 19:05:30 +02:00
return WriteBatch(batch, true);
}
CDBIterator *NewIterator()
2015-10-07 17:12:24 -07:00
{
2018-11-02 20:42:45 +01:00
return new CDBIterator(pdb->NewIterator(iteroptions));
2015-10-08 00:44:10 -07:00
}
/**
* Return true if the database managed by this class contains no entries.
*/
bool IsEmpty();
2012-09-03 19:05:30 +02:00
};
2018-01-16 10:47:52 +00:00
#endif