]> Git Repo - VerusCoin.git/blame - db.h
Gavin Andresen: clean shutdown on SIGTERM
[VerusCoin.git] / db.h
CommitLineData
0a61b0df 1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Distributed under the MIT/X11 software license, see the accompanying
3// file license.txt or http://www.opensource.org/licenses/mit-license.php.
4
5class CTransaction;
6class CTxIndex;
7class CDiskBlockIndex;
8class CDiskTxPos;
9class COutPoint;
10class CUser;
11class CReview;
12class CAddress;
13class CWalletTx;
14
15extern map<string, string> mapAddressBook;
16extern CCriticalSection cs_mapAddressBook;
17extern vector<unsigned char> vchDefaultKey;
18extern bool fClient;
19extern int nBestHeight;
20
21
22extern unsigned int nWalletDBUpdated;
23extern DbEnv dbenv;
24
25
26extern void DBFlush(bool fShutdown);
27
28
29
30
31class CDB
32{
33protected:
34 Db* pdb;
35 string strFile;
36 vector<DbTxn*> vTxn;
37 bool fReadOnly;
38
39 explicit CDB(const char* pszFile, const char* pszMode="r+");
40 ~CDB() { Close(); }
41public:
42 void Close();
43private:
44 CDB(const CDB&);
45 void operator=(const CDB&);
46
47protected:
48 template<typename K, typename T>
49 bool Read(const K& key, T& value)
50 {
51 if (!pdb)
52 return false;
53
54 // Key
55 CDataStream ssKey(SER_DISK);
56 ssKey.reserve(1000);
57 ssKey << key;
58 Dbt datKey(&ssKey[0], ssKey.size());
59
60 // Read
61 Dbt datValue;
62 datValue.set_flags(DB_DBT_MALLOC);
63 int ret = pdb->get(GetTxn(), &datKey, &datValue, 0);
64 memset(datKey.get_data(), 0, datKey.get_size());
65 if (datValue.get_data() == NULL)
66 return false;
67
68 // Unserialize value
69 CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK);
70 ssValue >> value;
71
72 // Clear and free memory
73 memset(datValue.get_data(), 0, datValue.get_size());
74 free(datValue.get_data());
75 return (ret == 0);
76 }
77
78 template<typename K, typename T>
79 bool Write(const K& key, const T& value, bool fOverwrite=true)
80 {
81 if (!pdb)
82 return false;
83 if (fReadOnly)
84 assert(("Write called on database in read-only mode", false));
85
86 // Key
87 CDataStream ssKey(SER_DISK);
88 ssKey.reserve(1000);
89 ssKey << key;
90 Dbt datKey(&ssKey[0], ssKey.size());
91
92 // Value
93 CDataStream ssValue(SER_DISK);
94 ssValue.reserve(10000);
95 ssValue << value;
96 Dbt datValue(&ssValue[0], ssValue.size());
97
98 // Write
99 int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
100
101 // Clear memory in case it was a private key
102 memset(datKey.get_data(), 0, datKey.get_size());
103 memset(datValue.get_data(), 0, datValue.get_size());
104 return (ret == 0);
105 }
106
107 template<typename K>
108 bool Erase(const K& key)
109 {
110 if (!pdb)
111 return false;
112 if (fReadOnly)
113 assert(("Erase called on database in read-only mode", false));
114
115 // Key
116 CDataStream ssKey(SER_DISK);
117 ssKey.reserve(1000);
118 ssKey << key;
119 Dbt datKey(&ssKey[0], ssKey.size());
120
121 // Erase
122 int ret = pdb->del(GetTxn(), &datKey, 0);
123
124 // Clear memory
125 memset(datKey.get_data(), 0, datKey.get_size());
126 return (ret == 0 || ret == DB_NOTFOUND);
127 }
128
129 template<typename K>
130 bool Exists(const K& key)
131 {
132 if (!pdb)
133 return false;
134
135 // Key
136 CDataStream ssKey(SER_DISK);
137 ssKey.reserve(1000);
138 ssKey << key;
139 Dbt datKey(&ssKey[0], ssKey.size());
140
141 // Exists
142 int ret = pdb->exists(GetTxn(), &datKey, 0);
143
144 // Clear memory
145 memset(datKey.get_data(), 0, datKey.get_size());
146 return (ret == 0);
147 }
148
149 Dbc* GetCursor()
150 {
151 if (!pdb)
152 return NULL;
153 Dbc* pcursor = NULL;
154 int ret = pdb->cursor(NULL, &pcursor, 0);
155 if (ret != 0)
156 return NULL;
157 return pcursor;
158 }
159
160 int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT)
161 {
162 // Read at cursor
163 Dbt datKey;
164 if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
165 {
166 datKey.set_data(&ssKey[0]);
167 datKey.set_size(ssKey.size());
168 }
169 Dbt datValue;
170 if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE)
171 {
172 datValue.set_data(&ssValue[0]);
173 datValue.set_size(ssValue.size());
174 }
175 datKey.set_flags(DB_DBT_MALLOC);
176 datValue.set_flags(DB_DBT_MALLOC);
177 int ret = pcursor->get(&datKey, &datValue, fFlags);
178 if (ret != 0)
179 return ret;
180 else if (datKey.get_data() == NULL || datValue.get_data() == NULL)
181 return 99999;
182
183 // Convert to streams
184 ssKey.SetType(SER_DISK);
185 ssKey.clear();
186 ssKey.write((char*)datKey.get_data(), datKey.get_size());
187 ssValue.SetType(SER_DISK);
188 ssValue.clear();
189 ssValue.write((char*)datValue.get_data(), datValue.get_size());
190
191 // Clear and free memory
192 memset(datKey.get_data(), 0, datKey.get_size());
193 memset(datValue.get_data(), 0, datValue.get_size());
194 free(datKey.get_data());
195 free(datValue.get_data());
196 return 0;
197 }
198
199 DbTxn* GetTxn()
200 {
201 if (!vTxn.empty())
202 return vTxn.back();
203 else
204 return NULL;
205 }
206
207public:
208 bool TxnBegin()
209 {
210 if (!pdb)
211 return false;
212 DbTxn* ptxn = NULL;
213 int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_NOSYNC);
214 if (!ptxn || ret != 0)
215 return false;
216 vTxn.push_back(ptxn);
217 return true;
218 }
219
220 bool TxnCommit()
221 {
222 if (!pdb)
223 return false;
224 if (vTxn.empty())
225 return false;
226 int ret = vTxn.back()->commit(0);
227 vTxn.pop_back();
228 return (ret == 0);
229 }
230
231 bool TxnAbort()
232 {
233 if (!pdb)
234 return false;
235 if (vTxn.empty())
236 return false;
237 int ret = vTxn.back()->abort();
238 vTxn.pop_back();
239 return (ret == 0);
240 }
241
242 bool ReadVersion(int& nVersion)
243 {
244 nVersion = 0;
245 return Read(string("version"), nVersion);
246 }
247
248 bool WriteVersion(int nVersion)
249 {
250 return Write(string("version"), nVersion);
251 }
252};
253
254
255
256
257
258
259
260
261class CTxDB : public CDB
262{
263public:
264 CTxDB(const char* pszMode="r+") : CDB(!fClient ? "blkindex.dat" : NULL, pszMode) { }
265private:
266 CTxDB(const CTxDB&);
267 void operator=(const CTxDB&);
268public:
269 bool ReadTxIndex(uint256 hash, CTxIndex& txindex);
270 bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex);
271 bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight);
272 bool EraseTxIndex(const CTransaction& tx);
273 bool ContainsTx(uint256 hash);
274 bool ReadOwnerTxes(uint160 hash160, int nHeight, vector<CTransaction>& vtx);
275 bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex);
276 bool ReadDiskTx(uint256 hash, CTransaction& tx);
277 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex);
278 bool ReadDiskTx(COutPoint outpoint, CTransaction& tx);
279 bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
280 bool EraseBlockIndex(uint256 hash);
281 bool ReadHashBestChain(uint256& hashBestChain);
282 bool WriteHashBestChain(uint256 hashBestChain);
283 bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork);
284 bool WriteBestInvalidWork(CBigNum bnBestInvalidWork);
285 bool LoadBlockIndex();
286};
287
288
289
290
291
292class CAddrDB : public CDB
293{
294public:
295 CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { }
296private:
297 CAddrDB(const CAddrDB&);
298 void operator=(const CAddrDB&);
299public:
300 bool WriteAddress(const CAddress& addr);
301 bool LoadAddresses();
302};
303
304bool LoadAddresses();
305
306
307
308
309
310
311class CWalletDB : public CDB
312{
313public:
314 CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode) { }
315private:
316 CWalletDB(const CWalletDB&);
317 void operator=(const CWalletDB&);
318public:
319 bool ReadName(const string& strAddress, string& strName)
320 {
321 strName = "";
322 return Read(make_pair(string("name"), strAddress), strName);
323 }
324
325 bool WriteName(const string& strAddress, const string& strName)
326 {
327 CRITICAL_BLOCK(cs_mapAddressBook)
328 mapAddressBook[strAddress] = strName;
329 nWalletDBUpdated++;
330 return Write(make_pair(string("name"), strAddress), strName);
331 }
332
333 bool EraseName(const string& strAddress)
334 {
335 // This should only be used for sending addresses, never for receiving addresses,
336 // receiving addresses must always have an address book entry if they're not change return.
337 CRITICAL_BLOCK(cs_mapAddressBook)
338 mapAddressBook.erase(strAddress);
339 nWalletDBUpdated++;
340 return Erase(make_pair(string("name"), strAddress));
341 }
342
343 bool ReadTx(uint256 hash, CWalletTx& wtx)
344 {
345 return Read(make_pair(string("tx"), hash), wtx);
346 }
347
348 bool WriteTx(uint256 hash, const CWalletTx& wtx)
349 {
350 nWalletDBUpdated++;
351 return Write(make_pair(string("tx"), hash), wtx);
352 }
353
354 bool EraseTx(uint256 hash)
355 {
356 nWalletDBUpdated++;
357 return Erase(make_pair(string("tx"), hash));
358 }
359
360 bool ReadKey(const vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey)
361 {
362 vchPrivKey.clear();
363 return Read(make_pair(string("key"), vchPubKey), vchPrivKey);
364 }
365
366 bool WriteKey(const vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey)
367 {
368 nWalletDBUpdated++;
369 return Write(make_pair(string("key"), vchPubKey), vchPrivKey, false);
370 }
371
372 bool ReadDefaultKey(vector<unsigned char>& vchPubKey)
373 {
374 vchPubKey.clear();
375 return Read(string("defaultkey"), vchPubKey);
376 }
377
378 bool WriteDefaultKey(const vector<unsigned char>& vchPubKey)
379 {
380 vchDefaultKey = vchPubKey;
381 nWalletDBUpdated++;
382 return Write(string("defaultkey"), vchPubKey);
383 }
384
385 template<typename T>
386 bool ReadSetting(const string& strKey, T& value)
387 {
388 return Read(make_pair(string("setting"), strKey), value);
389 }
390
391 template<typename T>
392 bool WriteSetting(const string& strKey, const T& value)
393 {
394 nWalletDBUpdated++;
395 return Write(make_pair(string("setting"), strKey), value);
396 }
397
398 bool LoadWallet();
399};
400
401bool LoadWallet(bool& fFirstRunRet);
d743f035 402void BackupWallet(const string& strDest);
0a61b0df 403
404inline bool SetAddressBookName(const string& strAddress, const string& strName)
405{
406 return CWalletDB().WriteName(strAddress, strName);
407}
This page took 0.068054 seconds and 4 git commands to generate.