mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-08-06 06:54:49 +02:00
Implement MigrateToSQLite
This commit is contained in:
parent
5b62f095e7
commit
e7b16f925a
@ -3654,4 +3654,76 @@ ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const Flat
|
|||||||
|
|
||||||
return spk_man;
|
return spk_man;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CWallet::MigrateToSQLite(bilingual_str& error)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_wallet);
|
||||||
|
|
||||||
|
WalletLogPrintf("Migrating wallet storage database from BerkeleyDB to SQLite.\n");
|
||||||
|
|
||||||
|
if (m_database->Format() == "sqlite") {
|
||||||
|
error = _("Error: This wallet already uses SQLite");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all of the records for DB type migration
|
||||||
|
std::unique_ptr<DatabaseBatch> batch = m_database->MakeBatch();
|
||||||
|
std::vector<std::pair<SerializeData, SerializeData>> records;
|
||||||
|
if (!batch->StartCursor()) {
|
||||||
|
error = _("Error: Unable to begin reading all records in the database");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool complete = false;
|
||||||
|
while (true) {
|
||||||
|
CDataStream ss_key(SER_DISK, CLIENT_VERSION);
|
||||||
|
CDataStream ss_value(SER_DISK, CLIENT_VERSION);
|
||||||
|
bool ret = batch->ReadAtCursor(ss_key, ss_value, complete);
|
||||||
|
if (!ret) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SerializeData key(ss_key.begin(), ss_key.end());
|
||||||
|
SerializeData value(ss_value.begin(), ss_value.end());
|
||||||
|
records.emplace_back(key, value);
|
||||||
|
}
|
||||||
|
batch->CloseCursor();
|
||||||
|
batch.reset();
|
||||||
|
if (!complete) {
|
||||||
|
error = _("Error: Unable to read all records in the database");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close this database and delete the file
|
||||||
|
fs::path db_path = fs::PathFromString(m_database->Filename());
|
||||||
|
fs::path db_dir = db_path.parent_path();
|
||||||
|
m_database->Close();
|
||||||
|
fs::remove(db_path);
|
||||||
|
|
||||||
|
// Make new DB
|
||||||
|
DatabaseOptions opts;
|
||||||
|
opts.require_create = true;
|
||||||
|
opts.require_format = DatabaseFormat::SQLITE;
|
||||||
|
DatabaseStatus db_status;
|
||||||
|
std::unique_ptr<WalletDatabase> new_db = MakeDatabase(db_dir, opts, db_status, error);
|
||||||
|
assert(new_db); // This is to prevent doing anything further with this wallet. The original file was deleted, but a backup exists.
|
||||||
|
m_database.reset();
|
||||||
|
m_database = std::move(new_db);
|
||||||
|
|
||||||
|
// Write existing records into the new DB
|
||||||
|
batch = m_database->MakeBatch();
|
||||||
|
bool began = batch->TxnBegin();
|
||||||
|
assert(began); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
|
||||||
|
for (const auto& [key, value] : records) {
|
||||||
|
CDataStream ss_key(key, SER_DISK, CLIENT_VERSION);
|
||||||
|
CDataStream ss_value(value, SER_DISK, CLIENT_VERSION);
|
||||||
|
if (!batch->Write(ss_key, ss_value)) {
|
||||||
|
batch->TxnAbort();
|
||||||
|
m_database->Close();
|
||||||
|
fs::remove(m_database->Filename());
|
||||||
|
assert(false); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool committed = batch->TxnCommit();
|
||||||
|
assert(committed); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
} // namespace wallet
|
} // namespace wallet
|
||||||
|
@ -316,7 +316,7 @@ private:
|
|||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
||||||
/** Internal database handle. */
|
/** Internal database handle. */
|
||||||
std::unique_ptr<WalletDatabase> const m_database;
|
std::unique_ptr<WalletDatabase> m_database;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The following is used to keep track of how far behind the wallet is
|
* The following is used to keep track of how far behind the wallet is
|
||||||
@ -920,6 +920,13 @@ public:
|
|||||||
|
|
||||||
//! Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type
|
//! Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type
|
||||||
ScriptPubKeyMan* AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
ScriptPubKeyMan* AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
|
|
||||||
|
/** Move all records from the BDB database to a new SQLite database for storage.
|
||||||
|
* The original BDB file will be deleted and replaced with a new SQLite file.
|
||||||
|
* A backup is not created.
|
||||||
|
* May crash if something unexpected happens in the filesystem.
|
||||||
|
*/
|
||||||
|
bool MigrateToSQLite(bilingual_str& error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user