]> git.proxmox.com Git - ceph.git/blob - ceph/src/crimson/osd/osd_operation.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / crimson / osd / osd_operation.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #pragma once
5
6 #include "crimson/common/operation.h"
7 #include "crimson/osd/pg_interval_interrupt_condition.h"
8 #include "crimson/osd/scheduler/scheduler.h"
9 #include "osd/osd_types.h"
10
11 namespace crimson::osd {
12
13 enum class OperationTypeCode {
14 client_request = 0,
15 peering_event,
16 compound_peering_request,
17 pg_advance_map,
18 pg_creation,
19 replicated_request,
20 background_recovery,
21 background_recovery_sub,
22 internal_client_request,
23 last_op
24 };
25
26 static constexpr const char* const OP_NAMES[] = {
27 "client_request",
28 "peering_event",
29 "compound_peering_request",
30 "pg_advance_map",
31 "pg_creation",
32 "replicated_request",
33 "background_recovery",
34 "background_recovery_sub",
35 "internal_client_request",
36 };
37
38 // prevent the addition of OperationTypeCode-s with no matching OP_NAMES entry:
39 static_assert(
40 (sizeof(OP_NAMES)/sizeof(OP_NAMES[0])) ==
41 static_cast<int>(OperationTypeCode::last_op));
42
43 struct InterruptibleOperation : Operation {
44 template <typename ValuesT = void>
45 using interruptible_future =
46 ::crimson::interruptible::interruptible_future<
47 ::crimson::osd::IOInterruptCondition, ValuesT>;
48 using interruptor =
49 ::crimson::interruptible::interruptor<
50 ::crimson::osd::IOInterruptCondition>;
51 };
52
53 template <typename T>
54 class OperationT : public InterruptibleOperation {
55 public:
56 static constexpr const char *type_name = OP_NAMES[static_cast<int>(T::type)];
57 using IRef = boost::intrusive_ptr<T>;
58
59 unsigned get_type() const final {
60 return static_cast<unsigned>(T::type);
61 }
62
63 const char *get_type_name() const final {
64 return T::type_name;
65 }
66
67 virtual ~OperationT() = default;
68
69 private:
70 virtual void dump_detail(ceph::Formatter *f) const = 0;
71 };
72
73 /**
74 * Maintains a set of lists of all active ops.
75 */
76 using OSDOperationRegistry = OperationRegistryT<
77 static_cast<size_t>(OperationTypeCode::last_op)
78 >;
79
80 /**
81 * Throttles set of currently running operations
82 *
83 * Very primitive currently, assumes all ops are equally
84 * expensive and simply limits the number that can be
85 * concurrently active.
86 */
87 class OperationThrottler : public Blocker,
88 private md_config_obs_t {
89 public:
90 OperationThrottler(ConfigProxy &conf);
91
92 const char** get_tracked_conf_keys() const final;
93 void handle_conf_change(const ConfigProxy& conf,
94 const std::set<std::string> &changed) final;
95 void update_from_config(const ConfigProxy &conf);
96
97 template <typename F>
98 auto with_throttle(
99 OperationRef op,
100 crimson::osd::scheduler::params_t params,
101 F &&f) {
102 if (!max_in_progress) return f();
103 auto fut = acquire_throttle(params);
104 return op->with_blocking_future(std::move(fut))
105 .then(std::forward<F>(f))
106 .then([this](auto x) {
107 release_throttle();
108 return x;
109 });
110 }
111
112 template <typename F>
113 seastar::future<> with_throttle_while(
114 OperationRef op,
115 crimson::osd::scheduler::params_t params,
116 F &&f) {
117 return with_throttle(op, params, f).then([this, params, op, f](bool cont) {
118 if (cont)
119 return with_throttle_while(op, params, f);
120 else
121 return seastar::make_ready_future<>();
122 });
123 }
124
125 private:
126 void dump_detail(Formatter *f) const final;
127 const char *get_type_name() const final {
128 return "OperationThrottler";
129 }
130
131 private:
132 crimson::osd::scheduler::SchedulerRef scheduler;
133
134 uint64_t max_in_progress = 0;
135 uint64_t in_progress = 0;
136
137 uint64_t pending = 0;
138
139 void wake();
140
141 blocking_future<> acquire_throttle(
142 crimson::osd::scheduler::params_t params);
143
144 void release_throttle();
145 };
146
147 }