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)
virtual void handleAppMessage (cMessage *msg)
 Processes "timer" self-messages.
virtual void receiveChangeNotification (int category, const cPolymorphic *details)
 callback-method for events at the NotificationBoard
virtual bool handleRpcCall (BaseCallMessage *msg)
 Processes Remote-Procedure-Call invocation 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
bool allowOldMoveMessages
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

Detailed Description

Definition at line 33 of file PubSubMMOG.h.


Constructor & Destructor Documentation

PubSubMMOG::~PubSubMMOG (  )  [virtual]

Definition at line 2006 of file PubSubMMOG.cc.

02007 {
02008     // Delete all waiting move messages
02009     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
02010     for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it) {
02011         deque<PubSubMoveMessage*>::iterator msgIt;
02012         for( msgIt = it->second.waitingMoveMessages.begin(); msgIt != it->second.waitingMoveMessages.end(); ++msgIt ){
02013             cancelAndDelete( *msgIt );
02014         }
02015         it->second.waitingMoveMessages.clear();
02016     }
02017 
02018     cancelAndDelete(heartbeatTimer);
02019 }


Member Function Documentation

void PubSubMMOG::finishOverlay (  )  [virtual]

collects statistical data in derived class

Reimplemented from BaseOverlay.

Definition at line 1977 of file PubSubMMOG.cc.

01978 {
01979     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
01980     if (time < GlobalStatistics::MIN_MEASURED) return;
01981 
01982     globalStatistics->addStdDev("PubSubMMOG: Sent Signaling Messages/s",
01983                                 numPubSubSignalingMessages / time);
01984     globalStatistics->addStdDev("PubSubMMOG: Sent Signaling bytes/s",
01985                                 pubSubSignalingMessagesSize / time);
01986     globalStatistics->addStdDev("PubSubMMOG: Sent Move Messages/s",
01987                                 numMoveMessages / time);
01988     globalStatistics->addStdDev("PubSubMMOG: Sent Move bytes/s",
01989                                 moveMessagesSize / time);
01990     globalStatistics->addStdDev("PubSubMMOG: Sent MoveList Messages/s",
01991                                 numMoveListMessages / time);
01992     globalStatistics->addStdDev("PubSubMMOG: Sent MoveList bytes/s",
01993                                 moveListMessagesSize / time);
01994     globalStatistics->addStdDev("PubSubMMOG: Received Move Events (correct timeslot)/s",
01995                                 numEventsCorrectTimeslot / time);
01996     globalStatistics->addStdDev("PubSubMMOG: Received Move Events (wrong timeslot)/s",
01997                                 numEventsWrongTimeslot / time);
01998     globalStatistics->addStdDev("PubSubMMOG: Responsible Nodes: Send MoveList Bytes/s",
01999                                 respMoveListMessagesSize / time);
02000     globalStatistics->addStdDev("PubSubMMOG: Lost or too long delayed MoveLists/s",
02001                                 lostMovementLists / time);
02002     globalStatistics->addStdDev("PubSubMMOG: Received valid MoveLists/s",
02003                                 receivedMovementLists / time);
02004 }

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

Definition at line 1026 of file PubSubMMOG.cc.

Referenced by handleRpcCall().

01027 {
01028     std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it;
01029     it = intermediateSubspaces.find( PubSubSubspaceId(adoptCall->getSubspaceId(), numSubspaces) );
01030     if( it == intermediateSubspaces.end() ) {
01031         EV << "[PubSubMMOG::handleAdoptChildCall() @ " << thisNode.getAddress()
01032            << " (" << thisNode.getKey().toString(16) << ")]\n"
01033            << "  Received Adopt Child Call for unknown Subspace!\n"
01034            << endl;
01035         cancelAndDelete( adoptCall );
01036         return;
01037     }
01038 
01039     it->second.addChild( adoptCall->getChild() );
01040     PubSubAdoptChildResponse* adoptResp = new PubSubAdoptChildResponse("I adopted child");
01041     adoptResp->setSubspaceId( adoptCall->getSubspaceId() );
01042     adoptResp->setChild( adoptCall->getChild() );
01043     adoptResp->setBitLength( PUBSUB_ADOPTCHILDRESPONSE_L( adoptResp ));
01044     RECORD_STATS(
01045             ++numPubSubSignalingMessages;
01046             pubSubSignalingMessagesSize+= adoptResp->getByteLength()
01047             );
01048     sendRpcResponse( adoptCall, adoptResp );
01049 }

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

Definition at line 1051 of file PubSubMMOG.cc.

Referenced by handleRpcResponse().

01052 {
01053     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01054     it = responsibleSubspaces.find( PubSubSubspaceId(adoptResp->getSubspaceId(), numSubspaces) );
01055     if( it == responsibleSubspaces.end() ) {
01056         EV << "[PubSubMMOG::handleAdoptChildResponse() @ " << thisNode.getAddress()
01057            << " (" << thisNode.getKey().toString(16) << ")]\n"
01058            << "  Received AdoptChild Response for unknown Subspace!\n"
01059            << endl;
01060         return;
01061     }
01062 
01063 // FIXME: just for testing
01064 PubSubSubspaceResponsible& subspace = it->second;
01065 int iii = subspace.getTotalChildrenCount();
01066 subspace.fixTotalChildrenCount();
01067 if( iii != subspace.getTotalChildrenCount() ){
01068     opp_error("Huh?");
01069 }
01070 
01071     // Find intermediate node in subspace
01072     deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
01073     for( iit = it->second.intermediateNodes.begin(); iit !=  it->second.intermediateNodes.end(); ++iit ){
01074         if( !iit->node.isUnspecified() && iit->node == adoptResp->getSrcNode() ){
01075 
01076             // if adoption was for a child intermediate node, nothing is to be done
01077             int intermediatePos = iit - it->second.intermediateNodes.begin();
01078             for( int pos = (intermediatePos+1) * maxChildren; pos < (int) it->second.intermediateNodes.size() &&
01079                     pos < (intermediatePos+2) * maxChildren; ++pos )
01080             {
01081                 if( !it->second.intermediateNodes[pos].node.isUnspecified() &&
01082                         adoptResp->getChild() == it->second.intermediateNodes[pos].node ){
01083                     return;
01084                 }
01085             }
01086 
01087             // child is a "real" child->remove it from cache
01088             if( !it->second.cachedChildren.erase( adoptResp->getChild() ) ){
01089                 // if node got deleted in the meantime, inform parent...
01090                 PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Node left Subspace");
01091                 goneMsg->setNode( adoptResp->getChild() );
01092                 goneMsg->setSubspaceId( it->second.getId().getId() );
01093                 goneMsg->setBitLength( PUBSUB_NODELEFT_L( goneMsg ));
01094                 RECORD_STATS(
01095                         ++numPubSubSignalingMessages;
01096                         pubSubSignalingMessagesSize+= goneMsg->getByteLength()
01097                         );
01098                 sendMessageToUDP( adoptResp->getSrcNode(), goneMsg );
01099                 return;
01100             }
01101 
01102             // move child to intermediate node's childrenlist
01103             if( !iit->children.insert( adoptResp->getChild() ).second ){
01104                 // Node was already in children list, fix children count
01105                 subspace.fixTotalChildrenCount();
01106             }
01107             iit->waitingChildren--;
01108 
01109 // FIXME: just for testing
01110 PubSubSubspaceResponsible& subspace = it->second;
01111 int iii = subspace.getTotalChildrenCount();
01112 subspace.fixTotalChildrenCount();
01113 if( iii != subspace.getTotalChildrenCount() ){
01114     opp_error("Huh?");
01115 }
01116 
01117             // Inform Backup
01118             if( !it->second.getBackupNode().isUnspecified() ){
01119                 PubSubBackupSubscriptionMessage* backupMsg = new PubSubBackupSubscriptionMessage("Backup: node got a new parent");
01120                 backupMsg->setSubspaceId( adoptResp->getSubspaceId() );
01121                 backupMsg->setChild( adoptResp->getChild() );
01122                 backupMsg->setParent( adoptResp->getSrcNode() );
01123                 backupMsg->setBitLength( PUBSUB_BACKUPSUBSCRIPTION_L( backupMsg ));
01124                 RECORD_STATS(
01125                         ++numPubSubSignalingMessages;
01126                        pubSubSignalingMessagesSize+= backupMsg->getByteLength()
01127                        );
01128                 sendMessageToUDP( it->second.getBackupNode(), backupMsg );
01129                 return;
01130             }
01131         }
01132     }
01133 
01134     EV << "[PubSubMMOG::handleAdoptChildResponse() @ " << thisNode.getAddress()
01135        << " (" << thisNode.getKey().toString(16) << ")]\n"
01136        << "  Received AdoptChild Response for unknown child!\n"
01137        << endl;
01138 }

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

