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