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