Processes "timer" self-messages.

Parameters:
msg A self-message Processes non-commonAPI messages
msg non-commonAPIMessage

Reimplemented from BaseOverlay.

Definition at line 315 of file PubSubMMOG.cc.

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

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

Definition at line 799 of file PubSubMMOG.cc.

Referenced by handleRpcCall().

00800 {
00801     int intId = backupCall->getSubspaceId();
00802     PubSubSubspaceId subspaceId(intId, numSubspaces);
00803 
00804     // Start Heartbeat Timer
00805     PubSubTimer* parentTimeout = new PubSubTimer("ParentTimeout");
00806     parentTimeout->setType( PUBSUB_PARENT_TIMEOUT );
00807     parentTimeout->setSubspaceId( intId );
00808     startTimer( parentTimeout );
00809 
00810     // insert subspace into responsible list
00811     PubSubSubspaceResponsible subspace( subspaceId );
00812     subspace.setResponsibleNode( backupCall->getSrcNode() );
00813     subspace.setHeartbeatTimer( parentTimeout );
00814 
00815     // recounstruct load balancing tree
00816     for( unsigned int i = 0; i < backupCall->getIntermediatesArraySize(); ++i ){
00817         PubSubSubspaceResponsible::IntermediateNode iNode;
00818         iNode.node = backupCall->getIntermediates(i);
00819         subspace.intermediateNodes.push_back( iNode );
00820     }
00821     for( unsigned int i = 0; i < backupCall->getChildrenArraySize(); ++i ){
00822         int pos = backupCall->getChildrenPos( i );
00823         if( pos == -2 ){
00824             subspace.cachedChildren.insert( make_pair( backupCall->getChildren(i), false ));
00825         } else if( pos == -1 ){
00826             subspace.children.insert( backupCall->getChildren(i) );
00827         } else {
00828             subspace.intermediateNodes[pos].children.insert( backupCall->getChildren(i) );
00829         }
00830     }
00831 
00832     backupSubspaces.insert( make_pair(subspaceId, subspace) );
00833 
00834     PubSubBackupResponse* backupResp = new PubSubBackupResponse("I'll be your backup");
00835     backupResp->setSubspaceId( intId );
00836     backupResp->setBitLength( PUBSUB_BACKUPRESPONSE_L( backupResp ));
00837     RECORD_STATS(
00838             ++numPubSubSignalingMessages;
00839             pubSubSignalingMessagesSize+= backupResp->getByteLength()
00840             );
00841     sendRpcResponse( backupCall, backupResp );
00842 }

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

Definition at line 1288 of file PubSubMMOG.cc.

Referenced by handleRpcTimeout().

01289 {
01290     // FIXME: cast oldNode to NodeHandle
01291     // Inform Lobbyserver over failed node
01292     PubSubFailedNodeMessage* failedNode = new PubSubFailedNodeMessage("Node failed");
01293     failedNode->setFailedNode( oldNode );
01294     failedNode->setBitLength( PUBSUB_FAILEDNODE_L( failedNode ));
01295     RECORD_STATS(
01296             ++numPubSubSignalingMessages;
01297             pubSubSignalingMessagesSize+= failedNode->getByteLength()
01298             );
01299     sendMessageToUDP( lobbyServer, failedNode );
01300 
01301     // Request new Backup
01302     PubSubHelpCall* helpCall = new PubSubHelpCall("I need a backup node");
01303     helpCall->setHelpType( PUBSUB_BACKUP );
01304     helpCall->setSubspaceId( backupCall->getSubspaceId() );
01305     helpCall->setBitLength( PUBSUB_HELPCALL_L( helpCall ));
01306     RECORD_STATS(
01307             ++numPubSubSignalingMessages;
01308             pubSubSignalingMessagesSize+= helpCall->getByteLength()
01309             );
01310     sendUdpRpcCall( lobbyServer, helpCall );
01311 
01312     // find appropriate subspace and mark backup as failed
01313     PubSubSubspaceId subspaceId(backupCall->getSubspaceId(), numSubspaces);
01314     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01315     it = responsibleSubspaces.find( subspaceId );
01316     if( it == responsibleSubspaces.end() ) {
01317         return;
01318     }
01319     it->second.setBackupNode( NodeHandle::UNSPECIFIED_NODE );
01320 }

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

Definition at line 844 of file PubSubMMOG.cc.

Referenced by handleRpcResponse().

00845 {
00846     // Nothing to be done
00847     // HandleHelpResponse() already did everything important
00848 }

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

Definition at line 722 of file PubSubMMOG.cc.

Referenced by handleRpcResponse().

00723 {
00724    // lobby server answered our call for help
00725    // (i.e. he sends us a candidate for backup/intermediate nodes
00726     if( helpResp->getHelpType() == PUBSUB_BACKUP ){
00727         PubSubBackupCall* backupCall = new PubSubBackupCall("Become my backup node!");
00728         backupCall->setSubspaceId( helpResp->getSubspaceId() );
00729 
00730         // Find the subspace in the subspace map
00731         std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
00732         it = responsibleSubspaces.find( PubSubSubspaceId(helpResp->getSubspaceId(), numSubspaces) );
00733         if( it == responsibleSubspaces.end() ){
00734             EV << "[PubSubMMOG::handleHelpResponse() @ " << thisNode.getAddress()
00735                << " (" << thisNode.getKey().toString(16) << ")]\n"
00736                << "  received helpResponse for unknown subspace" << helpResp->getSubspaceId() << "\n"
00737                << endl;
00738             return;
00739         }
00740         PubSubSubspaceResponsible& subspace = it->second;
00741 
00742         // Assume the new backup will not refuse his task
00743         subspace.setBackupNode( helpResp->getNode() );
00744 
00745 // FIXME: just for testing
00746 int iii = subspace.getTotalChildrenCount();
00747 subspace.fixTotalChildrenCount();
00748 if( iii != subspace.getTotalChildrenCount() ){
00749     opp_error("Huh?");
00750 }
00751 
00752         // backup the load balancing tree
00753         backupCall->setChildrenArraySize( subspace.getTotalChildrenCount() );
00754         backupCall->setChildrenPosArraySize( subspace.getTotalChildrenCount() );
00755         backupCall->setIntermediatesArraySize( subspace.intermediateNodes.size() );
00756 
00757         set<NodeHandle>::iterator childIt;
00758         map<NodeHandle, bool>::iterator childMapIt;
00759         unsigned int i = 0;
00760         for( childMapIt = subspace.cachedChildren.begin(); childMapIt != subspace.cachedChildren.end(); ++childMapIt ){
00761             backupCall->setChildren(i, childMapIt->first);
00762             backupCall->setChildrenPos(i, -2);
00763             ++i;
00764         }
00765         for( childIt = subspace.children.begin(); childIt != subspace.children.end(); ++childIt ){
00766             backupCall->setChildren(i, *childIt);
00767             backupCall->setChildrenPos(i, -1);
00768             ++i;
00769         }
00770         for( unsigned int ii = 0; ii < subspace.intermediateNodes.size(); ++ii ){
00771             PubSubSubspaceResponsible::IntermediateNode& iNode =  subspace.intermediateNodes[ii];
00772             backupCall->setIntermediates(ii, iNode.node);
00773             for( childIt = iNode.children.begin(); childIt != iNode.children.end(); ++childIt ){
00774                 backupCall->setChildren(i, *childIt);
00775                 backupCall->setChildrenPos(i, ii);
00776                 ++i;
00777             }
00778         }
00779 
00780         backupCall->setBitLength( PUBSUB_BACKUPCALL_L( backupCall ));
00781         RECORD_STATS(
00782                 ++numPubSubSignalingMessages;
00783                 pubSubSignalingMessagesSize+= backupCall->getByteLength()
00784                 );
00785         sendUdpRpcCall( helpResp->getNode(), backupCall );
00786 
00787     } else if( helpResp->getHelpType() == PUBSUB_INTERMEDIATE ){
00788         PubSubIntermediateCall* intermediateCall = new PubSubIntermediateCall("Become my intermediate node!");
00789         intermediateCall->setSubspaceId( helpResp->getSubspaceId() );
00790         intermediateCall->setBitLength( PUBSUB_INTERMEDIATECALL_L( intermediateCall ));
00791         RECORD_STATS(
00792                 ++numPubSubSignalingMessages;
00793                 pubSubSignalingMessagesSize+= intermediateCall->getByteLength()
00794                 );
00795         sendUdpRpcCall( helpResp->getNode(), intermediateCall );
00796     }
00797 }

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

Definition at line 1512 of file PubSubMMOG.cc.

Referenced by handleUDPMessage().

01513 {
01514     // find appropriate subspace
01515     PubSubSubspaceId subspaceId(backupMsg->getSubspaceId(), numSubspaces);
01516     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01517     it = backupSubspaces.find( subspaceId );
01518     if( it == backupSubspaces.end() ) {
01519         return;
01520     }
01521 
01522     if( backupMsg->getPos() >= (int) it->second.intermediateNodes.size() ){
01523         it->second.intermediateNodes.resize( backupMsg->getPos() + 1 );
01524     }
01525     it->second.intermediateNodes[ backupMsg->getPos() ].node = backupMsg->getNode();
01526 }

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

Definition at line 850 of file PubSubMMOG.cc.

Referenced by handleRpcCall().

00851 {
00852     // insert subspace into intermediate list
00853     PubSubSubspaceId subspaceId(intermediateCall->getSubspaceId(), numSubspaces);
00854     PubSubSubspaceIntermediate subspace( subspaceId );
00855     subspace.setResponsibleNode( intermediateCall->getSrcNode() );
00856     subspace.setTimestamp(0);
00857     intermediateSubspaces.insert( make_pair(subspaceId, subspace) );
00858 
00859     PubSubIntermediateResponse* iResp = new PubSubIntermediateResponse("I'll be your intermediate node");
00860     iResp->setSubspaceId( intermediateCall->getSubspaceId() );
00861     iResp->setBitLength( PUBSUB_INTERMEDIATERESPONSE_L( iResp ));
00862     RECORD_STATS(
00863             ++numPubSubSignalingMessages;
00864             pubSubSignalingMessagesSize+= iResp->getByteLength()
00865             );
00866     sendRpcResponse( intermediateCall, iResp );
00867 }

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

Definition at line 869 of file PubSubMMOG.cc.

Referenced by handleRpcResponse().

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

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

Definition at line 367 of file PubSubMMOG.cc.

Referenced by handleRpcResponse().

00368 {
00369     state = JOINING;
00370     setBootstrapedIcon();
00371     PubSubSubspaceId region( currentRegionX, currentRegionY, numSubspaces);
00372 
00373     NodeHandle respNode = joinResp->getResponsibleNode();
00374     PubSubSubspace sub(region);
00375     sub.setResponsibleNode( respNode );
00376     subscribedSubspaces.push_back( sub );
00377     if( respNode.isUnspecified() ) {
00378         PubSubResponsibleNodeCall* respCall = new PubSubResponsibleNodeCall("Request Responsible NodeHandle");
00379         respCall->setSubspacePos( Vector2D(currentRegionX, currentRegionY) );
00380         respCall->setBitLength( PUBSUB_RESPONSIBLENODECALL_L( respCall ) );
00381         RECORD_STATS(
00382                 ++numPubSubSignalingMessages;
00383                 pubSubSignalingMessagesSize+= respCall->getByteLength()
00384                 );
00385         sendUdpRpcCall( lobbyServer, respCall, NULL, 5, 5 ); // FIXME: Make it a parameter...
00386     } else {
00387         PubSubSubscriptionCall* subCall = new PubSubSubscriptionCall("JoinSubspace");
00388         subCall->setSubspaceId( region.getId() );
00389         subCall->setBitLength( PUBSUB_SUBSCRIPTIONCALL_L( subCall ));
00390         RECORD_STATS(
00391                 ++numPubSubSignalingMessages;
00392                 pubSubSignalingMessagesSize+= subCall->getByteLength()
00393                 );
00394         sendUdpRpcCall( respNode, subCall );
00395     }
00396 }

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

Definition at line 541 of file PubSubMMOG.cc.

Referenced by handleAppMessage().

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

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

Definition at line 666 of file PubSubMMOG.cc.

Referenced by handleUDPMessage().

00667 {
00668     simtime_t timestamp = moveMsg->getTimestamp();
00669 
00670     // If I'm intermediate node for this subspace, forward message to children
00671     std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it;
00672     it = intermediateSubspaces.find( PubSubSubspaceId(moveMsg->getSubspaceId(), numSubspaces) );
00673     if( it != intermediateSubspaces.end() ){
00674         // Forward only if the message has not already been forwarded
00675         if( it->second.getLastTimestamp() < moveMsg->getTimestamp() ){
00676             set<NodeHandle>::iterator childIt;
00677             for( childIt = it->second.children.begin(); childIt != it->second.children.end(); ++childIt ){
00678                 sendMessageToUDP( *childIt, (BaseOverlayMessage*) moveMsg->dup() );
00679                 RECORD_STATS(
00680                         ++numMoveListMessages;
00681                         moveListMessagesSize+= moveMsg->getByteLength()
00682                         );
00683             }
00684             it->second.setTimestamp( timestamp );
00685         }
00686     }
00687 
00688     // If I'm subscribed to the subspace, transfer a GameAPIMoveList to app
00689     std::list<PubSubSubspace>::iterator subIt;
00690     for( subIt = subscribedSubspaces.begin(); subIt != subscribedSubspaces.end(); ++subIt ){
00691         if( subIt->getId().getId() == moveMsg->getSubspaceId() ){
00692             if( subIt->getLastTimestamp() < moveMsg->getTimestamp() ){
00693                 GameAPIListMessage* moveList = new GameAPIListMessage("player position update");
00694                 moveList->setCommand( NEIGHBOR_UPDATE );
00695                 moveList->setAddNeighborArraySize( moveMsg->getPlayerArraySize() );
00696                 moveList->setNeighborPositionArraySize( moveMsg->getPositionArraySize() );
00697                 for( unsigned int i = 0; i < moveMsg->getPlayerArraySize(); ++i ){
00698                     moveList->setAddNeighbor( i, moveMsg->getPlayer(i) );
00699                     moveList->setNeighborPosition( i, moveMsg->getPosition(i) );
00700                     RECORD_STATS(
00701                         globalStatistics->addStdDev("PubSubMMOG: MoveDelay",
00702                                 SIMTIME_DBL(simTime() - timestamp + moveMsg->getPositionAge(i)) );
00703                         );
00704                 }
00705                 send( moveList, "appOut" );
00706                 RECORD_STATS(
00707                         if( timestamp < simTime() - maxMoveDelay ){
00708                             ++lostMovementLists;
00709                         } else {
00710                             ++receivedMovementLists;
00711                         }
00712                         if( subIt->getLastTimestamp() != 0) lostMovementLists += (int)(SIMTIME_DBL(timestamp - subIt->getLastTimestamp())*movementRate -1);
00713 
00714                         );
00715                 subIt->setTimestamp( timestamp );
00716             }
00717             return;
00718         }
00719     }
00720 }

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

Definition at line 635 of file PubSubMMOG.cc.

Referenced by handleUDPMessage().

00636 {
00637     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
00638     it = responsibleSubspaces.find( PubSubSubspaceId(moveMsg->getSubspaceId(), numSubspaces) );
00639     if( it == responsibleSubspaces.end() ){
00640          EV << "[PubSubMMOG::handleMoveMessage() @ " << thisNode.getAddress()
00641             << " (" << thisNode.getKey().toString(16) << ")]\n"
00642             << "  received moveMessage for unknown subspace" << moveMsg->getSubspaceId() << "\n"
00643             << endl;
00644         return;
00645     }
00646 
00647     // If message arrived in the correct timeslot, store move message until deadline
00648     // Note: This assumes, we get no messages with future timestamps. At least in
00649     // the simulation, this assumption will hold.
00650     // The allowOldMoveMessages parameter allows overriding the timeslot barriers and forward all
00651     // messages.
00652     if( allowOldMoveMessages || moveMsg->getTimestamp() >= eventDeliveryTimer->getArrivalTime() - 1.0/(2*movementRate) ){
00653         it->second.waitingMoveMessages.push_back( moveMsg );
00654         ++numEventsCorrectTimeslot;
00655     } else {
00656          EV << "[PubSubMMOG::handleMoveMessage() @ " << thisNode.getAddress()
00657             << " (" << thisNode.getKey().toString(16) << ")]\n"
00658             << "  received moveMesage with Timestamp: " << moveMsg->getTimestamp() << "\n"
00659             << "  deadline was: " << eventDeliveryTimer->getArrivalTime() - 1.0/(2*movementRate) << "\n"
00660             << endl;
00661         ++numEventsWrongTimeslot;
00662         cancelAndDelete( moveMsg );
00663     }
00664 }

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

Definition at line 432 of file PubSubMMOG.cc.

Referenced by handleUDPMessage().

