void Monitor::bootstrap()
{
- if (paxos->is_writing()) {
+ if (paxos->is_writing() || paxos->is_writing_previous()) {
dout(10) << "bootstrap flushing pending write" << dendl;
lock.Unlock();
store->flush();
}
if (prefix == "scrub") {
- while (paxos->is_writing()) {
+ while (paxos->is_writing() || paxos->is_writing_previous()) {
lock.Unlock();
store->flush();
lock.Lock();
dout(1) << "accept timeout, calling fresh election" << dendl;
accept_timeout_event = 0;
assert(mon->is_leader());
- assert(is_updating() || is_updating_previous() || is_writing());
+ assert(is_updating() || is_updating_previous() || is_writing() ||
+ is_writing_previous());
logger->inc(l_paxos_accept_timeout);
mon->bootstrap();
}
get_store()->queue_transaction(t, new C_Committed(this));
- state = STATE_WRITING;
+ if (is_updating_previous())
+ state = STATE_WRITING_PREVIOUS;
+ else if (is_updating())
+ state = STATE_WRITING;
+ else
+ assert(0);
}
void Paxos::commit_finish()
// WRITING -> REFRESH
// among other things, this lets do_refresh() -> mon->bootstrap() know
// it doesn't need to flush the store queue
- assert(state == STATE_WRITING);
+ assert(is_writing() || is_writing_previous());
state = STATE_REFRESH;
if (do_refresh()) {
cancel_events();
new_value.clear();
- if (is_writing()) {
+ if (is_writing() || is_writing_previous()) {
dout(10) << __func__ << " flushing" << dendl;
mon->lock.Unlock();
mon->store->flush();
* writeable.
*/
STATE_WRITING,
+ /*
+ * Leader/Peon is writing a new commit from a previous round.
+ */
+ STATE_WRITING_PREVIOUS,
// leader: refresh following a commit
STATE_REFRESH,
};
return "updating-previous";
case STATE_WRITING:
return "writing";
+ case STATE_WRITING_PREVIOUS:
+ return "writing-previous";
case STATE_REFRESH:
return "refresh";
default:
/// @return 'true' if we are writing an update to disk
bool is_writing() const { return state == STATE_WRITING; }
+ /// @return 'true' if we are writing an update-previous to disk
+ bool is_writing_previous() const { return state == STATE_WRITING_PREVIOUS; }
+
/// @return 'true' if we are refreshing an update just committed
bool is_refresh() const { return state == STATE_REFRESH; }
// make sure the client is still connected. note that a proxied
// connection will be disconnected with a null message; don't drop
// those. also ignore loopback (e.g., log) messages.
- if (!m->get_connection()->is_connected() &&
+ if (m->get_connection() &&
+ !m->get_connection()->is_connected() &&
m->get_connection() != mon->con_self &&
m->get_connection()->get_messenger() != NULL) {
dout(10) << " discarding message from disconnected client "