aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2012-09-03 19:05:30 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2012-10-20 23:08:56 +0200
commit43b7905e98d827df45e970dbaf5f08561ecc6cda (patch)
treea2f90a07dfd16e3a3ec1ae418e3f65a2f2177579 /src
parent3ff3a2bd60a905d830de157390facde14aa0ffe3 (diff)
LevelDB glue
Database-independent glue for supporting LevelDB databases. Based on code from earlier commits by Mike Hearn in his leveldb branch.
Diffstat (limited to 'src')
-rw-r--r--src/leveldb.cpp58
-rw-r--r--src/leveldb.h144
-rw-r--r--src/makefile.linux-mingw5
-rw-r--r--src/makefile.mingw3
-rw-r--r--src/makefile.osx3
-rw-r--r--src/makefile.unix3
6 files changed, 211 insertions, 5 deletions
diff --git a/src/leveldb.cpp b/src/leveldb.cpp
new file mode 100644
index 0000000000..29e5e6a7fd
--- /dev/null
+++ b/src/leveldb.cpp
@@ -0,0 +1,58 @@
+// Copyright (c) 2012 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "leveldb.h"
+#include "util.h"
+
+#include <leveldb/env.h>
+#include <leveldb/cache.h>
+#include <leveldb/filter_policy.h>
+
+#include <boost/filesystem.hpp>
+
+static leveldb::Options GetOptions() {
+ leveldb::Options options;
+ int nCacheSizeMB = GetArg("-dbcache", 25);
+ options.block_cache = leveldb::NewLRUCache(nCacheSizeMB * 1048576);
+ options.filter_policy = leveldb::NewBloomFilterPolicy(10);
+ options.compression = leveldb::kNoCompression;
+ return options;
+}
+
+CLevelDB::CLevelDB(const boost::filesystem::path &path) {
+ penv = NULL;
+ readoptions.verify_checksums = true;
+ iteroptions.verify_checksums = true;
+ iteroptions.fill_cache = false;
+ syncoptions.sync = true;
+ options = GetOptions();
+ options.create_if_missing = true;
+ boost::filesystem::create_directory(path);
+ printf("Opening LevelDB in %s\n", path.string().c_str());
+ leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
+ if (!status.ok())
+ throw std::runtime_error(strprintf("CLevelDB(): error opening database environment %s", status.ToString().c_str()));
+ printf("Opened LevelDB successfully\n");
+}
+
+CLevelDB::~CLevelDB() {
+ 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 CLevelDB::WriteBatch(CLevelDBBatch &batch, bool fSync) {
+ leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
+ if (!status.ok()) {
+ printf("LevelDB write failure: %s\n", status.ToString().c_str());
+ return false;
+ }
+ return true;
+}
+
diff --git a/src/leveldb.h b/src/leveldb.h
new file mode 100644
index 0000000000..28484dac9d
--- /dev/null
+++ b/src/leveldb.h
@@ -0,0 +1,144 @@
+// Copyright (c) 2012 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_LEVELDB_H
+#define BITCOIN_LEVELDB_H
+
+#include "serialize.h"
+
+#include <leveldb/db.h>
+#include <leveldb/write_batch.h>
+
+#include <boost/filesystem/path.hpp>
+
+// Batch of changes queued to be written to a CLevelDB
+class CLevelDBBatch
+{
+ friend class CLevelDB;
+
+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 CLevelDB
+{
+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:
+ CLevelDB(const boost::filesystem::path &path);
+ ~CLevelDB();
+
+ template<typename K, typename V> bool Read(const K& key, V& value) {
+ 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;
+ printf("LevelDB read failure: %s\n", status.ToString().c_str());
+ }
+ 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) {
+ CLevelDBBatch batch;
+ batch.Write(key, value);
+ return WriteBatch(batch, fSync);
+ }
+
+ template<typename K> bool Exists(const K& key) {
+ 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;
+ printf("LevelDB read failure: %s\n", status.ToString().c_str());
+ }
+ return true;
+ }
+
+ template<typename K> bool Erase(const K& key, bool fSync = false) {
+ CLevelDBBatch batch;
+ batch.Erase(key);
+ return WriteBatch(batch, fSync);
+ }
+
+ bool WriteBatch(CLevelDBBatch &batch, bool fSync = false);
+
+ // not available for LevelDB; provide for compatibility with BDB
+ bool Flush() {
+ return true;
+ }
+
+ bool Sync() {
+ 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_LEVELDB_H
+ \ No newline at end of file
diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw
index 8f8279c926..9bad54cb61 100644
--- a/src/makefile.linux-mingw
+++ b/src/makefile.linux-mingw
@@ -88,12 +88,13 @@ OBJS= \
all: bitcoind.exe
ifdef USE_LEVELDB
-LIBS += $(CURDIR)/leveldb/libleveldb.lib $(CURDIR)/leveldb/libmemenv.a
+LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
DEFS += -I"$(CURDIR)/leveldb/include" -DUSE_LEVELDB
DEFS += -I"$(CURDIR)/leveldb/helpers"
+OBJS += obj/leveldb.o
leveldb/libleveldb.a:
@echo "Building LevelDB ..."; cd leveldb; TARGET_OS=OS_WINDOWS_CROSSCOMPILE CXXFLAGS="-I$(INCLUDEPATHS)" LDFLAGS="-L$(LIBPATHS)" make libleveldb.a libmemenv.a; cd ..
-obj/db.o: leveldb/libleveldb.a
+obj/leveldb.o: leveldb/libleveldb.a
endif
obj/build.h: FORCE
diff --git a/src/makefile.mingw b/src/makefile.mingw
index e2560d9912..3953af3b0a 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -94,9 +94,10 @@ ifdef USE_LEVELDB
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
+OBJS += obj/leveldb.o
leveldb/libleveldb.a:
cd leveldb; make libleveldb.a libmemenv.a; cd ..
-obj/db.o: leveldb/libleveldb.lib
+obj/leveldb.o: leveldb/libleveldb.lib
endif
obj/%.o: %.cpp $(HEADERS)
diff --git a/src/makefile.osx b/src/makefile.osx
index bfda788410..618236521a 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -127,9 +127,10 @@ ifdef USE_LEVELDB
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
+OBJS += obj/leveldb.o
leveldb/libleveldb.a:
@echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..
-obj/db.o: leveldb/libleveldb.a
+obj/leveldb.o: leveldb/libleveldb.a
endif
# auto-generated dependencies:
diff --git a/src/makefile.unix b/src/makefile.unix
index 01b637e9c6..3fcefa1ea9 100644
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -143,9 +143,10 @@ ifdef USE_LEVELDB
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
+OBJS += obj/leveldb.o
leveldb/libleveldb.a:
@echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..;
-obj/db.o: leveldb/libleveldb.a
+obj/leveldb.o: leveldb/libleveldb.a
endif
# auto-generated dependencies: