Maestro Open Toolkit: An example of synchronous (blocking) state transfer.

This document is a part of online Ensemble documentation, under Maestro Open Toolkit.

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.
  // .....
}

send mail to alexey@cs.cornell.edu