PubSubMMOG Class Reference

#include <PubSubMMOG.h>

Inheritance diagram for PubSubMMOG:

BaseOverlay BaseRpc TopologyVis RpcListener

List of all members.

Public Member Functions

virtual ~PubSubMMOG ()
virtual void initializeOverlay (int stage)
 Initializes derived-class-attributes.
virtual void finishOverlay ()
 collects statistical data in derived class
virtual void handleUDPMessage (BaseOverlayMessage *msg)
 Processes messages from underlay.
virtual void handleTimerEvent (cMessage *msg)
 Processes "timer" self-messages.
virtual void handleAppMessage (cMessage *msg)
 Processes non-commonAPI messages.
virtual void receiveChangeNotification (int category, cPolymorphic *details)
 callback-method for events at the NotificationBoard
virtual bool handleRpc (BaseCallMessage *msg)
 Processes Remote-Procedure-Call invokation messages.
virtual void handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
virtual void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &destKey)
 This method is called if an RPC timeout has been reached.

Protected Member Functions

void setBootstrapedIcon ()
void handleMove (GameAPIPositionMessage *posMsg)
void handleMoveMessage (PubSubMoveMessage *moveMsg)
void handleMoveListMessage (PubSubMoveListMessage *moveMsg)
void handleJoinResponse (PubSubJoinResponse *joinResp)
void handleSubscriptionCall (PubSubSubscriptionCall *subCall)
void handleSubscriptionResponse (PubSubSubscriptionResponse *subResp)
void handleResponsibleNodeResponse (PubSubResponsibleNodeResponse *subResp)
void handleTakeOver (PubSubTakeOverSubspaceCall *toCall)
void handleHelpResponse (PubSubHelpResponse *helpResp)
void handleBackupCall (PubSubBackupCall *backupCall)
void handleBackupResponse (PubSubBackupResponse *backupResp)
void handleIntermediateCall (PubSubIntermediateCall *intermediateCall)
void handleIntermediateResponse (PubSubIntermediateResponse *intermediateResp)
void handleAdoptChildCall (PubSubAdoptChildCall *adoptCall)
void handleAdoptChildResponse (PubSubAdoptChildResponse *adoptResp)
void handlePingCall (PubSubPingCall *hearbeatCall)
void handlePingResponse (PubSubPingResponse *pingResp)
void takeOverNewSubspace (PubSubSubspaceId subspaceId)
void takeOverSubspace (PubSubSubspaceResponsible &subspaceId, bool isNew)
void sendHearbeatToChildren ()
void sendPingToChildren ()
void handleParentTimeout (PubSubTimer *timer)
void handleBackupCallTimeout (PubSubBackupCall *backupCall, const TransportAddress &oldNode)
void handlePingCallTimeout (PubSubPingCall *pingCall, const TransportAddress &oldNode)
void handleSubscriptionCallTimeout (PubSubSubscriptionCall *subscriptionCall, const TransportAddress &oldNode)
void handleUnsubscriptionMessage (PubSubUnsubscriptionMessage *unsMsg)
void handleNodeLeftMessage (PubSubNodeLeftMessage *leftMsg)
void handleReplacementMessage (PubSubReplacementMessage *replaceMsg)
void handleReleaseIntermediate (PubSubReleaseIntermediateMessage *releaseMsg)
void handleIntermediateBackup (PubSubBackupIntermediateMessage *backupMsg)
void handleSubscriptionBackup (PubSubBackupSubscriptionMessage *backupMsg)
void handleUnsubscribeBackup (PubSubBackupUnsubscribeMessage *backupMsg)
void unsubscribeChild (const NodeHandle &node, PubSubSubspaceResponsible &subspace)
void sendMessageToChildren (PubSubSubspaceResponsible &subspace, BaseOverlayMessage *toIntermediates, BaseOverlayMessage *toBackup, BaseOverlayMessage *toPlayers)
void publishEvents ()
void startTimer (PubSubTimer *timer)

Protected Attributes

std::list< PubSubSubspacesubscribedSubspaces
std::map< PubSubSubspaceId,
PubSubSubspaceResponsible
responsibleSubspaces
std::map< PubSubSubspaceId,
PubSubSubspaceResponsible
backupSubspaces
std::map< PubSubSubspaceId,
PubSubSubspaceIntermediate
intermediateSubspaces
int subspaceSize
int AOIWidth
int numSubspaces
int parentTimeout
int maxChildren
unsigned int currentRegionX
unsigned int currentRegionY
int movementRate
int maxMoveDelay
PubSubTimer * heartbeatTimer
PubSubTimer * childPingTimer
PubSubTimer * eventDeliveryTimer
cMessage * joinTimer
TransportAddress lobbyServer
int numEventsWrongTimeslot
int numEventsCorrectTimeslot
int numPubSubSignalingMessages
int pubSubSignalingMessagesSize
int numMoveMessages
int moveMessagesSize
int numMoveListMessages
int moveListMessagesSize
int respMoveListMessagesSize
int lostMovementLists
int receivedMovementLists


Constructor & Destructor Documentation

PubSubMMOG::~PubSubMMOG (  )  [virtual]

01971 {
01972     // Delete all waiting move messages
01973     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01974     for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it) {
01975         deque<PubSubMoveMessage*>::iterator msgIt;
01976         for( msgIt = it->second.waitingMoveMessages.begin(); msgIt != it->second.waitingMoveMessages.end(); ++msgIt ){
01977             cancelAndDelete( *msgIt );
01978         }
01979         it->second.waitingMoveMessages.clear();
01980     }
01981 
01982     cancelAndDelete(heartbeatTimer);
01983 }


Member Function Documentation

void PubSubMMOG::initializeOverlay ( int  stage  )  [virtual]

Initializes derived-class-attributes.


Initializes derived-class-attributes, called by BaseOverlay::initialize(). By default this method is called once. If more stages are needed one can overload numInitStages() and add more stages.

Parameters:
stage the init stage

Reimplemented from BaseOverlay.

00037 {
00038     // because of IPAddressResolver, we need to wait until interfaces are registered,
00039     // address auto-assignment takes place etc.
00040     if(stage != MIN_STAGE_OVERLAY) return;
00041 
00042     state = INIT;
00043     setBootstrapedIcon();
00044     lobbyServer = bootstrapOracle->getBootstrapNode();
00045 
00046     joinTimer = new cMessage("join timer");
00047     simtime_t joinTime = ceil(simulation.simTime() + (simtime_t) par("joinDelay"));
00048     scheduleAt( joinTime, joinTimer );
00049 
00050     movementRate = par("movementRate");
00051     eventDeliveryTimer = new PubSubTimer("event delivery timer");
00052     eventDeliveryTimer->setType( PUBSUB_EVENTDELIVERY );
00053     scheduleAt( joinTime + 1.0/(2*movementRate), eventDeliveryTimer );
00054 
00055     numSubspaces = par("numSubspaces");
00056     subspaceSize = (int) ( (unsigned int) par("areaDimension") / numSubspaces);
00057     thisNode.setKey( OverlayKey::random() );
00058 
00059     maxChildren = par("maxChildren");
00060     PubSubSubspaceResponsible::maxChildren = maxChildren;
00061 
00062     AOIWidth = par("AOIWidth");
00063     maxMoveDelay = par("maxMoveDelay");
00064 
00065     parentTimeout = par("parentTimeout");
00066     heartbeatTimer = new PubSubTimer("HeartbeatTimer");
00067     heartbeatTimer->setType( PUBSUB_HEARTBEAT );
00068     startTimer( heartbeatTimer );
00069     childPingTimer = new PubSubTimer("ChildPingTimer");
00070     childPingTimer->setType( PUBSUB_CHILDPING );
00071     startTimer( childPingTimer );
00072 
00073     numEventsWrongTimeslot = numEventsCorrectTimeslot = 0;
00074     numPubSubSignalingMessages = 0;
00075     pubSubSignalingMessagesSize = 0;
00076     numMoveMessages = 0;
00077     moveMessagesSize = 0;
00078     numMoveListMessages = 0;
00079     moveListMessagesSize = 0;
00080     respMoveListMessagesSize = 0;
00081     lostMovementLists = 0;
00082     receivedMovementLists = 0;
00083     WATCH( numPubSubSignalingMessages );
00084     WATCH( pubSubSignalingMessagesSize );
00085     WATCH( numMoveMessages );
00086     WATCH( moveMessagesSize );
00087     WATCH( numMoveListMessages );
00088     WATCH( moveListMessagesSize );
00089     WATCH( numEventsWrongTimeslot );
00090     WATCH( numEventsCorrectTimeslot );
00091     WATCH( lostMovementLists );
00092     WATCH( receivedMovementLists );
00093     WATCH_LIST( subscribedSubspaces );
00094     WATCH_MAP( responsibleSubspaces );
00095     WATCH_MAP( backupSubspaces );
00096     WATCH_MAP( intermediateSubspaces );
00097 }

void PubSubMMOG::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from BaseOverlay.

01942 {
01943     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
01944     if(time == 0) return;
01945 
01946     globalStatistics->addStdDev("PubSubMMOG: Sent Signaling Messages/s",
01947                                 numPubSubSignalingMessages / time);
01948     globalStatistics->addStdDev("PubSubMMOG: Sent Signaling bytes/s",
01949                                 pubSubSignalingMessagesSize / time);
01950     globalStatistics->addStdDev("PubSubMMOG: Sent Move Messages/s",
01951                                 numMoveMessages / time);
01952     globalStatistics->addStdDev("PubSubMMOG: Sent Move bytes/s",
01953                                 moveMessagesSize / time);
01954     globalStatistics->addStdDev("PubSubMMOG: Sent MoveList Messages/s",
01955                                 numMoveListMessages / time);
01956     globalStatistics->addStdDev("PubSubMMOG: Sent MoveList bytes/s",
01957                                 moveListMessagesSize / time);
01958     globalStatistics->addStdDev("PubSubMMOG: Received Move Events (correct timeslot)/s",
01959                                 numEventsCorrectTimeslot / time);
01960     globalStatistics->addStdDev("PubSubMMOG: Received Move Events (wrong timeslot)/s",
01961                                 numEventsWrongTimeslot / time);
01962     globalStatistics->addStdDev("PubSubMMOG: Responsible Nodes: Send MoveList Bytes/s",
01963                                 respMoveListMessagesSize / time);
01964     globalStatistics->addStdDev("PubSubMMOG: Lost or too long delayed MoveLists/s",
01965                                 lostMovementLists / time);
01966     globalStatistics->addStdDev("PubSubMMOG: Received valid MoveLists/s",
01967                                 receivedMovementLists / time);
01968 }

void PubSubMMOG::handleUDPMessage ( BaseOverlayMessage *  msg  )  [virtual]

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from BaseOverlay.

00241 {
00242     if( PubSubMoveListMessage* moveMsg = dynamic_cast<PubSubMoveListMessage*>(msg) ){
00243         handleMoveListMessage( moveMsg );
00244         delete moveMsg;
00245     } else if( PubSubMoveMessage* moveMsg = dynamic_cast<PubSubMoveMessage*>(msg) ){
00246         handleMoveMessage( moveMsg );
00247     } else if( PubSubUnsubscriptionMessage* unsMsg = dynamic_cast<PubSubUnsubscriptionMessage*>(msg) ){
00248         handleUnsubscriptionMessage( unsMsg );
00249         delete unsMsg;
00250     } else if( PubSubNodeLeftMessage* leftMsg = dynamic_cast<PubSubNodeLeftMessage*>(msg) ){
00251         handleNodeLeftMessage( leftMsg );
00252         delete leftMsg;
00253     } else if( PubSubReplacementMessage* replaceMsg = dynamic_cast<PubSubReplacementMessage*>(msg) ){
00254         handleReplacementMessage( replaceMsg );
00255         delete replaceMsg;
00256     } else if( PubSubBackupSubscriptionMessage* backupMsg = dynamic_cast<PubSubBackupSubscriptionMessage*>(msg) ){
00257         handleSubscriptionBackup( backupMsg );
00258         delete backupMsg;
00259     } else if( PubSubBackupUnsubscribeMessage* backupMsg = dynamic_cast<PubSubBackupUnsubscribeMessage*>(msg) ){
00260         handleUnsubscribeBackup( backupMsg );
00261         delete backupMsg;
00262     } else if( PubSubBackupIntermediateMessage* backupMsg = dynamic_cast<PubSubBackupIntermediateMessage*>(msg) ){
00263         handleIntermediateBackup( backupMsg );
00264         delete backupMsg;
00265     } else if( PubSubReleaseIntermediateMessage* releaseMsg = dynamic_cast<PubSubReleaseIntermediateMessage*>(msg) ){
00266         handleReleaseIntermediate( releaseMsg );
00267         delete releaseMsg;
00268     }
00269 }

void PubSubMMOG::handleTimerEvent ( cMessage *  msg  )  [virtual]

Processes "timer" self-messages.

Parameters:
msg A self-message

Reimplemented from BaseOverlay.

