#include "PyModuleRegistry.h"
#include "ActivePyModules.h"
+#include "DaemonKey.h"
#include "DaemonServer.h"
#define dout_context g_ceph_context
f->open_array_section("services");
std::string ceph_version;
- for (const auto &i : dmc) {
- std::lock_guard l(i.second->lock);
- const auto &key = i.first;
- const std::string &str_type = key.first;
- const std::string &svc_name = key.second;
-
+ for (const auto &[key, state] : dmc) {
+ std::lock_guard l(state->lock);
// TODO: pick the highest version, and make sure that
// somewhere else (during health reporting?) we are
// indicating to the user if we see mixed versions
- auto ver_iter = i.second->metadata.find("ceph_version");
- if (ver_iter != i.second->metadata.end()) {
- ceph_version = i.second->metadata.at("ceph_version");
+ auto ver_iter = state->metadata.find("ceph_version");
+ if (ver_iter != state->metadata.end()) {
+ ceph_version = state->metadata.at("ceph_version");
}
f->open_object_section("service");
- f->dump_string("type", str_type);
- f->dump_string("id", svc_name);
+ f->dump_string("type", key.type);
+ f->dump_string("id", key.name);
f->close_section();
}
f->close_section();
const std::string &svc_type,
const std::string &svc_id)
{
- auto metadata = daemon_state.get(DaemonKey(svc_type, svc_id));
+ auto metadata = daemon_state.get(DaemonKey{svc_type, svc_id});
if (metadata == nullptr) {
derr << "Requested missing service " << svc_type << "." << svc_id << dendl;
Py_RETURN_NONE;
const std::string &svc_type,
const std::string &svc_id)
{
- auto metadata = daemon_state.get(DaemonKey(svc_type, svc_id));
+ auto metadata = daemon_state.get(DaemonKey{svc_type, svc_id});
if (metadata == nullptr) {
derr << "Requested missing service " << svc_type << "." << svc_id << dendl;
Py_RETURN_NONE;
auto dmc = daemon_state.get_by_service("osd");
PyEval_RestoreThread(tstate);
- for (const auto &i : dmc) {
- std::lock_guard l(i.second->lock);
- f.open_object_section(i.first.second.c_str());
- f.dump_string("hostname", i.second->hostname);
- for (const auto &j : i.second->metadata) {
- f.dump_string(j.first.c_str(), j.second);
+ for (const auto &[key, state] : dmc) {
+ std::lock_guard l(state->lock);
+ f.open_object_section(key.name.c_str());
+ f.dump_string("hostname", state->hostname);
+ for (const auto &[name, val] : state->metadata) {
+ f.dump_string(name.c_str(), val);
}
f.close_section();
}
PyFormatter f;
f.open_array_section(path.c_str());
- auto metadata = daemon_state.get(DaemonKey(svc_name, svc_id));
+ auto metadata = daemon_state.get(DaemonKey{svc_name, svc_id});
if (metadata) {
std::lock_guard l2(metadata->lock);
if (metadata->perf_counters.instances.count(path)) {
} else if (svc_id.empty()) {
daemons = daemon_state.get_by_service(svc_type);
} else {
- auto key = DaemonKey(svc_type, svc_id);
+ auto key = DaemonKey{svc_type, svc_id};
// so that the below can be a loop in all cases
auto got = daemon_state.get(key);
if (got != nullptr) {
PyFormatter f;
if (!daemons.empty()) {
- for (auto statepair : daemons) {
- auto key = statepair.first;
- auto state = statepair.second;
-
- std::ostringstream daemon_name;
- daemon_name << key.first << "." << key.second;
- f.open_object_section(daemon_name.str().c_str());
+ for (auto& [key, state] : daemons) {
+ f.open_object_section(ceph::to_string(key).c_str());
std::lock_guard l(state->lock);
for (auto ctr_inst_iter : state->perf_counters.instances) {
BaseMgrStandbyModule.cc
ClusterState.cc
DaemonHealthMetricCollector.cc
+ DaemonKey.cc
DaemonServer.cc
DaemonState.cc
Gil.cc
#include "include/types.h"
#include "DaemonHealthMetricCollector.h"
-
-
-ostream& operator<<(ostream& os,
- const DaemonHealthMetricCollector::DaemonKey& daemon) {
- return os << daemon.first << "." << daemon.second;
-}
-
-// define operator<<(ostream&, const vector<DaemonKey>&) after
-// ostream& operator<<(ostream&, const DaemonKey&), so that C++'s
-// ADL can use the former instead of using the generic one:
-// operator<<(ostream&, const std::pair<A,B>&)
-ostream& operator<<(
- ostream& os,
- const vector<DaemonHealthMetricCollector::DaemonKey>& daemons)
-{
- os << "[";
- for (auto d = daemons.begin(); d != daemons.end(); ++d) {
- if (d != daemons.begin()) os << ",";
- os << *d;
- }
- os << "]";
- return os;
-}
-
namespace {
class SlowOps final : public DaemonHealthMetricCollector {
#include <string>
#include "DaemonHealthMetric.h"
+#include "DaemonKey.h"
#include "mon/health_check.h"
class DaemonHealthMetricCollector {
public:
- using DaemonKey = std::pair<std::string, std::string>;
static std::unique_ptr<DaemonHealthMetricCollector> create(daemon_metric m);
void update(const DaemonKey& daemon, const DaemonHealthMetric& metric) {
if (_is_relevant(metric.get_type())) {
--- /dev/null
+#include "DaemonKey.h"
+
+std::pair<DaemonKey, bool> DaemonKey::parse(const std::string& s)
+{
+ auto p = s.find('.');
+ if (p == s.npos) {
+ return {{}, false};
+ } else {
+ return {DaemonKey{s.substr(0, p), s.substr(p + 1)}, true};
+ }
+}
+
+bool operator<(const DaemonKey& lhs, const DaemonKey& rhs)
+{
+ if (int cmp = lhs.type.compare(rhs.type); cmp < 0) {
+ return true;
+ } else if (cmp > 0) {
+ return false;
+ } else {
+ return lhs.name < rhs.name;
+ }
+}
+
+std::ostream& operator<<(std::ostream& os, const DaemonKey& key)
+{
+ return os << key.type << '.' << key.name;
+}
+
+namespace ceph {
+std::string to_string(const DaemonKey& key)
+{
+ return key.type + '.' + key.name;
+}
+}
+
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include <ostream>
+#include <string>
+#include <utility>
+
+// Unique reference to a daemon within a cluster
+struct DaemonKey
+{
+ std::string type; // service type, like "osd", "mon"
+ std::string name; // service id / name, like "1", "a"
+ static std::pair<DaemonKey, bool> parse(const std::string& s);
+};
+
+bool operator<(const DaemonKey& lhs, const DaemonKey& rhs);
+std::ostream& operator<<(std::ostream& os, const DaemonKey& key);
+
+namespace ceph {
+ std::string to_string(const DaemonKey& key);
+}
+
const std::string& daemon_name)
{
if (!service_name.empty()) {
- return DaemonKey(service_name, daemon_name);
+ return DaemonKey{service_name, daemon_name};
} else {
- return DaemonKey(ceph_entity_type_name(peer_type), daemon_name);
+ return DaemonKey{ceph_entity_type_name(peer_type), daemon_name};
}
}
-static bool key_from_string(
- const std::string& name,
- DaemonKey *out)
-{
- auto p = name.find('.');
- if (p == std::string::npos) {
- return false;
- }
- out->first = name.substr(0, p);
- out->second = name.substr(p + 1);
- return true;
-}
-
-bool DaemonServer::handle_open(MMgrOpen *m)
+bool DaemonServer::handle_open(MMgrOpen* m)
{
std::lock_guard l(lock);
void DaemonServer::update_task_status(DaemonKey key, MMgrReport *m) {
dout(10) << "got task status from " << key << dendl;
- auto p = pending_service_map.get_daemon(key.first, key.second);
+ auto p = pending_service_map.get_daemon(key.type, key.name);
if (!map_compare(p.first->task_status, *m->task_status)) {
p.first->task_status = *m->task_status;
pending_service_map_dirty = pending_service_map.epoch;
{
DaemonKey key;
if (!m->service_name.empty()) {
- key.first = m->service_name;
+ key.type = m->service_name;
} else {
- key.first = ceph_entity_type_name(m->get_connection()->get_peer_type());
+ key.type = ceph_entity_type_name(m->get_connection()->get_peer_type());
}
- key.second = m->daemon_name;
+ key.name = m->daemon_name;
dout(4) << "from " << m->get_connection() << " " << key << dendl;
<< dendl;
// issue metadata request in background
if (!daemon_state.is_updating(key) &&
- (key.first == "osd" || key.first == "mds" || key.first == "mon")) {
+ (key.type == "osd" || key.type == "mds" || key.type == "mon")) {
std::ostringstream oss;
auto c = new MetadataUpdate(daemon_state, key);
- if (key.first == "osd") {
+ if (key.type == "osd") {
oss << "{\"prefix\": \"osd metadata\", \"id\": "
- << key.second<< "}";
+ << key.name<< "}";
- } else if (key.first == "mds") {
+ } else if (key.type == "mds") {
c->set_default("addr", stringify(m->get_source_addr()));
oss << "{\"prefix\": \"mds metadata\", \"who\": \""
- << key.second << "\"}";
+ << key.name << "\"}";
- } else if (key.first == "mon") {
+ } else if (key.type == "mon") {
oss << "{\"prefix\": \"mon metadata\", \"id\": \""
- << key.second << "\"}";
+ << key.name << "\"}";
} else {
ceph_abort();
}
// if there are any schema updates, notify the python modules
if (!m->declare_types.empty() || !m->undeclare_types.empty()) {
- ostringstream oss;
- oss << key.first << '.' << key.second;
- py_modules.notify_all("perf_schema_update", oss.str());
+ py_modules.notify_all("perf_schema_update", ceph::to_string(key));
}
if (m->get_connection()->peer_is_osd()) {
f.reset(Formatter::create("json-pretty"));
// only include state from services that are in the persisted service map
f->open_object_section("service_status");
- for (auto& p : pending_service_map.services) {
- if (ServiceMap::is_normal_ceph_entity(p.first)) {
+ for (auto& [type, service] : pending_service_map.services) {
+ if (ServiceMap::is_normal_ceph_entity(type)) {
continue;
}
-
- f->open_object_section(p.first.c_str());
- for (auto& q : p.second.daemons) {
+ f->open_object_section(type.c_str());
+ for (auto& q : service.daemons) {
f->open_object_section(q.first.c_str());
- DaemonKey key(p.first, q.first);
+ DaemonKey key{type, q.first};
ceph_assert(daemon_state.exists(key));
auto daemon = daemon_state.get(key);
std::lock_guard l(daemon->lock);
prefix == "config show-with-defaults") {
string who;
cmd_getval(g_ceph_context, cmdctx->cmdmap, "who", who);
- int r = 0;
- auto dot = who.find('.');
- DaemonKey key;
- key.first = who.substr(0, dot);
- key.second = who.substr(dot + 1);
+ auto [key, valid] = DaemonKey::parse(who);
+ if (!valid) {
+ ss << "invalid daemon name: use <type>.<id>";
+ cmdctx->reply(-EINVAL, ss);
+ return true;
+ }
DaemonStatePtr daemon = daemon_state.get(key);
- string name;
if (!daemon) {
ss << "no config state for daemon " << who;
cmdctx->reply(-ENOENT, ss);
std::lock_guard l(daemon->lock);
+ int r = 0;
+ string name;
if (cmd_getval(g_ceph_context, cmdctx->cmdmap, "key", name)) {
// handle special options
if (name == "fsid") {
} else if (prefix == "device ls-by-daemon") {
string who;
cmd_getval(g_ceph_context, cmdctx->cmdmap, "who", who);
- DaemonKey k;
- if (!key_from_string(who, &k)) {
+ if (auto [k, valid] = DaemonKey::parse(who); !valid) {
ss << who << " is not a valid daemon name";
r = -EINVAL;
} else {
while (p != pending_service_map.services.end()) {
auto q = p->second.daemons.begin();
while (q != p->second.daemons.end()) {
- DaemonKey key(p->first, q->first);
+ DaemonKey key{p->first, q->first};
if (!daemon_state.exists(key)) {
if (ServiceMap::is_normal_ceph_entity(p->first)) {
dout(10) << "daemon " << key << " in service map but not in daemon state "
if (acc == accumulated.end()) {
auto collector = DaemonHealthMetricCollector::create(metric.get_type());
if (!collector) {
- derr << __func__ << " " << key.first << "." << key.second
+ derr << __func__ << " " << key
<< " sent me an unknown health metric: "
<< std::hex << static_cast<uint8_t>(metric.get_type())
<< std::dec << dendl;
// cull missing daemons, populate new ones
std::set<std::string> types;
- for (auto& p : pending_service_map.services) {
- if (ServiceMap::is_normal_ceph_entity(p.first)) {
+ for (auto& [type, service] : pending_service_map.services) {
+ if (ServiceMap::is_normal_ceph_entity(type)) {
continue;
}
- types.insert(p.first);
+ types.insert(type);
std::set<std::string> names;
- for (auto& q : p.second.daemons) {
+ for (auto& q : service.daemons) {
names.insert(q.first);
- DaemonKey key(p.first, q.first);
+ DaemonKey key{type, q.first};
if (!daemon_state.exists(key)) {
auto daemon = std::make_shared<DaemonState>(daemon_state.types);
daemon->key = key;
dout(10) << "added missing " << key << dendl;
}
}
- daemon_state.cull(p.first, names);
+ daemon_state.cull(type, names);
}
daemon_state.cull_services(types);
}
auto c = new MetadataUpdate(daemon_state, key);
// FIXME remove post-nautilus: include 'id' for luminous mons
oss << "{\"prefix\": \"mgr metadata\", \"who\": \""
- << key.second << "\", \"id\": \"" << key.second << "\"}";
+ << key.name << "\", \"id\": \"" << key.name << "\"}";
monc->start_mon_command({oss.str()}, {}, &c->outbl, &c->outs, c);
};
if (mgrmap.active_name.size()) {
- DaemonKey key("mgr", mgrmap.active_name);
+ DaemonKey key{"mgr", mgrmap.active_name};
have.insert(mgrmap.active_name);
if (!daemon_state.exists(key) && !daemon_state.is_updating(key)) {
md_update(key);
}
}
for (auto& i : mgrmap.standbys) {
- DaemonKey key("mgr", i.second.name);
+ DaemonKey key{"mgr", i.second.name};
have.insert(i.second.name);
if (!daemon_state.exists(key) && !daemon_state.is_updating(key)) {
md_update(key);
#include "DaemonState.h"
+#include <experimental/iterator>
+
#include "MgrSession.h"
#include "include/stringify.h"
#include "common/Formatter.h"
f->close_section();
f->open_array_section("daemons");
for (auto& i : daemons) {
- f->dump_string("daemon", to_string(i));
+ f->dump_stream("daemon") << i;
}
f->close_section();
if (life_expectancy.first != utime_t()) {
for (auto& i : devnames) {
out << "attachment " << i.first << ":" << i.second << "\n";
}
- set<string> d;
- for (auto& j : daemons) {
- d.insert(to_string(j));
- }
- out << "daemons " << d << "\n";
+ std::copy(std::begin(daemons), std::end(daemons),
+ std::experimental::make_ostream_joiner(out, ","));
+ out << '\n';
if (life_expectancy.first != utime_t()) {
out << "life_expectancy " << life_expectancy.first << " to "
<< life_expectancy.second
DaemonStateCollection result;
- for (const auto &i : all) {
- if (i.first.first == svc) {
- result[i.first] = i.second;
+ for (const auto& [key, state] : all) {
+ if (key.type == svc) {
+ result[key] = state;
}
}
auto end = all.end();
for (auto &i = begin; i != end; ++i) {
const auto& daemon_key = i->first;
- if (daemon_key.first != svc_name)
+ if (daemon_key.type != svc_name)
break;
- if (names_exist.count(daemon_key.second) == 0) {
- victims.push_back(daemon_key.second);
+ if (names_exist.count(daemon_key.name) == 0) {
+ victims.push_back(daemon_key.name);
}
}
// For PerfCounterType
#include "messages/MMgrReport.h"
+#include "DaemonKey.h"
namespace ceph {
class Formatter;
}
-// Unique reference to a daemon within a cluster
-typedef std::pair<std::string, std::string> DaemonKey;
-
-static inline std::string to_string(const DaemonKey& dk) {
- return dk.first + "." + dk.second;
-}
-
// An instance of a performance counter type, within
// a particular daemon.
class PerfCounterInstance
{
daemon_state.clear_updating(key);
if (r == 0) {
- if (key.first == "mds" || key.first == "osd" ||
- key.first == "mgr" || key.first == "mon") {
+ if (key.type == "mds" || key.type == "osd" ||
+ key.type == "mgr" || key.type == "mon") {
json_spirit::mValue json_result;
bool read_ok = json_spirit::read(
outbl.to_str(), json_result);
if (!read_ok) {
- dout(1) << "mon returned invalid JSON for "
- << key.first << "." << key.second << dendl;
+ dout(1) << "mon returned invalid JSON for " << key << dendl;
return;
}
if (json_result.type() != json_spirit::obj_type) {
- dout(1) << "mon returned valid JSON "
- << key.first << "." << key.second
+ dout(1) << "mon returned valid JSON " << key
<< " but not an object: '" << outbl.to_str() << "'" << dendl;
return;
}
- dout(4) << "mon returned valid metadata JSON for "
- << key.first << "." << key.second << dendl;
+ dout(4) << "mon returned valid metadata JSON for " << key << dendl;
json_spirit::mObject daemon_meta = json_result.get_obj();
// Skip daemon who doesn't have hostname yet
if (daemon_meta.count("hostname") == 0) {
- dout(1) << "Skipping incomplete metadata entry for "
- << key.first << "." << key.second << dendl;
+ dout(1) << "Skipping incomplete metadata entry for " << key << dendl;
return;
}
DaemonStatePtr state;
if (daemon_state.exists(key)) {
state = daemon_state.get(key);
- state->hostname = daemon_meta.at("hostname").get_str();
-
- if (key.first == "mds" || key.first == "mgr" || key.first == "mon") {
+ state->hostname = daemon_meta.at("hostname").get_str();
+ if (key.type == "mds" || key.type == "mgr" || key.type == "mon") {
daemon_meta.erase("name");
- } else if (key.first == "osd") {
+ } else if (key.type == "osd") {
daemon_meta.erase("id");
}
daemon_meta.erase("hostname");
- map<string,string> m;
+ map<string,string> m;
for (const auto &i : daemon_meta) {
m[i.first] = i.second.get_str();
}
state->key = key;
state->hostname = daemon_meta.at("hostname").get_str();
- if (key.first == "mds" || key.first == "mgr" || key.first == "mon") {
+ if (key.type == "mds" || key.type == "mgr" || key.type == "mon") {
daemon_meta.erase("name");
- } else if (key.first == "osd") {
+ } else if (key.type == "osd") {
daemon_meta.erase("id");
}
daemon_meta.erase("hostname");
ceph_abort();
}
} else {
- dout(1) << "mon failed to return metadata for "
- << key.first << "." << key.second << ": "
- << cpp_strerror(r) << dendl;
+ dout(1) << "mon failed to return metadata for " << key
+ << ": " << cpp_strerror(r) << dendl;
}
}
}
DaemonStatePtr dm = std::make_shared<DaemonState>(daemon_state.types);
- dm->key = DaemonKey("mds",
- daemon_meta.at("name").get_str());
+ dm->key = DaemonKey{"mds",
+ daemon_meta.at("name").get_str()};
dm->hostname = daemon_meta.at("hostname").get_str();
daemon_meta.erase("name");
}
DaemonStatePtr dm = std::make_shared<DaemonState>(daemon_state.types);
- dm->key = DaemonKey("mon",
- daemon_meta.at("name").get_str());
+ dm->key = DaemonKey{"mon",
+ daemon_meta.at("name").get_str()};
dm->hostname = daemon_meta.at("hostname").get_str();
daemon_meta.erase("name");
dout(4) << osd_metadata.at("hostname").get_str() << dendl;
DaemonStatePtr dm = std::make_shared<DaemonState>(daemon_state.types);
- dm->key = DaemonKey("osd",
- stringify(osd_metadata.at("id").get_int()));
+ dm->key = DaemonKey{"osd",
+ stringify(osd_metadata.at("id").get_int())};
dm->hostname = osd_metadata.at("hostname").get_str();
osd_metadata.erase("id");
names_exist.insert(stringify(osd_id));
// Consider whether to update the daemon metadata (new/restarted daemon)
- const auto k = DaemonKey("osd", stringify(osd_id));
+ bool update_meta = false;
+ const auto k = DaemonKey{"osd", std::to_string(osd_id)};
if (daemon_state.is_updating(k)) {
continue;
}
- bool update_meta = false;
if (daemon_state.exists(k)) {
if (osd_map.get_up_from(osd_id) == osd_map.get_epoch()) {
dout(4) << "Mgr::handle_osd_map: osd." << osd_id
// Remember which MDS exists so that we can cull any that don't
names_exist.insert(info.name);
- const auto k = DaemonKey("mds", info.name);
+ const auto k = DaemonKey{"mds", info.name};
if (daemon_state.is_updating(k)) {
continue;
}