void PaxosService::refresh(bool *need_bootstrap)
{
+ dout(10) << __func__ << dendl;
+
// update cached versions
- cached_first_committed = mon.store->get(get_service_name(), first_committed_name);
- cached_last_committed = mon.store->get(get_service_name(), last_committed_name);
+ auto first_committed = mon.store->get(get_service_name(), first_committed_name);
+ auto last_committed = mon.store->get(get_service_name(), last_committed_name);
+ if (last_committed > cached_last_committed) {
+ finish_contexts(g_ceph_context, waiting_for_commit, 0);
+ }
+ cached_first_committed = first_committed;
+ cached_last_committed = last_committed;
version_t new_format = get_value("format_version");
if (new_format != format_version) {
}
format_version = new_format;
- dout(10) << __func__ << dendl;
update_from_paxos(need_bootstrap);
}
post_paxos_update();
- if (mon.is_peon() && !waiting_for_finished_proposal.empty()) {
+ if (mon.is_peon()) {
finish_contexts(g_ceph_context, waiting_for_finished_proposal, -EAGAIN);
+ finish_contexts(g_ceph_context, waiting_for_commit, -EAGAIN);
}
}
}
finish_contexts(g_ceph_context, waiting_for_finished_proposal, -EAGAIN);
+ finish_contexts(g_ceph_context, waiting_for_commit, -EAGAIN);
if (have_pending) {
discard_pending();
dout(10) << __func__ << dendl;
finish_contexts(g_ceph_context, waiting_for_finished_proposal, -EAGAIN);
+ finish_contexts(g_ceph_context, waiting_for_commit, -EAGAIN);
// make sure we update our state
_active();
proposal_timer = 0;
}
+ finish_contexts(g_ceph_context, waiting_for_commit, -EAGAIN);
finish_contexts(g_ceph_context, waiting_for_finished_proposal, -EAGAIN);
on_shutdown();
* @}
*/
+ /**
+ * Callback list to be used for waiting for the next proposal to commit.
+ */
+ std::vector<Context*> waiting_for_commit;
+
/**
* Callback list to be used whenever we are running a proposal through
* Paxos. These callbacks will be awaken whenever the said proposal
- * finishes.
+ * finishes **and** the PaxosService is active.
*/
- std::list<Context*> waiting_for_finished_proposal;
+ std::vector<Context*> waiting_for_finished_proposal;
public:
}
/**
- * Wait for a proposal to finish.
+ * Wait for a proposal to commit.
+ *
+ * Note: the proposal may not be signaled yet. This simply adds a context to
+ * be completed when the next proposal commits.
+ *
+ * @param c The callback to be awaken once the proposal is committed.
+ */
+ void wait_for_commit(MonOpRequestRef op, Context *c) {
+ if (op)
+ op->mark_event(service_name + ":wait_for_commit");
+ waiting_for_commit.push_back(c);
+ }
+
+ /**
+ * Wait for a proposal to finish and PaxosService to become active.
*
* Add a callback to be awaken whenever our current proposal finishes being
* proposed through Paxos.
waiting_for_finished_proposal.push_back(c);
}
+
/**
* Wait for us to become active
*