1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
10 #include <seastar/core/shared_ptr.hh>
12 #include "crimson/net/Connection.h"
13 #include "crimson/osd/object_context.h"
14 #include "include/denc.h"
16 namespace crimson::osd
{
19 using NotifyRef
= seastar::shared_ptr
<Notify
>;
21 // NOTE: really need to have this public. Otherwise `shared_from_this()`
22 // will abort. According to cppreference.com:
24 // "The constructors of std::shared_ptr detect the presence
25 // of an unambiguous and accessible (ie. public inheritance
26 // is mandatory) (since C++17) enable_shared_from_this base".
28 // I expect the `seastar::shared_ptr` shares this behaviour.
29 class Watch
: public seastar::enable_shared_from_this
<Watch
> {
30 // this is a private tag for the public constructor that turns it into
31 // de facto private one. The motivation behind the hack is make_shared
33 struct private_ctag_t
{};
36 inline bool operator()(NotifyRef lhs
, NotifyRef rhs
) const;
38 std::set
<NotifyRef
, NotifyCmp
> in_progress_notifies
;
39 crimson::net::ConnectionRef conn
;
40 crimson::osd::ObjectContextRef obc
;
43 entity_name_t entity_name
;
45 seastar::future
<> start_notify(NotifyRef
);
46 seastar::future
<> send_notify_msg(NotifyRef
);
47 seastar::future
<> send_disconnect_msg();
54 crimson::osd::ObjectContextRef obc
,
55 const watch_info_t
& winfo
,
56 const entity_name_t
& entity_name
)
57 : obc(std::move(obc
)),
59 entity_name(entity_name
) {
62 seastar::future
<> connect(crimson::net::ConnectionRef
, bool);
63 bool is_alive() const {
66 bool is_connected() const {
67 return static_cast<bool>(conn
);
69 void got_ping(utime_t
) {
73 seastar::future
<> remove(bool send_disconnect
);
75 /// Call when notify_ack received on notify_id
76 seastar::future
<> notify_ack(
77 uint64_t notify_id
, ///< [in] id of acked notify
78 const ceph::bufferlist
& reply_bl
); ///< [in] notify reply buffer
80 template <class... Args
>
81 static seastar::shared_ptr
<Watch
> create(Args
&&... args
) {
82 return seastar::make_shared
<Watch
>(private_ctag_t
{},
83 std::forward
<Args
>(args
)...);
86 uint64_t get_watcher_gid() const {
87 return entity_name
.num();
89 uint64_t get_cookie() const {
94 using WatchRef
= seastar::shared_ptr
<Watch
>;
96 struct notify_reply_t
{
98 uint64_t watcher_cookie
;
101 bool operator<(const notify_reply_t
& rhs
) const;
102 DENC(notify_reply_t
, v
, p
) {
104 denc(v
.watcher_gid
, p
);
105 denc(v
.watcher_cookie
, p
);
112 std::set
<WatchRef
> watchers
;
114 crimson::net::ConnectionRef conn
;
116 uint64_t user_version
;
117 bool complete
= false;
118 bool discarded
= false;
120 /// (gid,cookie) -> reply_bl for everyone who acked the notify
121 std::multiset
<notify_reply_t
> notify_replies
;
123 uint64_t get_id() const { return ninfo
.notify_id
; }
124 seastar::future
<> maybe_send_completion();
126 template <class WatchIteratorT
>
127 Notify(WatchIteratorT begin
,
129 crimson::net::ConnectionRef conn
,
130 const notify_info_t
& ninfo
,
131 const uint64_t client_gid
,
132 const uint64_t user_version
);
133 // this is a private tag for the public constructor that turns it into
134 // de facto private one. The motivation behind the hack is make_shared
135 // used by create_n_propagate factory.
136 struct private_ctag_t
{};
141 template <class... Args
>
142 Notify(private_ctag_t
, Args
&&... args
) : Notify(std::forward
<Args
>(args
)...) {
145 template <class WatchIteratorT
, class... Args
>
146 static seastar::future
<> create_n_propagate(
147 WatchIteratorT begin
,
151 seastar::future
<> remove_watcher(WatchRef watch
);
152 seastar::future
<> complete_watcher(WatchRef watch
,
153 const ceph::bufferlist
& reply_bl
);
157 template <class WatchIteratorT
>
158 Notify::Notify(WatchIteratorT begin
,
160 crimson::net::ConnectionRef conn
,
161 const notify_info_t
& ninfo
,
162 const uint64_t client_gid
,
163 const uint64_t user_version
)
164 : watchers(begin
, end
),
166 conn(std::move(conn
)),
167 client_gid(client_gid
),
168 user_version(user_version
) {
171 template <class WatchIteratorT
, class... Args
>
172 seastar::future
<> Notify::create_n_propagate(
173 WatchIteratorT begin
,
178 std::is_same_v
<typename
std::iterator_traits
<WatchIteratorT
>::value_type
,
179 crimson::osd::WatchRef
>);
180 auto notify
= seastar::make_shared
<Notify
>(
184 std::forward
<Args
>(args
)...);
185 return seastar::do_for_each(begin
, end
, [=] (auto& watchref
) {
186 return watchref
->start_notify(notify
);
187 }).then([notify
= std::move(notify
)] {
188 return notify
->maybe_send_completion();
192 } // namespace crimson::osd
194 WRITE_CLASS_DENC(crimson::osd::notify_reply_t
)