Skip to content

Commit 3965d83

Browse files
author
Daniele Sciascia
committed
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. This way it is possible get options which are given at DBMS startup, in command line or config file.
1 parent 2dc8339 commit 3965d83

File tree

12 files changed

+193
-54
lines changed

12 files changed

+193
-54
lines changed

include/wsrep/provider.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
#include <cstring>
3131

32+
#include <functional>
3233
#include <memory>
3334
#include <string>
3435
#include <vector>
@@ -50,6 +51,7 @@ namespace wsrep
5051
class event_service;
5152
class client_service;
5253
class connection_monitor_service;
54+
class provider_options;
5355
class stid
5456
{
5557
public:
@@ -521,13 +523,13 @@ namespace wsrep
521523
* Create a new provider.
522524
*
523525
* @param provider_spec Provider specification
524-
* @param provider_options Initial options to provider
526+
* @param provider_options_cb Callback to get initial provider options
525527
* @param thread_service Optional thread service implementation.
526528
*/
527529
static std::unique_ptr<provider> make_provider(
528-
wsrep::server_state&,
529-
const std::string& provider_spec,
530-
const std::string& provider_options,
530+
wsrep::server_state&, const std::string& provider_spec,
531+
const std::function<int(const provider_options&, std::string&)>&
532+
provider_options_cb,
531533
const wsrep::provider::services& services
532534
= wsrep::provider::services());
533535

include/wsrep/provider_options.hpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ namespace wsrep
214214
int flags_;
215215
};
216216

217-
provider_options(wsrep::provider&);
217+
provider_options();
218218
provider_options(const provider_options&) = delete;
219219
provider_options& operator=(const provider_options&) = delete;
220220

@@ -225,7 +225,7 @@ namespace wsrep
225225
*
226226
* @return Provider status code.
227227
*/
228-
enum wsrep::provider::status initial_options();
228+
enum wsrep::provider::status initial_options(wsrep::provider& provider);
229229

230230
/**
231231
* Get the option with the given name
@@ -241,7 +241,8 @@ namespace wsrep
241241
* @return wsrep::provider::error_size_exceeded if memory could
242242
* not be allocated for the new value.
243243
*/
244-
enum wsrep::provider::status set(const std::string& name,
244+
enum wsrep::provider::status set(wsrep::provider& provider,
245+
const std::string& name,
245246
std::unique_ptr<option_value> value);
246247

247248
/**
@@ -252,10 +253,15 @@ namespace wsrep
252253
std::unique_ptr<option_value> value,
253254
std::unique_ptr<option_value> default_value, int flags);
254255

255-
void for_each(const std::function<void(option*)>& fn);
256+
/**
257+
* Invoke the given function with each provider option
258+
* as argument.
259+
*
260+
* @param fn Function to call for each option
261+
*/
262+
void for_each(const std::function<void(option*)>& fn) const;
256263

257264
private:
258-
provider& provider_;
259265
using options_map = std::map<std::string, std::unique_ptr<option>>;
260266
options_map options_;
261267
};

include/wsrep/server_state.hpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ namespace wsrep
117117
class server_service;
118118
class client_service;
119119
class encryption_service;
120+
class provider_options;
120121

121122
/** @class Server Context
122123
*
@@ -287,17 +288,47 @@ namespace wsrep
287288
* Load WSRep provider.
288289
*
289290
* @param provider WSRep provider library to be loaded.
290-
* @param provider_options Provider specific options string
291+
* @param provider_options_cb Callback to get provider options.
292+
* The function to be called must be
293+
* idempotent.
294+
* @param services Application defined services passed to
295+
* the provider.
296+
*
297+
* @return Zero on success, non-zero on error.
298+
*/
299+
int load_provider(
300+
const std::string& provider,
301+
const std::function<int(const provider_options&, std::string&)>&
302+
provider_options_cb,
303+
const wsrep::provider::services& services
304+
= wsrep::provider::services());
305+
306+
/**
307+
* Load WSRep provider.
308+
*
309+
* @param provider WSRep provider library to be loaded.
310+
* @param options Provider specific options string
291311
* to be passed for provider during initialization.
292312
* @param services Application defined services passed to
293313
* the provider.
294314
*
295315
* @return Zero on success, non-zero on error.
316+
*
317+
* @note Provided for backward compatibility.
296318
*/
297319
int load_provider(const std::string& provider,
298-
const std::string& provider_options,
320+
const std::string& options,
299321
const wsrep::provider::services& services
300-
= wsrep::provider::services());
322+
= wsrep::provider::services())
323+
{
324+
return load_provider(
325+
provider,
326+
[options](const provider_options&, std::string& option_string) {
327+
option_string.append(options);
328+
return 0;
329+
},
330+
services);
331+
}
301332

