mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-11 20:32:35 -03:00
walletdb: Handle cursor internally
Instead of returning a Dbc (BDB cursor object) and having the caller deal with the cursor, make BerkeleyBatch handle the cursor internally. This prepares BerkeleyBatch to work with other database systems as Dbc objects are BDB specific.
This commit is contained in:
parent
39bd9ddb87
commit
ca24edfbc1
3 changed files with 50 additions and 35 deletions
|
@ -335,7 +335,7 @@ void BerkeleyEnvironment::CheckpointLSN(const std::string& strFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bool fFlushOnCloseIn) : pdb(nullptr), activeTxn(nullptr)
|
BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bool fFlushOnCloseIn) : pdb(nullptr), activeTxn(nullptr), m_cursor(nullptr)
|
||||||
{
|
{
|
||||||
fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
|
fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
|
||||||
fFlushOnClose = fFlushOnCloseIn;
|
fFlushOnClose = fFlushOnCloseIn;
|
||||||
|
@ -442,6 +442,7 @@ void BerkeleyBatch::Close()
|
||||||
activeTxn->abort();
|
activeTxn->abort();
|
||||||
activeTxn = nullptr;
|
activeTxn = nullptr;
|
||||||
pdb = nullptr;
|
pdb = nullptr;
|
||||||
|
CloseCursor();
|
||||||
|
|
||||||
if (fFlushOnClose)
|
if (fFlushOnClose)
|
||||||
Flush();
|
Flush();
|
||||||
|
@ -528,17 +529,15 @@ bool BerkeleyBatch::Rewrite(BerkeleyDatabase& database, const char* pszSkip)
|
||||||
fSuccess = false;
|
fSuccess = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dbc* pcursor = db.GetCursor();
|
if (db.StartCursor()) {
|
||||||
if (pcursor)
|
|
||||||
while (fSuccess) {
|
while (fSuccess) {
|
||||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||||
int ret1 = db.ReadAtCursor(pcursor, ssKey, ssValue);
|
bool complete;
|
||||||
if (ret1 == DB_NOTFOUND) {
|
bool ret1 = db.ReadAtCursor(ssKey, ssValue, complete);
|
||||||
pcursor->close();
|
if (complete) {
|
||||||
break;
|
break;
|
||||||
} else if (ret1 != 0) {
|
} else if (!ret1) {
|
||||||
pcursor->close();
|
|
||||||
fSuccess = false;
|
fSuccess = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -556,6 +555,8 @@ bool BerkeleyBatch::Rewrite(BerkeleyDatabase& database, const char* pszSkip)
|
||||||
if (ret2 > 0)
|
if (ret2 > 0)
|
||||||
fSuccess = false;
|
fSuccess = false;
|
||||||
}
|
}
|
||||||
|
db.CloseCursor();
|
||||||
|
}
|
||||||
if (fSuccess) {
|
if (fSuccess) {
|
||||||
db.Close();
|
db.Close();
|
||||||
env->CloseDb(strFile);
|
env->CloseDb(strFile);
|
||||||
|
@ -738,27 +739,30 @@ void BerkeleyDatabase::ReloadDbEnv()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Dbc* BerkeleyBatch::GetCursor()
|
bool BerkeleyBatch::StartCursor()
|
||||||
{
|
{
|
||||||
|
assert(!m_cursor);
|
||||||
if (!pdb)
|
if (!pdb)
|
||||||
return nullptr;
|
return false;
|
||||||
Dbc* pcursor = nullptr;
|
int ret = pdb->cursor(nullptr, &m_cursor, 0);
|
||||||
int ret = pdb->cursor(nullptr, &pcursor, 0);
|
return ret == 0;
|
||||||
if (ret != 0)
|
|
||||||
return nullptr;
|
|
||||||
return pcursor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int BerkeleyBatch::ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue)
|
bool BerkeleyBatch::ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete)
|
||||||
{
|
{
|
||||||
|
complete = false;
|
||||||
|
if (m_cursor == nullptr) return false;
|
||||||
// Read at cursor
|
// Read at cursor
|
||||||
SafeDbt datKey;
|
SafeDbt datKey;
|
||||||
SafeDbt datValue;
|
SafeDbt datValue;
|
||||||
int ret = pcursor->get(datKey, datValue, DB_NEXT);
|
int ret = m_cursor->get(datKey, datValue, DB_NEXT);
|
||||||
|
if (ret == DB_NOTFOUND) {
|
||||||
|
complete = true;
|
||||||
|
}
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return false;
|
||||||
else if (datKey.get_data() == nullptr || datValue.get_data() == nullptr)
|
else if (datKey.get_data() == nullptr || datValue.get_data() == nullptr)
|
||||||
return 99999;
|
return false;
|
||||||
|
|
||||||
// Convert to streams
|
// Convert to streams
|
||||||
ssKey.SetType(SER_DISK);
|
ssKey.SetType(SER_DISK);
|
||||||
|
@ -767,7 +771,14 @@ int BerkeleyBatch::ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& s
|
||||||
ssValue.SetType(SER_DISK);
|
ssValue.SetType(SER_DISK);
|
||||||
ssValue.clear();
|
ssValue.clear();
|
||||||
ssValue.write((char*)datValue.get_data(), datValue.get_size());
|
ssValue.write((char*)datValue.get_data(), datValue.get_size());
|
||||||
return 0;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BerkeleyBatch::CloseCursor()
|
||||||
|
{
|
||||||
|
if (!m_cursor) return;
|
||||||
|
m_cursor->close();
|
||||||
|
m_cursor = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BerkeleyBatch::TxnBegin()
|
bool BerkeleyBatch::TxnBegin()
|
||||||
|
|
|
@ -211,6 +211,7 @@ protected:
|
||||||
Db* pdb;
|
Db* pdb;
|
||||||
std::string strFile;
|
std::string strFile;
|
||||||
DbTxn* activeTxn;
|
DbTxn* activeTxn;
|
||||||
|
Dbc* m_cursor;
|
||||||
bool fReadOnly;
|
bool fReadOnly;
|
||||||
bool fFlushOnClose;
|
bool fFlushOnClose;
|
||||||
BerkeleyEnvironment *env;
|
BerkeleyEnvironment *env;
|
||||||
|
@ -323,8 +324,9 @@ public:
|
||||||
return (ret == 0);
|
return (ret == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Dbc* GetCursor();
|
bool StartCursor();
|
||||||
int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue);
|
bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete);
|
||||||
|
void CloseCursor();
|
||||||
bool TxnBegin();
|
bool TxnBegin();
|
||||||
bool TxnCommit();
|
bool TxnCommit();
|
||||||
bool TxnAbort();
|
bool TxnAbort();
|
||||||
|
|
|
@ -699,8 +699,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get cursor
|
// Get cursor
|
||||||
Dbc* pcursor = m_batch.GetCursor();
|
if (!m_batch.StartCursor())
|
||||||
if (!pcursor)
|
|
||||||
{
|
{
|
||||||
pwallet->WalletLogPrintf("Error getting wallet database cursor\n");
|
pwallet->WalletLogPrintf("Error getting wallet database cursor\n");
|
||||||
return DBErrors::CORRUPT;
|
return DBErrors::CORRUPT;
|
||||||
|
@ -711,11 +710,14 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
|
||||||
// Read next record
|
// Read next record
|
||||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||||
int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue);
|
bool complete;
|
||||||
if (ret == DB_NOTFOUND)
|
bool ret = m_batch.ReadAtCursor(ssKey, ssValue, complete);
|
||||||
|
if (complete) {
|
||||||
break;
|
break;
|
||||||
else if (ret != 0)
|
}
|
||||||
|
else if (!ret)
|
||||||
{
|
{
|
||||||
|
m_batch.CloseCursor();
|
||||||
pwallet->WalletLogPrintf("Error reading next record from wallet database\n");
|
pwallet->WalletLogPrintf("Error reading next record from wallet database\n");
|
||||||
return DBErrors::CORRUPT;
|
return DBErrors::CORRUPT;
|
||||||
}
|
}
|
||||||
|
@ -742,10 +744,10 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
|
||||||
if (!strErr.empty())
|
if (!strErr.empty())
|
||||||
pwallet->WalletLogPrintf("%s\n", strErr);
|
pwallet->WalletLogPrintf("%s\n", strErr);
|
||||||
}
|
}
|
||||||
pcursor->close();
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
result = DBErrors::CORRUPT;
|
result = DBErrors::CORRUPT;
|
||||||
}
|
}
|
||||||
|
m_batch.CloseCursor();
|
||||||
|
|
||||||
// Set the active ScriptPubKeyMans
|
// Set the active ScriptPubKeyMans
|
||||||
for (auto spk_man_pair : wss.m_active_external_spks) {
|
for (auto spk_man_pair : wss.m_active_external_spks) {
|
||||||
|
@ -849,8 +851,7 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWal
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get cursor
|
// Get cursor
|
||||||
Dbc* pcursor = m_batch.GetCursor();
|
if (!m_batch.StartCursor())
|
||||||
if (!pcursor)
|
|
||||||
{
|
{
|
||||||
LogPrintf("Error getting wallet database cursor\n");
|
LogPrintf("Error getting wallet database cursor\n");
|
||||||
return DBErrors::CORRUPT;
|
return DBErrors::CORRUPT;
|
||||||
|
@ -861,11 +862,12 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWal
|
||||||
// Read next record
|
// Read next record
|
||||||
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
|
||||||
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
|
||||||
int ret = m_batch.ReadAtCursor(pcursor, ssKey, ssValue);
|
bool complete;
|
||||||
if (ret == DB_NOTFOUND)
|
bool ret = m_batch.ReadAtCursor(ssKey, ssValue, complete);
|
||||||
|
if (complete) {
|
||||||
break;
|
break;
|
||||||
else if (ret != 0)
|
} else if (!ret) {
|
||||||
{
|
m_batch.CloseCursor();
|
||||||
LogPrintf("Error reading next record from wallet database\n");
|
LogPrintf("Error reading next record from wallet database\n");
|
||||||
return DBErrors::CORRUPT;
|
return DBErrors::CORRUPT;
|
||||||
}
|
}
|
||||||
|
@ -880,10 +882,10 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWal
|
||||||
ssValue >> vWtx.back();
|
ssValue >> vWtx.back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pcursor->close();
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
result = DBErrors::CORRUPT;
|
result = DBErrors::CORRUPT;
|
||||||
}
|
}
|
||||||
|
m_batch.CloseCursor();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue