From c5015ef3494962e37726251f904372b6e37c30db Mon Sep 17 00:00:00 2001 From: Joao Eduardo Luis Date: Mon, 21 May 2012 18:00:06 -0700 Subject: [PATCH] mon: add doxygen-format comments to the PaxosService class. Signed-off-by: Joao Eduardo Luis --- src/mon/PaxosService.cc | 10 +- src/mon/PaxosService.h | 261 +++++++++++++++++++++++++++++++++------- 2 files changed, 224 insertions(+), 47 deletions(-) diff --git a/src/mon/PaxosService.cc b/src/mon/PaxosService.cc index 812ae996a17..38fbceab221 100644 --- a/src/mon/PaxosService.cc +++ b/src/mon/PaxosService.cc @@ -104,6 +104,7 @@ bool PaxosService::should_propose(double& delay) return true; } + void PaxosService::propose_pending() { dout(10) << "propose_pending" << dendl; @@ -115,7 +116,14 @@ void PaxosService::propose_pending() proposal_timer = 0; } - // finish and encode + /** + * @note The value we propose is encoded in a bufferlist, passed to + * Paxos::propose_new_value and it is obtained by calling a + * function that must be implemented by the class implementing us. + * I.e., the function encode_pending will be the one responsible + * to encode whatever is pending on the implementation class into a + * bufferlist, so we can then propose that as a value through Paxos. + */ bufferlist bl; encode_pending(bl); have_pending = false; diff --git a/src/mon/PaxosService.h b/src/mon/PaxosService.h index e8c7ca41d85..2cb59a3d61a 100644 --- a/src/mon/PaxosService.h +++ b/src/mon/PaxosService.h @@ -21,12 +21,42 @@ class Monitor; class Paxos; +/** + * A Paxos Service is an abstraction that easily allows one to obtain an + * association between a Monitor and a Paxos class, in order to implement any + * service. + */ class PaxosService { + /** + * @defgroup PaxosService_h_class Paxos Service + * @{ + */ public: + /** + * The Monitor to which this class is associated with + */ Monitor *mon; + /** + * The Paxos instance to which this class is associated with + */ Paxos *paxos; protected: + /** + * @defgroup PaxosService_h_callbacks Callback classes + * @{ + */ + /** + * Retry dispatching a given service message + * + * This callback class is used when we had to wait for some condition to + * become true while we were dispatching it. + * + * For instance, if the message's version isn't readable, according to Paxos, + * then we must wait for it to become readable. So, we just queue an + * instance of this class onto the Paxos::wait_for_readable function, and + * we will retry the whole dispatch again once the callback is fired. + */ class C_RetryMessage : public Context { PaxosService *svc; PaxosServiceMessage *m; @@ -36,6 +66,15 @@ protected: svc->dispatch(m); } }; + + /** + * Callback used to make sure we call the PaxosService::_active function + * whenever a condition is fulfilled. + * + * This is used in multiple situations, from waiting for the Paxos to commit + * our proposed value, to waiting for the Paxos to become active once an + * election is finished. + */ class C_Active : public Context { PaxosService *svc; public: @@ -46,6 +85,10 @@ protected: } }; + /** + * Callback class used to propose the pending value once the proposal_timer + * fires up. + */ class C_Propose : public Context { PaxosService *ps; public: @@ -54,112 +97,235 @@ protected: ps->proposal_timer = 0; ps->propose_pending(); } - }; + }; + /** + * @} + */ friend class C_Propose; private: + /** + * Event callback responsible for proposing our pending value once a timer + * runs out and fires. + */ Context *proposal_timer; + /** + * If the implementation class has anything pending to be proposed to Paxos, + * then have_pending should be true; otherwise, false. + */ bool have_pending; public: + /** + * @param mn A Monitor instance + * @param p A Paxos instance + */ PaxosService(Monitor *mn, Paxos *p) : mon(mn), paxos(p), proposal_timer(0), have_pending(false) { } virtual ~PaxosService() {} + /** + * Get the machine name. + * + * @returns The machine name. + */ const char *get_machine_name(); // i implement and you ignore + /** + * Informs this instance that it should consider itself restarted. + * + * This means that we will cancel our proposal_timer event, if any exists. + */ void restart(); + /** + * Informs this instance that an election has finished. + * + * This means that we will invoke a PaxosService::discard_pending while + * setting have_pending to false (basically, ignore our pending state) and + * we will then make sure we obtain a new state. + * + * Our state shall be updated by PaxosService::_active if the Paxos is + * active; otherwise, we will wait for it to become active by adding a + * PaxosService::C_Active callback to it. + */ void election_finished(); + /** + * Informs this instance that it is supposed to shutdown. + * + * Basically, it will instruct Paxos to cancel all events/callbacks and then + * will cancel the proposal_timer event if any exists. + */ void shutdown(); private: + /** + * Update our state by updating it from Paxos, and then creating a new + * pending state if need be. + * + * @remarks We only create a pending state we our Monitor is the Leader. + * + * @pre Paxos is active + * @post have_pending is true iif our Monitor is the Leader and Paxos is + * active + */ void _active(); public: - // i implement and you use - void propose_pending(); // propose current pending as new paxos state + /** + * Propose a new value through Paxos. + * + * This function should be called by the classes implementing + * PaxosService, in order to propose a new value through Paxos. + * + * @pre The implementation class implements the encode_pending function. + * @pre have_pending is true + * @pre Our monitor is the Leader + * @pre Paxos is active + * @post Cancel the proposal timer, if any + * @post have_pending is false + * @post propose pending value through Paxos + * + * @note This function depends on the implementation of encode_pending on + * the class that is implementing PaxosService + */ + void propose_pending(); + /** + * Dispatch a message by passing it to several different functions that are + * either implemented directly by this service, or that should be implemented + * by the class implementing this service. + * + * @param m A message + * @returns 'true' on successful dispatch; 'false' otherwise. + */ bool dispatch(PaxosServiceMessage *m); - // you implement - /* + /** + * @defgroup PaxosService_h_override_funcs Functions that should be + * overridden. + * + * These functions should be overridden at will by the class implementing + * this service. + * @{ + */ + /** * Create the initial state for your system. - * In some of ours the state is actually set up - * elsewhere so this does nothing. + * + * In some of ours the state is actually set up elsewhere so this does + * nothing. */ virtual void create_initial() = 0; - /* - * Query the Paxos system for the latest state and apply it if - * it's newer than the current Monitor state. - * Return true on success. + /** + * Query the Paxos system for the latest state and apply it if it's newer + * than the current Monitor state. + * + * @returns 'true' on success; 'false' otherwise. */ virtual void update_from_paxos() = 0; - /* - * This function is only called on a leader. Create the pending state. - * (this created state is then modified by incoming messages). - * Called at startup and after every Paxos ratification round. + /** + * Create the pending state. + * + * @invariant This function is only called on a Leader. + * @remarks This created state is then modified by incoming messages. + * @remarks Called at startup and after every Paxos ratification round. */ virtual void create_pending() = 0; - /* - * This function is only called on a leader. Encode the pending state - * into a bufferlist for ratification and transmission - * as the next state. + /** + * Encode the pending state into a bufferlist for ratification and + * transmission as the next state. + * + * @invariant This function is only called on a Leader. + * + * @param[out] bl A bufferlist containing the encoded pending state */ virtual void encode_pending(bufferlist& bl) = 0; - /* - * As this function is NOT overridden in any of our code, - * but it is called in election_finished if have_pending. + /** + * Discard the pending state + * + * @invariant This function is only called on a Leader. + * + * @remarks This function is NOT overridden in any of our code, but it is + * called in PaxosService::election_finished if have_pending is + * true. */ - virtual void discard_pending() { } // [leader] discard pending + virtual void discard_pending() { } - /* - * Look at the query; if the query can be handled without changing - * state, do so. - * Return true if the query was handled (ie, was a read that got answered, - * was a state change that has no effect), false otherwise. + /** + * Look at the query; if the query can be handled without changing state, + * do so. + * + * @param m A query message + * @returns 'true' if the query was handled (e.g., was a read that got + * answered, was a state change that has no effect); 'false' + * otherwise. */ virtual bool preprocess_query(PaxosServiceMessage *m) = 0; - /* - * This function is only called on the leader. Apply the message - * to the pending state. + /** + * Apply the message to the pending state. + * + * @invariant This function is only called on a Leader. + * + * @param m An update message + * @returns 'true' if the update message was handled (e.g., a command that + * went through); 'false' otherwise. */ virtual bool prepare_update(PaxosServiceMessage *m) = 0; + /** + * @} + */ - /* - * Determine if the Paxos system should vote on pending, and - * if so how long it should wait to vote. - * Returns true if the Paxos system should propose, - * and fills in the delay paramater with the wait time - * (so you can limit update traffic spamming). + /** + * Determine if the Paxos system should vote on pending, and if so how long + * it should wait to vote. + * + * @param[out] delay The wait time, used so we can limit the update traffic + * spamming. + * @returns 'true' if the Paxos system should propose; 'false' otherwise. */ virtual bool should_propose(double &delay); - /* - * This is called when the Paxos state goes to active. - * It's a courtesy method if you have things you want/need - * to do at that time. + /** + * @defgroup PaxosService_h_courtesy Courtesy functions * - * Note that is may get called twice in certain recovery cases. + * Courtesy functions, in case the class implementing this service has + * anything it wants/needs to do at these times. + * @{ + */ + /** + * This is called when the Paxos state goes to active. + * + * @remarks It's a courtesy method, in case the class implementing this + * service has anything it wants/needs to do at that time. + * + * @note This function may get called twice in certain recovery cases. */ virtual void on_active() { } - /* - * Another courtesy method. Called when the Paxos - * system enters a leader election. + /** + * Called when the Paxos system enters a Leader election. + * + * @remarks It's a courtesy method, in case the class implementing this + * service has anything it wants/needs to do at that time. */ virtual void on_restart() { } + /** + * @} + */ + /** + * Tick. + */ virtual void tick() {} /** - * get health information + * Get health information * * @param summary list of summary strings and associated severity * @param detail optional list of detailed problem reports; may be NULL @@ -167,6 +333,9 @@ public: virtual void get_health(list >& summary, list > *detail) const { } + /** + * @} + */ }; #endif