#include <set>
#include <boost/circular_buffer.hpp>
-#include "common/RWLock.h"
#include "include/str_map.h"
#include "msg/msg_types.h"
// 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
std::map<std::string, PerfCounterInstance> instances;
- void update(MMgrReport *report);
+ void update(const MMgrReport& report);
void clear()
{
class DaemonState
{
public:
- Mutex lock = {"DaemonState::lock"};
+ ceph::mutex lock = ceph::make_mutex("DaemonState::lock");
DaemonKey key;
/// device ids -> devname, derived from metadata[device_ids]
std::map<std::string,std::string> devices;
+ /// device ids -> by-path, derived from metadata[device_ids]
+ std::map<std::string,std::string> devices_bypath;
+
// TODO: this can be generalized to other daemons
std::vector<DaemonHealthMetric> daemon_health_metrics;
: perf_counters(types_)
{
}
-
- void set_metadata(const std::map<std::string,std::string>& m) {
- devices.clear();
- metadata = m;
- auto p = m.find("device_ids");
- if (p != m.end()) {
- map<std::string,std::string> devs;
- get_str_map(p->second, &devs, ",; ");
- for (auto& i : devs) {
- if (i.second.size()) { // skip blank ids
- devices[i.second] = i.first;
- }
- }
- }
- p = m.find("hostname");
- if (p != m.end()) {
- hostname = p->second;
- }
- }
-
- const std::map<std::string,std::string>& _get_config_defaults() {
- if (config_defaults.empty() &&
- config_defaults_bl.length()) {
- auto p = config_defaults_bl.cbegin();
- try {
- decode(config_defaults, p);
- } catch (buffer::error& e) {
- }
- }
- return config_defaults;
- }
+ void set_metadata(const std::map<std::string,std::string>& m);
+ const std::map<std::string,std::string>& _get_config_defaults();
};
typedef std::shared_ptr<DaemonState> DaemonStatePtr;
struct DeviceState : public RefCountedObject
{
std::string devid;
- std::set<pair<std::string,std::string>> devnames; ///< (server,devname)
+ /// (server,devname,path)
+ std::set<std::tuple<std::string,std::string,std::string>> attachments;
std::set<DaemonKey> daemons;
- std::map<string,string> metadata; ///< persistent metadata
+ std::map<std::string,std::string> metadata; ///< persistent metadata
- pair<utime_t,utime_t> life_expectancy; ///< when device failure is expected
+ std::pair<utime_t,utime_t> life_expectancy; ///< when device failure is expected
utime_t life_expectancy_stamp; ///< when life expectency was recorded
+ float wear_level = -1; ///< SSD wear level (negative if unknown)
- DeviceState(const std::string& n)
- : RefCountedObject(nullptr, 0),
- devid(n) {}
-
- void set_metadata(map<string,string>&& m);
+ void set_metadata(std::map<std::string,std::string>&& m);
void set_life_expectancy(utime_t from, utime_t to, utime_t now);
void rm_life_expectancy();
- string get_life_expectancy_str(utime_t now) const;
+ void set_wear_level(float wear);
+
+ std::string get_life_expectancy_str(utime_t now) const;
/// true of we can be safely forgotten/removed from memory
bool empty() const {
}
void dump(Formatter *f) const;
- void print(ostream& out) const;
-};
+ void print(std::ostream& out) const;
-typedef boost::intrusive_ptr<DeviceState> DeviceStateRef;
+private:
+ FRIEND_MAKE_REF(DeviceState);
+ DeviceState(const std::string& n) : devid(n) {}
+};
/**
* Fuse the collection of per-daemon metadata from Ceph into
class DaemonStateIndex
{
private:
- mutable RWLock lock = {"DaemonStateIndex", true, true, true};
+ mutable ceph::shared_mutex lock =
+ ceph::make_shared_mutex("DaemonStateIndex", true, true, true);
std::map<std::string, DaemonStateCollection> by_server;
DaemonStateCollection all;
std::set<DaemonKey> updating;
- std::map<std::string,DeviceStateRef> devices;
+ std::map<std::string,ceph::ref_t<DeviceState>> devices;
void _erase(const DaemonKey& dmk);
- DeviceStateRef _get_or_create_device(const std::string& dev) {
- auto p = devices.find(dev);
- if (p != devices.end()) {
- return p->second;
+ ceph::ref_t<DeviceState> _get_or_create_device(const std::string& dev) {
+ auto em = devices.try_emplace(dev, nullptr);
+ auto& d = em.first->second;
+ if (em.second) {
+ d = ceph::make_ref<DeviceState>(dev);
}
- devices[dev] = new DeviceState(dev);
- return devices[dev];
+ return d;
}
- void _erase_device(DeviceStateRef d) {
+ void _erase_device(const ceph::ref_t<DeviceState>& d) {
devices.erase(d->devid);
}
template<typename Callback, typename...Args>
auto with_daemons_by_server(Callback&& cb, Args&&... args) const ->
decltype(cb(by_server, std::forward<Args>(args)...)) {
- RWLock::RLocker l(lock);
+ std::shared_lock l{lock};
return std::forward<Callback>(cb)(by_server, std::forward<Args>(args)...);
}
template<typename Callback, typename...Args>
bool with_device(const std::string& dev,
Callback&& cb, Args&&... args) const {
- RWLock::RLocker l(lock);
+ std::shared_lock l{lock};
auto p = devices.find(dev);
if (p == devices.end()) {
return false;
template<typename Callback, typename...Args>
bool with_device_write(const std::string& dev,
Callback&& cb, Args&&... args) {
- RWLock::WLocker l(lock);
+ std::unique_lock l{lock};
auto p = devices.find(dev);
if (p == devices.end()) {
return false;
template<typename Callback, typename...Args>
void with_device_create(const std::string& dev,
Callback&& cb, Args&&... args) {
- RWLock::WLocker l(lock);
+ std::unique_lock l{lock};
auto d = _get_or_create_device(dev);
std::forward<Callback>(cb)(*d, std::forward<Args>(args)...);
}
template<typename Callback, typename...Args>
void with_devices(Callback&& cb, Args&&... args) const {
- RWLock::RLocker l(lock);
+ std::shared_lock l{lock};
for (auto& i : devices) {
std::forward<Callback>(cb)(*i.second, std::forward<Args>(args)...);
}
void with_devices2(CallbackInitial&& cbi, // with lock taken
Callback&& cb, // for each device
Args&&... args) const {
- RWLock::RLocker l(lock);
+ std::shared_lock l{lock};
cbi();
for (auto& i : devices) {
std::forward<Callback>(cb)(*i.second, std::forward<Args>(args)...);
}
void notify_updating(const DaemonKey &k) {
- RWLock::WLocker l(lock);
+ std::unique_lock l{lock};
updating.insert(k);
}
void clear_updating(const DaemonKey &k) {
- RWLock::WLocker l(lock);
+ std::unique_lock l{lock};
updating.erase(k);
}
bool is_updating(const DaemonKey &k) {
- RWLock::RLocker l(lock);
+ std::shared_lock l{lock};
return updating.count(k) > 0;
}
void update_metadata(DaemonStatePtr state,
- const map<string,string>& meta) {
+ const std::map<std::string,std::string>& meta) {
// remove and re-insert in case the device metadata changed
- RWLock::WLocker l(lock);
+ std::unique_lock l{lock};
_rm(state->key);
{
- Mutex::Locker l2(state->lock);
+ std::lock_guard l2{state->lock};
state->set_metadata(meta);
}
_insert(state);