Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/bdb.h
Show First 20 Lines • Show All 221 Lines • ▼ Show 20 Lines | public: | ||||
// delegate to Dbt | // delegate to Dbt | ||||
const void *get_data() const; | const void *get_data() const; | ||||
u_int32_t get_size() const; | u_int32_t get_size() const; | ||||
// conversion operator to access the underlying Dbt | // conversion operator to access the underlying Dbt | ||||
operator Dbt *(); | operator Dbt *(); | ||||
}; | }; | ||||
private: | |||||
bool ReadKey(CDataStream &key, CDataStream &value); | |||||
bool WriteKey(CDataStream &key, CDataStream &value, bool overwrite = true); | |||||
bool EraseKey(CDataStream &key); | |||||
bool HasKey(CDataStream &key); | |||||
protected: | protected: | ||||
Db *pdb; | Db *pdb; | ||||
std::string strFile; | std::string strFile; | ||||
DbTxn *activeTxn; | DbTxn *activeTxn; | ||||
bool fReadOnly; | bool fReadOnly; | ||||
bool fFlushOnClose; | bool fFlushOnClose; | ||||
BerkeleyEnvironment *env; | BerkeleyEnvironment *env; | ||||
public: | public: | ||||
explicit BerkeleyBatch(BerkeleyDatabase &database, | explicit BerkeleyBatch(BerkeleyDatabase &database, | ||||
const char *pszMode = "r+", | const char *pszMode = "r+", | ||||
bool fFlushOnCloseIn = true); | bool fFlushOnCloseIn = true); | ||||
~BerkeleyBatch() { Close(); } | ~BerkeleyBatch() { Close(); } | ||||
BerkeleyBatch(const BerkeleyBatch &) = delete; | BerkeleyBatch(const BerkeleyBatch &) = delete; | ||||
BerkeleyBatch &operator=(const BerkeleyBatch &) = delete; | BerkeleyBatch &operator=(const BerkeleyBatch &) = delete; | ||||
void Flush(); | void Flush(); | ||||
void Close(); | void Close(); | ||||
template <typename K, typename T> bool Read(const K &key, T &value) { | template <typename K, typename T> bool Read(const K &key, T &value) { | ||||
if (!pdb) { | |||||
return false; | |||||
} | |||||
// Key | // Key | ||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION); | CDataStream ssKey(SER_DISK, CLIENT_VERSION); | ||||
ssKey.reserve(1000); | ssKey.reserve(1000); | ||||
ssKey << key; | ssKey << key; | ||||
SafeDbt datKey(ssKey.data(), ssKey.size()); | |||||
// Read | CDataStream ssValue(SER_DISK, CLIENT_VERSION); | ||||
SafeDbt datValue; | |||||
int ret = pdb->get(activeTxn, datKey, datValue, 0); | |||||
bool success = false; | bool success = false; | ||||
if (datValue.get_data() != nullptr) { | bool ret = ReadKey(ssKey, ssValue); | ||||
if (ret) { | |||||
// Unserialize value | // Unserialize value | ||||
try { | try { | ||||
CDataStream ssValue((char *)datValue.get_data(), | |||||
(char *)datValue.get_data() + | |||||
datValue.get_size(), | |||||
SER_DISK, CLIENT_VERSION); | |||||
ssValue >> value; | ssValue >> value; | ||||
success = true; | success = true; | ||||
} catch (const std::exception &) { | } catch (const std::exception &) { | ||||
// In this case success remains 'false' | // In this case success remains 'false' | ||||
} | } | ||||
} | } | ||||
return ret == 0 && success; | return ret && success; | ||||
} | } | ||||
template <typename K, typename T> | template <typename K, typename T> | ||||
bool Write(const K &key, const T &value, bool fOverwrite = true) { | bool Write(const K &key, const T &value, bool fOverwrite = true) { | ||||
if (!pdb) { | |||||
return true; | |||||
} | |||||
if (fReadOnly) { | |||||
assert(!"Write called on database in read-only mode"); | |||||
} | |||||
// Key | // Key | ||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION); | CDataStream ssKey(SER_DISK, CLIENT_VERSION); | ||||
ssKey.reserve(1000); | ssKey.reserve(1000); | ||||
ssKey << key; | ssKey << key; | ||||
SafeDbt datKey(ssKey.data(), ssKey.size()); | |||||
// Value | // Value | ||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION); | CDataStream ssValue(SER_DISK, CLIENT_VERSION); | ||||
ssValue.reserve(10000); | ssValue.reserve(10000); | ||||
ssValue << value; | ssValue << value; | ||||
SafeDbt datValue(ssValue.data(), ssValue.size()); | |||||
// Write | // Write | ||||
int ret = pdb->put(activeTxn, datKey, datValue, | return WriteKey(ssKey, ssValue, fOverwrite); | ||||
(fOverwrite ? 0 : DB_NOOVERWRITE)); | |||||
return (ret == 0); | |||||
} | } | ||||
template <typename K> bool Erase(const K &key) { | template <typename K> bool Erase(const K &key) { | ||||
if (!pdb) { | |||||
return false; | |||||
} | |||||
if (fReadOnly) { | |||||
assert(!"Erase called on database in read-only mode"); | |||||
} | |||||
// Key | // Key | ||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION); | CDataStream ssKey(SER_DISK, CLIENT_VERSION); | ||||
ssKey.reserve(1000); | ssKey.reserve(1000); | ||||
ssKey << key; | ssKey << key; | ||||
SafeDbt datKey(ssKey.data(), ssKey.size()); | |||||
// Erase | // Erase | ||||
int ret = pdb->del(activeTxn, datKey, 0); | return EraseKey(ssKey); | ||||
return (ret == 0 || ret == DB_NOTFOUND); | |||||
} | } | ||||
template <typename K> bool Exists(const K &key) { | template <typename K> bool Exists(const K &key) { | ||||
if (!pdb) { | |||||
return false; | |||||
} | |||||
// Key | // Key | ||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION); | CDataStream ssKey(SER_DISK, CLIENT_VERSION); | ||||
ssKey.reserve(1000); | ssKey.reserve(1000); | ||||
ssKey << key; | ssKey << key; | ||||
SafeDbt datKey(ssKey.data(), ssKey.size()); | |||||
// Exists | // Exists | ||||
int ret = pdb->exists(activeTxn, datKey, 0); | return HasKey(ssKey); | ||||
return (ret == 0); | |||||
} | } | ||||
Dbc *GetCursor(); | Dbc *GetCursor(); | ||||
int ReadAtCursor(Dbc *pcursor, CDataStream &ssKey, CDataStream &ssValue); | int ReadAtCursor(Dbc *pcursor, CDataStream &ssKey, CDataStream &ssValue); | ||||
bool TxnBegin(); | bool TxnBegin(); | ||||
bool TxnCommit(); | bool TxnCommit(); | ||||
bool TxnAbort(); | bool TxnAbort(); | ||||
}; | }; | ||||
#endif // BITCOIN_WALLET_BDB_H | #endif // BITCOIN_WALLET_BDB_H |