gui: fix ban from qt console
[bitcoinplatinum.git] / src / dbwrapper.h
blob47bdb31b5b888fbe329e8fa64072fda509909786
1 // Copyright (c) 2012-2015 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_DBWRAPPER_H
6 #define BITCOIN_DBWRAPPER_H
8 #include "clientversion.h"
9 #include "serialize.h"
10 #include "streams.h"
11 #include "util.h"
12 #include "utilstrencodings.h"
13 #include "version.h"
15 #include <boost/filesystem/path.hpp>
17 #include <leveldb/db.h>
18 #include <leveldb/write_batch.h>
20 class dbwrapper_error : public std::runtime_error
22 public:
23 dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {}
26 class CDBWrapper;
28 /** These should be considered an implementation detail of the specific database.
30 namespace dbwrapper_private {
32 /** Handle database error by throwing dbwrapper_error exception.
34 void HandleError(const leveldb::Status& status);
36 /** Work around circular dependency, as well as for testing in dbwrapper_tests.
37 * Database obfuscation should be considered an implementation detail of the
38 * specific database.
40 const std::vector<unsigned char>& GetObfuscateKey(const CDBWrapper &w);
44 /** Batch of changes queued to be written to a CDBWrapper */
45 class CDBBatch
47 friend class CDBWrapper;
49 private:
50 const CDBWrapper &parent;
51 leveldb::WriteBatch batch;
53 public:
54 /**
55 * @param[in] _parent CDBWrapper that this batch is to be submitted to
57 CDBBatch(const CDBWrapper &_parent) : parent(_parent) { };
59 template <typename K, typename V>
60 void Write(const K& key, const V& value)
62 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
63 ssKey.reserve(ssKey.GetSerializeSize(key));
64 ssKey << key;
65 leveldb::Slice slKey(&ssKey[0], ssKey.size());
67 CDataStream ssValue(SER_DISK, CLIENT_VERSION);
68 ssValue.reserve(ssValue.GetSerializeSize(value));
69 ssValue << value;
70 ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent));
71 leveldb::Slice slValue(&ssValue[0], ssValue.size());
73 batch.Put(slKey, slValue);
76 template <typename K>
77 void Erase(const K& key)
79 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
80 ssKey.reserve(ssKey.GetSerializeSize(key));
81 ssKey << key;
82 leveldb::Slice slKey(&ssKey[0], ssKey.size());
84 batch.Delete(slKey);
88 class CDBIterator
90 private:
91 const CDBWrapper &parent;
92 leveldb::Iterator *piter;
94 public:
96 /**
97 * @param[in] _parent Parent CDBWrapper instance.
98 * @param[in] _piter The original leveldb iterator.
100 CDBIterator(const CDBWrapper &_parent, leveldb::Iterator *_piter) :
101 parent(_parent), piter(_piter) { };
102 ~CDBIterator();
104 bool Valid();
106 void SeekToFirst();
108 template<typename K> void Seek(const K& key) {
109 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
110 ssKey.reserve(ssKey.GetSerializeSize(key));
111 ssKey << key;
112 leveldb::Slice slKey(&ssKey[0], ssKey.size());
113 piter->Seek(slKey);
116 void Next();
118 template<typename K> bool GetKey(K& key) {
119 leveldb::Slice slKey = piter->key();
120 try {
121 CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
122 ssKey >> key;
123 } catch (const std::exception&) {
124 return false;
126 return true;
129 unsigned int GetKeySize() {
130 return piter->key().size();
133 template<typename V> bool GetValue(V& value) {
134 leveldb::Slice slValue = piter->value();
135 try {
136 CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
137 ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent));
138 ssValue >> value;
139 } catch (const std::exception&) {
140 return false;
142 return true;
145 unsigned int GetValueSize() {
146 return piter->value().size();
151 class CDBWrapper
153 friend const std::vector<unsigned char>& dbwrapper_private::GetObfuscateKey(const CDBWrapper &w);
154 private:
155 //! custom environment this database is using (may be NULL in case of default environment)
156 leveldb::Env* penv;
158 //! database options used
159 leveldb::Options options;
161 //! options used when reading from the database
162 leveldb::ReadOptions readoptions;
164 //! options used when iterating over values of the database
165 leveldb::ReadOptions iteroptions;
167 //! options used when writing to the database
168 leveldb::WriteOptions writeoptions;
170 //! options used when sync writing to the database
171 leveldb::WriteOptions syncoptions;
173 //! the database itself
174 leveldb::DB* pdb;
176 //! a key used for optional XOR-obfuscation of the database
177 std::vector<unsigned char> obfuscate_key;
179 //! the key under which the obfuscation key is stored
180 static const std::string OBFUSCATE_KEY_KEY;
182 //! the length of the obfuscate key in number of bytes
183 static const unsigned int OBFUSCATE_KEY_NUM_BYTES;
185 std::vector<unsigned char> CreateObfuscateKey() const;
187 public:
189 * @param[in] path Location in the filesystem where leveldb data will be stored.
190 * @param[in] nCacheSize Configures various leveldb cache settings.
191 * @param[in] fMemory If true, use leveldb's memory environment.
192 * @param[in] fWipe If true, remove all existing data.
193 * @param[in] obfuscate If true, store data obfuscated via simple XOR. If false, XOR
194 * with a zero'd byte array.
196 CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool obfuscate = false);
197 ~CDBWrapper();
199 template <typename K, typename V>
200 bool Read(const K& key, V& value) const
202 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
203 ssKey.reserve(ssKey.GetSerializeSize(key));
204 ssKey << key;
205 leveldb::Slice slKey(&ssKey[0], ssKey.size());
207 std::string strValue;
208 leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
209 if (!status.ok()) {
210 if (status.IsNotFound())
211 return false;
212 LogPrintf("LevelDB read failure: %s\n", status.ToString());
213 dbwrapper_private::HandleError(status);
215 try {
216 CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
217 ssValue.Xor(obfuscate_key);
218 ssValue >> value;
219 } catch (const std::exception&) {
220 return false;
222 return true;
225 template <typename K, typename V>
226 bool Write(const K& key, const V& value, bool fSync = false)
228 CDBBatch batch(*this);
229 batch.Write(key, value);
230 return WriteBatch(batch, fSync);
233 template <typename K>
234 bool Exists(const K& key) const
236 CDataStream ssKey(SER_DISK, CLIENT_VERSION);
237 ssKey.reserve(ssKey.GetSerializeSize(key));
238 ssKey << key;
239 leveldb::Slice slKey(&ssKey[0], ssKey.size());
241 std::string strValue;
242 leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
243 if (!status.ok()) {
244 if (status.IsNotFound())
245 return false;
246 LogPrintf("LevelDB read failure: %s\n", status.ToString());
247 dbwrapper_private::HandleError(status);
249 return true;
252 template <typename K>
253 bool Erase(const K& key, bool fSync = false)
255 CDBBatch batch(*this);
256 batch.Erase(key);
257 return WriteBatch(batch, fSync);
260 bool WriteBatch(CDBBatch& batch, bool fSync = false);
262 // not available for LevelDB; provide for compatibility with BDB
263 bool Flush()
265 return true;
268 bool Sync()
270 CDBBatch batch(*this);
271 return WriteBatch(batch, true);
274 CDBIterator *NewIterator()
276 return new CDBIterator(*this, pdb->NewIterator(iteroptions));
280 * Return true if the database managed by this class contains no entries.
282 bool IsEmpty();
285 #endif // BITCOIN_DBWRAPPER_H