diff options
author | fanquake <fanquake@gmail.com> | 2019-07-23 12:22:58 +0800 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2019-07-23 12:42:24 +0800 |
commit | 848f245d04b604abcae84dcb9f0f6078325d418d (patch) | |
tree | 33ff897dbc61f12368bfac8957d26dc69c8cdaea /src | |
parent | ad4391ca384bf04a994781c2ec3486a579c90265 (diff) | |
parent | 4f050b91c706181084b9288b8a87b7b637e4e4f7 (diff) |
Merge #16355: refactor: move CCoinsViewErrorCatcher out of init.cpp
4f050b91c706181084b9288b8a87b7b637e4e4f7 move-onlyish: move CCoinsViewErrorCatcher out of init.cpp (James O'Beirne)
Pull request description:
This is part of the [assumeutxo project](https://github.com/bitcoin/bitcoin/projects/11):
Parent PR: #15606
Issue: #15605
Specification: https://github.com/jamesob/assumeutxo-docs/tree/2019-04-proposal/proposal
---
This change moves `CCoinsViewErrorCatcher` out of `init` and into `coins` so that it can later be included in [a `CoinsView` instance](https://github.com/bitcoin/bitcoin/pull/15606/commits/91284964ef34b90ee6c626137973d2c15e7b25da#diff-349fbb003d5ae550a2e8fa658e475880R504) under `CChainState`.
Instead of hardcoding read failure behavior that has knowledge of qt, it accepts error callbacks via `AddReadErrCallback()`.
ACKs for top commit:
dongcarl:
re-ACK 4f050b91c706181084b9288b8a87b7b637e4e4f7
ryanofsky:
utACK 4f050b91c706181084b9288b8a87b7b637e4e4f7. Only change since last review is fixing const.
Tree-SHA512: eaba21606d15d2b8d0e3db7cec57779ce181af953db1ef4af80a0bc1dfb57923d0befde9d61b7be55c32224744f7fb6bd47d4e4c72f3ccfe6eaf0f4ae3765c17
Diffstat (limited to 'src')
-rw-r--r-- | src/coins.cpp | 17 | ||||
-rw-r--r-- | src/coins.h | 25 | ||||
-rw-r--r-- | src/init.cpp | 31 |
3 files changed, 48 insertions, 25 deletions
diff --git a/src/coins.cpp b/src/coins.cpp index 3ef9e0463c..6b85edd01a 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -5,6 +5,7 @@ #include <coins.h> #include <consensus/consensus.h> +#include <logging.h> #include <random.h> #include <version.h> @@ -258,3 +259,19 @@ const Coin& AccessByTxid(const CCoinsViewCache& view, const uint256& txid) } return coinEmpty; } + +bool CCoinsViewErrorCatcher::GetCoin(const COutPoint &outpoint, Coin &coin) const { + try { + return CCoinsViewBacked::GetCoin(outpoint, coin); + } catch(const std::runtime_error& e) { + for (auto f : m_err_callbacks) { + f(); + } + LogPrintf("Error reading from database: %s\n", e.what()); + // Starting the shutdown sequence and returning false to the caller would be + // interpreted as 'entry not found' (as opposed to unable to read data), and + // could lead to invalid interpretation. Just exit immediately, as we can't + // continue anyway, and all writes should be atomic. + std::abort(); + } +} diff --git a/src/coins.h b/src/coins.h index 482e233e8c..dca1beabb6 100644 --- a/src/coins.h +++ b/src/coins.h @@ -17,6 +17,7 @@ #include <assert.h> #include <stdint.h> +#include <functional> #include <unordered_map> /** @@ -315,4 +316,28 @@ void AddCoins(CCoinsViewCache& cache, const CTransaction& tx, int nHeight, bool //! lookups to database, so it should be used with care. const Coin& AccessByTxid(const CCoinsViewCache& cache, const uint256& txid); +/** + * This is a minimally invasive approach to shutdown on LevelDB read errors from the + * chainstate, while keeping user interface out of the common library, which is shared + * between bitcoind, and bitcoin-qt and non-server tools. + * + * Writes do not need similar protection, as failure to write is handled by the caller. +*/ +class CCoinsViewErrorCatcher final : public CCoinsViewBacked +{ +public: + explicit CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {} + + void AddReadErrCallback(std::function<void()> f) { + m_err_callbacks.emplace_back(std::move(f)); + } + + bool GetCoin(const COutPoint &outpoint, Coin &coin) const override; + +private: + /** A list of callbacks to execute upon leveldb read error. */ + std::vector<std::function<void()>> m_err_callbacks; + +}; + #endif // BITCOIN_COINS_H diff --git a/src/init.cpp b/src/init.cpp index 26b2f9d6c2..068b05286c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -15,6 +15,7 @@ #include <blockfilter.h> #include <chain.h> #include <chainparams.h> +#include <coins.h> #include <compat/sanity.h> #include <consensus/validation.h> #include <fs.h> @@ -146,31 +147,6 @@ NODISCARD static bool CreatePidFile() // shutdown thing. // -/** - * This is a minimally invasive approach to shutdown on LevelDB read errors from the - * chainstate, while keeping user interface out of the common library, which is shared - * between bitcoind, and bitcoin-qt and non-server tools. -*/ -class CCoinsViewErrorCatcher final : public CCoinsViewBacked -{ -public: - explicit CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {} - bool GetCoin(const COutPoint &outpoint, Coin &coin) const override { - try { - return CCoinsViewBacked::GetCoin(outpoint, coin); - } catch(const std::runtime_error& e) { - uiInterface.ThreadSafeMessageBox(_("Error reading from database, shutting down."), "", CClientUIInterface::MSG_ERROR); - LogPrintf("Error reading from database: %s\n", e.what()); - // Starting the shutdown sequence and returning false to the caller would be - // interpreted as 'entry not found' (as opposed to unable to read data), and - // could lead to invalid interpretation. Just exit immediately, as we can't - // continue anyway, and all writes should be atomic. - abort(); - } - } - // Writes do not need similar protection, as failure to write is handled by the caller. -}; - static std::unique_ptr<CCoinsViewErrorCatcher> pcoinscatcher; static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle; @@ -1544,6 +1520,11 @@ bool AppInitMain(InitInterfaces& interfaces) pcoinsdbview.reset(new CCoinsViewDB(nCoinDBCache, false, fReset || fReindexChainState)); pcoinscatcher.reset(new CCoinsViewErrorCatcher(pcoinsdbview.get())); + pcoinscatcher->AddReadErrCallback([]() { + uiInterface.ThreadSafeMessageBox( + _("Error reading from database, shutting down."), + "", CClientUIInterface::MSG_ERROR); + }); // If necessary, upgrade from older database format. // This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate |