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