00272 {
00273     if( PubSubTimer* timer = dynamic_cast<PubSubTimer*>(msg) ) {
00274         switch( timer->getType() ) {
00275             case PUBSUB_HEARTBEAT:
00276                 sendHearbeatToChildren();
00277                 startTimer( timer );
00278                 break;
00279             case PUBSUB_CHILDPING:
00280                 sendPingToChildren();
00281                 startTimer( timer );
00282                 break;
00283             case PUBSUB_PARENT_TIMEOUT:
00284                 handleParentTimeout( timer );
00285                 break;
00286             case PUBSUB_EVENTDELIVERY:
00287                 publishEvents();
00288                 startTimer( timer );
00289                 break;
00290         }
00291     } else if( msg == joinTimer ) {
00292         // send a fake ready message to app to get initial position
00293         // Note: This is not consistent to the paper, where the lobby server
00294         // positions player. But it is needed for consistency with other MMOG protocols
00295         CompReadyMessage* msg = new CompReadyMessage("fake READY");
00296         msg->setReady(true);
00297         msg->setComp(getThisCompType());
00298         send( msg, "to_app");
00299         delete joinTimer;
00300         joinTimer = NULL;
00301     }
00302 }

void PubSubMMOG::handleAppMessage ( cMessage *  msg  )  [virtual]

Processes non-commonAPI messages.

Parameters:
msg non-commonAPIMessage

Reimplemented from BaseOverlay.

00305 {
00306     if( GameAPIPositionMessage *posMsg = dynamic_cast<GameAPIPositionMessage*>(msg) ) {
00307         if( state == READY ) {
00308             handleMove( posMsg );
00309         } else if ( state == JOINING ) {
00310             // We are not connected to our responsible node, inform app
00311             CompReadyMessage* msg = new CompReadyMessage("Overlay not READY!");
00312             msg->setReady(false);
00313             msg->setComp(getThisCompType());
00314             send( msg, "to_app");
00315         } else if ( state == INIT ) {
00316             // This is only called for the first MOVE message
00317             // Trigger login
00318             PubSubJoinCall* joinMsg = new PubSubJoinCall("Login");
00319             joinMsg->setPosition( posMsg->getPosition() );
00320             // FIXME: Ressource handling not yet supported!
00321             joinMsg->setRessources( 4 );
00322             sendUdpRpcCall( lobbyServer, joinMsg );
00323 
00324             state = JOINING;
00325             setBootstrapedIcon();
00326 
00327             // tell app to wait until login is confirmed...
00328             CompReadyMessage* readyMsg = new CompReadyMessage("Overlay not READY!");
00329             readyMsg->setReady(false);
00330             readyMsg->setComp(getThisCompType());
00331             send( readyMsg, "to_app");
00332 
00333             currentRegionX = (unsigned int) (posMsg->getPosition().x/subspaceSize);
00334             currentRegionY = (unsigned int) (posMsg->getPosition().y/subspaceSize);
00335         }
00336         delete msg;
00337     }
00338 }

void PubSubMMOG::receiveChangeNotification ( int  category,
cPolymorphic *  details 
) [virtual]

callback-method for events at the NotificationBoard

Parameters:
category ... TODO ...
details ... TODO ...

Reimplemented from BaseOverlay.

00525 {
00526     if(category == NF_OVERLAY_NODE_GRACEFUL_LEAVE && state == READY) {
00527     }
00528 }

bool PubSubMMOG::handleRpc ( BaseCallMessage *  msg  )  [virtual]

Processes Remote-Procedure-Call invokation messages.


This method should be overloaded when the overlay provides RPC functionality.

Returns:
true, if rpc has been handled

Reimplemented from BaseRpc.

00100 {
00101     // delegate messages
00102     RPC_SWITCH_START( msg )
00103     RPC_DELEGATE( PubSubSubscription, handleSubscriptionCall );
00104     RPC_DELEGATE( PubSubTakeOverSubspace, handleTakeOver );
00105     RPC_DELEGATE( PubSubBackup, handleBackupCall );
00106     RPC_DELEGATE( PubSubIntermediate, handleIntermediateCall );
00107     RPC_DELEGATE( PubSubAdoptChild, handleAdoptChildCall );
00108     RPC_DELEGATE( PubSubPing, handlePingCall );
00109     RPC_SWITCH_END( )
00110 
00111     return RPC_HANDLED;
00112 
00113 }

