1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 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.
6 #ifndef BITCOIN_WALLET_DB_H
7 #define BITCOIN_WALLET_DB_H
9 #include "clientversion.h"
10 #include "serialize.h"
19 #include <boost/filesystem/path.hpp>
23 static const unsigned int DEFAULT_WALLET_DBLOGSIZE
= 100;
25 extern unsigned int nWalletDBUpdated
;
32 // Don't change into boost::filesystem::path, as that can result in
33 // shutdown problems/crashes caused by a static initialized internal pointer.
39 mutable CCriticalSection cs_db
;
41 std::map
<std::string
, int> mapFileUseCount
;
42 std::map
<std::string
, Db
*> mapDb
;
49 bool IsMock() { return fMockDb
; }
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.
57 enum VerifyResult
{ VERIFY_OK
,
60 VerifyResult
Verify(const std::string
& strFile
, bool (*recoverFunc
)(CDBEnv
& dbenv
, const std::string
& strFile
));
62 * Salvage data from a file that Verify says is bad.
63 * fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation).
64 * Appends binary key/value pairs to vResult, returns true if successful.
65 * NOTE: reads the entire database into memory, so cannot be used
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
);
71 bool Open(const boost::filesystem::path
& path
);
73 void Flush(bool fShutdown
);
74 void CheckpointLSN(const std::string
& strFile
);
76 void CloseDb(const std::string
& strFile
);
77 bool RemoveDb(const std::string
& strFile
);
79 DbTxn
* TxnBegin(int flags
= DB_TXN_WRITE_NOSYNC
)
82 int ret
= dbenv
->txn_begin(NULL
, &ptxn
, flags
);
83 if (!ptxn
|| ret
!= 0)
92 /** RAII class that provides access to a Berkeley database */
102 explicit CDB(const std::string
& strFilename
, const char* pszMode
= "r+", bool fFlushOnCloseIn
=true);
111 void operator=(const CDB
&);
114 template <typename K
, typename T
>
115 bool Read(const K
& key
, T
& value
)
121 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
124 Dbt
datKey(&ssKey
[0], ssKey
.size());
128 datValue
.set_flags(DB_DBT_MALLOC
);
129 int ret
= pdb
->get(activeTxn
, &datKey
, &datValue
, 0);
130 memset(datKey
.get_data(), 0, datKey
.get_size());
131 if (datValue
.get_data() == NULL
)
136 CDataStream
ssValue((char*)datValue
.get_data(), (char*)datValue
.get_data() + datValue
.get_size(), SER_DISK
, CLIENT_VERSION
);
138 } catch (const std::exception
&) {
142 // Clear and free memory
143 memset(datValue
.get_data(), 0, datValue
.get_size());
144 free(datValue
.get_data());
148 template <typename K
, typename T
>
149 bool Write(const K
& key
, const T
& value
, bool fOverwrite
= true)
154 assert(!"Write called on database in read-only mode");
157 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
160 Dbt
datKey(&ssKey
[0], ssKey
.size());
163 CDataStream
ssValue(SER_DISK
, CLIENT_VERSION
);
164 ssValue
.reserve(10000);
166 Dbt
datValue(&ssValue
[0], ssValue
.size());
169 int ret
= pdb
->put(activeTxn
, &datKey
, &datValue
, (fOverwrite
? 0 : DB_NOOVERWRITE
));
171 // Clear memory in case it was a private key
172 memset(datKey
.get_data(), 0, datKey
.get_size());
173 memset(datValue
.get_data(), 0, datValue
.get_size());
177 template <typename K
>
178 bool Erase(const K
& key
)
183 assert(!"Erase called on database in read-only mode");
186 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
189 Dbt
datKey(&ssKey
[0], ssKey
.size());
192 int ret
= pdb
->del(activeTxn
, &datKey
, 0);
195 memset(datKey
.get_data(), 0, datKey
.get_size());
196 return (ret
== 0 || ret
== DB_NOTFOUND
);
199 template <typename K
>
200 bool Exists(const K
& key
)
206 CDataStream
ssKey(SER_DISK
, CLIENT_VERSION
);
209 Dbt
datKey(&ssKey
[0], ssKey
.size());
212 int ret
= pdb
->exists(activeTxn
, &datKey
, 0);
215 memset(datKey
.get_data(), 0, datKey
.get_size());
224 int ret
= pdb
->cursor(NULL
, &pcursor
, 0);
230 int ReadAtCursor(Dbc
* pcursor
, CDataStream
& ssKey
, CDataStream
& ssValue
, unsigned int fFlags
= DB_NEXT
)
234 if (fFlags
== DB_SET
|| fFlags
== DB_SET_RANGE
|| fFlags
== DB_GET_BOTH
|| fFlags
== DB_GET_BOTH_RANGE
) {
235 datKey
.set_data(&ssKey
[0]);
236 datKey
.set_size(ssKey
.size());
239 if (fFlags
== DB_GET_BOTH
|| fFlags
== DB_GET_BOTH_RANGE
) {
240 datValue
.set_data(&ssValue
[0]);
241 datValue
.set_size(ssValue
.size());
243 datKey
.set_flags(DB_DBT_MALLOC
);
244 datValue
.set_flags(DB_DBT_MALLOC
);
245 int ret
= pcursor
->get(&datKey
, &datValue
, fFlags
);
248 else if (datKey
.get_data() == NULL
|| datValue
.get_data() == NULL
)
251 // Convert to streams
252 ssKey
.SetType(SER_DISK
);
254 ssKey
.write((char*)datKey
.get_data(), datKey
.get_size());
255 ssValue
.SetType(SER_DISK
);
257 ssValue
.write((char*)datValue
.get_data(), datValue
.get_size());
259 // Clear and free memory
260 memset(datKey
.get_data(), 0, datKey
.get_size());
261 memset(datValue
.get_data(), 0, datValue
.get_size());
262 free(datKey
.get_data());
263 free(datValue
.get_data());
270 if (!pdb
|| activeTxn
)
272 DbTxn
* ptxn
= bitdb
.TxnBegin();
281 if (!pdb
|| !activeTxn
)
283 int ret
= activeTxn
->commit(0);
290 if (!pdb
|| !activeTxn
)
292 int ret
= activeTxn
->abort();
297 bool ReadVersion(int& nVersion
)
300 return Read(std::string("version"), nVersion
);
303 bool WriteVersion(int nVersion
)
305 return Write(std::string("version"), nVersion
);
308 bool static Rewrite(const std::string
& strFile
, const char* pszSkip
= NULL
);
311 #endif // BITCOIN_WALLET_DB_H