class CInode;
struct MDRequestImpl;
+class DecayCounter;
#include "CInode.h"
#include "Capability.h"
l_mdssm_session_count,
l_mdssm_session_add,
l_mdssm_session_remove,
+ l_mdssm_session_open,
+ l_mdssm_session_stale,
+ l_mdssm_total_load,
+ l_mdssm_avg_load,
+ l_mdssm_avg_session_uptime,
l_mdssm_last,
};
+ additional dimension of 'importing' (with counter)
*/
+
+ using clock = ceph::coarse_mono_clock;
+ using time = ceph::coarse_mono_time;
+
+
enum {
STATE_CLOSED = 0,
STATE_OPENING = 1, // journaling open
// that appropriate mark_dirty calls follow.
std::deque<version_t> projected;
+ // request load average for this session
+ mutable DecayCounter load_avg;
+ DecayRate load_avg_rate;
+ // session start time -- used to track average session time
+ // note that this is initialized in the constructor rather
+ // than at the time of adding a session to the sessionmap
+ // as journal replay of sessionmap will not call add_session().
+ time birth_time;
public:
std::string get_human_name() const {return human_name;}
// Ephemeral state for tracking progress of capability recalls
- utime_t recalled_at; // When was I asked to SESSION_RECALL?
- utime_t last_recall_sent;
+ time recalled_at = time::min(); // When was I asked to SESSION_RECALL?
+ time last_recall_sent = time::min();
uint32_t recall_count; // How many caps was I asked to SESSION_RECALL?
uint32_t recall_release_count; // How many caps have I actually revoked?
}
bool is_importing() const { return importing_count > 0; }
+ void set_load_avg_decay_rate(double rate) {
+ assert(is_open() || is_stale());
+ load_avg_rate.set_halflife(rate);
+ }
+ uint64_t get_load_avg() const {
+ return (uint64_t)load_avg.get(ceph_clock_now(), load_avg_rate);
+ }
+ void hit_session() {
+ load_avg.hit(ceph_clock_now(), load_avg_rate);
+ }
+
+ double get_session_uptime() const {
+ chrono::duration<double> uptime = clock::now() - birth_time;
+ return uptime.count();
+ }
+
+ time get_birth_time() const {
+ return birth_time;
+ }
+
// -- caps --
private:
version_t cap_push_seq; // cap push seq #
public:
xlist<Capability*> caps; // inodes with caps; front=most recently used
xlist<ClientLease*> leases; // metadata leases to clients
- utime_t last_cap_renew;
+ time last_cap_renew = time::min();
public:
version_t inc_push_seq() { return ++cap_push_seq; }
Session() :
state(STATE_CLOSED), state_seq(0), importing_count(0),
- recall_count(0), recall_release_count(0),
- auth_caps(g_ceph_context),
+ birth_time(clock::now()), recall_count(0),
+ recall_release_count(0), auth_caps(g_ceph_context),
connection(NULL), item_session_list(this),
requests(0), // member_offset passed to front() manually
cap_push_seq(0),
info.clear_meta();
cap_push_seq = 0;
- last_cap_renew = utime_t();
-
+ last_cap_renew = time::min();
}
};
* encode/decode outside of live MDS instance.
*/
class SessionMapStore {
+public:
+ using clock = Session::clock;
+ using time = Session::time;
+
protected:
version_t version;
ceph::unordered_map<entity_name_t, Session*> session_map;
PerfCounters *logger;
+
+ // total request load avg
+ double decay_rate;
+ DecayCounter total_load_avg;
+ DecayRate total_load_avg_rate;
+
public:
mds_rank_t rank;
} else {
s = session_map[i.name] = new Session;
s->info.inst = i;
- s->last_cap_renew = ceph_clock_now();
+ s->last_cap_renew = Session::clock::now();
if (logger) {
logger->set(l_mdssm_session_count, session_map.size());
logger->inc(l_mdssm_session_add);
session_map.clear();
}
- SessionMapStore() : version(0), logger(nullptr), rank(MDS_RANK_NONE) {}
+ SessionMapStore()
+ : version(0), logger(nullptr),
+ decay_rate(g_conf->get_val<double>("mds_request_load_average_decay_rate")),
+ total_load_avg_rate(decay_rate), rank(MDS_RANK_NONE) {
+ }
virtual ~SessionMapStore() {};
};
map<int,xlist<Session*>* > by_state;
uint64_t set_state(Session *session, int state);
map<version_t, list<MDSInternalContextBase*> > commit_waiters;
+ void update_average_session_age();
explicit SessionMap(MDSRank *m) : mds(m),
projected(0), committing(0), committed(0),
*/
void save_if_dirty(const std::set<entity_name_t> &tgt_sessions,
MDSGatherBuilder *gather_bld);
+
+private:
+ time avg_birth_time = time::min();
+
+ uint64_t get_session_count_in_state(int state) {
+ return !is_any_state(state) ? 0 : by_state[state]->size();
+ }
+
+ void update_average_birth_time(const Session &s, bool added=true) {
+ uint32_t sessions = session_map.size();
+ time birth_time = s.get_birth_time();
+
+ if (sessions == 1) {
+ avg_birth_time = added ? birth_time : time::min();
+ return;
+ }
+
+ if (added) {
+ avg_birth_time = clock::time_point(
+ ((avg_birth_time - time::min()) / sessions) * (sessions - 1) +
+ (birth_time - time::min()) / sessions);
+ } else {
+ avg_birth_time = clock::time_point(
+ ((avg_birth_time - time::min()) / (sessions - 1)) * sessions -
+ (birth_time - time::min()) / (sessions - 1));
+ }
+ }
+
+public:
+ void hit_session(Session *session);
+ void handle_conf_change(const struct md_config_t *conf,
+ const std::set <std::string> &changed);
};
std::ostream& operator<<(std::ostream &out, const Session &s);