From 31db8476768ba68296ad91b6785bb06a6a9abf71 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Thu, 18 Apr 2024 15:02:42 +0300 Subject: [PATCH] MDEV-32363 Add interface to set node isolation mode in provider --- include/wsrep/provider.hpp | 25 ++++++++++++++++++++++ src/service_helpers.hpp | 24 ++++++++++++++++++++- src/wsrep_provider_v26.cpp | 44 +++++++++++++++++++++++++++++++++++++- src/wsrep_provider_v26.hpp | 1 + test/mock_provider.hpp | 3 +++ wsrep-API/v26 | 2 +- 6 files changed, 96 insertions(+), 3 deletions(-) diff --git a/include/wsrep/provider.hpp b/include/wsrep/provider.hpp index c00e9ed..5e82ecd 100644 --- a/include/wsrep/provider.hpp +++ b/include/wsrep/provider.hpp @@ -288,6 +288,21 @@ namespace wsrep static std::string str(int); }; + /** + * Node isolation mode. + */ + enum node_isolation + { + /** Node is not isolated. */ + not_isolated, + /** Node is isolated from the rest of the cluster on + * network level. */ + isolated, + /** As on, but also force the provider to deliver a view with + * disconnected status. */ + force_disconnect + }; + provider(wsrep::server_state& server_state) : server_state_(server_state) { } @@ -389,6 +404,16 @@ namespace wsrep virtual std::string options() const = 0; virtual enum status options(const std::string&) = 0; + + + /** + * Set node isolation mode. + * + * @param mode node_isolation mode. + * @return Provider status indicating the result of the call. + */ + virtual enum status set_node_isolation(enum node_isolation mode) = 0; + /** * Get provider name. * diff --git a/src/service_helpers.hpp b/src/service_helpers.hpp index 6e9f9ca..5ebe187 100644 --- a/src/service_helpers.hpp +++ b/src/service_helpers.hpp @@ -100,7 +100,29 @@ namespace wsrep_impl << service_name; } } -} + + template Fn resolve_function(void* dlh, const char* symbol) + { + union + { + Fn fun; + void* obj; + } alias; + (void)dlerror(); + alias.obj = dlsym(dlh, symbol); + if (alias.obj) + { + wsrep::log_info() << "Resolved symbol '" << symbol << "'"; + return alias.fun; + } + else + { + wsrep::log_info() + << "Symbol '" << symbol << "' not found from provider"; + return nullptr; + } + } +} // namespace wsrep_impl #endif // WSREP_SERVICE_HELPERS_HPP diff --git a/src/wsrep_provider_v26.cpp b/src/wsrep_provider_v26.cpp index eb8679c..8fa9fee 100644 --- a/src/wsrep_provider_v26.cpp +++ b/src/wsrep_provider_v26.cpp @@ -29,12 +29,13 @@ #include "wsrep/tls_service.hpp" #include "wsrep/allowlist_service.hpp" +#include "service_helpers.hpp" #include "thread_service_v1.hpp" #include "tls_service_v1.hpp" #include "allowlist_service_v1.hpp" #include "event_service_v1.hpp" #include "v26/wsrep_api.h" - +#include "v26/wsrep_node_isolation.h" #include #include @@ -671,6 +672,8 @@ namespace { wsrep::event_service_v1_deinit(dlh); } + + wsrep_node_isolation_mode_set_fn_v1 node_isolation_mode_set; } @@ -714,6 +717,10 @@ void wsrep::wsrep_provider_v26::init_services( services_enabled_.event_service = services.event_service; } } + + node_isolation_mode_set + = wsrep_impl::resolve_function( + wsrep_->dlh, WSREP_NODE_ISOLATION_MODE_SET_V1); } void wsrep::wsrep_provider_v26::deinit_services() @@ -726,6 +733,7 @@ void wsrep::wsrep_provider_v26::deinit_services() deinit_thread_service(wsrep_->dlh); if (services_enabled_.allowlist_service) deinit_allowlist_service(wsrep_->dlh); + node_isolation_mode_set = nullptr; } wsrep::wsrep_provider_v26::wsrep_provider_v26( @@ -1162,6 +1170,40 @@ wsrep::wsrep_provider_v26::options(const std::string& opts) return map_return_value(wsrep_->options_set(wsrep_, opts.c_str())); } +/* + * Set node isolation mode in the provider. This function may be called from + * signal handler, so make sure that only 'safe' system calls and library + * functions are used. See + * https://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html + */ +enum wsrep::provider::status +wsrep::wsrep_provider_v26::set_node_isolation(node_isolation mode) +{ + if (not node_isolation_mode_set) + { + return error_not_implemented; + } + + enum wsrep_node_isolation_mode ws_mode = WSREP_NODE_ISOLATION_NOT_ISOLATED; + switch (mode) + { + case node_isolation::not_isolated: + ws_mode = WSREP_NODE_ISOLATION_NOT_ISOLATED; + break; + case node_isolation::isolated: + ws_mode = WSREP_NODE_ISOLATION_ISOLATED; + break; + case node_isolation::force_disconnect: + ws_mode = WSREP_NODE_ISOLATION_FORCE_DISCONNECT; + break; + } + if ((*node_isolation_mode_set)(ws_mode) != WSREP_NODE_ISOLATION_SUCCESS) + { + return error_warning; + } + return success; +} + std::string wsrep::wsrep_provider_v26::name() const { return (wsrep_->provider_name ? wsrep_->provider_name : "unknown"); diff --git a/src/wsrep_provider_v26.hpp b/src/wsrep_provider_v26.hpp index 608b7c9..2e03c55 100644 --- a/src/wsrep_provider_v26.hpp +++ b/src/wsrep_provider_v26.hpp @@ -100,6 +100,7 @@ namespace wsrep void reset_status() WSREP_OVERRIDE; std::string options() const WSREP_OVERRIDE; enum wsrep::provider::status options(const std::string&) WSREP_OVERRIDE; + enum status set_node_isolation(enum node_isolation mode) WSREP_OVERRIDE; std::string name() const WSREP_OVERRIDE; std::string version() const WSREP_OVERRIDE; std::string vendor() const WSREP_OVERRIDE; diff --git a/test/mock_provider.hpp b/test/mock_provider.hpp index bcfd2e4..b99ddeb 100644 --- a/test/mock_provider.hpp +++ b/test/mock_provider.hpp @@ -294,6 +294,9 @@ namespace wsrep enum wsrep::provider::status options(const std::string&) WSREP_OVERRIDE { return wsrep::provider::success; } + enum status set_node_isolation(enum node_isolation) WSREP_OVERRIDE { + return error_not_implemented; + } std::string name() const WSREP_OVERRIDE { return "mock"; } std::string version() const WSREP_OVERRIDE { return "0.0"; } std::string vendor() const WSREP_OVERRIDE { return "mock"; } diff --git a/wsrep-API/v26 b/wsrep-API/v26 index 06ce602..427c73c 160000 --- a/wsrep-API/v26 +++ b/wsrep-API/v26 @@ -1 +1 @@ -Subproject commit 06ce602ade58389cdd5db785934dbfe4d9b00ec4 +Subproject commit 427c73c5c8c443765ec16bfc70d94a65a7fca64c