From 627db4d751bc2e583f0800be0856a3cfb2aaf67b Mon Sep 17 00:00:00 2001 From: Alexey Zatelepin Date: Fri, 10 May 2024 15:35:27 +0200 Subject: [PATCH] utils: introduce concurrent_modification_error exception It is handy to have a base class for all instances of concurrent modifications. --- src/v/cluster/topic_table.h | 13 ++++------- src/v/cluster/topics_frontend.cc | 2 +- src/v/utils/exceptions.h | 33 +++++++++++++++++++++++++++ src/v/utils/stable_iterator_adaptor.h | 10 ++++---- 4 files changed, 43 insertions(+), 15 deletions(-) create mode 100644 src/v/utils/exceptions.h diff --git a/src/v/cluster/topic_table.h b/src/v/cluster/topic_table.h index 92bf4b70f5c3a..558e762e59198 100644 --- a/src/v/cluster/topic_table.h +++ b/src/v/cluster/topic_table.h @@ -94,22 +94,17 @@ class topic_table { // * partition::get_revision_id() // * raft::group_configuration::revision_id() - class concurrent_modification_error final : public std::exception { + class concurrent_modification_error final + : public ::concurrent_modification_error { public: concurrent_modification_error( model::revision_id initial_revision, model::revision_id current_revision) - : _msg(ssx::sformat( + : ::concurrent_modification_error(ssx::sformat( "Topic table was modified by concurrent fiber. " - "(initial_revision: " - "{}, current_revision: {}) ", + "(initial_revision: {}, current_revision: {}) ", initial_revision, current_revision)) {} - - const char* what() const noexcept final { return _msg.c_str(); } - - private: - ss::sstring _msg; }; class in_progress_update { diff --git a/src/v/cluster/topics_frontend.cc b/src/v/cluster/topics_frontend.cc index a100e95c9eb17..26749601066a5 100644 --- a/src/v/cluster/topics_frontend.cc +++ b/src/v/cluster/topics_frontend.cc @@ -1014,7 +1014,7 @@ topics_frontend::partitions_with_lost_majority( co_return errc::concurrent_modification_error; } co_return result; - } catch (const topic_table::concurrent_modification_error& e) { + } catch (const concurrent_modification_error& e) { // state changed while generating the plan, force caller to retry; vlog( clusterlog.info, diff --git a/src/v/utils/exceptions.h b/src/v/utils/exceptions.h new file mode 100644 index 0000000000000..f8289206d2fa1 --- /dev/null +++ b/src/v/utils/exceptions.h @@ -0,0 +1,33 @@ +/* + * Copyright 2024 Redpanda Data, Inc. + * + * Use of this software is governed by the Business Source License + * included in the file licenses/BSL.md + * + * As of the Change Date specified in that file, in accordance with + * the Business Source License, use of this software will be governed + * by the Apache License, Version 2.0 + */ +#pragma once + +#include "base/seastarx.h" + +#include + +#include + +/// Some objects reference state that changes comparatively rarely (e.g. +/// topic_table state) across yield points and expect these references to remain +/// valid. In case these references are invalidated by a concurrent fiber, this +/// exception is thrown. This is a signal for the caller to restart the +/// computation with up-to-date state. +class concurrent_modification_error : public std::exception { +public: + explicit concurrent_modification_error(ss::sstring s) + : _msg(std::move(s)) {} + + const char* what() const noexcept override { return _msg.c_str(); } + +private: + ss::sstring _msg; +}; diff --git a/src/v/utils/stable_iterator_adaptor.h b/src/v/utils/stable_iterator_adaptor.h index cfde5ec4d47ff..0e93cbace1227 100644 --- a/src/v/utils/stable_iterator_adaptor.h +++ b/src/v/utils/stable_iterator_adaptor.h @@ -11,20 +11,20 @@ #pragma once #include "base/seastarx.h" +#include "utils/exceptions.h" #include #include #include -#include -#include #include -class iterator_stability_violation : public std::runtime_error { +class iterator_stability_violation final + : public concurrent_modification_error { public: - explicit iterator_stability_violation(const std::string& why) - : std::runtime_error(why){}; + explicit iterator_stability_violation(ss::sstring why) + : concurrent_modification_error(std::move(why)){}; }; /*