diff --git a/include/bitcoin/database/impl/query/query.ipp b/include/bitcoin/database/impl/query/query.ipp index c2fa4b15..d273c4ec 100644 --- a/include/bitcoin/database/impl/query/query.ipp +++ b/include/bitcoin/database/impl/query/query.ipp @@ -77,13 +77,13 @@ CLASS::query(Store& value) NOEXCEPT TEMPLATE bool CLASS::is_full() const NOEXCEPT { - return store_.get_error(error::disk_full); + return store_.is_error(error::disk_full); } TEMPLATE bool CLASS::is_fault() const NOEXCEPT { - return !!store_.get_first_error(); + return !!store_.get_fault(); } } // namespace database diff --git a/include/bitcoin/database/impl/store.ipp b/include/bitcoin/database/impl/store.ipp index df0fb5bc..ed4d1714 100644 --- a/include/bitcoin/database/impl/store.ipp +++ b/include/bitcoin/database/impl/store.ipp @@ -393,128 +393,20 @@ code CLASS::close(const event_handler& handler) NOEXCEPT if (!ec) ec = unload_close(handler); - // unlock errors override ec, fault overrides unlock errors. - const auto fault = get_first_error() && !get_error(error::disk_full); - if (!fault && !flush_lock_.try_unlock()) ec = error::flush_unlock; - if (!process_lock_.try_unlock()) ec = error::process_unlock; - if (fault) ec = error::integrity; - transactor_mutex_.unlock(); - return ec; -} + // unlock errors override ec. + if (!process_lock_.try_unlock()) + ec = error::process_unlock; -TEMPLATE -const typename CLASS::transactor CLASS::get_transactor() NOEXCEPT -{ - return transactor{ transactor_mutex_ }; -} + // fault overrides unlock errors and leaves behind flush_lock. + if (get_fault()) + ec = error::integrity; + else if (!flush_lock_.try_unlock()) + ec = error::flush_unlock; -TEMPLATE -code CLASS::get_first_error() const NOEXCEPT -{ - code ec{}; - if ((ec = header_body_.get_error())) return ec; - if ((ec = input_body_.get_error())) return ec; - if ((ec = output_body_.get_error())) return ec; - if ((ec = point_body_.get_error())) return ec; - if ((ec = puts_body_.get_error())) return ec; - if ((ec = spend_body_.get_error())) return ec; - if ((ec = tx_body_.get_error())) return ec; - if ((ec = txs_body_.get_error())) return ec; - if ((ec = candidate_body_.get_error())) return ec; - if ((ec = confirmed_body_.get_error())) return ec; - if ((ec = strong_tx_body_.get_error())) return ec; - if ((ec = validated_bk_body_.get_error())) return ec; - if ((ec = validated_tx_body_.get_error())) return ec; - if ((ec = address_body_.get_error())) return ec; - if ((ec = neutrino_body_.get_error())) return ec; - ////if ((ec = bootstrap_body_.get_error())) return ec; - ////if ((ec = buffer_body_.get_error())) return ec; + transactor_mutex_.unlock(); return ec; } -TEMPLATE -bool CLASS::get_error(const code& ec) const NOEXCEPT -{ - // A disk full error will not leave a flush lock, but others will. - // There may be other error codes as well so check all. - - bool found{}; - const auto match = [&ec, &found](const auto& storage) NOEXCEPT - { - const auto error = storage.get_error(); - if (error == ec) found = true; - return !error || found; - }; - - return match(header_body_) - && match(input_body_) - && match(output_body_) - && match(point_body_) - && match(puts_body_) - && match(spend_body_) - && match(tx_body_) - && match(txs_body_) - && match(candidate_body_) - && match(confirmed_body_) - && match(strong_tx_body_) - && match(validated_bk_body_) - && match(validated_tx_body_) - && match(address_body_) - && match(neutrino_body_) - ////&& match(bootstrap_body_) - ////&& match(buffer_body_) - && found; -} - -TEMPLATE -void CLASS::clear_error() NOEXCEPT -{ - header_body_.clear_error(); - input_body_.clear_error(); - output_body_.clear_error(); - point_body_.clear_error(); - puts_body_.clear_error(); - spend_body_.clear_error(); - tx_body_.clear_error(); - txs_body_.clear_error(); - candidate_body_.clear_error(); - confirmed_body_.clear_error(); - strong_tx_body_.clear_error(); - validated_bk_body_.clear_error(); - validated_tx_body_.clear_error(); - address_body_.clear_error(); - neutrino_body_.clear_error(); - ////bootstrap_body_.clear_error(); - ////buffer_body_.clear_error(); -} - -TEMPLATE -void CLASS::report_errors(const error_handler& handler) NOEXCEPT -{ - const auto report = [&handler](const auto& storage, table_t table) NOEXCEPT - { - handler(storage.get_error(), table); - }; - - report(header_body_, table_t::header_body); - report(input_body_, table_t::input_body); - report(output_body_, table_t::output_body); - report(point_body_, table_t::point_body); - report(puts_body_, table_t::puts_body); - report(spend_body_, table_t::spend_body); - report(tx_body_, table_t::tx_body); - report(txs_body_, table_t::txs_body); - report(candidate_body_, table_t::candidate_body); - report(confirmed_body_, table_t::confirmed_body); - report(strong_tx_body_, table_t::strong_tx_body); - report(validated_bk_body_, table_t::validated_bk_body); - report(validated_tx_body_, table_t::validated_tx_body); - report(address_body_, table_t::address_body); - report(neutrino_body_, table_t::neutrino_body); - ////report(bootstrap_body_, table_t::bootstrap_body); - ////report(buffer_body_, table_t::buffer_body); -} - // protected // ---------------------------------------------------------------------------- @@ -968,6 +860,128 @@ code CLASS::restore(const event_handler& handler) NOEXCEPT return ec; } +// context +// ---------------------------------------------------------------------------- + +TEMPLATE +const typename CLASS::transactor CLASS::get_transactor() NOEXCEPT +{ + return transactor{ transactor_mutex_ }; +} + +TEMPLATE +code CLASS::get_fault() const NOEXCEPT +{ + const auto fault = [](const auto& storage) NOEXCEPT + { + const auto ec = storage.get_error(); + return ec == error::disk_full ? error::success : ec; + }; + + code ec{}; + if ((ec = fault(header_body_))) return ec; + if ((ec = fault(input_body_))) return ec; + if ((ec = fault(output_body_))) return ec; + if ((ec = fault(point_body_))) return ec; + if ((ec = fault(puts_body_))) return ec; + if ((ec = fault(spend_body_))) return ec; + if ((ec = fault(tx_body_))) return ec; + if ((ec = fault(txs_body_))) return ec; + if ((ec = fault(candidate_body_))) return ec; + if ((ec = fault(confirmed_body_))) return ec; + if ((ec = fault(strong_tx_body_))) return ec; + if ((ec = fault(validated_bk_body_))) return ec; + if ((ec = fault(validated_tx_body_))) return ec; + if ((ec = fault(address_body_))) return ec; + if ((ec = fault(neutrino_body_))) return ec; + ////if ((ec = fault(bootstrap_body_))) return ec; + ////if ((ec = fault(buffer_body_))) return ec; + return ec; +} + +TEMPLATE +bool CLASS::is_error(const code& ec) const NOEXCEPT +{ + // A disk full error will not leave a flush lock, but others will. + // There may be other error codes as well so check all. + + bool found{}; + const auto match = [&ec, &found](const auto& storage) NOEXCEPT + { + const auto error = storage.get_error(); + if (error == ec) found = true; + return !error || found; + }; + + return match(header_body_) + && match(input_body_) + && match(output_body_) + && match(point_body_) + && match(puts_body_) + && match(spend_body_) + && match(tx_body_) + && match(txs_body_) + && match(candidate_body_) + && match(confirmed_body_) + && match(strong_tx_body_) + && match(validated_bk_body_) + && match(validated_tx_body_) + && match(address_body_) + && match(neutrino_body_) + ////&& match(bootstrap_body_) + ////&& match(buffer_body_) + && found; +} + +TEMPLATE +void CLASS::clear_errors() NOEXCEPT +{ + header_body_.clear_error(); + input_body_.clear_error(); + output_body_.clear_error(); + point_body_.clear_error(); + puts_body_.clear_error(); + spend_body_.clear_error(); + tx_body_.clear_error(); + txs_body_.clear_error(); + candidate_body_.clear_error(); + confirmed_body_.clear_error(); + strong_tx_body_.clear_error(); + validated_bk_body_.clear_error(); + validated_tx_body_.clear_error(); + address_body_.clear_error(); + neutrino_body_.clear_error(); + ////bootstrap_body_.clear_error(); + ////buffer_body_.clear_error(); +} + +TEMPLATE +void CLASS::report_errors(const error_handler& handler) NOEXCEPT +{ + const auto report = [&handler](const auto& storage, table_t table) NOEXCEPT + { + handler(storage.get_error(), table); + }; + + report(header_body_, table_t::header_body); + report(input_body_, table_t::input_body); + report(output_body_, table_t::output_body); + report(point_body_, table_t::point_body); + report(puts_body_, table_t::puts_body); + report(spend_body_, table_t::spend_body); + report(tx_body_, table_t::tx_body); + report(txs_body_, table_t::txs_body); + report(candidate_body_, table_t::candidate_body); + report(confirmed_body_, table_t::confirmed_body); + report(strong_tx_body_, table_t::strong_tx_body); + report(validated_bk_body_, table_t::validated_bk_body); + report(validated_tx_body_, table_t::validated_tx_body); + report(address_body_, table_t::address_body); + report(neutrino_body_, table_t::neutrino_body); + ////report(bootstrap_body_, table_t::bootstrap_body); + ////report(buffer_body_, table_t::buffer_body); +} + BC_POP_WARNING() } // namespace database diff --git a/include/bitcoin/database/query.hpp b/include/bitcoin/database/query.hpp index b0e5874d..9fff4c48 100644 --- a/include/bitcoin/database/query.hpp +++ b/include/bitcoin/database/query.hpp @@ -85,7 +85,7 @@ class query /// True if disk is full and no other store error condition. bool is_full() const NOEXCEPT; - /// True if there is any store error condition. + /// True if there is any store error condition (excludes error::disk_full). bool is_fault() const NOEXCEPT; /// Initialization (natural-keyed). diff --git a/include/bitcoin/database/store.hpp b/include/bitcoin/database/store.hpp index a1bdec39..d75a5613 100644 --- a/include/bitcoin/database/store.hpp +++ b/include/bitcoin/database/store.hpp @@ -50,6 +50,9 @@ class store /// Construct a store from settings. store(const settings& config) NOEXCEPT; + /// Methods. + /// ----------------------------------------------------------------------- + /// Create the set of empty files (from unloaded). code create(const event_handler& handler) NOEXCEPT; @@ -65,21 +68,27 @@ class store /// Unload and close the set of tables, clear locks. code close(const event_handler& handler) NOEXCEPT; + /// Context. + /// ----------------------------------------------------------------------- + /// Get a transactor object. const transactor get_transactor() NOEXCEPT; - /// Detect the first error condition. - code get_first_error() const NOEXCEPT; + /// Detect the first error condition (excludes error::disk_full). + code get_fault() const NOEXCEPT; - /// Detect the specified error condition (exclusive). - bool get_error(const code& ec) const NOEXCEPT; + /// Detect the exclusive existence of the specified error condition. + bool is_error(const code& ec) const NOEXCEPT; /// Clear all error conditions. - void clear_error() NOEXCEPT; + void clear_errors() NOEXCEPT; /// Dump all error conditions to error handler. void report_errors(const error_handler& handler) NOEXCEPT; + /// Tables. + /// ----------------------------------------------------------------------- + /// Archives. table::header header; table::input input; diff --git a/test/store.cpp b/test/store.cpp index 70f947cd..1a0df283 100644 --- a/test/store.cpp +++ b/test/store.cpp @@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(store__get_error__disk_full__false) { const settings configuration{}; test::map_store instance{ configuration }; - BOOST_REQUIRE(!instance.get_error(error::disk_full)); + BOOST_REQUIRE(!instance.is_error(error::disk_full)); } // create