]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "common/dout.h" | |
5 | ||
6 | #include "mds/MDSRank.h" | |
7 | #include "mds/MDSPinger.h" | |
8 | ||
9 | #define dout_context g_ceph_context | |
10 | #define dout_subsys ceph_subsys_mds | |
11 | #undef dout_prefix | |
12 | #define dout_prefix *_dout << "mds.pinger " << __func__ | |
13 | ||
14 | MDSPinger::MDSPinger(MDSRank *mds) | |
15 | : mds(mds) { | |
16 | } | |
17 | ||
18 | void MDSPinger::send_ping(mds_rank_t rank, const entity_addrvec_t &addr) { | |
19 | dout(10) << ": rank=" << rank << dendl; | |
20 | ||
21 | std::scoped_lock locker(lock); | |
22 | auto [it, inserted] = ping_state_by_rank.emplace(rank, PingState()); | |
23 | if (inserted) { | |
24 | dout(20) << ": init ping pong state for rank=" << rank << dendl; | |
25 | } | |
26 | ||
27 | auto &ping_state = it->second; | |
28 | auto last_seq = ping_state.last_seq++; | |
29 | ||
30 | ping_state.seq_time_map.emplace(last_seq, clock::now()); | |
31 | ||
32 | dout(10) << ": sending ping with sequence=" << last_seq << " to rank=" | |
33 | << rank << dendl; | |
34 | mds->send_message_mds(make_message<MMDSPing>(last_seq), addr); | |
35 | } | |
36 | ||
37 | bool MDSPinger::pong_received(mds_rank_t rank, version_t seq) { | |
38 | dout(10) << ": rank=" << rank << ", sequence=" << seq << dendl; | |
39 | ||
40 | std::scoped_lock locker(lock); | |
41 | auto it1 = ping_state_by_rank.find(rank); | |
42 | if (it1 == ping_state_by_rank.end()) { | |
43 | // this *might* just happen on mds failover when a non-rank-0 mds | |
44 | // acks backs a ping message from an earlier rank 0 mds to a newly | |
45 | // appointed rank 0 mds (possible?). | |
46 | // or when non rank 0 active MDSs begin sending metric updates before | |
47 | // rank 0 can start pinging it (although, that should resolve out soon). | |
48 | dout(10) << ": received pong from rank=" << rank << " to which ping was never" | |
49 | << " sent (ignoring...)." << dendl; | |
50 | return false; | |
51 | } | |
52 | ||
53 | auto &ping_state = it1->second; | |
54 | // find incoming seq timestamp for updation | |
55 | auto it2 = ping_state.seq_time_map.find(seq); | |
56 | if (it2 == ping_state.seq_time_map.end()) { | |
57 | // rank still bootstrapping | |
58 | dout(10) << ": pong received for unknown ping sequence " << seq | |
59 | << ", rank " << rank << " should catch up soon." << dendl; | |
60 | return false; | |
61 | } | |
62 | ||
63 | ping_state.last_acked_time = it2->second; | |
64 | ping_state.seq_time_map.erase(ping_state.seq_time_map.begin(), it2); | |
65 | ||
66 | return true; | |
67 | } | |
68 | ||
69 | void MDSPinger::reset_ping(mds_rank_t rank) { | |
70 | dout(10) << ": rank=" << rank << dendl; | |
71 | ||
72 | std::scoped_lock locker(lock); | |
73 | auto it = ping_state_by_rank.find(rank); | |
74 | if (it == ping_state_by_rank.end()) { | |
75 | dout(10) << ": rank=" << rank << " was never sent ping request." << dendl; | |
76 | return; | |
77 | } | |
78 | ||
79 | // remove the rank from ping state, send_ping() will init it | |
80 | // later when invoked. | |
81 | ping_state_by_rank.erase(it); | |
82 | } | |
83 | ||
84 | bool MDSPinger::is_rank_lagging(mds_rank_t rank) { | |
85 | dout(10) << ": rank=" << rank << dendl; | |
86 | ||
87 | std::scoped_lock locker(lock); | |
88 | auto it = ping_state_by_rank.find(rank); | |
89 | if (it == ping_state_by_rank.end()) { | |
90 | derr << ": rank=" << rank << " was never sent ping request." << dendl; | |
91 | return false; | |
92 | } | |
93 | ||
94 | auto now = clock::now(); | |
95 | auto since = std::chrono::duration<double>(now - it->second.last_acked_time).count(); | |
96 | if (since > g_conf().get_val<std::chrono::seconds>("mds_ping_grace").count()) { | |
97 | dout(5) << ": rank=" << rank << " is lagging a pong response (last ack time is " | |
98 | << it->second.last_acked_time << ")" << dendl; | |
99 | return true; | |
100 | } | |
101 | ||
102 | return false; | |
103 | } |