1    	// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2    	// vim: ts=8 sw=2 smarttab ft=cpp
3    	
4    	#ifndef RGW_DMCLOCK_SCHEDULER_CTX_H
5    	#define RGW_DMCLOCK_SCHEDULER_CTX_H
6    	
7    	#include "common/perf_counters.h"
8    	#include "common/ceph_context.h"
9    	#include "common/config.h"
10   	#include "rgw_dmclock.h"
11   	
12   	namespace queue_counters {
13   	
14   	  enum {
15   	        l_first = 427150,
16   	        l_qlen,
17   	        l_cost,
18   	        l_res,
19   	        l_res_cost,
20   	        l_prio,
21   	        l_prio_cost,
22   	        l_limit,
23   	        l_limit_cost,
24   	        l_cancel,
25   	        l_cancel_cost,
26   	        l_res_latency,
27   	        l_prio_latency,
28   	        l_last,
29   	  };
30   	
31   	  PerfCountersRef build(CephContext *cct, const std::string& name);
32   	
33   	} // namespace queue_counters
34   	
35   	namespace throttle_counters {
36   	  enum {
37   	        l_first = 437219,
38   	        l_throttle,
39   	        l_last
40   	  };
41   	
42   	  PerfCountersRef build(CephContext *cct, const std::string& name);
43   	} // namespace throttle
44   	
45   	namespace rgw::dmclock {
46   	
47   	// the last client counter would be for global scheduler stats
48   	static constexpr auto counter_size = static_cast<size_t>(client_id::count) + 1;
49   	/// array of per-client counters to serve as GetClientCounters
50   	class ClientCounters {
51   	  std::array<PerfCountersRef, counter_size> clients;
52   	 public:
53   	  ClientCounters(CephContext *cct);
54   	
55   	  PerfCounters* operator()(client_id client) const {
56   	    return clients[static_cast<size_t>(client)].get();
57   	  }
58   	};
59   	
60   	class ThrottleCounters {
61   	  PerfCountersRef counters;
62   	public:
63   	  ThrottleCounters(CephContext* const cct,const std::string& name):
64   	    counters(throttle_counters::build(cct, name)) {}
65   	
66   	  PerfCounters* operator()() const {
67   	    return counters.get();
68   	  }
69   	};
70   	
71   	
72   	struct ClientSum {
73   	  uint64_t count{0};
74   	  Cost cost{0};
75   	};
76   	
77   	constexpr auto client_count = static_cast<size_t>(client_id::count);
78   	using ClientSums = std::array<ClientSum, client_count>;
79   	
80   	void inc(ClientSums& sums, client_id client, Cost cost);
81   	void on_cancel(PerfCounters *c, const ClientSum& sum);
82   	void on_process(PerfCounters* c, const ClientSum& rsum, const ClientSum& psum);
83   	
84   	
85   	class ClientConfig : public md_config_obs_t {
86   	  std::vector<ClientInfo> clients;
87   	
88   	  void update(const ConfigProxy &conf);
89   	
90   	public:
91   	  ClientConfig(CephContext *cct);
92   	
93   	  ClientInfo* operator()(client_id client);
94   	
95   	  const char** get_tracked_conf_keys() const override;
96   	  void handle_conf_change(const ConfigProxy& conf,
97   	                          const std::set<std::string>& changed) override;
98   	};
99   	
100  	class SchedulerCtx {
101  	public:
102  	  SchedulerCtx(CephContext* const cct) : sched_t(get_scheduler_t(cct))
103  	  {
104  	    if(sched_t == scheduler_t::dmclock) {
105  	      dmc_client_config = std::make_shared<ClientConfig>(cct);
106  	      // we don't have a move only cref std::function yet
107  	      dmc_client_counters = std::make_optional<ClientCounters>(cct);
108  	    }
109  	  }
110  	  // We need to construct a std::function from a NonCopyable object
111  	  ClientCounters& get_dmc_client_counters() { return dmc_client_counters.value(); }
(1) Event useless_type_qualifier_on_return_type: type qualifier on return type is meaningless
(2) Event caretline: ^
112  	  ClientConfig* const get_dmc_client_config() const { return dmc_client_config.get(); }
113  	private:
114  	  scheduler_t sched_t;
115  	  std::shared_ptr<ClientConfig> dmc_client_config {nullptr};
116  	  std::optional<ClientCounters> dmc_client_counters  {std::nullopt};
117  	};
118  	
119  	} // namespace rgw::dmclock
120  	
121  	#endif /* RGW_DMCLOCK_SCHEDULER_CTX_H */
122