Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | bool AddWallet(const std::shared_ptr<CWallet> &wallet) { | ||||
if (i != vpwallets.end()) { | if (i != vpwallets.end()) { | ||||
return false; | return false; | ||||
} | } | ||||
vpwallets.push_back(wallet); | vpwallets.push_back(wallet); | ||||
return true; | return true; | ||||
} | } | ||||
bool RemoveWallet(const std::shared_ptr<CWallet> &wallet) { | bool RemoveWallet(const std::shared_ptr<CWallet> &wallet) { | ||||
LOCK(cs_wallets); | |||||
assert(wallet); | assert(wallet); | ||||
// Unregister with the validation interface which also drops shared ponters. | |||||
wallet->m_chain_notifications_handler.reset(); | |||||
LOCK(cs_wallets); | |||||
std::vector<std::shared_ptr<CWallet>>::iterator i = | std::vector<std::shared_ptr<CWallet>>::iterator i = | ||||
std::find(vpwallets.begin(), vpwallets.end(), wallet); | std::find(vpwallets.begin(), vpwallets.end(), wallet); | ||||
if (i == vpwallets.end()) { | if (i == vpwallets.end()) { | ||||
return false; | return false; | ||||
} | } | ||||
vpwallets.erase(i); | vpwallets.erase(i); | ||||
return true; | return true; | ||||
} | } | ||||
Show All 19 Lines | |||||
} | } | ||||
static Mutex g_wallet_release_mutex; | static Mutex g_wallet_release_mutex; | ||||
static std::condition_variable g_wallet_release_cv; | static std::condition_variable g_wallet_release_cv; | ||||
static std::set<std::string> g_unloading_wallet_set; | static std::set<std::string> g_unloading_wallet_set; | ||||
// Custom deleter for shared_ptr<CWallet>. | // Custom deleter for shared_ptr<CWallet>. | ||||
static void ReleaseWallet(CWallet *wallet) { | static void ReleaseWallet(CWallet *wallet) { | ||||
// Unregister and delete the wallet right after | |||||
// BlockUntilSyncedToCurrentChain so that it's in sync with the current | |||||
// chainstate. | |||||
const std::string name = wallet->GetName(); | const std::string name = wallet->GetName(); | ||||
wallet->WalletLogPrintf("Releasing wallet\n"); | wallet->WalletLogPrintf("Releasing wallet\n"); | ||||
wallet->BlockUntilSyncedToCurrentChain(); | |||||
wallet->Flush(); | wallet->Flush(); | ||||
wallet->m_chain_notifications_handler.reset(); | |||||
delete wallet; | delete wallet; | ||||
// Wallet is now released, notify UnloadWallet, if any. | // Wallet is now released, notify UnloadWallet, if any. | ||||
{ | { | ||||
LOCK(g_wallet_release_mutex); | LOCK(g_wallet_release_mutex); | ||||
if (g_unloading_wallet_set.erase(name) == 0) { | if (g_unloading_wallet_set.erase(name) == 0) { | ||||
// UnloadWallet was not called for this wallet, all done. | // UnloadWallet was not called for this wallet, all done. | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
g_wallet_release_cv.notify_all(); | g_wallet_release_cv.notify_all(); | ||||
} | } | ||||
void UnloadWallet(std::shared_ptr<CWallet> &&wallet) { | void UnloadWallet(std::shared_ptr<CWallet> &&wallet) { | ||||
// Mark wallet for unloading. | // Mark wallet for unloading. | ||||
const std::string name = wallet->GetName(); | const std::string name = wallet->GetName(); | ||||
{ | { | ||||
LOCK(g_wallet_release_mutex); | LOCK(g_wallet_release_mutex); | ||||
auto it = g_unloading_wallet_set.insert(name); | auto it = g_unloading_wallet_set.insert(name); | ||||
assert(it.second); | assert(it.second); | ||||
} | } | ||||
// The wallet can be in use so it's not possible to explicitly unload here. | // The wallet can be in use so it's not possible to explicitly unload here. | ||||
// Notify the unload intent so that all remaining shared pointers are | // Notify the unload intent so that all remaining shared pointers are | ||||
// released. | // released. | ||||
wallet->NotifyUnload(); | wallet->NotifyUnload(); | ||||
// Time to ditch our shared_ptr and wait for ReleaseWallet call. | // Time to ditch our shared_ptr and wait for ReleaseWallet call. | ||||
wallet.reset(); | wallet.reset(); | ||||
{ | { | ||||
WAIT_LOCK(g_wallet_release_mutex, lock); | WAIT_LOCK(g_wallet_release_mutex, lock); | ||||
while (g_unloading_wallet_set.count(name) == 1) { | while (g_unloading_wallet_set.count(name) == 1) { | ||||
g_wallet_release_cv.wait(lock); | g_wallet_release_cv.wait(lock); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 4,955 Lines • ▼ Show 20 Lines | if (tip_height && *tip_height != rescan_height) { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
chain.loadWallet(interfaces::MakeWallet(walletInstance)); | chain.loadWallet(interfaces::MakeWallet(walletInstance)); | ||||
// Register with the validation interface. It's ok to do this after rescan | // Register with the validation interface. It's ok to do this after rescan | ||||
// since we're still holding locked_chain. | // since we're still holding locked_chain. | ||||
walletInstance->handleNotifications(); | walletInstance->m_chain_notifications_handler = | ||||
walletInstance->chain().handleNotifications(walletInstance); | |||||
walletInstance->SetBroadcastTransactions( | walletInstance->SetBroadcastTransactions( | ||||
gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); | gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); | ||||
walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", | walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", | ||||
walletInstance->GetKeyPoolSize()); | walletInstance->GetKeyPoolSize()); | ||||
walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", | walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", | ||||
walletInstance->mapWallet.size()); | walletInstance->mapWallet.size()); | ||||
walletInstance->WalletLogPrintf("mapAddressBook.size() = %u\n", | walletInstance->WalletLogPrintf("mapAddressBook.size() = %u\n", | ||||
walletInstance->mapAddressBook.size()); | walletInstance->mapAddressBook.size()); | ||||
return walletInstance; | return walletInstance; | ||||
} | } | ||||
void CWallet::handleNotifications() { | |||||
m_chain_notifications_handler = m_chain->handleNotifications(*this); | |||||
} | |||||
void CWallet::postInitProcess() { | void CWallet::postInitProcess() { | ||||
auto locked_chain = chain().lock(); | auto locked_chain = chain().lock(); | ||||
LOCK(cs_wallet); | LOCK(cs_wallet); | ||||
// Add wallet transactions that aren't already in a block to mempool. | // Add wallet transactions that aren't already in a block to mempool. | ||||
// Do this here as mempool requires genesis block to be loaded. | // Do this here as mempool requires genesis block to be loaded. | ||||
ReacceptWalletTransactions(*locked_chain); | ReacceptWalletTransactions(*locked_chain); | ||||
▲ Show 20 Lines • Show All 333 Lines • Show Last 20 Lines |