]>
git.proxmox.com Git - ceph.git/blob - ceph/src/mon/ElectionLogic.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "ElectionLogic.h"
17 #include "include/ceph_assert.h"
18 #include "common/dout.h"
20 #define dout_subsys ceph_subsys_mon
22 #define dout_prefix _prefix(_dout, epoch, elector)
23 static ostream
& _prefix(std::ostream
*_dout
, epoch_t epoch
, ElectionOwner
* elector
) {
24 return *_dout
<< "paxos." << elector
->get_my_rank()
25 << ").electionLogic(" << epoch
<< ") ";
27 void ElectionLogic::init()
29 epoch
= elector
->read_persisted_epoch();
31 ldout(cct
, 1) << "init, first boot, initializing epoch at 1 " << dendl
;
33 } else if (epoch
% 2) {
34 ldout(cct
, 1) << "init, last seen epoch " << epoch
35 << ", mid-election, bumping" << dendl
;
37 elector
->persist_epoch(epoch
);
39 ldout(cct
, 1) << "init, last seen epoch " << epoch
<< dendl
;
43 void ElectionLogic::bump_epoch(epoch_t e
)
45 ldout(cct
, 10) << __func__
<< epoch
<< " to " << e
<< dendl
;
46 ceph_assert(epoch
<= e
);
48 elector
->persist_epoch(epoch
);
49 // clear up some state
52 elector
->notify_bump_epoch();
55 void ElectionLogic::declare_standalone_victory()
57 assert(elector
->paxos_size() == 1 && elector
->get_my_rank() == 0);
62 void ElectionLogic::start()
65 ldout(cct
, 0) << "not starting new election -- not participating" << dendl
;
68 ldout(cct
, 5) << "start -- can i be leader?" << dendl
;
73 // start by trying to elect me
75 bump_epoch(epoch
+1); // odd == election cycle
77 elector
->validate_store();
80 acked_me
.insert(elector
->get_my_rank());
83 elector
->propose_to_peers(epoch
);
87 void ElectionLogic::defer(int who
)
89 ldout(cct
, 5) << "defer to " << who
<< dendl
;
99 elector
->_defer_to(who
);
102 void ElectionLogic::end_election_period()
104 ldout(cct
, 5) << "election period ended" << dendl
;
108 acked_me
.size() > (elector
->paxos_size() / 2)) {
112 // whoever i deferred to didn't declare victory quickly enough.
113 if (elector
->ever_participated())
116 elector
->reset_election();
121 void ElectionLogic::declare_victory()
127 new_quorum
.swap(acked_me
);
129 ceph_assert(epoch
% 2 == 1); // election
130 bump_epoch(epoch
+1); // is over!
132 elector
->message_victory(new_quorum
);
135 void ElectionLogic::receive_propose(int from
, epoch_t mepoch
)
137 if (mepoch
> epoch
) {
139 } else if (mepoch
< epoch
) {
140 // got an "old" propose,
141 if (epoch
% 2 == 0 && // in a non-election cycle
142 !elector
->is_current_member(from
)) { // from someone outside the quorum
143 // a mon just started up, call a new election so they can rejoin!
144 ldout(cct
, 5) << " got propose from old epoch, "
145 << from
<< " must have just started" << dendl
;
146 // we may be active; make sure we reset things in the monitor appropriately.
147 elector
->trigger_new_election();
149 ldout(cct
, 5) << " ignoring old propose" << dendl
;
154 if (elector
->get_my_rank() < from
) {
155 // i would win over them.
156 if (leader_acked
>= 0) { // we already acked someone
157 ceph_assert(leader_acked
< from
); // and they still win, of course
158 ldout(cct
, 5) << "no, we already acked " << leader_acked
<< dendl
;
160 // wait, i should win!
162 elector
->trigger_new_election();
166 // they would win over me
167 if (leader_acked
< 0 || // haven't acked anyone yet, or
168 leader_acked
> from
|| // they would win over who you did ack, or
169 leader_acked
== from
) { // this is the guy we're already deferring to
173 ldout(cct
, 5) << "no, we already acked " << leader_acked
<< dendl
;
178 void ElectionLogic::receive_ack(int from
, epoch_t from_epoch
)
180 ceph_assert(from_epoch
% 2 == 1); // sender in an election epoch
181 if (from_epoch
> epoch
) {
182 ldout(cct
, 5) << "woah, that's a newer epoch, i must have rebooted. bumping and re-starting!" << dendl
;
183 bump_epoch(from_epoch
);
187 // is that _everyone_?
189 acked_me
.insert(from
);
190 if (acked_me
.size() == elector
->paxos_size()) {
191 // if yes, shortcut to election finish
195 // ignore, i'm deferring already.
196 ceph_assert(leader_acked
>= 0);
200 bool ElectionLogic::receive_victory_claim(int from
, epoch_t from_epoch
)
202 ceph_assert(from
< elector
->get_my_rank());
203 ceph_assert(from_epoch
% 2 == 0);
207 // i should have seen this election if i'm getting the victory.
208 if (from_epoch
!= epoch
+ 1) {
209 ldout(cct
, 5) << "woah, that's a funny epoch, i must have rebooted. bumping and re-starting!" << dendl
;
210 bump_epoch(from_epoch
);
215 bump_epoch(from_epoch
);