]>
Commit | Line | Data |
---|---|---|
f914f1a7 | 1 | // Copyright (c) 2012-2014 The Bitcoin Core developers |
fa94b9d5 | 2 | // Distributed under the MIT software license, see the accompanying |
43b7905e | 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
b64187d0 BD |
4 | |
5 | #ifndef BITCOIN_LEVELDBWRAPPER_H | |
6 | #define BITCOIN_LEVELDBWRAPPER_H | |
43b7905e | 7 | |
71697f97 | 8 | #include "clientversion.h" |
43b7905e | 9 | #include "serialize.h" |
fa736190 | 10 | #include "streams.h" |
881a85a2 | 11 | #include "util.h" |
51ed9ec9 | 12 | #include "version.h" |
43b7905e | 13 | |
51ed9ec9 | 14 | #include <boost/filesystem/path.hpp> |
611116d4 | 15 | |
43b7905e PW |
16 | #include <leveldb/db.h> |
17 | #include <leveldb/write_batch.h> | |
18 | ||
421218d3 PW |
19 | class leveldb_error : public std::runtime_error |
20 | { | |
21 | public: | |
20e01b1a | 22 | leveldb_error(const std::string& msg) : std::runtime_error(msg) {} |
421218d3 PW |
23 | }; |
24 | ||
ecd04e91 | 25 | void HandleError(const leveldb::Status& status); |
421218d3 | 26 | |
fa94b9d5 | 27 | /** Batch of changes queued to be written to a CLevelDBWrapper */ |
43b7905e PW |
28 | class CLevelDBBatch |
29 | { | |
b64187d0 | 30 | friend class CLevelDBWrapper; |
43b7905e PW |
31 | |
32 | private: | |
33 | leveldb::WriteBatch batch; | |
34 | ||
35 | public: | |
20e01b1a PW |
36 | template <typename K, typename V> |
37 | void Write(const K& key, const V& value) | |
38 | { | |
43b7905e PW |
39 | CDataStream ssKey(SER_DISK, CLIENT_VERSION); |
40 | ssKey.reserve(ssKey.GetSerializeSize(key)); | |
41 | ssKey << key; | |
42 | leveldb::Slice slKey(&ssKey[0], ssKey.size()); | |
43 | ||
44 | CDataStream ssValue(SER_DISK, CLIENT_VERSION); | |
45 | ssValue.reserve(ssValue.GetSerializeSize(value)); | |
46 | ssValue << value; | |
47 | leveldb::Slice slValue(&ssValue[0], ssValue.size()); | |
48 | ||
49 | batch.Put(slKey, slValue); | |
50 | } | |
51 | ||
20e01b1a PW |
52 | template <typename K> |
53 | void Erase(const K& key) | |
54 | { | |
43b7905e PW |
55 | CDataStream ssKey(SER_DISK, CLIENT_VERSION); |
56 | ssKey.reserve(ssKey.GetSerializeSize(key)); | |
57 | ssKey << key; | |
58 | leveldb::Slice slKey(&ssKey[0], ssKey.size()); | |
59 | ||
60 | batch.Delete(slKey); | |
61 | } | |
62 | }; | |
63 | ||
b64187d0 | 64 | class CLevelDBWrapper |
43b7905e PW |
65 | { |
66 | private: | |
fa94b9d5 | 67 | //! custom environment this database is using (may be NULL in case of default environment) |
20e01b1a | 68 | leveldb::Env* penv; |
43b7905e | 69 | |
fa94b9d5 | 70 | //! database options used |
43b7905e PW |
71 | leveldb::Options options; |
72 | ||
fa94b9d5 | 73 | //! options used when reading from the database |
43b7905e PW |
74 | leveldb::ReadOptions readoptions; |
75 | ||
fa94b9d5 | 76 | //! options used when iterating over values of the database |
43b7905e PW |
77 | leveldb::ReadOptions iteroptions; |
78 | ||
fa94b9d5 | 79 | //! options used when writing to the database |
43b7905e PW |
80 | leveldb::WriteOptions writeoptions; |
81 | ||
fa94b9d5 | 82 | //! options used when sync writing to the database |
43b7905e PW |
83 | leveldb::WriteOptions syncoptions; |
84 | ||
fa94b9d5 | 85 | //! the database itself |
20e01b1a | 86 | leveldb::DB* pdb; |
43b7905e PW |
87 | |
88 | public: | |
20e01b1a | 89 | CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false); |
b64187d0 | 90 | ~CLevelDBWrapper(); |
43b7905e | 91 | |
20e01b1a | 92 | template <typename K, typename V> |
ecd04e91 | 93 | bool Read(const K& key, V& value) const |
20e01b1a | 94 | { |
43b7905e PW |
95 | CDataStream ssKey(SER_DISK, CLIENT_VERSION); |
96 | ssKey.reserve(ssKey.GetSerializeSize(key)); | |
97 | ssKey << key; | |
98 | leveldb::Slice slKey(&ssKey[0], ssKey.size()); | |
99 | ||
100 | std::string strValue; | |
101 | leveldb::Status status = pdb->Get(readoptions, slKey, &strValue); | |
102 | if (!status.ok()) { | |
103 | if (status.IsNotFound()) | |
104 | return false; | |
79d06dc6 | 105 | LogPrintf("LevelDB read failure: %s\n", status.ToString()); |
421218d3 | 106 | HandleError(status); |
43b7905e PW |
107 | } |
108 | try { | |
109 | CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION); | |
110 | ssValue >> value; | |
20e01b1a | 111 | } catch (const std::exception&) { |
43b7905e PW |
112 | return false; |
113 | } | |
114 | return true; | |
115 | } | |
116 | ||
20e01b1a | 117 | template <typename K, typename V> |
ecd04e91 | 118 | bool Write(const K& key, const V& value, bool fSync = false) |
20e01b1a | 119 | { |
43b7905e PW |
120 | CLevelDBBatch batch; |
121 | batch.Write(key, value); | |
122 | return WriteBatch(batch, fSync); | |
123 | } | |
124 | ||
20e01b1a | 125 | template <typename K> |
ecd04e91 | 126 | bool Exists(const K& key) const |
20e01b1a | 127 | { |
43b7905e PW |
128 | CDataStream ssKey(SER_DISK, CLIENT_VERSION); |
129 | ssKey.reserve(ssKey.GetSerializeSize(key)); | |
130 | ssKey << key; | |
131 | leveldb::Slice slKey(&ssKey[0], ssKey.size()); | |
132 | ||
133 | std::string strValue; | |
134 | leveldb::Status status = pdb->Get(readoptions, slKey, &strValue); | |
135 | if (!status.ok()) { | |
136 | if (status.IsNotFound()) | |
137 | return false; | |
79d06dc6 | 138 | LogPrintf("LevelDB read failure: %s\n", status.ToString()); |
421218d3 | 139 | HandleError(status); |
43b7905e PW |
140 | } |
141 | return true; | |
142 | } | |
143 | ||
20e01b1a | 144 | template <typename K> |
ecd04e91 | 145 | bool Erase(const K& key, bool fSync = false) |
20e01b1a | 146 | { |
43b7905e PW |
147 | CLevelDBBatch batch; |
148 | batch.Erase(key); | |
149 | return WriteBatch(batch, fSync); | |
150 | } | |
151 | ||
ecd04e91 | 152 | bool WriteBatch(CLevelDBBatch& batch, bool fSync = false); |
43b7905e PW |
153 | |
154 | // not available for LevelDB; provide for compatibility with BDB | |
20e01b1a PW |
155 | bool Flush() |
156 | { | |
43b7905e PW |
157 | return true; |
158 | } | |
159 | ||
ecd04e91 | 160 | bool Sync() |
20e01b1a | 161 | { |
43b7905e PW |
162 | CLevelDBBatch batch; |
163 | return WriteBatch(batch, true); | |
164 | } | |
165 | ||
166 | // not exactly clean encapsulation, but it's easiest for now | |
20e01b1a PW |
167 | leveldb::Iterator* NewIterator() |
168 | { | |
43b7905e PW |
169 | return pdb->NewIterator(iteroptions); |
170 | } | |
171 | }; | |
172 | ||
b64187d0 | 173 | #endif // BITCOIN_LEVELDBWRAPPER_H |