00433 {
00434     std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it;
00435     it = intermediateSubspaces.find( PubSubSubspaceId(leftMsg->getSubspaceId(), numSubspaces) );
00436 
00437     if( it == intermediateSubspaces.end() ) return;
00438 
00439     it->second.removeChild( leftMsg->getNode() );
00440 }

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

Definition at line 1260 of file PubSubMMOG.cc.

Referenced by handleTimerEvent().

01261 {
01262     // our parent timed out. we have to take over the subspace...
01263     PubSubSubspaceId subspaceId(timer->getSubspaceId(), numSubspaces);
01264     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01265     it = backupSubspaces.find( subspaceId );
01266     if( it == backupSubspaces.end() ) {
01267         delete timer;
01268         return;
01269     }
01270 
01271     // increase fail count; if to high, take over subspace
01272     it->second.incHeartbeatFailCount();
01273     if( it->second.getHeartbeatFailCount() > 1 ) { // FIXME: make it a parameter
01274 
01275         // Delete Timer
01276         cancelAndDelete( timer );
01277         it->second.setHeartbeatTimer( NULL );
01278 
01279         // Take over Subspace
01280         takeOverSubspace( it->second );
01281         backupSubspaces.erase( it );
01282 
01283     } else {
01284         startTimer( timer );
01285     }
01286 }

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

Definition at line 1140 of file PubSubMMOG.cc.

Referenced by handleRpcCall().

01141 {
01142     int subspaceId = pingCall->getSubspaceId();
01143 
01144     if( pingCall->getPingType() == PUBSUB_PING_BACKUP ){
01145         // reset heartbeat timer
01146         std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01147         it = backupSubspaces.find( PubSubSubspaceId(pingCall->getSubspaceId(), numSubspaces) );
01148         if( it == backupSubspaces.end() ) {
01149             EV << "[PubSubMMOG::handlePingCall() @ " << thisNode.getAddress()
01150                << " (" << thisNode.getKey().toString(16) << ")]\n"
01151                << "  Received PingCall for unknown Subspace!\n"
01152                << endl;
01153             // FIXME: Somebody thinks we are his backup. What shall we do?
01154         } else {
01155             it->second.resetHeartbeatFailCount();
01156             startTimer( it->second.getHeartbeatTimer() );
01157         }
01158     }
01159 
01160     PubSubPingResponse* pingResp = new PubSubPingResponse("PingResponse");
01161     pingResp->setSubspaceId( subspaceId );
01162     pingResp->setBitLength( PUBSUB_PINGRESPONSE_L( pingResp ));
01163     RECORD_STATS(
01164             ++numPubSubSignalingMessages;
01165             pubSubSignalingMessagesSize+= pingResp->getByteLength()
01166             );
01167     sendRpcResponse( pingCall, pingResp );
01168 }

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

Definition at line 1322 of file PubSubMMOG.cc.

Referenced by handleRpcTimeout().

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

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

Definition at line 1170 of file PubSubMMOG.cc.

Referenced by handleRpcResponse().

01171 {
01172 }

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

Definition at line 1506 of file PubSubMMOG.cc.

Referenced by handleUDPMessage().

01507 {
01508     PubSubSubspaceId subspaceId(releaseMsg->getSubspaceId(), numSubspaces);
01509     intermediateSubspaces.erase( subspaceId );
01510 }

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

Definition at line 1484 of file PubSubMMOG.cc.

Referenced by handleUDPMessage().

01485 {
01486     PubSubSubspaceId subspaceId(replaceMsg->getSubspaceId(), numSubspaces);
01487 
01488     // There's a new responsible node for a subspace
01489     // Replace the old one in the intermediateSubspaces map...
01490     std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it;
01491     it = intermediateSubspaces.find( subspaceId );
01492     if( it != intermediateSubspaces.end() ) {
01493         it->second.setResponsibleNode( replaceMsg->getNewResponsibleNode() );
01494     }
01495 
01496     // ... and in the subsribed subspaces list
01497     std::list<PubSubSubspace>::iterator iit;
01498     for( iit = subscribedSubspaces.begin(); iit != subscribedSubspaces.end(); ++iit ){
01499         if( iit->getId() == subspaceId ) {
01500             iit->setResponsibleNode( replaceMsg->getNewResponsibleNode() );
01501             return;
01502         }
01503     }
01504 }

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

Definition at line 398 of file PubSubMMOG.cc.

Referenced by handleRpcResponse().

00399 {
00400     int subspaceId = subResp->getSubspaceId();
00401     NodeHandle respNode = subResp->getResponsibleNode();
00402 
00403     std::list<PubSubSubspace>::iterator it = subscribedSubspaces.begin();
00404     while( it != subscribedSubspaces.end() ) {
00405         if( it->getId().getId() == subspaceId) break;
00406         ++it;
00407     }
00408     if( it != subscribedSubspaces.end() ) {
00409         it->setResponsibleNode( respNode );
00410 
00411         PubSubSubscriptionCall* subCall = new PubSubSubscriptionCall("JoinSubspace");
00412         subCall->setSubspaceId( subspaceId );
00413         subCall->setBitLength( PUBSUB_SUBSCRIPTIONCALL_L( subCall ));
00414         RECORD_STATS(
00415                 ++numPubSubSignalingMessages;
00416                 pubSubSignalingMessagesSize+= subCall->getByteLength()
00417                 );
00418         sendUdpRpcCall( respNode, subCall );
00419     }
00420 }

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

Processes Remote-Procedure-Call invocation messages.


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

Returns:
true, if rpc has been handled

Reimplemented from BaseRpc.

Definition at line 103 of file PubSubMMOG.cc.

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

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.

Definition at line 119 of file PubSubMMOG.cc.

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

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.

Definition at line 199 of file PubSubMMOG.cc.

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

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

Definition at line 1528 of file PubSubMMOG.cc.

Referenced by handleUDPMessage().

01529 {
01530     // Note: this funktion may break subspace's tatalChildrenCall
01531     // You have to use fixTotalChildrenCount before using the subspace
01532     // find appropriate subspace
01533     PubSubSubspaceId subspaceId(backupMsg->getSubspaceId(), numSubspaces);
01534     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01535     it = backupSubspaces.find( subspaceId );
01536     if( it == backupSubspaces.end() ) {
01537         return;
01538     }
01539     PubSubSubspaceResponsible& subspace = it->second;
01540 
01541     deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
01542 
01543     if( !backupMsg->getOldParent().isUnspecified() ){
01544         // oldParent set -> move child
01545         if( backupMsg->getOldParent() == subspace.getResponsibleNode() ){
01546             // direct child -> cache
01547             subspace.removeChild( backupMsg->getChild() );
01548             subspace.cachedChildren.insert(make_pair( backupMsg->getChild(), false) );
01549 
01550         } else {
01551             // from I -> chache
01552             for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
01553 //                if( !iit->node.isUnspecified() && iit->node == backupMsg->getOldParent() ){
01554                     iit->children.erase( backupMsg->getChild() );
01555 //                }
01556             }
01557             subspace.cachedChildren.insert(make_pair( backupMsg->getChild(), false) );
01558         }
01559     } else if( backupMsg->getParent().isUnspecified() ){
01560         // parent not set -> new child to chache
01561         subspace.cachedChildren.insert(make_pair( backupMsg->getChild(), false) );
01562 
01563     } else if( backupMsg->getParent() == subspace.getResponsibleNode() ){
01564         // new direct child
01565         subspace.addChild( backupMsg->getChild() );
01566     } else {
01567         // move child from cache to intermediate
01568         subspace.cachedChildren.erase( backupMsg->getChild() );
01569 
01570         for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
01571             if( !iit->node.isUnspecified() && iit->node == backupMsg->getParent() ){
01572                 iit->children.insert( backupMsg->getChild() );
01573             }
01574         }
01575         // FIXME: check for errors
01576     }
01577 }

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

Definition at line 442 of file PubSubMMOG.cc.

Referenced by handleRpcCall().

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

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

Definition at line 1458 of file PubSubMMOG.cc.

Referenced by handleRpcTimeout().

01459 {
01460     // FIXME: cast oldNode to NodeHandle
01461     // our subscription call timed out. This means the responsible node is dead...
01462     // Inform Lobbyserver over failed node
01463     PubSubFailedNodeMessage* failedNode = new PubSubFailedNodeMessage("Node failed");
01464     failedNode->setFailedNode( oldNode );
01465     failedNode->setBitLength( PUBSUB_FAILEDNODE_L( failedNode ));
01466     RECORD_STATS(
01467             ++numPubSubSignalingMessages;
01468             pubSubSignalingMessagesSize+= failedNode->getByteLength()
01469             );
01470     sendMessageToUDP( lobbyServer, failedNode );
01471 
01472     // Ask for new responsible node
01473     PubSubResponsibleNodeCall* respCall = new PubSubResponsibleNodeCall("Request Responsible NodeHandle");
01474     PubSubSubspaceId subspaceId( subscriptionCall->getSubspaceId(), numSubspaces);
01475     respCall->setSubspacePos( Vector2D(subspaceId.getX(), subspaceId.getY()) );
01476     respCall->setBitLength( PUBSUB_RESPONSIBLENODECALL_L( respCall ));
01477     RECORD_STATS(
01478             ++numPubSubSignalingMessages;
01479             pubSubSignalingMessagesSize+= respCall->getByteLength()
01480             );
01481     sendUdpRpcCall( lobbyServer, respCall, NULL, 5, 5 ); // FIXME: Make it a parameter...
01482 }

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

Definition at line 351 of file PubSubMMOG.cc.

Referenced by handleRpcResponse().

00352 {
00353     if( subResp->getFailed() ) {
00354         // TODO: get new resp node...
00355     } else {
00356         if( state != READY ){
00357             state = READY;
00358             setBootstrapedIcon();
00359             CompReadyMessage* readyMsg = new CompReadyMessage("Overlay READY!");
00360             readyMsg->setReady(true);
00361             readyMsg->setComp(getThisCompType());
00362             sendDelayed( readyMsg, ceil(simTime()) - simTime(), "appOut" );
00363         }
00364     }
00365 }

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

Definition at line 519 of file PubSubMMOG.cc.

Referenced by handleRpcCall().

00520 {
00521     PubSubSubspaceId region((int) toCall->getSubspacePos().x, (int) toCall->getSubspacePos().y, numSubspaces);
00522 
00523     takeOverNewSubspace( region );
00524 
00525     PubSubTakeOverSubspaceResponse* toResp = new PubSubTakeOverSubspaceResponse("Accept subspace responsibility");
00526     toResp->setSubspacePos( toCall->getSubspacePos() );
00527     toResp->setBitLength( PUBSUB_TAKEOVERSUBSPACERESPONSE_L( toResp ));
00528     RECORD_STATS(
00529             ++numPubSubSignalingMessages;
00530             pubSubSignalingMessagesSize+= toResp->getByteLength()
00531             );
00532     sendRpcResponse( toCall, toResp );
00533 }

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

Reimplemented from BaseRpc.

Definition at line 275 of file PubSubMMOG.cc.

00276 {
00277     if( PubSubTimer* timer = dynamic_cast<PubSubTimer*>(msg) ) {
00278         switch( timer->getType() ) {
00279             case PUBSUB_HEARTBEAT:
00280                 sendHearbeatToChildren();
00281                 startTimer( timer );
00282                 break;
00283             case PUBSUB_CHILDPING:
00284                 sendPingToChildren();
00285                 startTimer( timer );
00286                 break;
00287             case PUBSUB_PARENT_TIMEOUT:
00288                 handleParentTimeout( timer );
00289                 break;
00290             case PUBSUB_EVENTDELIVERY:
00291                 publishEvents();
00292                 startTimer( timer );
00293                 break;
00294         }
00295     } else if( msg == joinTimer ) {
00296         // send a fake ready message to app to get initial position
00297         // Note: This is not consistent to the paper, where the lobby server
00298         // positions player. But it is needed for consistency with other MMOG protocols
00299         CompReadyMessage* msg = new CompReadyMessage("fake READY");
00300         msg->setReady(true);
00301         msg->setComp(getThisCompType());
00302         send( msg, "appOut");
00303         delete joinTimer;
00304         joinTimer = NULL;
00305         // send initial AOI size to the application
00306         // Note: This is not consistent to the paper.
00307         // But it is needed for this nodes movement generation within the application layer.
00308         GameAPIResizeAOIMessage* gameMsg = new GameAPIResizeAOIMessage("RESIZE_AOI");
00309         gameMsg->setCommand(RESIZE_AOI);
00310         gameMsg->setAOIsize(AOIWidth);
00311         send( gameMsg, "appOut");
00312     }
00313 }

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

Processes messages from underlay.

Parameters:
msg Message from UDP

Reimplemented from BaseOverlay.

Definition at line 244 of file PubSubMMOG.cc.

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

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

Definition at line 1579 of file PubSubMMOG.cc.

Referenced by handleUDPMessage().

01580 {
01581     // Note: this funktion may break subspace's tatalChildrenCall
01582     // You have to use fixTotalChildrenCount before using the subspace
01583     // find appropriate subspace
01584     PubSubSubspaceId subspaceId(backupMsg->getSubspaceId(), numSubspaces);
01585     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01586     it = backupSubspaces.find( subspaceId );
01587     if( it == backupSubspaces.end() ) {
01588         return;
01589     }
01590     PubSubSubspaceResponsible& subspace = it->second;
01591 
01592     deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
01593     set<NodeHandle>::iterator childIt;
01594 
01595     if( !subspace.removeChild(backupMsg->getChild()) && !subspace.cachedChildren.erase( backupMsg->getChild()) ){
01596         for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
01597             iit->children.erase( backupMsg->getChild() );
01598         }
01599     }
01600     if( !backupMsg->getIntermediate().isUnspecified() ){
01601         // remove intermediate
01602         for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
01603             if( !iit->node.isUnspecified() && iit->node == backupMsg->getIntermediate() ){
01604                 for( childIt = iit->children.begin(); childIt != iit->children.end(); ++childIt ){
01605                     // FIXME: note really stable. let the resp node inform us about child moves
01606                     // remove children of last intermediate
01607                     if( subspace.getNumChildren() + subspace.getNumIntermediates() < maxChildren ){
01608                         // we have room for the child
01609                         subspace.children.insert( *childIt );
01610                     } else {
01611                         // Node has to go to some intermediate
01612                         // cache it
01613                         subspace.cachedChildren.insert( make_pair(*childIt, true) );
01614                     }
01615                 }
01616                 subspace.intermediateNodes.erase( iit );
01617                 break;
01618             }
01619         }
01620     }
01621 }

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

Definition at line 422 of file PubSubMMOG.cc.

Referenced by handleUDPMessage().

00423 {
00424     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
00425     it = responsibleSubspaces.find( PubSubSubspaceId(unsMsg->getSubspaceId(), numSubspaces) );
00426 
00427     if( it != responsibleSubspaces.end() ) {
00428         unsubscribeChild( unsMsg->getSrc(), it->second );
00429     }
00430 }

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.

Definition at line 36 of file PubSubMMOG.cc.

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     // TODO: use BootstrapList instead (but this currently preferes
00045     //       nodes from the same partition)
00046     lobbyServer = globalNodeList->getBootstrapNode();
00047 
00048     joinTimer = new cMessage("join timer");
00049     simtime_t joinTime = ceil(simTime() + (simtime_t) par("joinDelay"));
00050     scheduleAt( joinTime, joinTimer );
00051 
00052     movementRate = par("movementRate");
00053     eventDeliveryTimer = new PubSubTimer("event delivery timer");
00054     eventDeliveryTimer->setType( PUBSUB_EVENTDELIVERY );
00055     scheduleAt( joinTime + 1.0/(2*movementRate), eventDeliveryTimer );
00056 
00057     numSubspaces = par("numSubspaces");
00058     subspaceSize = (int) ( (unsigned int) par("areaDimension") / numSubspaces);
00059     thisNode.setKey( OverlayKey::random() );
00060 
00061     maxChildren = par("maxChildren");
00062     PubSubSubspaceResponsible::maxChildren = maxChildren;
00063 
00064     AOIWidth = par("AOIWidth");
00065     maxMoveDelay = par("maxMoveDelay");
00066 
00067     parentTimeout = par("parentTimeout");
00068     heartbeatTimer = new PubSubTimer("HeartbeatTimer");
00069     heartbeatTimer->setType( PUBSUB_HEARTBEAT );
00070     startTimer( heartbeatTimer );
00071     childPingTimer = new PubSubTimer("ChildPingTimer");
00072     childPingTimer->setType( PUBSUB_CHILDPING );
00073     startTimer( childPingTimer );
00074 
00075     allowOldMoveMessages  = par("allowOldMoveMessages");
00076 
00077     numEventsWrongTimeslot = numEventsCorrectTimeslot = 0;
00078     numPubSubSignalingMessages = 0;
00079     pubSubSignalingMessagesSize = 0;
00080     numMoveMessages = 0;
00081     moveMessagesSize = 0;
00082     numMoveListMessages = 0;
00083     moveListMessagesSize = 0;
00084     respMoveListMessagesSize = 0;
00085     lostMovementLists = 0;
00086     receivedMovementLists = 0;
00087     WATCH( numPubSubSignalingMessages );
00088     WATCH( pubSubSignalingMessagesSize );
00089     WATCH( numMoveMessages );
00090     WATCH( moveMessagesSize );
00091     WATCH( numMoveListMessages );
00092     WATCH( moveListMessagesSize );
00093     WATCH( numEventsWrongTimeslot );
00094     WATCH( numEventsCorrectTimeslot );
00095     WATCH( lostMovementLists );
00096     WATCH( receivedMovementLists );
00097     WATCH_LIST( subscribedSubspaces );
00098     WATCH_MAP( responsibleSubspaces );
00099     WATCH_MAP( backupSubspaces );
00100     WATCH_MAP( intermediateSubspaces );
00101 }