void PubSubMMOG::handleRpcResponse ( BaseResponseMessage *  msg,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [virtual]

This method is called if an RPC response has been received.

Parameters:
msg The response message.
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from RpcListener.

00118 {
00119     RPC_SWITCH_START(msg);
00120     RPC_ON_RESPONSE( PubSubJoin ) {
00121         handleJoinResponse( _PubSubJoinResponse );
00122         EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip
00123             << " (" << thisNode.key.toString(16) << ")]\n"
00124             << "    Received a PubSubJoin RPC Response: id=" << rpcId << "\n"
00125             << "    msg=" << *_PubSubJoinResponse << " rtt=" << rtt
00126             << endl;
00127         break;
00128     }
00129     RPC_ON_RESPONSE( PubSubSubscription ) {
00130         handleSubscriptionResponse( _PubSubSubscriptionResponse );
00131         EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip
00132             << " (" << thisNode.key.toString(16) << ")]\n"
00133             << "    Received a PubSubSubscription RPC Response: id=" << rpcId << "\n"
00134             << "    msg=" << *_PubSubSubscriptionResponse << " rtt=" << rtt
00135             << endl;
00136         break;
00137     }
00138     RPC_ON_RESPONSE( PubSubResponsibleNode ) {
00139         handleResponsibleNodeResponse( _PubSubResponsibleNodeResponse );
00140         EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip
00141             << " (" << thisNode.key.toString(16) << ")]\n"
00142             << "    Received a PubSubResponsibleNode RPC Response: id=" << rpcId << "\n"
00143             << "    msg=" << *_PubSubResponsibleNodeResponse << " rtt=" << rtt
00144             << endl;
00145         break;
00146     }
00147     RPC_ON_RESPONSE( PubSubHelp ) {
00148         handleHelpResponse( _PubSubHelpResponse );
00149         EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip
00150             << " (" << thisNode.key.toString(16) << ")]\n"
00151             << "    Received a PubSubHelp RPC Response: id=" << rpcId << "\n"
00152             << "    msg=" << *_PubSubHelpResponse << " rtt=" << rtt
00153             << endl;
00154         break;
00155     }
00156     RPC_ON_RESPONSE( PubSubBackup ) {
00157         handleBackupResponse( _PubSubBackupResponse );
00158         EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip
00159             << " (" << thisNode.key.toString(16) << ")]\n"
00160             << "    Received a PubSubBackup RPC Response: id=" << rpcId << "\n"
00161             << "    msg=" << *_PubSubBackupResponse << " rtt=" << rtt
00162             << endl;
00163         break;
00164     }
00165     RPC_ON_RESPONSE( PubSubIntermediate ) {
00166         handleIntermediateResponse( _PubSubIntermediateResponse );
00167         EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip
00168             << " (" << thisNode.key.toString(16) << ")]\n"
00169             << "    Received a PubSubIntermediate RPC Response: id=" << rpcId << "\n"
00170             << "    msg=" << *_PubSubIntermediateResponse << " rtt=" << rtt
00171             << endl;
00172         break;
00173     }
00174     RPC_ON_RESPONSE( PubSubAdoptChild ) {
00175         handleAdoptChildResponse( _PubSubAdoptChildResponse );
00176         EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip
00177             << " (" << thisNode.key.toString(16) << ")]\n"
00178             << "    Received a PubSubAdoptChild RPC Response: id=" << rpcId << "\n"
00179             << "    msg=" << *_PubSubAdoptChildResponse << " rtt=" << rtt
00180             << endl;
00181         break;
00182     }
00183     RPC_ON_RESPONSE( PubSubPing ) {
00184         handlePingResponse( _PubSubPingResponse );
00185         EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip
00186             << " (" << thisNode.key.toString(16) << ")]\n"
00187             << "    Received a PubSubPing RPC Response: id=" << rpcId << "\n"
00188             << "    msg=" << *_PubSubPingResponse << " rtt=" << rtt
00189             << endl;
00190         break;
00191     }
00192     RPC_SWITCH_END( );
00193 }

void PubSubMMOG::handleRpcTimeout ( BaseCallMessage *  msg,
const TransportAddress dest,
cPolymorphic *  context,
int  rpcId,
const OverlayKey destKey 
) [virtual]

This method is called if an RPC timeout has been reached.

Parameters:
msg The original RPC message.
dest The destination node
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
destKey the destination OverlayKey

Reimplemented from RpcListener.

00199 {
00200     RPC_SWITCH_START(msg)
00201     RPC_ON_CALL( PubSubBackup ) {
00202         handleBackupCallTimeout( _PubSubBackupCall, dest );
00203         EV << "[PubSubMMOG::handleRpcTimeout() @ " << thisNode.ip
00204            << " (" << thisNode.key.toString(16) << ")]\n"
00205            << "    Backup RPC Call timed out: id=" << rpcId << "\n"
00206            << "    msg=" << *_PubSubBackupCall
00207            << "    oldNode=" << dest
00208            << endl;
00209         break;
00210     }
00211     RPC_ON_CALL( PubSubPing ) {
00212         handlePingCallTimeout( _PubSubPingCall, dest );
00213         EV << "[PubSubMMOG::handleRpcTimeout() @ " << thisNode.ip
00214            << " (" << thisNode.key.toString(16) << ")]\n"
00215            << "    Ping RPC Call timed out: id=" << rpcId << "\n"
00216            << "    msg=" << *_PubSubPingCall
00217            << "    oldNode=" << dest
00218            << endl;
00219         break;
00220     }
00221     RPC_ON_CALL( PubSubSubscription ) {
00222         handleSubscriptionCallTimeout( _PubSubSubscriptionCall, dest );
00223         EV << "[PubSubMMOG::handleRpcTimeout() @ " << thisNode.ip
00224            << " (" << thisNode.key.toString(16) << ")]\n"
00225            << "    Subscription RPC Call timed out: id=" << rpcId << "\n"
00226            << "    msg=" << *_PubSubSubscriptionCall
00227            << "    oldNode=" << dest
00228            << endl;
00229         break;
00230     }
00231     RPC_SWITCH_END( )
00232 
00233     // FIXME:
00234     //   AdoptCall missing!
00235     //   IntermediateCall missing!
00236     //   (ResponsibleNodeCall missing)
00237     //   (HelpCall missing)
00238 }

void PubSubMMOG::setBootstrapedIcon (  )  [protected]

Referenced by handleAppMessage(), handleJoinResponse(), handleSubscriptionResponse(), and initializeOverlay().

01895 {
01896     if(ev.isGUI()) {
01897         if(state == READY) {
01898             parentModule()->parentModule()->displayString().setTagArg("i2", 1, "green");
01899             displayString().setTagArg("i", 1, "green");
01900         }
01901         else if(state == JOINING) {
01902             parentModule()->parentModule()->displayString().setTagArg("i2", 1, "yellow");
01903             displayString().setTagArg("i", 1, "yellow");
01904         }
01905         else {
01906             parentModule()->parentModule()->displayString().setTagArg("i2", 1, "red");
01907             displayString().setTagArg("i", 1, "red");
01908         }
01909     }
01910 }

void PubSubMMOG::handleMove ( GameAPIPositionMessage *  posMsg  )  [protected]

Referenced by handleAppMessage().

00531 {
00532     currentRegionX = (unsigned int) (posMsg->getPosition().x/subspaceSize);
00533     currentRegionY = (unsigned int) (posMsg->getPosition().y/subspaceSize);
00534 
00535     PubSubSubspaceId region( currentRegionX, currentRegionY, numSubspaces);
00536 
00537     set<PubSubSubspaceId> expectedRegions;
00538     int minX = (int) ((posMsg->getPosition().x - AOIWidth)/subspaceSize);
00539     if( minX < 0 ) minX = 0;
00540     int maxX = (int) ((posMsg->getPosition().x + AOIWidth)/subspaceSize);
00541     if( maxX >= numSubspaces ) maxX = numSubspaces -1;
00542     int minY = (int) ((posMsg->getPosition().y - AOIWidth)/subspaceSize);
00543     if( minY < 0 ) minY = 0;
00544     int maxY = (int) ((posMsg->getPosition().y + AOIWidth)/subspaceSize);
00545     if( maxY >= numSubspaces ) maxY = numSubspaces -1;
00546 
00547     // FIXME: make parameter: unsubscription size
00548     int minUnsubX = (int) ((posMsg->getPosition().x - 1.5*AOIWidth)/subspaceSize);
00549     if( minUnsubX < 0 ) minUnsubX = 0;
00550     int maxUnsubX = (int) ((posMsg->getPosition().x + 1.5*AOIWidth)/subspaceSize);
00551     if( maxUnsubX >= numSubspaces ) maxUnsubX = numSubspaces -1;
00552     int minUnsubY = (int) ((posMsg->getPosition().y - 1.5*AOIWidth)/subspaceSize);
00553     if( minUnsubY < 0 ) minUnsubY = 0;
00554     int maxUnsubY = (int) ((posMsg->getPosition().y + 1.5+AOIWidth)/subspaceSize);
00555     if( maxUnsubY >= numSubspaces ) maxUnsubY = numSubspaces -1;
00556 
00557     for( int x = minX; x <= maxX; ++x ){
00558         for( int y = minY; y <= maxY; ++y ){
00559             expectedRegions.insert( PubSubSubspaceId( x, y, numSubspaces ));
00560         }
00561     }
00562 
00563     list<PubSubSubspace>::iterator subIt = subscribedSubspaces.begin();
00564     PubSubSubspace* subspace = NULL;
00565     while( subIt != subscribedSubspaces.end() ){
00566         if( subIt->getId() == region ){
00567             subspace = &*subIt;
00568         }
00569         expectedRegions.erase( subIt->getId() );
00570 
00571         // unsubscribe region if to far away
00572         if( subIt->getId().getX() < minX || subIt->getId().getX() > maxX ||
00573                 subIt->getId().getY() < minY || subIt->getId().getY() > maxY ){
00574             if( !subIt->getResponsibleNode().isUnspecified() ){
00575                 PubSubUnsubscriptionMessage* unsubMsg = new PubSubUnsubscriptionMessage("Unsubscribe from subspace");
00576                 unsubMsg->setSubspaceId( subIt->getId().getId() );
00577                 unsubMsg->setSrc( thisNode );
00578                 unsubMsg->setLength( PUBSUB_UNSUBSCRIPTION_L( unsubMsg ));
00579                 RECORD_STATS(
00580                         ++numPubSubSignalingMessages;
00581                         pubSubSignalingMessagesSize+= unsubMsg->byteLength()
00582                         );
00583                 sendMessageToUDP( subIt->getResponsibleNode(), unsubMsg );
00584             }
00585             // Erase subspace from subscribedList and increase iterator
00586             subscribedSubspaces.erase( subIt++ );
00587         } else {
00588             ++subIt;
00589         }
00590     }
00591 
00592     // if any "near" region is not yet subscribed, subscribe
00593     for( set<PubSubSubspaceId>::iterator regionIt = expectedRegions.begin(); regionIt != expectedRegions.end(); ++regionIt ){
00594         PubSubSubspace sub( *regionIt );
00595         subscribedSubspaces.push_back( sub );
00596         PubSubResponsibleNodeCall* respCall = new PubSubResponsibleNodeCall("Request Responsible NodeHandle");
00597         respCall->setSubspacePos( Vector2D(regionIt->getX(), regionIt->getY()) );
00598         respCall->setLength( PUBSUB_RESPONSIBLENODECALL_L( respCall ));
00599         RECORD_STATS(
00600                 ++numPubSubSignalingMessages;
00601                 pubSubSignalingMessagesSize+= respCall->byteLength()
00602                 );
00603         sendUdpRpcCall( lobbyServer, respCall, NULL, 5, 5 ); // FIXME: Make it a parameter...
00604     }
00605 
00606     if( subspace && !subspace->getResponsibleNode().isUnspecified() ){
00607         PubSubMoveMessage* moveMsg = new PubSubMoveMessage("Player move");
00608         moveMsg->setSubspaceId( region.getId() );
00609         moveMsg->setPlayer( thisNode );
00610         moveMsg->setPosition( posMsg->getPosition() );
00611         moveMsg->setTimestamp( simulation.simTime() );
00612         moveMsg->setLength( PUBSUB_MOVE_L( moveMsg ));
00613         RECORD_STATS(
00614                 ++numMoveMessages;
00615                 moveMessagesSize+= moveMsg->byteLength()
00616                 );
00617         sendMessageToUDP( subspace->getResponsibleNode(), moveMsg );
00618     } else {
00619         // trying to move to not-yet subscribed region
00620         // FIXME: change state to JOINING?
00621     }
00622 }

void PubSubMMOG::handleMoveMessage ( PubSubMoveMessage *  moveMsg  )  [protected]

Referenced by handleUDPMessage().

00625 {
00626     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
00627     it = responsibleSubspaces.find( PubSubSubspaceId(moveMsg->getSubspaceId(), numSubspaces) );
00628     if( it == responsibleSubspaces.end() ){
00629         EV << "PubSubMMOG::handleMoveMessage@" << thisNode << ":\n"
00630             << "  received moveMessage for unknown subspace" << moveMsg->getSubspaceId() << "\n";
00631         return;
00632     }
00633 
00634     // If message arrived in the correct timeslot, store move message until deadline
00635     // Note: This assumes, we get no messages with future timestamps. At least in
00636     // the simulation, this assumption will hold.
00637     if( moveMsg->getTimestamp() >= eventDeliveryTimer->arrivalTime() - 1.0/(2*movementRate) ){
00638         it->second.waitingMoveMessages.push_back( moveMsg );
00639         ++numEventsCorrectTimeslot;
00640     } else {
00641         EV << "PubSubMMOG::handleMoveMessage@" << thisNode << ":\n"
00642             << "  received moveMesage with Timestamp: " << moveMsg->getTimestamp() << "\n"
00643             << "  deadline was: " << eventDeliveryTimer->arrivalTime() - 1.0/(2*movementRate) << "\n";
00644         ++numEventsWrongTimeslot;
00645         cancelAndDelete( moveMsg );
00646     }
00647 }

void PubSubMMOG::handleMoveListMessage ( PubSubMoveListMessage *  moveMsg  )  [protected]

Referenced by handleUDPMessage().

00650 {
00651     simtime_t timestamp = moveMsg->getTimestamp();
00652 
00653     // If I'm intermediate node for this subspace, forward message to children
00654     std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it;
00655     it = intermediateSubspaces.find( PubSubSubspaceId(moveMsg->getSubspaceId(), numSubspaces) );
00656     if( it != intermediateSubspaces.end() ){
00657         // Forward only if the message has not already been forwarded
00658         if( it->second.getLastTimestamp() < moveMsg->getTimestamp() ){
00659             set<NodeHandle>::iterator childIt;
00660             for( childIt = it->second.children.begin(); childIt != it->second.children.end(); ++childIt ){
00661                 sendMessageToUDP( *childIt, (BaseOverlayMessage*) moveMsg->dup() );
00662                 RECORD_STATS(
00663                         ++numMoveListMessages;
00664                         moveListMessagesSize+= moveMsg->byteLength()
00665                         );
00666             }
00667             it->second.setTimestamp( timestamp );
00668         }
00669     }
00670 
00671     // If I'm subscribed to the subspace, transfer a GameAPIMoveList to app
00672     std::list<PubSubSubspace>::iterator subIt;
00673     for( subIt = subscribedSubspaces.begin(); subIt != subscribedSubspaces.end(); ++subIt ){
00674         if( subIt->getId().getId() == moveMsg->getSubspaceId() ){
00675             if( subIt->getLastTimestamp() < moveMsg->getTimestamp() ){
00676                 GameAPIListMessage* moveList = new GameAPIListMessage("player position update");
00677                 moveList->setCommand( NEIGHBOR_UPDATE );
00678                 moveList->setAddNeighborArraySize( moveMsg->getPlayerArraySize() );
00679                 moveList->setNeighborPositionArraySize( moveMsg->getPositionArraySize() );
00680                 for( unsigned int i = 0; i < moveMsg->getPlayerArraySize(); ++i ){
00681                     moveList->setAddNeighbor( i, moveMsg->getPlayer(i) );
00682                     moveList->setNeighborPosition( i, moveMsg->getPosition(i) );
00683                 }
00684                 send( moveList, "to_app" );
00685                 RECORD_STATS(
00686                         if( timestamp < simulation.simTime() - maxMoveDelay ){
00687                             ++lostMovementLists;
00688                         } else {
00689                             ++receivedMovementLists;
00690                         }
00691                         if( subIt->getLastTimestamp() )lostMovementLists += (timestamp - subIt->getLastTimestamp())*movementRate -1;
00692 
00693                         globalStatistics->addStdDev("PubSubMMOG: Move Delay",
00694                                 simulation.simTime() - timestamp + 0.5/movementRate );
00695                         );
00696                 subIt->setTimestamp( timestamp );
00697             }
00698             return;
00699         }
00700     }
00701 }

void PubSubMMOG::handleJoinResponse ( PubSubJoinResponse *  joinResp  )  [protected]

Referenced by handleRpcResponse().

00357 {
00358     state = JOINING;
00359     setBootstrapedIcon();
00360     PubSubSubspaceId region( currentRegionX, currentRegionY, numSubspaces);
00361 
00362     NodeHandle respNode = joinResp->getResponsibleNode();
00363     PubSubSubspace sub(region);
00364     sub.setResponsibleNode( respNode );
00365     subscribedSubspaces.push_back( sub );
00366     if( respNode.isUnspecified() ) {
00367         PubSubResponsibleNodeCall* respCall = new PubSubResponsibleNodeCall("Request Responsible NodeHandle");
00368         respCall->setSubspacePos( Vector2D(currentRegionX, currentRegionY) );
00369         respCall->setLength( PUBSUB_RESPONSIBLENODECALL_L( respCall ) );
00370         RECORD_STATS(
00371                 ++numPubSubSignalingMessages;
00372                 pubSubSignalingMessagesSize+= respCall->byteLength()
00373                 );
00374         sendUdpRpcCall( lobbyServer, respCall, NULL, 5, 5 ); // FIXME: Make it a parameter...
00375     } else {
00376         PubSubSubscriptionCall* subCall = new PubSubSubscriptionCall("JoinSubspace");
00377         subCall->setSubspaceId( region.getId() );
00378         subCall->setLength( PUBSUB_SUBSCRIPTIONCALL_L( subCall ));
00379         RECORD_STATS(
00380                 ++numPubSubSignalingMessages;
00381                 pubSubSignalingMessagesSize+= subCall->byteLength()
00382                 );
00383         sendUdpRpcCall( respNode, subCall );
00384     }
00385 }

void PubSubMMOG::handleSubscriptionCall ( PubSubSubscriptionCall *  subCall  )  [protected]

Referenced by handleRpc().

00432 {
00433     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
00434     it = responsibleSubspaces.find( PubSubSubspaceId(subCall->getSubspaceId(), numSubspaces) );
00435 
00436     PubSubBackupSubscriptionMessage* backupMsg = 0;
00437     PubSubSubscriptionResponse* resp;
00438     if( it == responsibleSubspaces.end() ) {
00439         resp = new PubSubSubscriptionResponse("Subscription failed");
00440         resp->setFailed( true );
00441     } else {
00442         resp = new PubSubSubscriptionResponse("Subscription successful");
00443         backupMsg = new PubSubBackupSubscriptionMessage("Backup: new subscription");
00444         backupMsg->setSubspaceId( subCall->getSubspaceId() );
00445         backupMsg->setChild( subCall->getSrcNode() );
00446 
00447         if( it->second.addChild( subCall->getSrcNode() )) {
00448             // We have still room for the child
00449             backupMsg->setParent( thisNode );
00450         } else {
00451             // Child has to go to an intermediate node...
00452             if( PubSubSubspaceResponsible::IntermediateNode* iNode = it->second.getNextFreeIntermediate() ){
00453                 // find intermediate node with free slots
00454                 PubSubAdoptChildCall* adoptCall = new PubSubAdoptChildCall("Adopt child");
00455                 adoptCall->setChild( subCall->getSrcNode() );
00456                 adoptCall->setSubspaceId( subCall->getSubspaceId() );
00457                 adoptCall->setLength( PUBSUB_ADOPTCHILDCALL_L( adoptCall ));
00458                 sendUdpRpcCall( iNode->node, adoptCall );
00459                 RECORD_STATS(
00460                         ++numPubSubSignalingMessages;
00461                         pubSubSignalingMessagesSize+= adoptCall->byteLength()
00462                         );
00463                 iNode->waitingChildren++;
00464             } else {
00465                 // no free slots available, create new intermediate node
00466                 // FIXME: when getting two subscriptions at once, we're requesting too many intermediates
00467                 PubSubHelpCall* helpCall = new PubSubHelpCall("I need an intermediate node");
00468                 helpCall->setHelpType( PUBSUB_INTERMEDIATE );
00469                 helpCall->setSubspaceId( subCall->getSubspaceId() );
00470                 helpCall->setLength( PUBSUB_HELPCALL_L( helpCall ));
00471                 sendUdpRpcCall( lobbyServer, helpCall );
00472                 RECORD_STATS(
00473                         ++numPubSubSignalingMessages;
00474                         pubSubSignalingMessagesSize+= helpCall->byteLength()
00475                         );
00476             }
00477         }
00478     }
00479     resp->setLength( PUBSUB_SUBSCRIPTIONRESPONSE_L( resp ));
00480     sendRpcResponse( subCall, resp );
00481     RECORD_STATS(
00482             ++numPubSubSignalingMessages;
00483             pubSubSignalingMessagesSize+= resp->byteLength()
00484             );
00485 
00486     if( it == responsibleSubspaces.end() ) return;
00487 
00488 // FIXME: just for testing
00489 PubSubSubspaceResponsible& subspace = it->second;
00490 int iii = subspace.getTotalChildrenCount();
00491 subspace.fixTotalChildrenCount();
00492 if( iii != subspace.getTotalChildrenCount() ){
00493     opp_error("Huh?");
00494 }
00495 
00496     if( !it->second.getBackupNode().isUnspecified() ){
00497         backupMsg->setLength( PUBSUB_BACKUPSUBSCRIPTION_L( backupMsg ));
00498         RECORD_STATS(
00499                 ++numPubSubSignalingMessages;
00500                 pubSubSignalingMessagesSize+= backupMsg->byteLength()
00501                 );
00502         sendMessageToUDP( it->second.getBackupNode(), backupMsg );
00503     } else {
00504         delete backupMsg;
00505     }
00506 }

void PubSubMMOG::handleSubscriptionResponse ( PubSubSubscriptionResponse *  subResp  )  [protected]

Referenced by handleRpcResponse().

00341 {
00342     if( subResp->getFailed() ) {
00343         // TODO: get new resp node...
00344     } else {
00345         if( state != READY ){
00346             state = READY;
00347             setBootstrapedIcon();
00348             CompReadyMessage* readyMsg = new CompReadyMessage("Overlay READY!");
00349             readyMsg->setReady(true);
00350             readyMsg->setComp(getThisCompType());
00351             sendDelayed( readyMsg, ceil(simulation.simTime()) - simulation.simTime(), "to_app" );
00352         }
00353     }
00354 }

void PubSubMMOG::handleResponsibleNodeResponse ( PubSubResponsibleNodeResponse *  subResp  )  [protected]

Referenced by handleRpcResponse().

00388 {
00389     int subspaceId = subResp->getSubspaceId();
00390     NodeHandle respNode = subResp->getResponsibleNode();
00391 
00392     std::list<PubSubSubspace>::iterator it = subscribedSubspaces.begin();
00393     while( it != subscribedSubspaces.end() ) {
00394         if( it->getId().getId() == subspaceId) break;
00395         ++it;
00396     }
00397     if( it != subscribedSubspaces.end() ) {
00398         it->setResponsibleNode( respNode );
00399 
00400         PubSubSubscriptionCall* subCall = new PubSubSubscriptionCall("JoinSubspace");
00401         subCall->setSubspaceId( subspaceId );
00402         subCall->setLength( PUBSUB_SUBSCRIPTIONCALL_L( subCall ));
00403         RECORD_STATS(
00404                 ++numPubSubSignalingMessages;
00405                 pubSubSignalingMessagesSize+= subCall->byteLength()
00406                 );
00407         sendUdpRpcCall( respNode, subCall );
00408     }
00409 }

void PubSubMMOG::handleTakeOver ( PubSubTakeOverSubspaceCall *  toCall  )  [protected]

Referenced by handleRpc().

00509 {
00510     PubSubSubspaceId region((int) toCall->getSubspacePos().x, (int) toCall->getSubspacePos().y, numSubspaces);
00511 
00512     takeOverNewSubspace( region );
00513 
00514     PubSubTakeOverSubspaceResponse* toResp = new PubSubTakeOverSubspaceResponse("Accept subspace responsibility");
00515     toResp->setSubspacePos( toCall->getSubspacePos() );
00516     toResp->setLength( PUBSUB_TAKEOVERSUBSPACERESPONSE_L( toResp ));
00517     RECORD_STATS(
00518             ++numPubSubSignalingMessages;
00519             pubSubSignalingMessagesSize+= toResp->byteLength()
00520             );
00521     sendRpcResponse( toCall, toResp );
00522 }

void PubSubMMOG::handleHelpResponse ( PubSubHelpResponse *  helpResp  )  [protected]

Referenced by handleRpcResponse().

00704 {
00705    // lobby server answered our call for help
00706    // (i.e. he sends us a candidate for backup/intermediate nodes
00707     if( helpResp->getHelpType() == PUBSUB_BACKUP ){
00708         PubSubBackupCall* backupCall = new PubSubBackupCall("Become my backup node!");
00709         backupCall->setSubspaceId( helpResp->getSubspaceId() );
00710 
00711         // Find the subspace in the subspace map
00712         std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
00713         it = responsibleSubspaces.find( PubSubSubspaceId(helpResp->getSubspaceId(), numSubspaces) );
00714         if( it == responsibleSubspaces.end() ){
00715             EV << "PubSubMMOG::handleHelpResponse@" << thisNode << ":\n"
00716                 << "  received helpResponse for unknown subspace" << helpResp->getSubspaceId() << "\n";
00717             return;
00718         }
00719         PubSubSubspaceResponsible& subspace = it->second;
00720 
00721         // Assume the new backup will not refuse his task
00722         subspace.setBackupNode( helpResp->getNode() );
00723 
00724 // FIXME: just for testing
00725 int iii = subspace.getTotalChildrenCount();
00726 subspace.fixTotalChildrenCount();
00727 if( iii != subspace.getTotalChildrenCount() ){
00728     opp_error("Huh?");
00729 }
00730 
00731         // backup the load balancing tree
00732         backupCall->setChildrenArraySize( subspace.getTotalChildrenCount() );
00733         backupCall->setChildrenPosArraySize( subspace.getTotalChildrenCount() );
00734         backupCall->setIntermediatesArraySize( subspace.intermediateNodes.size() );
00735 
00736         set<NodeHandle>::iterator childIt;
00737         map<NodeHandle, bool>::iterator childMapIt;
00738         unsigned int i = 0;
00739         for( childMapIt = subspace.cachedChildren.begin(); childMapIt != subspace.cachedChildren.end(); ++childMapIt ){
00740             backupCall->setChildren(i, childMapIt->first);
00741             backupCall->setChildrenPos(i, -2);
00742             ++i;
00743         }
00744         for( childIt = subspace.children.begin(); childIt != subspace.children.end(); ++childIt ){
00745             backupCall->setChildren(i, *childIt);
00746             backupCall->setChildrenPos(i, -1);
00747             ++i;
00748         }
00749         for( unsigned int ii = 0; ii < subspace.intermediateNodes.size(); ++ii ){
00750             PubSubSubspaceResponsible::IntermediateNode& iNode =  subspace.intermediateNodes[ii];
00751             backupCall->setIntermediates(ii, iNode.node);
00752             for( childIt = iNode.children.begin(); childIt != iNode.children.end(); ++childIt ){
00753                 backupCall->setChildren(i, *childIt);
00754                 backupCall->setChildrenPos(i, ii);
00755                 ++i;
00756             }
00757         }
00758 
00759         backupCall->setLength( PUBSUB_BACKUPCALL_L( backupCall ));
00760         RECORD_STATS(
00761                 ++numPubSubSignalingMessages;
00762                 pubSubSignalingMessagesSize+= backupCall->byteLength()
00763                 );
00764         sendUdpRpcCall( helpResp->getNode(), backupCall );
00765 
00766     } else if( helpResp->getHelpType() == PUBSUB_INTERMEDIATE ){
00767         PubSubIntermediateCall* intermediateCall = new PubSubIntermediateCall("Become my intermediate node!");
00768         intermediateCall->setSubspaceId( helpResp->getSubspaceId() );
00769         intermediateCall->setLength( PUBSUB_INTERMEDIATECALL_L( intermediateCall ));
00770         RECORD_STATS(
00771                 ++numPubSubSignalingMessages;
00772                 pubSubSignalingMessagesSize+= intermediateCall->byteLength()
00773                 );
00774         sendUdpRpcCall( helpResp->getNode(), intermediateCall );
00775     }
00776 }

void PubSubMMOG::handleBackupCall ( PubSubBackupCall *  backupCall  )  [protected]

Referenced by handleRpc().

00779 {
00780     int intId = backupCall->getSubspaceId();
00781     PubSubSubspaceId subspaceId(intId, numSubspaces);
00782 
00783     // Start Heartbeat Timer
00784     PubSubTimer* parentTimeout = new PubSubTimer("ParentTimeout");
00785     parentTimeout->setType( PUBSUB_PARENT_TIMEOUT );
00786     parentTimeout->setSubspaceId( intId );
00787     startTimer( parentTimeout );
00788 
00789     // insert subspace into responsible list
00790     PubSubSubspaceResponsible subspace( subspaceId );
00791     subspace.setResponsibleNode( backupCall->getSrcNode() );
00792     subspace.setHeartbeatTimer( parentTimeout );
00793 
00794     // recounstruct load balancing tree
00795     for( unsigned int i = 0; i < backupCall->getIntermediatesArraySize(); ++i ){
00796         PubSubSubspaceResponsible::IntermediateNode iNode;
00797         iNode.node = backupCall->getIntermediates(i);
00798         subspace.intermediateNodes.push_back( iNode );
00799     }
00800     for( unsigned int i = 0; i < backupCall->getChildrenArraySize(); ++i ){
00801         int pos = backupCall->getChildrenPos( i );
00802         if( pos == -2 ){
00803             subspace.cachedChildren.insert( make_pair( backupCall->getChildren(i), false ));
00804         } else if( pos == -1 ){
00805             subspace.children.insert( backupCall->getChildren(i) );
00806         } else {
00807             subspace.intermediateNodes[pos].children.insert( backupCall->getChildren(i) );
00808         }
00809     }
00810 
00811     backupSubspaces.insert( make_pair(subspaceId, subspace) );
00812 
00813     PubSubBackupResponse* backupResp = new PubSubBackupResponse("I'll be your backup");
00814     backupResp->setSubspaceId( intId );
00815     backupResp->setLength( PUBSUB_BACKUPRESPONSE_L( backupResp ));
00816     RECORD_STATS(
00817             ++numPubSubSignalingMessages;
00818             pubSubSignalingMessagesSize+= backupResp->byteLength()
00819             );
00820     sendRpcResponse( backupCall, backupResp );
00821 }

void PubSubMMOG::handleBackupResponse ( PubSubBackupResponse *  backupResp  )  [protected]

Referenced by handleRpcResponse().

00824 {
00825     // Nothing to be done
00826     // HandleHelpResponse() already did everything important
00827 }

void PubSubMMOG::handleIntermediateCall ( PubSubIntermediateCall *  intermediateCall  )  [protected]

Referenced by handleRpc().

00830 {
00831     // insert subspace into intermediate list
00832     PubSubSubspaceId subspaceId(intermediateCall->getSubspaceId(), numSubspaces);
00833     PubSubSubspaceIntermediate subspace( subspaceId );
00834     subspace.setResponsibleNode( intermediateCall->getSrcNode() );
00835     subspace.setTimestamp(0);
00836     intermediateSubspaces.insert( make_pair(subspaceId, subspace) );
00837 
00838     PubSubIntermediateResponse* iResp = new PubSubIntermediateResponse("I'll be your intermediate node");
00839     iResp->setSubspaceId( intermediateCall->getSubspaceId() );
00840     iResp->setLength( PUBSUB_INTERMEDIATERESPONSE_L( iResp ));
00841     RECORD_STATS(
00842             ++numPubSubSignalingMessages;
00843             pubSubSignalingMessagesSize+= iResp->byteLength()
00844             );
00845     sendRpcResponse( intermediateCall, iResp );
00846 }

void PubSubMMOG::handleIntermediateResponse ( PubSubIntermediateResponse *  intermediateResp  )  [protected]

Referenced by handleRpcResponse().

00849 {
00850     // we found a new intermediate node for a subspace
00851     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
00852     it = responsibleSubspaces.find( PubSubSubspaceId(intermediateResp->getSubspaceId(), numSubspaces) );
00853     if( it == responsibleSubspaces.end() ) {
00854         EV << "PubSubMMOG::handleIntermediateResponse @ " << thisNode << "\n"
00855             << "  Received Intermediate Response for unknown Subspace!\n";
00856         return;
00857     }
00858     PubSubSubspaceResponsible& subspace = it->second;
00859     PubSubSubspaceResponsible::IntermediateNode iNode;
00860     iNode.node = intermediateResp->getSrcNode();
00861 
00862     // if there is any broken intermediate node in list, replace it
00863     bool newIntermediate = true;
00864     deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
00865     for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
00866         if( iit->node.isUnspecified() ){
00867             iit->node = iNode.node;
00868             newIntermediate = false;
00869             break;
00870         }
00871     }
00872     if( iit == subspace.intermediateNodes.end() ){
00873         subspace.intermediateNodes.push_back( iNode );
00874         iit = subspace.intermediateNodes.end() - 1;
00875     }
00876 
00877     // inform Backup
00878     if( !subspace.getBackupNode().isUnspecified() ){
00879         PubSubBackupIntermediateMessage* backupMsg = new PubSubBackupIntermediateMessage("Backup: new Intermediate");
00880         backupMsg->setSubspaceId( intermediateResp->getSubspaceId() );
00881         backupMsg->setNode( iNode.node );
00882         backupMsg->setPos( iit - subspace.intermediateNodes.begin() );
00883         backupMsg->setLength( PUBSUB_BACKUPINTERMEDIATE_L( backupMsg ));
00884         RECORD_STATS(
00885                 ++numPubSubSignalingMessages;
00886                 pubSubSignalingMessagesSize+= backupMsg->byteLength()
00887                 );
00888         sendMessageToUDP( subspace.getBackupNode(), backupMsg );
00889     }
00890 
00891     // if needed, send adopt to parent
00892     int intermediatePos = iit - subspace.intermediateNodes.begin();
00893     int parentPos = intermediatePos/maxChildren -1;
00894     if( parentPos >= 0 && !subspace.intermediateNodes[parentPos].node.isUnspecified() ){
00895         PubSubAdoptChildCall* adoptCall = new PubSubAdoptChildCall("Adopt (intermediate) Node");
00896         adoptCall->setSubspaceId( intermediateResp->getSubspaceId() );
00897         adoptCall->setChild( iit->node );
00898         adoptCall->setLength( PUBSUB_ADOPTCHILDCALL_L( adoptCall ));
00899         RECORD_STATS(
00900                 ++numPubSubSignalingMessages;
00901                 pubSubSignalingMessagesSize+= adoptCall->byteLength()
00902                 );
00903         sendUdpRpcCall( subspace.intermediateNodes[parentPos].node, adoptCall );
00904     }
00905 
00906     if( newIntermediate ){
00907         // move one child from iNodes's parent to cache
00908         if( parentPos >= 0 ) {
00909             // parent is an intermediate node
00910             PubSubSubspaceResponsible::IntermediateNode& parent = subspace.intermediateNodes[parentPos];
00911             if( parent.children.begin() != parent.children.end() ){
00912                 bool fixNeeded = false;
00913                 if( !subspace.cachedChildren.insert( make_pair( *(parent.children.begin()), false )).second ){
00914                     fixNeeded = true;
00915                 }
00916                 if( !subspace.getBackupNode().isUnspecified() ){
00917                     PubSubBackupSubscriptionMessage* backupMsg = new PubSubBackupSubscriptionMessage("Backup: nodes moved to cache");
00918                     backupMsg->setSubspaceId( intermediateResp->getSubspaceId() );
00919                     backupMsg->setChild( *(parent.children.begin()) );
00920                     backupMsg->setOldParent( parent.node );
00921                     backupMsg->setLength( PUBSUB_BACKUPSUBSCRIPTION_L( backupMsg ));
00922                     RECORD_STATS(
00923                             ++numPubSubSignalingMessages;
00924                             pubSubSignalingMessagesSize+= backupMsg->byteLength()
00925                             );
00926                     sendMessageToUDP( subspace.getBackupNode(), backupMsg );
00927                 }
00928                 PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Node left: moved");
00929                 goneMsg->setNode( *(parent.children.begin()) );
00930                 goneMsg->setSubspaceId( intermediateResp->getSubspaceId() );
00931                 goneMsg->setLength( PUBSUB_NODELEFT_L( goneMsg ));
00932                 RECORD_STATS(
00933                         ++numPubSubSignalingMessages;
00934                         pubSubSignalingMessagesSize+= goneMsg->byteLength()
00935                         );
00936                 sendMessageToUDP( parent.node, goneMsg );
00937                 parent.children.erase( parent.children.begin() );
00938                 if( fixNeeded ){
00939                     subspace.fixTotalChildrenCount();
00940                 }
00941             }
00942 
00943         } else {
00944             // we are parent
00945             if( subspace.children.begin() != subspace.children.end() ){
00946                 bool fixNeeded = false;
00947                 if( !subspace.cachedChildren.insert( make_pair( *(subspace.children.begin()), false )).second ){
00948                     fixNeeded = true;
00949                 }
00950                 if( !subspace.getBackupNode().isUnspecified() ){
00951                     PubSubBackupSubscriptionMessage* backupMsg = new PubSubBackupSubscriptionMessage("Backup: nodes moved to cache");
00952                     backupMsg->setSubspaceId( intermediateResp->getSubspaceId() );
00953                     backupMsg->setChild( *(subspace.children.begin()) );
00954                     backupMsg->setOldParent( thisNode );
00955                     backupMsg->setLength( PUBSUB_BACKUPSUBSCRIPTION_L( backupMsg ));
00956                     RECORD_STATS(
00957                             ++numPubSubSignalingMessages;
00958                             pubSubSignalingMessagesSize+= backupMsg->byteLength()
00959                             );
00960                     sendMessageToUDP( subspace.getBackupNode(), backupMsg );
00961                 }
00962                 subspace.children.erase( *(subspace.children.begin()) );
00963                 if( fixNeeded ){
00964                     subspace.fixTotalChildrenCount();
00965                 }
00966             }
00967         }
00968     } else {
00969         // send adopt for all children intermediates
00970         for( int pos = (intermediatePos+1) * maxChildren; pos < (int) subspace.intermediateNodes.size() &&
00971                 pos < (intermediatePos+2) * maxChildren; ++pos ){
00972             if( subspace.intermediateNodes[pos].node.isUnspecified() ) continue;
00973             PubSubAdoptChildCall* adoptCall = new PubSubAdoptChildCall("Adopt (intermediate) Node");
00974             adoptCall->setSubspaceId( intermediateResp->getSubspaceId() );
00975             adoptCall->setChild( subspace.intermediateNodes[pos].node );
00976             adoptCall->setLength( PUBSUB_ADOPTCHILDCALL_L( adoptCall ));
00977             RECORD_STATS(
00978                     ++numPubSubSignalingMessages;
00979                     pubSubSignalingMessagesSize+= adoptCall->byteLength()
00980                     );
00981             sendUdpRpcCall( iit->node, adoptCall );
00982         }
00983     }
00984 
00985     // move as many cached children to the new node as possible
00986     std::map<NodeHandle,bool>::iterator childIt;
00987     for( childIt = subspace.cachedChildren.begin(); childIt != subspace.cachedChildren.end(); ++childIt ){
00988         if( childIt->second ) continue;
00989         PubSubAdoptChildCall* adoptCall = new PubSubAdoptChildCall("Adopt Node");
00990         adoptCall->setSubspaceId( intermediateResp->getSubspaceId() );
00991         adoptCall->setChild( childIt->first );
00992         adoptCall->setLength( PUBSUB_ADOPTCHILDCALL_L( adoptCall ));
00993         RECORD_STATS(
00994                 ++numPubSubSignalingMessages;
00995                 pubSubSignalingMessagesSize+= adoptCall->byteLength()
00996                 );
00997         sendUdpRpcCall( intermediateResp->getSrcNode(), adoptCall );
00998         childIt->second = true;
00999         if( (unsigned int) maxChildren == ++(iit->waitingChildren) ) break;
01000     }
01001 }

