summaryrefslogtreecommitdiffstats
path: root/src/rgw/rgw_dmclock_scheduler_ctx.h
blob: f27b81c266e55f642239ee7b0a20e25b3f72b079 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab ft=cpp

#pragma once

#include "common/perf_counters.h"
#include "common/ceph_context.h"
#include "common/config.h"
#include "rgw_dmclock.h"

namespace queue_counters {

  enum {
        l_first = 427150,
        l_qlen,
        l_cost,
        l_res,
        l_res_cost,
        l_prio,
        l_prio_cost,
        l_limit,
        l_limit_cost,
        l_cancel,
        l_cancel_cost,
        l_res_latency,
        l_prio_latency,
        l_last,
  };

  PerfCountersRef build(CephContext *cct, const std::string& name);

} // namespace queue_counters

namespace throttle_counters {
  enum {
        l_first = 437219,
        l_throttle,
        l_outstanding,
        l_last
  };

  PerfCountersRef build(CephContext *cct, const std::string& name);
} // namespace throttle

namespace rgw::dmclock {

// the last client counter would be for global scheduler stats
static constexpr auto counter_size = static_cast<size_t>(client_id::count) + 1;
/// array of per-client counters to serve as GetClientCounters
class ClientCounters {
  std::array<PerfCountersRef, counter_size> clients;
 public:
  ClientCounters(CephContext *cct);

  PerfCounters* operator()(client_id client) const {
    return clients[static_cast<size_t>(client)].get();
  }
};

class ThrottleCounters {
  PerfCountersRef counters;
public:
  ThrottleCounters(CephContext* const cct,const std::string& name):
    counters(throttle_counters::build(cct, name)) {}

  PerfCounters* operator()() const {
    return counters.get();
  }
};


struct ClientSum {
  uint64_t count{0};
  Cost cost{0};
};

constexpr auto client_count = static_cast<size_t>(client_id::count);
using ClientSums = std::array<ClientSum, client_count>;

void inc(ClientSums& sums, client_id client, Cost cost);
void on_cancel(PerfCounters *c, const ClientSum& sum);
void on_process(PerfCounters* c, const ClientSum& rsum, const ClientSum& psum);


class ClientConfig : public md_config_obs_t {
  std::vector<ClientInfo> clients;

  void update(const ConfigProxy &conf);

public:
  ClientConfig(CephContext *cct);

  ClientInfo* operator()(client_id client);

  const char** get_tracked_conf_keys() const override;
  void handle_conf_change(const ConfigProxy& conf,
                          const std::set<std::string>& changed) override;
};

class SchedulerCtx {
public:
  SchedulerCtx(CephContext* const cct) : sched_t(get_scheduler_t(cct))
  {
    if(sched_t == scheduler_t::dmclock) {
      dmc_client_config = std::make_shared<ClientConfig>(cct);
      // we don't have a move only cref std::function yet
      dmc_client_counters = std::make_optional<ClientCounters>(cct);
    }
  }
  // We need to construct a std::function from a NonCopyable object
  ClientCounters& get_dmc_client_counters() { return dmc_client_counters.value(); }
  ClientConfig* const get_dmc_client_config() const { return dmc_client_config.get(); }
private:
  scheduler_t sched_t;
  std::shared_ptr<ClientConfig> dmc_client_config {nullptr};
  std::optional<ClientCounters> dmc_client_counters  {std::nullopt};
};

} // namespace rgw::dmclock