void PubSubMMOG::publishEvents (  )  [protected]

Definition at line 1851 of file PubSubMMOG.cc.

Referenced by handleTimerEvent().

01852 {
01853     // FOr all (responsible) subspaces
01854     int numRespSubspaces = responsibleSubspaces.size();
01855     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01856     for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it ){
01857         PubSubSubspaceResponsible& subspace = it->second;
01858 
01859         // Prepare a movement list message aggregating all stored move messages
01860         PubSubMoveListMessage* moveList = new PubSubMoveListMessage("Movement list");
01861         moveList->setTimestamp( simTime() );
01862         moveList->setSubspaceId( subspace.getId().getId() );
01863         moveList->setPlayerArraySize( subspace.waitingMoveMessages.size() );
01864         moveList->setPositionArraySize( subspace.waitingMoveMessages.size() );
01865         moveList->setPositionAgeArraySize( subspace.waitingMoveMessages.size() );
01866 
01867         std::deque<PubSubMoveMessage*>::iterator msgIt;
01868         int pos = 0;
01869         for( msgIt = subspace.waitingMoveMessages.begin(); msgIt != subspace.waitingMoveMessages.end(); ++msgIt ){
01870             moveList->setPlayer( pos, (*msgIt)->getPlayer() );
01871             moveList->setPosition( pos, (*msgIt)->getPosition() );
01872             moveList->setPositionAge( pos, simTime() - (*msgIt)->getCreationTime() );
01873             pos++;
01874             cancelAndDelete( *msgIt );
01875         }
01876         subspace.waitingMoveMessages.clear();
01877 
01878         moveList->setBitLength( PUBSUB_MOVELIST_L( moveList ));
01879         // Send message to all direct children...
01880         for( set<NodeHandle>::iterator childIt = subspace.children.begin();
01881                 childIt != subspace.children.end(); ++childIt )
01882         {
01883             RECORD_STATS(
01884                     ++numMoveListMessages;
01885                     moveListMessagesSize+= moveList->getByteLength();
01886                     respMoveListMessagesSize+= (int)((double) moveList->getByteLength() / numRespSubspaces)
01887                     );
01888             sendMessageToUDP( *childIt, (BaseOverlayMessage*) moveList->dup() );
01889         }
01890 
01891         //... all cached children (if messages are not too big) ...
01892         if( moveList->getByteLength() < 1024 ){ // FIXME: magic number. make it a parameter, or dependant on the available bandwidth
01893             for( map<NodeHandle, bool>::iterator childIt = subspace.cachedChildren.begin();
01894                     childIt != subspace.cachedChildren.end(); ++childIt )
01895             {
01896                 RECORD_STATS(
01897                         ++numMoveListMessages;
01898                         moveListMessagesSize+= moveList->getByteLength();
01899                         respMoveListMessagesSize+= (int)((double) moveList->getByteLength() / numRespSubspaces)
01900                         );
01901                 sendMessageToUDP( childIt->first, (BaseOverlayMessage*) moveList->dup() );
01902                 // ... but don't send msgs to too many cached children, as this would exhaust our bandwidth
01903             }
01904         }
01905 
01906         // ... all direct intermediates and intermediates with broken parent
01907         deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
01908         for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit )
01909         {
01910             int intermediatePos = iit - subspace.intermediateNodes.begin();
01911             if( intermediatePos >= maxChildren &&
01912                   !subspace.intermediateNodes[intermediatePos/maxChildren -1].node.isUnspecified() ) continue;
01913             if( !iit->node.isUnspecified() ) {
01914                 RECORD_STATS(
01915                         ++numMoveListMessages;
01916                         moveListMessagesSize+= moveList->getByteLength();
01917                         respMoveListMessagesSize+= (int)((double) moveList->getByteLength() / numRespSubspaces)
01918                 );
01919                 sendMessageToUDP( iit->node, (BaseOverlayMessage*) moveList->dup() );
01920             }
01921         }
01922 
01923         delete moveList;
01924     }
01925 }

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

callback-method for events at the NotificationBoard

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

Reimplemented from BaseOverlay.

Definition at line 535 of file PubSubMMOG.cc.

00536 {
00537     if(category == NF_OVERLAY_NODE_GRACEFUL_LEAVE && state == READY) {
00538     }
00539 }

void PubSubMMOG::sendHearbeatToChildren (  )  [protected]

Definition at line 1227 of file PubSubMMOG.cc.

Referenced by handleTimerEvent().

01228 {
01229     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01230     for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it) {
01231         PubSubPingCall* bHeartbeat = new PubSubPingCall("Heartbeat Backup");
01232         bHeartbeat->setPingType( PUBSUB_PING_BACKUP );
01233         bHeartbeat->setSubspaceId( it->second.getId().getId() );
01234         bHeartbeat->setBitLength( PUBSUB_PINGCALL_L( bHeartbeat ));
01235 
01236         PubSubPingCall* iHeartbeat = new PubSubPingCall("Heartbeat Intermediate");
01237         iHeartbeat->setPingType( PUBSUB_PING_INTERMEDIATE );
01238         iHeartbeat->setSubspaceId( it->second.getId().getId() );
01239         iHeartbeat->setBitLength( PUBSUB_PINGCALL_L( iHeartbeat ));
01240 
01241         sendMessageToChildren( it->second, iHeartbeat, bHeartbeat, NULL);
01242         delete bHeartbeat;
01243         delete iHeartbeat;
01244     }
01245 }

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

Definition at line 1749 of file PubSubMMOG.cc.

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

01753 {
01754     BaseCallMessage* intermediateCall = dynamic_cast<BaseCallMessage*>(toIntermediates);
01755     BaseCallMessage* backupCall = dynamic_cast<BaseCallMessage*>(toBackup);
01756     BaseCallMessage* playerCall = dynamic_cast<BaseCallMessage*>(toPlayers);
01757 
01758     std::set<NodeHandle>::iterator childIt;
01759 
01760     if( toPlayers ) {
01761         // Inform all children ...
01762         for( childIt = subspace.children.begin(); childIt != subspace.children.end(); ++childIt ) {
01763             if( playerCall ){
01764                 RECORD_STATS(
01765                         ++numPubSubSignalingMessages;
01766                         pubSubSignalingMessagesSize+= playerCall->getByteLength()
01767                         );
01768                 sendUdpRpcCall( *childIt, static_cast<BaseCallMessage*>(playerCall->dup()) );
01769             } else {
01770                 RECORD_STATS(
01771                         ++numPubSubSignalingMessages;
01772                         pubSubSignalingMessagesSize+= toPlayers->getByteLength()
01773                         );
01774                 sendMessageToUDP( *childIt, static_cast<BaseOverlayMessage*>(toPlayers->dup()) );
01775             }
01776         }
01777         // ... and all cached children ...
01778         std::map<NodeHandle, bool>::iterator cacheChildIt;
01779         for( cacheChildIt = subspace.cachedChildren.begin(); cacheChildIt != subspace.cachedChildren.end(); ++cacheChildIt ) {
01780             if( playerCall ){
01781                 RECORD_STATS(
01782                         ++numPubSubSignalingMessages;
01783                         pubSubSignalingMessagesSize+= playerCall->getByteLength()
01784                         );
01785                 sendUdpRpcCall( cacheChildIt->first, static_cast<BaseCallMessage*>(playerCall->dup()) );
01786             } else {
01787                 RECORD_STATS(
01788                         ++numPubSubSignalingMessages;
01789                         pubSubSignalingMessagesSize+= toPlayers->getByteLength()
01790                         );
01791                 sendMessageToUDP( cacheChildIt->first, static_cast<BaseOverlayMessage*>(toPlayers->dup()) );
01792             }
01793         }
01794     }
01795     deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit;
01796     // ... all intermediate nodes ...
01797     for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){
01798         if( toIntermediates && !iit->node.isUnspecified() ){
01799             if( intermediateCall ){
01800                 RECORD_STATS(
01801                         ++numPubSubSignalingMessages;
01802                         pubSubSignalingMessagesSize+= intermediateCall->getByteLength()
01803                         );
01804                 sendUdpRpcCall( iit->node, static_cast<BaseCallMessage*>(intermediateCall->dup()) );
01805             } else {
01806                 RECORD_STATS(
01807                         ++numPubSubSignalingMessages;
01808                         pubSubSignalingMessagesSize+= toIntermediates->getByteLength()
01809                         );
01810                 sendMessageToUDP( iit->node, static_cast<BaseOverlayMessage*>(toIntermediates->dup()) );
01811             }
01812         }
01813         if( toPlayers ) {
01814             // .. and all intermediate node's children ...
01815             for( childIt = iit->children.begin(); childIt != iit->children.end(); ++childIt ){
01816                 if( playerCall ){
01817                     RECORD_STATS(
01818                             ++numPubSubSignalingMessages;
01819                             pubSubSignalingMessagesSize+= playerCall->getByteLength()
01820                             );
01821                     sendUdpRpcCall( *childIt, static_cast<BaseCallMessage*>(playerCall->dup()) );
01822                 } else {
01823                     RECORD_STATS(
01824                             ++numPubSubSignalingMessages;
01825                             pubSubSignalingMessagesSize+= toPlayers->getByteLength()
01826                             );
01827                     sendMessageToUDP( *childIt, static_cast<BaseOverlayMessage*>(toPlayers->dup()) );
01828                 }
01829             }
01830         }
01831     }
01832     // ... and the backup node
01833     if( toBackup && !subspace.getBackupNode().isUnspecified() ) {
01834         if( backupCall ){
01835             RECORD_STATS(
01836                     ++numPubSubSignalingMessages;
01837                     pubSubSignalingMessagesSize+= backupCall->getByteLength()
01838                     );
01839             sendUdpRpcCall( subspace.getBackupNode(), static_cast<BaseCallMessage*>(backupCall->dup()) );
01840         } else {
01841             RECORD_STATS(
01842                     ++numPubSubSignalingMessages;
01843                     pubSubSignalingMessagesSize+= toBackup->getByteLength()
01844                     );
01845             sendMessageToUDP( subspace.getBackupNode(), static_cast<BaseOverlayMessage*>(toBackup->dup()) );
01846         }
01847     }
01848 }

