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