]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/ceph_context.cc
update sources to v12.2.3
[ceph.git] / ceph / src / common / ceph_context.cc
CommitLineData
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) 2011 New Dream Network
7 * Copyright (C) 2017 OVH
8 *
9 * This is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License version 2.1, as published by the Free Software
12 * Foundation. See file COPYING.
13 *
14 */
15
7c673cae
FG
16#include <boost/algorithm/string.hpp>
17
18#include "include/mempool.h"
19#include "common/admin_socket.h"
20#include "common/perf_counters.h"
7c673cae 21#include "common/code_environment.h"
7c673cae 22#include "common/ceph_crypto.h"
7c673cae
FG
23#include "common/HeartbeatMap.h"
24#include "common/errno.h"
7c673cae 25#include "common/Graylog.h"
7c673cae
FG
26#include "auth/Crypto.h"
27#include "include/str_list.h"
7c673cae 28#include "common/PluginRegistry.h"
7c673cae 29
31f18b77 30using ceph::bufferlist;
7c673cae
FG
31using ceph::HeartbeatMap;
32
33namespace {
34
35class LockdepObs : public md_config_obs_t {
36public:
37 explicit LockdepObs(CephContext *cct) : m_cct(cct), m_registered(false) {
38 }
39 ~LockdepObs() override {
40 if (m_registered) {
41 lockdep_unregister_ceph_context(m_cct);
42 }
43 }
44
45 const char** get_tracked_conf_keys() const override {
46 static const char *KEYS[] = {"lockdep", NULL};
47 return KEYS;
48 }
49
50 void handle_conf_change(const md_config_t *conf,
51 const std::set <std::string> &changed) override {
52 if (conf->lockdep && !m_registered) {
53 lockdep_register_ceph_context(m_cct);
54 m_registered = true;
55 } else if (!conf->lockdep && m_registered) {
56 lockdep_unregister_ceph_context(m_cct);
57 m_registered = false;
58 }
59 }
60private:
61 CephContext *m_cct;
62 bool m_registered;
63};
64
65class MempoolObs : public md_config_obs_t,
66 public AdminSocketHook {
67 CephContext *cct;
68
69public:
70 explicit MempoolObs(CephContext *cct) : cct(cct) {
71 cct->_conf->add_observer(this);
72 int r = cct->get_admin_socket()->register_command(
73 "dump_mempools",
74 "dump_mempools",
75 this,
76 "get mempool stats");
77 assert(r == 0);
78 }
79 ~MempoolObs() override {
80 cct->_conf->remove_observer(this);
81 cct->get_admin_socket()->unregister_command("dump_mempools");
82 }
83
84 // md_config_obs_t
85 const char** get_tracked_conf_keys() const override {
86 static const char *KEYS[] = {
87 "mempool_debug",
88 NULL
89 };
90 return KEYS;
91 }
92
93 void handle_conf_change(const md_config_t *conf,
94 const std::set <std::string> &changed) override {
95 if (changed.count("mempool_debug")) {
96 mempool::set_debug_mode(cct->_conf->mempool_debug);
97 }
98 }
99
100 // AdminSocketHook
101 bool call(std::string command, cmdmap_t& cmdmap, std::string format,
102 bufferlist& out) override {
103 if (command == "dump_mempools") {
104 std::unique_ptr<Formatter> f(Formatter::create(format));
105 f->open_object_section("mempools");
106 mempool::dump(f.get());
107 f->close_section();
108 f->flush(out);
109 return true;
110 }
111 return false;
112 }
113};
114
115} // anonymous namespace
116
117class CephContextServiceThread : public Thread
118{
119public:
120 explicit CephContextServiceThread(CephContext *cct)
121 : _lock("CephContextServiceThread::_lock"),
122 _reopen_logs(false), _exit_thread(false), _cct(cct)
123 {
124 }
125
126 ~CephContextServiceThread() override {}
127
128 void *entry() override
129 {
130 while (1) {
131 Mutex::Locker l(_lock);
132
133 if (_cct->_conf->heartbeat_interval) {
134 utime_t interval(_cct->_conf->heartbeat_interval, 0);
135 _cond.WaitInterval(_lock, interval);
136 } else
137 _cond.Wait(_lock);
138
139 if (_exit_thread) {
140 break;
141 }
142
143 if (_reopen_logs) {
144 _cct->_log->reopen_log_file();
145 _reopen_logs = false;
146 }
147 _cct->_heartbeat_map->check_touch_file();
148
149 // refresh the perf coutners
150 _cct->refresh_perf_values();
151 }
152 return NULL;
153 }
154
155 void reopen_logs()
156 {
157 Mutex::Locker l(_lock);
158 _reopen_logs = true;
159 _cond.Signal();
160 }
161
162 void exit_thread()
163 {
164 Mutex::Locker l(_lock);
165 _exit_thread = true;
166 _cond.Signal();
167 }
168
169private:
170 Mutex _lock;
171 Cond _cond;
172 bool _reopen_logs;
173 bool _exit_thread;
174 CephContext *_cct;
175};
176
177
178/**
179 * observe logging config changes
180 *
181 * The logging subsystem sits below most of the ceph code, including
182 * the config subsystem, to keep it simple and self-contained. Feed
183 * logging-related config changes to the log.
184 */
185class LogObs : public md_config_obs_t {
186 ceph::logging::Log *log;
187
188public:
189 explicit LogObs(ceph::logging::Log *l) : log(l) {}
190
191 const char** get_tracked_conf_keys() const override {
192 static const char *KEYS[] = {
193 "log_file",
194 "log_max_new",
195 "log_max_recent",
196 "log_to_syslog",
197 "err_to_syslog",
b32b8144 198 "log_stderr_prefix",
7c673cae
FG
199 "log_to_stderr",
200 "err_to_stderr",
201 "log_to_graylog",
202 "err_to_graylog",
203 "log_graylog_host",
204 "log_graylog_port",
205 "fsid",
206 "host",
207 NULL
208 };
209 return KEYS;
210 }
211
212 void handle_conf_change(const md_config_t *conf,
213 const std::set <std::string> &changed) override {
214 // stderr
215 if (changed.count("log_to_stderr") || changed.count("err_to_stderr")) {
216 int l = conf->log_to_stderr ? 99 : (conf->err_to_stderr ? -1 : -2);
217 log->set_stderr_level(l, l);
218 }
219
220 // syslog
221 if (changed.count("log_to_syslog")) {
222 int l = conf->log_to_syslog ? 99 : (conf->err_to_syslog ? -1 : -2);
223 log->set_syslog_level(l, l);
224 }
225
226 // file
227 if (changed.count("log_file")) {
228 log->set_log_file(conf->log_file);
229 log->reopen_log_file();
230 }
231
b32b8144
FG
232 if (changed.count("log_stderr_prefix")) {
233 log->set_log_stderr_prefix(conf->get_val<string>("log_stderr_prefix"));
234 }
235
7c673cae
FG
236 if (changed.count("log_max_new")) {
237
238 log->set_max_new(conf->log_max_new);
239 }
240
241 if (changed.count("log_max_recent")) {
242 log->set_max_recent(conf->log_max_recent);
243 }
244
245 // graylog
246 if (changed.count("log_to_graylog") || changed.count("err_to_graylog")) {
247 int l = conf->log_to_graylog ? 99 : (conf->err_to_graylog ? -1 : -2);
248 log->set_graylog_level(l, l);
249
250 if (conf->log_to_graylog || conf->err_to_graylog) {
251 log->start_graylog();
252 } else if (! (conf->log_to_graylog && conf->err_to_graylog)) {
253 log->stop_graylog();
254 }
255 }
256
257 if (log->graylog() && (changed.count("log_graylog_host") || changed.count("log_graylog_port"))) {
258 log->graylog()->set_destination(conf->log_graylog_host, conf->log_graylog_port);
259 }
260
261 // metadata
262 if (log->graylog() && changed.count("host")) {
263 log->graylog()->set_hostname(conf->host);
264 }
265
266 if (log->graylog() && changed.count("fsid")) {
3efd9988 267 log->graylog()->set_fsid(conf->get_val<uuid_d>("fsid"));
7c673cae
FG
268 }
269 }
270};
271
272
273// cct config watcher
274class CephContextObs : public md_config_obs_t {
275 CephContext *cct;
276
277public:
278 explicit CephContextObs(CephContext *cct) : cct(cct) {}
279
280 const char** get_tracked_conf_keys() const override {
281 static const char *KEYS[] = {
282 "enable_experimental_unrecoverable_data_corrupting_features",
283 "crush_location",
284 NULL
285 };
286 return KEYS;
287 }
288
289 void handle_conf_change(const md_config_t *conf,
290 const std::set <std::string> &changed) override {
291 if (changed.count(
292 "enable_experimental_unrecoverable_data_corrupting_features")) {
293 ceph_spin_lock(&cct->_feature_lock);
294 get_str_set(
295 conf->enable_experimental_unrecoverable_data_corrupting_features,
296 cct->_experimental_features);
297 ceph_spin_unlock(&cct->_feature_lock);
298 if (getenv("CEPH_DEV") == NULL) {
299 if (!cct->_experimental_features.empty()) {
300 if (cct->_experimental_features.count("*")) {
301 lderr(cct) << "WARNING: all dangerous and experimental features are enabled." << dendl;
302 } else {
303 lderr(cct) << "WARNING: the following dangerous and experimental features are enabled: "
304 << cct->_experimental_features << dendl;
305 }
306 }
307 }
308
309 }
310 if (changed.count("crush_location")) {
311 cct->crush_location.update_from_conf();
312 }
313 }
314};
315
316bool CephContext::check_experimental_feature_enabled(const std::string& feat)
317{
318 stringstream message;
319 bool enabled = check_experimental_feature_enabled(feat, &message);
320 lderr(this) << message.str() << dendl;
321 return enabled;
322}
323
324bool CephContext::check_experimental_feature_enabled(const std::string& feat,
325 std::ostream *message)
326{
327 ceph_spin_lock(&_feature_lock);
328 bool enabled = (_experimental_features.count(feat) ||
329 _experimental_features.count("*"));
330 ceph_spin_unlock(&_feature_lock);
331
332 if (enabled) {
333 (*message) << "WARNING: experimental feature '" << feat << "' is enabled\n";
334 (*message) << "Please be aware that this feature is experimental, untested,\n";
335 (*message) << "unsupported, and may result in data corruption, data loss,\n";
336 (*message) << "and/or irreparable damage to your cluster. Do not use\n";
337 (*message) << "feature with important data.\n";
338 } else {
339 (*message) << "*** experimental feature '" << feat << "' is not enabled ***\n";
340 (*message) << "This feature is marked as experimental, which means it\n";
341 (*message) << " - is untested\n";
342 (*message) << " - is unsupported\n";
343 (*message) << " - may corrupt your data\n";
344 (*message) << " - may break your cluster is an unrecoverable fashion\n";
345 (*message) << "To enable this feature, add this to your ceph.conf:\n";
346 (*message) << " enable experimental unrecoverable data corrupting features = " << feat << "\n";
347 }
348 return enabled;
349}
350
351// perfcounter hooks
352
353class CephContextHook : public AdminSocketHook {
354 CephContext *m_cct;
355
356public:
357 explicit CephContextHook(CephContext *cct) : m_cct(cct) {}
358
359 bool call(std::string command, cmdmap_t& cmdmap, std::string format,
360 bufferlist& out) override {
361 m_cct->do_command(command, cmdmap, format, &out);
362 return true;
363 }
364};
365
366void CephContext::do_command(std::string command, cmdmap_t& cmdmap,
367 std::string format, bufferlist *out)
368{
369 Formatter *f = Formatter::create(format, "json-pretty", "json-pretty");
370 stringstream ss;
371 for (cmdmap_t::iterator it = cmdmap.begin(); it != cmdmap.end(); ++it) {
372 if (it->first != "prefix") {
373 ss << it->first << ":" << cmd_vartype_stringify(it->second) << " ";
374 }
375 }
376 lgeneric_dout(this, 1) << "do_command '" << command << "' '"
377 << ss.str() << dendl;
378 if (command == "perfcounters_dump" || command == "1" ||
379 command == "perf dump") {
380 std::string logger;
381 std::string counter;
382 cmd_getval(this, cmdmap, "logger", logger);
383 cmd_getval(this, cmdmap, "counter", counter);
384 _perf_counters_collection->dump_formatted(f, false, logger, counter);
385 }
386 else if (command == "perfcounters_schema" || command == "2" ||
387 command == "perf schema") {
388 _perf_counters_collection->dump_formatted(f, true);
389 }
390 else if (command == "perf histogram dump") {
391 std::string logger;
392 std::string counter;
393 cmd_getval(this, cmdmap, "logger", logger);
394 cmd_getval(this, cmdmap, "counter", counter);
395 _perf_counters_collection->dump_formatted_histograms(f, false, logger,
396 counter);
397 }
398 else if (command == "perf histogram schema") {
399 _perf_counters_collection->dump_formatted_histograms(f, true);
400 }
401 else if (command == "perf reset") {
402 std::string var;
403 string section = command;
404 f->open_object_section(section.c_str());
405 if (!cmd_getval(this, cmdmap, "var", var)) {
406 f->dump_string("error", "syntax error: 'perf reset <var>'");
407 } else {
408 if(!_perf_counters_collection->reset(var))
409 f->dump_stream("error") << "Not find: " << var;
410 else
411 f->dump_string("success", command + ' ' + var);
412 }
413 f->close_section();
414 }
415 else {
416 string section = command;
417 boost::replace_all(section, " ", "_");
418 f->open_object_section(section.c_str());
419 if (command == "config show") {
420 _conf->show_config(f);
421 }
422 else if (command == "config set") {
423 std::string var;
424 std::vector<std::string> val;
425
426 if (!(cmd_getval(this, cmdmap, "var", var)) ||
427 !(cmd_getval(this, cmdmap, "val", val))) {
428 f->dump_string("error", "syntax error: 'config set <var> <value>'");
429 } else {
430 // val may be multiple words
431 string valstr = str_join(val, " ");
432 int r = _conf->set_val(var.c_str(), valstr.c_str());
433 if (r < 0) {
434 f->dump_stream("error") << "error setting '" << var << "' to '" << valstr << "': " << cpp_strerror(r);
435 } else {
436 ostringstream ss;
437 _conf->apply_changes(&ss);
438 f->dump_string("success", ss.str());
439 }
440 }
441 } else if (command == "config get") {
442 std::string var;
443 if (!cmd_getval(this, cmdmap, "var", var)) {
444 f->dump_string("error", "syntax error: 'config get <var>'");
445 } else {
446 char buf[4096];
447 memset(buf, 0, sizeof(buf));
448 char *tmp = buf;
449 int r = _conf->get_val(var.c_str(), &tmp, sizeof(buf));
450 if (r < 0) {
451 f->dump_stream("error") << "error getting '" << var << "': " << cpp_strerror(r);
452 } else {
453 f->dump_string(var.c_str(), buf);
454 }
455 }
c07f9fc5
FG
456 } else if (command == "config help") {
457 std::string var;
458 if (cmd_getval(this, cmdmap, "var", var)) {
459 // Output a single one
460 std::string key = ConfFile::normalize_key_name(var);
461 const auto &i = _conf->schema.find(key);
462 if (i == _conf->schema.end()) {
463 std::ostringstream msg;
464 msg << "Setting not found: '" << key << "'";
465 f->dump_string("error", msg.str());
466 } else {
467 i->second.dump(f);
468 }
469 } else {
470 // Output all
471 f->open_array_section("options");
472 for (const auto &option : ceph_options) {
473 option.dump(f);
474 }
475 f->close_section();
476 }
7c673cae
FG
477 } else if (command == "config diff") {
478 md_config_t def_conf;
479 def_conf.set_val("cluster", _conf->cluster);
480 def_conf.name = _conf->name;
481 def_conf.set_val("host", _conf->host);
482 def_conf.apply_changes(NULL);
483
484 map<string,pair<string,string> > diff;
485 set<string> unknown;
486 def_conf.diff(_conf, &diff, &unknown);
487 f->open_object_section("diff");
488
489 f->open_object_section("current");
490 for (map<string,pair<string,string> >::iterator p = diff.begin();
491 p != diff.end(); ++p) {
492 f->dump_string(p->first.c_str(), p->second.second);
493 }
494 f->close_section(); // current
495 f->open_object_section("defaults");
496 for (map<string,pair<string,string> >::iterator p = diff.begin();
497 p != diff.end(); ++p) {
498 f->dump_string(p->first.c_str(), p->second.first);
499 }
500 f->close_section(); // defaults
501 f->close_section(); // diff
502
503 f->open_array_section("unknown");
504 for (set<string>::iterator p = unknown.begin();
505 p != unknown.end(); ++p) {
506 f->dump_string("option", *p);
507 }
508 f->close_section(); // unknown
31f18b77
FG
509 } else if (command == "config diff get") {
510 std::string setting;
511 if (!cmd_getval(this, cmdmap, "var", setting)) {
512 f->dump_string("error", "syntax error: 'config diff get <var>'");
513 } else {
514 md_config_t def_conf;
515 def_conf.set_val("cluster", _conf->cluster);
516 def_conf.name = _conf->name;
517 def_conf.set_val("host", _conf->host);
518 def_conf.apply_changes(NULL);
519
520 map<string, pair<string, string>> diff;
521 set<string> unknown;
522 def_conf.diff(_conf, &diff, &unknown, setting);
523 f->open_object_section("diff");
524 f->open_object_section("current");
525
526 for (const auto& p : diff) {
527 f->dump_string(p.first.c_str(), p.second.second);
528 }
529 f->close_section(); //-- current
530
531 f->open_object_section("defaults");
532 for (const auto& p : diff) {
533 f->dump_string(p.first.c_str(), p.second.first);
534 }
535 f->close_section(); //-- defaults
536 f->close_section(); //-- diff
537 }
7c673cae
FG
538 } else if (command == "log flush") {
539 _log->flush();
540 }
541 else if (command == "log dump") {
542 _log->dump_recent();
543 }
544 else if (command == "log reopen") {
545 _log->reopen_log_file();
546 }
547 else {
548 assert(0 == "registered under wrong command?");
549 }
550 f->close_section();
551 }
552 f->flush(*out);
553 delete f;
554 lgeneric_dout(this, 1) << "do_command '" << command << "' '" << ss.str()
555 << "result is " << out->length() << " bytes" << dendl;
556}
557
c07f9fc5
FG
558CephContext::CephContext(uint32_t module_type_,
559 enum code_environment_t code_env,
560 int init_flags_)
7c673cae 561 : nref(1),
c07f9fc5 562 _conf(new md_config_t(code_env == CODE_ENVIRONMENT_DAEMON)),
7c673cae
FG
563 _log(NULL),
564 _module_type(module_type_),
565 _init_flags(init_flags_),
566 _set_uid(0),
567 _set_gid(0),
568 _set_uid_string(),
569 _set_gid_string(),
570 _crypto_inited(false),
571 _service_thread(NULL),
572 _log_obs(NULL),
573 _admin_socket(NULL),
574 _perf_counters_collection(NULL),
575 _perf_counters_conf_obs(NULL),
576 _heartbeat_map(NULL),
577 _crypto_none(NULL),
578 _crypto_aes(NULL),
579 _plugin_registry(NULL),
580 _lockdep_obs(NULL),
581 crush_location(this),
582 _cct_perf(NULL)
583{
584 ceph_spin_init(&_service_thread_lock);
585 ceph_spin_init(&_associated_objs_lock);
586 ceph_spin_init(&_fork_watchers_lock);
587 ceph_spin_init(&_feature_lock);
588 ceph_spin_init(&_cct_perf_lock);
589
590 _log = new ceph::logging::Log(&_conf->subsys);
591 _log->start();
592
593 _log_obs = new LogObs(_log);
594 _conf->add_observer(_log_obs);
595
596 _cct_obs = new CephContextObs(this);
597 _conf->add_observer(_cct_obs);
598
599 _lockdep_obs = new LockdepObs(this);
600 _conf->add_observer(_lockdep_obs);
601
602 _perf_counters_collection = new PerfCountersCollection(this);
603
604 _admin_socket = new AdminSocket(this);
605 _heartbeat_map = new HeartbeatMap(this);
606
607 _plugin_registry = new PluginRegistry(this);
608
609 _admin_hook = new CephContextHook(this);
610 _admin_socket->register_command("perfcounters_dump", "perfcounters_dump", _admin_hook, "");
611 _admin_socket->register_command("1", "1", _admin_hook, "");
612 _admin_socket->register_command("perf dump", "perf dump name=logger,type=CephString,req=false name=counter,type=CephString,req=false", _admin_hook, "dump perfcounters value");
613 _admin_socket->register_command("perfcounters_schema", "perfcounters_schema", _admin_hook, "");
614 _admin_socket->register_command("perf histogram dump", "perf histogram dump name=logger,type=CephString,req=false name=counter,type=CephString,req=false", _admin_hook, "dump perf histogram values");
615 _admin_socket->register_command("2", "2", _admin_hook, "");
616 _admin_socket->register_command("perf schema", "perf schema", _admin_hook, "dump perfcounters schema");
617 _admin_socket->register_command("perf histogram schema", "perf histogram schema", _admin_hook, "dump perf histogram schema");
618 _admin_socket->register_command("perf reset", "perf reset name=var,type=CephString", _admin_hook, "perf reset <name>: perf reset all or one perfcounter name");
619 _admin_socket->register_command("config show", "config show", _admin_hook, "dump current config settings");
c07f9fc5 620 _admin_socket->register_command("config help", "config help name=var,type=CephString,req=false", _admin_hook, "get config setting schema and descriptions");
7c673cae
FG
621 _admin_socket->register_command("config set", "config set name=var,type=CephString name=val,type=CephString,n=N", _admin_hook, "config set <field> <val> [<val> ...]: set a config variable");
622 _admin_socket->register_command("config get", "config get name=var,type=CephString", _admin_hook, "config get <field>: get the config value");
623 _admin_socket->register_command("config diff",
624 "config diff", _admin_hook,
625 "dump diff of current config and default config");
31f18b77
FG
626 _admin_socket->register_command("config diff get",
627 "config diff get name=var,type=CephString", _admin_hook,
628 "dump diff get <field>: dump diff of current and default config setting <field>");
7c673cae
FG
629 _admin_socket->register_command("log flush", "log flush", _admin_hook, "flush log entries to log file");
630 _admin_socket->register_command("log dump", "log dump", _admin_hook, "dump recent log entries to log file");
631 _admin_socket->register_command("log reopen", "log reopen", _admin_hook, "reopen log file");
632
633 _crypto_none = CryptoHandler::create(CEPH_CRYPTO_NONE);
634 _crypto_aes = CryptoHandler::create(CEPH_CRYPTO_AES);
635
636 MempoolObs *mempool_obs = 0;
637 lookup_or_create_singleton_object(mempool_obs, "mempool_obs");
638}
639
640CephContext::~CephContext()
641{
642 join_service_thread();
643
644 for (map<string, SingletonWrapper*>::iterator it = _associated_objs.begin();
645 it != _associated_objs.end(); ++it)
646 delete it->second;
647
648 if (_cct_perf) {
649 _perf_counters_collection->remove(_cct_perf);
650 delete _cct_perf;
651 _cct_perf = NULL;
652 }
653
654 delete _plugin_registry;
655
656 _admin_socket->unregister_command("perfcounters_dump");
7c673cae 657 _admin_socket->unregister_command("1");
31f18b77 658 _admin_socket->unregister_command("perf dump");
7c673cae 659 _admin_socket->unregister_command("perfcounters_schema");
31f18b77 660 _admin_socket->unregister_command("perf histogram dump");
7c673cae 661 _admin_socket->unregister_command("2");
31f18b77
FG
662 _admin_socket->unregister_command("perf schema");
663 _admin_socket->unregister_command("perf histogram schema");
7c673cae
FG
664 _admin_socket->unregister_command("perf reset");
665 _admin_socket->unregister_command("config show");
666 _admin_socket->unregister_command("config set");
667 _admin_socket->unregister_command("config get");
c07f9fc5 668 _admin_socket->unregister_command("config help");
7c673cae 669 _admin_socket->unregister_command("config diff");
31f18b77 670 _admin_socket->unregister_command("config diff get");
7c673cae
FG
671 _admin_socket->unregister_command("log flush");
672 _admin_socket->unregister_command("log dump");
673 _admin_socket->unregister_command("log reopen");
674 delete _admin_hook;
675 delete _admin_socket;
676
677 delete _heartbeat_map;
678
679 delete _perf_counters_collection;
680 _perf_counters_collection = NULL;
681
682 delete _perf_counters_conf_obs;
683 _perf_counters_conf_obs = NULL;
684
685 _conf->remove_observer(_log_obs);
686 delete _log_obs;
687 _log_obs = NULL;
688
689 _conf->remove_observer(_cct_obs);
690 delete _cct_obs;
691 _cct_obs = NULL;
692
693 _conf->remove_observer(_lockdep_obs);
694 delete _lockdep_obs;
695 _lockdep_obs = NULL;
696
697 _log->stop();
698 delete _log;
699 _log = NULL;
700
701 delete _conf;
702 ceph_spin_destroy(&_service_thread_lock);
703 ceph_spin_destroy(&_fork_watchers_lock);
704 ceph_spin_destroy(&_associated_objs_lock);
705 ceph_spin_destroy(&_feature_lock);
706 ceph_spin_destroy(&_cct_perf_lock);
707
708 delete _crypto_none;
709 delete _crypto_aes;
710 if (_crypto_inited)
711 ceph::crypto::shutdown(g_code_env == CODE_ENVIRONMENT_LIBRARY);
712}
713
714void CephContext::put() {
31f18b77 715 if (--nref == 0) {
7c673cae
FG
716 ANNOTATE_HAPPENS_AFTER(&nref);
717 ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&nref);
718 delete this;
719 } else {
720 ANNOTATE_HAPPENS_BEFORE(&nref);
721 }
722}
723
724void CephContext::init_crypto()
725{
726 if (!_crypto_inited) {
727 ceph::crypto::init(this);
728 _crypto_inited = true;
729 }
730}
731
732void CephContext::start_service_thread()
733{
734 ceph_spin_lock(&_service_thread_lock);
735 if (_service_thread) {
736 ceph_spin_unlock(&_service_thread_lock);
737 return;
738 }
739 _service_thread = new CephContextServiceThread(this);
740 _service_thread->create("service");
741 ceph_spin_unlock(&_service_thread_lock);
742
743 // make logs flush on_exit()
744 if (_conf->log_flush_on_exit)
745 _log->set_flush_on_exit();
746
747 // Trigger callbacks on any config observers that were waiting for
748 // it to become safe to start threads.
749 _conf->set_val("internal_safe_to_start_threads", "true");
750 _conf->call_all_observers();
751
752 // start admin socket
753 if (_conf->admin_socket.length())
754 _admin_socket->init(_conf->admin_socket);
755}
756
757void CephContext::reopen_logs()
758{
759 ceph_spin_lock(&_service_thread_lock);
760 if (_service_thread)
761 _service_thread->reopen_logs();
762 ceph_spin_unlock(&_service_thread_lock);
763}
764
765void CephContext::join_service_thread()
766{
767 ceph_spin_lock(&_service_thread_lock);
768 CephContextServiceThread *thread = _service_thread;
769 if (!thread) {
770 ceph_spin_unlock(&_service_thread_lock);
771 return;
772 }
773 _service_thread = NULL;
774 ceph_spin_unlock(&_service_thread_lock);
775
776 thread->exit_thread();
777 thread->join();
778 delete thread;
779}
780
781uint32_t CephContext::get_module_type() const
782{
783 return _module_type;
784}
785
786void CephContext::set_init_flags(int flags)
787{
788 _init_flags = flags;
789}
790
791int CephContext::get_init_flags() const
792{
793 return _init_flags;
794}
795
796PerfCountersCollection *CephContext::get_perfcounters_collection()
797{
798 return _perf_counters_collection;
799}
800
801void CephContext::enable_perf_counter()
802{
803 PerfCountersBuilder plb(this, "cct", l_cct_first, l_cct_last);
804 plb.add_u64(l_cct_total_workers, "total_workers", "Total workers");
805 plb.add_u64(l_cct_unhealthy_workers, "unhealthy_workers", "Unhealthy workers");
806 PerfCounters *perf_tmp = plb.create_perf_counters();
807
808 ceph_spin_lock(&_cct_perf_lock);
809 assert(_cct_perf == NULL);
810 _cct_perf = perf_tmp;
811 ceph_spin_unlock(&_cct_perf_lock);
812
813 _perf_counters_collection->add(_cct_perf);
814}
815
816void CephContext::disable_perf_counter()
817{
818 _perf_counters_collection->remove(_cct_perf);
819
820 ceph_spin_lock(&_cct_perf_lock);
821 delete _cct_perf;
822 _cct_perf = NULL;
823 ceph_spin_unlock(&_cct_perf_lock);
824}
825
826void CephContext::refresh_perf_values()
827{
828 ceph_spin_lock(&_cct_perf_lock);
829 if (_cct_perf) {
830 _cct_perf->set(l_cct_total_workers, _heartbeat_map->get_total_workers());
831 _cct_perf->set(l_cct_unhealthy_workers, _heartbeat_map->get_unhealthy_workers());
832 }
833 ceph_spin_unlock(&_cct_perf_lock);
834}
835
836AdminSocket *CephContext::get_admin_socket()
837{
838 return _admin_socket;
839}
840
841CryptoHandler *CephContext::get_crypto_handler(int type)
842{
843 switch (type) {
844 case CEPH_CRYPTO_NONE:
845 return _crypto_none;
846 case CEPH_CRYPTO_AES:
847 return _crypto_aes;
848 default:
849 return NULL;
850 }
851}