dogecoin/src/leveldbwrapper.h
Daniel Kraft ffb4c210bc Mark LevelDB "Read" and "Exists" functions as const.
Mark the "Read" and "Exists" functions in CLevelDBWrapper as "const".
They do not change anything in the DB, by definition.
2014-08-26 11:26:58 +02:00

156 lines
4.6 KiB
C++

// Copyright (c) 2012-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_LEVELDBWRAPPER_H
#define BITCOIN_LEVELDBWRAPPER_H
#include "serialize.h"
#include "util.h"
#include "version.h"
#include <boost/filesystem/path.hpp>
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
class leveldb_error : public std::runtime_error
{
public:
leveldb_error(const std::string &msg) : std::runtime_error(msg) {}
};
void HandleError(const leveldb::Status &status) throw(leveldb_error);
// Batch of changes queued to be written to a CLevelDBWrapper
class CLevelDBBatch
{
friend class CLevelDBWrapper;
private:
leveldb::WriteBatch batch;
public:
template<typename K, typename V> void Write(const K& key, const V& value) {
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) {
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(ssKey.GetSerializeSize(key));
ssKey << key;
leveldb::Slice slKey(&ssKey[0], ssKey.size());
batch.Delete(slKey);
}
};
class CLevelDBWrapper
{
private:
// custom environment this database is using (may be NULL in case of default environment)
leveldb::Env *penv;
// database options used
leveldb::Options options;
// options used when reading from the database
leveldb::ReadOptions readoptions;
// options used when iterating over values of the database
leveldb::ReadOptions iteroptions;
// options used when writing to the database
leveldb::WriteOptions writeoptions;
// options used when sync writing to the database
leveldb::WriteOptions syncoptions;
// the database itself
leveldb::DB *pdb;
public:
CLevelDBWrapper(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
~CLevelDBWrapper();
template<typename K, typename V> bool Read(const K& key, V& value) const throw(leveldb_error) {
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;
LogPrintf("LevelDB read failure: %s\n", status.ToString());
HandleError(status);
}
try {
CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
ssValue >> value;
} catch(std::exception &e) {
return false;
}
return true;
}
template<typename K, typename V> bool Write(const K& key, const V& value, bool fSync = false) throw(leveldb_error) {
CLevelDBBatch batch;
batch.Write(key, value);
return WriteBatch(batch, fSync);
}
template<typename K> bool Exists(const K& key) const throw(leveldb_error) {
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;
LogPrintf("LevelDB read failure: %s\n", status.ToString());
HandleError(status);
}
return true;
}
template<typename K> bool Erase(const K& key, bool fSync = false) throw(leveldb_error) {
CLevelDBBatch batch;
batch.Erase(key);
return WriteBatch(batch, fSync);
}
bool WriteBatch(CLevelDBBatch &batch, bool fSync = false) throw(leveldb_error);
// not available for LevelDB; provide for compatibility with BDB
bool Flush() {
return true;
}
bool Sync() throw(leveldb_error) {
CLevelDBBatch batch;
return WriteBatch(batch, true);
}
// not exactly clean encapsulation, but it's easiest for now
leveldb::Iterator *NewIterator() {
return pdb->NewIterator(iteroptions);
}
};
#endif // BITCOIN_LEVELDBWRAPPER_H