void PubSubMMOG::sendPingToChildren (  )  [protected]

Definition at line 1247 of file PubSubMMOG.cc.

Referenced by handleTimerEvent().

01248 {
01249     std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it;
01250     for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it) {
01251         PubSubPingCall* heartbeat = new PubSubPingCall("Ping");
01252         heartbeat->setPingType( PUBSUB_PING_CHILD );
01253         heartbeat->setSubspaceId( it->second.getId().getId() );
01254         heartbeat->setBitLength( PUBSUB_PINGCALL_L( heartbeat ));
01255         sendMessageToChildren( it->second, NULL, NULL, heartbeat );
01256         delete heartbeat;
01257     }
01258 }

void PubSubMMOG::setBootstrapedIcon (  )  [protected]

Definition at line 1927 of file PubSubMMOG.cc.

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

01928 {
01929     if(ev.isGUI()) {
01930         if(state == READY) {
01931             getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "green");
01932             getDisplayString().setTagArg("i", 1, "green");
01933         }
01934         else if(state == JOINING) {
01935             getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "yellow");
01936             getDisplayString().setTagArg("i", 1, "yellow");
01937         }
01938         else {
01939             getParentModule()->getParentModule()->getDisplayString().setTagArg("i2", 1, "red");
01940             getDisplayString().setTagArg("i", 1, "red");
01941         }
01942     }
01943 }

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

Definition at line 1945 of file PubSubMMOG.cc.

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

01946 {
01947     if( !timer ) {
01948         EV << "[PubSubMMOG::startTimer() @ " << thisNode.getAddress()
01949            << " (" << thisNode.getKey().toString(16) << ")]\n"
01950            << "    WARNING! Trying to start NULL timer @ " << thisNode << "\n"
01951            << endl;
01952         return;
01953     }
01954 
01955     if( timer->isScheduled() ) {
01956         cancelEvent( timer );
01957     }
01958 
01959     simtime_t duration = 0;
01960     switch( timer->getType() ) {
01961         case PUBSUB_HEARTBEAT:
01962             duration = parentTimeout/2;
01963             break;
01964         case PUBSUB_CHILDPING:
01965             duration = parentTimeout*10; // FIXME: make it a parameter
01966             break;
01967         case PUBSUB_PARENT_TIMEOUT:
01968             duration = parentTimeout;
01969             break;
01970         case PUBSUB_EVENTDELIVERY:
01971             duration = 1.0/movementRate;
01972             break;
01973     }
01974     scheduleAt(simTime() + duration, timer );
01975 }

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

Definition at line 1174 of file PubSubMMOG.cc.

Referenced by handleTakeOver().

01175 {
01176     // create a new subspace
01177     PubSubSubspaceResponsible subspace( subspaceId );
01178     takeOverSubspace( subspace, true );
01179 }

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

Definition at line 1181 of file PubSubMMOG.cc.

Referenced by handleParentTimeout(), and takeOverNewSubspace().

01182 {
01183     const PubSubSubspaceId& subspaceId = subspace.getId();
01184     int intId = subspaceId.getId();
01185 
01186     subspace.fixTotalChildrenCount();
01187 
01188     NodeHandle oldNode = subspace.getResponsibleNode();
01189 
01190     // insert subspace into responsible list
01191     subspace.setResponsibleNode( thisNode );
01192     responsibleSubspaces.insert( make_pair(subspaceId, subspace) );
01193 
01194     // request backup
01195     PubSubHelpCall* helpCall = new PubSubHelpCall("I need a backup node");
01196     helpCall->setHelpType( PUBSUB_BACKUP );
01197     helpCall->setSubspaceId( intId );
01198     helpCall->setBitLength( PUBSUB_HELPCALL_L( helpCall ));
01199     RECORD_STATS(
01200             ++numPubSubSignalingMessages;
01201             pubSubSignalingMessagesSize+= helpCall->getByteLength()
01202             );
01203     sendUdpRpcCall( lobbyServer, helpCall );
01204 
01205     if( !isNew ) {
01206         PubSubReplacementMessage* repMsg = new PubSubReplacementMessage("I replaced the responsible node");
01207         repMsg->setSubspaceId( intId );
01208         repMsg->setNewResponsibleNode( thisNode );
01209         repMsg->setBitLength( PUBSUB_REPLACEMENT_L( repMsg ));
01210 
01211         // Inform children and lobbyserver about takeover
01212         sendMessageToChildren( subspace, repMsg, NULL, repMsg );
01213         sendMessageToUDP( lobbyServer, repMsg );
01214 
01215         // inform lobby server over failed node
01216         PubSubFailedNodeMessage* failedNode = new PubSubFailedNodeMessage("Node failed");
01217         failedNode->setFailedNode( oldNode );
01218         failedNode->setBitLength( PUBSUB_FAILEDNODE_L( failedNode ));
01219         RECORD_STATS(
01220                 ++numPubSubSignalingMessages;
01221                 pubSubSignalingMessagesSize+= failedNode->getByteLength()
01222                 );
01223         sendMessageToUDP( lobbyServer, failedNode );
01224    }
01225 }

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

Definition at line 1623 of file PubSubMMOG.cc.

Referenced by handlePingCallTimeout(), and handleUnsubscriptionMessage().

