Heartbeat::Peer::~Peer()
{ disconnect(); }
-bool Heartbeat::Peer::is_unhealthy(clock::time_point now) const
+bool Heartbeat::Peer::pinged() const
{
- if (ping_history.empty()) {
- // we haven't sent a ping yet or we have got all replies,
- // in either way we are safe and healthy for now
+ if (clock::is_zero(first_tx)) {
+ // i can never receive a pong without sending any ping message first.
+ assert(clock::is_zero(last_rx_front) &&
+ clock::is_zero(last_rx_back));
return false;
} else {
- auto oldest_ping = ping_history.begin();
- return now > oldest_ping->second.deadline;
+ return true;
}
}
-bool Heartbeat::Peer::is_healthy(clock::time_point now) const
+Heartbeat::Peer::health_state
+Heartbeat::Peer::do_health_screen(clock::time_point now) const
{
- if (clock::is_zero(last_rx_front)) {
- return false;
- }
- if (clock::is_zero(last_rx_back)) {
- return false;
+ if (!pinged()) {
+ // we are not healty nor unhealty because we haven't sent anything yet
+ return health_state::UNKNOWN;
+ } else if (!ping_history.empty() && ping_history.begin()->second.deadline < now) {
+ return health_state::UNHEALTHY;
+ } else if (!clock::is_zero(last_rx_front) &&
+ !clock::is_zero(last_rx_back)) {
+ // only declare to be healthy until we have received the first
+ // replies from both front/back connections
+ return health_state::HEALTHY;
+ } else {
+ return health_state::UNKNOWN;
}
- // only declare to be healthy until we have received the first
- // replies from both front/back connections
- return !is_unhealthy(now);
}
Heartbeat::clock::time_point
Heartbeat::Peer::failed_since(clock::time_point now) const
{
- if (clock::is_zero(first_tx)) {
- return clock::zero();
- }
- if (!is_unhealthy(now)) {
- return clock::zero();
- }
-
- auto oldest_deadline = ping_history.begin()->second.deadline;
- auto failed_since = std::min(last_rx_back, last_rx_front);
- if (clock::is_zero(failed_since)) {
- logger().error("failed_since: no reply from osd.{} "
- "ever on either front or back, first ping sent {} "
- "(oldest deadline {})",
- peer, first_tx, oldest_deadline);
- failed_since = first_tx;
+ if (do_health_screen(now) == health_state::UNHEALTHY) {
+ auto oldest_deadline = ping_history.begin()->second.deadline;
+ auto failed_since = std::min(last_rx_back, last_rx_front);
+ if (clock::is_zero(failed_since)) {
+ logger().error("failed_since: no reply from osd.{} "
+ "ever on either front or back, first ping sent {} "
+ "(oldest deadline {})",
+ peer, first_tx, oldest_deadline);
+ failed_since = first_tx;
+ } else {
+ logger().error("failed_since: no reply from osd.{} "
+ "since back {} front {} (oldest deadline {})",
+ peer, last_rx_back, last_rx_front, oldest_deadline);
+ }
+ return failed_since;
} else {
- logger().error("failed_since: no reply from osd.{} "
- "since back {} front {} (oldest deadline {})",
- peer, last_rx_back, last_rx_front, oldest_deadline);
+ return clock::zero();
}
- return failed_since;
}
void Heartbeat::Peer::send_heartbeat(
ceph::signedspan mnow,
std::vector<seastar::future<>>& futures)
{
- if (clock::is_zero(first_tx)) {
+ if (!pinged()) {
first_tx = now;
}
last_tx = now;
if (unacked == 0) {
ping_history.erase(ping_history.begin(), ++ping);
}
- if (is_healthy(now)) {
+ if (do_health_screen(now) == health_state::HEALTHY) {
// cancel false reports
if (auto pending = heartbeat.failure_pending.find(peer);
pending != heartbeat.failure_pending.end()) {