--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2012 Inktank, Inc.
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#pragma once
+
+struct MTimeCheck2 : public Message
+{
+ static const int HEAD_VERSION = 1;
+ static const int COMPAT_VERSION = 1;
+
+ enum {
+ OP_PING = 1,
+ OP_PONG = 2,
+ OP_REPORT = 3,
+ };
+
+ int op = 0;
+ version_t epoch = 0;
+ version_t round = 0;
+
+ utime_t timestamp;
+ map<int, double> skews;
+ map<int, double> latencies;
+
+ MTimeCheck2() : Message(MSG_TIMECHECK2, HEAD_VERSION, COMPAT_VERSION) { }
+ MTimeCheck2(int op) :
+ Message(MSG_TIMECHECK2, HEAD_VERSION, COMPAT_VERSION),
+ op(op)
+ { }
+
+private:
+ ~MTimeCheck2() override { }
+
+public:
+ const char *get_type_name() const override { return "time_check2"; }
+ const char *get_op_name() const {
+ switch (op) {
+ case OP_PING: return "ping";
+ case OP_PONG: return "pong";
+ case OP_REPORT: return "report";
+ }
+ return "???";
+ }
+ void print(ostream &o) const override {
+ o << "time_check( " << get_op_name()
+ << " e " << epoch << " r " << round;
+ if (op == OP_PONG) {
+ o << " ts " << timestamp;
+ } else if (op == OP_REPORT) {
+ o << " #skews " << skews.size()
+ << " #latencies " << latencies.size();
+ }
+ o << " )";
+ }
+
+ void decode_payload() override {
+ auto p = payload.cbegin();
+ decode(op, p);
+ decode(epoch, p);
+ decode(round, p);
+ decode(timestamp, p);
+ decode(skews, p);
+ decode(latencies, p);
+ }
+
+ void encode_payload(uint64_t features) override {
+ using ceph::encode;
+ encode(op, payload);
+ encode(epoch, payload);
+ encode(round, payload);
+ encode(timestamp, payload);
+ encode(skews, payload, features);
+ encode(latencies, payload, features);
+ }
+};
#include "messages/MAuthReply.h"
-#include "messages/MTimeCheck.h"
+#include "messages/MTimeCheck2.h"
#include "messages/MPing.h"
#include "common/strtol.h"
if (!timecheck_skews.empty()) {
f->open_object_section("time_skew_status");
for (auto& i : timecheck_skews) {
- entity_inst_t inst = i.first;
double skew = i.second;
- double latency = timecheck_latencies[inst];
- string name = monmap->get_name(inst.addr);
+ double latency = timecheck_latencies[i.first];
+ string name = monmap->get_name(i.first);
ostringstream tcss;
health_status_t tcstatus = timecheck_status(tcss, skew, latency);
f->open_object_section(name.c_str());
return;
case MSG_TIMECHECK:
+ dout(5) << __func__ << " ignoring " << op << dendl;
+ return;
+ case MSG_TIMECHECK2:
handle_timecheck(op);
return;
{
dout(10) << __func__ << dendl;
timecheck_cleanup();
- timecheck_start_round();
+ if (get_quorum_mon_features().contains_all(
+ ceph::features::mon::FEATURE_NAUTILUS)) {
+ timecheck_start_round();
+ }
}
void Monitor::timecheck_finish()
dout(10) << __func__ << " " << timecheck_waiting.size()
<< " peers still waiting:";
- for (map<entity_inst_t,utime_t>::iterator p = timecheck_waiting.begin();
- p != timecheck_waiting.end(); ++p) {
- *_dout << " " << p->first.name;
+ for (auto& p : timecheck_waiting) {
+ *_dout << " mon." << p.first;
}
*_dout << dendl;
timecheck_waiting.clear();
assert(timecheck_latencies.size() == timecheck_skews.size());
bool found_skew = false;
- for (map<entity_inst_t, double>::iterator p = timecheck_skews.begin();
- p != timecheck_skews.end(); ++p) {
-
+ for (auto& p : timecheck_skews) {
double abs_skew;
- if (timecheck_has_skew(p->second, &abs_skew)) {
+ if (timecheck_has_skew(p.second, &abs_skew)) {
dout(10) << __func__
- << " " << p->first << " skew " << abs_skew << dendl;
+ << " " << p.first << " skew " << abs_skew << dendl;
found_skew = true;
}
}
if (monmap->get_name(*q) == name)
continue;
- MTimeCheck *m = new MTimeCheck(MTimeCheck::OP_REPORT);
+ MTimeCheck2 *m = new MTimeCheck2(MTimeCheck2::OP_REPORT);
m->epoch = get_epoch();
m->round = timecheck_round;
- for (map<entity_inst_t, double>::iterator it = timecheck_skews.begin();
- it != timecheck_skews.end(); ++it) {
- double skew = it->second;
- double latency = timecheck_latencies[it->first];
+ for (auto& it : timecheck_skews) {
+ double skew = it.second;
+ double latency = timecheck_latencies[it.first];
- m->skews[it->first] = skew;
- m->latencies[it->first] = latency;
+ m->skews[it.first] = skew;
+ m->latencies[it.first] = latency;
if (do_output) {
- dout(25) << __func__ << " " << it->first
+ dout(25) << __func__ << " mon." << it.first
<< " latency " << latency
<< " skew " << skew << dendl;
}
}
do_output = false;
+ dout(10) << __func__ << " send report to mon." << *q << dendl;
entity_inst_t inst = monmap->get_inst(*q);
- dout(10) << __func__ << " send report to " << inst << dendl;
messenger->send_message(m, inst);
}
}
<< " round " << timecheck_round << dendl;
// we are at the eye of the storm; the point of reference
- timecheck_skews[messenger->get_myinst()] = 0.0;
- timecheck_latencies[messenger->get_myinst()] = 0.0;
+ timecheck_skews[rank] = 0.0;
+ timecheck_latencies[rank] = 0.0;
for (set<int>::iterator it = quorum.begin(); it != quorum.end(); ++it) {
if (monmap->get_name(*it) == name)
entity_inst_t inst = monmap->get_inst(*it);
utime_t curr_time = ceph_clock_now();
- timecheck_waiting[inst] = curr_time;
- MTimeCheck *m = new MTimeCheck(MTimeCheck::OP_PING);
+ timecheck_waiting[*it] = curr_time;
+ MTimeCheck2 *m = new MTimeCheck2(MTimeCheck2::OP_PING);
m->epoch = get_epoch();
m->round = timecheck_round;
- dout(10) << __func__ << " send " << *m << " to " << inst << dendl;
+ dout(10) << __func__ << " send " << *m << " to mon." << *it << dendl;
messenger->send_message(m, inst);
}
}
void Monitor::handle_timecheck_leader(MonOpRequestRef op)
{
- MTimeCheck *m = static_cast<MTimeCheck*>(op->get_req());
+ MTimeCheck2 *m = static_cast<MTimeCheck2*>(op->get_req());
dout(10) << __func__ << " " << *m << dendl;
/* handles PONG's */
- assert(m->op == MTimeCheck::OP_PONG);
+ assert(m->op == MTimeCheck2::OP_PONG);
- entity_inst_t other = m->get_source_inst();
+ int other = m->get_source().num();
if (m->epoch < get_epoch()) {
dout(1) << __func__ << " got old timecheck epoch " << m->epoch
<< " from " << other
void Monitor::handle_timecheck_peon(MonOpRequestRef op)
{
- MTimeCheck *m = static_cast<MTimeCheck*>(op->get_req());
+ MTimeCheck2 *m = static_cast<MTimeCheck2*>(op->get_req());
dout(10) << __func__ << " " << *m << dendl;
assert(is_peon());
- assert(m->op == MTimeCheck::OP_PING || m->op == MTimeCheck::OP_REPORT);
+ assert(m->op == MTimeCheck2::OP_PING || m->op == MTimeCheck2::OP_REPORT);
if (m->epoch != get_epoch()) {
dout(1) << __func__ << " got wrong epoch "
timecheck_round = m->round;
- if (m->op == MTimeCheck::OP_REPORT) {
+ if (m->op == MTimeCheck2::OP_REPORT) {
assert((timecheck_round % 2) == 0);
timecheck_latencies.swap(m->latencies);
timecheck_skews.swap(m->skews);
}
assert((timecheck_round % 2) != 0);
- MTimeCheck *reply = new MTimeCheck(MTimeCheck::OP_PONG);
+ MTimeCheck2 *reply = new MTimeCheck2(MTimeCheck2::OP_PONG);
utime_t curr_time = ceph_clock_now();
reply->timestamp = curr_time;
reply->epoch = m->epoch;
void Monitor::handle_timecheck(MonOpRequestRef op)
{
- MTimeCheck *m = static_cast<MTimeCheck*>(op->get_req());
+ MTimeCheck2 *m = static_cast<MTimeCheck2*>(op->get_req());
dout(10) << __func__ << " " << *m << dendl;
if (is_leader()) {
- if (m->op != MTimeCheck::OP_PONG) {
+ if (m->op != MTimeCheck2::OP_PONG) {
dout(1) << __func__ << " drop unexpected msg (not pong)" << dendl;
} else {
handle_timecheck_leader(op);
}
} else if (is_peon()) {
- if (m->op != MTimeCheck::OP_PING && m->op != MTimeCheck::OP_REPORT) {
+ if (m->op != MTimeCheck2::OP_PING && m->op != MTimeCheck2::OP_REPORT) {
dout(1) << __func__ << " drop unexpected msg (not ping or report)" << dendl;
} else {
handle_timecheck_peon(op);