302333
using provider_factory_func =
303334
std::function<decltype(wsrep::provider::make_provider)>;

src/config_service_v1.cpp

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "config_service_v1.hpp"
2121
#include "service_helpers.hpp"
22+
#include "v26/wsrep_api.h"
2223
#include "v26/wsrep_config_service.h"
2324
#include "wsrep/logger.hpp"
2425
#include "wsrep/provider_options.hpp"
@@ -150,7 +151,7 @@ static void config_service_v1_deinit(void* dlh)
150151
int wsrep::config_service_v1_fetch(wsrep::provider& provider,
151152
wsrep::provider_options* options)
152153
{
153-
struct wsrep_st* wsrep = (struct wsrep_st*)provider.native();
154+
struct wsrep_st* wsrep = static_cast<struct wsrep_st*>(provider.native());
154155
if (wsrep == nullptr)
155156
{
156157
// Not a provider which was loaded via wsrep-API
@@ -179,3 +180,70 @@ int wsrep::config_service_v1_fetch(wsrep::provider& provider,
179180

180181
return 0;
181182
}
183+
184+
namespace wsrep_config_service_v2
185+
{
186+
wsrep_config_service_v2_t service{ 0 };
187+
188+
wsrep_status_t service_callback(const wsrep_parameter* p, void* context)
189+
{
190+
return wsrep_config_service_v1::service_callback(p, context);
191+
}
192+
} // namespace wsrep_config_service_v2
193+
194+
static int config_service_v2_probe(void* dlh)
195+
{
196+
typedef int (*init_fn)(wsrep_config_service_v2_t*);
197+
typedef void (*deinit_fn)();
198+
return wsrep_impl::service_probe<init_fn>(
199+
dlh, WSREP_CONFIG_SERVICE_INIT_FUNC_V2, "config service v2")
200+
|| wsrep_impl::service_probe<deinit_fn>(
201+
dlh, WSREP_CONFIG_SERVICE_DEINIT_FUNC_V2, "config service v2");
202+
}
203+
204+
static int config_service_v2_init(void* dlh)
205+
{
206+
typedef int (*init_fn)(wsrep_config_service_v2_t*);
207+
return wsrep_impl::service_init<init_fn>(
208+
dlh, WSREP_CONFIG_SERVICE_INIT_FUNC_V2,
209+
&wsrep_config_service_v2::service, "config service v2");
210+
}
211+
212+
static void config_service_v2_deinit(void* dlh)
213+
{
214+
typedef int (*deinit_fn)();
215+
wsrep_impl::service_deinit<deinit_fn>(
216+
dlh, WSREP_CONFIG_SERVICE_DEINIT_FUNC_V2, "config service v2");
217+
}
218+
219+
int wsrep::config_service_v2_fetch(struct wsrep_st* wsrep,
220+
wsrep::provider_options* options)
221+
{
222+
if (wsrep == nullptr)
223+
{
224+
// Not a provider which was loaded via wsrep-API
225+
return 0;
226+
}
227+
if (config_service_v2_probe(wsrep->dlh))
228+
{
229+
wsrep::log_info() << "Provider does not support config service v2";
230+
return 1;
231+
}
232+
if (config_service_v2_init(wsrep->dlh))
233+
{
234+
wsrep::log_warning() << "Failed to initialize config service v2";
235+
return 1;
236+
}
237+
238+
wsrep_status_t ret = wsrep_config_service_v2::service.get_parameters(
239+
wsrep, &wsrep_config_service_v2::service_callback, options);
240+
241+
config_service_v2_deinit(wsrep->dlh);
242+
243+
if (ret != WSREP_OK)
244+
{
245+
return 1;
246+
}
247+
248+
return 0;
249+
}

src/config_service_v1.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,15 @@
2020
#ifndef WSREP_CONFIG_SERVICE_V1_HPP
2121
#define WSREP_CONFIG_SERVICE_V1_HPP
2222

23+
struct wsrep_st;
24+
2325
namespace wsrep
2426
{
2527
class provider;
2628
class provider_options;
2729
int config_service_v1_fetch(provider& provider, provider_options* opts);
30+
int config_service_v1_fetch(struct wsrep_st* wsrep, provider_options* opts);
31+
int config_service_v2_fetch(struct wsrep_st* wsrep, provider_options* opts);
2832
} // namespace wsrep
2933

3034
#endif // WSREP_CONFIG_SERVICE_V1_HPP

src/provider.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "wsrep/provider.hpp"
2121
#include "wsrep/logger.hpp"
22+
#include "wsrep/provider_options.hpp"
2223

2324
#include "wsrep_provider_v26.hpp"
2425

@@ -27,29 +28,36 @@
2728
#include <memory>
2829

2930
std::unique_ptr<wsrep::provider> wsrep::provider::make_provider(
30-
wsrep::server_state& server_state,
31-
const std::string& provider_spec,
32-
const std::string& provider_options,
31+
wsrep::server_state& server_state, const std::string& provider_spec,
32+
const std::function<int(const provider_options&, std::string&)>&
33+
provider_options_cb,
3334
const wsrep::provider::services& services)
3435
{
3536
try
3637
{
3738
return std::unique_ptr<wsrep::provider>(new wsrep::wsrep_provider_v26(
38-
server_state, provider_options, provider_spec, services));
39+
server_state, provider_spec, provider_options_cb,
40+
services));
3941
}
4042
catch (const wsrep::runtime_error& e)
4143
{
44+
provider_options options;
45+
std::string options_string;
4246
wsrep::log_error() << "Failed to create a new provider '"
4347
<< provider_spec << "'"
44-
<< " with options '" << provider_options
48+
<< " with options '"
49+
<< provider_options_cb(options, options_string)
4550
<< "': " << e.what();
4651
}
4752
catch (...)
4853
{
54+
provider_options options;
55+
std::string options_string;
4956
wsrep::log_error() << "Caught unknown exception when trying to "
5057
<< "create a new provider '"
5158
<< provider_spec << "'"
52-
<< " with options '" << provider_options;
59+
<< " with options '"
60+
<< provider_options_cb(options, options_string);
5361
}
5462
return 0;
5563
}

