LevelDB glue
Database-independent glue for supporting LevelDB databases. Based on code from earlier commits by Mike Hearn in his leveldb branch.
This commit is contained in:
parent
3ff3a2bd60
commit
43b7905e98
7 changed files with 212 additions and 5 deletions
|
@ -97,6 +97,7 @@ contains(USE_LEVELDB, -) {
|
||||||
DEFINES += USE_LEVELDB
|
DEFINES += USE_LEVELDB
|
||||||
INCLUDEPATH += src/leveldb/include src/leveldb/helpers
|
INCLUDEPATH += src/leveldb/include src/leveldb/helpers
|
||||||
LIBS += $$PWD/src/leveldb/libleveldb.a $$PWD/src/leveldb/libmemenv.a
|
LIBS += $$PWD/src/leveldb/libleveldb.a $$PWD/src/leveldb/libmemenv.a
|
||||||
|
SOURCES += src/leveldb.cpp
|
||||||
!windows {
|
!windows {
|
||||||
genleveldb.commands = cd $$PWD/src/leveldb ; $(MAKE) libleveldb.a libmemenv.a
|
genleveldb.commands = cd $$PWD/src/leveldb ; $(MAKE) libleveldb.a libmemenv.a
|
||||||
} else {
|
} else {
|
||||||
|
|
58
src/leveldb.cpp
Normal file
58
src/leveldb.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
144
src/leveldb.h
Normal file
144
src/leveldb.h
Normal file
|
@ -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
|
||||||
|
|
|
@ -88,12 +88,13 @@ OBJS= \
|
||||||
all: bitcoind.exe
|
all: bitcoind.exe
|
||||||
|
|
||||||
ifdef USE_LEVELDB
|
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/include" -DUSE_LEVELDB
|
||||||
DEFS += -I"$(CURDIR)/leveldb/helpers"
|
DEFS += -I"$(CURDIR)/leveldb/helpers"
|
||||||
|
OBJS += obj/leveldb.o
|
||||||
leveldb/libleveldb.a:
|
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 ..
|
@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
|
endif
|
||||||
|
|
||||||
obj/build.h: FORCE
|
obj/build.h: FORCE
|
||||||
|
|
|
@ -94,9 +94,10 @@ ifdef USE_LEVELDB
|
||||||
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
|
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
|
||||||
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB
|
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB
|
||||||
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
|
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
|
||||||
|
OBJS += obj/leveldb.o
|
||||||
leveldb/libleveldb.a:
|
leveldb/libleveldb.a:
|
||||||
cd leveldb; make libleveldb.a libmemenv.a; cd ..
|
cd leveldb; make libleveldb.a libmemenv.a; cd ..
|
||||||
obj/db.o: leveldb/libleveldb.lib
|
obj/leveldb.o: leveldb/libleveldb.lib
|
||||||
endif
|
endif
|
||||||
|
|
||||||
obj/%.o: %.cpp $(HEADERS)
|
obj/%.o: %.cpp $(HEADERS)
|
||||||
|
|
|
@ -127,9 +127,10 @@ ifdef USE_LEVELDB
|
||||||
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
|
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
|
||||||
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB
|
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB
|
||||||
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
|
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
|
||||||
|
OBJS += obj/leveldb.o
|
||||||
leveldb/libleveldb.a:
|
leveldb/libleveldb.a:
|
||||||
@echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..
|
@echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..
|
||||||
obj/db.o: leveldb/libleveldb.a
|
obj/leveldb.o: leveldb/libleveldb.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# auto-generated dependencies:
|
# auto-generated dependencies:
|
||||||
|
|
|
@ -143,9 +143,10 @@ ifdef USE_LEVELDB
|
||||||
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
|
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
|
||||||
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB
|
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB
|
||||||
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
|
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
|
||||||
|
OBJS += obj/leveldb.o
|
||||||
leveldb/libleveldb.a:
|
leveldb/libleveldb.a:
|
||||||
@echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..;
|
@echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..;
|
||||||
obj/db.o: leveldb/libleveldb.a
|
obj/leveldb.o: leveldb/libleveldb.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# auto-generated dependencies:
|
# auto-generated dependencies:
|
||||||
|
|
Loading…
Reference in a new issue