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) 2011 New Dream Network
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_CEPHCONTEXT_H
16   	#define CEPH_CEPHCONTEXT_H
17   	
18   	#include <atomic>
19   	#include <map>
20   	#include <memory>
21   	#include <mutex>
22   	#include <set>
23   	#include <string>
24   	#include <string_view>
25   	#include <typeinfo>
26   	#include <typeindex>
27   	
28   	#include "include/any.h"
29   	
30   	#include "common/cmdparse.h"
31   	#include "common/code_environment.h"
32   	#ifdef WITH_SEASTAR
33   	#include "crimson/common/config_proxy.h"
34   	#include "crimson/common/perf_counters_collection.h"
35   	#else
36   	#include "common/config_proxy.h"
37   	#include "include/spinlock.h"
38   	#include "common/perf_counters_collection.h"
39   	#endif
40   	
41   	
42   	#include "crush/CrushLocation.h"
43   	
44   	class AdminSocket;
45   	class CephContextServiceThread;
46   	class CephContextHook;
47   	class CephContextObs;
48   	class CryptoHandler;
49   	class CryptoRandom;
50   	
51   	namespace ceph {
52   	  class PluginRegistry;
53   	  class HeartbeatMap;
54   	  namespace logging {
55   	    class Log;
56   	  }
57   	}
58   	
59   	#ifdef WITH_SEASTAR
60   	class CephContext {
61   	public:
62   	  CephContext();
63   	  CephContext(uint32_t,
64   		      code_environment_t=CODE_ENVIRONMENT_UTILITY,
65   		      int = 0)
66   	    : CephContext{}
67   	  {}
68   	  CephContext(CephContext&&) = default;
69   	  ~CephContext();
70   	
71   	  uint32_t get_module_type() const;
72   	  bool check_experimental_feature_enabled(const std::string& feature) {
73   	    // everything crimson is experimental...
74   	    return true;
75   	  }
76   	  CryptoRandom* random() const;
77   	  PerfCountersCollectionImpl* get_perfcounters_collection();
78   	  ceph::common::ConfigProxy& _conf;
79   	  ceph::common::PerfCountersCollection& _perf_counters_collection;
80   	  CephContext* get();
81   	  void put();
82   	private:
83   	  std::unique_ptr<CryptoRandom> _crypto_random;
84   	  unsigned nref;
85   	};
86   	#else
87   	/* A CephContext represents the context held by a single library user.
88   	 * There can be multiple CephContexts in the same process.
89   	 *
90   	 * For daemons and utility programs, there will be only one CephContext.  The
91   	 * CephContext contains the configuration, the dout object, and anything else
92   	 * that you might want to pass to libcommon with every function call.
93   	 */
94   	class CephContext {
95   	public:
96   	  CephContext(uint32_t module_type_,
97   	              enum code_environment_t code_env=CODE_ENVIRONMENT_UTILITY,
98   	              int init_flags_ = 0);
99   	
100  	  CephContext(const CephContext&) = delete;
101  	  CephContext& operator =(const CephContext&) = delete;
102  	  CephContext(CephContext&&) = delete;
103  	  CephContext& operator =(CephContext&&) = delete;
104  	
105  	  bool _finished = false;
106  	
107  	  // ref count!
108  	private:
109  	  ~CephContext();
110  	  std::atomic<unsigned> nref;
111  	public:
112  	  CephContext *get() {
113  	    ++nref;
114  	    return this;
115  	  }
116  	  void put();
117  	
118  	  ConfigProxy _conf;
119  	  ceph::logging::Log *_log;
120  	
121  	  /* init ceph::crypto */
122  	  void init_crypto();
123  	
124  	  /// shutdown crypto (should match init_crypto calls)
125  	  void shutdown_crypto();
126  	
127  	  /* Start the Ceph Context's service thread */
128  	  void start_service_thread();
129  	
130  	  /* Reopen the log files */
131  	  void reopen_logs();
132  	
133  	  /* Get the module type (client, mon, osd, mds, etc.) */
134  	  uint32_t get_module_type() const;
135  	
136  	  // this is here only for testing purposes!
137  	  void _set_module_type(uint32_t t) {
138  	    _module_type = t;
139  	  }
140  	
141  	  void set_init_flags(int flags);
142  	  int get_init_flags() const;
143  	
144  	  /* Get the PerfCountersCollection of this CephContext */
145  	  PerfCountersCollection *get_perfcounters_collection();
146  	
147  	  ceph::HeartbeatMap *get_heartbeat_map() {
148  	    return _heartbeat_map;
149  	  }
150  	
151  	  /**
152  	   * Get the admin socket associated with this CephContext.
153  	   *
154  	   * Currently there is always an admin socket object,
155  	   * so this will never return NULL.
156  	   *
157  	   * @return the admin socket
158  	   */
159  	  AdminSocket *get_admin_socket();
160  	
161  	  /**
162  	   * process an admin socket command
163  	   */
164  	  int do_command(std::string_view command, const cmdmap_t& cmdmap,
165  			 Formatter *f,
166  			 std::ostream& errss,
167  			 ceph::bufferlist *out);
168  	  int _do_command(std::string_view command, const cmdmap_t& cmdmap,
169  			  Formatter *f,
170  			  std::ostream& errss,
171  			  ceph::bufferlist *out);
172  	
173  	  static constexpr std::size_t largest_singleton = 8 * 72;
174  	
175  	  template<typename T, typename... Args>
176  	  T& lookup_or_create_singleton_object(std::string_view name,
177  					       bool drop_on_fork,
178  					       Args&&... args) {
179  	    static_assert(sizeof(T) <= largest_singleton,
180  			  "Please increase largest singleton.");
181  	    std::lock_guard lg(associated_objs_lock);
182  	    std::type_index type = typeid(T);
183  	
184  	    auto i = associated_objs.find(std::make_pair(name, type));
185  	    if (i == associated_objs.cend()) {
186  	      if (drop_on_fork) {
187  		associated_objs_drop_on_fork.insert(std::string(name));
188  	      }
189  	      i = associated_objs.emplace_hint(
190  		i,
191  		std::piecewise_construct,
192  		std::forward_as_tuple(name, type),
193  		std::forward_as_tuple(std::in_place_type<T>,
(13) Event template_instantiation_context: instantiation of "std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::emplace_hint(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, _Args &&...) [with _Key=std::pair<std::string, std::type_index>, _Tp=ceph::immobile_any<576UL>, _Compare=CephContext::associated_objs_cmp, _Alloc=std::allocator<std::pair<const std::pair<std::string, std::type_index>, ceph::immobile_any<576UL>>>, _Args=<const std::piecewise_construct_t &, std::tuple<std::string_view &, std::type_index &>, std::tuple<const std::in_place_type_t<<unnamed>::MempoolObs> &, CephContext *&&>>]" at line 194 of "/ceph/src/common/ceph_context.h"
Also see events: [no_matching_constructor][caretline][argument_list_types_add_on][compiler_generated_function_context][template_instantiation_context][template_instantiation_context][template_instantiation_context][template_instantiation_context][template_instantiation_context][template_instantiation_context][template_instantiation_context][template_instantiation_context][template_instantiation_context]
194  				      std::forward<Args>(args)...));
195  	    }
196  	    return ceph::any_cast<T&>(i->second);
197  	  }
198  	
199  	  /**
200  	   * get a crypto handler
201  	   */
202  	  CryptoHandler *get_crypto_handler(int type);
203  	
204  	  CryptoRandom* random() const { return _crypto_random.get(); }
205  	
206  	  /// check if experimental feature is enable, and emit appropriate warnings
207  	  bool check_experimental_feature_enabled(const std::string& feature);
208  	  bool check_experimental_feature_enabled(const std::string& feature,
209  						  std::ostream *message);
210  	
211  	  ceph::PluginRegistry *get_plugin_registry() {
212  	    return _plugin_registry;
213  	  }
214  	
215  	  void set_uid_gid(uid_t u, gid_t g) {
216  	    _set_uid = u;
217  	    _set_gid = g;
218  	  }
219  	  uid_t get_set_uid() const {
220  	    return _set_uid;
221  	  }
222  	  gid_t get_set_gid() const {
223  	    return _set_gid;
224  	  }
225  	
226  	  void set_uid_gid_strings(const std::string &u, const std::string &g) {
227  	    _set_uid_string = u;
228  	    _set_gid_string = g;
229  	  }
230  	  std::string get_set_uid_string() const {
231  	    return _set_uid_string;
232  	  }
233  	  std::string get_set_gid_string() const {
234  	    return _set_gid_string;
235  	  }
236  	
237  	  class ForkWatcher {
238  	   public:
239  	    virtual ~ForkWatcher() {}
240  	    virtual void handle_pre_fork() = 0;
241  	    virtual void handle_post_fork() = 0;
242  	  };
243  	
244  	  void register_fork_watcher(ForkWatcher *w) {
245  	    std::lock_guard lg(_fork_watchers_lock);
246  	    _fork_watchers.push_back(w);
247  	  }
248  	
249  	  void notify_pre_fork();
250  	  void notify_post_fork();
251  	
252  	private:
253  	
254  	
255  	  /* Stop and join the Ceph Context's service thread */
256  	  void join_service_thread();
257  	
258  	  uint32_t _module_type;
259  	
260  	  int _init_flags;
261  	
262  	  uid_t _set_uid; ///< uid to drop privs to
263  	  gid_t _set_gid; ///< gid to drop privs to
264  	  std::string _set_uid_string;
265  	  std::string _set_gid_string;
266  	
267  	  int _crypto_inited;
268  	
269  	  /* libcommon service thread.
270  	   * SIGHUP wakes this thread, which then reopens logfiles */
271  	  friend class CephContextServiceThread;
272  	  CephContextServiceThread *_service_thread;
273  	
274  	  using md_config_obs_t = ceph::md_config_obs_impl<ConfigProxy>;
275  	
276  	  md_config_obs_t *_log_obs;
277  	
278  	  /* The admin socket associated with this context */
279  	  AdminSocket *_admin_socket;
280  	
281  	  /* lock which protects service thread creation, destruction, etc. */
282  	  ceph::spinlock _service_thread_lock;
283  	
284  	  /* The collection of profiling loggers associated with this context */
285  	  PerfCountersCollection *_perf_counters_collection;
286  	
287  	  md_config_obs_t *_perf_counters_conf_obs;
288  	
289  	  CephContextHook *_admin_hook;
290  	
291  	  ceph::HeartbeatMap *_heartbeat_map;
292  	
293  	  ceph::spinlock associated_objs_lock;
294  	
295  	  struct associated_objs_cmp {
296  	    using is_transparent = std::true_type;
297  	    template<typename T, typename U>
298  	    bool operator ()(const std::pair<T, std::type_index>& l,
299  			     const std::pair<U, std::type_index>& r) const noexcept {
300  	      return ((l.first < r.first)  ||
301  		      (l.first == r.first && l.second < r.second));
302  	    }
303  	  };
304  	
305  	  std::map<std::pair<std::string, std::type_index>,
306  		   ceph::immobile_any<largest_singleton>,
307  		   associated_objs_cmp> associated_objs;
308  	  std::set<std::string> associated_objs_drop_on_fork;
309  	
310  	  ceph::spinlock _fork_watchers_lock;
311  	  std::vector<ForkWatcher*> _fork_watchers;
312  	
313  	  // crypto
314  	  CryptoHandler *_crypto_none;
315  	  CryptoHandler *_crypto_aes;
316  	  std::unique_ptr<CryptoRandom> _crypto_random;
317  	
318  	  // experimental
319  	  CephContextObs *_cct_obs;
320  	  ceph::spinlock _feature_lock;
321  	  std::set<std::string> _experimental_features;
322  	
323  	  ceph::PluginRegistry* _plugin_registry;
324  	
325  	  md_config_obs_t *_lockdep_obs;
326  	
327  	public:
328  	  CrushLocation crush_location;
329  	private:
330  	
331  	  enum {
332  	    l_cct_first,
333  	    l_cct_total_workers,
334  	    l_cct_unhealthy_workers,
335  	    l_cct_last
336  	  };
337  	  enum {
338  	    l_mempool_first = 873222,
339  	    l_mempool_bytes,
340  	    l_mempool_items,
341  	    l_mempool_last
342  	  };
343  	  PerfCounters *_cct_perf = nullptr;
344  	  PerfCounters* _mempool_perf = nullptr;
345  	  std::vector<std::string> _mempool_perf_names, _mempool_perf_descriptions;
346  	
347  	  /**
348  	   * Enable the performance counters.
349  	   */
350  	  void _enable_perf_counter();
351  	
352  	  /**
353  	   * Disable the performance counter.
354  	   */
355  	  void _disable_perf_counter();
356  	
357  	  /**
358  	   * Refresh perf counter values.
359  	   */
360  	  void _refresh_perf_values();
361  	
362  	  friend class CephContextObs;
363  	};
364  	#endif	// WITH_SEASTAR
365  	
366  	#endif
367