aboutsummaryrefslogtreecommitdiff
path: root/src/leveldbwrapper.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/leveldbwrapper.h')
-rw-r--r--src/leveldbwrapper.h155
1 files changed, 155 insertions, 0 deletions
diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h
new file mode 100644
index 0000000000..53e9e439bd
--- /dev/null
+++ b/src/leveldbwrapper.h
@@ -0,0 +1,155 @@
+// 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) 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().c_str());
+ 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) 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().c_str());
+ 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