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