Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

db.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #ifndef BITCOIN_WALLET_DB_H
7 #define BITCOIN_WALLET_DB_H
8 
9 #include <clientversion.h>
10 #include <fs.h>
11 #include <serialize.h>
12 #include <streams.h>
13 #include <sync.h>
14 #include <util.h>
15 #include <version.h>
16 
17 #include <atomic>
18 #include <map>
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 #include <db_cxx.h>
24 
25 static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
26 static const bool DEFAULT_WALLET_PRIVDB = true;
27 
29 {
30 private:
31  bool fDbEnvInit;
32  bool fMockDb;
33  // Don't change into fs::path, as that can result in
34  // shutdown problems/crashes caused by a static initialized internal pointer.
35  std::string strPath;
36 
37 public:
38  std::unique_ptr<DbEnv> dbenv;
39  std::map<std::string, int> mapFileUseCount;
40  std::map<std::string, Db*> mapDb;
41 
42  BerkeleyEnvironment(const fs::path& env_directory);
44  void Reset();
45 
46  void MakeMock();
47  bool IsMock() const { return fMockDb; }
48  bool IsInitialized() const { return fDbEnvInit; }
49  fs::path Directory() const { return strPath; }
50 
60  typedef bool (*recoverFunc_type)(const fs::path& file_path, std::string& out_backup_filename);
61  VerifyResult Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename);
69  typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair;
70  bool Salvage(const std::string& strFile, bool fAggressive, std::vector<KeyValPair>& vResult);
71 
72  bool Open(bool retry);
73  void Close();
74  void Flush(bool fShutdown);
75  void CheckpointLSN(const std::string& strFile);
76 
77  void CloseDb(const std::string& strFile);
78 
79  DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC)
80  {
81  DbTxn* ptxn = nullptr;
82  int ret = dbenv->txn_begin(nullptr, &ptxn, flags);
83  if (!ptxn || ret != 0)
84  return nullptr;
85  return ptxn;
86  }
87 };
88 
90 BerkeleyEnvironment* GetWalletEnv(const fs::path& wallet_path, std::string& database_filename);
91 
96 {
97  friend class BerkeleyBatch;
98 public:
101  {
102  }
103 
105  BerkeleyDatabase(const fs::path& wallet_path, bool mock = false) :
107  {
108  env = GetWalletEnv(wallet_path, strFile);
109  if (mock) {
110  env->Close();
111  env->Reset();
112  env->MakeMock();
113  }
114  }
115 
117  static std::unique_ptr<BerkeleyDatabase> Create(const fs::path& path)
118  {
119  return MakeUnique<BerkeleyDatabase>(path);
120  }
121 
123  static std::unique_ptr<BerkeleyDatabase> CreateDummy()
124  {
125  return MakeUnique<BerkeleyDatabase>();
126  }
127 
129  static std::unique_ptr<BerkeleyDatabase> CreateMock()
130  {
131  return MakeUnique<BerkeleyDatabase>("", true /* mock */);
132  }
133 
136  bool Rewrite(const char* pszSkip=nullptr);
137 
140  bool Backup(const std::string& strDest);
141 
144  void Flush(bool shutdown);
145 
146  void IncrementUpdateCounter();
147 
148  std::atomic<unsigned int> nUpdateCounter;
149  unsigned int nLastSeen;
150  unsigned int nLastFlushed;
152 
153 private:
156  std::string strFile;
157 
162  bool IsDummy() { return env == nullptr; }
163 };
164 
165 
168 {
169 protected:
170  Db* pdb;
171  std::string strFile;
172  DbTxn* activeTxn;
173  bool fReadOnly;
176 
177 public:
178  explicit BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode = "r+", bool fFlushOnCloseIn=true);
180 
181  BerkeleyBatch(const BerkeleyBatch&) = delete;
182  BerkeleyBatch& operator=(const BerkeleyBatch&) = delete;
183 
184  void Flush();
185  void Close();
186  static bool Recover(const fs::path& file_path, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename);
187 
188  /* flush the wallet passively (TRY_LOCK)
189  ideal to be called periodically */
190  static bool PeriodicFlush(BerkeleyDatabase& database);
191  /* verifies the database environment */
192  static bool VerifyEnvironment(const fs::path& file_path, std::string& errorStr);
193  /* verifies the database file */
194  static bool VerifyDatabaseFile(const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc);
195 
196 public:
197  template <typename K, typename T>
198  bool Read(const K& key, T& value)
199  {
200  if (!pdb)
201  return false;
202 
203  // Key
205  ssKey.reserve(1000);
206  ssKey << key;
207  Dbt datKey(ssKey.data(), ssKey.size());
208 
209  // Read
210  Dbt datValue;
211  datValue.set_flags(DB_DBT_MALLOC);
212  int ret = pdb->get(activeTxn, &datKey, &datValue, 0);
213  memory_cleanse(datKey.get_data(), datKey.get_size());
214  bool success = false;
215  if (datValue.get_data() != nullptr) {
216  // Unserialize value
217  try {
218  CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
219  ssValue >> value;
220  success = true;
221  } catch (const std::exception&) {
222  // In this case success remains 'false'
223  }
224 
225  // Clear and free memory
226  memory_cleanse(datValue.get_data(), datValue.get_size());
227  free(datValue.get_data());
228  }
229  return ret == 0 && success;
230  }
231 
232  template <typename K, typename T>
233  bool Write(const K& key, const T& value, bool fOverwrite = true)
234  {
235  if (!pdb)
236  return true;
237  if (fReadOnly)
238  assert(!"Write called on database in read-only mode");
239 
240  // Key
242  ssKey.reserve(1000);
243  ssKey << key;
244  Dbt datKey(ssKey.data(), ssKey.size());
245 
246  // Value
248  ssValue.reserve(10000);
249  ssValue << value;
250  Dbt datValue(ssValue.data(), ssValue.size());
251 
252  // Write
253  int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
254 
255  // Clear memory in case it was a private key
256  memory_cleanse(datKey.get_data(), datKey.get_size());
257  memory_cleanse(datValue.get_data(), datValue.get_size());
258  return (ret == 0);
259  }
260 
261  template <typename K>
262  bool Erase(const K& key)
263  {
264  if (!pdb)
265  return false;
266  if (fReadOnly)
267  assert(!"Erase called on database in read-only mode");
268 
269  // Key
271  ssKey.reserve(1000);
272  ssKey << key;
273  Dbt datKey(ssKey.data(), ssKey.size());
274 
275  // Erase
276  int ret = pdb->del(activeTxn, &datKey, 0);
277 
278  // Clear memory
279  memory_cleanse(datKey.get_data(), datKey.get_size());
280  return (ret == 0 || ret == DB_NOTFOUND);
281  }
282 
283  template <typename K>
284  bool Exists(const K& key)
285  {
286  if (!pdb)
287  return false;
288 
289  // Key
291  ssKey.reserve(1000);
292  ssKey << key;
293  Dbt datKey(ssKey.data(), ssKey.size());
294 
295  // Exists
296  int ret = pdb->exists(activeTxn, &datKey, 0);
297 
298  // Clear memory
299  memory_cleanse(datKey.get_data(), datKey.get_size());
300  return (ret == 0);
301  }
302 
303  Dbc* GetCursor()
304  {
305  if (!pdb)
306  return nullptr;
307  Dbc* pcursor = nullptr;
308  int ret = pdb->cursor(nullptr, &pcursor, 0);
309  if (ret != 0)
310  return nullptr;
311  return pcursor;
312  }
313 
314  int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, bool setRange = false)
315  {
316  // Read at cursor
317  Dbt datKey;
318  unsigned int fFlags = DB_NEXT;
319  if (setRange) {
320  datKey.set_data(ssKey.data());
321  datKey.set_size(ssKey.size());
322  fFlags = DB_SET_RANGE;
323  }
324  Dbt datValue;
325  datKey.set_flags(DB_DBT_MALLOC);
326  datValue.set_flags(DB_DBT_MALLOC);
327  int ret = pcursor->get(&datKey, &datValue, fFlags);
328  if (ret != 0)
329  return ret;
330  else if (datKey.get_data() == nullptr || datValue.get_data() == nullptr)
331  return 99999;
332 
333  // Convert to streams
334  ssKey.SetType(SER_DISK);
335  ssKey.clear();
336  ssKey.write((char*)datKey.get_data(), datKey.get_size());
337  ssValue.SetType(SER_DISK);
338  ssValue.clear();
339  ssValue.write((char*)datValue.get_data(), datValue.get_size());
340 
341  // Clear and free memory
342  memory_cleanse(datKey.get_data(), datKey.get_size());
343  memory_cleanse(datValue.get_data(), datValue.get_size());
344  free(datKey.get_data());
345  free(datValue.get_data());
346  return 0;
347  }
348 
349 public:
350  bool TxnBegin()
351  {
352  if (!pdb || activeTxn)
353  return false;
354  DbTxn* ptxn = env->TxnBegin();
355  if (!ptxn)
356  return false;
357  activeTxn = ptxn;
358  return true;
359  }
360 
361  bool TxnCommit()
362  {
363  if (!pdb || !activeTxn)
364  return false;
365  int ret = activeTxn->commit(0);
366  activeTxn = nullptr;
367  return (ret == 0);
368  }
369 
370  bool TxnAbort()
371  {
372  if (!pdb || !activeTxn)
373  return false;
374  int ret = activeTxn->abort();
375  activeTxn = nullptr;
376  return (ret == 0);
377  }
378 
379  bool ReadVersion(int& nVersion)
380  {
381  nVersion = 0;
382  return Read(std::string("version"), nVersion);
383  }
384 
385  bool WriteVersion(int nVersion)
386  {
387  return Write(std::string("version"), nVersion);
388  }
389 
390  bool static Rewrite(BerkeleyDatabase& database, const char* pszSkip = nullptr);
391 };
392 
393 #endif // BITCOIN_WALLET_DB_H
void Flush(bool shutdown)
Make sure all changes are flushed to disk.
Definition: db.cpp:790
static std::unique_ptr< BerkeleyDatabase > CreateDummy()
Return object for accessing dummy database with no read/write capabilities.
Definition: db.h:123
bool fReadOnly
Definition: db.h:173
static std::unique_ptr< BerkeleyDatabase > CreateMock()
Return object for accessing temporary in-memory database.
Definition: db.h:129
bool IsInitialized() const
Definition: db.h:48
bool fDbEnvInit
Definition: db.h:31
void Close()
Definition: db.cpp:87
BerkeleyDatabase(const fs::path &wallet_path, bool mock=false)
Create DB handle to real database.
Definition: db.h:105
bool TxnCommit()
Definition: db.h:361
VerifyResult
Verify that database file strFile is OK.
Definition: db.h:57
void Close()
Definition: db.cpp:540
unsigned int nLastSeen
Definition: db.h:149
bool fFlushOnClose
Definition: db.h:174
bool TxnBegin()
Definition: db.h:350
bool Exists(const K &key)
Definition: db.h:284
bool Write(const K &key, const T &value, bool fOverwrite=true)
Definition: db.h:233
value_type * data()
Definition: streams.h:203
An instance of this class represents one database.
Definition: db.h:95
int flags
Definition: dash-tx.cpp:462
Dbc * GetCursor()
Definition: db.h:303
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:103
void write(const char *pch, size_t nSize)
Definition: streams.h:336
bool Backup(const std::string &strDest)
Back up the entire database to a file.
Definition: db.cpp:749
fs::path Directory() const
Definition: db.h:49
bool Open(bool retry)
Definition: db.cpp:128
static bool PeriodicFlush(BerkeleyDatabase &database)
Definition: db.cpp:701
std::map< std::string, Db * > mapDb
Definition: db.h:40
DbTxn * TxnBegin(int flags=DB_TXN_WRITE_NOSYNC)
Definition: db.h:79
std::map< std::string, int > mapFileUseCount
Definition: db.h:39
std::unique_ptr< DbEnv > dbenv
Definition: db.h:38
void CheckpointLSN(const std::string &strFile)
Definition: db.cpp:434
bool Erase(const K &key)
Definition: db.h:262
std::pair< std::vector< unsigned char >, std::vector< unsigned char > > KeyValPair
Salvage data from a file that Verify says is bad.
Definition: db.h:69
bool TxnAbort()
Definition: db.h:370
bool Read(const K &key, T &value)
Definition: db.h:198
void memory_cleanse(void *ptr, size_t len)
Definition: cleanse.cpp:31
size_type size() const
Definition: streams.h:194
std::string strFile
Definition: db.h:171
BerkeleyEnvironment * GetWalletEnv(const fs::path &wallet_path, std::string &database_filename)
Get BerkeleyEnvironment and database filename given a wallet path.
Definition: db.cpp:60
bool Rewrite(const char *pszSkip=nullptr)
Rewrite the entire database on disk, with the exception of key pszSkip if non-zero.
Definition: db.cpp:744
~BerkeleyBatch()
Definition: db.h:179
bool WriteVersion(int nVersion)
Definition: db.h:385
BerkeleyDatabase()
Create dummy DB handle.
Definition: db.h:100
DbTxn * activeTxn
Definition: db.h:172
void MakeMock()
Definition: db.cpp:198
RAII class that provides access to a Berkeley database.
Definition: db.h:167
void Flush()
Definition: db.cpp:522
std::string strFile
Definition: db.h:156
static const unsigned int DEFAULT_WALLET_DBLOGSIZE
Definition: db.h:25
static bool VerifyEnvironment(const fs::path &file_path, std::string &errorStr)
Definition: db.cpp:316
BerkeleyEnvironment(const fs::path &env_directory)
Definition: db.cpp:118
static bool Recover(const fs::path &file_path, void *callbackDataIn, bool(*recoverKVcallback)(void *callbackData, CDataStream ssKey, CDataStream ssValue), std::string &out_backup_filename)
Definition: db.cpp:247
static std::unique_ptr< BerkeleyDatabase > Create(const fs::path &path)
Return object for accessing database at specified path.
Definition: db.h:117
bool Salvage(const std::string &strFile, bool fAggressive, std::vector< KeyValPair > &vResult)
Definition: db.cpp:373
static bool Rewrite(BerkeleyDatabase &database, const char *pszSkip=nullptr)
Definition: db.cpp:572
int64_t nLastWalletUpdate
Definition: db.h:151
void IncrementUpdateCounter()
Definition: db.cpp:535
void reserve(size_type n)
Definition: streams.h:197
std::string strPath
Definition: db.h:35
BerkeleyBatch(BerkeleyDatabase &database, const char *pszMode="r+", bool fFlushOnCloseIn=true)
Definition: db.cpp:443
unsigned int nLastFlushed
Definition: db.h:150
int ReadAtCursor(Dbc *pcursor, CDataStream &ssKey, CDataStream &ssValue, bool setRange=false)
Definition: db.h:314
BerkeleyEnvironment * env
Definition: db.h:175
void Flush(bool fShutdown)
Definition: db.cpp:661
Db * pdb
Definition: db.h:170
std::atomic< unsigned int > nUpdateCounter
Definition: db.h:148
bool(* recoverFunc_type)(const fs::path &file_path, std::string &out_backup_filename)
Definition: db.h:60
VerifyResult Verify(const std::string &strFile, recoverFunc_type recoverFunc, std::string &out_backup_filename)
Definition: db.cpp:230
static const bool DEFAULT_WALLET_PRIVDB
Definition: db.h:26
bool ReadVersion(int &nVersion)
Definition: db.h:379
void clear()
Definition: streams.h:200
static bool VerifyDatabaseFile(const fs::path &file_path, std::string &warningStr, std::string &errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc)
Definition: db.cpp:340
void Reset()
Definition: db.cpp:111
void CloseDb(const std::string &strFile)
Definition: db.cpp:558
bool IsMock() const
Definition: db.h:47
~BerkeleyEnvironment()
Definition: db.cpp:123
BerkeleyEnvironment * env
BerkeleyDB specific.
Definition: db.h:155
bool fMockDb
Definition: db.h:32
static const int CLIENT_VERSION
dashd-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:38
BerkeleyBatch & operator=(const BerkeleyBatch &)=delete
void SetType(int n)
Definition: streams.h:294
bool IsDummy()
Return whether this database handle is a dummy for testing.
Definition: db.h:162
Released under the MIT license