]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/mgr/DaemonState.h
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / mgr / DaemonState.h
index 7dad81593f654248bf380b43e230edad1669ab72..680d4a0cc2cf5112e13a1b322e67c92f7110ea9e 100644 (file)
 #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"
 
+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
@@ -66,10 +74,18 @@ class PerfCounterInstance
   {
     return buffer;
   }
+  const DataPoint& get_latest_data() const
+  {
+    return buffer.back();
+  }
   const boost::circular_buffer<AvgDataPoint> & get_data_avg() const
   {
     return avg_buffer;
   }
+  const AvgDataPoint& get_latest_data_avg() const
+  {
+    return avg_buffer.back();
+  }
   void push(utime_t t, uint64_t const &v);
   void push_avg(utime_t t, uint64_t const &s, uint64_t const &c);
 
@@ -92,7 +108,7 @@ class DaemonPerfCounters
   // The record of perf stat types, shared between daemons
   PerfCounterTypes &types;
 
-  DaemonPerfCounters(PerfCounterTypes &types_)
+  explicit DaemonPerfCounters(PerfCounterTypes &types_)
     : types(types_)
   {}
 
@@ -121,8 +137,11 @@ class DaemonState
   // The metadata (hostname, version, etc) sent from the daemon
   std::map<std::string, std::string> metadata;
 
+  /// device ids -> devname, derived from metadata[device_ids]
+  std::map<std::string,std::string> devices;
+
   // TODO: this can be generalized to other daemons
-  std::vector<OSDHealthMetric> osd_health_metrics;
+  std::vector<DaemonHealthMetric> daemon_health_metrics;
 
   // Ephemeral state
   bool service_daemon = false;
@@ -130,20 +149,88 @@ class DaemonState
   std::map<std::string, std::string> service_status;
   utime_t last_service_beacon;
 
+  // running config
+  std::map<std::string,std::map<int32_t,std::string>> config;
+
+  // mon config values we failed to set
+  std::map<std::string,std::string> ignored_mon_config;
+
+  // compiled-in config defaults (rarely used, so we leave them encoded!)
+  bufferlist config_defaults_bl;
+  std::map<std::string,std::string> config_defaults;
+
   // The perf counters received in MMgrReport messages
   DaemonPerfCounters perf_counters;
 
-  DaemonState(PerfCounterTypes &types_)
+  explicit DaemonState(PerfCounterTypes &types_)
     : 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;
+       }
+      }
+    }
+  }
+
+  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;
+  }
 };
 
 typedef std::shared_ptr<DaemonState> DaemonStatePtr;
 typedef std::map<DaemonKey, DaemonStatePtr> DaemonStateCollection;
 
 
