mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-12-10 04:33:59 +01:00
[Wallet] refactor CWallet/CWalletDB/CDB
Try to hide CDB/bitdb behinde CWalletDB. Prepare for full wallet database abstraction.
This commit is contained in:
@@ -546,7 +546,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsKeyType(string strType)
|
||||
bool CWalletDB::IsKeyType(const std::string& strType)
|
||||
{
|
||||
return (strType== "key" || strType == "wkey" ||
|
||||
strType == "mkey" || strType == "ckey");
|
||||
@@ -804,38 +804,9 @@ void ThreadFlushWalletDB()
|
||||
|
||||
if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2)
|
||||
{
|
||||
TRY_LOCK(bitdb.cs_db,lockDb);
|
||||
if (lockDb)
|
||||
{
|
||||
// Don't do this if any databases are in use
|
||||
int nRefCount = 0;
|
||||
map<string, int>::iterator mi = bitdb.mapFileUseCount.begin();
|
||||
while (mi != bitdb.mapFileUseCount.end())
|
||||
{
|
||||
nRefCount += (*mi).second;
|
||||
mi++;
|
||||
}
|
||||
|
||||
if (nRefCount == 0)
|
||||
{
|
||||
boost::this_thread::interruption_point();
|
||||
const std::string& strFile = pwalletMain->strWalletFile;
|
||||
map<string, int>::iterator _mi = bitdb.mapFileUseCount.find(strFile);
|
||||
if (_mi != bitdb.mapFileUseCount.end())
|
||||
{
|
||||
LogPrint("db", "Flushing %s\n", strFile);
|
||||
nLastFlushed = CWalletDB::GetUpdateCounter();
|
||||
int64_t nStart = GetTimeMillis();
|
||||
|
||||
// Flush wallet file so it's self contained
|
||||
bitdb.CloseDb(strFile);
|
||||
bitdb.CheckpointLSN(strFile);
|
||||
|
||||
bitdb.mapFileUseCount.erase(_mi++);
|
||||
LogPrint("db", "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
const std::string& strFile = pwalletMain->strWalletFile;
|
||||
if (CDB::PeriodicFlush(strFile))
|
||||
nLastFlushed = CWalletDB::GetUpdateCounter();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -843,90 +814,49 @@ void ThreadFlushWalletDB()
|
||||
//
|
||||
// Try to (very carefully!) recover wallet file if there is a problem.
|
||||
//
|
||||
bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys)
|
||||
bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue))
|
||||
{
|
||||
// Recovery procedure:
|
||||
// move wallet file to wallet.timestamp.bak
|
||||
// Call Salvage with fAggressive=true to
|
||||
// get as much data as possible.
|
||||
// Rewrite salvaged data to fresh wallet file
|
||||
// Set -rescan so any missing transactions will be
|
||||
// found.
|
||||
int64_t now = GetTime();
|
||||
std::string newFilename = strprintf("wallet.%d.bak", now);
|
||||
|
||||
int result = dbenv.dbenv->dbrename(NULL, filename.c_str(), NULL,
|
||||
newFilename.c_str(), DB_AUTO_COMMIT);
|
||||
if (result == 0)
|
||||
LogPrintf("Renamed %s to %s\n", filename, newFilename);
|
||||
else
|
||||
{
|
||||
LogPrintf("Failed to rename %s to %s\n", filename, newFilename);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<CDBEnv::KeyValPair> salvagedData;
|
||||
bool fSuccess = dbenv.Salvage(newFilename, true, salvagedData);
|
||||
if (salvagedData.empty())
|
||||
{
|
||||
LogPrintf("Salvage(aggressive) found no records in %s.\n", newFilename);
|
||||
return false;
|
||||
}
|
||||
LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size());
|
||||
|
||||
std::unique_ptr<Db> pdbCopy(new Db(dbenv.dbenv, 0));
|
||||
int ret = pdbCopy->open(NULL, // Txn pointer
|
||||
filename.c_str(), // Filename
|
||||
"main", // Logical db name
|
||||
DB_BTREE, // Database type
|
||||
DB_CREATE, // Flags
|
||||
0);
|
||||
if (ret > 0)
|
||||
{
|
||||
LogPrintf("Cannot create database file %s\n", filename);
|
||||
return false;
|
||||
}
|
||||
CWallet dummyWallet;
|
||||
CWalletScanState wss;
|
||||
|
||||
DbTxn* ptxn = dbenv.TxnBegin();
|
||||
BOOST_FOREACH(CDBEnv::KeyValPair& row, salvagedData)
|
||||
{
|
||||
if (fOnlyKeys)
|
||||
{
|
||||
CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION);
|
||||
CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION);
|
||||
string strType, strErr;
|
||||
bool fReadOK;
|
||||
{
|
||||
// Required in LoadKeyMetadata():
|
||||
LOCK(dummyWallet.cs_wallet);
|
||||
fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue,
|
||||
wss, strType, strErr);
|
||||
}
|
||||
if (!IsKeyType(strType) && strType != "hdchain")
|
||||
continue;
|
||||
if (!fReadOK)
|
||||
{
|
||||
LogPrintf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType, strErr);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Dbt datKey(&row.first[0], row.first.size());
|
||||
Dbt datValue(&row.second[0], row.second.size());
|
||||
int ret2 = pdbCopy->put(ptxn, &datKey, &datValue, DB_NOOVERWRITE);
|
||||
if (ret2 > 0)
|
||||
fSuccess = false;
|
||||
}
|
||||
ptxn->commit(0);
|
||||
pdbCopy->close(0);
|
||||
|
||||
return fSuccess;
|
||||
return CDB::Recover(filename, callbackDataIn, recoverKVcallback);
|
||||
}
|
||||
|
||||
bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename)
|
||||
bool CWalletDB::Recover(const std::string& filename)
|
||||
{
|
||||
return CWalletDB::Recover(dbenv, filename, false);
|
||||
// recover without a key filter callback
|
||||
// results in recovering all record types
|
||||
return CWalletDB::Recover(filename, NULL, NULL);
|
||||
}
|
||||
|
||||
bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue)
|
||||
{
|
||||
CWallet *dummyWallet = reinterpret_cast<CWallet*>(callbackData);
|
||||
CWalletScanState dummyWss;
|
||||
std::string strType, strErr;
|
||||
bool fReadOK;
|
||||
{
|
||||
// Required in LoadKeyMetadata():
|
||||
LOCK(dummyWallet->cs_wallet);
|
||||
fReadOK = ReadKeyValue(dummyWallet, ssKey, ssValue,
|
||||
dummyWss, strType, strErr);
|
||||
}
|
||||
if (!IsKeyType(strType) && strType != "hdchain")
|
||||
return false;
|
||||
if (!fReadOK)
|
||||
{
|
||||
LogPrintf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType, strErr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const boost::filesystem::path& dataDir, std::string& errorStr)
|
||||
{
|
||||
return CDB::VerifyEnvironment(walletFile, dataDir, errorStr);
|
||||
}
|
||||
|
||||
bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const boost::filesystem::path& dataDir, std::string& warningStr, std::string& errorStr)
|
||||
{
|
||||
return CDB::VerifyDatabaseFile(walletFile, dataDir, errorStr, warningStr, CWalletDB::Recover);
|
||||
}
|
||||
|
||||
bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
|
||||
|
||||
Reference in New Issue
Block a user