}
start_stamp = ceph_clock_now(g_ceph_context);
electing_me = true;
- acked_me[mon->rank] = CEPH_FEATURES_ALL;
+ acked_me[mon->rank].cluster_features = CEPH_FEATURES_ALL;
+ acked_me[mon->rank].mon_features = ceph::features::mon::get_supported();
leader_acked = -1;
// bcast to everyone else
for (unsigned i=0; i<mon->monmap->size(); ++i) {
if ((int)i == mon->rank) continue;
- Message *m = new MMonElection(MMonElection::OP_PROPOSE, epoch, mon->monmap);
+ MMonElection *m =
+ new MMonElection(MMonElection::OP_PROPOSE, epoch, mon->monmap);
+ m->mon_features = ceph::features::mon::get_supported();
mon->messenger->send_message(m, mon->monmap->get_inst(i));
}
leader_acked = who;
ack_stamp = ceph_clock_now(g_ceph_context);
MMonElection *m = new MMonElection(MMonElection::OP_ACK, epoch, mon->monmap);
+ m->mon_features = ceph::features::mon::get_supported();
m->sharing_bl = mon->get_supported_commands_bl();
mon->messenger->send_message(m, mon->monmap->get_inst(who));
leader_acked = -1;
electing_me = false;
- uint64_t features = CEPH_FEATURES_ALL;
+ uint64_t cluster_features = CEPH_FEATURES_ALL;
+ mon_feature_t mon_features = ceph::features::mon::get_supported();
set<int> quorum;
- for (map<int, uint64_t>::iterator p = acked_me.begin(); p != acked_me.end();
+ for (map<int, elector_features_t>::iterator p = acked_me.begin();
+ p != acked_me.end();
++p) {
quorum.insert(p->first);
- features &= p->second;
+ cluster_features &= p->second.cluster_features;
+ mon_features &= p->second.mon_features;
}
// decide what command set we're supporting
if (*p == mon->rank) continue;
MMonElection *m = new MMonElection(MMonElection::OP_VICTORY, epoch, mon->monmap);
m->quorum = quorum;
- m->quorum_features = features;
+ m->quorum_features = cluster_features;
+ m->mon_features = mon_features;
m->sharing_bl = *cmds_bl;
mon->messenger->send_message(m, mon->monmap->get_inst(*p));
}
// tell monitor
- mon->win_election(epoch, quorum, features, cmds, cmdsize, ©_classic_mons);
+ mon->win_election(epoch, quorum,
+ cluster_features, mon_features,
+ cmds, cmdsize, ©_classic_mons);
}
<< " without required features" << dendl;
return;
}
-
+
if (electing_me) {
// thanks
- acked_me[from] = m->get_connection()->get_features();
+ acked_me[from].cluster_features = m->get_connection()->get_features();
+ acked_me[from].mon_features = m->mon_features;
if (!m->sharing_bl.length())
classic_mons.insert(from);
- dout(5) << " so far i have " << acked_me << dendl;
+ dout(5) << " so far i have {";
+ for (map<int, elector_features_t>::const_iterator p = acked_me.begin();
+ p != acked_me.end();
+ ++p) {
+ if (p != acked_me.begin())
+ *_dout << ",";
+ *_dout << " mon." << p->first << ":"
+ << " features " << p->second.cluster_features
+ << " " << p->second.mon_features;
+ }
+ *_dout << " }" << dendl;
// is that _everyone_?
if (acked_me.size() == mon->monmap->size()) {
{
op->mark_event("elector:handle_victory");
MMonElection *m = static_cast<MMonElection*>(op->get_req());
- dout(5) << "handle_victory from " << m->get_source() << " quorum_features " << m->quorum_features << dendl;
+ dout(5) << "handle_victory from " << m->get_source()
+ << " quorum_features " << m->quorum_features
+ << " " << m->mon_features
+ << dendl;
int from = m->get_source().num();
assert(from < mon->rank);
}
bump_epoch(m->epoch);
-
+
// they win
- mon->lose_election(epoch, m->quorum, from, m->quorum_features);
-
+ mon->lose_election(epoch, m->quorum, from,
+ m->quorum_features, m->mon_features);
+
// cancel my timer
cancel_timer();
#include "include/types.h"
#include "include/Context.h"
#include "mon/MonOpRequest.h"
+#include "mon/mon_types.h"
class Monitor;
* @{
*/
private:
+ /**
+ * @defgroup Elector_h_internal_types Internal Types
+ * @{
+ */
+ /**
+ * This struct will hold the features from a given peer.
+ * Features may both be the cluster's (in the form of a uint64_t), or
+ * mon-specific features. Instead of keeping maps to hold them both, or
+ * a pair, which would be weird, a struct to keep them seems appropriate.
+ */
+ struct elector_features_t {
+ uint64_t cluster_features;
+ mon_feature_t mon_features;
+ };
+
+ /**
+ * @}
+ */
+
/**
* The Monitor instance associated with this class.
*/
* If we are acked by everyone in the MonMap, we will declare
* victory. Also note each peer's feature set.
*/
- map<int, uint64_t> acked_me;
+ map<int, elector_features_t> acked_me;
set<int> classic_mons;
/**
* @}
// i'm ready!
messenger->add_dispatcher_tail(this);
-
bootstrap();
// encode command sets
const MonCommand *my_cmds;
int cmdsize;
get_locally_supported_monitor_commands(&my_cmds, &cmdsize);
- win_election(elector.get_epoch(), q, CEPH_FEATURES_ALL, my_cmds, cmdsize, NULL);
+ win_election(elector.get_epoch(), q,
+ CEPH_FEATURES_ALL,
+ ceph::features::mon::get_supported(),
+ my_cmds, cmdsize, NULL);
}
const utime_t& Monitor::get_leader_since() const
}
void Monitor::win_election(epoch_t epoch, set<int>& active, uint64_t features,
+ const mon_feature_t& mon_features,
const MonCommand *cmdset, int cmdsize,
const set<int> *classic_monitors)
{
dout(10) << __func__ << " epoch " << epoch << " quorum " << active
- << " features " << features << dendl;
+ << " features " << features
+ << " mon_features " << mon_features
+ << dendl;
assert(is_electing());
state = STATE_LEADER;
leader_since = ceph_clock_now(g_ceph_context);
leader = rank;
quorum = active;
quorum_features = features;
+ quorum_mon_features = mon_features;
outside_quorum.clear();
clog->info() << "mon." << name << "@" << rank
update_mon_metadata(rank, std::move(my_meta));
}
-void Monitor::lose_election(epoch_t epoch, set<int> &q, int l, uint64_t features)
+void Monitor::lose_election(epoch_t epoch, set<int> &q, int l,
+ uint64_t features,
+ const mon_feature_t& mon_features)
{
state = STATE_PEON;
leader_since = utime_t();
quorum = q;
outside_quorum.clear();
quorum_features = features;
+ quorum_mon_features = mon_features;
dout(10) << "lose_election, epoch " << epoch << " leader is mon" << leader
- << " quorum is " << quorum << " features are " << quorum_features << dendl;
+ << " quorum is " << quorum << " features are " << quorum_features
+ << " mon_features are " << quorum_mon_features
+ << dendl;
paxos->peon_init();
_finish_svc_election();
utime_t leader_since; // when this monitor became the leader, if it is the leader
utime_t exited_quorum; // time detected as not in quorum; 0 if in
uint64_t quorum_features; ///< intersection of quorum member feature bits
+ /**
+ * Intersection of quorum members mon-specific feature bits
+ */
+ mon_feature_t quorum_mon_features;
bufferlist supported_commands_bl; // encoded MonCommands we support
bufferlist classic_commands_bl; // encoded MonCommands supported by Dumpling
set<int> classic_mons; // set of "classic" monitors; only valid on leader
// end election (called by Elector)
void win_election(epoch_t epoch, set<int>& q,
uint64_t features,
+ const mon_feature_t& mon_features,
const MonCommand *cmdset, int cmdsize,
const set<int> *classic_monitors);
void lose_election(epoch_t epoch, set<int>& q, int l,
- uint64_t features); // end election (called by Elector)
+ uint64_t features,
+ const mon_feature_t& mon_features);
+ // end election (called by Elector)
void finish_election();
const bufferlist& get_supported_commands_bl() {