]> git.proxmox.com Git - ceph.git/blob - ceph/src/crimson/osd/watch.h
import 15.2.0 Octopus source
[ceph.git] / ceph / src / crimson / osd / watch.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 <iterator>
7 #include <map>
8 #include <set>
9
10 #include <seastar/core/shared_ptr.hh>
11
12 #include "crimson/net/Connection.h"
13 #include "crimson/osd/object_context.h"
14 #include "include/denc.h"
15
16 namespace crimson::osd {
17
18 class Notify;
19 using NotifyRef = seastar::shared_ptr<Notify>;
20
21 // NOTE: really need to have this public. Otherwise `shared_from_this()`
22 // will abort. According to cppreference.com:
23 //
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".
27 //
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
32 // used by create().
33 struct private_ctag_t{};
34
35 struct NotifyCmp {
36 inline bool operator()(NotifyRef lhs, NotifyRef rhs) const;
37 };
38 std::set<NotifyRef, NotifyCmp> in_progress_notifies;
39 crimson::net::ConnectionRef conn;
40 crimson::osd::ObjectContextRef obc;
41
42 watch_info_t winfo;
43 entity_name_t entity_name;
44
45 seastar::future<> start_notify(NotifyRef);
46 seastar::future<> send_notify_msg(NotifyRef);
47 seastar::future<> send_disconnect_msg();
48 void discard_state();
49
50 friend Notify;
51
52 public:
53 Watch(private_ctag_t,
54 crimson::osd::ObjectContextRef obc,
55 const watch_info_t& winfo,
56 const entity_name_t& entity_name)
57 : obc(std::move(obc)),
58 winfo(winfo),
59 entity_name(entity_name) {
60 }
61
62 seastar::future<> connect(crimson::net::ConnectionRef, bool);
63 bool is_alive() const {
64 return true;
65 }
66 bool is_connected() const {
67 return static_cast<bool>(conn);
68 }
69 void got_ping(utime_t) {
70 // NOP
71 }
72
73 seastar::future<> remove(bool send_disconnect);
74
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
79
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)...);
84 };
85
86 uint64_t get_watcher_gid() const {
87 return entity_name.num();
88 }
89 uint64_t get_cookie() const {
90 return winfo.cookie;
91 }
92 };
93
94 using WatchRef = seastar::shared_ptr<Watch>;
95
96 struct notify_reply_t {
97 uint64_t watcher_gid;
98 uint64_t watcher_cookie;
99 ceph::bufferlist bl;
100
101 bool operator<(const notify_reply_t& rhs) const;
102 DENC(notify_reply_t, v, p) {
103 DENC_START(1, 1, p);
104 denc(v.watcher_gid, p);
105 denc(v.watcher_cookie, p);
106 denc(v.bl, p);
107 DENC_FINISH(p);
108 }
109 };
110
111 class Notify {
112 std::set<WatchRef> watchers;
113 notify_info_t ninfo;
114 crimson::net::ConnectionRef conn;
115 uint64_t client_gid;
116 uint64_t user_version;
117 bool complete = false;
118 bool discarded = false;
119
120 /// (gid,cookie) -> reply_bl for everyone who acked the notify
121 std::multiset<notify_reply_t> notify_replies;
122
123 uint64_t get_id() const { return ninfo.notify_id; }
124 seastar::future<> maybe_send_completion();
125
126 template <class WatchIteratorT>
127 Notify(WatchIteratorT begin,
128 WatchIteratorT end,
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{};
137
138 friend Watch;
139
140 public:
141 template <class... Args>
142 Notify(private_ctag_t, Args&&... args) : Notify(std::forward<Args>(args)...) {
143 }
144
145 template <class WatchIteratorT, class... Args>
146 static seastar::future<> create_n_propagate(
147 WatchIteratorT begin,
148 WatchIteratorT end,
149 Args&&... args);
150
151 seastar::future<> remove_watcher(WatchRef watch);
152 seastar::future<> complete_watcher(WatchRef watch,
153 const ceph::bufferlist& reply_bl);
154 };
155
156
157 template <class WatchIteratorT>
158 Notify::Notify(WatchIteratorT begin,
159 WatchIteratorT end,
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),
165 ninfo(ninfo),
166 conn(std::move(conn)),
167 client_gid(client_gid),
168 user_version(user_version) {
169 }
170
171 template <class WatchIteratorT, class... Args>
172 seastar::future<> Notify::create_n_propagate(
173 WatchIteratorT begin,
174 WatchIteratorT end,
175 Args&&... args)
176 {
177 static_assert(
178 std::is_same_v<typename std::iterator_traits<WatchIteratorT>::value_type,
179 crimson::osd::WatchRef>);
180 auto notify = seastar::make_shared<Notify>(
181 private_ctag_t{},
182 begin,
183 end,
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();
189 });
190 }
191
192 } // namespace crimson::osd
193
194 WRITE_CLASS_DENC(crimson::osd::notify_reply_t)