]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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) 2004-2006 Sage Weil <sage@newdream.net> | |
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 | #ifndef CEPH_WATCH_H | |
15 | #define CEPH_WATCH_H | |
16 | ||
7c673cae | 17 | #include <set> |
11fdf7f2 | 18 | #include "msg/Connection.h" |
7c673cae FG |
19 | #include "include/Context.h" |
20 | ||
21 | enum WatcherState { | |
22 | WATCHER_PENDING, | |
23 | WATCHER_NOTIFIED, | |
24 | }; | |
25 | ||
26 | class OSDService; | |
27 | class PrimaryLogPG; | |
28 | void intrusive_ptr_add_ref(PrimaryLogPG *pg); | |
29 | void intrusive_ptr_release(PrimaryLogPG *pg); | |
30 | struct ObjectContext; | |
31 | class MWatchNotify; | |
32 | ||
33 | class Watch; | |
11fdf7f2 TL |
34 | typedef std::shared_ptr<Watch> WatchRef; |
35 | typedef std::weak_ptr<Watch> WWatchRef; | |
7c673cae FG |
36 | |
37 | class Notify; | |
11fdf7f2 TL |
38 | typedef std::shared_ptr<Notify> NotifyRef; |
39 | typedef std::weak_ptr<Notify> WNotifyRef; | |
7c673cae FG |
40 | |
41 | struct CancelableContext; | |
42 | ||
43 | /** | |
44 | * Notify tracks the progress of a particular notify | |
45 | * | |
46 | * References are held by Watch and the timeout callback. | |
47 | */ | |
48 | class Notify { | |
49 | friend class NotifyTimeoutCB; | |
50 | friend class Watch; | |
51 | WNotifyRef self; | |
52 | ConnectionRef client; | |
53 | uint64_t client_gid; | |
54 | bool complete; | |
55 | bool discarded; | |
56 | bool timed_out; ///< true if the notify timed out | |
9f95a23c | 57 | std::set<WatchRef> watchers; |
7c673cae | 58 | |
9f95a23c | 59 | ceph::buffer::list payload; |
7c673cae FG |
60 | uint32_t timeout; |
61 | uint64_t cookie; | |
62 | uint64_t notify_id; | |
63 | uint64_t version; | |
64 | ||
65 | OSDService *osd; | |
66 | CancelableContext *cb; | |
9f95a23c | 67 | ceph::mutex lock = ceph::make_mutex("Notify::lock"); |
7c673cae FG |
68 | |
69 | /// (gid,cookie) -> reply_bl for everyone who acked the notify | |
9f95a23c | 70 | std::multimap<std::pair<uint64_t,uint64_t>, ceph::buffer::list> notify_replies; |
7c673cae FG |
71 | |
72 | /// true if this notify is being discarded | |
73 | bool is_discarded() { | |
74 | return discarded || complete; | |
75 | } | |
76 | ||
77 | /// Sends notify completion if watchers.empty() or timeout | |
78 | void maybe_complete_notify(); | |
79 | ||
80 | /// Called on Notify timeout | |
81 | void do_timeout(); | |
82 | ||
83 | Notify( | |
84 | ConnectionRef client, | |
85 | uint64_t client_gid, | |
9f95a23c | 86 | ceph::buffer::list& payload, |
7c673cae FG |
87 | uint32_t timeout, |
88 | uint64_t cookie, | |
89 | uint64_t notify_id, | |
90 | uint64_t version, | |
91 | OSDService *osd); | |
92 | ||
93 | /// registers a timeout callback with the watch_timer | |
94 | void register_cb(); | |
95 | ||
96 | /// removes the timeout callback, called on completion or cancellation | |
97 | void unregister_cb(); | |
98 | public: | |
99 | ||
11fdf7f2 | 100 | std::ostream& gen_dbg_prefix(std::ostream& out) { |
9f95a23c | 101 | return out << "Notify(" << std::make_pair(cookie, notify_id) << " " |
11fdf7f2 TL |
102 | << " watchers=" << watchers.size() |
103 | << ") "; | |
7c673cae FG |
104 | } |
105 | void set_self(NotifyRef _self) { | |
106 | self = _self; | |
107 | } | |
108 | static NotifyRef makeNotifyRef( | |
109 | ConnectionRef client, | |
110 | uint64_t client_gid, | |
9f95a23c | 111 | ceph::buffer::list &payload, |
7c673cae FG |
112 | uint32_t timeout, |
113 | uint64_t cookie, | |
114 | uint64_t notify_id, | |
115 | uint64_t version, | |
116 | OSDService *osd); | |
117 | ||
118 | /// Call after creation to initialize | |
119 | void init(); | |
120 | ||
121 | /// Called once per watcher prior to init() | |
122 | void start_watcher( | |
123 | WatchRef watcher ///< [in] watcher to complete | |
124 | ); | |
125 | ||
126 | /// Called once per NotifyAck | |
127 | void complete_watcher( | |
128 | WatchRef watcher, ///< [in] watcher to complete | |
9f95a23c | 129 | ceph::buffer::list& reply_bl ///< [in] reply buffer from the notified watcher |
7c673cae FG |
130 | ); |
131 | /// Called when a watcher unregisters or times out | |
132 | void complete_watcher_remove( | |
133 | WatchRef watcher ///< [in] watcher to complete | |
134 | ); | |
135 | ||
136 | /// Called when the notify is canceled due to a new peering interval | |
137 | void discard(); | |
138 | }; | |
139 | ||
140 | /** | |
141 | * Watch is a mapping between a Connection and an ObjectContext | |
142 | * | |
143 | * References are held by ObjectContext and the timeout callback | |
144 | */ | |
145 | class HandleWatchTimeout; | |
146 | class HandleDelayedWatchTimeout; | |
147 | class Watch { | |
148 | WWatchRef self; | |
149 | friend class HandleWatchTimeout; | |
150 | friend class HandleDelayedWatchTimeout; | |
151 | ConnectionRef conn; | |
152 | CancelableContext *cb; | |
153 | ||
154 | OSDService *osd; | |
155 | boost::intrusive_ptr<PrimaryLogPG> pg; | |
11fdf7f2 | 156 | std::shared_ptr<ObjectContext> obc; |
7c673cae FG |
157 | |
158 | std::map<uint64_t, NotifyRef> in_progress_notifies; | |
159 | ||
160 | // Could have watch_info_t here, but this file includes osd_types.h | |
161 | uint32_t timeout; ///< timeout in seconds | |
162 | uint64_t cookie; | |
163 | entity_addr_t addr; | |
164 | ||
165 | bool will_ping; ///< is client new enough to ping the watch | |
11fdf7f2 | 166 | utime_t last_ping; ///< last client ping |
7c673cae FG |
167 | |
168 | entity_name_t entity; | |
169 | bool discarded; | |
170 | ||
171 | Watch( | |
172 | PrimaryLogPG *pg, OSDService *osd, | |
11fdf7f2 | 173 | std::shared_ptr<ObjectContext> obc, uint32_t timeout, |
7c673cae FG |
174 | uint64_t cookie, entity_name_t entity, |
175 | const entity_addr_t& addr); | |
176 | ||
177 | /// Registers the timeout callback with watch_timer | |
178 | void register_cb(); | |
179 | ||
180 | /// send a Notify message when connected for notif | |
181 | void send_notify(NotifyRef notif); | |
182 | ||
183 | /// Cleans up state on discard or remove (including Connection state, obc) | |
184 | void discard_state(); | |
185 | public: | |
186 | /// Unregisters the timeout callback | |
187 | void unregister_cb(); | |
188 | ||
189 | /// note receipt of a ping | |
190 | void got_ping(utime_t t); | |
7c673cae | 191 | |
9f95a23c | 192 | /// True if currently connected |
7c673cae FG |
193 | bool is_connected() const { |
194 | return conn.get() != NULL; | |
195 | } | |
196 | bool is_connected(Connection *con) const { | |
197 | return conn.get() == con; | |
198 | } | |
199 | ||
200 | /// NOTE: must be called with pg lock held | |
201 | ~Watch(); | |
202 | ||
203 | uint64_t get_watcher_gid() const { | |
204 | return entity.num(); | |
205 | } | |
206 | ||
11fdf7f2 | 207 | std::ostream& gen_dbg_prefix(std::ostream& out); |
7c673cae FG |
208 | static WatchRef makeWatchRef( |
209 | PrimaryLogPG *pg, OSDService *osd, | |
11fdf7f2 | 210 | std::shared_ptr<ObjectContext> obc, uint32_t timeout, uint64_t cookie, entity_name_t entity, const entity_addr_t &addr); |
7c673cae FG |
211 | void set_self(WatchRef _self) { |
212 | self = _self; | |
213 | } | |
214 | ||
215 | /// Does not grant a ref count! | |
216 | boost::intrusive_ptr<PrimaryLogPG> get_pg() { return pg; } | |
217 | ||
11fdf7f2 | 218 | std::shared_ptr<ObjectContext> get_obc() { return obc; } |
7c673cae FG |
219 | |
220 | uint64_t get_cookie() const { return cookie; } | |
221 | entity_name_t get_entity() const { return entity; } | |
222 | entity_addr_t get_peer_addr() const { return addr; } | |
223 | uint32_t get_timeout() const { return timeout; } | |
224 | ||
225 | /// Generates context for use if watch timeout is delayed by scrub or recovery | |
226 | Context *get_delayed_cb(); | |
227 | ||
7c673cae FG |
228 | /// Transitions Watch to connected, unregister_cb, resends pending Notifies |
229 | void connect( | |
230 | ConnectionRef con, ///< [in] Reference to new connection | |
231 | bool will_ping ///< [in] client is new and will send pings | |
232 | ); | |
233 | ||
234 | /// Transitions watch to disconnected, register_cb | |
235 | void disconnect(); | |
236 | ||
237 | /// Called if Watch state is discarded due to new peering interval | |
238 | void discard(); | |
239 | ||
240 | /// True if removed or discarded | |
241 | bool is_discarded() const; | |
242 | ||
243 | /// Called on unwatch | |
244 | void remove(bool send_disconnect); | |
245 | ||
246 | /// Adds notif as in-progress notify | |
247 | void start_notify( | |
248 | NotifyRef notif ///< [in] Reference to new in-progress notify | |
249 | ); | |
250 | ||
251 | /// Removes timed out notify | |
252 | void cancel_notify( | |
253 | NotifyRef notif ///< [in] notify which timed out | |
254 | ); | |
255 | ||
256 | /// Call when notify_ack received on notify_id | |
257 | void notify_ack( | |
258 | uint64_t notify_id, ///< [in] id of acked notify | |
9f95a23c | 259 | ceph::buffer::list& reply_bl ///< [in] notify reply buffer |
7c673cae FG |
260 | ); |
261 | }; | |
262 | ||
263 | /** | |
264 | * Holds weak refs to Watch structures corresponding to a connection | |
265 | * Lives in the Session object of an OSD connection | |
266 | */ | |
267 | class WatchConState { | |
9f95a23c | 268 | ceph::mutex lock = ceph::make_mutex("WatchConState"); |
7c673cae FG |
269 | std::set<WatchRef> watches; |
270 | public: | |
271 | CephContext* cct; | |
9f95a23c | 272 | explicit WatchConState(CephContext* cct) : cct(cct) {} |
7c673cae FG |
273 | |
274 | /// Add a watch | |
275 | void addWatch( | |
276 | WatchRef watch ///< [in] Ref to new watch object | |
277 | ); | |
278 | ||
279 | /// Remove a watch | |
280 | void removeWatch( | |
281 | WatchRef watch ///< [in] Ref to watch object to remove | |
282 | ); | |
283 | ||
284 | /// Called on session reset, disconnects watchers | |
285 | void reset(Connection *con); | |
286 | }; | |
287 | ||
288 | #endif |