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