1 // Copyright (c) 2012-2014 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 #ifndef BITCOIN_LEVELDBWRAPPER_H
6 #define BITCOIN_LEVELDBWRAPPER_H
8 #include "clientversion.h"
14 #include <boost/filesystem/path.hpp>
16 #include <leveldb/db.h>
17 #include <leveldb/write_batch.h>
19 class leveldb_error
: public std::runtime_error
22 leveldb_error(const std::string
& msg
) : std::runtime_error(msg
) {}
25 void HandleError(const leveldb::Status
& status
) throw(leveldb_error
);
27 /** Batch of changes queued to be written to a CLevelDBWrapper */
30 friend class CLevelDBWrapper
;
33 leveldb::WriteBatch batch
;
36 template <typename K
, typename V
>
37 void Write(const K
& key
, const V
& value
)
39 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
40 ssKey
.reserve(ssKey
.GetSerializeSize(key
));
42 leveldb::Slice
slKey(&ssKey
[0], ssKey
.size());
44 CDataStream
ssValue(SER_DISK
, CLIENT_VERSION
);
45 ssValue
.reserve(ssValue
.GetSerializeSize(value
));
47 leveldb::Slice
slValue(&ssValue
[0], ssValue
.size());
49 batch
.Put(slKey
, slValue
);
53 void Erase(const K
& key
)
55 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
56 ssKey
.reserve(ssKey
.GetSerializeSize(key
));
58 leveldb::Slice
slKey(&ssKey
[0], ssKey
.size());
67 //! custom environment this database is using (may be NULL in case of default environment)
70 //! database options used
71 leveldb::Options options
;
73 //! options used when reading from the database
74 leveldb::ReadOptions readoptions
;
76 //! options used when iterating over values of the database
77 leveldb::ReadOptions iteroptions
;
79 //! options used when writing to the database
80 leveldb::WriteOptions writeoptions
;
82 //! options used when sync writing to the database
83 leveldb::WriteOptions syncoptions
;
85 //! the database itself
89 CLevelDBWrapper(const boost::filesystem::path
& path
, size_t nCacheSize
, bool fMemory
= false, bool fWipe
= false);
92 template <typename K
, typename V
>
93 bool Read(const K
& key
, V
& value
) const throw(leveldb_error
)
95 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
96 ssKey
.reserve(ssKey
.GetSerializeSize(key
));
98 leveldb::Slice
slKey(&ssKey
[0], ssKey
.size());
100 std::string strValue
;
101 leveldb::Status status
= pdb
->Get(readoptions
, slKey
, &strValue
);
103 if (status
.IsNotFound())
105 LogPrintf("LevelDB read failure: %s\n", status
.ToString());
109 CDataStream
ssValue(strValue
.data(), strValue
.data() + strValue
.size(), SER_DISK
, CLIENT_VERSION
);
111 } catch (const std::exception
&) {
117 template <typename K
, typename V
>
118 bool Write(const K
& key
, const V
& value
, bool fSync
= false) throw(leveldb_error
)
121 batch
.Write(key
, value
);
122 return WriteBatch(batch
, fSync
);
125 template <typename K
>
126 bool Exists(const K
& key
) const throw(leveldb_error
)
128 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
129 ssKey
.reserve(ssKey
.GetSerializeSize(key
));
131 leveldb::Slice
slKey(&ssKey
[0], ssKey
.size());
133 std::string strValue
;
134 leveldb::Status status
= pdb
->Get(readoptions
, slKey
, &strValue
);
136 if (status
.IsNotFound())
138 LogPrintf("LevelDB read failure: %s\n", status
.ToString());
144 template <typename K
>
145 bool Erase(const K
& key
, bool fSync
= false) throw(leveldb_error
)
149 return WriteBatch(batch
, fSync
);
152 bool WriteBatch(CLevelDBBatch
& batch
, bool fSync
= false) throw(leveldb_error
);
154 // not available for LevelDB; provide for compatibility with BDB
160 bool Sync() throw(leveldb_error
)
163 return WriteBatch(batch
, true);
166 // not exactly clean encapsulation, but it's easiest for now
167 leveldb::Iterator
* NewIterator()
169 return pdb
->NewIterator(iteroptions
);
173 #endif // BITCOIN_LEVELDBWRAPPER_H