void PubSubMMOG::handleAdoptChildCall ( PubSubAdoptChildCall *  adoptCall  )  [protected]

Referenced by handleRpc().

01004 {
01005     std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it;
01006     it = intermediateSubspaces.find( PubSubSubspaceId(adoptCall->getSubspaceId(), numSubspaces) );
01007     if( it == intermediateSubspaces.end() ) {
01008         EV << "PubSubMMOG::handleIntermediateResponse @ " << thisNode << "\n"
01009            << "  Received Intermediate Response for unknown Subspace!\n";
01010         cancelAndDelete( adoptCall );
01011         return;
01012     }
01013 
01014     it->second.addChild( adoptCall->getChild() );
01015     PubSubAdoptChildResponse* adoptResp = new PubSubAdoptChildResponse("I adopted child");
01016     adoptResp->setSubspaceId( adoptCall->getSubspaceId() );
01017     adoptResp->setChild( adoptCall->getChild() );
01018     adoptResp->setLength( PUBSUB_ADOPTCHILDRESPONSE_L( adoptResp ));
01019     RECORD_STATS(
01020             ++numPubSubSignalingMessages;
01021             pubSubSignalingMessagesSize+= adoptResp->byteLength()
01022             );
01023     sendRpcResponse( adoptCall, adoptResp );
01024 }

