/
config.h
415 lines (355 loc) · 14.2 KB
/
config.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
* Ceph - scalable distributed file system
*
* Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software
* Foundation. See file COPYING.
*
*/
#ifndef CEPH_CONFIG_H
#define CEPH_CONFIG_H
#include "common/ConfUtils.h"
#include "common/entity_name.h"
#include "common/Mutex.h"
#include "log/SubsystemMap.h"
#include "common/config_obs.h"
enum {
CEPH_DEFAULT_CRUSH_REPLICATED_RULESET,
CEPH_DEFAULT_CRUSH_ERASURE_RULESET,
};
#define OSD_REP_PRIMARY 0
#define OSD_REP_SPLAY 1
#define OSD_REP_CHAIN 2
class CephContext;
extern const char *CEPH_CONF_FILE_DEFAULT;
#define LOG_TO_STDERR_NONE 0
#define LOG_TO_STDERR_SOME 1
#define LOG_TO_STDERR_ALL 2
/** This class represents the current Ceph configuration.
*
* For Ceph daemons, this is the daemon configuration. Log levels, caching
* settings, btrfs settings, and so forth can all be found here. For libcephfs
* and librados users, this is the configuration associated with their context.
*
* For information about how this class is loaded from a configuration file,
* see common/ConfUtils.
*
* ACCESS
*
* There are 3 ways to read the ceph context-- the old way and two new ways.
* In the old way, code would simply read the public variables of the
* configuration, without taking a lock. In the new way #1, code registers a
* configuration obserever which receives callbacks when a value changes. These
* callbacks take place under the md_config_t lock. Alternatively one can use
* get_val(const char *name) method to safely get a copy of the value.
*
* To prevent serious problems resulting from thread-safety issues, we disallow
* changing std::string configuration values after
* md_config_t::internal_safe_to_start_threads becomes true. You can still
* change integer or floating point values, and the option declared with
* SAFE_OPTION macro. Notice the latter options can not be read directly
* (conf->foo), one should use either observers or get_val() method
* (conf->get_val("foo")).
*
* FIXME: really we shouldn't allow changing integer or floating point values
* while another thread is reading them, either.
*/
struct md_config_t {
public:
/* Maps configuration options to the observer listening for them. */
typedef std::multimap <std::string, md_config_obs_t*> obs_map_t;
/* Set of configuration options that have changed since the last
* apply_changes */
typedef std::set < std::string > changed_set_t;
struct invalid_config_value_t { };
typedef boost::variant<invalid_config_value_t,
int,
long long,
std::string,
double,
float,
bool,
entity_addr_t,
uint32_t,
uint64_t,
uuid_d> config_value_t;
typedef boost::variant<const int md_config_t::*,
const long long md_config_t::*,
const std::string md_config_t::*,
const double md_config_t::*,
const float md_config_t::*,
const bool md_config_t::*,
const entity_addr_t md_config_t::*,
const uint32_t md_config_t::*,
const uint64_t md_config_t::*,
const uuid_d md_config_t::*> member_ptr_t;
typedef enum {
OPT_INT, OPT_LONGLONG, OPT_STR, OPT_DOUBLE, OPT_FLOAT, OPT_BOOL,
OPT_ADDR, OPT_U32, OPT_U64, OPT_UUID
} opt_type_t;
typedef std::function<int(std::string*, std::string*)> validator_t;
class config_option {
public:
const char *name;
opt_type_t type;
md_config_t::member_ptr_t md_member_ptr;
bool safe; // promise to access it only via md_config_t::get_val
validator_t validator;
private:
template<typename T> struct get_typed_pointer_visitor : public boost::static_visitor<T const *> {
md_config_t const *conf;
explicit get_typed_pointer_visitor(md_config_t const *conf_) : conf(conf_) { }
template<typename U,
typename boost::enable_if<boost::is_same<T, U>, int>::type = 0>
T const *operator()(const U md_config_t::* member_ptr) {
return &(conf->*member_ptr);
}
template<typename U,
typename boost::enable_if_c<!boost::is_same<T, U>::value, int>::type = 0>
T const *operator()(const U md_config_t::* member_ptr) {
return nullptr;
}
};
public:
// is it OK to alter the value when threads are running?
bool is_safe() const;
// Given a configuration, return a pointer to this option inside
// that configuration.
template<typename T> void conf_ptr(T const *&ptr, md_config_t const *conf) const {
get_typed_pointer_visitor<T> gtpv(conf);
ptr = boost::apply_visitor(gtpv, md_member_ptr);
}
template<typename T> void conf_ptr(T *&ptr, md_config_t *conf) const {
get_typed_pointer_visitor<T> gtpv(conf);
ptr = const_cast<T *>(boost::apply_visitor(gtpv, md_member_ptr));
}
template<typename T> T const *conf_ptr(md_config_t const *conf) const {
get_typed_pointer_visitor<T> gtpv(conf);
return boost::apply_visitor(gtpv, md_member_ptr);
}
template<typename T> T *conf_ptr(md_config_t *conf) const {
get_typed_pointer_visitor<T> gtpv(conf);
return const_cast<T *>(boost::apply_visitor(gtpv, md_member_ptr));
}
};
// Create a new md_config_t structure.
md_config_t();
~md_config_t();
// Adds a new observer to this configuration. You can do this at any time,
// but it will only receive notifications for the changes that happen after
// you attach it, obviously.
//
// Most developers will probably attach their observers after global_init,
// but before anyone can call injectargs.
//
// The caller is responsible for allocating observers.
void add_observer(md_config_obs_t* observer_);
// Remove an observer from this configuration.
// This doesn't delete the observer! If you allocated it with new(),
// you need to delete it yourself.
// This function will assert if you try to delete an observer that isn't
// there.
void remove_observer(md_config_obs_t* observer_);
// Parse a config file
int parse_config_files(const char *conf_files,
std::ostream *warnings, int flags);
// Absorb config settings from the environment
void parse_env();
// Absorb config settings from argv
int parse_argv(std::vector<const char*>& args);
// Expand all metavariables. Make any pending observer callbacks.
void apply_changes(std::ostream *oss);
void _apply_changes(std::ostream *oss);
bool _internal_field(const string& k);
void call_all_observers();
// Called by the Ceph daemons to make configuration changes at runtime
int injectargs(const std::string &s, std::ostream *oss);
// Set a configuration value, or crash
// Metavariables will be expanded.
void set_val_or_die(const char *key, const char *val);
// Set a configuration value.
// Metavariables will be expanded.
int set_val(const char *key, const char *val, bool meta=true);
int set_val(const char *key, const string& s, bool meta=true) {
return set_val(key, s.c_str(), meta);
}
// Get a configuration value.
// No metavariables will be returned (they will have already been expanded)
int get_val(const char *key, char **buf, int len) const;
int _get_val(const char *key, char **buf, int len) const;
config_value_t get_val_generic(const char *key) const;
template<typename T> T get_val(const char *key) const;
void get_all_keys(std::vector<std::string> *keys) const;
// Return a list of all the sections that the current entity is a member of.
void get_my_sections(std::vector <std::string> §ions) const;
// Return a list of all sections
int get_all_sections(std::vector <std::string> §ions) const;
// Get a value from the configuration file that we read earlier.
// Metavariables will be expanded if emeta is true.
int get_val_from_conf_file(const std::vector <std::string> §ions,
const char *key, std::string &out, bool emeta) const;
/// dump all config values to a stream
void show_config(std::ostream& out);
/// dump all config values to a formatter
void show_config(Formatter *f);
/// obtain a diff between our config values and another md_config_t values
void diff(const md_config_t *other,
map<string,pair<string,string> > *diff, set<string> *unknown);
/// obtain a diff between config values and another md_config_t
/// values for a specific setting.
void diff(const md_config_t *other,
map<string,pair<string,string>> *diff, set<string> *unknown,
const string& setting);
/// print/log warnings/errors from parsing the config
void complain_about_parse_errors(CephContext *cct);
private:
void validate_default_settings();
int _get_val(const char *key, std::string *value) const;
config_value_t _get_val(const char *key) const;
void _show_config(std::ostream *out, Formatter *f);
void _get_my_sections(std::vector <std::string> §ions) const;
int _get_val_from_conf_file(const std::vector <std::string> §ions,
const char *key, std::string &out, bool emeta) const;
int parse_option(std::vector<const char*>& args,
std::vector<const char*>::iterator& i,
std::ostream *oss);
int parse_injectargs(std::vector<const char*>& args,
std::ostream *oss);
int parse_config_files_impl(const std::list<std::string> &conf_files,
std::ostream *warnings);
int set_val_impl(const std::string &val, config_option const *opt,
std::string *error_message);
int set_val_raw(const char *val, config_option const *opt);
void init_subsys();
bool expand_meta(std::string &val,
std::ostream *oss) const;
void diff_helper(const md_config_t* other,
map<string, pair<string, string>>* diff,
set<string>* unknown, const string& setting = string{});
public: // for global_init
bool early_expand_meta(std::string &val,
std::ostream *oss) const {
Mutex::Locker l(lock);
return expand_meta(val, oss);
}
private:
bool expand_meta(std::string &val,
config_option const *opt,
std::list<config_option const *> stack,
std::ostream *oss) const;
/// expand all metavariables in config structure.
void expand_all_meta();
// The configuration file we read, or NULL if we haven't read one.
ConfFile cf;
public:
std::deque<std::string> parse_errors;
private:
obs_map_t observers;
changed_set_t changed;
public:
ceph::logging::SubsystemMap subsys;
EntityName name;
string data_dir_option; ///< data_dir config option, if any
/// cluster name
string cluster;
#define OPTION_OPT_INT(name) const int name;
#define OPTION_OPT_LONGLONG(name) const long long name;
#define OPTION_OPT_STR(name) const std::string name;
#define OPTION_OPT_DOUBLE(name) const double name;
#define OPTION_OPT_FLOAT(name) const float name;
#define OPTION_OPT_BOOL(name) const bool name;
#define OPTION_OPT_ADDR(name) const entity_addr_t name;
#define OPTION_OPT_U32(name) const uint32_t name;
#define OPTION_OPT_U64(name) const uint64_t name;
#define OPTION_OPT_UUID(name) const uuid_d name;
#define OPTION(name, ty, init) \
public: \
OPTION_##ty(name) \
struct option_##name##_t;
#define OPTION_VALIDATOR(name)
#define SAFE_OPTION(name, ty, init) \
protected: \
OPTION_##ty(name) \
public: \
struct option_##name##_t;
#define SUBSYS(name, log, gather)
#define DEFAULT_SUBSYS(log, gather)
#include "common/config_opts.h"
#undef OPTION_OPT_INT
#undef OPTION_OPT_LONGLONG
#undef OPTION_OPT_STR
#undef OPTION_OPT_DOUBLE
#undef OPTION_OPT_FLOAT
#undef OPTION_OPT_BOOL
#undef OPTION_OPT_ADDR
#undef OPTION_OPT_U32
#undef OPTION_OPT_U64
#undef OPTION_OPT_UUID
#undef OPTION
#undef OPTION_VALIDATOR
#undef SAFE_OPTION
#undef SUBSYS
#undef DEFAULT_SUBSYS
unsigned get_osd_pool_default_min_size() const {
return osd_pool_default_min_size ?
MIN(osd_pool_default_min_size, osd_pool_default_size) :
osd_pool_default_size - osd_pool_default_size / 2;
}
/** A lock that protects the md_config_t internals. It is
* recursive, for simplicity.
* It is best if this lock comes first in the lock hierarchy. We will
* hold this lock when calling configuration observers. */
mutable Mutex lock;
friend class test_md_config_t;
protected:
// Tests and possibly users expect options to appear in the output
// of ceph-conf in the same order as declared in config_opts.h
std::shared_ptr<const std::vector<config_option>> config_options;
config_option const *find_config_option(const std::string& normalized_key) const;
};
template<typename T>
struct get_typed_value_visitor : public boost::static_visitor<T> {
template<typename U,
typename boost::enable_if<boost::is_same<T, U>, int>::type = 0>
T operator()(U & val) {
return std::move(val);
}
template<typename U,
typename boost::enable_if_c<!boost::is_same<T, U>::value, int>::type = 0>
T operator()(U &val) {
assert("wrong type or option does not exist" == nullptr);
}
};
template<typename T> T md_config_t::get_val(const char *key) const {
config_value_t generic_val = this->get_val_generic(key);
get_typed_value_visitor<T> gtv;
return boost::apply_visitor(gtv, generic_val);
}
inline std::ostream& operator<<(std::ostream& o, const md_config_t::invalid_config_value_t& ) {
return o << "INVALID_CONFIG_VALUE";
}
int ceph_resolve_file_search(const std::string& filename_list,
std::string& result);
typedef md_config_t::config_option config_option;
enum config_subsys_id {
ceph_subsys_, // default
#define OPTION(a,b,c)
#define OPTION_VALIDATOR(name)
#define SAFE_OPTION(a,b,c)
#define SUBSYS(name, log, gather) \
ceph_subsys_##name,
#define DEFAULT_SUBSYS(log, gather)
#include "common/config_opts.h"
#undef SUBSYS
#undef OPTION
#undef OPTION_VALIDATOR
#undef SAFE_OPTION
#undef DEFAULT_SUBSYS
ceph_subsys_max
};
#endif