]> git.proxmox.com Git - ceph.git/blob - ceph/src/crimson/mgr/client.cc
6e3d7cdd848c007970be328b8e2d5b6241499eb4
[ceph.git] / ceph / src / crimson / mgr / client.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "client.h"
5
6 #include <seastar/core/sleep.hh>
7
8 #include "crimson/common/log.h"
9 #include "crimson/net/Connection.h"
10 #include "crimson/net/Messenger.h"
11 #include "messages/MMgrConfigure.h"
12 #include "messages/MMgrMap.h"
13 #include "messages/MMgrOpen.h"
14
15 namespace {
16 seastar::logger& logger()
17 {
18 return crimson::get_logger(ceph_subsys_mgrc);
19 }
20 }
21
22 using crimson::common::local_conf;
23
24 namespace crimson::mgr
25 {
26
27 Client::Client(crimson::net::Messenger& msgr,
28 WithStats& with_stats)
29 : msgr{msgr},
30 with_stats{with_stats},
31 report_timer{[this] {report();}}
32 {}
33
34 seastar::future<> Client::start()
35 {
36 return seastar::now();
37 }
38
39 seastar::future<> Client::stop()
40 {
41 logger().info("{}", __func__);
42 report_timer.cancel();
43 auto fut = gate.close();
44 if (conn) {
45 conn->mark_down();
46 }
47 return fut;
48 }
49
50 std::optional<seastar::future<>>
51 Client::ms_dispatch(crimson::net::ConnectionRef conn, MessageRef m)
52 {
53 bool dispatched = true;
54 gate.dispatch_in_background(__func__, *this, [this, conn, &m, &dispatched] {
55 switch(m->get_type()) {
56 case MSG_MGR_MAP:
57 return handle_mgr_map(conn, boost::static_pointer_cast<MMgrMap>(m));
58 case MSG_MGR_CONFIGURE:
59 return handle_mgr_conf(conn, boost::static_pointer_cast<MMgrConfigure>(m));
60 default:
61 dispatched = false;
62 return seastar::now();
63 }
64 });
65 return (dispatched ? std::make_optional(seastar::now()) : std::nullopt);
66 }
67
68 void Client::ms_handle_connect(crimson::net::ConnectionRef c)
69 {
70 gate.dispatch_in_background(__func__, *this, [this, c] {
71 if (conn == c) {
72 // ask for the mgrconfigure message
73 auto m = crimson::make_message<MMgrOpen>();
74 m->daemon_name = local_conf()->name.get_id();
75 return conn->send(std::move(m));
76 } else {
77 return seastar::now();
78 }
79 });
80 }
81
82 void Client::ms_handle_reset(crimson::net::ConnectionRef c, bool /* is_replace */)
83 {
84 gate.dispatch_in_background(__func__, *this, [this, c] {
85 if (conn == c) {
86 report_timer.cancel();
87 return reconnect();
88 } else {
89 return seastar::now();
90 }
91 });
92 }
93
94 seastar::future<> Client::reconnect()
95 {
96 if (conn) {
97 conn->mark_down();
98 conn = {};
99 }
100 if (!mgrmap.get_available()) {
101 logger().warn("No active mgr available yet");
102 return seastar::now();
103 }
104 auto retry_interval = std::chrono::duration<double>(
105 local_conf().get_val<double>("mgr_connect_retry_interval"));
106 auto a_while = std::chrono::duration_cast<seastar::steady_clock_type::duration>(
107 retry_interval);
108 return seastar::sleep(a_while).then([this] {
109 auto peer = mgrmap.get_active_addrs().pick_addr(msgr.get_myaddr().get_type());
110 if (peer == entity_addr_t{}) {
111 // crimson msgr only uses the first bound addr
112 logger().error("mgr.{} does not have an addr compatible with me",
113 mgrmap.get_active_name());
114 return;
115 }
116 conn = msgr.connect(peer, CEPH_ENTITY_TYPE_MGR);
117 });
118 }
119
120 seastar::future<> Client::handle_mgr_map(crimson::net::ConnectionRef,
121 Ref<MMgrMap> m)
122 {
123 mgrmap = m->get_map();
124 if (!conn) {
125 return reconnect();
126 } else if (conn->get_peer_addr() !=
127 mgrmap.get_active_addrs().legacy_addr()) {
128 return reconnect();
129 } else {
130 return seastar::now();
131 }
132 }
133
134 seastar::future<> Client::handle_mgr_conf(crimson::net::ConnectionRef,
135 Ref<MMgrConfigure> m)
136 {
137 logger().info("{} {}", __func__, *m);
138
139 auto report_period = std::chrono::seconds{m->stats_period};
140 if (report_period.count()) {
141 if (report_timer.armed()) {
142 report_timer.rearm(report_timer.get_timeout(), report_period);
143 } else {
144 report_timer.arm_periodic(report_period);
145 }
146 } else {
147 report_timer.cancel();
148 }
149 return seastar::now();
150 }
151
152 void Client::report()
153 {
154 gate.dispatch_in_background(__func__, *this, [this] {
155 if (!conn) {
156 logger().warn("report: no conn available; raport skipped");
157 return seastar::now();
158 }
159 return with_stats.get_stats(
160 ).then([this](auto &&pg_stats) {
161 return conn->send(std::move(pg_stats));
162 });
163 });
164 }
165
166 void Client::print(std::ostream& out) const
167 {
168 out << "mgrc ";
169 }
170
171 }