]> Git Repo - VerusCoin.git/blob - src/db.h
Merge branch 'loaderror' of git://github.com/sipa/bitcoin
[VerusCoin.git] / src / db.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 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 #ifndef BITCOIN_DB_H
6 #define BITCOIN_DB_H
7
8 #include "main.h"
9
10 #include <map>
11 #include <string>
12 #include <vector>
13
14 #include <db_cxx.h>
15
16 class CAddress;
17 class CAddrMan;
18 class CBlockLocator;
19 class CDiskBlockIndex;
20 class CMasterKey;
21 class COutPoint;
22 class CWallet;
23 class CWalletTx;
24
25 extern unsigned int nWalletDBUpdated;
26
27 void ThreadFlushWalletDB(void* parg);
28 bool BackupWallet(const CWallet& wallet, const std::string& strDest);
29
30
31 class CDBEnv
32 {
33 private:
34     bool fDbEnvInit;
35     bool fMockDb;
36     std::string strPath;
37
38     void EnvShutdown();
39
40 public:
41     mutable CCriticalSection cs_db;
42     DbEnv dbenv;
43     std::map<std::string, int> mapFileUseCount;
44     std::map<std::string, Db*> mapDb;
45
46     CDBEnv();
47     ~CDBEnv();
48     void MakeMock();
49     bool IsMock() { return fMockDb; }
50
51     /*
52      * Verify that database file strFile is OK. If it is not,
53      * call the callback to try to recover.
54      * This must be called BEFORE strFile is opened.
55      * Returns true if strFile is OK.
56      */
57     enum VerifyResult { VERIFY_OK, RECOVER_OK, RECOVER_FAIL };
58     VerifyResult Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile));
59     /*
60      * Salvage data from a file that Verify says is bad.
61      * fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation).
62      * Appends binary key/value pairs to vResult, returns true if successful.
63      * NOTE: reads the entire database into memory, so cannot be used
64      * for huge databases.
65      */
66     typedef std::pair<std::vector<unsigned char>, std::vector<unsigned char> > KeyValPair;
67     bool Salvage(std::string strFile, bool fAggressive, std::vector<KeyValPair>& vResult);
68
69     bool Open(const boost::filesystem::path &path);
70     void Close();
71     void Flush(bool fShutdown);
72     void CheckpointLSN(std::string strFile);
73
74     void CloseDb(const std::string& strFile);
75     bool RemoveDb(const std::string& strFile);
76
77     DbTxn *TxnBegin(int flags=DB_TXN_WRITE_NOSYNC)
78     {
79         DbTxn* ptxn = NULL;
80         int ret = dbenv.txn_begin(NULL, &ptxn, flags);
81         if (!ptxn || ret != 0)
82             return NULL;
83         return ptxn;
84     }
85 };
86
87 extern CDBEnv bitdb;
88
89
90 /** RAII class that provides access to a Berkeley database */
91 class CDB
92 {
93 protected:
94     Db* pdb;
95     std::string strFile;
96     DbTxn *activeTxn;
97     bool fReadOnly;
98
99     explicit CDB(const char* pszFile, const char* pszMode="r+");
100     ~CDB() { Close(); }
101 public:
102     void Flush();
103     void Close();
104 private:
105     CDB(const CDB&);
106     void operator=(const CDB&);
107
108 protected:
109     template<typename K, typename T>
110     bool Read(const K& key, T& value)
111     {
112         if (!pdb)
113             return false;
114
115         // Key
116         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
117         ssKey.reserve(1000);
118         ssKey << key;
119         Dbt datKey(&ssKey[0], ssKey.size());
120
121         // Read
122         Dbt datValue;
123         datValue.set_flags(DB_DBT_MALLOC);
124         int ret = pdb->get(activeTxn, &datKey, &datValue, 0);
125         memset(datKey.get_data(), 0, datKey.get_size());
126         if (datValue.get_data() == NULL)
127             return false;
128
129         // Unserialize value
130         try {
131             CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
132             ssValue >> value;
133         }
134         catch (std::exception &e) {
135             return false;
136         }
137
138         // Clear and free memory
139         memset(datValue.get_data(), 0, datValue.get_size());
140         free(datValue.get_data());
141         return (ret == 0);
142     }
143
144     template<typename K, typename T>
145     bool Write(const K& key, const T& value, bool fOverwrite=true)
146     {
147         if (!pdb)
148             return false;
149         if (fReadOnly)
150             assert(!"Write called on database in read-only mode");
151
152         // Key
153         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
154         ssKey.reserve(1000);
155         ssKey << key;
156         Dbt datKey(&ssKey[0], ssKey.size());
157
158         // Value
159         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
160         ssValue.reserve(10000);
161         ssValue << value;
162         Dbt datValue(&ssValue[0], ssValue.size());
163
164         // Write
165         int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
166
167         // Clear memory in case it was a private key
168         memset(datKey.get_data(), 0, datKey.get_size());
169         memset(datValue.get_data(), 0, datValue.get_size());
170         return (ret == 0);
171     }
172
173     template<typename K>
174     bool Erase(const K& key)
175     {
176         if (!pdb)
177             return false;
178         if (fReadOnly)
179             assert(!"Erase called on database in read-only mode");
180
181         // Key
182         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
183         ssKey.reserve(1000);
184         ssKey << key;
185         Dbt datKey(&ssKey[0], ssKey.size());
186
187         // Erase
188         int ret = pdb->del(activeTxn, &datKey, 0);
189
190         // Clear memory
191         memset(datKey.get_data(), 0, datKey.get_size());
192         return (ret == 0 || ret == DB_NOTFOUND);
193     }
194
195     template<typename K>
196     bool Exists(const K& key)
197     {
198         if (!pdb)
199             return false;
200
201         // Key
202         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
203         ssKey.reserve(1000);
204         ssKey << key;
205         Dbt datKey(&ssKey[0], ssKey.size());
206
207         // Exists
208         int ret = pdb->exists(activeTxn, &datKey, 0);
209
210         // Clear memory
211         memset(datKey.get_data(), 0, datKey.get_size());
212         return (ret == 0);
213     }
214
215     Dbc* GetCursor()
216     {
217         if (!pdb)
218             return NULL;
219         Dbc* pcursor = NULL;
220         int ret = pdb->cursor(NULL, &pcursor, 0);
221         if (ret != 0)
222             return NULL;
223         return pcursor;
224     }
225
226     int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
227     {
228         // Read at cursor
229         Dbt datKey;
230         if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
231         {
232             datKey.set_data(&ssKey[0]);
233             datKey.set_size(ssKey.size());
234         }
235         Dbt datValue;
236         if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
237         {
238             datValue.set_data(&ssValue[0]);
239             datValue.set_size(ssValue.size());
240         }
241         datKey.set_flags(DB_DBT_MALLOC);
242         datValue.set_flags(DB_DBT_MALLOC);
243         int ret = pcursor->get(&datKey, &datValue, fFlags);
244         if (ret != 0)
245             return ret;
246         else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
247             return 99999;
248
249         // Convert to streams
250         ssKey.SetType(SER_DISK);
251         ssKey.clear();
252         ssKey.write((char*)datKey.get_data(), datKey.get_size());
253         ssValue.SetType(SER_DISK);
254         ssValue.clear();
255         ssValue.write((char*)datValue.get_data(), datValue.get_size());
256
257         // Clear and free memory
258         memset(datKey.get_data(), 0, datKey.get_size());
259         memset(datValue.get_data(), 0, datValue.get_size());
260         free(datKey.get_data());
261         free(datValue.get_data());
262         return 0;
263     }
264
265 public:
266     bool TxnBegin()
267     {
268         if (!pdb || activeTxn)
269             return false;
270         DbTxn* ptxn = bitdb.TxnBegin();
271         if (!ptxn)
272             return false;
273         activeTxn = ptxn;
274         return true;
275     }
276
277     bool TxnCommit()
278     {
279         if (!pdb || !activeTxn)
280             return false;
281         int ret = activeTxn->commit(0);
282         activeTxn = NULL;
283         return (ret == 0);
284     }
285
286     bool TxnAbort()
287     {
288         if (!pdb || !activeTxn)
289             return false;
290         int ret = activeTxn->abort();
291         activeTxn = NULL;
292         return (ret == 0);
293     }
294
295     bool ReadVersion(int& nVersion)
296     {
297         nVersion = 0;
298         return Read(std::string("version"), nVersion);
299     }
300
301     bool WriteVersion(int nVersion)
302     {
303         return Write(std::string("version"), nVersion);
304     }
305
306     bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
307 };
308
309
310
311
312
313
314
315
316 /** Access to the (IP) address database (peers.dat) */
317 class CAddrDB
318 {
319 private:
320     boost::filesystem::path pathAddr;
321 public:
322     CAddrDB();
323     bool Write(const CAddrMan& addr);
324     bool Read(CAddrMan& addr);
325 };
326
327 #endif // BITCOIN_DB_H
This page took 0.042403 seconds and 4 git commands to generate.