]> git.proxmox.com Git - ceph.git/blame - ceph/src/osd/OpQueueItem.h
update download target update for octopus release
[ceph.git] / ceph / src / osd / OpQueueItem.h
CommitLineData
11fdf7f2
TL
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 Red Hat Inc.
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
15#pragma once
16
17#include <ostream>
18
19#include "include/types.h"
20#include "include/utime.h"
21#include "osd/OpRequest.h"
22#include "osd/PG.h"
23#include "PGPeeringEvent.h"
24
25class OSD;
26class OSDShard;
27
28class OpQueueItem {
29public:
30 class OrderLocker {
31 public:
32 using Ref = unique_ptr<OrderLocker>;
33 virtual void lock() = 0;
34 virtual void unlock() = 0;
35 virtual ~OrderLocker() {}
36 };
37 // Abstraction for operations queueable in the op queue
38 class OpQueueable {
39 public:
40 enum class op_type_t {
41 client_op,
42 peering_event,
43 bg_snaptrim,
44 bg_recovery,
45 bg_scrub,
46 bg_pg_delete
47 };
48 using Ref = std::unique_ptr<OpQueueable>;
49
50 /// Items with the same queue token will end up in the same shard
51 virtual uint32_t get_queue_token() const = 0;
52
53 /* Items will be dequeued and locked atomically w.r.t. other items with the
54 * same ordering token */
55 virtual const spg_t& get_ordering_token() const = 0;
56 virtual OrderLocker::Ref get_order_locker(PGRef pg) = 0;
57 virtual op_type_t get_op_type() const = 0;
58 virtual boost::optional<OpRequestRef> maybe_get_op() const {
59 return boost::none;
60 }
61
62 virtual uint64_t get_reserved_pushes() const {
63 return 0;
64 }
65
66 virtual bool is_peering() const {
67 return false;
68 }
69 virtual bool peering_requires_pg() const {
70 ceph_abort();
71 }
72 virtual const PGCreateInfo *creates_pg() const {
73 return nullptr;
74 }
75
76 virtual ostream &print(ostream &rhs) const = 0;
77
78 virtual void run(OSD *osd, OSDShard *sdata, PGRef& pg, ThreadPool::TPHandle &handle) = 0;
79 virtual ~OpQueueable() {}
80 friend ostream& operator<<(ostream& out, const OpQueueable& q) {
81 return q.print(out);
82 }
83
84 };
85
86private:
87 OpQueueable::Ref qitem;
88 int cost;
89 unsigned priority;
90 utime_t start_time;
91 uint64_t owner; ///< global id (e.g., client.XXX)
92 epoch_t map_epoch; ///< an epoch we expect the PG to exist in
93
94public:
95 OpQueueItem(
96 OpQueueable::Ref &&item,
97 int cost,
98 unsigned priority,
99 utime_t start_time,
100 uint64_t owner,
101 epoch_t e)
102 : qitem(std::move(item)),
103 cost(cost),
104 priority(priority),
105 start_time(start_time),
106 owner(owner),
107 map_epoch(e)
108 {}
109 OpQueueItem(OpQueueItem &&) = default;
110 OpQueueItem(const OpQueueItem &) = delete;
111 OpQueueItem &operator=(OpQueueItem &&) = default;
112 OpQueueItem &operator=(const OpQueueItem &) = delete;
113
114 OrderLocker::Ref get_order_locker(PGRef pg) {
115 return qitem->get_order_locker(pg);
116 }
117 uint32_t get_queue_token() const {
118 return qitem->get_queue_token();
119 }
120 const spg_t& get_ordering_token() const {
121 return qitem->get_ordering_token();
122 }
123 using op_type_t = OpQueueable::op_type_t;
124 OpQueueable::op_type_t get_op_type() const {
125 return qitem->get_op_type();
126 }
127 boost::optional<OpRequestRef> maybe_get_op() const {
128 return qitem->maybe_get_op();
129 }
130 uint64_t get_reserved_pushes() const {
131 return qitem->get_reserved_pushes();
132 }
133 void run(OSD *osd, OSDShard *sdata,PGRef& pg, ThreadPool::TPHandle &handle) {
134 qitem->run(osd, sdata, pg, handle);
135 }
136 unsigned get_priority() const { return priority; }
137 int get_cost() const { return cost; }
138 utime_t get_start_time() const { return start_time; }
139 uint64_t get_owner() const { return owner; }
140 epoch_t get_map_epoch() const { return map_epoch; }
141
142 bool is_peering() const {
143 return qitem->is_peering();
144 }
145
146 const PGCreateInfo *creates_pg() const {
147 return qitem->creates_pg();
148 }
149
150 bool peering_requires_pg() const {
151 return qitem->peering_requires_pg();
152 }
153
154 friend ostream& operator<<(ostream& out, const OpQueueItem& item) {
155 out << "OpQueueItem("
156 << item.get_ordering_token() << " " << *item.qitem
157 << " prio " << item.get_priority()
158 << " cost " << item.get_cost()
159 << " e" << item.get_map_epoch();
160 if (item.get_reserved_pushes()) {
161 out << " reserved_pushes " << item.get_reserved_pushes();
162 }
163 return out << ")";
164 }
165}; // class OpQueueItem
166
167/// Implements boilerplate for operations queued for the pg lock
168class PGOpQueueable : public OpQueueItem::OpQueueable {
169 spg_t pgid;
170protected:
171 const spg_t& get_pgid() const {
172 return pgid;
173 }
174public:
175 explicit PGOpQueueable(spg_t pg) : pgid(pg) {}
176 uint32_t get_queue_token() const override final {
177 return get_pgid().ps();
178 }
179
180 const spg_t& get_ordering_token() const override final {
181 return get_pgid();
182 }
183
184 OpQueueItem::OrderLocker::Ref get_order_locker(PGRef pg) override final {
185 class Locker : public OpQueueItem::OrderLocker {
186 PGRef pg;
187 public:
188 explicit Locker(PGRef pg) : pg(pg) {}
189 void lock() override final {
190 pg->lock();
191 }
192 void unlock() override final {
193 pg->unlock();
194 }
195 };
196 return OpQueueItem::OrderLocker::Ref(
197 new Locker(pg));
198 }
199};
200
201class PGOpItem : public PGOpQueueable {
202 OpRequestRef op;
203public:
204 PGOpItem(spg_t pg, OpRequestRef op) : PGOpQueueable(pg), op(std::move(op)) {}
205 op_type_t get_op_type() const override final {
206 return op_type_t::client_op;
207 }
208 ostream &print(ostream &rhs) const override final {
209 return rhs << "PGOpItem(op=" << *(op->get_req()) << ")";
210 }
211 boost::optional<OpRequestRef> maybe_get_op() const override final {
212 return op;
213 }
214 void run(OSD *osd, OSDShard *sdata, PGRef& pg, ThreadPool::TPHandle &handle) override final;
215};
216
217class PGPeeringItem : public PGOpQueueable {
218 PGPeeringEventRef evt;
219public:
220 PGPeeringItem(spg_t pg, PGPeeringEventRef e) : PGOpQueueable(pg), evt(e) {}
221 op_type_t get_op_type() const override final {
222 return op_type_t::peering_event;
223 }
224 ostream &print(ostream &rhs) const override final {
225 return rhs << "PGPeeringEvent(" << evt->get_desc() << ")";
226 }
227 void run(OSD *osd, OSDShard *sdata, PGRef& pg, ThreadPool::TPHandle &handle) override final;
228 bool is_peering() const override {
229 return true;
230 }
231 bool peering_requires_pg() const override {
232 return evt->requires_pg;
233 }
234 const PGCreateInfo *creates_pg() const override {
235 return evt->create_info.get();
236 }
237};
238
239class PGSnapTrim : public PGOpQueueable {
240 epoch_t epoch_queued;
241public:
242 PGSnapTrim(
243 spg_t pg,
244 epoch_t epoch_queued)
245 : PGOpQueueable(pg), epoch_queued(epoch_queued) {}
246 op_type_t get_op_type() const override final {
247 return op_type_t::bg_snaptrim;
248 }
249 ostream &print(ostream &rhs) const override final {
250 return rhs << "PGSnapTrim(pgid=" << get_pgid()
251 << "epoch_queued=" << epoch_queued
252 << ")";
253 }
254 void run(
255 OSD *osd, OSDShard *sdata, PGRef& pg, ThreadPool::TPHandle &handle) override final;
256};
257
258class PGScrub : public PGOpQueueable {
259 epoch_t epoch_queued;
260public:
261 PGScrub(
262 spg_t pg,
263 epoch_t epoch_queued)
264 : PGOpQueueable(pg), epoch_queued(epoch_queued) {}
265 op_type_t get_op_type() const override final {
266 return op_type_t::bg_scrub;
267 }
268 ostream &print(ostream &rhs) const override final {
269 return rhs << "PGScrub(pgid=" << get_pgid()
270 << "epoch_queued=" << epoch_queued
271 << ")";
272 }
273 void run(
274 OSD *osd, OSDShard *sdata, PGRef& pg, ThreadPool::TPHandle &handle) override final;
275};
276
277class PGRecovery : public PGOpQueueable {
278 epoch_t epoch_queued;
279 uint64_t reserved_pushes;
280public:
281 PGRecovery(
282 spg_t pg,
283 epoch_t epoch_queued,
284 uint64_t reserved_pushes)
285 : PGOpQueueable(pg),
286 epoch_queued(epoch_queued),
287 reserved_pushes(reserved_pushes) {}
288 op_type_t get_op_type() const override final {
289 return op_type_t::bg_recovery;
290 }
291 virtual ostream &print(ostream &rhs) const override final {
292 return rhs << "PGRecovery(pgid=" << get_pgid()
293 << "epoch_queued=" << epoch_queued
294 << "reserved_pushes=" << reserved_pushes
295 << ")";
296 }
297 virtual uint64_t get_reserved_pushes() const override final {
298 return reserved_pushes;
299 }
300 virtual void run(
301 OSD *osd, OSDShard *sdata, PGRef& pg, ThreadPool::TPHandle &handle) override final;
302};
303
304class PGRecoveryContext : public PGOpQueueable {
305 unique_ptr<GenContext<ThreadPool::TPHandle&>> c;
306 epoch_t epoch;
307public:
308 PGRecoveryContext(spg_t pgid,
309 GenContext<ThreadPool::TPHandle&> *c, epoch_t epoch)
310 : PGOpQueueable(pgid),
311 c(c), epoch(epoch) {}
312 op_type_t get_op_type() const override final {
313 return op_type_t::bg_recovery;
314 }
315 ostream &print(ostream &rhs) const override final {
316 return rhs << "PGRecoveryContext(pgid=" << get_pgid()
317 << " c=" << c.get() << " epoch=" << epoch
318 << ")";
319 }
320 void run(
321 OSD *osd, OSDShard *sdata, PGRef& pg, ThreadPool::TPHandle &handle) override final;
322};
323
324class PGDelete : public PGOpQueueable {
325 epoch_t epoch_queued;
326public:
327 PGDelete(
328 spg_t pg,
329 epoch_t epoch_queued)
330 : PGOpQueueable(pg),
331 epoch_queued(epoch_queued) {}
332 op_type_t get_op_type() const override final {
333 return op_type_t::bg_pg_delete;
334 }
335 ostream &print(ostream &rhs) const override final {
336 return rhs << "PGDelete(" << get_pgid()
337 << " e" << epoch_queued
338 << ")";
339 }
340 void run(
341 OSD *osd, OSDShard *sdata, PGRef& pg, ThreadPool::TPHandle &handle) override final;
342};