From f527d3b70ee30d4161e3c4d7f37fecf6e9afa3df Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Tue, 16 Jan 2024 11:29:19 -0500 Subject: [PATCH 1/3] move chainbase's scope_exit and scope_fail to separate header --- include/chainbase/scope_exit.hpp | 26 ++++++++++++++++++++++++++ include/chainbase/undo_index.hpp | 14 +------------- test/undo_index.cpp | 12 ++---------- 3 files changed, 29 insertions(+), 23 deletions(-) create mode 100644 include/chainbase/scope_exit.hpp diff --git a/include/chainbase/scope_exit.hpp b/include/chainbase/scope_exit.hpp new file mode 100644 index 0000000..5e4e1a6 --- /dev/null +++ b/include/chainbase/scope_exit.hpp @@ -0,0 +1,26 @@ +#pragma once +#include +#include + +namespace chainbase { + template + struct scope_exit { + [[nodiscard]] scope_exit(F&& f) : _f(std::move(f)) {} + scope_exit(const scope_exit&) = delete; + scope_exit& operator=(const scope_exit&) = delete; + ~scope_exit() { if(!_canceled) _f(); } + void cancel() { _canceled = true; } + F _f; + bool _canceled = false; + }; + + template + struct scope_fail { + scope_fail(F&& f) : _f{static_cast(f)}, _exception_count{std::uncaught_exceptions()} {} + ~scope_fail() { + if(_exception_count != std::uncaught_exceptions()) _f(); + } + F _f; + int _exception_count; + }; +} \ No newline at end of file diff --git a/include/chainbase/undo_index.hpp b/include/chainbase/undo_index.hpp index cf472f9..93e56c2 100644 --- a/include/chainbase/undo_index.hpp +++ b/include/chainbase/undo_index.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -20,19 +21,6 @@ namespace chainbase { - template - struct scope_exit { - public: - [[nodiscard]] scope_exit(F&& f) : _f(std::move(f)) {} - scope_exit(const scope_exit&) = delete; - scope_exit& operator=(const scope_exit&) = delete; - ~scope_exit() { if(!_canceled) _f(); } - void cancel() { _canceled = true; } - private: - F _f; - bool _canceled = false; - }; - // Adapts multi_index's idea of keys to intrusive template struct get_key { diff --git a/test/undo_index.cpp b/test/undo_index.cpp index 0cccbd6..60538f1 100644 --- a/test/undo_index.cpp +++ b/test/undo_index.cpp @@ -72,17 +72,9 @@ class test_allocator : public test_allocator_base { return base::allocate(count); } }; - -template -struct scope_fail { - scope_fail(F&& f) : _f{static_cast(f)}, _exception_count{std::uncaught_exceptions()} {} - ~scope_fail() { - if(_exception_count != std::uncaught_exceptions()) _f(); - } - F _f; - int _exception_count; -}; + +using chainbase::scope_fail; struct basic_element_t { template From 7b8b8307161e6c189c1bdc7a90aae72c665e777a Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Tue, 16 Jan 2024 11:36:37 -0500 Subject: [PATCH 2/3] reset db dirty bit when ctor fails to complete --- src/pinnable_mapped_file.cpp | 32 ++++++++++++++++---------------- test/test.cpp | 17 +++++++++++++++++ 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/pinnable_mapped_file.cpp b/src/pinnable_mapped_file.cpp index 8d2e424..ed367ea 100644 --- a/src/pinnable_mapped_file.cpp +++ b/src/pinnable_mapped_file.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -163,6 +164,12 @@ pinnable_mapped_file::pinnable_mapped_file(const std::filesystem::path& dir, boo set_mapped_file_db_dirty(true); } + auto reset_dirty_on_ctor_fail = scope_fail([&]() { + if(_writable) + set_mapped_file_db_dirty(false); + std::erase(_instance_tracker, this); + }); + if(mode == mapped || mode == mapped_private) { if (_writable && !_sharable) { // First make sure the db file is not on a ram-based tempfs, as it would be an @@ -198,26 +205,19 @@ pinnable_mapped_file::pinnable_mapped_file(const std::filesystem::path& dir, boo BOOST_THROW_EXCEPTION(std::system_error(make_error_code(db_error_code::aborted))); }); - try { - setup_non_file_mapping(); - _file_mapped_region = bip::mapped_region(); - load_database_file(sig_ios); + setup_non_file_mapping(); + _file_mapped_region = bip::mapped_region(); + load_database_file(sig_ios); #ifndef _WIN32 - if(mode == locked) { - if(mlock(_non_file_mapped_mapping, _non_file_mapped_mapping_size)) { - std::string what_str("Failed to mlock database \"" + _database_name + "\""); - BOOST_THROW_EXCEPTION(std::system_error(make_error_code(db_error_code::no_mlock), what_str)); - } - std::cerr << "CHAINBASE: Database \"" << _database_name << "\" has been successfully locked in memory" << '\n'; + if(mode == locked) { + if(mlock(_non_file_mapped_mapping, _non_file_mapped_mapping_size)) { + std::string what_str("Failed to mlock database \"" + _database_name + "\""); + BOOST_THROW_EXCEPTION(std::system_error(make_error_code(db_error_code::no_mlock), what_str)); } -#endif - } - catch(...) { - if(_writable) - set_mapped_file_db_dirty(false); - throw; + std::cerr << "CHAINBASE: Database \"" << _database_name << "\" has been successfully locked in memory" << '\n'; } +#endif _segment_manager = reinterpret_cast((char*)_non_file_mapped_mapping+header_size); } diff --git a/test/test.cpp b/test/test.cpp index e3083db..f7f0885 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -127,4 +127,21 @@ BOOST_AUTO_TEST_CASE( open_and_create ) { BOOST_REQUIRE_EQUAL( new_book.b, copy_new_book.b ); } +BOOST_AUTO_TEST_CASE( mapped_big_boy ) { + temp_directory temp_dir; + const auto& temp = temp_dir.path(); + + BOOST_REQUIRE_THROW(chainbase::database(temp, database::read_write, 1024ull*1024*1024*1024*4, false, pinnable_mapped_file::map_mode::mapped_private), boost::interprocess::interprocess_exception); + chainbase::database(temp, database::read_write, 0, false); +} + +BOOST_AUTO_TEST_CASE( mapped_big_boy_extra ) { + temp_directory temp_dir; + const auto& temp = temp_dir.path(); + + chainbase::database(temp, database::read_write, 1024ull*1024*1024*1024*4, false); + BOOST_REQUIRE_THROW(chainbase::database(temp, database::read_write, 0, false, pinnable_mapped_file::map_mode::mapped_private), boost::interprocess::interprocess_exception); + chainbase::database(temp, database::read_write, 0, false); +} + // BOOST_AUTO_TEST_SUITE_END() From 3e22a1c9c189ef63b68c804be67403f77ce71111 Mon Sep 17 00:00:00 2001 From: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com> Date: Wed, 17 Jan 2024 16:48:04 -0500 Subject: [PATCH 3/3] more cleanup on ctor failure --- src/pinnable_mapped_file.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pinnable_mapped_file.cpp b/src/pinnable_mapped_file.cpp index ed367ea..19f6d09 100644 --- a/src/pinnable_mapped_file.cpp +++ b/src/pinnable_mapped_file.cpp @@ -164,7 +164,11 @@ pinnable_mapped_file::pinnable_mapped_file(const std::filesystem::path& dir, boo set_mapped_file_db_dirty(true); } - auto reset_dirty_on_ctor_fail = scope_fail([&]() { + auto reset_on_ctor_fail = scope_fail([&]() { + _file_mapped_region = bip::mapped_region(); + if(_non_file_mapped_mapping && _non_file_mapped_mapping != MAP_FAILED) + munmap(_non_file_mapped_mapping, _non_file_mapped_mapping_size); + if(_writable) set_mapped_file_db_dirty(false); std::erase(_instance_tracker, this);