+struct DeviceState : public RefCountedObject
+{
+  std::string devid;
+  std::set<pair<std::string,std::string>> devnames; ///< (server,devname)
+  std::set<DaemonKey> daemons;
 
+  std::map<string,string> metadata;  ///< persistent metadata
+
+  pair<utime_t,utime_t> life_expectancy;  ///< when device failure is expected
+  utime_t life_expectancy_stamp;          ///< when life expectency was recorded
+
+  DeviceState(const std::string& n)
+    : RefCountedObject(nullptr, 0),
+      devid(n) {}
+
+  void set_metadata(map<string,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;
+
+  /// true of we can be safely forgotten/removed from memory
+  bool empty() const {
+    return daemons.empty() && metadata.empty();
+  }
+
+  void dump(Formatter *f) const;
+  void print(ostream& out) const;
+};
+
+typedef boost::intrusive_ptr<DeviceState> DeviceStateRef;
 
 /**
  * Fuse the collection of per-daemon metadata from Ceph into
@@ -152,16 +239,30 @@ typedef std::map<DaemonKey, DaemonStatePtr> DaemonStateCollection;
  */
 class DaemonStateIndex
 {
-  private:
+private:
   mutable RWLock lock = {"DaemonStateIndex", true, true, true};
 
   std::map<std::string, DaemonStateCollection> by_server;
   DaemonStateCollection all;
   std::set<DaemonKey> updating;
 
+  std::map<std::string,DeviceStateRef> devices;
+
   void _erase(const DaemonKey& dmk);
 
-  public:
+  DeviceStateRef _get_or_create_device(const std::string& dev) {
+    auto p = devices.find(dev);
+    if (p != devices.end()) {
+      return p->second;
+    }
+    devices[dev] = new DeviceState(dev);
+    return devices[dev];
+  }
+  void _erase_device(DeviceStateRef d) {
+    devices.erase(d->devid);
+  }
+
+public:
   DaemonStateIndex() {}
 
   // FIXME: shouldn't really be public, maybe construct DaemonState
@@ -169,8 +270,11 @@ class DaemonStateIndex
   PerfCounterTypes types;
 
   void insert(DaemonStatePtr dm);
+  void _insert(DaemonStatePtr dm);
   bool exists(const DaemonKey &key) const;
   DaemonStatePtr get(const DaemonKey &key);
+  void rm(const DaemonKey &key);
+  void _rm(const DaemonKey &key);
 
   // Note that these return by value rather than reference to avoid
   // callers needing to stay in lock while using result.  Callers must
@@ -187,6 +291,71 @@ class DaemonStateIndex
     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);
+    auto p = devices.find(dev);
+    if (p == devices.end()) {
+      return false;
+    }
+    std::forward<Callback>(cb)(*p->second, std::forward<Args>(args)...);
+    return true;
+  }
+
+  template<typename Callback, typename...Args>
+  bool with_device_write(const std::string& dev,
+                        Callback&& cb, Args&&... args) {
+    RWLock::WLocker l(lock);
+    auto p = devices.find(dev);
+    if (p == devices.end()) {
+      return false;
+    }
+    std::forward<Callback>(cb)(*p->second, std::forward<Args>(args)...);
+    if (p->second->empty()) {
+      _erase_device(p->second);
+    }
+    return true;
+  }
+
+  template<typename Callback, typename...Args>
+  void with_device_create(const std::string& dev,
+                         Callback&& cb, Args&&... args) {
+    RWLock::WLocker 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);
+    for (auto& i : devices) {
+      std::forward<Callback>(cb)(*i.second, std::forward<Args>(args)...);
+    }
+  }
+
+  template<typename CallbackInitial, typename Callback, typename...Args>
+  void with_devices2(CallbackInitial&& cbi,  // with lock taken
+                    Callback&& cb,          // for each device
+                    Args&&... args) const {
+    RWLock::RLocker l(lock);
+    cbi();
+    for (auto& i : devices) {
+      std::forward<Callback>(cb)(*i.second, std::forward<Args>(args)...);
+    }
+  }
+
+  void list_devids_by_server(const std::string& server,
+                            std::set<std::string> *ls) {
+    auto m = get_by_server(server);
+    for (auto& i : m) {
+      std::lock_guard l(i.second->lock);
+      for (auto& j : i.second->devices) {
+       ls->insert(j.first);
+      }
+    }
+  }
+
   void notify_updating(const DaemonKey &k) {
     RWLock::WLocker l(lock);
     updating.insert(k);
@@ -200,6 +369,18 @@ class DaemonStateIndex
     return updating.count(k) > 0;
   }
 
+  void update_metadata(DaemonStatePtr state,
+                      const map<string,string>& meta) {
+    // remove and re-insert in case the device metadata changed
+    RWLock::WLocker l(lock);
+    _rm(state->key);
+    {
+      Mutex::Locker l2(state->lock);
+      state->set_metadata(meta);
+    }
+    _insert(state);
+  }
+
   /**
    * Remove state for all daemons of this type whose names are
    * not present in `names_exist`.  Use this function when you have