Master Core  v0.0.9 - 49a5c0d97abf09ef2911ddfe8d9551df59f9efd3-dirty
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
db.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #ifndef BITCOIN_DB_H
7 #define BITCOIN_DB_H
8 
9 #include "serialize.h"
10 #include "sync.h"
11 #include "version.h"
12 
13 #include <map>
14 #include <string>
15 #include <vector>
16 
17 #include <boost/filesystem/path.hpp>
18 #include <db_cxx.h>
19 
20 class CAddrMan;
21 struct CBlockLocator;
22 class CDiskBlockIndex;
23 class COutPoint;
24 
25 extern unsigned int nWalletDBUpdated;
26 
27 void ThreadFlushWalletDB(const std::string& strWalletFile);
28 
29 
30 class CDBEnv
31 {
32 private:
33  bool fDbEnvInit;
34  bool fMockDb;
35  boost::filesystem::path path;
36 
37  void EnvShutdown();
38 
39 public:
41  DbEnv dbenv;
42  std::map<std::string, int> mapFileUseCount;
43  std::map<std::string, Db*> mapDb;
44 
45  CDBEnv();
46  ~CDBEnv();
47  void MakeMock();
48  bool IsMock() { return fMockDb; }
49 
50  /*
51  * Verify that database file strFile is OK. If it is not,
52  * call the callback to try to recover.
53  * This must be called BEFORE strFile is opened.
54  * Returns true if strFile is OK.
55  */
57  VerifyResult Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile));
58  /*
59  * Salvage data from a file that Verify says is bad.
60  * fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation).
61  * Appends binary key/value pairs to vResult, returns true if successful.
62  * NOTE: reads the entire database into memory, so cannot be used
63  * for huge databases.
64  */
65  typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair;
66  bool Salvage(std::string strFile, bool fAggressive, std::vector<KeyValPair>& vResult);
67 
68  bool Open(const boost::filesystem::path &path);
69  void Close();
70  void Flush(bool fShutdown);
71  void CheckpointLSN(std::string strFile);
72 
73  void CloseDb(const std::string& strFile);
74  bool RemoveDb(const std::string& strFile);
75 
76  DbTxn *TxnBegin(int flags=DB_TXN_WRITE_NOSYNC)
77  {
78  DbTxn* ptxn = NULL;
79  int ret = dbenv.txn_begin(NULL, &ptxn, flags);
80  if (!ptxn || ret != 0)
81  return NULL;
82  return ptxn;
83  }
84 };
85 
86 extern CDBEnv bitdb;
87 
88 
90 class CDB
91 {
92 protected:
93  Db* pdb;
94  std::string strFile;
95  DbTxn *activeTxn;
96  bool fReadOnly;
97 
98  explicit CDB(const char* pszFile, const char* pszMode="r+");
99  ~CDB() { Close(); }
100 public:
101  void Flush();
102  void Close();
103 private:
104  CDB(const CDB&);
105  void operator=(const CDB&);
106 
107 protected:
108  template<typename K, typename T>
109  bool Read(const K& key, T& value)
110  {
111  if (!pdb)
112  return false;
113 
114  // Key
116  ssKey.reserve(1000);
117  ssKey << key;
118  Dbt datKey(&ssKey[0], ssKey.size());
119 
120  // Read
121  Dbt datValue;
122  datValue.set_flags(DB_DBT_MALLOC);
123  int ret = pdb->get(activeTxn, &datKey, &datValue, 0);
124  memset(datKey.get_data(), 0, datKey.get_size());
125  if (datValue.get_data() == NULL)
126  return false;
127 
128  // Unserialize value
129  try {
130  CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
131  ssValue >> value;
132  }
133  catch (std::exception &e) {
134  return false;
135  }
136 
137  // Clear and free memory
138  memset(datValue.get_data(), 0, datValue.get_size());
139  free(datValue.get_data());
140  return (ret == 0);
141  }
142 
143  template<typename K, typename T>
144  bool Write(const K& key, const T& value, bool fOverwrite=true)
145  {
146  if (!pdb)
147  return false;
148  if (fReadOnly)
149  assert(!"Write called on database in read-only mode");
150 
151  // Key
153  ssKey.reserve(1000);
154  ssKey << key;
155  Dbt datKey(&ssKey[0], ssKey.size());
156 
157  // Value
159  ssValue.reserve(10000);
160  ssValue << value;
161  Dbt datValue(&ssValue[0], ssValue.size());
162 
163  // Write
164  int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
165 
166  // Clear memory in case it was a private key
167  memset(datKey.get_data(), 0, datKey.get_size());
168  memset(datValue.get_data(), 0, datValue.get_size());
169  return (ret == 0);
170  }
171 
172  template<typename K>
173  bool Erase(const K& key)
174  {
175  if (!pdb)
176  return false;
177  if (fReadOnly)
178  assert(!"Erase called on database in read-only mode");
179 
180  // Key
182  ssKey.reserve(1000);
183  ssKey << key;
184  Dbt datKey(&ssKey[0], ssKey.size());
185 
186  // Erase
187  int ret = pdb->del(activeTxn, &datKey, 0);
188 
189  // Clear memory
190  memset(datKey.get_data(), 0, datKey.get_size());
191  return (ret == 0 || ret == DB_NOTFOUND);
192  }
193 
194  template<typename K>
195  bool Exists(const K& key)
196  {
197  if (!pdb)
198  return false;
199 
200  // Key
202  ssKey.reserve(1000);
203  ssKey << key;
204  Dbt datKey(&ssKey[0], ssKey.size());
205 
206  // Exists
207  int ret = pdb->exists(activeTxn, &datKey, 0);
208 
209  // Clear memory
210  memset(datKey.get_data(), 0, datKey.get_size());
211  return (ret == 0);
212  }
213 
214  Dbc* GetCursor()
215  {
216  if (!pdb)
217  return NULL;
218  Dbc* pcursor = NULL;
219  int ret = pdb->cursor(NULL, &pcursor, 0);
220  if (ret != 0)
221  return NULL;
222  return pcursor;
223  }
224 
225  int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
226  {
227  // Read at cursor
228  Dbt datKey;
229  if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
230  {
231  datKey.set_data(&ssKey[0]);
232  datKey.set_size(ssKey.size());
233  }
234  Dbt datValue;
235  if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
236  {
237  datValue.set_data(&ssValue[0]);
238  datValue.set_size(ssValue.size());
239  }
240  datKey.set_flags(DB_DBT_MALLOC);
241  datValue.set_flags(DB_DBT_MALLOC);
242  int ret = pcursor->get(&datKey, &datValue, fFlags);
243  if (ret != 0)
244  return ret;
245  else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
246  return 99999;
247 
248  // Convert to streams
249  ssKey.SetType(SER_DISK);
250  ssKey.clear();
251  ssKey.write((char*)datKey.get_data(), datKey.get_size());
252  ssValue.SetType(SER_DISK);
253  ssValue.clear();
254  ssValue.write((char*)datValue.get_data(), datValue.get_size());
255 
256  // Clear and free memory
257  memset(datKey.get_data(), 0, datKey.get_size());
258  memset(datValue.get_data(), 0, datValue.get_size());
259  free(datKey.get_data());
260  free(datValue.get_data());
261  return 0;
262  }
263 
264 public:
265  bool TxnBegin()
266  {
267  if (!pdb || activeTxn)
268  return false;
269  DbTxn* ptxn = bitdb.TxnBegin();
270  if (!ptxn)
271  return false;
272  activeTxn = ptxn;
273  return true;
274  }
275 
276  bool TxnCommit()
277  {
278  if (!pdb || !activeTxn)
279  return false;
280  int ret = activeTxn->commit(0);
281  activeTxn = NULL;
282  return (ret == 0);
283  }
284 
285  bool TxnAbort()
286  {
287  if (!pdb || !activeTxn)
288  return false;
289  int ret = activeTxn->abort();
290  activeTxn = NULL;
291  return (ret == 0);
292  }
293 
294  bool ReadVersion(int& nVersion)
295  {
296  nVersion = 0;
297  return Read(std::string("version"), nVersion);
298  }
299 
300  bool WriteVersion(int nVersion)
301  {
302  return Write(std::string("version"), nVersion);
303  }
304 
305  bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
306 };
307 
308 #endif // BITCOIN_DB_H
bool Erase(const K &key)
Definition: db.h:173
std::map< std::string, int > mapFileUseCount
Definition: db.h:42
DbTxn * activeTxn
Definition: db.h:95
void CheckpointLSN(std::string strFile)
Definition: db.cpp:215
DbTxn * TxnBegin(int flags=DB_TXN_WRITE_NOSYNC)
Definition: db.h:76
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: core.h:459
int ReadAtCursor(Dbc *pcursor, CDataStream &ssKey, CDataStream &ssValue, unsigned int fFlags=DB_NEXT)
Definition: db.h:225
static bool Rewrite(const std::string &strFile, const char *pszSkip=NULL)
Definition: db.cpp:341
std::string strFile
Definition: db.h:94
bool Write(const K &key, const T &value, bool fOverwrite=true)
Definition: db.h:144
void Close()
Definition: db.cpp:300
static const int CLIENT_VERSION
Definition: version.h:15
std::string strWalletFile
bool fReadOnly
Definition: db.h:96
Dbc * GetCursor()
Definition: db.h:214
void Flush(bool fShutdown)
Definition: db.cpp:435
CDBEnv bitdb
Definition: db.cpp:35
void EnvShutdown()
Definition: db.cpp:37
bool Exists(const K &key)
Definition: db.h:195
Double ended buffer combining vector and stream-like interfaces.
Definition: serialize.h:839
unsigned int nWalletDBUpdated
Definition: db.cpp:27
~CDBEnv()
Definition: db.cpp:56
bool fDbEnvInit
Definition: db.h:33
bool TxnBegin()
Definition: db.h:265
boost::filesystem::path path
Definition: db.h:35
Stochastical (IP) address manager.
Definition: addrman.h:166
void MakeMock()
Definition: db.cpp:111
VerifyResult
Definition: db.h:56
std::map< std::string, Db * > mapDb
Definition: db.h:43
size_type size() const
Definition: serialize.h:928
bool ReadVersion(int &nVersion)
Definition: db.h:294
bool TxnCommit()
Definition: db.h:276
bool TxnAbort()
Definition: db.h:285
RAII class that provides access to a Berkeley database.
Definition: db.h:90
Used to marshal pointers into hashes for db storage.
Definition: main.h:871
CCriticalSection cs_db
Definition: db.h:40
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: core.h:22
bool IsMock()
Definition: db.h:48
bool RemoveDb(const std::string &strFile)
Definition: db.cpp:332
bool Read(const K &key, T &value)
Definition: db.h:109
void operator=(const CDB &)
void Close()
Definition: db.cpp:61
bool Salvage(std::string strFile, bool fAggressive, std::vector< KeyValPair > &vResult)
Definition: db.cpp:160
CDataStream & write(const char *pch, int nSize)
Definition: serialize.h:1085
void reserve(size_type n)
Definition: serialize.h:931
void CloseDb(const std::string &strFile)
Definition: db.cpp:317
bool WriteVersion(int nVersion)
Definition: db.h:300
Definition: db.h:30
CDB(const char *pszFile, const char *pszMode="r+")
Definition: db.cpp:224
bool fMockDb
Definition: db.h:34
VerifyResult Verify(std::string strFile, bool(*recoverFunc)(CDBEnv &dbenv, std::string strFile))
Definition: db.cpp:143
DbEnv dbenv
Definition: db.h:41
void clear()
Definition: serialize.h:934
Db * pdb
Definition: db.h:93
std::pair< std::vector< unsigned char >, std::vector< unsigned char > > KeyValPair
Definition: db.h:65
CDBEnv()
Definition: db.cpp:50
bool Open(const boost::filesystem::path &path)
Definition: db.cpp:66
~CDB()
Definition: db.h:99
void ThreadFlushWalletDB(const std::string &strWalletFile)
Definition: walletdb.cpp:763
void Flush()
Definition: db.cpp:287
void SetType(int n)
Definition: serialize.h:1038