void PubSubMMOG::handleAdoptChildResponse ( PubSubAdoptChildResponse *  adoptResp  )  [protected]

Referenced by handleRpcResponse().

01027 {
01028     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01029     it = responsibleSubspaces.find( PubSubSubspaceId(adoptResp->getSubspaceId(), numSubspaces) );
01030     if( it == responsibleSubspaces.end() ) {
01031         EV << "PubSubMMOG::handleAdoptChildResponse @ " << thisNode << "\n"
01032             << "  Received AdoptChild Response for unknown Subspace!\n";
01033         return;
01034     }
01035 
01036 // FIXME: just for testing
01037 PubSubSubspaceResponsible& subspace = it->second;
01038 int iii = subspace.getTotalChildrenCount();
01039 subspace.fixTotalChildrenCount();
01040 if( iii != subspace.getTotalChildrenCount() ){
01041     opp_error("Huh?");
01042 }
01043 
01044     // Find intermediate node in subspace
01045     deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
01046     for( iit = it->second.intermediateNodes.begin(); iit !=  it->second.intermediateNodes.end(); ++iit ){
01047         if( !iit->node.isUnspecified() && iit->node == adoptResp->getSrcNode() ){
01048 
01049             // if adoption was for a child intermediate node, nothing is to be done
01050             int intermediatePos = iit - it->second.intermediateNodes.begin();
01051             for( int pos = (intermediatePos+1) * maxChildren; pos < (int) it->second.intermediateNodes.size() &&
01052                     pos < (intermediatePos+2) * maxChildren; ++pos )
01053             {
01054                 if( !it->second.intermediateNodes[pos].node.isUnspecified() &&
01055                         adoptResp->getChild() == it->second.intermediateNodes[pos].node ){
01056                     return;
01057                 }
01058             }
01059 
01060             // child is a "real" child->remove it from cache
01061             if( !it->second.cachedChildren.erase( adoptResp->getChild() ) ){
01062                 // if node got deleted in the meantime, inform parent...
01063                 PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Node left Subspace");
01064                 goneMsg->setNode( adoptResp->getChild() );
01065                 goneMsg->setSubspaceId( it->second.getId().getId() );
01066                 goneMsg->setLength( PUBSUB_NODELEFT_L( goneMsg ));
01067                 RECORD_STATS(
01068                         ++numPubSubSignalingMessages;
01069                         pubSubSignalingMessagesSize+= goneMsg->byteLength()
01070                         );
01071                 sendMessageToUDP( adoptResp->getSrcNode(), goneMsg );
01072                 return;
01073             }
01074 
01075             // move child to intermediate node's childrenlist
01076             if( !iit->children.insert( adoptResp->getChild() ).second ){
01077                 // Node was already in children list, fix children count
01078                 subspace.fixTotalChildrenCount();
01079             }
01080             iit->waitingChildren--;
01081 
01082 // FIXME: just for testing
01083 PubSubSubspaceResponsible& subspace = it->second;
01084 int iii = subspace.getTotalChildrenCount();
01085 subspace.fixTotalChildrenCount();
01086 if( iii != subspace.getTotalChildrenCount() ){
01087     opp_error("Huh?");
01088 }
01089 
01090             // Inform Backup
01091             if( !it->second.getBackupNode().isUnspecified() ){
01092                 PubSubBackupSubscriptionMessage* backupMsg = new PubSubBackupSubscriptionMessage("Backup: node got a new parent");
01093                 backupMsg->setSubspaceId( adoptResp->getSubspaceId() );
01094                 backupMsg->setChild( adoptResp->getChild() );
01095                 backupMsg->setParent( adoptResp->getSrcNode() );
01096                 backupMsg->setLength( PUBSUB_BACKUPSUBSCRIPTION_L( backupMsg ));
01097                 RECORD_STATS(
01098                         ++numPubSubSignalingMessages;
01099                        pubSubSignalingMessagesSize+= backupMsg->byteLength()
01100                        );
01101                 sendMessageToUDP( it->second.getBackupNode(), backupMsg );
01102                 return;
01103             }
01104         }
01105     }
01106 
01107     EV << "PubSubMMOG::handleAdoptChildResponse @ " << thisNode << "\n"
01108        << "  Received AdoptChild Response for unknown child!\n";
01109 }

void PubSubMMOG::handlePingCall ( PubSubPingCall *  hearbeatCall  )  [protected]

Referenced by handleRpc().

01112 {
01113     int subspaceId = pingCall->getSubspaceId();
01114 
01115     if( pingCall->getPingType() == PUBSUB_PING_BACKUP ){
01116         // reset heartbeat timer
01117         std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01118         it = backupSubspaces.find( PubSubSubspaceId(pingCall->getSubspaceId(), numSubspaces) );
01119         if( it == backupSubspaces.end() ) {
01120             EV << "PubSubMMOG::handlePingCall @ " << thisNode << "\n"
01121                 << "  Received PingCall for unknown Subspace!\n";
01122             // FIXME: Somebody thinks we are his backup. What shall we do?
01123         } else {
01124             it->second.resetHeartbeatFailCount();
01125             startTimer( it->second.getHeartbeatTimer() );
01126         }
01127     }
01128 
01129     PubSubPingResponse* pingResp = new PubSubPingResponse("PingResponse");
01130     pingResp->setSubspaceId( subspaceId );
01131     pingResp->setLength( PUBSUB_PINGRESPONSE_L( pingResp ));
01132     RECORD_STATS(
01133             ++numPubSubSignalingMessages;
01134             pubSubSignalingMessagesSize+= pingResp->byteLength()
01135             );
01136     sendRpcResponse( pingCall, pingResp );
01137 }

void PubSubMMOG::handlePingResponse ( PubSubPingResponse *  pingResp  )  [protected]

Referenced by handleRpcResponse().

01140 {
01141 }

void PubSubMMOG::takeOverNewSubspace ( PubSubSubspaceId  subspaceId  )  [protected]

Referenced by handleTakeOver().

01144 {
01145     // create a new subspace
01146     PubSubSubspaceResponsible subspace( subspaceId );
01147     takeOverSubspace( subspace, true );
01148 }

void PubSubMMOG::takeOverSubspace ( PubSubSubspaceResponsible subspaceId,
bool  isNew = false 
) [protected]

Referenced by handleParentTimeout(), and takeOverNewSubspace().

