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