01624 {
01625     PubSubBackupUnsubscribeMessage* backupMsg = new PubSubBackupUnsubscribeMessage("Backup: node left subspace");
01626     backupMsg->setChild( node );
01627     backupMsg->setSubspaceId( subspace.getId().getId() );
01628     PubSubSubspaceResponsible::IntermediateNode* iNode = subspace.removeAnyChild( node );
01629     if( iNode && !iNode->node.isUnspecified() ) {
01630         // Node is handled by an intermediate node, inform him
01631         PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Node left Subspace");
01632         goneMsg->setNode( node );
01633         goneMsg->setSubspaceId( subspace.getId().getId() );
01634         goneMsg->setBitLength( PUBSUB_NODELEFT_L( goneMsg ));
01635         RECORD_STATS(
01636                 ++numPubSubSignalingMessages;
01637                 pubSubSignalingMessagesSize+= goneMsg->getByteLength()
01638                 );
01639         sendMessageToUDP( iNode->node, goneMsg );
01640     }
01641     if ( subspace.getTotalChildrenCount() < ( maxChildren - 1) * subspace.getNumIntermediates()){// FIXME: parameter when to start cleanup?
01642         // Too many "free" slots, remove one intermediate node
01643         PubSubSubspaceResponsible::IntermediateNode& liNode = subspace.intermediateNodes.back();
01644         if( !liNode.node.isUnspecified() ){
01645             // Inform node + lobby about release from intermediate node status
01646             PubSubReleaseIntermediateMessage* releaseMsg = new PubSubReleaseIntermediateMessage("I don't need you anymore as intermediate");
01647             releaseMsg->setSubspaceId( subspace.getId().getId() );
01648             releaseMsg->setBitLength( PUBSUB_RELEASEINTERMEDIATE_L( releaseMsg ));
01649             RECORD_STATS(
01650                     ++numPubSubSignalingMessages;
01651                     pubSubSignalingMessagesSize+= releaseMsg->getByteLength()
01652                     );
01653             sendMessageToUDP( liNode.node, releaseMsg );
01654 
01655             PubSubHelpReleaseMessage* helpRMsg = new PubSubHelpReleaseMessage("node is not my intermediate anymore");
01656             helpRMsg->setSubspaceId( subspace.getId().getId() );
01657             helpRMsg->setNode( liNode.node );
01658             helpRMsg->setBitLength( PUBSUB_HELPRELEASE_L( helpRMsg ));
01659             RECORD_STATS(
01660                     ++numPubSubSignalingMessages;
01661                     pubSubSignalingMessagesSize+= helpRMsg->getByteLength()
01662                     );
01663             sendMessageToUDP( lobbyServer, helpRMsg );
01664 
01665             // inform parent of intermediate node
01666             int parentPos = (subspace.intermediateNodes.size()-1)/maxChildren -1;
01667             if( parentPos >= 0 ){
01668                 PubSubSubspaceResponsible::IntermediateNode& parent = subspace.intermediateNodes[parentPos];
01669                 if( !parent.node.isUnspecified() ){
01670                     PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Intermediate left Subspace");
01671                     goneMsg->setNode( liNode.node );
01672                     goneMsg->setSubspaceId( subspace.getId().getId() );
01673                     goneMsg->setBitLength( PUBSUB_NODELEFT_L( goneMsg ));
01674                     RECORD_STATS(
01675                             ++numPubSubSignalingMessages;
01676                             pubSubSignalingMessagesSize+= goneMsg->getByteLength()
01677                             );
01678                     sendMessageToUDP( parent.node, goneMsg );
01679                 }
01680             }
01681         }
01682 
01683         bool fixNeeded = false;
01684         set<NodeHandle>::iterator childIt;
01685         for( childIt = liNode.children.begin(); childIt != liNode.children.end(); ++childIt ){
01686             // remove children of last intermediate
01687             if( subspace.getNumChildren() + subspace.getNumIntermediates() < maxChildren ){
01688                 // we have room for the child
01689                 if( !subspace.children.insert( *childIt ).second ) fixNeeded = true;
01690 
01691                 //FIXME: send backup new->toMe
01692             } else {
01693                 // Node has to go to some intermediate
01694                 // find intermediate with free capacities
01695                 PubSubSubspaceResponsible::IntermediateNode* newINode;
01696                 newINode = subspace.getNextFreeIntermediate();
01697 
01698                 if( newINode  && newINode->node != liNode.node ){
01699                     // cache it
01700                     if( !subspace.cachedChildren.insert( make_pair(*childIt, true) ).second ) fixNeeded = true;
01701                     //FIXME: send backup new->toCache
01702 
01703                     ++(newINode->waitingChildren);
01704 
01705                     // let him adopt the child
01706                     PubSubAdoptChildCall* adoptCall = new PubSubAdoptChildCall("Adopt Node");
01707                     adoptCall->setSubspaceId( subspace.getId().getId() );
01708                     adoptCall->setChild( *childIt );
01709                     adoptCall->setBitLength( PUBSUB_ADOPTCHILDCALL_L( adoptCall ));
01710                     RECORD_STATS(
01711                             ++numPubSubSignalingMessages;
01712                             pubSubSignalingMessagesSize+= adoptCall->getByteLength()
01713                             );
01714                     sendUdpRpcCall( newINode->node, adoptCall );
01715                 } else {
01716                     // no intermediate found
01717                     // just move child to cache and wait for a new one
01718                     if( !subspace.cachedChildren.insert( make_pair(*childIt, false) ).second ) fixNeeded = true;
01719                 }
01720             }
01721         }
01722         // delete node from subspace's intermediate node list
01723         subspace.intermediateNodes.pop_back();
01724         // inform backup about deleted intermediate
01725         backupMsg->setIntermediate( liNode.node );
01726 
01727         if( fixNeeded ) subspace.fixTotalChildrenCount();
01728     }
01729 
01730 // FIXME: just for testing
01731 int iii = subspace.getTotalChildrenCount();
01732 subspace.fixTotalChildrenCount();
01733 if( iii != subspace.getTotalChildrenCount() ){
01734     opp_error("Huh?");
01735 }
01736 
01737     if( !subspace.getBackupNode().isUnspecified() ){
01738         backupMsg->setBitLength( PUBSUB_BACKUPUNSUBSCRIBE_L( backupMsg ));
01739         RECORD_STATS(
01740                 ++numPubSubSignalingMessages;
01741                 pubSubSignalingMessagesSize+= backupMsg->getByteLength()
01742                 );
01743         sendMessageToUDP( subspace.getBackupNode(), backupMsg );
01744     } else {
01745         delete backupMsg;
01746     }
01747 }


Member Data Documentation

Definition at line 111 of file PubSubMMOG.h.

Referenced by handleMoveMessage(), and initializeOverlay().

int PubSubMMOG::AOIWidth [protected]

Definition at line 105 of file PubSubMMOG.h.

Referenced by handleMove(), handleTimerEvent(), and initializeOverlay().

PubSubTimer* PubSubMMOG::childPingTimer [protected]

Definition at line 117 of file PubSubMMOG.h.

Referenced by initializeOverlay().

unsigned int PubSubMMOG::currentRegionX [protected]

Definition at line 113 of file PubSubMMOG.h.

Referenced by handleAppMessage(), handleJoinResponse(), and handleMove().

unsigned int PubSubMMOG::currentRegionY [protected]

Definition at line 113 of file PubSubMMOG.h.

Referenced by handleAppMessage(), handleJoinResponse(), and handleMove().

PubSubTimer* PubSubMMOG::eventDeliveryTimer [protected]

Definition at line 118 of file PubSubMMOG.h.

Referenced by handleMoveMessage(), and initializeOverlay().

PubSubTimer* PubSubMMOG::heartbeatTimer [protected]

Definition at line 116 of file PubSubMMOG.h.

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

cMessage* PubSubMMOG::joinTimer [protected]

Definition at line 119 of file PubSubMMOG.h.

Referenced by handleTimerEvent(), and initializeOverlay().

Definition at line 132 of file PubSubMMOG.h.

Referenced by finishOverlay(), handleMoveListMessage(), and initializeOverlay().

int PubSubMMOG::maxChildren [protected]
int PubSubMMOG::maxMoveDelay [protected]

Definition at line 115 of file PubSubMMOG.h.

Referenced by handleMoveListMessage(), and initializeOverlay().

int PubSubMMOG::movementRate [protected]

Definition at line 128 of file PubSubMMOG.h.

Referenced by finishOverlay(), handleMove(), and initializeOverlay().

Definition at line 124 of file PubSubMMOG.h.

Referenced by finishOverlay(), handleMoveMessage(), and initializeOverlay().

Definition at line 123 of file PubSubMMOG.h.

Referenced by finishOverlay(), handleMoveMessage(), and initializeOverlay().

int PubSubMMOG::numMoveMessages [protected]

Definition at line 127 of file PubSubMMOG.h.

Referenced by finishOverlay(), handleMove(), and initializeOverlay().

int PubSubMMOG::numSubspaces [protected]
int PubSubMMOG::parentTimeout [protected]

Definition at line 108 of file PubSubMMOG.h.

Referenced by handleBackupCall(), initializeOverlay(), and startTimer().

Definition at line 133 of file PubSubMMOG.h.

Referenced by finishOverlay(), handleMoveListMessage(), and initializeOverlay().

Definition at line 131 of file PubSubMMOG.h.

Referenced by finishOverlay(), initializeOverlay(), and publishEvents().

int PubSubMMOG::subspaceSize [protected]

Definition at line 104 of file PubSubMMOG.h.

Referenced by handleAppMessage(), handleMove(), and initializeOverlay().


The documentation for this class was generated from the following files:
Generated on Wed May 26 16:21:18 2010 for OverSim by  doxygen 1.6.3