01151 {
01152     const PubSubSubspaceId& subspaceId = subspace.getId();
01153     int intId = subspaceId.getId();
01154 
01155     subspace.fixTotalChildrenCount();
01156 
01157     NodeHandle oldNode = subspace.getResponsibleNode();
01158 
01159     // insert subspace into responsible list
01160     subspace.setResponsibleNode( thisNode );
01161     responsibleSubspaces.insert( make_pair(subspaceId, subspace) );
01162 
01163     // request backup
01164     PubSubHelpCall* helpCall = new PubSubHelpCall("I need a backup node");
01165     helpCall->setHelpType( PUBSUB_BACKUP );
01166     helpCall->setSubspaceId( intId );
01167     helpCall->setLength( PUBSUB_HELPCALL_L( helpCall ));
01168     RECORD_STATS(
01169             ++numPubSubSignalingMessages;
01170             pubSubSignalingMessagesSize+= helpCall->byteLength()
01171             );
01172     sendUdpRpcCall( lobbyServer, helpCall );
01173 
01174     if( !isNew ) {
01175         PubSubReplacementMessage* repMsg = new PubSubReplacementMessage("I replaced the responsible node");
01176         repMsg->setSubspaceId( intId );
01177         repMsg->setNewResponsibleNode( thisNode );
01178         repMsg->setLength( PUBSUB_REPLACEMENT_L( repMsg ));
01179 
01180         // Inform children and lobbyserver about takeover
01181         sendMessageToChildren( subspace, repMsg, NULL, repMsg );
01182         sendMessageToUDP( lobbyServer, repMsg );
01183 
01184         // inform lobby server over failed node
01185         PubSubFailedNodeMessage* failedNode = new PubSubFailedNodeMessage("Node failed");
01186         failedNode->setFailedNode( oldNode );
01187         failedNode->setLength( PUBSUB_FAILEDNODE_L( failedNode ));
01188         RECORD_STATS(
01189                 ++numPubSubSignalingMessages;
01190                 pubSubSignalingMessagesSize+= failedNode->byteLength()
01191                 );
01192         sendMessageToUDP( lobbyServer, failedNode );
01193    }
01194 }

void PubSubMMOG::sendHearbeatToChildren (  )  [protected]

Referenced by handleTimerEvent().

01197 {
01198     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01199     for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it) {
01200         PubSubPingCall* bHeartbeat = new PubSubPingCall("Heartbeat Backup");
01201         bHeartbeat->setPingType( PUBSUB_PING_BACKUP );
01202         bHeartbeat->setSubspaceId( it->second.getId().getId() );
01203         bHeartbeat->setLength( PUBSUB_PINGCALL_L( bHeartbeat ));
01204 
01205         PubSubPingCall* iHeartbeat = new PubSubPingCall("Heartbeat Intermediate");
01206         iHeartbeat->setPingType( PUBSUB_PING_INTERMEDIATE );
01207         iHeartbeat->setSubspaceId( it->second.getId().getId() );
01208         iHeartbeat->setLength( PUBSUB_PINGCALL_L( iHeartbeat ));
01209 
01210         sendMessageToChildren( it->second, iHeartbeat, bHeartbeat, NULL);
01211         delete bHeartbeat;
01212         delete iHeartbeat;
01213     }
01214 }

void PubSubMMOG::sendPingToChildren (  )  [protected]

Referenced by handleTimerEvent().

01217 {
01218     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01219     for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it) {
01220         PubSubPingCall* heartbeat = new PubSubPingCall("Ping");
01221         heartbeat->setPingType( PUBSUB_PING_CHILD );
01222         heartbeat->setSubspaceId( it->second.getId().getId() );
01223         heartbeat->setLength( PUBSUB_PINGCALL_L( heartbeat ));
01224         sendMessageToChildren( it->second, NULL, NULL, heartbeat );
01225         delete heartbeat;
01226     }
01227 }

void PubSubMMOG::handleParentTimeout ( PubSubTimer *  timer  )  [protected]

Referenced by handleTimerEvent().

01230 {
01231     // our parent timed out. we have to take over the subspace...
01232     PubSubSubspaceId subspaceId(timer->getSubspaceId(), numSubspaces);
01233     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01234     it = backupSubspaces.find( subspaceId );
01235     if( it == backupSubspaces.end() ) {
01236         delete timer;
01237         return;
01238     }
01239 
01240     // increase fail count; if to high, take over subspace
01241     it->second.incHeartbeatFailCount();
01242     if( it->second.getHeartbeatFailCount() > 1 ) { // FIXME: make it a parameter
01243 
01244         // Delete Timer
01245         cancelAndDelete( timer );
01246         it->second.setHeartbeatTimer( NULL );
01247 
01248         // Take over Subspace
01249         takeOverSubspace( it->second );
01250         backupSubspaces.erase( it );
01251 
01252     } else {
01253         startTimer( timer );
01254     }
01255 }

void PubSubMMOG::handleBackupCallTimeout ( PubSubBackupCall *  backupCall,
const TransportAddress oldNode 
) [protected]

Referenced by handleRpcTimeout().

01258 {
01259     // FIXME: cast oldNode to NodeHandle
01260     // Inform Lobbyserver over failed node
01261     PubSubFailedNodeMessage* failedNode = new PubSubFailedNodeMessage("Node failed");
01262     failedNode->setFailedNode( oldNode );
01263     failedNode->setLength( PUBSUB_FAILEDNODE_L( failedNode ));
01264     RECORD_STATS(
01265             ++numPubSubSignalingMessages;
01266             pubSubSignalingMessagesSize+= failedNode->byteLength()
01267             );
01268     sendMessageToUDP( lobbyServer, failedNode );
01269 
01270     // Request new Backup
01271     PubSubHelpCall* helpCall = new PubSubHelpCall("I need a backup node");
01272     helpCall->setHelpType( PUBSUB_BACKUP );
01273     helpCall->setSubspaceId( backupCall->getSubspaceId() );
01274     helpCall->setLength( PUBSUB_HELPCALL_L( helpCall ));
01275     RECORD_STATS(
01276             ++numPubSubSignalingMessages;
01277             pubSubSignalingMessagesSize+= helpCall->byteLength()
01278             );
01279     sendUdpRpcCall( lobbyServer, helpCall );
01280 
01281     // find appropriate subspace and mark backup as failed
01282     PubSubSubspaceId subspaceId(backupCall->getSubspaceId(), numSubspaces);
01283     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01284     it = responsibleSubspaces.find( subspaceId );
01285     if( it == responsibleSubspaces.end() ) {
01286         return;
01287     }
01288     it->second.setBackupNode( NodeHandle::UNSPECIFIED_NODE );
01289 }

void PubSubMMOG::handlePingCallTimeout ( PubSubPingCall *  pingCall,
const TransportAddress oldNode 
) [protected]

Referenced by handleRpcTimeout().

01292 {
01293     // Inform Lobbyserver over failed node
01294     const NodeHandle& oldNodeHandle = dynamic_cast<const NodeHandle&>(oldNode);
01295     // FIXME: use oldNodeHandle instead of oldNode
01296     PubSubFailedNodeMessage* failedNode = new PubSubFailedNodeMessage("Node failed");
01297     failedNode->setLength( PUBSUB_FAILEDNODE_L( failedNode ));
01298     RECORD_STATS(
01299             ++numPubSubSignalingMessages;
01300             pubSubSignalingMessagesSize+= failedNode->byteLength()
01301             );
01302     failedNode->setFailedNode( oldNode );
01303     sendMessageToUDP( lobbyServer, failedNode );
01304 
01305     // find appropriate subspace
01306     PubSubSubspaceId subspaceId(pingCall->getSubspaceId(), numSubspaces);
01307     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01308     it = responsibleSubspaces.find( subspaceId );
01309     if( it == responsibleSubspaces.end() ) {
01310         return;
01311     }
01312     PubSubSubspaceResponsible& subspace = it->second;
01313 
01314     if( pingCall->getPingType() == PUBSUB_PING_CHILD ){
01315         // remove child
01316         unsubscribeChild( oldNodeHandle, subspace );
01317 
01318     } else if( pingCall->getPingType() == PUBSUB_PING_BACKUP ){
01319 
01320         // if we didn't already have (or asked for) a new backup
01321         if( !subspace.getBackupNode().isUnspecified() &&
01322                 subspace.getBackupNode() == oldNodeHandle )
01323         {
01324             // our backup timed out. we have to request a new one...
01325             // delete old backup entry
01326             subspace.setBackupNode( NodeHandle::UNSPECIFIED_NODE );
01327 
01328             // Request new Backup
01329             PubSubHelpCall* helpCall = new PubSubHelpCall("I need a backup node");
01330             helpCall->setHelpType( PUBSUB_BACKUP );
01331             helpCall->setSubspaceId( pingCall->getSubspaceId() );
01332             helpCall->setLength( PUBSUB_HELPCALL_L( helpCall ));
01333             RECORD_STATS(
01334                     ++numPubSubSignalingMessages;
01335                     pubSubSignalingMessagesSize+= helpCall->byteLength()
01336                     );
01337             sendUdpRpcCall( lobbyServer, helpCall );
01338         }
01339 
01340     } else if( pingCall->getPingType() == PUBSUB_PING_INTERMEDIATE ){
01341         // one intermediate node timed out. we have to request a new one...
01342         // delete old intermediate entry
01343         deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
01344         for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
01345             if( !iit->node.isUnspecified() && oldNode == iit->node ) break;
01346         }
01347         if( iit == subspace.intermediateNodes.end() ) return;
01348 
01349         NodeHandle oldNode = iit->node;
01350         iit->node = NodeHandle::UNSPECIFIED_NODE;
01351 
01352         // inform Backup
01353         if( !subspace.getBackupNode().isUnspecified() ){
01354             PubSubBackupIntermediateMessage* backupMsg = new PubSubBackupIntermediateMessage("Backup: Intermediate failed");
01355             backupMsg->setSubspaceId( pingCall->getSubspaceId() );
01356             backupMsg->setPos( iit - it->second.intermediateNodes.begin() );
01357             backupMsg->setLength( PUBSUB_BACKUPINTERMEDIATE_L( backupMsg ));
01358             RECORD_STATS(
01359                     ++numPubSubSignalingMessages;
01360                     pubSubSignalingMessagesSize+= backupMsg->byteLength()
01361                     );
01362             sendMessageToUDP( subspace.getBackupNode(), backupMsg );
01363         }
01364 
01365         bool fixNeeded = false;
01366         // Take over all children until new intermediate is found.
01367         set<NodeHandle>::iterator childIt;
01368         for(  childIt = iit->children.begin(); childIt != iit->children.end(); ++childIt ){
01369             if( !subspace.cachedChildren.insert( make_pair(*childIt, false)).second ){
01370                 fixNeeded = true;
01371             }
01372 
01373             // Inform Backup
01374             if( !subspace.getBackupNode().isUnspecified() ){
01375                 PubSubBackupSubscriptionMessage* backupMsg = new PubSubBackupSubscriptionMessage("Backup: nodes moved to cache");
01376                 backupMsg->setSubspaceId( pingCall->getSubspaceId() );
01377                 backupMsg->setChild( *childIt );
01378                 backupMsg->setOldParent( oldNodeHandle );
01379                 backupMsg->setLength( PUBSUB_BACKUPSUBSCRIPTION_L( backupMsg ));
01380                 RECORD_STATS(
01381                         ++numPubSubSignalingMessages;
01382                         pubSubSignalingMessagesSize+= backupMsg->byteLength()
01383                         );
01384                 sendMessageToUDP( subspace.getBackupNode(), backupMsg );
01385             }
01386         }
01387         iit->children.clear();
01388         if( fixNeeded ) subspace.fixTotalChildrenCount();
01389 
01390         // inform parent of intermediate node
01391         int parentPos = (iit - subspace.intermediateNodes.begin())/maxChildren -1;
01392         if( parentPos >= 0 ){
01393             PubSubSubspaceResponsible::IntermediateNode& parent = subspace.intermediateNodes[parentPos];
01394             if( !parent.node.isUnspecified() ){
01395                 PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Intermediate left Subspace");
01396                 goneMsg->setNode( oldNodeHandle );
01397                 goneMsg->setSubspaceId( subspace.getId().getId() );
01398                 goneMsg->setLength( PUBSUB_NODELEFT_L( goneMsg ));
01399                 RECORD_STATS(
01400                         ++numPubSubSignalingMessages;
01401                         pubSubSignalingMessagesSize+= goneMsg->byteLength()
01402                         );
01403                 sendMessageToUDP( parent.node, goneMsg );
01404             }
01405         }
01406 
01407         // Request new Intermediate
01408         PubSubHelpCall* helpCall = new PubSubHelpCall("I need an intermediate node");
01409         helpCall->setHelpType( PUBSUB_INTERMEDIATE );
01410         helpCall->setSubspaceId( pingCall->getSubspaceId() );
01411         helpCall->setLength( PUBSUB_HELPCALL_L( helpCall ));
01412         RECORD_STATS(
01413                 ++numPubSubSignalingMessages;
01414                 pubSubSignalingMessagesSize+= helpCall->byteLength()
01415                 );
01416         sendUdpRpcCall( lobbyServer, helpCall );
01417     }
01418 // FIXME: just for testing
01419 int iii = subspace.getTotalChildrenCount();
01420 subspace.fixTotalChildrenCount();
01421 if( iii != subspace.getTotalChildrenCount() ){
01422     opp_error("Huh?");
01423 }
01424 
01425 }

