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 <map>
19 #include <boost/container/small_vector.hpp>
20 #include "common/ConfUtils.h"
21 #include "common/code_environment.h"
22 #include "log/SubsystemMap.h"
23 #include "common/options.h"
24 #include "common/subsys_types.h"
25 #include "common/config_tracker.h"
26 #include "common/config_values.h"
27
28 class CephContext;
29
30 enum {
31 CONF_DEFAULT,
32 CONF_MON,
33 CONF_FILE,
34 CONF_ENV,
35 CONF_CMDLINE,
36 CONF_OVERRIDE,
37 CONF_FINAL
38 };
39
40 extern const char *ceph_conf_level_name(int level);
41
42 /** This class represents the current Ceph configuration.
43 *
44 * For Ceph daemons, this is the daemon configuration. Log levels, caching
45 * settings, btrfs settings, and so forth can all be found here. For libcephfs
46 * and librados users, this is the configuration associated with their context.
47 *
48 * For information about how this class is loaded from a configuration file,
49 * see common/ConfUtils.
50 *
51 * ACCESS
52 *
53 * There are 3 ways to read the ceph context-- the old way and two new ways.
54 * In the old way, code would simply read the public variables of the
55 * configuration, without taking a lock. In the new way #1, code registers a
56 * configuration observer which receives callbacks when a value changes. These
57 * callbacks take place under the md_config_t lock. Alternatively one can use
58 * get_val(const char *name) method to safely get a copy of the value.
59 *
60 * To prevent serious problems resulting from thread-safety issues, we disallow
61 * changing std::string configuration values after
62 * md_config_t::safe_to_start_threads becomes true. You can still
63 * change integer or floating point values, and the option declared with
64 * SAFE_OPTION macro. Notice the latter options can not be read directly
65 * (conf->foo), one should use either observers or get_val() method
66 * (conf->get_val("foo")).
67 *
68 * FIXME: really we shouldn't allow changing integer or floating point values
69 * while another thread is reading them, either.
70 */
71 struct md_config_t {
72 public:
73 typedef boost::variant<int64_t ConfigValues::*,
74 uint64_t ConfigValues::*,
75 std::string ConfigValues::*,
76 double ConfigValues::*,
77 bool ConfigValues::*,
78 entity_addr_t ConfigValues::*,
79 entity_addrvec_t ConfigValues::*,
80 uuid_d ConfigValues::*> member_ptr_t;
81
82 // For use when intercepting configuration updates
83 typedef std::function<bool(
84 const std::string &k, const std::string &v)> config_callback;
85
86 /// true if we are a daemon (as per CephContext::code_env)
87 const bool is_daemon;
88
89 /*
90 * Mapping from legacy config option names to class members
91 */
92 std::map<std::string_view, member_ptr_t> legacy_values;
93
94 /**
95 * The configuration schema, in the form of Option objects describing
96 * possible settings.
97 */
98 std::map<std::string_view, const Option&> schema;
99
100 /// values from mon that we failed to set
101 std::map<std::string,std::string> ignored_mon_values;
102
103 /// original raw values saved that may need to re-expand at certain time
104 mutable std::map<std::string, std::string> may_reexpand_meta;
105
106 /// encoded, cached copy of of values + ignored_mon_values
107 ceph::bufferlist values_bl;
108
109 /// version for values_bl; increments each time there is a change
110 uint64_t values_bl_version = 0;
111
112 /// encoded copy of defaults (map<string,string>)
113 ceph::bufferlist defaults_bl;
114
115 // Create a new md_config_t structure.
116 explicit md_config_t(ConfigValues& values,
117 const ConfigTracker& tracker,
118 bool is_daemon=false);
119 ~md_config_t();
120
121 // Parse a config file
122 int parse_config_files(ConfigValues& values, const ConfigTracker& tracker,
123 const char *conf_files,
124 std::ostream *warnings, int flags);
125
126 // Absorb config settings from the environment
127 void parse_env(unsigned entity_type,
128 ConfigValues& values, const ConfigTracker& tracker,
129 const char *env_var = "CEPH_ARGS");
130
131 // Absorb config settings from argv
132 int parse_argv(ConfigValues& values, const ConfigTracker& tracker,
133 std::vector<const char*>& args, int level=CONF_CMDLINE);
134
135 // do any commands we got from argv (--show-config, --show-config-val)
136 void do_argv_commands(const ConfigValues& values) const;
137
138 bool _internal_field(const std::string& k);
139
140 void set_safe_to_start_threads();
141 void _clear_safe_to_start_threads(); // this is only used by the unit test
142
143 /// Look up an option in the schema
144 const Option *find_option(const std::string_view name) const;
145
146 /// Set a default value
147 void set_val_default(ConfigValues& values,
148 const ConfigTracker& tracker,
149 const std::string_view key, const std::string &val);
150
151 /// Set a values from mon
152 int set_mon_vals(CephContext *cct,
153 ConfigValues& values,
154 const ConfigTracker& tracker,
155 const std::map<std::string,std::string, std::less<>>& kv,
156 config_callback config_cb);
157
158 // Called by the Ceph daemons to make configuration changes at runtime
159 int injectargs(ConfigValues& values,
160 const ConfigTracker& tracker,
161 const std::string &s,
162 std::ostream *oss);
163
164 // Set a configuration value, or crash
165 // Metavariables will be expanded.
166 void set_val_or_die(ConfigValues& values, const ConfigTracker& tracker,
167 const std::string_view key, const std::string &val);
168
169 // Set a configuration value.
170 // Metavariables will be expanded.
171 int set_val(ConfigValues& values, const ConfigTracker& tracker,
172 const std::string_view key, const char *val,
173 std::stringstream *err_ss=nullptr);
174 int set_val(ConfigValues& values, const ConfigTracker& tracker,
175 const std::string_view key, const std::string& s,
176 std::stringstream *err_ss=nullptr) {
(1) Event fun_call_w_exception: |
Called function throws an exception of type "boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_get> >". [details] |
177 return set_val(values, tracker, key, s.c_str(), err_ss);
178 }
179
180 /// clear override value
181 int rm_val(ConfigValues& values, const std::string_view key);
182
183 /// get encoded map<string,map<int32_t,string>> of entire config
184 void get_config_bl(const ConfigValues& values,
185 uint64_t have_version,
186 ceph::buffer::list *bl,
187 uint64_t *got_version);
188
189 /// get encoded map<string,string> of compiled-in defaults
190 void get_defaults_bl(const ConfigValues& values, ceph::buffer::list *bl);
191
192 // Get a configuration value.
193 // No metavariables will be returned (they will have already been expanded)
194 int get_val(const ConfigValues& values, const std::string_view key, char **buf, int len) const;
195 int get_val(const ConfigValues& values, const std::string_view key, std::string *val) const;
196 template<typename T> const T get_val(const ConfigValues& values, const std::string_view key) const;
197 template<typename T, typename Callback, typename...Args>
198 auto with_val(const ConfigValues& values, const std::string_view key,
199 Callback&& cb, Args&&... args) const ->
200 std::result_of_t<Callback(const T&, Args...)> {
201 return std::forward<Callback>(cb)(
202 boost::get<T>(this->get_val_generic(values, key)),
203 std::forward<Args>(args)...);
204 }
205
206 void get_all_keys(std::vector<std::string> *keys) const;
207
208 // Return a list of all the sections that the current entity is a member of.
209 void get_my_sections(const ConfigValues& values,
210 std::vector <std::string> §ions) const;
211
212 // Return a list of all sections
213 int get_all_sections(std::vector <std::string> §ions) 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 ConfigValues& values,
218 const std::vector <std::string> §ions,
219 const std::string_view key, std::string &out, bool emeta) const;
220
221 /// dump all config values to a stream
222 void show_config(const ConfigValues& values, std::ostream& out) const;
223 /// dump all config values to a formatter
224 void show_config(const ConfigValues& values, ceph::Formatter *f) const;
225
226 /// dump all config settings to a formatter
227 void config_options(ceph::Formatter *f) const;
228
229 /// dump config diff from default, conf, mon, etc.
230 void diff(const ConfigValues& values,
231 ceph::Formatter *f,
232 std::string name = {}) const;
233
234 /// print/log warnings/errors from parsing the config
235 void complain_about_parse_error(CephContext *cct);
236
237 private:
238 // we use this to avoid variable expansion loops
239 typedef boost::container::small_vector<std::pair<const Option*,
240 const Option::value_t*>,
241 4> expand_stack_t;
242
243 void validate_schema();
244 void validate_default_settings();
245
246 Option::value_t get_val_generic(const ConfigValues& values,
247 const std::string_view key) const;
248 int _get_val_cstr(const ConfigValues& values,
249 const std::string& key, char **buf, int len) const;
250 Option::value_t _get_val(const ConfigValues& values,
251 const std::string_view key,
252 expand_stack_t *stack=0,
253 std::ostream *err=0) const;
254 Option::value_t _get_val(const ConfigValues& values,
255 const Option& o,
256 expand_stack_t *stack=0,
257 std::ostream *err=0) const;
258 const Option::value_t& _get_val_default(const Option& o) const;
259 Option::value_t _get_val_nometa(const ConfigValues& values,
260 const Option& o) const;
261
262 int _rm_val(ConfigValues& values, const std::string_view key, int level);
263
264 void _refresh(ConfigValues& values, const Option& opt);
265
266 void _show_config(const ConfigValues& values,
267 std::ostream *out, ceph::Formatter *f) const;
268
269 void _get_my_sections(const ConfigValues& values,
270 std::vector<std::string> §ions) const;
271
272 int _get_val_from_conf_file(const std::vector<std::string> §ions,
273 const std::string_view key, std::string &out) const;
274
275 int parse_option(ConfigValues& values,
276 const ConfigTracker& tracker,
277 std::vector<const char*>& args,
278 std::vector<const char*>::iterator& i,
279 std::ostream *oss,
280 int level);
281 int parse_injectargs(ConfigValues& values,
282 const ConfigTracker& tracker,
283 std::vector<const char*>& args,
284 std::ostream *oss);
285
286 // @returns negative number for an error, otherwise a
287 // @c ConfigValues::set_value_result_t is returned.
288 int _set_val(
289 ConfigValues& values,
290 const ConfigTracker& tracker,
291 const std::string &val,
292 const Option &opt,
293 int level, // CONF_*
294 std::string *error_message);
295
296 template <typename T>
297 void assign_member(member_ptr_t ptr, const Option::value_t &val);
298
299
300 void update_legacy_vals(ConfigValues& values);
301 void update_legacy_val(ConfigValues& values,
302 const Option &opt,
303 member_ptr_t member);
304
305 Option::value_t _expand_meta(
306 const ConfigValues& values,
307 const Option::value_t& in,
308 const Option *o,
309 expand_stack_t *stack,
310 std::ostream *err) const;
311
312 public: // for global_init
313 void early_expand_meta(const ConfigValues& values,
314 std::string &val,
315 std::ostream *oss) const;
316
317 // for those want to reexpand special meta, e.g, $pid
318 bool finalize_reexpand_meta(ConfigValues& values,
319 const ConfigTracker& tracker);
320 private:
321
322 /// expand all metavariables in config structure.
323 void expand_all_meta();
324
325 // The configuration file we read, or NULL if we haven't read one.
326 ConfFile cf;
327 public:
328 std::string parse_error;
329 private:
330
331 // This will be set to true when it is safe to start threads.
332 // Once it is true, it will never change.
333 bool safe_to_start_threads = false;
334
335 bool do_show_config = false;
336 std::string do_show_config_value;
337
338 std::vector<Option> subsys_options;
339
340 public:
341 std::string data_dir_option; ///< data_dir config option, if any
342
343 public:
344 unsigned get_osd_pool_default_min_size(const ConfigValues& values,
345 uint8_t size) const {
346 uint8_t min_size = get_val<uint64_t>(values, "osd_pool_default_min_size");
347 return min_size ? std::min(min_size, size) : (size - size / 2);
348 }
349
350 friend class test_md_config_t;
351 };
352
353 template<typename T>
354 const T md_config_t::get_val(const ConfigValues& values,
355 const std::string_view key) const {
356 return boost::get<T>(this->get_val_generic(values, key));
357 }
358
359 inline std::ostream& operator<<(std::ostream& o, const boost::blank& ) {
360 return o << "INVALID_CONFIG_VALUE";
361 }
362
363 int ceph_resolve_file_search(const std::string& filename_list,
364 std::string& result);
365
366 #endif
367