Fabcoin Core  0.16.2
P2P Digital Currency
db.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 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 FABCOIN_WALLET_DB_H
7 #define FABCOIN_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 <version.h>
15 
16 #include <atomic>
17 #include <map>
18 #include <string>
19 #include <vector>
20 
21 #include <db_cxx.h>
22 
23 static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
24 static const bool DEFAULT_WALLET_PRIVDB = true;
25 
26 class CDBEnv
27 {
28 private:
29  bool fDbEnvInit;
30  bool fMockDb;
31  // Don't change into fs::path, as that can result in
32  // shutdown problems/crashes caused by a static initialized internal pointer.
33  std::string strPath;
34 
35  void EnvShutdown();
36 
37 public:
39  DbEnv *dbenv;
40  std::map<std::string, int> mapFileUseCount;
41  std::map<std::string, Db*> mapDb;
42 
43  CDBEnv();
44  ~CDBEnv();
45  void Reset();
46 
47  void MakeMock();
48  bool IsMock() const { return fMockDb; }
49 
59  typedef bool (*recoverFunc_type)(const std::string& strFile, std::string& out_backup_filename);
60  VerifyResult Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename);
68  typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair;
69  bool Salvage(const std::string& strFile, bool fAggressive, std::vector<KeyValPair>& vResult);
70 
71  bool Open(const fs::path& path);
72  void Close();
73  void Flush(bool fShutdown);
74  void CheckpointLSN(const std::string& strFile);
75 
76  void CloseDb(const std::string& strFile);
77 
78  DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC)
79  {
80  DbTxn* ptxn = nullptr;
81  int ret = dbenv->txn_begin(nullptr, &ptxn, flags);
82  if (!ptxn || ret != 0)
83  return nullptr;
84  return ptxn;
85  }
86 };
87 
88 extern CDBEnv bitdb;
89 
94 {
95  friend class CDB;
96 public:
98  CWalletDBWrapper() : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr)
99  {
100  }
101 
103  CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in) :
104  nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(env_in), strFile(strFile_in)
105  {
106  }
107 
110  bool Rewrite(const char* pszSkip=nullptr);
111 
114  bool Backup(const std::string& strDest);
115 
118  std::string GetName() const { return strFile; }
119 
122  void Flush(bool shutdown);
123 
124  void IncrementUpdateCounter();
125 
126  std::atomic<unsigned int> nUpdateCounter;
127  unsigned int nLastSeen;
128  unsigned int nLastFlushed;
130 
131 private:
134  std::string strFile;
135 
140  bool IsDummy() { return env == nullptr; }
141 };
142 
143 
145 class CDB
146 {
147 protected:
148  Db* pdb;
149  std::string strFile;
150  DbTxn* activeTxn;
151  bool fReadOnly;
154 
155 public:
156  explicit CDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool fFlushOnCloseIn=true);
157  ~CDB() { Close(); }
158 
159  void Flush();
160  void Close();
161  static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename);
162 
163  /* flush the wallet passively (TRY_LOCK)
164  ideal to be called periodically */
165  static bool PeriodicFlush(CWalletDBWrapper& dbw);
166  /* verifies the database environment */
167  static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr);
168  /* verifies the database file */
169  static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc);
170 
171 private:
172  CDB(const CDB&);
173  void operator=(const CDB&);
174 
175 public:
176  template <typename K, typename T>
177  bool Read(const K& key, T& value)
178  {
179  if (!pdb)
180  return false;
181 
182  // Key
183  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
184  ssKey.reserve(1000);
185  ssKey << key;
186  Dbt datKey(ssKey.data(), ssKey.size());
187 
188  // Read
189  Dbt datValue;
190  datValue.set_flags(DB_DBT_MALLOC);
191  int ret = pdb->get(activeTxn, &datKey, &datValue, 0);
192  memory_cleanse(datKey.get_data(), datKey.get_size());
193  bool success = false;
194  if (datValue.get_data() != nullptr) {
195  // Unserialize value
196  try {
197  CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
198  ssValue >> value;
199  success = true;
200  } catch (const std::exception&) {
201  // In this case success remains 'false'
202  }
203 
204  // Clear and free memory
205  memory_cleanse(datValue.get_data(), datValue.get_size());
206  free(datValue.get_data());
207  }
208  return ret == 0 && success;
209  }
210 
211  template <typename K, typename T>
212  bool Write(const K& key, const T& value, bool fOverwrite = true)
213  {
214  if (!pdb)
215  return true;
216  if (fReadOnly)
217  assert(!"Write called on database in read-only mode");
218 
219  // Key
220  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
221  ssKey.reserve(1000);
222  ssKey << key;
223  Dbt datKey(ssKey.data(), ssKey.size());
224 
225  // Value
226  CDataStream ssValue(SER_DISK, CLIENT_VERSION);
227  ssValue.reserve(10000);
228  ssValue << value;
229  Dbt datValue(ssValue.data(), ssValue.size());
230 
231  // Write
232  int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
233 
234  // Clear memory in case it was a private key
235  memory_cleanse(datKey.get_data(), datKey.get_size());
236  memory_cleanse(datValue.get_data(), datValue.get_size());
237  return (ret == 0);
238  }
239 
240  template <typename K>
241  bool Erase(const K& key)
242  {
243  if (!pdb)
244  return false;
245  if (fReadOnly)
246  assert(!"Erase called on database in read-only mode");
247 
248  // Key
249  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
250  ssKey.reserve(1000);
251  ssKey << key;
252  Dbt datKey(ssKey.data(), ssKey.size());
253 
254  // Erase
255  int ret = pdb->del(activeTxn, &datKey, 0);
256 
257  // Clear memory
258  memory_cleanse(datKey.get_data(), datKey.get_size());
259  return (ret == 0 || ret == DB_NOTFOUND);
260  }
261 
262  template <typename K>
263  bool Exists(const K& key)
264  {
265  if (!pdb)
266  return false;
267 
268  // Key
269  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
270  ssKey.reserve(1000);
271  ssKey << key;
272  Dbt datKey(ssKey.data(), ssKey.size());
273 
274  // Exists
275  int ret = pdb->exists(activeTxn, &datKey, 0);
276 
277  // Clear memory
278  memory_cleanse(datKey.get_data(), datKey.get_size());
279  return (ret == 0);
280  }
281 
282  Dbc* GetCursor()
283  {
284  if (!pdb)
285  return nullptr;
286  Dbc* pcursor = nullptr;
287  int ret = pdb->cursor(nullptr, &pcursor, 0);
288  if (ret != 0)
289  return nullptr;
290  return pcursor;
291  }
292 
293  int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, bool setRange = false)
294  {
295  // Read at cursor
296  Dbt datKey;
297  unsigned int fFlags = DB_NEXT;
298  if (setRange) {
299  datKey.set_data(ssKey.data());
300  datKey.set_size(ssKey.size());
301  fFlags = DB_SET_RANGE;
302  }
303  Dbt datValue;
304  datKey.set_flags(DB_DBT_MALLOC);
305  datValue.set_flags(DB_DBT_MALLOC);
306  int ret = pcursor->get(&datKey, &datValue, fFlags);
307  if (ret != 0)
308  return ret;
309  else if (datKey.get_data() == nullptr || datValue.get_data() == nullptr)
310  return 99999;
311 
312  // Convert to streams
313  ssKey.SetType(SER_DISK);
314  ssKey.clear();
315  ssKey.write((char*)datKey.get_data(), datKey.get_size());
316  ssValue.SetType(SER_DISK);
317  ssValue.clear();
318  ssValue.write((char*)datValue.get_data(), datValue.get_size());
319 
320  // Clear and free memory
321  memory_cleanse(datKey.get_data(), datKey.get_size());
322  memory_cleanse(datValue.get_data(), datValue.get_size());
323  free(datKey.get_data());
324  free(datValue.get_data());
325  return 0;
326  }
327 
328 public:
329  bool TxnBegin()
330  {
331  if (!pdb || activeTxn)
332  return false;
333  DbTxn* ptxn = bitdb.TxnBegin();
334  if (!ptxn)
335  return false;
336  activeTxn = ptxn;
337  return true;
338  }
339 
340  bool TxnCommit()
341  {
342  if (!pdb || !activeTxn)
343  return false;
344  int ret = activeTxn->commit(0);
345  activeTxn = nullptr;
346  return (ret == 0);
347  }
348 
349  bool TxnAbort()
350  {
351  if (!pdb || !activeTxn)
352  return false;
353  int ret = activeTxn->abort();
354  activeTxn = nullptr;
355  return (ret == 0);
356  }
357 
358  bool ReadVersion(int& nVersion)
359  {
360  nVersion = 0;
361  return Read(std::string("version"), nVersion);
362  }
363 
364  bool WriteVersion(int nVersion)
365  {
366  return Write(std::string("version"), nVersion);
367  }
368 
369  bool static Rewrite(CWalletDBWrapper& dbw, const char* pszSkip = nullptr);
370 };
371 
372 #endif // FABCOIN_WALLET_DB_H
bool Erase(const K &key)
Definition: db.h:241
std::map< std::string, int > mapFileUseCount
Definition: db.h:40
DbTxn * activeTxn
Definition: db.h:150
unsigned int nLastSeen
Definition: db.h:127
DbTxn * TxnBegin(int flags=DB_TXN_WRITE_NOSYNC)
Definition: db.h:78
void Reset()
Definition: db.cpp:76
std::string strFile
Definition: db.h:149
#define T(i, x)
bool Write(const K &key, const T &value, bool fOverwrite=true)
Definition: db.h:212
bool fReadOnly
Definition: db.h:151
value_type * data()
Definition: streams.h:246
Dbc * GetCursor()
Definition: db.h:282
void Flush(bool fShutdown)
Definition: db.cpp:598
void EnvShutdown()
Definition: db.cpp:63
assert(len-trim+(2 *lenIndices)<=WIDTH)
bool Exists(const K &key)
Definition: db.h:263
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:146
void write(const char *pch, size_t nSize)
Definition: streams.h:381
bool IsMock() const
Definition: db.h:48
bool Salvage(const std::string &strFile, bool fAggressive, std::vector< KeyValPair > &vResult)
Definition: db.cpp:326
~CDBEnv()
Definition: db.cpp:89
#define nullptr
Definition: eqcuda.hpp:22
CDBEnv * env
Definition: db.h:153
CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in)
Create DB handle to real database.
Definition: db.h:103
std::string strPath
Definition: db.h:33
bool fDbEnvInit
Definition: db.h:29
bool TxnBegin()
Definition: db.h:329
std::atomic< unsigned int > nUpdateCounter
Definition: db.h:126
bool IsDummy()
Return whether this database handle is a dummy for testing.
Definition: db.h:140
CDBEnv bitdb
Definition: db.cpp:61
void MakeMock()
Definition: db.cpp:148
VerifyResult
Verify that database file strFile is OK.
Definition: db.h:56
void memory_cleanse(void *ptr, size_t len)
Definition: cleanse.cpp:10
An instance of this class represents one database.
Definition: db.h:93
std::map< std::string, Db * > mapDb
Definition: db.h:41
size_type size() const
Definition: streams.h:237
bool ReadVersion(int &nVersion)
Definition: db.h:358
bool TxnCommit()
Definition: db.h:340
std::string GetName() const
Get a name for this database, for debugging etc.
Definition: db.h:118
unsigned int nLastFlushed
Definition: db.h:128
bool TxnAbort()
Definition: db.h:349
RAII class that provides access to a Berkeley database.
Definition: db.h:145
CCriticalSection cs_db
Definition: db.h:38
int64_t nLastWalletUpdate
Definition: db.h:129
bool(* recoverFunc_type)(const std::string &strFile, std::string &out_backup_filename)
Definition: db.h:59
bool Read(const K &key, T &value)
Definition: db.h:177
void Close()
Definition: db.cpp:96
static bool Rewrite(CWalletDBWrapper &dbw, const char *pszSkip=nullptr)
Definition: db.cpp:507
void reserve(size_type n)
Definition: streams.h:240
void CloseDb(const std::string &strFile)
Definition: db.cpp:493
bool WriteVersion(int nVersion)
Definition: db.h:364
Definition: db.h:26
bool fMockDb
Definition: db.h:30
int ReadAtCursor(Dbc *pcursor, CDataStream &ssKey, CDataStream &ssValue, bool setRange=false)
Definition: db.h:293
bool Open(const fs::path &path)
Definition: db.cpp:101
void CheckpointLSN(const std::string &strFile)
Definition: db.cpp:387
void clear()
Definition: streams.h:243
std::string strFile
Definition: db.h:134
CWalletDBWrapper()
Create dummy DB handle.
Definition: db.h:98
Db * pdb
Definition: db.h:148
std::pair< std::vector< unsigned char >, std::vector< unsigned char > > KeyValPair
Salvage data from a file that Verify says is bad.
Definition: db.h:68
CDBEnv()
Definition: db.cpp:84
CDBEnv * env
BerkeleyDB specific.
Definition: db.h:133
~CDB()
Definition: db.h:157
VerifyResult Verify(const std::string &strFile, recoverFunc_type recoverFunc, std::string &out_backup_filename)
Definition: db.cpp:180
bool fFlushOnClose
Definition: db.h:152
Wrapped boost mutex: supports recursive locking, but no waiting TODO: We should move away from using ...
Definition: sync.h:91
DbEnv * dbenv
Definition: db.h:39
void SetType(int n)
Definition: streams.h:337