void PubSubMMOG::handleSubscriptionCallTimeout ( PubSubSubscriptionCall *  subscriptionCall,
const TransportAddress oldNode 
) [protected]

Referenced by handleRpcTimeout().

01428 {
01429     // FIXME: cast oldNode to NodeHandle
01430     // our subscription call timed out. This means the responsible node is dead...
01431     // Inform Lobbyserver over failed node
01432     PubSubFailedNodeMessage* failedNode = new PubSubFailedNodeMessage("Node failed");
01433     failedNode->setFailedNode( oldNode );
01434     failedNode->setLength( PUBSUB_FAILEDNODE_L( failedNode ));
01435     RECORD_STATS(
01436             ++numPubSubSignalingMessages;
01437             pubSubSignalingMessagesSize+= failedNode->byteLength()
01438             );
01439     sendMessageToUDP( lobbyServer, failedNode );
01440 
01441     // Ask for new responsible node
01442     PubSubResponsibleNodeCall* respCall = new PubSubResponsibleNodeCall("Request Responsible NodeHandle");
01443     PubSubSubspaceId subspaceId( subscriptionCall->getSubspaceId(), numSubspaces);
01444     respCall->setSubspacePos( Vector2D(subspaceId.getX(), subspaceId.getY()) );
01445     respCall->setLength( PUBSUB_RESPONSIBLENODECALL_L( respCall ));
01446     RECORD_STATS(
01447             ++numPubSubSignalingMessages;
01448             pubSubSignalingMessagesSize+= respCall->byteLength()
01449             );
01450     sendUdpRpcCall( lobbyServer, respCall, NULL, 5, 5 ); // FIXME: Make it a parameter...
01451 }

void PubSubMMOG::handleUnsubscriptionMessage ( PubSubUnsubscriptionMessage *  unsMsg  )  [protected]

Referenced by handleUDPMessage().

00412 {
00413     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
00414     it = responsibleSubspaces.find( PubSubSubspaceId(unsMsg->getSubspaceId(), numSubspaces) );
00415 
00416     if( it != responsibleSubspaces.end() ) {
00417         unsubscribeChild( unsMsg->getSrc(), it->second );
00418     }
00419 }

void PubSubMMOG::handleNodeLeftMessage ( PubSubNodeLeftMessage *  leftMsg  )  [protected]

Referenced by handleUDPMessage().

00422 {
00423     std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it;
00424     it = intermediateSubspaces.find( PubSubSubspaceId(leftMsg->getSubspaceId(), numSubspaces) );
00425 
00426     if( it == intermediateSubspaces.end() ) return;
00427 
00428     it->second.removeChild( leftMsg->getNode() );
00429 }

void PubSubMMOG::handleReplacementMessage ( PubSubReplacementMessage *  replaceMsg  )  [protected]

Referenced by handleUDPMessage().

01454 {
01455     PubSubSubspaceId subspaceId(replaceMsg->getSubspaceId(), numSubspaces);
01456 
01457     // There's a new responsible node for a subspace
01458     // Replace the old one in the intermediateSubspaces map...
01459     std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it;
01460     it = intermediateSubspaces.find( subspaceId );
01461     if( it != intermediateSubspaces.end() ) {
01462         it->second.setResponsibleNode( replaceMsg->getNewResponsibleNode() );
01463     }
01464 
01465     // ... and in the subsribed subspaces list
01466     std::list<PubSubSubspace>::iterator iit;
01467     for( iit = subscribedSubspaces.begin(); iit != subscribedSubspaces.end(); ++iit ){
01468         if( iit->getId() == subspaceId ) {
01469             iit->setResponsibleNode( replaceMsg->getNewResponsibleNode() );
01470             return;
01471         }
01472     }
01473 }

void PubSubMMOG::handleReleaseIntermediate ( PubSubReleaseIntermediateMessage *  releaseMsg  )  [protected]

Referenced by handleUDPMessage().

01476 {
01477     PubSubSubspaceId subspaceId(releaseMsg->getSubspaceId(), numSubspaces);
01478     intermediateSubspaces.erase( subspaceId );
01479 }

void PubSubMMOG::handleIntermediateBackup ( PubSubBackupIntermediateMessage *  backupMsg  )  [protected]

Referenced by handleUDPMessage().

01482 {
01483     // find appropriate subspace
01484     PubSubSubspaceId subspaceId(backupMsg->getSubspaceId(), numSubspaces);
01485     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01486     it = backupSubspaces.find( subspaceId );
01487     if( it == backupSubspaces.end() ) {
01488         return;
01489     }
01490 
01491     if( backupMsg->getPos() >= (int) it->second.intermediateNodes.size() ){
01492         it->second.intermediateNodes.resize( backupMsg->getPos() + 1 );
01493     }
01494     it->second.intermediateNodes[ backupMsg->getPos() ].node = backupMsg->getNode();
01495 }

void PubSubMMOG::handleSubscriptionBackup ( PubSubBackupSubscriptionMessage *  backupMsg  )  [protected]

Referenced by handleUDPMessage().

01498 {
01499     // Note: this funktion may break subspace's tatalChildrenCall
01500     // You have to use fixTotalChildrenCount before using the subspace
01501     // find appropriate subspace
01502     PubSubSubspaceId subspaceId(backupMsg->getSubspaceId(), numSubspaces);
01503     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01504     it = backupSubspaces.find( subspaceId );
01505     if( it == backupSubspaces.end() ) {
01506         return;
01507     }
01508     PubSubSubspaceResponsible& subspace = it->second;
01509 
01510     deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
01511 
01512     if( !backupMsg->getOldParent().isUnspecified() ){
01513         // oldParent set -> move child
01514         if( backupMsg->getOldParent() == subspace.getResponsibleNode() ){
01515             // direct child -> cache
01516             subspace.removeChild( backupMsg->getChild() );
01517             subspace.cachedChildren.insert(make_pair( backupMsg->getChild(), false) );
01518 
01519         } else {
01520             // from I -> chache
01521             for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
01522 //                if( !iit->node.isUnspecified() && iit->node == backupMsg->getOldParent() ){
01523                     iit->children.erase( backupMsg->getChild() );
01524 //                }
01525             }
01526             subspace.cachedChildren.insert(make_pair( backupMsg->getChild(), false) );
01527         }
01528     } else if( backupMsg->getParent().isUnspecified() ){
01529         // parent not set -> new child to chache
01530         subspace.cachedChildren.insert(make_pair( backupMsg->getChild(), false) );
01531 
01532     } else if( backupMsg->getParent() == subspace.getResponsibleNode() ){
01533         // new direct child
01534         subspace.addChild( backupMsg->getChild() );
01535     } else {
01536         // move child from cache to intermediate
01537         subspace.cachedChildren.erase( backupMsg->getChild() );
01538 
01539         for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
01540             if( !iit->node.isUnspecified() && iit->node == backupMsg->getParent() ){
01541                 iit->children.insert( backupMsg->getChild() );
01542             }
01543         }
01544         // FIXME: check for errors
01545     }
01546 }

void PubSubMMOG::handleUnsubscribeBackup ( PubSubBackupUnsubscribeMessage *  backupMsg  )  [protected]

Referenced by handleUDPMessage().

01549 {
01550     // Note: this funktion may break subspace's tatalChildrenCall
01551     // You have to use fixTotalChildrenCount before using the subspace
01552     // find appropriate subspace
01553     PubSubSubspaceId subspaceId(backupMsg->getSubspaceId(), numSubspaces);
01554     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01555     it = backupSubspaces.find( subspaceId );
01556     if( it == backupSubspaces.end() ) {
01557         return;
01558     }
01559     PubSubSubspaceResponsible& subspace = it->second;
01560 
01561     deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
01562     set<NodeHandle>::iterator childIt;
01563 
01564     if( !subspace.removeChild(backupMsg->getChild()) && !subspace.cachedChildren.erase( backupMsg->getChild()) ){
01565         for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
01566             iit->children.erase( backupMsg->getChild() );
01567         }
01568     }
01569     if( !backupMsg->getIntermediate().isUnspecified() ){
01570         // remove intermediate
01571         for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
01572             if( !iit->node.isUnspecified() && iit->node == backupMsg->getIntermediate() ){
01573                 for( childIt = iit->children.begin(); childIt != iit->children.end(); ++childIt ){
01574                     // FIXME: note really stable. let the resp node inform us about child moves
01575                     // remove children of last intermediate
01576                     if( subspace.getNumChildren() + subspace.getNumIntermediates() < maxChildren ){
01577                         // we have room for the child
01578                         subspace.children.insert( *childIt );
01579                     } else {
01580                         // Node has to go to some intermediate
01581                         // cache it
01582                         subspace.cachedChildren.insert( make_pair(*childIt, true) );
01583                     }
01584                 }
01585                 subspace.intermediateNodes.erase( iit );
01586                 break;
01587             }
01588         }
01589     }
01590 }

void PubSubMMOG::unsubscribeChild ( const NodeHandle node,
PubSubSubspaceResponsible subspace 
) [protected]

Referenced by handlePingCallTimeout(), and handleUnsubscriptionMessage().

01593 {
01594     PubSubBackupUnsubscribeMessage* backupMsg = new PubSubBackupUnsubscribeMessage("Backup: node left subspace");
01595     backupMsg->setChild( node );
01596     backupMsg->setSubspaceId( subspace.getId().getId() );
01597     PubSubSubspaceResponsible::IntermediateNode* iNode = subspace.removeAnyChild( node );
01598     if( iNode && !iNode->node.isUnspecified() ) {
01599         // Node is handled by an intermediate node, inform him
01600         PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Node left Subspace");
01601         goneMsg->setNode( node );
01602         goneMsg->setSubspaceId( subspace.getId().getId() );
01603         goneMsg->setLength( PUBSUB_NODELEFT_L( goneMsg ));
01604         RECORD_STATS(
01605                 ++numPubSubSignalingMessages;
01606                 pubSubSignalingMessagesSize+= goneMsg->byteLength()
01607                 );
01608         sendMessageToUDP( iNode->node, goneMsg );
01609     }
01610     if ( subspace.getTotalChildrenCount() < ( maxChildren - 1) * subspace.getNumIntermediates()){// FIXME: parameter when to start cleanup?
01611         // Too many "free" slots, remove one intermediate node
01612         PubSubSubspaceResponsible::IntermediateNode& liNode = subspace.intermediateNodes.back();
01613         if( !liNode.node.isUnspecified() ){
01614             // Inform node + lobby about release from intermediate node status
01615             PubSubReleaseIntermediateMessage* releaseMsg = new PubSubReleaseIntermediateMessage("I don't need you anymore as intermediate");
01616             releaseMsg->setSubspaceId( subspace.getId().getId() );
01617             releaseMsg->setLength( PUBSUB_RELEASEINTERMEDIATE_L( releaseMsg ));
01618             RECORD_STATS(
01619                     ++numPubSubSignalingMessages;
01620                     pubSubSignalingMessagesSize+= releaseMsg->byteLength()
01621                     );
01622             sendMessageToUDP( liNode.node, releaseMsg );
01623 
01624             PubSubHelpReleaseMessage* helpRMsg = new PubSubHelpReleaseMessage("node is not my intermediate anymore");
01625             helpRMsg->setSubspaceId( subspace.getId().getId() );
01626             helpRMsg->setNode( liNode.node );
01627             helpRMsg->setLength( PUBSUB_HELPRELEASE_L( helpRMsg ));
01628             RECORD_STATS(
01629                     ++numPubSubSignalingMessages;
01630                     pubSubSignalingMessagesSize+= helpRMsg->byteLength()
01631                     );
01632             sendMessageToUDP( lobbyServer, helpRMsg );
01633 
01634             // inform parent of intermediate node
01635             int parentPos = (subspace.intermediateNodes.size()-1)/maxChildren -1;
01636             if( parentPos >= 0 ){
01637                 PubSubSubspaceResponsible::IntermediateNode& parent = subspace.intermediateNodes[parentPos];
01638                 if( !parent.node.isUnspecified() ){
01639                     PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Intermediate left Subspace");
01640                     goneMsg->setNode( liNode.node );
01641                     goneMsg->setSubspaceId( subspace.getId().getId() );
01642                     goneMsg->setLength( PUBSUB_NODELEFT_L( goneMsg ));
01643                     RECORD_STATS(
01644                             ++numPubSubSignalingMessages;
01645                             pubSubSignalingMessagesSize+= goneMsg->byteLength()
01646                             );
01647                     sendMessageToUDP( parent.node, goneMsg );
01648                 }
01649             }
01650         }
01651 
01652         bool fixNeeded = false;
01653         set<NodeHandle>::iterator childIt;
01654         for( childIt = liNode.children.begin(); childIt != liNode.children.end(); ++childIt ){
01655             // remove children of last intermediate
01656             if( subspace.getNumChildren() + subspace.getNumIntermediates() < maxChildren ){
01657                 // we have room for the child
01658                 if( !subspace.children.insert( *childIt ).second ) fixNeeded = true;
01659 
01660                 //FIXME: send backup new->toMe
01661             } else {
01662                 // Node has to go to some intermediate
01663                 // find intermediate with free capacities
01664                 PubSubSubspaceResponsible::IntermediateNode* newINode;
01665                 newINode = subspace.getNextFreeIntermediate();
01666 
01667                 if( newINode  && newINode->node != liNode.node ){
01668                     // cache it
01669                     if( !subspace.cachedChildren.insert( make_pair(*childIt, true) ).second ) fixNeeded = true;
01670                     //FIXME: send backup new->toCache
01671 
01672                     ++(newINode->waitingChildren);
01673 
01674                     // let him adopt the child
01675                     PubSubAdoptChildCall* adoptCall = new PubSubAdoptChildCall("Adopt Node");
01676                     adoptCall->setSubspaceId( subspace.getId().getId() );
01677                     adoptCall->setChild( *childIt );
01678                     adoptCall->setLength( PUBSUB_ADOPTCHILDCALL_L( adoptCall ));
01679                     RECORD_STATS(
01680                             ++numPubSubSignalingMessages;
01681                             pubSubSignalingMessagesSize+= adoptCall->byteLength()
01682                             );
01683                     sendUdpRpcCall( newINode->node, adoptCall );
01684                 } else {
01685                     // no intermediate found
01686                     // just move child to cache and wait for a new one
01687                     if( !subspace.cachedChildren.insert( make_pair(*childIt, false) ).second ) fixNeeded = true;
01688                 }
01689             }
01690         }
01691         // delete node from subspace's intermediate node list
01692         subspace.intermediateNodes.pop_back();
01693         // inform backup about deleted intermediate
01694         backupMsg->setIntermediate( liNode.node );
01695 
01696         if( fixNeeded ) subspace.fixTotalChildrenCount();
01697     }
01698 
01699 // FIXME: just for testing
01700 int iii = subspace.getTotalChildrenCount();
01701 subspace.fixTotalChildrenCount();
01702 if( iii != subspace.getTotalChildrenCount() ){
01703     opp_error("Huh?");
01704 }
01705 
01706     if( !subspace.getBackupNode().isUnspecified() ){
01707         backupMsg->setLength( PUBSUB_BACKUPUNSUBSCRIBE_L( backupMsg ));
01708         RECORD_STATS(
01709                 ++numPubSubSignalingMessages;
01710                 pubSubSignalingMessagesSize+= backupMsg->byteLength()
01711                 );
01712         sendMessageToUDP( subspace.getBackupNode(), backupMsg );
01713     } else {
01714         delete backupMsg;
01715     }
01716 }

