PRCYCoin  2.0.0.7rc1
P2P Digital Currency
db.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin 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_DB_H
7 #define BITCOIN_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 <map>
17 #include <string>
18 #include <vector>
19 
20 
21 #include <db_cxx.h>
22 
23 class CDiskBlockIndex;
24 class COutPoint;
25 
26 struct CBlockLocator;
27 
28 class CDBEnv
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  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 Reset();
48 
49  void MakeMock();
50  bool IsMock() { return fMockDb; }
51 
61  VerifyResult Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile));
69  bool Compact(const std::string& strFile);
70  typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair;
71  bool Salvage(std::string strFile, bool fAggressive, std::vector<KeyValPair>& vResult);
72 
73  bool Open(const fs::path& path);
74  void Close();
75  void Flush(bool fShutdown);
76  void CheckpointLSN(const std::string& strFile);
77 
78  void CloseDb(const std::string& strFile);
79  bool RemoveDb(const std::string& strFile);
80 
81  DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC)
82  {
83  DbTxn* ptxn = NULL;
84  int ret = dbenv->txn_begin(NULL, &ptxn, flags);
85  if (!ptxn || ret != 0)
86  return NULL;
87  return ptxn;
88  }
89 };
90 
91 extern CDBEnv bitdb;
92 
93 
95 class CDB
96 {
97 protected:
98  Db* pdb;
99  std::string strFile;
100  DbTxn* activeTxn;
101  bool fReadOnly;
103 
104  explicit CDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnCloseIn=true);
105  ~CDB() { Close(); }
106 
107 public:
108  void Flush();
109  void Close();
110 
111 private:
112  CDB(const CDB&);
113  void operator=(const CDB&);
114 
115 protected:
116  template <typename K, typename T>
117  bool Read(const K& key, T& value)
118  {
119  if (!pdb)
120  return false;
121 
122  // Key
123  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
124  ssKey.reserve(1000);
125  ssKey << key;
126  Dbt datKey(&ssKey[0], ssKey.size());
127 
128  // Read
129  Dbt datValue;
130  datValue.set_flags(DB_DBT_MALLOC);
131  int ret = pdb->get(activeTxn, &datKey, &datValue, 0);
132  memory_cleanse(datKey.get_data(), datKey.get_size());
133  bool success = false;
134  if (datValue.get_data() != NULL) {
135  // Unserialize value
136  try {
137  CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
138  ssValue >> value;
139  success = true;
140  } catch (const std::exception&) {
141  // In this case success remains 'false'
142  }
143 
144  // Clear and free memory
145  memory_cleanse(datValue.get_data(), datValue.get_size());
146  free(datValue.get_data());
147  }
148  return ret == 0 && success;
149  }
150 
151  template <typename K, typename T>
152  bool Write(const K& key, const T& value, bool fOverwrite = true)
153  {
154  if (!pdb)
155  return false;
156  if (fReadOnly)
157  assert(!"Write called on database in read-only mode");
158 
159  // Key
160  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
161  ssKey.reserve(1000);
162  ssKey << key;
163  Dbt datKey(&ssKey[0], ssKey.size());
164 
165  // Value
166  CDataStream ssValue(SER_DISK, CLIENT_VERSION);
167  ssValue.reserve(10000);
168  ssValue << value;
169  Dbt datValue(&ssValue[0], ssValue.size());
170 
171  // Write
172  int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
173 
174  // Clear memory in case it was a private key
175  memory_cleanse(datKey.get_data(), datKey.get_size());
176  memory_cleanse(datValue.get_data(), datValue.get_size());
177  return (ret == 0);
178  }
179 
180  template <typename K>
181  bool Erase(const K& key)
182  {
183  if (!pdb)
184  return false;
185  if (fReadOnly)
186  assert(!"Erase called on database in read-only mode");
187 
188  // Key
189  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
190  ssKey.reserve(1000);
191  ssKey << key;
192  Dbt datKey(&ssKey[0], ssKey.size());
193 
194  // Erase
195  int ret = pdb->del(activeTxn, &datKey, 0);
196 
197  // Clear memory
198  memory_cleanse(datKey.get_data(), datKey.get_size());
199  return (ret == 0 || ret == DB_NOTFOUND);
200  }
201 
202  template <typename K>
203  bool Exists(const K& key)
204  {
205  if (!pdb)
206  return false;
207 
208  // Key
209  CDataStream ssKey(SER_DISK, CLIENT_VERSION);
210  ssKey.reserve(1000);
211  ssKey << key;
212  Dbt datKey(&ssKey[0], ssKey.size());
213 
214  // Exists
215  int ret = pdb->exists(activeTxn, &datKey, 0);
216 
217  // Clear memory
218  memory_cleanse(datKey.get_data(), datKey.get_size());
219  return (ret == 0);
220  }
221 
222  Dbc* GetCursor()
223  {
224  if (!pdb)
225  return NULL;
226  Dbc* pcursor = NULL;
227  int ret = pdb->cursor(NULL, &pcursor, 0);
228  if (ret != 0)
229  return NULL;
230  return pcursor;
231  }
232 
233  int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags = DB_NEXT)
234  {
235  // Read at cursor
236  Dbt datKey;
237  datKey.set_data(NULL);
238  if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) {
239  datKey.set_data(&ssKey[0]);
240  datKey.set_size(ssKey.size());
241  }
242  Dbt datValue;
243  datValue.set_data(NULL);
244  if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) {
245  datValue.set_data(&ssValue[0]);
246  datValue.set_size(ssValue.size());
247  }
248  datKey.set_flags(DB_DBT_MALLOC);
249  datValue.set_flags(DB_DBT_MALLOC);
250  int ret = pcursor->get(&datKey, &datValue, fFlags);
251  if (ret != 0) {
252  if (datKey.get_data() != NULL)
253  free(datKey.get_data());
254  if (datValue.get_data() != NULL)
255  free(datValue.get_data());
256 
257  return ret;
258  }
259  else if (datKey.get_data() == NULL || datValue.get_data() == NULL) {
260  if (datKey.get_data() != NULL)
261  free(datKey.get_data());
262  if (datValue.get_data() != NULL)
263  free(datValue.get_data());
264 
265  return 99999;
266  }
267 
268  // Convert to streams
269  ssKey.SetType(SER_DISK);
270  ssKey.clear();
271  ssKey.write((char*)datKey.get_data(), datKey.get_size());
272  ssValue.SetType(SER_DISK);
273  ssValue.clear();
274  ssValue.write((char*)datValue.get_data(), datValue.get_size());
275 
276  // Clear and free memory
277  memory_cleanse(datKey.get_data(), datKey.get_size());
278  memory_cleanse(datValue.get_data(), datValue.get_size());
279  free(datKey.get_data());
280  free(datValue.get_data());
281  return 0;
282  }
283 
284 public:
285  bool TxnBegin()
286  {
287  if (!pdb || activeTxn)
288  return false;
289  DbTxn* ptxn = bitdb.TxnBegin();
290  if (!ptxn)
291  return false;
292  activeTxn = ptxn;
293  return true;
294  }
295 
296  bool TxnCommit()
297  {
298  if (!pdb || !activeTxn)
299  return false;
300  int ret = activeTxn->commit(0);
301  activeTxn = NULL;
302  return (ret == 0);
303  }
304 
305  bool TxnAbort()
306  {
307  if (!pdb || !activeTxn)
308  return false;
309  int ret = activeTxn->abort();
310  activeTxn = NULL;
311  return (ret == 0);
312  }
313 
314  bool ReadVersion(int& nVersion)
315  {
316  nVersion = 0;
317  return Read(std::string("version"), nVersion);
318  }
319 
320  bool WriteVersion(int nVersion)
321  {
322  return Write(std::string("version"), nVersion);
323  }
324 
325  bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
326 };
327 
328 #endif // BITCOIN_DB_H
CDBEnv::VERIFY_OK
@ VERIFY_OK
Definition: db.h:58
CDBEnv::VerifyResult
VerifyResult
Verify that database file strFile is OK.
Definition: db.h:58
CDBEnv::cs_db
RecursiveMutex cs_db
Definition: db.h:40
CDB::TxnCommit
bool TxnCommit()
Definition: db.h:296
CDBEnv::RemoveDb
bool RemoveDb(const std::string &strFile)
Definition: db.cpp:378
CDB::Exists
bool Exists(const K &key)
Definition: db.h:203
fs.h
streams.h
CDB::Flush
void Flush()
Definition: db.cpp:333
sync.h
CDB::~CDB
~CDB()
Definition: db.h:105
CDBEnv::Salvage
bool Salvage(std::string strFile, bool fAggressive, std::vector< KeyValPair > &vResult)
Definition: db.cpp:214
flags
int flags
Definition: prcycoin-tx.cpp:297
CDBEnv::Close
void Close()
Definition: db.cpp:64
AnnotatedMixin< std::recursive_mutex >
clientversion.h
CDBEnv::Verify
VerifyResult Verify(std::string strFile, bool(*recoverFunc)(CDBEnv &dbenv, std::string strFile))
Definition: db.cpp:148
CDBEnv::Open
bool Open(const fs::path &path)
Definition: db.cpp:69
CDBEnv
Definition: db.h:28
CDBEnv::fMockDb
bool fMockDb
Definition: db.h:32
CDBEnv::CDBEnv
CDBEnv()
Definition: db.cpp:52
CDB::activeTxn
DbTxn * activeTxn
Definition: db.h:100
CDiskBlockIndex
Used to marshal pointers into hashes for db storage.
Definition: chain.h:485
memory_cleanse
void memory_cleanse(void *ptr, size_t len)
Definition: cleanse.cpp:27
CDBEnv::CloseDb
void CloseDb(const std::string &strFile)
Definition: db.cpp:364
CDB::Rewrite
static bool Rewrite(const std::string &strFile, const char *pszSkip=NULL)
Definition: db.cpp:387
version.h
CDB::ReadVersion
bool ReadVersion(int &nVersion)
Definition: db.h:314
CDBEnv::KeyValPair
std::pair< std::vector< unsigned char >, std::vector< unsigned char > > KeyValPair
Definition: db.h:70
CDB::WriteVersion
bool WriteVersion(int nVersion)
Definition: db.h:320
CDB::fReadOnly
bool fReadOnly
Definition: db.h:101
CDBEnv::CheckpointLSN
void CheckpointLSN(const std::string &strFile)
Definition: db.cpp:264
CDB
RAII class that provides access to a Berkeley database.
Definition: db.h:95
CDB::Read
bool Read(const K &key, T &value)
Definition: db.h:117
bitdb
CDBEnv bitdb
Definition: db.cpp:29
CDB::pdb
Db * pdb
Definition: db.h:98
CDBEnv::Reset
void Reset()
Definition: db.cpp:44
CDB::Erase
bool Erase(const K &key)
Definition: db.h:181
CDBEnv::RECOVER_OK
@ RECOVER_OK
Definition: db.h:59
CDB::fFlushOnClose
bool fFlushOnClose
Definition: db.h:102
CDBEnv::dbenv
DbEnv * dbenv
Definition: db.h:41
CDB::ReadAtCursor
int ReadAtCursor(Dbc *pcursor, CDataStream &ssKey, CDataStream &ssValue, unsigned int fFlags=DB_NEXT)
Definition: db.h:233
SER_DISK
@ SER_DISK
Definition: serialize.h:160
CDBEnv::Flush
void Flush(bool fShutdown)
Definition: db.cpp:473
CDBEnv::EnvShutdown
void EnvShutdown()
Definition: db.cpp:31
CDataStream::reserve
void reserve(size_type n)
Definition: streams.h:123
CDataStream::size
size_type size() const
Definition: streams.h:120
CDBEnv::mapFileUseCount
std::map< std::string, int > mapFileUseCount
Definition: db.h:42
CDB::GetCursor
Dbc * GetCursor()
Definition: db.h:222
CDataStream::clear
void clear()
Definition: streams.h:126
CDBEnv::TxnBegin
DbTxn * TxnBegin(int flags=DB_TXN_WRITE_NOSYNC)
Definition: db.h:81
key
CKey key
Definition: bip38tooldialog.cpp:173
CDB::Close
void Close()
Definition: db.cpp:346
CDBEnv::Compact
bool Compact(const std::string &strFile)
Salvage data from a file that Verify says is bad.
Definition: db.cpp:165
CDBEnv::strPath
std::string strPath
Definition: db.h:35
CDB::operator=
void operator=(const CDB &)
serialize.h
CDataStream
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:34
CDB::TxnBegin
bool TxnBegin()
Definition: db.h:285
COutPoint
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:36
CDBEnv::MakeMock
void MakeMock()
Definition: db.cpp:116
CBlockLocator
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
Definition: block.h:249
CDBEnv::fDbEnvInit
bool fDbEnvInit
Definition: db.h:31
CDataStream::SetType
void SetType(int n)
Definition: streams.h:210
CDBEnv::mapDb
std::map< std::string, Db * > mapDb
Definition: db.h:43
CDBEnv::~CDBEnv
~CDBEnv()
Definition: db.cpp:57
CDBEnv::RECOVER_FAIL
@ RECOVER_FAIL
Definition: db.h:60
CDBEnv::IsMock
bool IsMock()
Definition: db.h:50
CDataStream::write
CDataStream & write(const char *pch, size_t nSize)
Definition: streams.h:251
CDB::Write
bool Write(const K &key, const T &value, bool fOverwrite=true)
Definition: db.h:152
CDB::TxnAbort
bool TxnAbort()
Definition: db.h:305
CDB::CDB
CDB(const std::string &strFilename, const char *pszMode="r+", bool fFlushOnCloseIn=true)
Definition: db.cpp:273
CDB::strFile
std::string strFile
Definition: db.h:99