Dogecoin Core  1.14.2
P2P Digital Currency
dbwrapper.h
Go to the documentation of this file.
1 // Copyright (c) 2012-2016 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.
4 
5 #ifndef BITCOIN_DBWRAPPER_H
6 #define BITCOIN_DBWRAPPER_H
7 
8 #include "clientversion.h"
9 #include "serialize.h"
10 #include "streams.h"
11 #include "util.h"
12 #include "utilstrencodings.h"
13 #include "version.h"
14 
15 #include <boost/filesystem/path.hpp>
16 
17 #include <leveldb/db.h>
18 #include <leveldb/write_batch.h>
19 
20 static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64;
21 static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024;
22 
23 class dbwrapper_error : public std::runtime_error
24 {
25 public:
26  dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {}
27 };
28 
29 class CDBWrapper;
30 
33 namespace dbwrapper_private {
34 
37 void HandleError(const leveldb::Status& status);
38 
43 const std::vector<unsigned char>& GetObfuscateKey(const CDBWrapper &w);
44 
45 };
46 
48 class CDBBatch
49 {
50  friend class CDBWrapper;
51 
52 private:
54  leveldb::WriteBatch batch;
55 
58 
59 public:
63  CDBBatch(const CDBWrapper &_parent) : parent(_parent), ssKey(SER_DISK, CLIENT_VERSION), ssValue(SER_DISK, CLIENT_VERSION) { };
64 
65  template <typename K, typename V>
66  void Write(const K& key, const V& value)
67  {
68  ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
69  ssKey << key;
70  leveldb::Slice slKey(ssKey.data(), ssKey.size());
71 
72  ssValue.reserve(DBWRAPPER_PREALLOC_VALUE_SIZE);
73  ssValue << value;
75  leveldb::Slice slValue(ssValue.data(), ssValue.size());
76 
77  batch.Put(slKey, slValue);
78  ssKey.clear();
79  ssValue.clear();
80  }
81 
82  template <typename K>
83  void Erase(const K& key)
84  {
85  ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
86  ssKey << key;
87  leveldb::Slice slKey(ssKey.data(), ssKey.size());
88 
89  batch.Delete(slKey);
90  ssKey.clear();
91  }
92 };
93 
95 {
96 private:
98  leveldb::Iterator *piter;
99 
100 public:
101 
106  CDBIterator(const CDBWrapper &_parent, leveldb::Iterator *_piter) :
107  parent(_parent), piter(_piter) { };
108  ~CDBIterator();
109 
110  bool Valid();
111 
112  void SeekToFirst();
113 
114  template<typename K> void Seek(const K& key) {
115  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
116  ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
117  ssKey << key;
118  leveldb::Slice slKey(ssKey.data(), ssKey.size());
119  piter->Seek(slKey);
120  }
121 
122  void Next();
123 
124  template<typename K> bool GetKey(K& key) {
125  leveldb::Slice slKey = piter->key();
126  try {
127  CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
128  ssKey >> key;
129  } catch (const std::exception&) {
130  return false;
131  }
132  return true;
133  }
134 
135  unsigned int GetKeySize() {
136  return piter->key().size();
137  }
138 
139  template<typename V> bool GetValue(V& value) {
140  leveldb::Slice slValue = piter->value();
141  try {
142  CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
144  ssValue >> value;
145  } catch (const std::exception&) {
146  return false;
147  }
148  return true;
149  }
150 
151  unsigned int GetValueSize() {
152  return piter->value().size();
153  }
154 
155 };
156 
158 {
159  friend const std::vector<unsigned char>& dbwrapper_private::GetObfuscateKey(const CDBWrapper &w);
160 private:
162  leveldb::Env* penv;
163 
165  leveldb::Options options;
166 
168  leveldb::ReadOptions readoptions;
169 
171  leveldb::ReadOptions iteroptions;
172 
174  leveldb::WriteOptions writeoptions;
175 
177  leveldb::WriteOptions syncoptions;
178 
180  leveldb::DB* pdb;
181 
183  std::vector<unsigned char> obfuscate_key;
184 
186  static const std::string OBFUSCATE_KEY_KEY;
187 
189  static const unsigned int OBFUSCATE_KEY_NUM_BYTES;
190 
191  std::vector<unsigned char> CreateObfuscateKey() const;
192 
193 public:
202  CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool obfuscate = false);
203  ~CDBWrapper();
204 
205  template <typename K, typename V>
206  bool Read(const K& key, V& value) const
207  {
208  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
209  ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
210  ssKey << key;
211  leveldb::Slice slKey(ssKey.data(), ssKey.size());
212 
213  std::string strValue;
214  leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
215  if (!status.ok()) {
216  if (status.IsNotFound())
217  return false;
218  LogPrintf("LevelDB read failure: %s\n", status.ToString());
220  }
221  try {
222  CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
223  ssValue.Xor(obfuscate_key);
224  ssValue >> value;
225  } catch (const std::exception&) {
226  return false;
227  }
228  return true;
229  }
230 
231  template <typename K, typename V>
232  bool Write(const K& key, const V& value, bool fSync = false)
233  {
234  CDBBatch batch(*this);
235  batch.Write(key, value);
236  return WriteBatch(batch, fSync);
237  }
238 
239  template <typename K>
240  bool Exists(const K& key) const
241  {
242  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
243  ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
244  ssKey << key;
245  leveldb::Slice slKey(ssKey.data(), ssKey.size());
246 
247  std::string strValue;
248  leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
249  if (!status.ok()) {
250  if (status.IsNotFound())
251  return false;
252  LogPrintf("LevelDB read failure: %s\n", status.ToString());
254  }
255  return true;
256  }
257 
258  template <typename K>
259  bool Erase(const K& key, bool fSync = false)
260  {
261  CDBBatch batch(*this);
262  batch.Erase(key);
263  return WriteBatch(batch, fSync);
264  }
265 
266  bool WriteBatch(CDBBatch& batch, bool fSync = false);
267 
268  // not available for LevelDB; provide for compatibility with BDB
269  bool Flush()
270  {
271  return true;
272  }
273 
274  bool Sync()
275  {
276  CDBBatch batch(*this);
277  return WriteBatch(batch, true);
278  }
279 
281  {
282  return new CDBIterator(*this, pdb->NewIterator(iteroptions));
283  }
284 
288  bool IsEmpty();
289 };
290 
291 #endif // BITCOIN_DBWRAPPER_H
292 
Batch of changes queued to be written to a CDBWrapper.
Definition: dbwrapper.h:49
void Erase(const K &key)
Definition: dbwrapper.h:83
CDataStream ssKey
Definition: dbwrapper.h:56
CDataStream ssValue
Definition: dbwrapper.h:57
void Write(const K &key, const V &value)
Definition: dbwrapper.h:66
CDBBatch(const CDBWrapper &_parent)
Definition: dbwrapper.h:63
leveldb::WriteBatch batch
Definition: dbwrapper.h:54
const CDBWrapper & parent
Definition: dbwrapper.h:53
bool GetValue(V &value)
Definition: dbwrapper.h:139
bool Valid()
Definition: dbwrapper.cpp:126
unsigned int GetKeySize()
Definition: dbwrapper.h:135
unsigned int GetValueSize()
Definition: dbwrapper.h:151
bool GetKey(K &key)
Definition: dbwrapper.h:124
leveldb::Iterator * piter
Definition: dbwrapper.h:98
void Seek(const K &key)
Definition: dbwrapper.h:114
const CDBWrapper & parent
Definition: dbwrapper.h:97
void SeekToFirst()
Definition: dbwrapper.cpp:127
void Next()
Definition: dbwrapper.cpp:128
CDBIterator(const CDBWrapper &_parent, leveldb::Iterator *_piter)
Definition: dbwrapper.h:106
CDBIterator * NewIterator()
Definition: dbwrapper.h:280
CDBWrapper(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory=false, bool fWipe=false, bool obfuscate=false)
Definition: dbwrapper.cpp:34
leveldb::Env * penv
custom environment this database is using (may be NULL in case of default environment)
Definition: dbwrapper.h:162
bool WriteBatch(CDBBatch &batch, bool fSync=false)
Definition: dbwrapper.cpp:91
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:206
bool Flush()
Definition: dbwrapper.h:269
bool Erase(const K &key, bool fSync=false)
Definition: dbwrapper.h:259
bool Write(const K &key, const V &value, bool fSync=false)
Definition: dbwrapper.h:232
bool Exists(const K &key) const
Definition: dbwrapper.h:240
std::vector< unsigned char > obfuscate_key
a key used for optional XOR-obfuscation of the database
Definition: dbwrapper.h:183
leveldb::Options options
database options used
Definition: dbwrapper.h:165
static const unsigned int OBFUSCATE_KEY_NUM_BYTES
the length of the obfuscate key in number of bytes
Definition: dbwrapper.h:189
static const std::string OBFUSCATE_KEY_KEY
the key under which the obfuscation key is stored
Definition: dbwrapper.h:186
leveldb::WriteOptions writeoptions
options used when writing to the database
Definition: dbwrapper.h:174
leveldb::WriteOptions syncoptions
options used when sync writing to the database
Definition: dbwrapper.h:177
leveldb::DB * pdb
the database itself
Definition: dbwrapper.h:180
std::vector< unsigned char > CreateObfuscateKey() const
Returns a string (consisting of 8 random bytes) suitable for use as an obfuscating XOR key.
Definition: dbwrapper.cpp:110
leveldb::ReadOptions iteroptions
options used when iterating over values of the database
Definition: dbwrapper.h:171
bool Sync()
Definition: dbwrapper.h:274
bool IsEmpty()
Return true if the database managed by this class contains no entries.
Definition: dbwrapper.cpp:118
leveldb::ReadOptions readoptions
options used when reading from the database
Definition: dbwrapper.h:168
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:147
value_type * data()
Definition: streams.h:246
void reserve(size_type n)
Definition: streams.h:240
void Xor(const std::vector< unsigned char > &key)
XOR the contents of this stream with a certain key.
Definition: streams.h:421
size_type size() const
Definition: streams.h:237
void clear()
Definition: streams.h:243
dbwrapper_error(const std::string &msg)
Definition: dbwrapper.h:26
These should be considered an implementation detail of the specific database.
Definition: dbwrapper.cpp:130
void HandleError(const leveldb::Status &status)
Handle database error by throwing dbwrapper_error exception.
Definition: dbwrapper.cpp:132
const std::vector< unsigned char > & GetObfuscateKey(const CDBWrapper &w)
Work around circular dependency, as well as for testing in dbwrapper_tests.
Definition: dbwrapper.cpp:146
@ SER_DISK
Definition: serialize.h:147
#define LogPrintf(...)
Definition: util.h:82