123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- // 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
|