From cb8f870d58f3af6e305c31fe33a9c5333ce428c1 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Wed, 19 Feb 2025 13:31:52 +0200 Subject: [PATCH] Pass callback to get provider options to provider_v26 constructor Passing a callback allows constructing the options string using config service after loading the provider but before initializing the provider. --- include/wsrep/provider.hpp | 4 ++-- include/wsrep/server_state.hpp | 31 ++++++++++++++++++++++++++++--- src/provider.cpp | 8 ++++---- src/server_state.cpp | 5 +++-- src/wsrep_provider_v26.cpp | 3 ++- src/wsrep_provider_v26.hpp | 2 +- test/mock_server_state.hpp | 2 +- 7 files changed, 41 insertions(+), 14 deletions(-) diff --git a/include/wsrep/provider.hpp b/include/wsrep/provider.hpp index 03709de..c5d521e 100644 --- a/include/wsrep/provider.hpp +++ b/include/wsrep/provider.hpp @@ -29,6 +29,7 @@ #include +#include #include #include #include @@ -527,10 +528,9 @@ namespace wsrep static std::unique_ptr make_provider( wsrep::server_state&, const std::string& provider_spec, - const std::string& provider_options, + const std::function& provider_options_cb, const wsrep::provider::services& services = wsrep::provider::services()); - protected: wsrep::server_state& server_state_; }; diff --git a/include/wsrep/server_state.hpp b/include/wsrep/server_state.hpp index 632d43b..009a724 100644 --- a/include/wsrep/server_state.hpp +++ b/include/wsrep/server_state.hpp @@ -287,18 +287,43 @@ namespace wsrep * Load WSRep provider. * * @param provider WSRep provider library to be loaded. - * @param provider_options Provider specific options string - * to be passed for provider during initialization. + * @param provider_options_cb Callback to get provider options. + * The function to be called must be + * idempotent. * @param services Application defined services passed to * the provider. * * @return Zero on success, non-zero on error. */ int load_provider(const std::string& provider, - const std::string& provider_options, + const std::function& provider_options_cb, const wsrep::provider::services& services = wsrep::provider::services()); + + /** + * Load WSRep provider. + * + * @param provider WSRep provider library to be loaded. + * @param provider_options Provider specific options string + * to be passed for provider during initialization. + * @param services Application defined services passed to + * the provider. + * + * @return Zero on success, non-zero on error. + * + * @note Provided for backward compatibility. + */ + int load_provider(const std::string& provider, + const std::string& provider_options, + const wsrep::provider::services& services + = wsrep::provider::services()) + { + return load_provider(provider, + [provider_options]() { return provider_options; }, + services); + } + using provider_factory_func = std::function; diff --git a/src/provider.cpp b/src/provider.cpp index ce9f5da..67e8f4a 100644 --- a/src/provider.cpp +++ b/src/provider.cpp @@ -29,19 +29,19 @@ std::unique_ptr wsrep::provider::make_provider( wsrep::server_state& server_state, const std::string& provider_spec, - const std::string& provider_options, + const std::function& provider_options_cb, const wsrep::provider::services& services) { try { return std::unique_ptr(new wsrep::wsrep_provider_v26( - server_state, provider_options, provider_spec, services)); + server_state, provider_spec, provider_options_cb, services)); } catch (const wsrep::runtime_error& e) { wsrep::log_error() << "Failed to create a new provider '" << provider_spec << "'" - << " with options '" << provider_options + << " with options '" << provider_options_cb() << "': " << e.what(); } catch (...) @@ -49,7 +49,7 @@ std::unique_ptr wsrep::provider::make_provider( wsrep::log_error() << "Caught unknown exception when trying to " << "create a new provider '" << provider_spec << "'" - << " with options '" << provider_options; + << " with options '" << provider_options_cb(); } return 0; } diff --git a/src/server_state.cpp b/src/server_state.cpp index c727dba..d3d19bc 100644 --- a/src/server_state.cpp +++ b/src/server_state.cpp @@ -499,13 +499,14 @@ static int apply_toi(wsrep::provider& provider, ////////////////////////////////////////////////////////////////////////////// int wsrep::server_state::load_provider( - const std::string& provider_spec, const std::string& provider_options, + const std::string& provider_spec, + const std::function& provider_options_cb, const wsrep::provider::services& services) { wsrep::log_info() << "Loading provider " << provider_spec << " initial position: " << initial_position_; provider_ - = provider_factory_(*this, provider_spec, provider_options, services); + = provider_factory_(*this, provider_spec, provider_options_cb, services); return (provider_ ? 0 : 1); } diff --git a/src/wsrep_provider_v26.cpp b/src/wsrep_provider_v26.cpp index 953c615..54898e7 100644 --- a/src/wsrep_provider_v26.cpp +++ b/src/wsrep_provider_v26.cpp @@ -775,8 +775,8 @@ void wsrep::wsrep_provider_v26::deinit_services() wsrep::wsrep_provider_v26::wsrep_provider_v26( wsrep::server_state& server_state, - const std::string& provider_options, const std::string& provider_spec, + const std::function& provider_options_cb, const wsrep::provider::services& services) : provider(server_state) , wsrep_() @@ -796,6 +796,7 @@ wsrep::wsrep_provider_v26::wsrep_provider_v26( init_args.node_address = server_state_.address().c_str(); init_args.node_incoming = server_state_.incoming_address().c_str(); init_args.data_dir = server_state_.working_dir().c_str(); + const auto& provider_options = provider_options_cb(); init_args.options = provider_options.c_str(); init_args.proto_ver = server_state.max_protocol_version(); init_args.state_id = &state_id; diff --git a/src/wsrep_provider_v26.hpp b/src/wsrep_provider_v26.hpp index 53edc20..f7d4457 100644 --- a/src/wsrep_provider_v26.hpp +++ b/src/wsrep_provider_v26.hpp @@ -33,7 +33,7 @@ namespace wsrep void init_services(const wsrep::provider::services& services); void deinit_services(); wsrep_provider_v26(wsrep::server_state&, const std::string&, - const std::string&, + const std::function&, const wsrep::provider::services& services); ~wsrep_provider_v26() WSREP_OVERRIDE; enum wsrep::provider::status diff --git a/test/mock_server_state.hpp b/test/mock_server_state.hpp index c2334ef..a862c21 100644 --- a/test/mock_server_state.hpp +++ b/test/mock_server_state.hpp @@ -262,7 +262,7 @@ namespace wsrep { set_provider_factory([&](wsrep::server_state&, const std::string&, - const std::string&, + const std::function&, const wsrep::provider::services&) { // The provider object is destroyed upon server state