From 23da53011fdfb819ad9179d620d259348de7154f Mon Sep 17 00:00:00 2001 From: Brian Szmyd Date: Wed, 12 Nov 2025 21:40:01 -0700 Subject: [PATCH 1/2] Remove dependence on folly::Expected --- .github/workflows/build_dependencies.yml | 61 ++------------ .jenkins/Jenkinsfile | 8 +- CMakeLists.txt | 2 +- conanfile.py | 8 +- .../homestore/replication/repl_decls.h | 5 +- src/lib/common/resource_mgr.cpp | 5 +- src/lib/device/device_manager.cpp | 6 +- src/lib/replication/repl_dev/common.cpp | 2 +- src/lib/replication/repl_dev/common.h | 8 +- .../replication/repl_dev/raft_repl_dev.cpp | 34 ++++---- src/lib/replication/repl_dev/raft_repl_dev.h | 4 +- .../replication/service/generic_repl_svc.cpp | 4 +- .../replication/service/raft_repl_service.cpp | 4 +- .../replication/service/raft_repl_service.h | 1 - src/tests/test_common/hs_repl_test_common.hpp | 2 +- src/tests/test_common/raft_repl_test_base.hpp | 6 +- src/tests/test_index_gc.cpp | 81 +++++++++---------- 17 files changed, 95 insertions(+), 146 deletions(-) diff --git a/.github/workflows/build_dependencies.yml b/.github/workflows/build_dependencies.yml index bcf6b6d65..c094054ee 100644 --- a/.github/workflows/build_dependencies.yml +++ b/.github/workflows/build_dependencies.yml @@ -164,22 +164,22 @@ jobs: conan export --user oss --channel main import/nuraft_mesg if: ${{ inputs.testing == 'True' || steps.restore-cache.outputs.cache-hit != 'true' }} - - name: Build Cache + - name: Create and Test Package run: | + sanitize=$([[ "${{ inputs.tooling }}" == "Sanitize" ]] && echo "True" || echo "False") pre=$([[ "${{ inputs.build-type }}" != "Debug" ]] && echo "-o iomgr/*:prerelease=${{ inputs.prerelease }}" || echo "") - conan install \ - -c tools.build:skip_test=True \ + conan build \ ${pre} \ -o sisl/*:malloc_impl=${{ inputs.malloc-impl }} \ -o iomgr/*:testing=off \ - -o homestore/*:testing=off \ + -o homestore/*:sanitize=${sanitize} \ -s:h build_type=${{ inputs.build-type }} \ - -c tools.build:skip_test=True \ + -s:h compiler.cppstd=23 \ --format=json \ --build missing \ . > ~/build.json conan list --graph ~/build.json --graph-binaries=build --format=json > ~/pkglist.json - if: ${{ steps.restore-cache.outputs.cache-hit != 'true' }} + if: ${{ inputs.testing == 'True' && inputs.tooling != 'Coverage' }} - name: Save Conan Cache uses: eBay/sisl/.github/actions/store_conan2@master @@ -187,54 +187,6 @@ jobs: key_prefix: HomestoreDeps-${{ inputs.platform }}-${{ inputs.build-type }}-${{ inputs.malloc-impl }}-${{ inputs.prerelease }} if: ${{ github.event_name != 'pull_request' && steps.restore-cache.outputs.cache-hit != 'true' }} - - name: Reload Sisl Cache - uses: eBay/sisl/.github/actions/load_conan2@master - with: - load_any: 'True' - key_prefix: SislDeps13-${{ inputs.platform }}-${{ inputs.build-type }}-${{ inputs.malloc-impl }} - if: ${{ inputs.testing == 'True' && github.event_name != 'pull_request' && steps.restore-cache.outputs.cache-hit != 'true' }} - - - name: Reload IOMgr Cache - uses: eBay/sisl/.github/actions/load_conan2@master - with: - testing: 'False' - path: import/iomgr - key_prefix: IOMgrDeps-${{ inputs.platform }}-${{ inputs.build-type }}-${{ inputs.malloc-impl }}-${{ inputs.prerelease }} - fail_on_cache_miss: true - if: ${{ inputs.testing == 'True' && github.event_name != 'pull_request' && steps.restore-cache.outputs.cache-hit != 'true' }} - - - name: Reload NuraftMesg Cache - uses: eBay/sisl/.github/actions/load_conan2@master - with: - testing: 'False' - path: import/nuraft_mesg - key_prefix: NuMesgDeps-${{ inputs.platform }}-${{ inputs.build-type }}-${{ inputs.malloc-impl }} - fail_on_cache_miss: true - if: ${{ inputs.testing == 'True' && github.event_name != 'pull_request' && steps.restore-cache.outputs.cache-hit != 'true' }} - - - uses: actions/checkout@main - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - with: - limit-access-to-actor: true - detached: true - connect-timeout-seconds: 60 - if: ${{ inputs.testing == 'True' }} - - - name: Create and Test Package - run: | - sanitize=$([[ "${{ inputs.tooling }}" == "Sanitize" ]] && echo "True" || echo "False") - pre=$([[ "${{ inputs.build-type }}" != "Debug" ]] && echo "-o iomgr/*:prerelease=${{ inputs.prerelease }}" || echo "") - conan create \ - ${pre} \ - -o sisl/*:malloc_impl=${{ inputs.malloc-impl }} \ - -o iomgr/*:testing=off \ - -o homestore/*:sanitize=${sanitize} \ - -s:h build_type=${{ inputs.build-type }} \ - --build missing \ - . - if: ${{ inputs.testing == 'True' && inputs.tooling != 'Coverage' }} - - name: Code Coverage Run run: | pre=$([[ "${{ inputs.build-type }}" != "Debug" ]] && echo "-o iomgr/*:prerelease=${{ inputs.prerelease }}" || echo "") @@ -244,6 +196,7 @@ jobs: -o iomgr/*:testing=off \ -o homestore/*:coverage=True \ -s:h build_type=${{ inputs.build-type }} \ + -s:h compiler.cppstd=23 \ --build missing \ . if: ${{ inputs.testing == 'True' && inputs.tooling == 'Coverage' }} diff --git a/.jenkins/Jenkinsfile b/.jenkins/Jenkinsfile index 6e1879f96..3015689ce 100644 --- a/.jenkins/Jenkinsfile +++ b/.jenkins/Jenkinsfile @@ -64,10 +64,10 @@ pipeline { steps { sh "hostname ; \ echo $NODE_NAME ; \ - conan create ${BUILD_MISSING} -s:h build_type=Debug -o ${PROJECT}/*:sanitize=True ${CONAN_FLAGS} . ; \ - conan create ${BUILD_MISSING} -s:h build_type=Debug ${CONAN_FLAGS} . ; \ - conan create ${BUILD_MISSING} -s:h build_type=RelWithDebInfo -o sisl/*:malloc_impl=tcmalloc ${CONAN_FLAGS} . ; \ - conan create ${BUILD_MISSING} -s:h build_type=RelWithDebInfo -o sisl/*:prerelease=True -o sisl/*:malloc_impl=tcmalloc ${CONAN_FLAGS} . ; \ + conan build -s:h compiler.cppstd=23 ${BUILD_MISSING} -s:h build_type=Debug -o ${PROJECT}/*:sanitize=True ${CONAN_FLAGS} . ; \ + conan create ${BUILD_MISSING} -s:h compiler.cppstd=23 -s:h build_type=Debug ${CONAN_FLAGS} . ; \ + conan create ${BUILD_MISSING} -s:h compiler.cppstd=23 -s:h build_type=RelWithDebInfo -o sisl/*:malloc_impl=tcmalloc ${CONAN_FLAGS} . ; \ + conan create ${BUILD_MISSING} -s:h compiler.cppstd=23 -s:h build_type=RelWithDebInfo -o sisl/*:prerelease=True -o sisl/*:malloc_impl=tcmalloc ${CONAN_FLAGS} . ; \ " } post { diff --git a/CMakeLists.txt b/CMakeLists.txt index e1a0bbdc0..12d9832e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON) # turn on folder hierarchies include (cmake/Flags.cmake) -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) enable_testing() include (cmake/test_mode.cmake) diff --git a/conanfile.py b/conanfile.py index 4519e6823..25cbea69b 100644 --- a/conanfile.py +++ b/conanfile.py @@ -5,7 +5,7 @@ from conan.tools.files import copy from os.path import join -required_conan_version = ">=1.60.0" +required_conan_version = ">=2.0" class HomestoreConan(ConanFile): name = "homestore" @@ -47,6 +47,10 @@ def configure(self): if self.options.coverage or self.options.sanitize: raise ConanInvalidConfiguration("Coverage/Sanitizer requires Testing!") + def validate(self): + if self.info.settings.compiler.cppstd: + check_min_cppstd(self, 23) + def build_requirements(self): self.test_requires("benchmark/1.9.4") self.test_requires("gtest/1.17.0") @@ -54,7 +58,7 @@ def build_requirements(self): def requirements(self): self.requires("iomgr/[^12]@oss/master", transitive_headers=True) self.requires("sisl/[^13]@oss/master", transitive_headers=True) - self.requires("nuraft_mesg/[^4]@oss/main", transitive_headers=True) + self.requires("nuraft_mesg/[^5]@oss/main", transitive_headers=True) self.requires("farmhash/cci.20190513@", transitive_headers=True) if self.settings.arch in ['x86', 'x86_64']: diff --git a/src/include/homestore/replication/repl_decls.h b/src/include/homestore/replication/repl_decls.h index a34d39387..e28313c67 100644 --- a/src/include/homestore/replication/repl_decls.h +++ b/src/include/homestore/replication/repl_decls.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include @@ -56,7 +57,7 @@ VENUM(ReplaceMemberStatus, int32_t, // clang-format on template < typename V, typename E > -using Result = folly::Expected< V, E >; +using Result = std::expected< V, E >; template < class V > using ReplResult = Result< V, ReplServiceError >; @@ -64,7 +65,7 @@ using ReplResult = Result< V, ReplServiceError >; template < class V, class E > using AsyncResult = folly::SemiFuture< Result< V, E > >; -template < class V = folly::Unit > +template < class V = void > using AsyncReplResult = AsyncResult< V, ReplServiceError >; using blkid_list_t = folly::small_vector< BlkId, 4 >; diff --git a/src/lib/common/resource_mgr.cpp b/src/lib/common/resource_mgr.cpp index 14aee150d..74e5f84e4 100644 --- a/src/lib/common/resource_mgr.cpp +++ b/src/lib/common/resource_mgr.cpp @@ -193,8 +193,9 @@ bool ResourceMgr::check_journal_vdev_size(const uint64_t used_size, const uint64 const uint32_t used_pct = (100 * used_size / total_size); if (used_pct >= get_journal_vdev_size_limit()) { m_journal_vdev_exceed_cb(used_size, used_pct >= get_journal_vdev_size_critical_limit() /* is_critical */); - HS_LOG_EVERY_N(WARN, base, unmove(50), "high watermark hit, used percentage: {}, high watermark percentage: {}", - used_pct, get_journal_vdev_size_limit()); + HS_LOG_EVERY_N(WARN, base, unmove(50), + "high watermark hit, used percentage: {}, high watermark percentage: {}", used_pct, + get_journal_vdev_size_limit()); return true; } } diff --git a/src/lib/device/device_manager.cpp b/src/lib/device/device_manager.cpp index f4b3cf19a..12fefd12d 100644 --- a/src/lib/device/device_manager.cpp +++ b/src/lib/device/device_manager.cpp @@ -115,7 +115,7 @@ void DeviceManager::format_devices() { // Get common iomgr_attributes for (auto& dinfo : m_dev_infos) { format_single_device(dinfo); - } + } // Verify the first blocks to see if the devs are unique HS_REL_ASSERT(verify_unique_devs(), "Found duplicate physical devices in the system"); @@ -163,7 +163,9 @@ bool DeviceManager::verify_unique_devs() const { for (auto& pdev : m_all_pdevs) { if (!pdev) { continue; } auto buf = hs_utils::iobuf_alloc(hs_super_blk::first_block_size(), sisl::buftag::superblk, 512); - if (auto err = pdev->read_super_block(buf, hs_super_blk::first_block_size(), hs_super_blk::first_block_offset()); err) { + if (auto err = + pdev->read_super_block(buf, hs_super_blk::first_block_size(), hs_super_blk::first_block_offset()); + err) { LOGERROR("Failed to read first block from device={}, error={}", pdev->get_devname(), err.message()); ret = false; continue; diff --git a/src/lib/replication/repl_dev/common.cpp b/src/lib/replication/repl_dev/common.cpp index fbc732775..d24177bfd 100644 --- a/src/lib/replication/repl_dev/common.cpp +++ b/src/lib/replication/repl_dev/common.cpp @@ -133,7 +133,7 @@ ReplServiceError repl_req_ctx::alloc_local_blks(cshared< ReplDevListener >& list DEBUG_ASSERT(has_linked_data(), "Trying to allocate a block for non-inlined block"); auto const hints_result = listener->get_blk_alloc_hints(m_header, data_size, repl_req_ptr_t(this)); - if (hints_result.hasError()) { return hints_result.error(); } + if (!hints_result.has_value()) { return hints_result.error(); } if (hints_result.value().committed_blk_id.has_value()) { // if the committed_blk_id is already present, use it and skip allocation and commitment diff --git a/src/lib/replication/repl_dev/common.h b/src/lib/replication/repl_dev/common.h index 3085a9d3c..3a935fe95 100644 --- a/src/lib/replication/repl_dev/common.h +++ b/src/lib/replication/repl_dev/common.h @@ -81,9 +81,9 @@ struct repl_dev_superblk { #pragma pack() -template < class V = folly::Unit > +template < class V = void > auto make_async_error(ReplServiceError err) { - return folly::makeSemiFuture< ReplResult< V > >(folly::makeUnexpected(err)); + return folly::makeSemiFuture< ReplResult< V > >(std::unexpected(err)); } template < class V > @@ -91,9 +91,9 @@ auto make_async_success(V v) { return folly::makeSemiFuture< ReplResult< V > >(std::move(v)); } -template < class V = folly::Unit > +template < class V = void > auto make_async_success() { - return folly::makeSemiFuture< ReplResult< folly::Unit > >(folly::Unit{}); + return folly::makeSemiFuture< ReplResult< void > >(ReplResult< void >()); } inline uint64_t generateRandomTraceId() { diff --git a/src/lib/replication/repl_dev/raft_repl_dev.cpp b/src/lib/replication/repl_dev/raft_repl_dev.cpp index 0be8ae0bd..b54a1cc7a 100644 --- a/src/lib/replication/repl_dev/raft_repl_dev.cpp +++ b/src/lib/replication/repl_dev/raft_repl_dev.cpp @@ -177,9 +177,7 @@ AsyncReplResult<> RaftReplDev::start_replace_member(std::string& task_id, const RD_LOGE(trace_id, "Step1. Replace member invalid parameter, out member is not found, task_id={}", task_id); return make_async_error<>(ReplServiceError::SERVER_NOT_FOUND); } - if (m_my_repl_id != get_leader_id()) { - return make_async_error<>(ReplServiceError::NOT_LEADER); - } + if (m_my_repl_id != get_leader_id()) { return make_async_error<>(ReplServiceError::NOT_LEADER); } // Check if leader itself is requested to move out. if (m_my_repl_id == member_out.id) { // immediate=false successor=-1, nuraft will choose an alive peer with highest priority as successor, and wait @@ -405,9 +403,7 @@ ReplaceMemberStatus RaftReplDev::get_replace_member_status(std::string& task_id, } init_req_counter counter(pending_request_num); - if (!m_repl_svc_ctx || !is_leader()) { - return ReplaceMemberStatus::NOT_LEADER; - } + if (!m_repl_svc_ctx || !is_leader()) { return ReplaceMemberStatus::NOT_LEADER; } auto peers = get_replication_status(); peer_info out_peer_info; @@ -480,7 +476,7 @@ ReplServiceError RaftReplDev::do_add_member(const replica_member_info& member, u auto add_ret = m_msg_mgr.add_member(m_group_id, srv_config) .via(&folly::InlineExecutor::instance()) .thenValue([this, member, trace_id](auto&& e) -> nuraft::cmd_result_code { - return e.hasError() ? e.error() : nuraft::cmd_result_code::OK; + return (!e.has_value()) ? e.error() : nuraft::cmd_result_code::OK; }); return add_ret.value(); }, @@ -517,7 +513,7 @@ ReplServiceError RaftReplDev::do_remove_member(const replica_member_info& member auto rem_ret = m_msg_mgr.rem_member(m_group_id, member.id) .via(&folly::InlineExecutor::instance()) .thenValue([this, member, trace_id](auto&& e) -> nuraft::cmd_result_code { - return e.hasError() ? e.error() : nuraft::cmd_result_code::OK; + return (!e.has_value()) ? e.error() : nuraft::cmd_result_code::OK; }); return rem_ret.value(); }, @@ -706,7 +702,7 @@ void RaftReplDev::on_create_snapshot(nuraft::snapshot& s, nuraft::async_result< auto snp_ctx = std::make_shared< nuraft_snapshot_context >(s); auto result = m_listener->create_snapshot(snp_ctx).get(); auto null_except = std::shared_ptr< std::exception >(); - HS_REL_ASSERT(result.hasError() == false, "Not expecting creating snapshot to return false. "); + HS_REL_ASSERT((!result.has_value()) == false, "Not expecting creating snapshot to return false. "); // propose truncate boundary on leader if needed if (is_leader()) { propose_truncate_boundary(); } @@ -890,7 +886,7 @@ void RaftReplDev::push_data_to_all_followers(repl_req_ptr_t rreq, sisl::sg_list for (auto const& res : v_res) { if (sisl_likely(res.value())) { auto r = res.value(); - if (r.hasError()) { + if (!r.has_value()) { // Just logging PushData error, no action is needed as follower can try by fetchData. RD_LOGI(rreq->traceID(), "Data Channel: Error in pushing data to all followers: rreq=[{}] error={}", rreq->to_string(), r.error()); @@ -1692,13 +1688,15 @@ AsyncReplResult<> RaftReplDev::become_leader() { } init_req_counter counter(pending_request_num); - return m_msg_mgr.become_leader(m_group_id).via(&folly::InlineExecutor::instance()).thenValue([this, counter = std::move(counter)](auto&& e) { - if (e.hasError()) { - RD_LOGE(NO_TRACE_ID, "Error in becoming leader: {}", e.error()); - return make_async_error<>(RaftReplService::to_repl_error(e.error())); - } - return make_async_success<>(); - }); + return m_msg_mgr.become_leader(m_group_id) + .via(&folly::InlineExecutor::instance()) + .thenValue([this, counter = std::move(counter)](auto&& e) { + if (!e.has_value()) { + RD_LOGE(NO_TRACE_ID, "Error in becoming leader: {}", e.error()); + return make_async_error<>(RaftReplService::to_repl_error(e.error())); + } + return make_async_success<>(); + }); } bool RaftReplDev::is_leader() const { return m_repl_svc_ctx && m_repl_svc_ctx->is_raft_leader(); } @@ -2159,7 +2157,7 @@ void RaftReplDev::monitor_replace_member_replication_status() { replica_member_info out{replica_out, ""}; replica_member_info in{replica_in, ""}; auto ret = complete_replace_member(task_id, out, in, 0, trace_id).get(); - if (ret.hasError()) { + if (!ret.has_value()) { RD_LOGE(trace_id, "Failed to complete replace member, next time will retry it, task_id={}, error={}", task_id, ret.error()); return; diff --git a/src/lib/replication/repl_dev/raft_repl_dev.h b/src/lib/replication/repl_dev/raft_repl_dev.h index 61f5cac0d..a28c72211 100644 --- a/src/lib/replication/repl_dev/raft_repl_dev.h +++ b/src/lib/replication/repl_dev/raft_repl_dev.h @@ -357,9 +357,9 @@ class RaftReplDev : public ReplDev, void become_leader_cb(); - void become_follower_cb() { + void become_follower_cb() { m_traffic_ready_lsn.store(0); - RD_LOGD(NO_TRACE_ID, "become_follower_cb called!"); + RD_LOGD(NO_TRACE_ID, "become_follower_cb called!"); } /// @brief This method is called when the data journal is compacted diff --git a/src/lib/replication/service/generic_repl_svc.cpp b/src/lib/replication/service/generic_repl_svc.cpp index b5966f239..2f5a489e7 100644 --- a/src/lib/replication/service/generic_repl_svc.cpp +++ b/src/lib/replication/service/generic_repl_svc.cpp @@ -54,7 +54,7 @@ GenericReplService::~GenericReplService() { ReplResult< shared< ReplDev > > GenericReplService::get_repl_dev(group_id_t group_id) const { std::shared_lock lg(m_rd_map_mtx); if (auto it = m_rd_map.find(group_id); it != m_rd_map.end()) { return it->second; } - return folly::makeUnexpected(ReplServiceError::SERVER_NOT_FOUND); + return std::unexpected(ReplServiceError::SERVER_NOT_FOUND); } void GenericReplService::iterate_repl_devs(std::function< void(cshared< ReplDev >&) > const& cb) { @@ -147,7 +147,7 @@ AsyncReplResult< shared< ReplDev > > SoloReplService::create_repl_dev(group_id_t folly::SemiFuture< ReplServiceError > SoloReplService::remove_repl_dev(group_id_t group_id) { // RD_LOGI("Removing repl dev for group_id={}", boost::uuids::to_string(group_id)); auto rdev = get_repl_dev(group_id); - if (rdev.hasError()) { return folly::makeSemiFuture(rdev.error()); } + if (!rdev.has_value()) { return folly::makeSemiFuture(rdev.error()); } auto rdev_ptr = rdev.value(); diff --git a/src/lib/replication/service/raft_repl_service.cpp b/src/lib/replication/service/raft_repl_service.cpp index 85f3554ed..b93fe97f5 100644 --- a/src/lib/replication/service/raft_repl_service.cpp +++ b/src/lib/replication/service/raft_repl_service.cpp @@ -527,7 +527,7 @@ AsyncReplResult<> RaftReplService::replace_member(group_id_t group_id, std::stri ->start_replace_member(task_id, member_out, member_in, commit_quorum, trace_id) .via(&folly::InlineExecutor::instance()) .thenValue([this](auto&& e) mutable { - if (e.hasError()) { + if (!e.has_value()) { decr_pending_request_num(); return make_async_error<>(e.error()); } @@ -550,7 +550,7 @@ AsyncReplResult<> RaftReplService::flip_learner_flag(group_id_t group_id, const ->flip_learner_flag(member, target, commit_quorum, wait_and_verify, trace_id) .via(&folly::InlineExecutor::instance()) .thenValue([this](auto&& e) mutable { - if (e.hasError()) { + if (!e.has_value()) { decr_pending_request_num(); return make_async_error<>(e.error()); } diff --git a/src/lib/replication/service/raft_repl_service.h b/src/lib/replication/service/raft_repl_service.h index 857f71471..0cf73d06c 100644 --- a/src/lib/replication/service/raft_repl_service.h +++ b/src/lib/replication/service/raft_repl_service.h @@ -19,7 +19,6 @@ #include #include -#include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wuninitialized" #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" diff --git a/src/tests/test_common/hs_repl_test_common.hpp b/src/tests/test_common/hs_repl_test_common.hpp index 25315221f..9009c4e0a 100644 --- a/src/tests/test_common/hs_repl_test_common.hpp +++ b/src/tests/test_common/hs_repl_test_common.hpp @@ -310,7 +310,7 @@ class HSReplTestHelper : public HSTestHelper { } auto v = hs()->repl_service().create_repl_dev(repl_group_id, members).get(); - ASSERT_EQ(v.hasValue(), true) + ASSERT_EQ(v.has_value(), true) << "Error in creating repl dev for group_id=" << boost::uuids::to_string(repl_group_id).c_str() << ", err=" << v.error(); auto& raftService = dynamic_cast< RaftReplService& >(hs()->repl_service()); diff --git a/src/tests/test_common/raft_repl_test_base.hpp b/src/tests/test_common/raft_repl_test_base.hpp index 6f80839c8..dc4804d93 100644 --- a/src/tests/test_common/raft_repl_test_base.hpp +++ b/src/tests/test_common/raft_repl_test_base.hpp @@ -566,7 +566,7 @@ class RaftReplDevTestBase : public testing::Test { for (auto const& db : dbs_) { do { auto result = db->repl_dev()->become_leader().get(); - if (result.hasError()) { + if (!result.has_value()) { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } else { break; @@ -778,9 +778,9 @@ class RaftReplDevTestBase : public testing::Test { auto result = hs()->repl_service().replace_member(db->repl_dev()->group_id(), task_id, out, in, commit_quorum).get(); if (error == ReplServiceError::OK) { - ASSERT_EQ(result.hasError(), false) << "Error in replacing member, err=" << result.error(); + ASSERT_EQ(!result.has_value(), false) << "Error in replacing member, err=" << result.error(); } else { - ASSERT_EQ(result.hasError(), true); + ASSERT_EQ(!result.has_value(), true); ASSERT_EQ(result.error(), error) << "Error in replacing member, err=" << result.error(); } }); diff --git a/src/tests/test_index_gc.cpp b/src/tests/test_index_gc.cpp index 712f56202..af6205e9c 100644 --- a/src/tests/test_index_gc.cpp +++ b/src/tests/test_index_gc.cpp @@ -12,7 +12,6 @@ #include "btree_helpers/btree_decls.h" #include "btree_helpers/blob_route.h" - using namespace homestore; SISL_LOGGING_INIT(HOMESTORE_LOG_MODS) @@ -22,11 +21,11 @@ SISL_LOGGING_DECL(test_index_gc) SISL_OPTION_GROUP( test_index_gc, (num_iters, "", "num_iters", "number of iterations for rand ops", - ::cxxopts::value< uint32_t >()->default_value("500000"), "number"), + ::cxxopts::value< uint32_t >()->default_value("500000"), "number"), (num_entries, "", "num_entries", "number of entries to test with", ::cxxopts::value< uint32_t >()->default_value("7000"), "number"), - (num_put, "", "num_put", "number of entries to test with", - ::cxxopts::value< uint32_t >()->default_value("20000"), "number"), + (num_put, "", "num_put", "number of entries to test with", ::cxxopts::value< uint32_t >()->default_value("20000"), + "number"), (run_time, "", "run_time", "run time for io", ::cxxopts::value< uint64_t >()->default_value("36000"), "seconds"), (disable_merge, "", "disable_merge", "disable_merge", ::cxxopts::value< bool >()->default_value("0"), ""), (operation_list, "", "operation_list", "operation list instead of default created following by percentage", @@ -34,7 +33,8 @@ SISL_OPTION_GROUP( (preload_size, "", "preload_size", "number of entries to preload tree with", ::cxxopts::value< uint32_t >()->default_value("1000"), "number"), (init_device, "", "init_device", "init device", ::cxxopts::value< bool >()->default_value("1"), ""), - (ignore_node_lock_refresh, "", "ignore_node_lock_refresh", "ignore node lock refresh", ::cxxopts::value< bool >(), ""), + (ignore_node_lock_refresh, "", "ignore_node_lock_refresh", "ignore node lock refresh", ::cxxopts::value< bool >(), + ""), (cleanup_after_shutdown, "", "cleanup_after_shutdown", "cleanup after shutdown", ::cxxopts::value< bool >()->default_value("1"), ""), (max_merge_level, "", "max_merge_level", "max merge level", ::cxxopts::value< uint8_t >()->default_value("127"), @@ -42,7 +42,6 @@ SISL_OPTION_GROUP( (seed, "", "seed", "random engine seed, use random if not defined", ::cxxopts::value< uint64_t >()->default_value("0"), "number")) - using BtreeType = IndexTable< BlobRouteByChunkKey, TestFixedValue >; using op_func_t = std::function< void(void) >; static constexpr uint32_t g_num_fibers{4}; @@ -93,10 +92,10 @@ class TestIndexGC : public ::testing::Test { create_io_reactors(g_num_fibers); m_run_time = SISL_OPTIONS["run_time"].as< uint64_t >(); - //m_operations["put"] = std::bind(&BtreeTestHelper::put_random, this); - //m_operations["range_remove"] = std::bind(&BtreeTestHelper::range_remove_existing_random, this); - //m_operations["range_query"] = std::bind(&BtreeTestHelper::query_random, this); - //m_operations["get"] = std::bind(&BtreeTestHelper::get_random, this); + // m_operations["put"] = std::bind(&BtreeTestHelper::put_random, this); + // m_operations["range_remove"] = std::bind(&BtreeTestHelper::range_remove_existing_random, this); + // m_operations["range_query"] = std::bind(&BtreeTestHelper::query_random, this); + // m_operations["get"] = std::bind(&BtreeTestHelper::get_random, this); m_bt = std::make_shared< BtreeType >(uuid, parent_uuid, 0, m_cfg); hs()->index_service().add_index_table(m_bt); LOGINFO("Added index table to index service"); @@ -131,17 +130,17 @@ class TestIndexGC : public ::testing::Test { }; auto ctx = std::make_shared< Context >(); for (uint32_t i{0}; i < num_io_reactors; ++i) { - iomanager.create_reactor("homeblks_long_running_io" + std::to_string(i), iomgr::INTERRUPT_LOOP, 1u, - [this, ctx](bool is_started) { - if (is_started) { - { - std::unique_lock< std::mutex > lk{ctx->mtx}; - m_fibers.push_back(iomanager.iofiber_self()); - ++(ctx->thread_cnt); + iomanager.create_reactor("homeblks_long_running_io" + std::to_string(i), iomgr::INTERRUPT_LOOP, 1u, + [this, ctx](bool is_started) { + if (is_started) { + { + std::unique_lock< std::mutex > lk{ctx->mtx}; + m_fibers.push_back(iomanager.iofiber_self()); + ++(ctx->thread_cnt); + } + ctx->cv.notify_one(); } - ctx->cv.notify_one(); - } - }); + }); } { std::unique_lock< std::mutex > lk{ctx->mtx}; @@ -152,7 +151,8 @@ class TestIndexGC : public ::testing::Test { void put_many_random(uint16_t chunk_id, uint32_t num_put) { for (uint16_t i = 0; i < num_put; ++i) { - auto key = BlobRouteByChunkKey{BlobRouteByChunk(chunk_id, g_randval_generator(g_re), g_randval_generator(g_re))}; + auto key = + BlobRouteByChunkKey{BlobRouteByChunk(chunk_id, g_randval_generator(g_re), g_randval_generator(g_re))}; auto value = TestFixedValue::generate_rand(); auto sreq = BtreeSinglePutRequest{&key, &value, btree_put_type::UPSERT}; sreq.enable_route_tracing(); @@ -189,13 +189,13 @@ class TestIndexGC : public ::testing::Test { status = m_bt->query(query_req, valid_blob_indexes); if (status != homestore::btree_status_t::success) { LOGERROR("Failed to query blobs after purging reserved chunk={} in gc index table, index ret={}", chunk_id, - status); + status); return false; } if (!valid_blob_indexes.empty()) { LOGERROR("gc index table is not empty for chunk={} after purging, valid_blob_indexes.size={}", chunk_id, - valid_blob_indexes.size()); + valid_blob_indexes.size()); return SISL_OPTIONS["ignore_node_lock_refresh"].as< bool >(); } @@ -205,18 +205,18 @@ class TestIndexGC : public ::testing::Test { void gc_task(uint32_t idx) { LOGINFO("GC task {} started", idx); auto num_puts = SISL_OPTIONS["num_put"].as< uint32_t >(); - while(!time_to_stop()) { + while (!time_to_stop()) { // Step 1: preload chunks with some data for (uint16_t i = 0; i < 20; ++i) { - uint16_t chunk_id = 20*idx + i; + uint16_t chunk_id = 20 * idx + i; put_many_random(chunk_id, num_puts); } LOGDEBUG("Preload done for index {}", idx); // Step 2: start chunk gc for (uint16_t i = 0; i < 20; ++i) { - uint16_t chunk_id = 20*idx + i; - ASSERT_TRUE(do_gc(chunk_id)); + uint16_t chunk_id = 20 * idx + i; + ASSERT_TRUE(do_gc(chunk_id)); } LOGDEBUG("GC done for index {}", idx); auto elapsed_time = get_elapsed_time_sec(m_start_time); @@ -234,7 +234,7 @@ class TestIndexGC : public ::testing::Test { LOGINFO("Put task {} started", idx); while (!time_to_stop()) { for (uint16_t i = 0; i < 1000; ++i) { - uint16_t chunk_id = 20*idx + i; + uint16_t chunk_id = 20 * idx + i; put_many_random(chunk_id, 10); } std::this_thread::sleep_for(std::chrono::milliseconds(1000)); @@ -247,8 +247,9 @@ class TestIndexGC : public ::testing::Test { LOGINFO("Get task {} started", idx); while (!time_to_stop()) { for (uint16_t i = 0; i < 1000; ++i) { - uint16_t chunk_id = 20*idx + i; - auto key = BlobRouteByChunkKey{BlobRouteByChunk(chunk_id, g_randval_generator(g_re), g_randval_generator(g_re))}; + uint16_t chunk_id = 20 * idx + i; + auto key = BlobRouteByChunkKey{ + BlobRouteByChunk(chunk_id, g_randval_generator(g_re), g_randval_generator(g_re))}; TestFixedValue value; homestore::BtreeSingleGetRequest get_req{&key, &value}; m_bt->get(get_req); @@ -259,9 +260,7 @@ class TestIndexGC : public ::testing::Test { m_test_done_latch.count_down(); } - bool time_to_stop() const { - return (get_elapsed_time_sec(m_start_time) > m_run_time); - } + bool time_to_stop() const { return (get_elapsed_time_sec(m_start_time) > m_run_time); } BtreeConfig m_cfg{g_node_size}; std::shared_ptr< BtreeType > m_bt; @@ -278,18 +277,10 @@ class TestIndexGC : public ::testing::Test { TEST_F(TestIndexGC, chunk_gc_test) { LOGINFO("Chunk GC test start"); m_start_time = Clock::now(); - iomanager.run_on_forget(m_fibers[0], [this]() { - gc_task(0); - }); - iomanager.run_on_forget(m_fibers[1], [this]() { - gc_task(1); - }); - iomanager.run_on_forget(m_fibers[2], [this]() { - put_task(2); - }); - iomanager.run_on_forget(m_fibers[3], [this]() { - get_task(3); - }); + iomanager.run_on_forget(m_fibers[0], [this]() { gc_task(0); }); + iomanager.run_on_forget(m_fibers[1], [this]() { gc_task(1); }); + iomanager.run_on_forget(m_fibers[2], [this]() { put_task(2); }); + iomanager.run_on_forget(m_fibers[3], [this]() { get_task(3); }); m_test_done_latch.wait(); LOGINFO("Chunk GC test passed"); } From fd4d68785947cf8d125afbb5c64fc0caff76718b Mon Sep 17 00:00:00 2001 From: Brian Szmyd Date: Wed, 12 Nov 2025 21:44:15 -0700 Subject: [PATCH 2/2] Bumpt version. --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 25cbea69b..74ddca5af 100644 --- a/conanfile.py +++ b/conanfile.py @@ -9,7 +9,7 @@ class HomestoreConan(ConanFile): name = "homestore" - version = "7.0.0" + version = "7.0.1" homepage = "https://github.com/eBay/Homestore" description = "HomeStore Storage Engine"