Merge #19292: wallet: Refactor BerkeleyBatch Read, Write, Erase, and Exists functions into non-template functions

a389ed52e8 walletdb: refactor Read, Write, Erase, and Exists into non-template func (Andrew Chow)

Pull request description:

  In order to override these later, the specific details of how the Read, Write, Erase, and Exists functions interact with the actual database file need to go into functions that are not templated.

  The functions `ReadKey`, `WriteKey`, `EraseKey`, and `HasKey` are introduced to handle the actual interaction with the database.

  This is mostly a moveonly.

  Based on #19290

ACKs for top commit:
  ryanofsky:
    Code review ACK a389ed52e8. No changes since last review, just non-conflicting rebase
  Sjors:
    utACK a389ed52e8
  MarcoFalke:
    ACK a389ed52e8 🔳

Tree-SHA512: 73bd2fe9ddc4a132d4db6b97e77f5d5f8aa68b8cb25192384f3bacd826365947763a9eee73672331d34578e3f5ade85ee6aa550ff4d89eb62e482250dd5973e4
This commit is contained in:
MarcoFalke 2020-06-18 10:25:45 -04:00
commit c7ebab12f9
No known key found for this signature in database
GPG key ID: CE2B75697E69A548
2 changed files with 77 additions and 33 deletions

View file

@ -803,3 +803,67 @@ std::string BerkeleyDatabaseVersion()
{
return DbEnv::version(nullptr, nullptr, nullptr);
}
bool BerkeleyBatch::ReadKey(CDataStream& key, CDataStream& value)
{
if (!pdb)
return false;
// Key
SafeDbt datKey(key.data(), key.size());
// Read
SafeDbt datValue;
int ret = pdb->get(activeTxn, datKey, datValue, 0);
if (ret == 0 && datValue.get_data() != nullptr) {
value.write((char*)datValue.get_data(), datValue.get_size());
return true;
}
return false;
}
bool BerkeleyBatch::WriteKey(CDataStream& key, CDataStream& value, bool overwrite)
{
if (!pdb)
return true;
if (fReadOnly)
assert(!"Write called on database in read-only mode");
// Key
SafeDbt datKey(key.data(), key.size());
// Value
SafeDbt datValue(value.data(), value.size());
// Write
int ret = pdb->put(activeTxn, datKey, datValue, (overwrite ? 0 : DB_NOOVERWRITE));
return (ret == 0);
}
bool BerkeleyBatch::EraseKey(CDataStream& key)
{
if (!pdb)
return false;
if (fReadOnly)
assert(!"Erase called on database in read-only mode");
// Key
SafeDbt datKey(key.data(), key.size());
// Erase
int ret = pdb->del(activeTxn, datKey, 0);
return (ret == 0 || ret == DB_NOTFOUND);
}
bool BerkeleyBatch::HasKey(CDataStream& key)
{
if (!pdb)
return false;
// Key
SafeDbt datKey(key.data(), key.size());
// Exists
int ret = pdb->exists(activeTxn, datKey, 0);
return ret == 0;
}

View file

@ -207,6 +207,12 @@ class BerkeleyBatch
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:
Db* pdb;
std::string strFile;
@ -236,91 +242,65 @@ public:
template <typename K, typename T>
bool Read(const K& key, T& value)
{
if (!pdb)
return false;
// Key
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
SafeDbt datKey(ssKey.data(), ssKey.size());
// Read
SafeDbt datValue;
int ret = pdb->get(activeTxn, datKey, datValue, 0);
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
bool success = false;
if (datValue.get_data() != nullptr) {
bool ret = ReadKey(ssKey, ssValue);
if (ret) {
// Unserialize value
try {
CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
ssValue >> value;
success = true;
} catch (const std::exception&) {
// In this case success remains 'false'
}
}
return ret == 0 && success;
return ret && success;
}
template <typename K, typename T>
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
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
SafeDbt datKey(ssKey.data(), ssKey.size());
// Value
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
ssValue.reserve(10000);
ssValue << value;
SafeDbt datValue(ssValue.data(), ssValue.size());
// Write
int ret = pdb->put(activeTxn, datKey, datValue, (fOverwrite ? 0 : DB_NOOVERWRITE));
return (ret == 0);
return WriteKey(ssKey, ssValue, fOverwrite);
}
template <typename K>
bool Erase(const K& key)
{
if (!pdb)
return false;
if (fReadOnly)
assert(!"Erase called on database in read-only mode");
// Key
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
SafeDbt datKey(ssKey.data(), ssKey.size());
// Erase
int ret = pdb->del(activeTxn, datKey, 0);
return (ret == 0 || ret == DB_NOTFOUND);
return EraseKey(ssKey);
}
template <typename K>
bool Exists(const K& key)
{
if (!pdb)
return false;
// Key
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(1000);
ssKey << key;
SafeDbt datKey(ssKey.data(), ssKey.size());
// Exists
int ret = pdb->exists(activeTxn, datKey, 0);
return (ret == 0);
return HasKey(ssKey);
}
Dbc* GetCursor();