]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/ceph_context.cc
update sources to v12.1.0
[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) : 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 }
60 private:
61 CephContext *m_cct;
62 bool m_registered;
63 };
64
65 class MempoolObs : public md_config_obs_t,
66 public AdminSocketHook {
67 CephContext *cct;
68
69 public:
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
117 class CephContextServiceThread : public Thread
118 {
119 public:
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
169 private:
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 */
185 class LogObs : public md_config_obs_t {
186 ceph::logging::Log *log;
187
188 public:
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",
198 "log_to_stderr",
199 "err_to_stderr",
200 "log_to_graylog",
201 "err_to_graylog",
202 "log_graylog_host",
203 "log_graylog_port",
204 "fsid",
205 "host",
206 NULL
207 };
208 return KEYS;
209 }
210
211 void handle_conf_change(const md_config_t *conf,
212 const std::set <std::string> &changed) override {
213 // stderr
214 if (changed.count("log_to_stderr") || changed.count("err_to_stderr")) {
215 int l = conf->log_to_stderr ? 99 : (conf->err_to_stderr ? -1 : -2);
216 log->set_stderr_level(l, l);
217 }
218
219 // syslog
220 if (changed.count("log_to_syslog")) {
221 int l = conf->log_to_syslog ? 99 : (conf->err_to_syslog ? -1 : -2);
222 log->set_syslog_level(l, l);
223 }
224
225 // file
226 if (changed.count("log_file")) {
227 log->set_log_file(conf->log_file);
228 log->reopen_log_file();
229 }
230
231 if (changed.count("log_max_new")) {
232
233 log->set_max_new(conf->log_max_new);
234 }
235
236 if (changed.count("log_max_recent")) {
237 log->set_max_recent(conf->log_max_recent);
238 }
239
240 // graylog
241 if (changed.count("log_to_graylog") || changed.count("err_to_graylog")) {
242 int l = conf->log_to_graylog ? 99 : (conf->err_to_graylog ? -1 : -2);
243 log->set_graylog_level(l, l);
244
245 if (conf->log_to_graylog || conf->err_to_graylog) {
246 log->start_graylog();
247 } else if (! (conf->log_to_graylog && conf->err_to_graylog)) {
248 log->stop_graylog();
249 }
250 }
251
252 if (log->graylog() && (changed.count("log_graylog_host") || changed.count("log_graylog_port"))) {
253 log->graylog()->set_destination(conf->log_graylog_host, conf->log_graylog_port);
254 }
255
256 // metadata
257 if (log->graylog() && changed.count("host")) {
258 log->graylog()->set_hostname(conf->host);
259 }
260
261 if (log->graylog() && changed.count("fsid")) {
262 log->graylog()->set_fsid(conf->fsid);
263 }
264 }
265 };
266
267
268 // cct config watcher
269 class CephContextObs : public md_config_obs_t {
270 CephContext *cct;
271
272 public:
273 explicit CephContextObs(CephContext *cct) : cct(cct) {}
274
275 const char** get_tracked_conf_keys() const override {
276 static const char *KEYS[] = {
277 "enable_experimental_unrecoverable_data_corrupting_features",
278 "crush_location",
279 NULL
280 };
281 return KEYS;
282 }
283
284 void handle_conf_change(const md_config_t *conf,
285 const std::set <std::string> &changed) override {
286 if (changed.count(
287 "enable_experimental_unrecoverable_data_corrupting_features")) {
288 ceph_spin_lock(&cct->_feature_lock);
289 get_str_set(
290 conf->enable_experimental_unrecoverable_data_corrupting_features,
291 cct->_experimental_features);
292 ceph_spin_unlock(&cct->_feature_lock);
293 if (getenv("CEPH_DEV") == NULL) {
294 if (!cct->_experimental_features.empty()) {
295 if (cct->_experimental_features.count("*")) {
296 lderr(cct) << "WARNING: all dangerous and experimental features are enabled." << dendl;
297 } else {
298 lderr(cct) << "WARNING: the following dangerous and experimental features are enabled: "
299 << cct->_experimental_features << dendl;
300 }
301 }
302 }
303
304 }
305 if (changed.count("crush_location")) {
306 cct->crush_location.update_from_conf();
307 }
308 }
309 };
310
311 bool CephContext::check_experimental_feature_enabled(const std::string& feat)
312 {
313 stringstream message;
314 bool enabled = check_experimental_feature_enabled(feat, &message);
315 lderr(this) << message.str() << dendl;
316 return enabled;
317 }
318
319 bool CephContext::check_experimental_feature_enabled(const std::string& feat,
320 std::ostream *message)
321 {
322 ceph_spin_lock(&_feature_lock);
323 bool enabled = (_experimental_features.count(feat) ||
324 _experimental_features.count("*"));
325 ceph_spin_unlock(&_feature_lock);
326
327 if (enabled) {
328 (*message) << "WARNING: experimental feature '" << feat << "' is enabled\n";
329 (*message) << "Please be aware that this feature is experimental, untested,\n";
330 (*message) << "unsupported, and may result in data corruption, data loss,\n";
331 (*message) << "and/or irreparable damage to your cluster. Do not use\n";
332 (*message) << "feature with important data.\n";
333 } else {
334 (*message) << "*** experimental feature '" << feat << "' is not enabled ***\n";
335 (*message) << "This feature is marked as experimental, which means it\n";
336 (*message) << " - is untested\n";
337 (*message) << " - is unsupported\n";
338 (*message) << " - may corrupt your data\n";
339 (*message) << " - may break your cluster is an unrecoverable fashion\n";
340 (*message) << "To enable this feature, add this to your ceph.conf:\n";
341 (*message) << " enable experimental unrecoverable data corrupting features = " << feat << "\n";
342 }
343 return enabled;
344 }
345
346 // perfcounter hooks
347
348 class CephContextHook : public AdminSocketHook {
349 CephContext *m_cct;
350
351 public:
352 explicit CephContextHook(CephContext *cct) : m_cct(cct) {}
353
354 bool call(std::string command, cmdmap_t& cmdmap, std::string format,
355 bufferlist& out) override {
356 m_cct->do_command(command, cmdmap, format, &out);
357 return true;
358 }
359 };
360
361 void CephContext::do_command(std::string command, cmdmap_t& cmdmap,
362 std::string format, bufferlist *out)
363 {
364 Formatter *f = Formatter::create(format, "json-pretty", "json-pretty");
365 stringstream ss;
366 for (cmdmap_t::iterator it = cmdmap.begin(); it != cmdmap.end(); ++it) {
367 if (it->first != "prefix") {
368 ss << it->first << ":" << cmd_vartype_stringify(it->second) << " ";
369 }
370 }
371 lgeneric_dout(this, 1) << "do_command '" << command << "' '"
372 << ss.str() << dendl;
373 if (command == "perfcounters_dump" || command == "1" ||
374 command == "perf dump") {
375 std::string logger;
376 std::string counter;
377 cmd_getval(this, cmdmap, "logger", logger);
378 cmd_getval(this, cmdmap, "counter", counter);
379 _perf_counters_collection->dump_formatted(f, false, logger, counter);
380 }
381 else if (command == "perfcounters_schema" || command == "2" ||
382 command == "perf schema") {
383 _perf_counters_collection->dump_formatted(f, true);
384 }
385 else if (command == "perf histogram dump") {
386 std::string logger;
387 std::string counter;
388 cmd_getval(this, cmdmap, "logger", logger);
389 cmd_getval(this, cmdmap, "counter", counter);
390 _perf_counters_collection->dump_formatted_histograms(f, false, logger,
391 counter);
392 }
393 else if (command == "perf histogram schema") {
394 _perf_counters_collection->dump_formatted_histograms(f, true);
395 }
396 else if (command == "perf reset") {
397 std::string var;
398 string section = command;
399 f->open_object_section(section.c_str());
400 if (!cmd_getval(this, cmdmap, "var", var)) {
401 f->dump_string("error", "syntax error: 'perf reset <var>'");
402 } else {
403 if(!_perf_counters_collection->reset(var))
404 f->dump_stream("error") << "Not find: " << var;
405 else
406 f->dump_string("success", command + ' ' + var);
407 }
408 f->close_section();
409 }
410 else {
411 string section = command;
412 boost::replace_all(section, " ", "_");
413 f->open_object_section(section.c_str());
414 if (command == "config show") {
415 _conf->show_config(f);
416 }
417 else if (command == "config set") {
418 std::string var;
419 std::vector<std::string> val;
420
421 if (!(cmd_getval(this, cmdmap, "var", var)) ||
422 !(cmd_getval(this, cmdmap, "val", val))) {
423 f->dump_string("error", "syntax error: 'config set <var> <value>'");
424 } else {
425 // val may be multiple words
426 string valstr = str_join(val, " ");
427 int r = _conf->set_val(var.c_str(), valstr.c_str());
428 if (r < 0) {
429 f->dump_stream("error") << "error setting '" << var << "' to '" << valstr << "': " << cpp_strerror(r);
430 } else {
431 ostringstream ss;
432 _conf->apply_changes(&ss);
433 f->dump_string("success", ss.str());
434 }
435 }
436 } else if (command == "config get") {
437 std::string var;
438 if (!cmd_getval(this, cmdmap, "var", var)) {
439 f->dump_string("error", "syntax error: 'config get <var>'");
440 } else {
441 char buf[4096];
442 memset(buf, 0, sizeof(buf));
443 char *tmp = buf;
444 int r = _conf->get_val(var.c_str(), &tmp, sizeof(buf));
445 if (r < 0) {
446 f->dump_stream("error") << "error getting '" << var << "': " << cpp_strerror(r);
447 } else {
448 f->dump_string(var.c_str(), buf);
449 }
450 }
451 } else if (command == "config diff") {
452 md_config_t def_conf;
453 def_conf.set_val("cluster", _conf->cluster);
454 def_conf.name = _conf->name;
455 def_conf.set_val("host", _conf->host);
456 def_conf.apply_changes(NULL);
457
458 map<string,pair<string,string> > diff;
459 set<string> unknown;
460 def_conf.diff(_conf, &diff, &unknown);
461 f->open_object_section("diff");
462
463 f->open_object_section("current");
464 for (map<string,pair<string,string> >::iterator p = diff.begin();
465 p != diff.end(); ++p) {
466 f->dump_string(p->first.c_str(), p->second.second);
467 }
468 f->close_section(); // current
469 f->open_object_section("defaults");
470 for (map<string,pair<string,string> >::iterator p = diff.begin();
471 p != diff.end(); ++p) {
472 f->dump_string(p->first.c_str(), p->second.first);
473 }
474 f->close_section(); // defaults
475 f->close_section(); // diff
476
477 f->open_array_section("unknown");
478 for (set<string>::iterator p = unknown.begin();
479 p != unknown.end(); ++p) {
480 f->dump_string("option", *p);
481 }
482 f->close_section(); // unknown
483 } else if (command == "config diff get") {
484 std::string setting;
485 if (!cmd_getval(this, cmdmap, "var", setting)) {
486 f->dump_string("error", "syntax error: 'config diff get <var>'");
487 } else {
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, setting);
497 f->open_object_section("diff");
498 f->open_object_section("current");
499
500 for (const auto& p : diff) {
501 f->dump_string(p.first.c_str(), p.second.second);
502 }
503 f->close_section(); //-- current
504
505 f->open_object_section("defaults");
506 for (const auto& p : diff) {
507 f->dump_string(p.first.c_str(), p.second.first);
508 }
509 f->close_section(); //-- defaults
510 f->close_section(); //-- diff
511 }
512 } else if (command == "log flush") {
513 _log->flush();
514 }
515 else if (command == "log dump") {
516 _log->dump_recent();
517 }
518 else if (command == "log reopen") {
519 _log->reopen_log_file();
520 }
521 else {
522 assert(0 == "registered under wrong command?");
523 }
524 f->close_section();
525 }
526 f->flush(*out);
527 delete f;
528 lgeneric_dout(this, 1) << "do_command '" << command << "' '" << ss.str()
529 << "result is " << out->length() << " bytes" << dendl;
530 }
531
532
533 CephContext::CephContext(uint32_t module_type_, int init_flags_)
534 : nref(1),
535 _conf(new md_config_t()),
536 _log(NULL),
537 _module_type(module_type_),
538 _init_flags(init_flags_),
539 _set_uid(0),
540 _set_gid(0),
541 _set_uid_string(),
542 _set_gid_string(),
543 _crypto_inited(false),
544 _service_thread(NULL),
545 _log_obs(NULL),
546 _admin_socket(NULL),
547 _perf_counters_collection(NULL),
548 _perf_counters_conf_obs(NULL),
549 _heartbeat_map(NULL),
550 _crypto_none(NULL),
551 _crypto_aes(NULL),
552 _plugin_registry(NULL),
553 _lockdep_obs(NULL),
554 crush_location(this),
555 _cct_perf(NULL)
556 {
557 ceph_spin_init(&_service_thread_lock);
558 ceph_spin_init(&_associated_objs_lock);
559 ceph_spin_init(&_fork_watchers_lock);
560 ceph_spin_init(&_feature_lock);
561 ceph_spin_init(&_cct_perf_lock);
562
563 _log = new ceph::logging::Log(&_conf->subsys);
564 _log->start();
565
566 _log_obs = new LogObs(_log);
567 _conf->add_observer(_log_obs);
568
569 _cct_obs = new CephContextObs(this);
570 _conf->add_observer(_cct_obs);
571
572 _lockdep_obs = new LockdepObs(this);
573 _conf->add_observer(_lockdep_obs);
574
575 _perf_counters_collection = new PerfCountersCollection(this);
576
577 _admin_socket = new AdminSocket(this);
578 _heartbeat_map = new HeartbeatMap(this);
579
580 _plugin_registry = new PluginRegistry(this);
581
582 _admin_hook = new CephContextHook(this);
583 _admin_socket->register_command("perfcounters_dump", "perfcounters_dump", _admin_hook, "");
584 _admin_socket->register_command("1", "1", _admin_hook, "");
585 _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");
586 _admin_socket->register_command("perfcounters_schema", "perfcounters_schema", _admin_hook, "");
587 _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");
588 _admin_socket->register_command("2", "2", _admin_hook, "");
589 _admin_socket->register_command("perf schema", "perf schema", _admin_hook, "dump perfcounters schema");
590 _admin_socket->register_command("perf histogram schema", "perf histogram schema", _admin_hook, "dump perf histogram schema");
591 _admin_socket->register_command("perf reset", "perf reset name=var,type=CephString", _admin_hook, "perf reset <name>: perf reset all or one perfcounter name");
592 _admin_socket->register_command("config show", "config show", _admin_hook, "dump current config settings");
593 _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");
594 _admin_socket->register_command("config get", "config get name=var,type=CephString", _admin_hook, "config get <field>: get the config value");
595 _admin_socket->register_command("config diff",
596 "config diff", _admin_hook,
597 "dump diff of current config and default config");
598 _admin_socket->register_command("config diff get",
599 "config diff get name=var,type=CephString", _admin_hook,
600 "dump diff get <field>: dump diff of current and default config setting <field>");
601 _admin_socket->register_command("log flush", "log flush", _admin_hook, "flush log entries to log file");
602 _admin_socket->register_command("log dump", "log dump", _admin_hook, "dump recent log entries to log file");
603 _admin_socket->register_command("log reopen", "log reopen", _admin_hook, "reopen log file");
604
605 _crypto_none = CryptoHandler::create(CEPH_CRYPTO_NONE);
606 _crypto_aes = CryptoHandler::create(CEPH_CRYPTO_AES);
607
608 MempoolObs *mempool_obs = 0;
609 lookup_or_create_singleton_object(mempool_obs, "mempool_obs");
610 }
611
612 CephContext::~CephContext()
613 {
614 join_service_thread();
615
616 for (map<string, SingletonWrapper*>::iterator it = _associated_objs.begin();
617 it != _associated_objs.end(); ++it)
618 delete it->second;
619
620 if (_cct_perf) {
621 _perf_counters_collection->remove(_cct_perf);
622 delete _cct_perf;
623 _cct_perf = NULL;
624 }
625
626 delete _plugin_registry;
627
628 _admin_socket->unregister_command("perfcounters_dump");
629 _admin_socket->unregister_command("1");
630 _admin_socket->unregister_command("perf dump");
631 _admin_socket->unregister_command("perfcounters_schema");
632 _admin_socket->unregister_command("perf histogram dump");
633 _admin_socket->unregister_command("2");
634 _admin_socket->unregister_command("perf schema");
635 _admin_socket->unregister_command("perf histogram schema");
636 _admin_socket->unregister_command("perf reset");
637 _admin_socket->unregister_command("config show");
638 _admin_socket->unregister_command("config set");
639 _admin_socket->unregister_command("config get");
640 _admin_socket->unregister_command("config diff");
641 _admin_socket->unregister_command("config diff get");
642 _admin_socket->unregister_command("log flush");
643 _admin_socket->unregister_command("log dump");
644 _admin_socket->unregister_command("log reopen");
645 delete _admin_hook;
646 delete _admin_socket;
647
648 delete _heartbeat_map;
649
650 delete _perf_counters_collection;
651 _perf_counters_collection = NULL;
652
653 delete _perf_counters_conf_obs;
654 _perf_counters_conf_obs = NULL;
655
656 _conf->remove_observer(_log_obs);
657 delete _log_obs;
658 _log_obs = NULL;
659
660 _conf->remove_observer(_cct_obs);
661 delete _cct_obs;
662 _cct_obs = NULL;
663
664 _conf->remove_observer(_lockdep_obs);
665 delete _lockdep_obs;
666 _lockdep_obs = NULL;
667
668 _log->stop();
669 delete _log;
670 _log = NULL;
671
672 delete _conf;
673 ceph_spin_destroy(&_service_thread_lock);
674 ceph_spin_destroy(&_fork_watchers_lock);
675 ceph_spin_destroy(&_associated_objs_lock);
676 ceph_spin_destroy(&_feature_lock);
677 ceph_spin_destroy(&_cct_perf_lock);
678
679 delete _crypto_none;
680 delete _crypto_aes;
681 if (_crypto_inited)
682 ceph::crypto::shutdown(g_code_env == CODE_ENVIRONMENT_LIBRARY);
683 }
684
685 void CephContext::put() {
686 if (--nref == 0) {
687 ANNOTATE_HAPPENS_AFTER(&nref);
688 ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&nref);
689 delete this;
690 } else {
691 ANNOTATE_HAPPENS_BEFORE(&nref);
692 }
693 }
694
695 void CephContext::init_crypto()
696 {
697 if (!_crypto_inited) {
698 ceph::crypto::init(this);
699 _crypto_inited = true;
700 }
701 }
702
703 void CephContext::start_service_thread()
704 {
705 ceph_spin_lock(&_service_thread_lock);
706 if (_service_thread) {
707 ceph_spin_unlock(&_service_thread_lock);
708 return;
709 }
710 _service_thread = new CephContextServiceThread(this);
711 _service_thread->create("service");
712 ceph_spin_unlock(&_service_thread_lock);
713
714 // make logs flush on_exit()
715 if (_conf->log_flush_on_exit)
716 _log->set_flush_on_exit();
717
718 // Trigger callbacks on any config observers that were waiting for
719 // it to become safe to start threads.
720 _conf->set_val("internal_safe_to_start_threads", "true");
721 _conf->call_all_observers();
722
723 // start admin socket
724 if (_conf->admin_socket.length())
725 _admin_socket->init(_conf->admin_socket);
726 }
727
728 void CephContext::reopen_logs()
729 {
730 ceph_spin_lock(&_service_thread_lock);
731 if (_service_thread)
732 _service_thread->reopen_logs();
733 ceph_spin_unlock(&_service_thread_lock);
734 }
735
736 void CephContext::join_service_thread()
737 {
738 ceph_spin_lock(&_service_thread_lock);
739 CephContextServiceThread *thread = _service_thread;
740 if (!thread) {
741 ceph_spin_unlock(&_service_thread_lock);
742 return;
743 }
744 _service_thread = NULL;
745 ceph_spin_unlock(&_service_thread_lock);
746
747 thread->exit_thread();
748 thread->join();
749 delete thread;
750 }
751
752 uint32_t CephContext::get_module_type() const
753 {
754 return _module_type;
755 }
756
757 void CephContext::set_init_flags(int flags)
758 {
759 _init_flags = flags;
760 }
761
762 int CephContext::get_init_flags() const
763 {
764 return _init_flags;
765 }
766
767 PerfCountersCollection *CephContext::get_perfcounters_collection()
768 {
769 return _perf_counters_collection;
770 }
771
772 void CephContext::enable_perf_counter()
773 {
774 PerfCountersBuilder plb(this, "cct", l_cct_first, l_cct_last);
775 plb.add_u64(l_cct_total_workers, "total_workers", "Total workers");
776 plb.add_u64(l_cct_unhealthy_workers, "unhealthy_workers", "Unhealthy workers");
777 PerfCounters *perf_tmp = plb.create_perf_counters();
778
779 ceph_spin_lock(&_cct_perf_lock);
780 assert(_cct_perf == NULL);
781 _cct_perf = perf_tmp;
782 ceph_spin_unlock(&_cct_perf_lock);
783
784 _perf_counters_collection->add(_cct_perf);
785 }
786
787 void CephContext::disable_perf_counter()
788 {
789 _perf_counters_collection->remove(_cct_perf);
790
791 ceph_spin_lock(&_cct_perf_lock);
792 delete _cct_perf;
793 _cct_perf = NULL;
794 ceph_spin_unlock(&_cct_perf_lock);
795 }
796
797 void CephContext::refresh_perf_values()
798 {
799 ceph_spin_lock(&_cct_perf_lock);
800 if (_cct_perf) {
801 _cct_perf->set(l_cct_total_workers, _heartbeat_map->get_total_workers());
802 _cct_perf->set(l_cct_unhealthy_workers, _heartbeat_map->get_unhealthy_workers());
803 }
804 ceph_spin_unlock(&_cct_perf_lock);
805 }
806
807 AdminSocket *CephContext::get_admin_socket()
808 {
809 return _admin_socket;
810 }
811
812 CryptoHandler *CephContext::get_crypto_handler(int type)
813 {
814 switch (type) {
815 case CEPH_CRYPTO_NONE:
816 return _crypto_none;
817 case CEPH_CRYPTO_AES:
818 return _crypto_aes;
819 default:
820 return NULL;
821 }
822 }