![]() |
Maestro Open Toolkit: An example of asynchronous (non-blocking) state transfer. |
State transfer can be done asynchronously (using the non-blocking version of getState ) when Maestro is running in either multi-threaded or single-threaded mode. In the single-threaded mode, asynchronous state transfer is the only option. In the multi-threaded mode, state transfer can also be done synchronously.
The program below defines a subclass (called MyServer) of the Maestro_CSX class. State transfer methods resetState, stateTransfer_Callback, askState_Callback, xferCanceled_Callback, and gotState_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 non-blocking version of getState. getState(xferID, requestMsg, xferStatus); if (xferStatus == MAESTRO_XFER_TERMINATED) { cout << "(Asynchronous) Xfer Terminated" << endl; } } // (Asynchronous) state transfer has been canceled. void xferCanceled_Callback(Maestro_XferID &xferID) { cout << "(Asynchronous) Xfer Canceled" << endl; } // Got a reply to an asynchronous call to getState. void gotState_Callback(Maestro_XferID &xferID, Maestro_Message &stateMsg) { stateMsg >> state; cout << "(Asynchronous) 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]; // Asynchronous state transfer can be done in both modes // (single-threaded and multi-threaded). ops.threadMode = MAESTRO_MODE_SINGLE_THREADED; // Join the group as a server; request state transfer. ops.mbrshipType = MAESTRO_SERVER; ops.xferType = MAESTRO_ATOMIC_XFER; for (i = 0; i < NMEMBERS; i++) svr[i] = new MyServer(i, ops); // Start Ensemble in the current thread. // The call to Maestro_CSX::start() does not return. Maestro_String progName(argv[0]); Maestro_CSX::start(progName); assert(0); }