]>
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 | |
57 | set<WatchRef> watchers; | |
58 | ||
59 | bufferlist payload; | |
60 | uint32_t timeout; | |
61 | uint64_t cookie; | |
62 | uint64_t notify_id; | |
63 | uint64_t version; | |
64 | ||
65 | OSDService *osd; | |
66 | CancelableContext *cb; | |
67 | Mutex lock; | |
68 | ||
69 | /// (gid,cookie) -> reply_bl for everyone who acked the notify | |
70 | multimap<pair<uint64_t,uint64_t>,bufferlist> notify_replies; | |
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, | |
86 | bufferlist &payload, | |
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 TL |
100 | std::ostream& gen_dbg_prefix(std::ostream& out) { |
101 | return out << "Notify(" << make_pair(cookie, notify_id) << " " | |
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, | |
111 | bufferlist &payload, | |
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 | |
129 | bufferlist& reply_bl ///< [in] reply buffer from the notified watcher | |
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); | |
191 | utime_t get_last_ping() const { | |
192 | return last_ping; | |
193 | } | |
194 | ||
195 | bool is_connected() const { | |
196 | return conn.get() != NULL; | |
197 | } | |
198 | bool is_connected(Connection *con) const { | |
199 | return conn.get() == con; | |
200 | } | |
201 | ||
202 | /// NOTE: must be called with pg lock held | |
203 | ~Watch(); | |
204 | ||
205 | uint64_t get_watcher_gid() const { | |
206 | return entity.num(); | |
207 | } | |
208 | ||
11fdf7f2 | 209 | std::ostream& gen_dbg_prefix(std::ostream& out); |
7c673cae FG |
210 | static WatchRef makeWatchRef( |
211 | PrimaryLogPG *pg, OSDService *osd, | |
11fdf7f2 | 212 | std::shared_ptr<ObjectContext> obc, uint32_t timeout, uint64_t cookie, entity_name_t entity, const entity_addr_t &addr); |
7c673cae FG |
213 | void set_self(WatchRef _self) { |
214 | self = _self; | |
215 | } | |
216 | ||
217 | /// Does not grant a ref count! | |
218 | boost::intrusive_ptr<PrimaryLogPG> get_pg() { return pg; } | |
219 | ||
11fdf7f2 | 220 | std::shared_ptr<ObjectContext> get_obc() { return obc; } |
7c673cae FG |
221 | |
222 | uint64_t get_cookie() const { return cookie; } | |
223 | entity_name_t get_entity() const { return entity; } | |
224 | entity_addr_t get_peer_addr() const { return addr; } | |
225 | uint32_t get_timeout() const { return timeout; } | |
226 | ||
227 | /// Generates context for use if watch timeout is delayed by scrub or recovery | |
228 | Context *get_delayed_cb(); | |
229 | ||
230 | /// True if currently connected | |
231 | bool connected(); | |
232 | ||
233 | /// Transitions Watch to connected, unregister_cb, resends pending Notifies | |
234 | void connect( | |
235 | ConnectionRef con, ///< [in] Reference to new connection | |
236 | bool will_ping ///< [in] client is new and will send pings | |
237 | ); | |
238 | ||
239 | /// Transitions watch to disconnected, register_cb | |
240 | void disconnect(); | |
241 | ||
242 | /// Called if Watch state is discarded due to new peering interval | |
243 | void discard(); | |
244 | ||
245 | /// True if removed or discarded | |
246 | bool is_discarded() const; | |
247 | ||
248 | /// Called on unwatch | |
249 | void remove(bool send_disconnect); | |
250 | ||
251 | /// Adds notif as in-progress notify | |
252 | void start_notify( | |
253 | NotifyRef notif ///< [in] Reference to new in-progress notify | |
254 | ); | |
255 | ||
256 | /// Removes timed out notify | |
257 | void cancel_notify( | |
258 | NotifyRef notif ///< [in] notify which timed out | |
259 | ); | |
260 | ||
261 | /// Call when notify_ack received on notify_id | |
262 | void notify_ack( | |
263 | uint64_t notify_id, ///< [in] id of acked notify | |
264 | bufferlist& reply_bl ///< [in] notify reply buffer | |
265 | ); | |
266 | }; | |
267 | ||
268 | /** | |
269 | * Holds weak refs to Watch structures corresponding to a connection | |
270 | * Lives in the Session object of an OSD connection | |
271 | */ | |
272 | class WatchConState { | |
273 | Mutex lock; | |
274 | std::set<WatchRef> watches; | |
275 | public: | |
276 | CephContext* cct; | |
11fdf7f2 | 277 | explicit WatchConState(CephContext* cct) : lock("WatchConState"), cct(cct) {} |
7c673cae FG |
278 | |
279 | /// Add a watch | |
280 | void addWatch( | |
281 | WatchRef watch ///< [in] Ref to new watch object | |
282 | ); | |
283 | ||
284 | /// Remove a watch | |
285 | void removeWatch( | |
286 | WatchRef watch ///< [in] Ref to watch object to remove | |
287 | ); | |
288 | ||
289 | /// Called on session reset, disconnects watchers | |
290 | void reset(Connection *con); | |
291 | }; | |
292 | ||
293 | #endif |