]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_aio_throttle.h
import ceph 15.2.10
[ceph.git] / ceph / src / rgw / rgw_aio_throttle.h
CommitLineData
11fdf7f2 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
11fdf7f2
TL
3
4/*
5 * Ceph - scalable distributed file system
6 *
7 * Copyright (C) 2018 Red Hat, Inc.
8 *
9 * This is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License version 2.1, as published by the Free Software
12 * Foundation. See file COPYING.
13 *
14 */
15
16#pragma once
17
18#include "include/rados/librados_fwd.hpp"
19#include <memory>
20#include "common/ceph_mutex.h"
9f95a23c
TL
21#include "common/async/completion.h"
22#include "common/async/yield_context.h"
11fdf7f2
TL
23#include "services/svc_rados.h"
24#include "rgw_aio.h"
25
26namespace rgw {
27
9f95a23c 28class Throttle {
11fdf7f2
TL
29 protected:
30 const uint64_t window;
31 uint64_t pending_size = 0;
32
9f95a23c
TL
33 AioResultList pending;
34 AioResultList completed;
35
11fdf7f2
TL
36 bool is_available() const { return pending_size <= window; }
37 bool has_completion() const { return !completed.empty(); }
38 bool is_drained() const { return pending.empty(); }
39
11fdf7f2
TL
40 enum class Wait { None, Available, Completion, Drained };
41 Wait waiter = Wait::None;
42
43 bool waiter_ready() const;
44
11fdf7f2 45 public:
9f95a23c 46 Throttle(uint64_t window) : window(window) {}
11fdf7f2 47
9f95a23c 48 ~Throttle() {
11fdf7f2
TL
49 // must drain before destructing
50 ceph_assert(pending.empty());
51 ceph_assert(completed.empty());
52 }
9f95a23c
TL
53};
54
55// a throttle for aio operations. all public functions must be called from
56// the same thread
57class BlockingAioThrottle final : public Aio, private Throttle {
58 ceph::mutex mutex = ceph::make_mutex("AioThrottle");
59 ceph::condition_variable cond;
60
61 struct Pending : AioResultEntry {
62 BlockingAioThrottle *parent = nullptr;
63 uint64_t cost = 0;
64 librados::AioCompletion *completion = nullptr;
65 };
66 public:
67 BlockingAioThrottle(uint64_t window) : Throttle(window) {}
68
69 AioResultList get(const RGWSI_RADOS::Obj& obj, OpFunc&& f,
70 uint64_t cost, uint64_t id) override final;
71
72 void put(AioResult& r) override final;
73
74 AioResultList poll() override final;
75
76 AioResultList wait() override final;
11fdf7f2 77
9f95a23c
TL
78 AioResultList drain() override final;
79};
80
81#ifdef HAVE_BOOST_CONTEXT
82// a throttle that yields the coroutine instead of blocking. all public
83// functions must be called within the coroutine strand
84class YieldingAioThrottle final : public Aio, private Throttle {
85 boost::asio::io_context& context;
86 spawn::yield_context yield;
87 struct Handler;
88
89 // completion callback associated with the waiter
90 using Completion = ceph::async::Completion<void(boost::system::error_code)>;
91 std::unique_ptr<Completion> completion;
11fdf7f2 92
9f95a23c
TL
93 template <typename CompletionToken>
94 auto async_wait(CompletionToken&& token);
11fdf7f2 95
9f95a23c
TL
96 struct Pending : AioResultEntry { uint64_t cost = 0; };
97
98 public:
99 YieldingAioThrottle(uint64_t window, boost::asio::io_context& context,
100 spawn::yield_context yield)
101 : Throttle(window), context(context), yield(yield)
102 {}
11fdf7f2 103
9f95a23c
TL
104 AioResultList get(const RGWSI_RADOS::Obj& obj, OpFunc&& f,
105 uint64_t cost, uint64_t id) override final;
11fdf7f2 106
9f95a23c
TL
107 void put(AioResult& r) override final;
108
109 AioResultList poll() override final;
110
111 AioResultList wait() override final;
112
113 AioResultList drain() override final;
11fdf7f2 114};
9f95a23c
TL
115#endif // HAVE_BOOST_CONTEXT
116
117// return a smart pointer to Aio
118inline auto make_throttle(uint64_t window_size, optional_yield y)
119{
120#ifdef HAVE_BOOST_CONTEXT
121 std::unique_ptr<Aio> aio;
122 if (y) {
123 aio = std::make_unique<YieldingAioThrottle>(window_size,
124 y.get_io_context(),
125 y.get_yield_context());
126 } else {
127 aio = std::make_unique<BlockingAioThrottle>(window_size);
128 }
129 return aio;
130#else
131 return std::make_optional<BlockingAioThrottle>(window_size);
132#endif
133}
11fdf7f2
TL
134
135} // namespace rgw