1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
5 * Ceph - scalable distributed file system
7 * Copyright (C) 2018 Red Hat, Inc.
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.
18 #include "include/rados/librados_fwd.hpp"
20 #include "common/ceph_mutex.h"
21 #include "common/async/completion.h"
22 #include "common/async/yield_context.h"
23 #include "services/svc_rados.h"
30 const uint64_t window
;
31 uint64_t pending_size
= 0;
33 AioResultList pending
;
34 AioResultList completed
;
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(); }
40 enum class Wait
{ None
, Available
, Completion
, Drained
};
41 Wait waiter
= Wait::None
;
43 bool waiter_ready() const;
46 Throttle(uint64_t window
) : window(window
) {}
49 // must drain before destructing
50 ceph_assert(pending
.empty());
51 ceph_assert(completed
.empty());
55 // a throttle for aio operations. all public functions must be called from
57 class BlockingAioThrottle final
: public Aio
, private Throttle
{
58 ceph::mutex mutex
= ceph::make_mutex("AioThrottle");
59 ceph::condition_variable cond
;
61 struct Pending
: AioResultEntry
{
62 BlockingAioThrottle
*parent
= nullptr;
64 librados::AioCompletion
*completion
= nullptr;
67 BlockingAioThrottle(uint64_t window
) : Throttle(window
) {}
69 virtual ~BlockingAioThrottle() override
{};
71 AioResultList
get(const RGWSI_RADOS::Obj
& obj
, OpFunc
&& f
,
72 uint64_t cost
, uint64_t id
) override final
;
74 void put(AioResult
& r
) override final
;
76 AioResultList
poll() override final
;
78 AioResultList
wait() override final
;
80 AioResultList
drain() override final
;
83 // a throttle that yields the coroutine instead of blocking. all public
84 // functions must be called within the coroutine strand
85 class YieldingAioThrottle final
: public Aio
, private Throttle
{
86 boost::asio::io_context
& context
;
90 // completion callback associated with the waiter
91 using Completion
= ceph::async::Completion
<void(boost::system::error_code
)>;
92 std::unique_ptr
<Completion
> completion
;
94 template <typename CompletionToken
>
95 auto async_wait(CompletionToken
&& token
);
97 struct Pending
: AioResultEntry
{ uint64_t cost
= 0; };
100 YieldingAioThrottle(uint64_t window
, boost::asio::io_context
& context
,
102 : Throttle(window
), context(context
), yield(yield
)
105 virtual ~YieldingAioThrottle() override
{};
107 AioResultList
get(const RGWSI_RADOS::Obj
& obj
, OpFunc
&& f
,
108 uint64_t cost
, uint64_t id
) override final
;
110 void put(AioResult
& r
) override final
;
112 AioResultList
poll() override final
;
114 AioResultList
wait() override final
;
116 AioResultList
drain() override final
;
119 // return a smart pointer to Aio
120 inline auto make_throttle(uint64_t window_size
, optional_yield y
)
122 std::unique_ptr
<Aio
> aio
;
124 aio
= std::make_unique
<YieldingAioThrottle
>(window_size
,
126 y
.get_yield_context());
128 aio
= std::make_unique
<BlockingAioThrottle
>(window_size
);