![]() |
Maestro Open Toolkit: An example of synchronous (blocking) state transfer. |
State transfer can be done synchronously (using the blocking version of getState ) only when Maestro is running in the multi-threaded mode. In the single-threaded mode, state transfer must be done asynchronously , using the non-blocking version of getState.
The program below defines a subclass (called MyServer) of the Maestro_CSX class. State transfer methods resetState, stateTransfer_Callback, and askState_Callback are overloaded in MyServer to implement application-specific state-transfer functionality.
The local state of a server replica is represented by an integer state. The value of state is sent to a joining server during state transfer.
#include "Maestro.h"
#define NMEMBERS 10
class MyServer: public Maestro_CSX {
public:
// Initialize the state of the server replica and join the group.
MyServer(Maestro_CSX_Options &ops) : Maestro_CSX(ops) {
resetState();
join();
}
protected:
void resetState() { state = 0; }
// State transfer is being (re)started.
void stateTransfer_Callback(Maestro_XferID &xferID) {
Maestro_Message requestMsg, stateMsg;
Maestro_XferStatus xferStatus;
resetState();
// Invoke the blocking version of getState.
// Upon return, stateMsg contains (a portion of) the state.
getState(xferID, requestMsg, stateMsg, xferStatus);
if (xferStatus == MAESTRO_XFER_TERMINATED) {
cout << "(Synchronous) Xfer Terminated" << endl;
}
else {
// Extract the state value from stateMsg.
stateMsg >> state;
cout << "(Synchronous) Xfer Successful, got state: " << state << endl;
xferDone(xferID);
}
}
// Got a state request from a joining server.
// Reply with (a portion of) the state.
void askState_Callback(Maestro_EndpID &origin,
Maestro_XferID &xferID,
Maestro_Message &requestMsg) {
Maestro_Message stateMsg;
stateMsg << state;
sendState(origin, xferID, stateMsg);
}
// Got a multicast message.
void csx_ReceiveCast_Callback(Maestro_EndpID &origin,
Maestro_Message &msg) {
// .....
}
// Got a point-to-point message.
void csx_ReceiveSend_Callback(Maestro_EndpID &origin,
Maestro_Message &msg) {
// .....
}
// Got a new view.
void csx_AcceptedView_Callback(Maestro_CSX_ViewData &viewData,
Maestro_Message &msg) {
// .....
}
private:
int state;
};
main(int argc, char *argv[]) {
MyServer *svr[NMEMBERS];
int i;
Maestro_CSX_Options ops;
ops.heartbeatRate = 1000;
ops.groupName = "lapa";
ops.protocol = "Top:Heal:Switch:Leave:Inter:Intra:Elect:Merge:Sync:Suspect:Top_appl:Pt2pt:Frag:Stable:Mnak:Bottom";
ops.transports = "UDP";
ops.programName = argv[0];
// Blocking state transfer can only be done in the multi-threaded mode.
ops.threadMode = MAESTRO_MODE_MULTI_THREADED;
// Join the group as a server; request state transfer.
ops.mbrshipType = MAESTRO_SERVER;
ops.xferType = MAESTRO_ATOMIC_XFER;
// Create NMEMBERS server objects.
for (i = 0; i < NMEMBERS; i++)
svr[i] = new MyServer(i, ops);
// Do something.
// .....
}