Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / mgr / DaemonState.h
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) 2016 John Spray <john.spray@redhat.com>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software
11  * Foundation.  See file COPYING.
12  */
13
14 #ifndef DAEMON_STATE_H_
15 #define DAEMON_STATE_H_
16
17 #include <map>
18 #include <string>
19 #include <memory>
20 #include <set>
21 #include <boost/circular_buffer.hpp>
22
23 #include "common/RWLock.h"
24
25 #include "msg/msg_types.h"
26
27 // For PerfCounterType
28 #include "messages/MMgrReport.h"
29
30
31 // Unique reference to a daemon within a cluster
32 typedef std::pair<std::string, std::string> DaemonKey;
33
34 // An instance of a performance counter type, within
35 // a particular daemon.
36 class PerfCounterInstance
37 {
38   class DataPoint
39   {
40     public:
41     utime_t t;
42     uint64_t v;
43     DataPoint(utime_t t_, uint64_t v_)
44       : t(t_), v(v_)
45     {}
46   };
47
48   boost::circular_buffer<DataPoint> buffer;
49   uint64_t get_current() const;
50
51   public:
52   const boost::circular_buffer<DataPoint> & get_data() const
53   {
54     return buffer;
55   }
56   void push(utime_t t, uint64_t const &v);
57   PerfCounterInstance()
58     : buffer(20) {}
59 };
60
61
62 typedef std::map<std::string, PerfCounterType> PerfCounterTypes;
63
64 // Performance counters for one daemon
65 class DaemonPerfCounters
66 {
67   public:
68   // The record of perf stat types, shared between daemons
69   PerfCounterTypes &types;
70
71   DaemonPerfCounters(PerfCounterTypes &types_)
72     : types(types_)
73   {}
74
75   std::map<std::string, PerfCounterInstance> instances;
76
77   void update(MMgrReport *report);
78
79   void clear()
80   {
81     instances.clear();
82   }
83 };
84
85 // The state that we store about one daemon
86 class DaemonState
87 {
88   public:
89   Mutex lock = {"DaemonState::lock"};
90
91   DaemonKey key;
92
93   // The hostname where daemon was last seen running (extracted
94   // from the metadata)
95   std::string hostname;
96
97   // The metadata (hostname, version, etc) sent from the daemon
98   std::map<std::string, std::string> metadata;
99
100   // Ephemeral state
101   bool service_daemon = false;
102   utime_t service_status_stamp;
103   std::map<std::string, std::string> service_status;
104   utime_t last_service_beacon;
105
106   // The perf counters received in MMgrReport messages
107   DaemonPerfCounters perf_counters;
108
109   DaemonState(PerfCounterTypes &types_)
110     : perf_counters(types_)
111   {
112   }
113 };
114
115 typedef std::shared_ptr<DaemonState> DaemonStatePtr;
116 typedef std::map<DaemonKey, DaemonStatePtr> DaemonStateCollection;
117
118
119
120
121 /**
122  * Fuse the collection of per-daemon metadata from Ceph into
123  * a view that can be queried by service type, ID or also
124  * by server (aka fqdn).
125  */
126 class DaemonStateIndex
127 {
128   private:
129   mutable RWLock lock = {"DaemonStateIndex", true, true, true};
130
131   std::map<std::string, DaemonStateCollection> by_server;
132   DaemonStateCollection all;
133   std::set<DaemonKey> updating;
134
135   void _erase(const DaemonKey& dmk);
136
137   public:
138   DaemonStateIndex() {}
139
140   // FIXME: shouldn't really be public, maybe construct DaemonState
141   // objects internally to avoid this.
142   PerfCounterTypes types;
143
144   void insert(DaemonStatePtr dm);
145   bool exists(const DaemonKey &key) const;
146   DaemonStatePtr get(const DaemonKey &key);
147
148   // Note that these return by value rather than reference to avoid
149   // callers needing to stay in lock while using result.  Callers must
150   // still take the individual DaemonState::lock on each entry though.
151   DaemonStateCollection get_by_server(const std::string &hostname) const;
152   DaemonStateCollection get_by_service(const std::string &svc_name) const;
153   DaemonStateCollection get_all() const {return all;}
154
155   template<typename Callback, typename...Args>
156   auto with_daemons_by_server(Callback&& cb, Args&&... args) const ->
157     decltype(cb(by_server, std::forward<Args>(args)...)) {
158     RWLock::RLocker l(lock);
159     
160     return std::forward<Callback>(cb)(by_server, std::forward<Args>(args)...);
161   }
162
163   void notify_updating(const DaemonKey &k) {
164     RWLock::WLocker l(lock);
165     updating.insert(k);
166   }
167   void clear_updating(const DaemonKey &k) {
168     RWLock::WLocker l(lock);
169     updating.erase(k);
170   }
171   bool is_updating(const DaemonKey &k) {
172     RWLock::RLocker l(lock);
173     return updating.count(k) > 0;
174   }
175
176   /**
177    * Remove state for all daemons of this type whose names are
178    * not present in `names_exist`.  Use this function when you have
179    * a cluster map and want to ensure that anything absent in the map
180    * is also absent in this class.
181    */
182   void cull(const std::string& svc_name,
183             const std::set<std::string>& names_exist);
184 };
185
186 #endif
187