1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
15 #ifndef CEPH_MON_SESSION_H
16 #define CEPH_MON_SESSION_H
19 #include <string_view>
21 #include "include/utime.h"
22 #include "include/xlist.h"
24 #include "global/global_context.h"
25 #include "msg/msg_types.h"
26 #include "mon/mon_types.h"
28 #include "auth/AuthServiceHandler.h"
29 #include "osd/OSDMap.h"
38 xlist
<Subscription
*>::item type_item
;
41 bool incremental_onetime
; // has CEPH_FEATURE_INCSUBOSDMAP
43 Subscription(MonSession
*s
, const std::string
& t
) : session(s
), type(t
), type_item(this),
44 next(0), onetime(false), incremental_onetime(false) {}
47 struct MonSession
: public RefCountedObject
{
50 uint64_t con_features
= 0; // zero if AnonConnection
52 entity_addrvec_t addrs
;
53 entity_addr_t socket_addr
;
54 utime_t session_timeout
;
56 xlist
<MonSession
*>::item item
;
57 std::set
<uint64_t> routed_request_tids
;
59 bool validated_stretch_connection
= false;
61 bool authenticated
= false; ///< true if auth handshake is complete
63 std::map
<std::string
, Subscription
*> sub_map
;
64 epoch_t osd_epoch
= 0; ///< the osdmap epoch sent to the mon client
66 AuthServiceHandler
*auth_handler
= nullptr;
67 EntityName entity_name
;
68 uint64_t global_id
= 0;
69 global_id_status_t global_id_status
= global_id_status_t::NONE
;
71 ConnectionRef proxy_con
;
72 uint64_t proxy_tid
= 0;
74 std::string remote_host
; ///< remote host name
75 std::map
<std::string
,std::string
,std::less
<>> last_config
; ///< most recently shared config
76 bool any_config
= false;
78 MonSession(Connection
*c
)
79 : RefCountedObject(g_ceph_context
),
83 void _ident(const entity_name_t
& n
, const entity_addrvec_t
& av
) {
84 con_type
= con
->get_peer_type();
87 socket_addr
= con
->get_peer_socket_addr();
88 if (con
->get_messenger()) {
89 // only fill in features if this is a non-anonymous connection
90 con_features
= con
->get_features();
94 ~MonSession() override
{
95 //generic_dout(0) << "~MonSession " << this << dendl;
96 // we should have been removed before we get destructed; see MonSessionMap::remove_session()
97 ceph_assert(!item
.is_on_list());
98 ceph_assert(sub_map
.empty());
102 bool is_capable(std::string service
, int mask
) {
103 std::map
<std::string
,std::string
> args
;
104 return caps
.is_capable(
108 mask
& MON_CAP_R
, mask
& MON_CAP_W
, mask
& MON_CAP_X
,
109 get_peer_socket_addr());
112 std::vector
<string
> get_allowed_fs_names() const {
113 return caps
.allowed_fs_names();
116 bool fs_name_capable(string_view fsname
, __u8 mask
) {
117 return caps
.fs_name_capable(entity_name
, fsname
, mask
);
120 const entity_addr_t
& get_peer_socket_addr() {
124 void dump(ceph::Formatter
*f
) const {
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
);
137 f
->dump_unsigned("global_id", global_id
);
138 f
->dump_stream("global_id_status") << global_id_status
;
139 f
->dump_unsigned("osd_epoch", osd_epoch
);
140 f
->dump_string("remote_host", remote_host
);
145 struct MonSessionMap
{
146 xlist
<MonSession
*> sessions
;
147 std::map
<std::string
, xlist
<Subscription
*>* > subs
;
148 std::multimap
<int, MonSession
*> by_osd
;
149 FeatureMap feature_map
; // type -> features -> count
153 while (!subs
.empty()) {
154 ceph_assert(subs
.begin()->second
->empty());
155 delete subs
.begin()->second
;
156 subs
.erase(subs
.begin());
160 unsigned get_size() const {
161 return sessions
.size();
164 void remove_session(MonSession
*s
) {
165 ceph_assert(!s
->closed
);
166 for (std::map
<std::string
,Subscription
*>::iterator p
= s
->sub_map
.begin(); p
!= s
->sub_map
.end(); ++p
) {
167 p
->second
->type_item
.remove_myself();
171 s
->item
.remove_myself();
172 if (s
->name
.is_osd() &&
173 s
->name
.num() >= 0) {
174 for (auto p
= by_osd
.find(s
->name
.num());
175 p
->first
== s
->name
.num();
177 if (p
->second
== s
) {
182 if (s
->con_features
) {
183 feature_map
.rm(s
->con_type
, s
->con_features
);
189 MonSession
*new_session(const entity_name_t
& n
,
190 const entity_addrvec_t
& av
,
192 MonSession
*s
= new MonSession(c
);
199 void add_session(MonSession
*s
) {
200 s
->session_timeout
= ceph_clock_now();
201 s
->session_timeout
+= g_conf()->mon_session_timeout
;
203 sessions
.push_back(&s
->item
);
205 if (s
->name
.is_osd() &&
206 s
->name
.num() >= 0) {
207 by_osd
.insert(std::pair
<int,MonSession
*>(s
->name
.num(), s
));
209 if (s
->con_features
) {
210 feature_map
.add(s
->con_type
, s
->con_features
);
214 MonSession
*get_random_osd_session(OSDMap
*osdmap
) {
215 // ok, this isn't actually random, but close enough.
218 int n
= by_osd
.rbegin()->first
+ 1;
221 auto p
= by_osd
.lower_bound(r
);
222 if (p
== by_osd
.end())
229 MonSession
*s
= NULL
;
233 bool backward
= true, forward
= true;
234 while (backward
|| forward
) {
236 if (osdmap
->is_up(b
->first
) &&
237 osdmap
->get_addrs(b
->first
) == b
->second
->con
->get_peer_addrs()) {
241 if (b
!= by_osd
.begin())
247 forward
= (f
!= by_osd
.end());
249 if (osdmap
->is_up(f
->first
)) {
260 void add_update_sub(MonSession
*s
, const std::string
& what
, version_t start
, bool onetime
, bool incremental_onetime
) {
261 Subscription
*sub
= 0;
262 if (s
->sub_map
.count(what
)) {
263 sub
= s
->sub_map
[what
];
265 sub
= new Subscription(s
, what
);
266 s
->sub_map
[what
] = sub
;
268 if (!subs
.count(what
))
269 subs
[what
] = new xlist
<Subscription
*>;
270 subs
[what
]->push_back(&sub
->type_item
);
273 sub
->onetime
= onetime
;
274 sub
->incremental_onetime
= onetime
&& incremental_onetime
;
277 void remove_sub(Subscription
*sub
) {
278 sub
->session
->sub_map
.erase(sub
->type
);
279 sub
->type_item
.remove_myself();
284 inline std::ostream
& operator<<(std::ostream
& out
, const MonSession
& s
)
286 out
<< "MonSession(" << s
.name
<< " " << s
.addrs
287 << " is " << (s
.closed
? "closed" : "open")
289 << ", features 0x" << std::hex
<< s
.con_features
<< std::dec
290 << " (" << ceph_release_name(ceph_release_from_features(s
.con_features
))