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