mirror of
https://github.com/ceph/ceph
synced 2024-12-18 17:37:38 +00:00
mon: add doxygen-format comments to the PaxosService class.
Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
This commit is contained in:
parent
7064a9c0ad
commit
c5015ef349
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user