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