mon: add doxygen-format comments to the PaxosService class.

Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
This commit is contained in:
Joao Eduardo Luis 2012-05-21 18:00:06 -07:00
parent 7064a9c0ad
commit c5015ef349
2 changed files with 224 additions and 47 deletions

View File

@ -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;

View File

@ -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<pair<health_status_t,string> >& summary,
list<pair<health_status_t,string> > *detail) const { }
/**
* @}
*/
};
#endif