src/provider_options.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919

2020
#include "wsrep/provider_options.hpp"
21+
#include "wsrep/provider.hpp"
2122
#include "config_service_v1.hpp"
2223
#include "wsrep/logger.hpp"
2324

@@ -92,16 +93,16 @@ void wsrep::provider_options::option::update_value(
9293

9394
wsrep::provider_options::option::~option() {}
9495

95-
wsrep::provider_options::provider_options(wsrep::provider& provider)
96-
: provider_(provider)
97-
, options_()
96+
wsrep::provider_options::provider_options()
97+
: options_()
9898
{
9999
}
100100

101-
enum wsrep::provider::status wsrep::provider_options::initial_options()
101+
enum wsrep::provider::status
102+
wsrep::provider_options::initial_options(wsrep::provider& provider)
102103
{
103104
options_.clear();
104-
if (config_service_v1_fetch(provider_, this))
105+
if (config_service_v1_fetch(provider, this))
105106
{
106107
return wsrep::provider::error_not_implemented;
107108
}
@@ -123,7 +124,7 @@ wsrep::provider_options::get_option(const std::string& name) const
123124
}
124125

125126
enum wsrep::provider::status wsrep::provider_options::set(
126-
const std::string& name,
127+
wsrep::provider& provider, const std::string& name,
127128
std::unique_ptr<wsrep::provider_options::option_value> value)
128129
{
129130
auto option(options_.find(name));
@@ -132,7 +133,7 @@ enum wsrep::provider::status wsrep::provider_options::set(
132133
return not_found_error;
133134
}
134135
provider_options_sep sep;
135-
auto ret(provider_.options(std::string(option->second->real_name())
136+
auto ret(provider.options(std::string(option->second->real_name())
136137
+ sep.key_value + value->as_string()
137138
+ sep.param));
138139
if (ret == provider::success)
@@ -160,9 +161,10 @@ enum wsrep::provider::status wsrep::provider_options::set_default(
160161
return wsrep::provider::success;
161162
}
162163

163-
void wsrep::provider_options::for_each(const std::function<void(option*)>& fn)
164+
void wsrep::provider_options::for_each(
165+
const std::function<void(option*)>& fn) const
164166
{
165-
std::for_each(
166-
options_.begin(), options_.end(),
167-
[&fn](const options_map::value_type& opt) { fn(opt.second.get()); });
167+
std::for_each(options_.begin(), options_.end(),
168+
[&fn](const options_map::value_type& opt)
169+
{ fn(opt.second.get()); });
168170
}

src/server_state.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,13 +499,15 @@ static int apply_toi(wsrep::provider& provider,
499499
//////////////////////////////////////////////////////////////////////////////
500500

501501
int wsrep::server_state::load_provider(
502-
const std::string& provider_spec, const std::string& provider_options,
502+
const std::string& provider_spec,
503+
const std::function<int(const provider_options&, std::string&)>&
504+
provider_options_cb,
503505
const wsrep::provider::services& services)
504506
{
505507
wsrep::log_info() << "Loading provider " << provider_spec
506508
<< " initial position: " << initial_position_;
507-
provider_
508-
= provider_factory_(*this, provider_spec, provider_options, services);
509+
provider_ = provider_factory_(*this, provider_spec, provider_options_cb,
510+
services);
509511
return (provider_ ? 0 : 1);
510512
}
511513

0 commit comments

Comments
 (0)