]>
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 | ||
15 | #ifndef CEPH_MON_SESSION_H | |
16 | #define CEPH_MON_SESSION_H | |
17 | ||
9f95a23c TL |
18 | #include <string> |
19 | #include <string_view> | |
20 | ||
21 | #include "include/utime.h" | |
7c673cae | 22 | #include "include/xlist.h" |
9f95a23c TL |
23 | |
24 | #include "global/global_context.h" | |
7c673cae | 25 | #include "msg/msg_types.h" |
31f18b77 | 26 | #include "mon/mon_types.h" |
7c673cae FG |
27 | |
28 | #include "auth/AuthServiceHandler.h" | |
29 | #include "osd/OSDMap.h" | |
30 | ||
31 | #include "MonCap.h" | |
32 | ||
33 | struct MonSession; | |
34 | ||
35 | struct Subscription { | |
36 | MonSession *session; | |
9f95a23c | 37 | std::string type; |
7c673cae FG |
38 | xlist<Subscription*>::item type_item; |
39 | version_t next; | |
40 | bool onetime; | |
41 | bool incremental_onetime; // has CEPH_FEATURE_INCSUBOSDMAP | |
42 | ||
9f95a23c | 43 | Subscription(MonSession *s, const std::string& t) : session(s), type(t), type_item(this), |
7c673cae FG |
44 | next(0), onetime(false), incremental_onetime(false) {} |
45 | }; | |
46 | ||
47 | struct MonSession : public RefCountedObject { | |
48 | ConnectionRef con; | |
31f18b77 FG |
49 | int con_type = 0; |
50 | uint64_t con_features = 0; // zero if AnonConnection | |
11fdf7f2 TL |
51 | entity_name_t name; |
52 | entity_addrvec_t addrs; | |
53 | entity_addr_t socket_addr; | |
7c673cae | 54 | utime_t session_timeout; |
11fdf7f2 | 55 | bool closed = false; |
7c673cae | 56 | xlist<MonSession*>::item item; |
9f95a23c | 57 | std::set<uint64_t> routed_request_tids; |
7c673cae | 58 | MonCap caps; |
f67539c2 | 59 | bool validated_stretch_connection = false; |
11fdf7f2 TL |
60 | |
61 | bool authenticated = false; ///< true if auth handshake is complete | |
7c673cae | 62 | |
9f95a23c | 63 | std::map<std::string, Subscription*> sub_map; |
11fdf7f2 | 64 | epoch_t osd_epoch = 0; ///< the osdmap epoch sent to the mon client |
7c673cae | 65 | |
11fdf7f2 | 66 | AuthServiceHandler *auth_handler = nullptr; |
7c673cae | 67 | EntityName entity_name; |
c5c27e9a TL |
68 | uint64_t global_id = 0; |
69 | global_id_status_t global_id_status = global_id_status_t::NONE; | |
7c673cae FG |
70 | |
71 | ConnectionRef proxy_con; | |
11fdf7f2 TL |
72 | uint64_t proxy_tid = 0; |
73 | ||
9f95a23c TL |
74 | std::string remote_host; ///< remote host name |
75 | std::map<std::string,std::string,std::less<>> last_config; ///< most recently shared config | |
11fdf7f2 TL |
76 | bool any_config = false; |
77 | ||
78 | MonSession(Connection *c) | |
79 | : RefCountedObject(g_ceph_context), | |
80 | con(c), | |
81 | item(this) { } | |
82 | ||
83 | void _ident(const entity_name_t& n, const entity_addrvec_t& av) { | |
84 | con_type = con->get_peer_type(); | |
85 | name = n; | |
86 | addrs = av; | |
87 | socket_addr = con->get_peer_socket_addr(); | |
88 | if (con->get_messenger()) { | |
31f18b77 | 89 | // only fill in features if this is a non-anonymous connection |
11fdf7f2 | 90 | con_features = con->get_features(); |
31f18b77 | 91 | } |
7c673cae | 92 | } |
11fdf7f2 | 93 | |
7c673cae FG |
94 | ~MonSession() override { |
95 | //generic_dout(0) << "~MonSession " << this << dendl; | |
96 | // we should have been removed before we get destructed; see MonSessionMap::remove_session() | |
11fdf7f2 TL |
97 | ceph_assert(!item.is_on_list()); |
98 | ceph_assert(sub_map.empty()); | |
7c673cae FG |
99 | delete auth_handler; |
100 | } | |
101 | ||
9f95a23c TL |
102 | bool is_capable(std::string service, int mask) { |
103 | std::map<std::string,std::string> args; | |
7c673cae FG |
104 | return caps.is_capable( |
105 | g_ceph_context, | |
7c673cae FG |
106 | entity_name, |
107 | service, "", args, | |
11fdf7f2 TL |
108 | mask & MON_CAP_R, mask & MON_CAP_W, mask & MON_CAP_X, |
109 | get_peer_socket_addr()); | |
110 | } | |
111 | ||
20effc67 | 112 | std::vector<std::string> get_allowed_fs_names() const { |
f67539c2 TL |
113 | return caps.allowed_fs_names(); |
114 | } | |
115 | ||
20effc67 | 116 | bool fs_name_capable(std::string_view fsname, __u8 mask) { |
f67539c2 TL |
117 | return caps.fs_name_capable(entity_name, fsname, mask); |
118 | } | |
119 | ||
11fdf7f2 TL |
120 | const entity_addr_t& get_peer_socket_addr() { |
121 | return socket_addr; | |
7c673cae | 122 | } |
9f95a23c | 123 | |
f67539c2 | 124 | void dump(ceph::Formatter *f) const { |
9f95a23c TL |
125 | f->dump_stream("name") << name; |
126 | f->dump_stream("entity_name") << entity_name; | |
127 | f->dump_object("addrs", addrs); | |
128 | f->dump_object("socket_addr", socket_addr); | |
129 | f->dump_string("con_type", ceph_entity_type_name(con_type)); | |
130 | f->dump_unsigned("con_features", con_features); | |
131 | f->dump_stream("con_features_hex") << std::hex << con_features << std::dec; | |
132 | f->dump_string("con_features_release", | |
133 | ceph_release_name(ceph_release_from_features(con_features))); | |
134 | f->dump_bool("open", !closed); | |
135 | f->dump_object("caps", caps); | |
136 | f->dump_bool("authenticated", authenticated); | |
c5c27e9a TL |
137 | f->dump_unsigned("global_id", global_id); |
138 | f->dump_stream("global_id_status") << global_id_status; | |
9f95a23c TL |
139 | f->dump_unsigned("osd_epoch", osd_epoch); |
140 | f->dump_string("remote_host", remote_host); | |
141 | } | |
7c673cae FG |
142 | }; |
143 | ||
144 | ||
145 | struct MonSessionMap { | |
146 | xlist<MonSession*> sessions; | |
9f95a23c TL |
147 | std::map<std::string, xlist<Subscription*>* > subs; |
148 | std::multimap<int, MonSession*> by_osd; | |
31f18b77 | 149 | FeatureMap feature_map; // type -> features -> count |
7c673cae FG |
150 | |
151 | MonSessionMap() {} | |
152 | ~MonSessionMap() { | |
153 | while (!subs.empty()) { | |
11fdf7f2 | 154 | ceph_assert(subs.begin()->second->empty()); |
7c673cae FG |
155 | delete subs.begin()->second; |
156 | subs.erase(subs.begin()); | |
157 | } | |
158 | } | |
159 | ||
160 | unsigned get_size() const { | |
161 | return sessions.size(); | |
162 | } | |
163 | ||
164 | void remove_session(MonSession *s) { | |
11fdf7f2 | 165 | ceph_assert(!s->closed); |
9f95a23c | 166 | for (std::map<std::string,Subscription*>::iterator p = s->sub_map.begin(); p != s->sub_map.end(); ++p) { |
7c673cae FG |
167 | p->second->type_item.remove_myself(); |
168 | delete p->second; | |
169 | } | |
170 | s->sub_map.clear(); | |
171 | s->item.remove_myself(); | |
92f5a8d4 TL |
172 | if (s->name.is_osd() && |
173 | s->name.num() >= 0) { | |
9f95a23c | 174 | for (auto p = by_osd.find(s->name.num()); |
11fdf7f2 | 175 | p->first == s->name.num(); |
7c673cae FG |
176 | ++p) |
177 | if (p->second == s) { | |
178 | by_osd.erase(p); | |
179 | break; | |
180 | } | |
181 | } | |
31f18b77 FG |
182 | if (s->con_features) { |
183 | feature_map.rm(s->con_type, s->con_features); | |
184 | } | |
7c673cae FG |
185 | s->closed = true; |
186 | s->put(); | |
187 | } | |
188 | ||
11fdf7f2 TL |
189 | MonSession *new_session(const entity_name_t& n, |
190 | const entity_addrvec_t& av, | |
191 | Connection *c) { | |
192 | MonSession *s = new MonSession(c); | |
193 | ceph_assert(s); | |
194 | s->_ident(n, av); | |
195 | add_session(s); | |
196 | return s; | |
197 | } | |
198 | ||
199 | void add_session(MonSession *s) { | |
f91f0fd5 TL |
200 | s->session_timeout = ceph_clock_now(); |
201 | s->session_timeout += g_conf()->mon_session_timeout; | |
202 | ||
7c673cae | 203 | sessions.push_back(&s->item); |
11fdf7f2 | 204 | s->get(); |
92f5a8d4 TL |
205 | if (s->name.is_osd() && |
206 | s->name.num() >= 0) { | |
9f95a23c | 207 | by_osd.insert(std::pair<int,MonSession*>(s->name.num(), s)); |
11fdf7f2 | 208 | } |
31f18b77 FG |
209 | if (s->con_features) { |
210 | feature_map.add(s->con_type, s->con_features); | |
211 | } | |
7c673cae FG |
212 | } |
213 | ||
214 | MonSession *get_random_osd_session(OSDMap *osdmap) { | |
215 | // ok, this isn't actually random, but close enough. | |
216 | if (by_osd.empty()) | |
217 | return 0; | |
218 | int n = by_osd.rbegin()->first + 1; | |
219 | int r = rand() % n; | |
220 | ||
9f95a23c | 221 | auto p = by_osd.lower_bound(r); |
7c673cae FG |
222 | if (p == by_osd.end()) |
223 | --p; | |
224 | ||
225 | if (!osdmap) { | |
226 | return p->second; | |
227 | } | |
228 | ||
229 | MonSession *s = NULL; | |
230 | ||
9f95a23c TL |
231 | auto b = p; |
232 | auto f = p; | |
7c673cae FG |
233 | bool backward = true, forward = true; |
234 | while (backward || forward) { | |
235 | if (backward) { | |
236 | if (osdmap->is_up(b->first) && | |
11fdf7f2 | 237 | osdmap->get_addrs(b->first) == b->second->con->get_peer_addrs()) { |
7c673cae FG |
238 | s = b->second; |
239 | break; | |
240 | } | |
241 | if (b != by_osd.begin()) | |
242 | --b; | |
243 | else | |
244 | backward = false; | |
245 | } | |
246 | ||
247 | forward = (f != by_osd.end()); | |
248 | if (forward) { | |
249 | if (osdmap->is_up(f->first)) { | |
250 | s = f->second; | |
251 | break; | |
252 | } | |
253 | ++f; | |
254 | } | |
255 | } | |
256 | ||
257 | return s; | |
258 | } | |
259 | ||
9f95a23c | 260 | void add_update_sub(MonSession *s, const std::string& what, version_t start, bool onetime, bool incremental_onetime) { |
7c673cae FG |
261 | Subscription *sub = 0; |
262 | if (s->sub_map.count(what)) { | |
263 | sub = s->sub_map[what]; | |
264 | } else { | |
265 | sub = new Subscription(s, what); | |
266 | s->sub_map[what] = sub; | |
224ce89b | 267 | |
7c673cae FG |
268 | if (!subs.count(what)) |
269 | subs[what] = new xlist<Subscription*>; | |
270 | subs[what]->push_back(&sub->type_item); | |
271 | } | |
272 | sub->next = start; | |
273 | sub->onetime = onetime; | |
274 | sub->incremental_onetime = onetime && incremental_onetime; | |
275 | } | |
276 | ||
277 | void remove_sub(Subscription *sub) { | |
278 | sub->session->sub_map.erase(sub->type); | |
279 | sub->type_item.remove_myself(); | |
280 | delete sub; | |
281 | } | |
282 | }; | |
283 | ||
9f95a23c | 284 | inline std::ostream& operator<<(std::ostream& out, const MonSession& s) |
7c673cae | 285 | { |
11fdf7f2 TL |
286 | out << "MonSession(" << s.name << " " << s.addrs |
287 | << " is " << (s.closed ? "closed" : "open") | |
288 | << " " << s.caps | |
289 | << ", features 0x" << std::hex << s.con_features << std::dec | |
1adf2230 AA |
290 | << " (" << ceph_release_name(ceph_release_from_features(s.con_features)) |
291 | << "))"; | |
7c673cae FG |
292 | return out; |
293 | } | |
294 | ||
295 | #endif |