Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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/code_environment.h"
21 #include "common/Mutex.h"
22 #include "log/SubsystemMap.h"
23 #include "common/config_obs.h"
24 #include "common/options.h"
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:
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
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
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;
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
105   // Create a new md_config_t structure.
106   md_config_t(bool is_daemon=false);
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.
147   void set_val_or_die(const std::string &key, const std::string &val,
148                       bool meta=true);
149
150   // Set a configuration value.
151   // Metavariables will be expanded.
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);
157   }
158
159   // Get a configuration value.
160   // No metavariables will be returned (they will have already been expanded)
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;
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> &sections) const;
170
171   // Return a list of all sections
172   int get_all_sections(std::vector <std::string> &sections) 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> &sections,
177                    std::string const &key, std::string &out, bool emeta) const;
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
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
194   /// print/log warnings/errors from parsing the config
195   void complain_about_parse_errors(CephContext *cct);
196
197 private:
198   void validate_schema();
199   void validate_default_settings();
200
201   int _get_val(const std::string &key, std::string *value) const;
202   Option::value_t _get_val(const std::string &key) const;
203   void _show_config(std::ostream *out, Formatter *f);
204
205   void _get_my_sections(std::vector <std::string> &sections) const;
206
207   int _get_val_from_conf_file(const std::vector <std::string> &sections,
208                               const std::string &key, std::string &out, bool emeta) const;
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
218   int set_val_impl(const std::string &val, const Option &opt,
219                    std::string *error_message);
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);
227
228   void init_subsys();
229
230   bool expand_meta(std::string &val,
231                    std::ostream *oss) const;
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
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,
245                    const Option *opt,
246                    std::list<const Option*> stack,
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
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) \
286   public:                      \
287     OPTION_##ty(name)          
288 #define SAFE_OPTION(name, ty) \
289   protected:                        \
290     OPTION_##ty(name)               
291 #include "common/legacy_config_opts.h"
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
303 #undef SAFE_OPTION
304
305 public:
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;
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
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);
337   get_typed_value_visitor<T> gtv;
338   return boost::apply_visitor(gtv, generic_val);
339 }
340
341 inline std::ostream& operator<<(std::ostream& o, const boost::blank& ) {
342       return o << "INVALID_CONFIG_VALUE";
343 }
344
345 int ceph_resolve_file_search(const std::string& filename_list,
346                              std::string& result);
347
348 enum config_subsys_id {
349   ceph_subsys_,   // default
350 #define SUBSYS(name, log, gather) \
351   ceph_subsys_##name,
352 #define DEFAULT_SUBSYS(log, gather)
353 #include "common/subsys.h"
354 #undef SUBSYS
355 #undef DEFAULT_SUBSYS
356   ceph_subsys_max
357 };
358
359 #endif