void PubSubMMOG::sendMessageToChildren ( PubSubSubspaceResponsible subspace,
BaseOverlayMessage *  toIntermediates,
BaseOverlayMessage *  toBackup,
BaseOverlayMessage *  toPlayers 
) [protected]

Referenced by sendHearbeatToChildren(), sendPingToChildren(), and takeOverSubspace().

01722 {
01723     BaseCallMessage* intermediateCall = dynamic_cast<BaseCallMessage*>(toIntermediates);
01724     BaseCallMessage* backupCall = dynamic_cast<BaseCallMessage*>(toBackup);
01725     BaseCallMessage* playerCall = dynamic_cast<BaseCallMessage*>(toPlayers);
01726 
01727     std::set<NodeHandle>::iterator childIt;
01728 
01729     if( toPlayers ) {
01730         // Inform all children ...
01731         for( childIt = subspace.children.begin(); childIt != subspace.children.end(); ++childIt ) {
01732             if( playerCall ){
01733                 RECORD_STATS(
01734                         ++numPubSubSignalingMessages;
01735                         pubSubSignalingMessagesSize+= playerCall->byteLength()
01736                         );
01737                 sendUdpRpcCall( *childIt, static_cast<BaseCallMessage*>(playerCall->dup()) );
01738             } else {
01739                 RECORD_STATS(
01740                         ++numPubSubSignalingMessages;
01741                         pubSubSignalingMessagesSize+= toPlayers->byteLength()
01742                         );
01743                 sendMessageToUDP( *childIt, static_cast<BaseOverlayMessage*>(toPlayers->dup()) );
01744             }
01745         }
01746         // ... and all cached children ...
01747         std::map<NodeHandle, bool>::iterator cacheChildIt;
01748         for( cacheChildIt = subspace.cachedChildren.begin(); cacheChildIt != subspace.cachedChildren.end(); ++cacheChildIt ) {
01749             if( playerCall ){
01750                 RECORD_STATS(
01751                         ++numPubSubSignalingMessages;
01752                         pubSubSignalingMessagesSize+= playerCall->byteLength()
01753                         );
01754                 sendUdpRpcCall( cacheChildIt->first, static_cast<BaseCallMessage*>(playerCall->dup()) );
01755             } else {
01756                 RECORD_STATS(
01757                         ++numPubSubSignalingMessages;
01758                         pubSubSignalingMessagesSize+= toPlayers->byteLength()
01759                         );
01760                 sendMessageToUDP( cacheChildIt->first, static_cast<BaseOverlayMessage*>(toPlayers->dup()) );
01761             }
01762         }
01763     }
01764     deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
01765     // ... all intermediate nodes ...
01766     for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
01767         if( toIntermediates && !iit->node.isUnspecified() ){
01768             if( intermediateCall ){
01769                 RECORD_STATS(
01770                         ++numPubSubSignalingMessages;
01771                         pubSubSignalingMessagesSize+= intermediateCall->byteLength()
01772                         );
01773                 sendUdpRpcCall( iit->node, static_cast<BaseCallMessage*>(intermediateCall->dup()) );
01774             } else {
01775                 RECORD_STATS(
01776                         ++numPubSubSignalingMessages;
01777                         pubSubSignalingMessagesSize+= toIntermediates->byteLength()
01778                         );
01779                 sendMessageToUDP( iit->node, static_cast<BaseOverlayMessage*>(toIntermediates->dup()) );
01780             }
01781         }
01782         if( toPlayers ) {
01783             // .. and all intermediate node's children ...
01784             for( childIt = iit->children.begin(); childIt != iit->children.end(); ++childIt ){
01785                 if( playerCall ){
01786                     RECORD_STATS(
01787                             ++numPubSubSignalingMessages;
01788                             pubSubSignalingMessagesSize+= playerCall->byteLength()
01789                             );
01790                     sendUdpRpcCall( *childIt, static_cast<BaseCallMessage*>(playerCall->dup()) );
01791                 } else {
01792                     RECORD_STATS(
01793                             ++numPubSubSignalingMessages;
01794                             pubSubSignalingMessagesSize+= toPlayers->byteLength()
01795                             );
01796                     sendMessageToUDP( *childIt, static_cast<BaseOverlayMessage*>(toPlayers->dup()) );
01797                 }
01798             }
01799         }
01800     }
01801     // ... and the backup node
01802     if( toBackup && !subspace.getBackupNode().isUnspecified() ) {
01803         if( backupCall ){
01804             RECORD_STATS(
01805                     ++numPubSubSignalingMessages;
01806                     pubSubSignalingMessagesSize+= backupCall->byteLength()
01807                     );
01808             sendUdpRpcCall( subspace.getBackupNode(), static_cast<BaseCallMessage*>(backupCall->dup()) );
01809         } else {
01810             RECORD_STATS(
01811                     ++numPubSubSignalingMessages;
01812                     pubSubSignalingMessagesSize+= toBackup->byteLength()
01813                     );
01814             sendMessageToUDP( subspace.getBackupNode(), static_cast<BaseOverlayMessage*>(toBackup->dup()) );
01815         }
01816     }
01817 }

void PubSubMMOG::publishEvents (  )  [protected]

Referenced by handleTimerEvent().

01821 {
01822     // FOr all (responsible) subspaces
01823     int numRespSubspaces = responsibleSubspaces.size();
01824     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01825     for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it ){
01826         PubSubSubspaceResponsible& subspace = it->second;
01827 
01828         // Prepare a movement list message aggregating all stored move messages
01829         PubSubMoveListMessage* moveList = new PubSubMoveListMessage("Movement list");
01830         moveList->setTimestamp( simulation.simTime() );
01831         moveList->setSubspaceId( subspace.getId().getId() );
01832         moveList->setPlayerArraySize( subspace.waitingMoveMessages.size() );
01833         moveList->setPositionArraySize( subspace.waitingMoveMessages.size() );
01834 
01835         std::deque<PubSubMoveMessage*>::iterator msgIt;
01836         int pos = 0;
01837         for( msgIt = subspace.waitingMoveMessages.begin(); msgIt != subspace.waitingMoveMessages.end(); ++msgIt ){
01838             moveList->setPlayer( pos, (*msgIt)->getPlayer() );
01839             moveList->setPosition( pos, (*msgIt)->getPosition() );
01840             pos++;
01841             cancelAndDelete( *msgIt );
01842         }
01843         subspace.waitingMoveMessages.clear();
01844 
01845         moveList->setLength( PUBSUB_MOVELIST_L( moveList ));
01846         // Send message to all direct children...
01847         for( set<NodeHandle>::iterator childIt = subspace.children.begin();
01848                 childIt != subspace.children.end(); ++childIt )
01849         {
01850             RECORD_STATS(
01851                     ++numMoveListMessages;
01852                     moveListMessagesSize+= moveList->byteLength();
01853                     respMoveListMessagesSize+= (double) moveList->byteLength() / numRespSubspaces
01854                     );
01855             sendMessageToUDP( *childIt, (BaseOverlayMessage*) moveList->dup() );
01856         }
01857 
01858         //... all cached children (if messages are not too big) ...
01859         if( moveList->byteLength() < 1024 ){ // FIXME: magic number. make it a parameter, or dependant on the available bandwidth
01860             for( map<NodeHandle, bool>::iterator childIt = subspace.cachedChildren.begin();
01861                     childIt != subspace.cachedChildren.end(); ++childIt )
01862             {
01863                 RECORD_STATS(
01864                         ++numMoveListMessages;
01865                         moveListMessagesSize+= moveList->byteLength();
01866                         respMoveListMessagesSize+= (double) moveList->byteLength() / numRespSubspaces
01867                         );
01868                 sendMessageToUDP( childIt->first, (BaseOverlayMessage*) moveList->dup() );
01869                 // ... but don't send msgs to too many cached children, as this would exhaust our bandwidth
01870             }
01871         }
01872 
01873         // ... all direct intermediates and intermediates with broken parent
01874         deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
01875         for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit )
01876         {
01877             int intermediatePos = iit - subspace.intermediateNodes.begin();
01878             if( intermediatePos >= maxChildren &&
01879                   !subspace.intermediateNodes[intermediatePos/maxChildren -1].node.isUnspecified() ) continue;
01880             if( !iit->node.isUnspecified() ) {
01881                 RECORD_STATS(
01882                         ++numMoveListMessages;
01883                         moveListMessagesSize+= moveList->byteLength();
01884                         respMoveListMessagesSize+= (double) moveList->byteLength() / numRespSubspaces
01885                 );
01886                 sendMessageToUDP( iit->node, (BaseOverlayMessage*) moveList->dup() );
01887             }
01888         }
01889 
01890         delete moveList;
01891     }
01892 }

void PubSubMMOG::startTimer ( PubSubTimer *  timer  )  [protected]

Referenced by handleBackupCall(), handleParentTimeout(), handlePingCall(), handleTimerEvent(), and initializeOverlay().

01913 {
01914     if( !timer ) {
01915         EV << "WARNING! Trying to start NULL timer @ " << thisNode << "\n";
01916         return;
01917     }
01918 
01919     if( timer->isScheduled() ) {
01920         cancelEvent( timer );
01921     }
01922 
01923     simtime_t duration = 0;
01924     switch( timer->getType() ) {
01925         case PUBSUB_HEARTBEAT:
01926             duration = parentTimeout/2;
01927             break;
01928         case PUBSUB_CHILDPING:
01929             duration = parentTimeout*10; // FIXME: make it a parameter
01930             break;
01931         case PUBSUB_PARENT_TIMEOUT:
01932             duration = parentTimeout;
01933             break;
01934         case PUBSUB_EVENTDELIVERY:
01935             duration = 1.0/movementRate;
01936             break;
01937     }
01938     scheduleAt(simulation.simTime() + duration, timer );
01939 }


Member Data Documentation

int PubSubMMOG::subspaceSize [protected]

int PubSubMMOG::AOIWidth [protected]

Referenced by handleMove(), and initializeOverlay().

int PubSubMMOG::numSubspaces [protected]

int PubSubMMOG::parentTimeout [protected]

int PubSubMMOG::maxChildren [protected]

unsigned int PubSubMMOG::currentRegionX [protected]

unsigned int PubSubMMOG::currentRegionY [protected]

int PubSubMMOG::movementRate [protected]

int PubSubMMOG::maxMoveDelay [protected]

PubSubTimer* PubSubMMOG::heartbeatTimer [protected]

Referenced by initializeOverlay(), and ~PubSubMMOG().

PubSubTimer* PubSubMMOG::childPingTimer [protected]

Referenced by initializeOverlay().

PubSubTimer* PubSubMMOG::eventDeliveryTimer [protected]

cMessage* PubSubMMOG::joinTimer [protected]

int PubSubMMOG::numMoveMessages [protected]


The documentation for this class was generated from the following files:

Generated on Fri Sep 19 13:05:08 2008 for ITM OverSim by  doxygen 1.5.5