#include <PubSubMMOG.h>
Public Member Functions | |
virtual | ~PubSubMMOG () |
virtual void | initializeOverlay (int stage) |
Initializes derived-class-attributes. | |
virtual void | finishOverlay () |
collects statistical data in derived class | |
virtual void | handleUDPMessage (BaseOverlayMessage *msg) |
Processes messages from underlay. | |
virtual void | handleTimerEvent (cMessage *msg) |
Processes "timer" self-messages. | |
virtual void | handleAppMessage (cMessage *msg) |
Processes non-commonAPI messages. | |
virtual void | receiveChangeNotification (int category, cPolymorphic *details) |
callback-method for events at the NotificationBoard | |
virtual bool | handleRpc (BaseCallMessage *msg) |
Processes Remote-Procedure-Call invokation messages. | |
virtual void | handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt) |
This method is called if an RPC response has been received. | |
virtual void | handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &destKey) |
This method is called if an RPC timeout has been reached. | |
Protected Member Functions | |
void | setBootstrapedIcon () |
void | handleMove (GameAPIPositionMessage *posMsg) |
void | handleMoveMessage (PubSubMoveMessage *moveMsg) |
void | handleMoveListMessage (PubSubMoveListMessage *moveMsg) |
void | handleJoinResponse (PubSubJoinResponse *joinResp) |
void | handleSubscriptionCall (PubSubSubscriptionCall *subCall) |
void | handleSubscriptionResponse (PubSubSubscriptionResponse *subResp) |
void | handleResponsibleNodeResponse (PubSubResponsibleNodeResponse *subResp) |
void | handleTakeOver (PubSubTakeOverSubspaceCall *toCall) |
void | handleHelpResponse (PubSubHelpResponse *helpResp) |
void | handleBackupCall (PubSubBackupCall *backupCall) |
void | handleBackupResponse (PubSubBackupResponse *backupResp) |
void | handleIntermediateCall (PubSubIntermediateCall *intermediateCall) |
void | handleIntermediateResponse (PubSubIntermediateResponse *intermediateResp) |
void | handleAdoptChildCall (PubSubAdoptChildCall *adoptCall) |
void | handleAdoptChildResponse (PubSubAdoptChildResponse *adoptResp) |
void | handlePingCall (PubSubPingCall *hearbeatCall) |
void | handlePingResponse (PubSubPingResponse *pingResp) |
void | takeOverNewSubspace (PubSubSubspaceId subspaceId) |
void | takeOverSubspace (PubSubSubspaceResponsible &subspaceId, bool isNew) |
void | sendHearbeatToChildren () |
void | sendPingToChildren () |
void | handleParentTimeout (PubSubTimer *timer) |
void | handleBackupCallTimeout (PubSubBackupCall *backupCall, const TransportAddress &oldNode) |
void | handlePingCallTimeout (PubSubPingCall *pingCall, const TransportAddress &oldNode) |
void | handleSubscriptionCallTimeout (PubSubSubscriptionCall *subscriptionCall, const TransportAddress &oldNode) |
void | handleUnsubscriptionMessage (PubSubUnsubscriptionMessage *unsMsg) |
void | handleNodeLeftMessage (PubSubNodeLeftMessage *leftMsg) |
void | handleReplacementMessage (PubSubReplacementMessage *replaceMsg) |
void | handleReleaseIntermediate (PubSubReleaseIntermediateMessage *releaseMsg) |
void | handleIntermediateBackup (PubSubBackupIntermediateMessage *backupMsg) |
void | handleSubscriptionBackup (PubSubBackupSubscriptionMessage *backupMsg) |
void | handleUnsubscribeBackup (PubSubBackupUnsubscribeMessage *backupMsg) |
void | unsubscribeChild (const NodeHandle &node, PubSubSubspaceResponsible &subspace) |
void | sendMessageToChildren (PubSubSubspaceResponsible &subspace, BaseOverlayMessage *toIntermediates, BaseOverlayMessage *toBackup, BaseOverlayMessage *toPlayers) |
void | publishEvents () |
void | startTimer (PubSubTimer *timer) |
Protected Attributes | |
std::list< PubSubSubspace > | subscribedSubspaces |
std::map< PubSubSubspaceId, PubSubSubspaceResponsible > | responsibleSubspaces |
std::map< PubSubSubspaceId, PubSubSubspaceResponsible > | backupSubspaces |
std::map< PubSubSubspaceId, PubSubSubspaceIntermediate > | intermediateSubspaces |
int | subspaceSize |
int | AOIWidth |
int | numSubspaces |
int | parentTimeout |
int | maxChildren |
unsigned int | currentRegionX |
unsigned int | currentRegionY |
int | movementRate |
int | maxMoveDelay |
PubSubTimer * | heartbeatTimer |
PubSubTimer * | childPingTimer |
PubSubTimer * | eventDeliveryTimer |
cMessage * | joinTimer |
TransportAddress | lobbyServer |
int | numEventsWrongTimeslot |
int | numEventsCorrectTimeslot |
int | numPubSubSignalingMessages |
int | pubSubSignalingMessagesSize |
int | numMoveMessages |
int | moveMessagesSize |
int | numMoveListMessages |
int | moveListMessagesSize |
int | respMoveListMessagesSize |
int | lostMovementLists |
int | receivedMovementLists |
PubSubMMOG::~PubSubMMOG | ( | ) | [virtual] |
01971 { 01972 // Delete all waiting move messages 01973 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01974 for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it) { 01975 deque<PubSubMoveMessage*>::iterator msgIt; 01976 for( msgIt = it->second.waitingMoveMessages.begin(); msgIt != it->second.waitingMoveMessages.end(); ++msgIt ){ 01977 cancelAndDelete( *msgIt ); 01978 } 01979 it->second.waitingMoveMessages.clear(); 01980 } 01981 01982 cancelAndDelete(heartbeatTimer); 01983 }
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.
stage | the init stage |
Reimplemented from BaseOverlay.
00037 { 00038 // because of IPAddressResolver, we need to wait until interfaces are registered, 00039 // address auto-assignment takes place etc. 00040 if(stage != MIN_STAGE_OVERLAY) return; 00041 00042 state = INIT; 00043 setBootstrapedIcon(); 00044 lobbyServer = bootstrapOracle->getBootstrapNode(); 00045 00046 joinTimer = new cMessage("join timer"); 00047 simtime_t joinTime = ceil(simulation.simTime() + (simtime_t) par("joinDelay")); 00048 scheduleAt( joinTime, joinTimer ); 00049 00050 movementRate = par("movementRate"); 00051 eventDeliveryTimer = new PubSubTimer("event delivery timer"); 00052 eventDeliveryTimer->setType( PUBSUB_EVENTDELIVERY ); 00053 scheduleAt( joinTime + 1.0/(2*movementRate), eventDeliveryTimer ); 00054 00055 numSubspaces = par("numSubspaces"); 00056 subspaceSize = (int) ( (unsigned int) par("areaDimension") / numSubspaces); 00057 thisNode.setKey( OverlayKey::random() ); 00058 00059 maxChildren = par("maxChildren"); 00060 PubSubSubspaceResponsible::maxChildren = maxChildren; 00061 00062 AOIWidth = par("AOIWidth"); 00063 maxMoveDelay = par("maxMoveDelay"); 00064 00065 parentTimeout = par("parentTimeout"); 00066 heartbeatTimer = new PubSubTimer("HeartbeatTimer"); 00067 heartbeatTimer->setType( PUBSUB_HEARTBEAT ); 00068 startTimer( heartbeatTimer ); 00069 childPingTimer = new PubSubTimer("ChildPingTimer"); 00070 childPingTimer->setType( PUBSUB_CHILDPING ); 00071 startTimer( childPingTimer ); 00072 00073 numEventsWrongTimeslot = numEventsCorrectTimeslot = 0; 00074 numPubSubSignalingMessages = 0; 00075 pubSubSignalingMessagesSize = 0; 00076 numMoveMessages = 0; 00077 moveMessagesSize = 0; 00078 numMoveListMessages = 0; 00079 moveListMessagesSize = 0; 00080 respMoveListMessagesSize = 0; 00081 lostMovementLists = 0; 00082 receivedMovementLists = 0; 00083 WATCH( numPubSubSignalingMessages ); 00084 WATCH( pubSubSignalingMessagesSize ); 00085 WATCH( numMoveMessages ); 00086 WATCH( moveMessagesSize ); 00087 WATCH( numMoveListMessages ); 00088 WATCH( moveListMessagesSize ); 00089 WATCH( numEventsWrongTimeslot ); 00090 WATCH( numEventsCorrectTimeslot ); 00091 WATCH( lostMovementLists ); 00092 WATCH( receivedMovementLists ); 00093 WATCH_LIST( subscribedSubspaces ); 00094 WATCH_MAP( responsibleSubspaces ); 00095 WATCH_MAP( backupSubspaces ); 00096 WATCH_MAP( intermediateSubspaces ); 00097 }
void PubSubMMOG::finishOverlay | ( | ) | [virtual] |
collects statistical data in derived class
Reimplemented from BaseOverlay.
01942 { 01943 simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime); 01944 if(time == 0) return; 01945 01946 globalStatistics->addStdDev("PubSubMMOG: Sent Signaling Messages/s", 01947 numPubSubSignalingMessages / time); 01948 globalStatistics->addStdDev("PubSubMMOG: Sent Signaling bytes/s", 01949 pubSubSignalingMessagesSize / time); 01950 globalStatistics->addStdDev("PubSubMMOG: Sent Move Messages/s", 01951 numMoveMessages / time); 01952 globalStatistics->addStdDev("PubSubMMOG: Sent Move bytes/s", 01953 moveMessagesSize / time); 01954 globalStatistics->addStdDev("PubSubMMOG: Sent MoveList Messages/s", 01955 numMoveListMessages / time); 01956 globalStatistics->addStdDev("PubSubMMOG: Sent MoveList bytes/s", 01957 moveListMessagesSize / time); 01958 globalStatistics->addStdDev("PubSubMMOG: Received Move Events (correct timeslot)/s", 01959 numEventsCorrectTimeslot / time); 01960 globalStatistics->addStdDev("PubSubMMOG: Received Move Events (wrong timeslot)/s", 01961 numEventsWrongTimeslot / time); 01962 globalStatistics->addStdDev("PubSubMMOG: Responsible Nodes: Send MoveList Bytes/s", 01963 respMoveListMessagesSize / time); 01964 globalStatistics->addStdDev("PubSubMMOG: Lost or too long delayed MoveLists/s", 01965 lostMovementLists / time); 01966 globalStatistics->addStdDev("PubSubMMOG: Received valid MoveLists/s", 01967 receivedMovementLists / time); 01968 }
void PubSubMMOG::handleUDPMessage | ( | BaseOverlayMessage * | msg | ) | [virtual] |
Processes messages from underlay.
msg | Message from UDP |
Reimplemented from BaseOverlay.
00241 { 00242 if( PubSubMoveListMessage* moveMsg = dynamic_cast<PubSubMoveListMessage*>(msg) ){ 00243 handleMoveListMessage( moveMsg ); 00244 delete moveMsg; 00245 } else if( PubSubMoveMessage* moveMsg = dynamic_cast<PubSubMoveMessage*>(msg) ){ 00246 handleMoveMessage( moveMsg ); 00247 } else if( PubSubUnsubscriptionMessage* unsMsg = dynamic_cast<PubSubUnsubscriptionMessage*>(msg) ){ 00248 handleUnsubscriptionMessage( unsMsg ); 00249 delete unsMsg; 00250 } else if( PubSubNodeLeftMessage* leftMsg = dynamic_cast<PubSubNodeLeftMessage*>(msg) ){ 00251 handleNodeLeftMessage( leftMsg ); 00252 delete leftMsg; 00253 } else if( PubSubReplacementMessage* replaceMsg = dynamic_cast<PubSubReplacementMessage*>(msg) ){ 00254 handleReplacementMessage( replaceMsg ); 00255 delete replaceMsg; 00256 } else if( PubSubBackupSubscriptionMessage* backupMsg = dynamic_cast<PubSubBackupSubscriptionMessage*>(msg) ){ 00257 handleSubscriptionBackup( backupMsg ); 00258 delete backupMsg; 00259 } else if( PubSubBackupUnsubscribeMessage* backupMsg = dynamic_cast<PubSubBackupUnsubscribeMessage*>(msg) ){ 00260 handleUnsubscribeBackup( backupMsg ); 00261 delete backupMsg; 00262 } else if( PubSubBackupIntermediateMessage* backupMsg = dynamic_cast<PubSubBackupIntermediateMessage*>(msg) ){ 00263 handleIntermediateBackup( backupMsg ); 00264 delete backupMsg; 00265 } else if( PubSubReleaseIntermediateMessage* releaseMsg = dynamic_cast<PubSubReleaseIntermediateMessage*>(msg) ){ 00266 handleReleaseIntermediate( releaseMsg ); 00267 delete releaseMsg; 00268 } 00269 }
void PubSubMMOG::handleTimerEvent | ( | cMessage * | msg | ) | [virtual] |
Processes "timer" self-messages.
msg | A self-message |
Reimplemented from BaseOverlay.
00272 { 00273 if( PubSubTimer* timer = dynamic_cast<PubSubTimer*>(msg) ) { 00274 switch( timer->getType() ) { 00275 case PUBSUB_HEARTBEAT: 00276 sendHearbeatToChildren(); 00277 startTimer( timer ); 00278 break; 00279 case PUBSUB_CHILDPING: 00280 sendPingToChildren(); 00281 startTimer( timer ); 00282 break; 00283 case PUBSUB_PARENT_TIMEOUT: 00284 handleParentTimeout( timer ); 00285 break; 00286 case PUBSUB_EVENTDELIVERY: 00287 publishEvents(); 00288 startTimer( timer ); 00289 break; 00290 } 00291 } else if( msg == joinTimer ) { 00292 // send a fake ready message to app to get initial position 00293 // Note: This is not consistent to the paper, where the lobby server 00294 // positions player. But it is needed for consistency with other MMOG protocols 00295 CompReadyMessage* msg = new CompReadyMessage("fake READY"); 00296 msg->setReady(true); 00297 msg->setComp(getThisCompType()); 00298 send( msg, "to_app"); 00299 delete joinTimer; 00300 joinTimer = NULL; 00301 } 00302 }
void PubSubMMOG::handleAppMessage | ( | cMessage * | msg | ) | [virtual] |
Processes non-commonAPI messages.
msg | non-commonAPIMessage |
Reimplemented from BaseOverlay.
00305 { 00306 if( GameAPIPositionMessage *posMsg = dynamic_cast<GameAPIPositionMessage*>(msg) ) { 00307 if( state == READY ) { 00308 handleMove( posMsg ); 00309 } else if ( state == JOINING ) { 00310 // We are not connected to our responsible node, inform app 00311 CompReadyMessage* msg = new CompReadyMessage("Overlay not READY!"); 00312 msg->setReady(false); 00313 msg->setComp(getThisCompType()); 00314 send( msg, "to_app"); 00315 } else if ( state == INIT ) { 00316 // This is only called for the first MOVE message 00317 // Trigger login 00318 PubSubJoinCall* joinMsg = new PubSubJoinCall("Login"); 00319 joinMsg->setPosition( posMsg->getPosition() ); 00320 // FIXME: Ressource handling not yet supported! 00321 joinMsg->setRessources( 4 ); 00322 sendUdpRpcCall( lobbyServer, joinMsg ); 00323 00324 state = JOINING; 00325 setBootstrapedIcon(); 00326 00327 // tell app to wait until login is confirmed... 00328 CompReadyMessage* readyMsg = new CompReadyMessage("Overlay not READY!"); 00329 readyMsg->setReady(false); 00330 readyMsg->setComp(getThisCompType()); 00331 send( readyMsg, "to_app"); 00332 00333 currentRegionX = (unsigned int) (posMsg->getPosition().x/subspaceSize); 00334 currentRegionY = (unsigned int) (posMsg->getPosition().y/subspaceSize); 00335 } 00336 delete msg; 00337 } 00338 }
void PubSubMMOG::receiveChangeNotification | ( | int | category, | |
cPolymorphic * | details | |||
) | [virtual] |
callback-method for events at the NotificationBoard
category | ... TODO ... | |
details | ... TODO ... |
Reimplemented from BaseOverlay.
bool PubSubMMOG::handleRpc | ( | BaseCallMessage * | msg | ) | [virtual] |
Processes Remote-Procedure-Call invokation messages.
This method should be overloaded when the overlay provides RPC functionality.
Reimplemented from BaseRpc.
00100 { 00101 // delegate messages 00102 RPC_SWITCH_START( msg ) 00103 RPC_DELEGATE( PubSubSubscription, handleSubscriptionCall ); 00104 RPC_DELEGATE( PubSubTakeOverSubspace, handleTakeOver ); 00105 RPC_DELEGATE( PubSubBackup, handleBackupCall ); 00106 RPC_DELEGATE( PubSubIntermediate, handleIntermediateCall ); 00107 RPC_DELEGATE( PubSubAdoptChild, handleAdoptChildCall ); 00108 RPC_DELEGATE( PubSubPing, handlePingCall ); 00109 RPC_SWITCH_END( ) 00110 00111 return RPC_HANDLED; 00112 00113 }
void PubSubMMOG::handleRpcResponse | ( | BaseResponseMessage * | msg, | |
cPolymorphic * | context, | |||
int | rpcId, | |||
simtime_t | rtt | |||
) | [virtual] |
This method is called if an RPC response has been received.
msg | The response message. | |
context | Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code | |
rpcId | The RPC id. | |
rtt | The Round-Trip-Time of this RPC |
Reimplemented from RpcListener.
00118 { 00119 RPC_SWITCH_START(msg); 00120 RPC_ON_RESPONSE( PubSubJoin ) { 00121 handleJoinResponse( _PubSubJoinResponse ); 00122 EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip 00123 << " (" << thisNode.key.toString(16) << ")]\n" 00124 << " Received a PubSubJoin RPC Response: id=" << rpcId << "\n" 00125 << " msg=" << *_PubSubJoinResponse << " rtt=" << rtt 00126 << endl; 00127 break; 00128 } 00129 RPC_ON_RESPONSE( PubSubSubscription ) { 00130 handleSubscriptionResponse( _PubSubSubscriptionResponse ); 00131 EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip 00132 << " (" << thisNode.key.toString(16) << ")]\n" 00133 << " Received a PubSubSubscription RPC Response: id=" << rpcId << "\n" 00134 << " msg=" << *_PubSubSubscriptionResponse << " rtt=" << rtt 00135 << endl; 00136 break; 00137 } 00138 RPC_ON_RESPONSE( PubSubResponsibleNode ) { 00139 handleResponsibleNodeResponse( _PubSubResponsibleNodeResponse ); 00140 EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip 00141 << " (" << thisNode.key.toString(16) << ")]\n" 00142 << " Received a PubSubResponsibleNode RPC Response: id=" << rpcId << "\n" 00143 << " msg=" << *_PubSubResponsibleNodeResponse << " rtt=" << rtt 00144 << endl; 00145 break; 00146 } 00147 RPC_ON_RESPONSE( PubSubHelp ) { 00148 handleHelpResponse( _PubSubHelpResponse ); 00149 EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip 00150 << " (" << thisNode.key.toString(16) << ")]\n" 00151 << " Received a PubSubHelp RPC Response: id=" << rpcId << "\n" 00152 << " msg=" << *_PubSubHelpResponse << " rtt=" << rtt 00153 << endl; 00154 break; 00155 } 00156 RPC_ON_RESPONSE( PubSubBackup ) { 00157 handleBackupResponse( _PubSubBackupResponse ); 00158 EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip 00159 << " (" << thisNode.key.toString(16) << ")]\n" 00160 << " Received a PubSubBackup RPC Response: id=" << rpcId << "\n" 00161 << " msg=" << *_PubSubBackupResponse << " rtt=" << rtt 00162 << endl; 00163 break; 00164 } 00165 RPC_ON_RESPONSE( PubSubIntermediate ) { 00166 handleIntermediateResponse( _PubSubIntermediateResponse ); 00167 EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip 00168 << " (" << thisNode.key.toString(16) << ")]\n" 00169 << " Received a PubSubIntermediate RPC Response: id=" << rpcId << "\n" 00170 << " msg=" << *_PubSubIntermediateResponse << " rtt=" << rtt 00171 << endl; 00172 break; 00173 } 00174 RPC_ON_RESPONSE( PubSubAdoptChild ) { 00175 handleAdoptChildResponse( _PubSubAdoptChildResponse ); 00176 EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip 00177 << " (" << thisNode.key.toString(16) << ")]\n" 00178 << " Received a PubSubAdoptChild RPC Response: id=" << rpcId << "\n" 00179 << " msg=" << *_PubSubAdoptChildResponse << " rtt=" << rtt 00180 << endl; 00181 break; 00182 } 00183 RPC_ON_RESPONSE( PubSubPing ) { 00184 handlePingResponse( _PubSubPingResponse ); 00185 EV << "[PubSubMMOG::handleRpcResponse() @ " << thisNode.ip 00186 << " (" << thisNode.key.toString(16) << ")]\n" 00187 << " Received a PubSubPing RPC Response: id=" << rpcId << "\n" 00188 << " msg=" << *_PubSubPingResponse << " rtt=" << rtt 00189 << endl; 00190 break; 00191 } 00192 RPC_SWITCH_END( ); 00193 }
void PubSubMMOG::handleRpcTimeout | ( | BaseCallMessage * | msg, | |
const TransportAddress & | dest, | |||
cPolymorphic * | context, | |||
int | rpcId, | |||
const OverlayKey & | destKey | |||
) | [virtual] |
This method is called if an RPC timeout has been reached.
msg | The original RPC message. | |
dest | The destination node | |
context | Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code | |
rpcId | The RPC id. | |
destKey | the destination OverlayKey |
Reimplemented from RpcListener.
00199 { 00200 RPC_SWITCH_START(msg) 00201 RPC_ON_CALL( PubSubBackup ) { 00202 handleBackupCallTimeout( _PubSubBackupCall, dest ); 00203 EV << "[PubSubMMOG::handleRpcTimeout() @ " << thisNode.ip 00204 << " (" << thisNode.key.toString(16) << ")]\n" 00205 << " Backup RPC Call timed out: id=" << rpcId << "\n" 00206 << " msg=" << *_PubSubBackupCall 00207 << " oldNode=" << dest 00208 << endl; 00209 break; 00210 } 00211 RPC_ON_CALL( PubSubPing ) { 00212 handlePingCallTimeout( _PubSubPingCall, dest ); 00213 EV << "[PubSubMMOG::handleRpcTimeout() @ " << thisNode.ip 00214 << " (" << thisNode.key.toString(16) << ")]\n" 00215 << " Ping RPC Call timed out: id=" << rpcId << "\n" 00216 << " msg=" << *_PubSubPingCall 00217 << " oldNode=" << dest 00218 << endl; 00219 break; 00220 } 00221 RPC_ON_CALL( PubSubSubscription ) { 00222 handleSubscriptionCallTimeout( _PubSubSubscriptionCall, dest ); 00223 EV << "[PubSubMMOG::handleRpcTimeout() @ " << thisNode.ip 00224 << " (" << thisNode.key.toString(16) << ")]\n" 00225 << " Subscription RPC Call timed out: id=" << rpcId << "\n" 00226 << " msg=" << *_PubSubSubscriptionCall 00227 << " oldNode=" << dest 00228 << endl; 00229 break; 00230 } 00231 RPC_SWITCH_END( ) 00232 00233 // FIXME: 00234 // AdoptCall missing! 00235 // IntermediateCall missing! 00236 // (ResponsibleNodeCall missing) 00237 // (HelpCall missing) 00238 }
void PubSubMMOG::setBootstrapedIcon | ( | ) | [protected] |
Referenced by handleAppMessage(), handleJoinResponse(), handleSubscriptionResponse(), and initializeOverlay().
01895 { 01896 if(ev.isGUI()) { 01897 if(state == READY) { 01898 parentModule()->parentModule()->displayString().setTagArg("i2", 1, "green"); 01899 displayString().setTagArg("i", 1, "green"); 01900 } 01901 else if(state == JOINING) { 01902 parentModule()->parentModule()->displayString().setTagArg("i2", 1, "yellow"); 01903 displayString().setTagArg("i", 1, "yellow"); 01904 } 01905 else { 01906 parentModule()->parentModule()->displayString().setTagArg("i2", 1, "red"); 01907 displayString().setTagArg("i", 1, "red"); 01908 } 01909 } 01910 }
void PubSubMMOG::handleMove | ( | GameAPIPositionMessage * | posMsg | ) | [protected] |
Referenced by handleAppMessage().
00531 { 00532 currentRegionX = (unsigned int) (posMsg->getPosition().x/subspaceSize); 00533 currentRegionY = (unsigned int) (posMsg->getPosition().y/subspaceSize); 00534 00535 PubSubSubspaceId region( currentRegionX, currentRegionY, numSubspaces); 00536 00537 set<PubSubSubspaceId> expectedRegions; 00538 int minX = (int) ((posMsg->getPosition().x - AOIWidth)/subspaceSize); 00539 if( minX < 0 ) minX = 0; 00540 int maxX = (int) ((posMsg->getPosition().x + AOIWidth)/subspaceSize); 00541 if( maxX >= numSubspaces ) maxX = numSubspaces -1; 00542 int minY = (int) ((posMsg->getPosition().y - AOIWidth)/subspaceSize); 00543 if( minY < 0 ) minY = 0; 00544 int maxY = (int) ((posMsg->getPosition().y + AOIWidth)/subspaceSize); 00545 if( maxY >= numSubspaces ) maxY = numSubspaces -1; 00546 00547 // FIXME: make parameter: unsubscription size 00548 int minUnsubX = (int) ((posMsg->getPosition().x - 1.5*AOIWidth)/subspaceSize); 00549 if( minUnsubX < 0 ) minUnsubX = 0; 00550 int maxUnsubX = (int) ((posMsg->getPosition().x + 1.5*AOIWidth)/subspaceSize); 00551 if( maxUnsubX >= numSubspaces ) maxUnsubX = numSubspaces -1; 00552 int minUnsubY = (int) ((posMsg->getPosition().y - 1.5*AOIWidth)/subspaceSize); 00553 if( minUnsubY < 0 ) minUnsubY = 0; 00554 int maxUnsubY = (int) ((posMsg->getPosition().y + 1.5+AOIWidth)/subspaceSize); 00555 if( maxUnsubY >= numSubspaces ) maxUnsubY = numSubspaces -1; 00556 00557 for( int x = minX; x <= maxX; ++x ){ 00558 for( int y = minY; y <= maxY; ++y ){ 00559 expectedRegions.insert( PubSubSubspaceId( x, y, numSubspaces )); 00560 } 00561 } 00562 00563 list<PubSubSubspace>::iterator subIt = subscribedSubspaces.begin(); 00564 PubSubSubspace* subspace = NULL; 00565 while( subIt != subscribedSubspaces.end() ){ 00566 if( subIt->getId() == region ){ 00567 subspace = &*subIt; 00568 } 00569 expectedRegions.erase( subIt->getId() ); 00570 00571 // unsubscribe region if to far away 00572 if( subIt->getId().getX() < minX || subIt->getId().getX() > maxX || 00573 subIt->getId().getY() < minY || subIt->getId().getY() > maxY ){ 00574 if( !subIt->getResponsibleNode().isUnspecified() ){ 00575 PubSubUnsubscriptionMessage* unsubMsg = new PubSubUnsubscriptionMessage("Unsubscribe from subspace"); 00576 unsubMsg->setSubspaceId( subIt->getId().getId() ); 00577 unsubMsg->setSrc( thisNode ); 00578 unsubMsg->setLength( PUBSUB_UNSUBSCRIPTION_L( unsubMsg )); 00579 RECORD_STATS( 00580 ++numPubSubSignalingMessages; 00581 pubSubSignalingMessagesSize+= unsubMsg->byteLength() 00582 ); 00583 sendMessageToUDP( subIt->getResponsibleNode(), unsubMsg ); 00584 } 00585 // Erase subspace from subscribedList and increase iterator 00586 subscribedSubspaces.erase( subIt++ ); 00587 } else { 00588 ++subIt; 00589 } 00590 } 00591 00592 // if any "near" region is not yet subscribed, subscribe 00593 for( set<PubSubSubspaceId>::iterator regionIt = expectedRegions.begin(); regionIt != expectedRegions.end(); ++regionIt ){ 00594 PubSubSubspace sub( *regionIt ); 00595 subscribedSubspaces.push_back( sub ); 00596 PubSubResponsibleNodeCall* respCall = new PubSubResponsibleNodeCall("Request Responsible NodeHandle"); 00597 respCall->setSubspacePos( Vector2D(regionIt->getX(), regionIt->getY()) ); 00598 respCall->setLength( PUBSUB_RESPONSIBLENODECALL_L( respCall )); 00599 RECORD_STATS( 00600 ++numPubSubSignalingMessages; 00601 pubSubSignalingMessagesSize+= respCall->byteLength() 00602 ); 00603 sendUdpRpcCall( lobbyServer, respCall, NULL, 5, 5 ); // FIXME: Make it a parameter... 00604 } 00605 00606 if( subspace && !subspace->getResponsibleNode().isUnspecified() ){ 00607 PubSubMoveMessage* moveMsg = new PubSubMoveMessage("Player move"); 00608 moveMsg->setSubspaceId( region.getId() ); 00609 moveMsg->setPlayer( thisNode ); 00610 moveMsg->setPosition( posMsg->getPosition() ); 00611 moveMsg->setTimestamp( simulation.simTime() ); 00612 moveMsg->setLength( PUBSUB_MOVE_L( moveMsg )); 00613 RECORD_STATS( 00614 ++numMoveMessages; 00615 moveMessagesSize+= moveMsg->byteLength() 00616 ); 00617 sendMessageToUDP( subspace->getResponsibleNode(), moveMsg ); 00618 } else { 00619 // trying to move to not-yet subscribed region 00620 // FIXME: change state to JOINING? 00621 } 00622 }
void PubSubMMOG::handleMoveMessage | ( | PubSubMoveMessage * | moveMsg | ) | [protected] |
Referenced by handleUDPMessage().
00625 { 00626 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 00627 it = responsibleSubspaces.find( PubSubSubspaceId(moveMsg->getSubspaceId(), numSubspaces) ); 00628 if( it == responsibleSubspaces.end() ){ 00629 EV << "PubSubMMOG::handleMoveMessage@" << thisNode << ":\n" 00630 << " received moveMessage for unknown subspace" << moveMsg->getSubspaceId() << "\n"; 00631 return; 00632 } 00633 00634 // If message arrived in the correct timeslot, store move message until deadline 00635 // Note: This assumes, we get no messages with future timestamps. At least in 00636 // the simulation, this assumption will hold. 00637 if( moveMsg->getTimestamp() >= eventDeliveryTimer->arrivalTime() - 1.0/(2*movementRate) ){ 00638 it->second.waitingMoveMessages.push_back( moveMsg ); 00639 ++numEventsCorrectTimeslot; 00640 } else { 00641 EV << "PubSubMMOG::handleMoveMessage@" << thisNode << ":\n" 00642 << " received moveMesage with Timestamp: " << moveMsg->getTimestamp() << "\n" 00643 << " deadline was: " << eventDeliveryTimer->arrivalTime() - 1.0/(2*movementRate) << "\n"; 00644 ++numEventsWrongTimeslot; 00645 cancelAndDelete( moveMsg ); 00646 } 00647 }
void PubSubMMOG::handleMoveListMessage | ( | PubSubMoveListMessage * | moveMsg | ) | [protected] |
Referenced by handleUDPMessage().
00650 { 00651 simtime_t timestamp = moveMsg->getTimestamp(); 00652 00653 // If I'm intermediate node for this subspace, forward message to children 00654 std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it; 00655 it = intermediateSubspaces.find( PubSubSubspaceId(moveMsg->getSubspaceId(), numSubspaces) ); 00656 if( it != intermediateSubspaces.end() ){ 00657 // Forward only if the message has not already been forwarded 00658 if( it->second.getLastTimestamp() < moveMsg->getTimestamp() ){ 00659 set<NodeHandle>::iterator childIt; 00660 for( childIt = it->second.children.begin(); childIt != it->second.children.end(); ++childIt ){ 00661 sendMessageToUDP( *childIt, (BaseOverlayMessage*) moveMsg->dup() ); 00662 RECORD_STATS( 00663 ++numMoveListMessages; 00664 moveListMessagesSize+= moveMsg->byteLength() 00665 ); 00666 } 00667 it->second.setTimestamp( timestamp ); 00668 } 00669 } 00670 00671 // If I'm subscribed to the subspace, transfer a GameAPIMoveList to app 00672 std::list<PubSubSubspace>::iterator subIt; 00673 for( subIt = subscribedSubspaces.begin(); subIt != subscribedSubspaces.end(); ++subIt ){ 00674 if( subIt->getId().getId() == moveMsg->getSubspaceId() ){ 00675 if( subIt->getLastTimestamp() < moveMsg->getTimestamp() ){ 00676 GameAPIListMessage* moveList = new GameAPIListMessage("player position update"); 00677 moveList->setCommand( NEIGHBOR_UPDATE ); 00678 moveList->setAddNeighborArraySize( moveMsg->getPlayerArraySize() ); 00679 moveList->setNeighborPositionArraySize( moveMsg->getPositionArraySize() ); 00680 for( unsigned int i = 0; i < moveMsg->getPlayerArraySize(); ++i ){ 00681 moveList->setAddNeighbor( i, moveMsg->getPlayer(i) ); 00682 moveList->setNeighborPosition( i, moveMsg->getPosition(i) ); 00683 } 00684 send( moveList, "to_app" ); 00685 RECORD_STATS( 00686 if( timestamp < simulation.simTime() - maxMoveDelay ){ 00687 ++lostMovementLists; 00688 } else { 00689 ++receivedMovementLists; 00690 } 00691 if( subIt->getLastTimestamp() )lostMovementLists += (timestamp - subIt->getLastTimestamp())*movementRate -1; 00692 00693 globalStatistics->addStdDev("PubSubMMOG: Move Delay", 00694 simulation.simTime() - timestamp + 0.5/movementRate ); 00695 ); 00696 subIt->setTimestamp( timestamp ); 00697 } 00698 return; 00699 } 00700 } 00701 }
void PubSubMMOG::handleJoinResponse | ( | PubSubJoinResponse * | joinResp | ) | [protected] |
Referenced by handleRpcResponse().
00357 { 00358 state = JOINING; 00359 setBootstrapedIcon(); 00360 PubSubSubspaceId region( currentRegionX, currentRegionY, numSubspaces); 00361 00362 NodeHandle respNode = joinResp->getResponsibleNode(); 00363 PubSubSubspace sub(region); 00364 sub.setResponsibleNode( respNode ); 00365 subscribedSubspaces.push_back( sub ); 00366 if( respNode.isUnspecified() ) { 00367 PubSubResponsibleNodeCall* respCall = new PubSubResponsibleNodeCall("Request Responsible NodeHandle"); 00368 respCall->setSubspacePos( Vector2D(currentRegionX, currentRegionY) ); 00369 respCall->setLength( PUBSUB_RESPONSIBLENODECALL_L( respCall ) ); 00370 RECORD_STATS( 00371 ++numPubSubSignalingMessages; 00372 pubSubSignalingMessagesSize+= respCall->byteLength() 00373 ); 00374 sendUdpRpcCall( lobbyServer, respCall, NULL, 5, 5 ); // FIXME: Make it a parameter... 00375 } else { 00376 PubSubSubscriptionCall* subCall = new PubSubSubscriptionCall("JoinSubspace"); 00377 subCall->setSubspaceId( region.getId() ); 00378 subCall->setLength( PUBSUB_SUBSCRIPTIONCALL_L( subCall )); 00379 RECORD_STATS( 00380 ++numPubSubSignalingMessages; 00381 pubSubSignalingMessagesSize+= subCall->byteLength() 00382 ); 00383 sendUdpRpcCall( respNode, subCall ); 00384 } 00385 }
void PubSubMMOG::handleSubscriptionCall | ( | PubSubSubscriptionCall * | subCall | ) | [protected] |
Referenced by handleRpc().
00432 { 00433 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 00434 it = responsibleSubspaces.find( PubSubSubspaceId(subCall->getSubspaceId(), numSubspaces) ); 00435 00436 PubSubBackupSubscriptionMessage* backupMsg = 0; 00437 PubSubSubscriptionResponse* resp; 00438 if( it == responsibleSubspaces.end() ) { 00439 resp = new PubSubSubscriptionResponse("Subscription failed"); 00440 resp->setFailed( true ); 00441 } else { 00442 resp = new PubSubSubscriptionResponse("Subscription successful"); 00443 backupMsg = new PubSubBackupSubscriptionMessage("Backup: new subscription"); 00444 backupMsg->setSubspaceId( subCall->getSubspaceId() ); 00445 backupMsg->setChild( subCall->getSrcNode() ); 00446 00447 if( it->second.addChild( subCall->getSrcNode() )) { 00448 // We have still room for the child 00449 backupMsg->setParent( thisNode ); 00450 } else { 00451 // Child has to go to an intermediate node... 00452 if( PubSubSubspaceResponsible::IntermediateNode* iNode = it->second.getNextFreeIntermediate() ){ 00453 // find intermediate node with free slots 00454 PubSubAdoptChildCall* adoptCall = new PubSubAdoptChildCall("Adopt child"); 00455 adoptCall->setChild( subCall->getSrcNode() ); 00456 adoptCall->setSubspaceId( subCall->getSubspaceId() ); 00457 adoptCall->setLength( PUBSUB_ADOPTCHILDCALL_L( adoptCall )); 00458 sendUdpRpcCall( iNode->node, adoptCall ); 00459 RECORD_STATS( 00460 ++numPubSubSignalingMessages; 00461 pubSubSignalingMessagesSize+= adoptCall->byteLength() 00462 ); 00463 iNode->waitingChildren++; 00464 } else { 00465 // no free slots available, create new intermediate node 00466 // FIXME: when getting two subscriptions at once, we're requesting too many intermediates 00467 PubSubHelpCall* helpCall = new PubSubHelpCall("I need an intermediate node"); 00468 helpCall->setHelpType( PUBSUB_INTERMEDIATE ); 00469 helpCall->setSubspaceId( subCall->getSubspaceId() ); 00470 helpCall->setLength( PUBSUB_HELPCALL_L( helpCall )); 00471 sendUdpRpcCall( lobbyServer, helpCall ); 00472 RECORD_STATS( 00473 ++numPubSubSignalingMessages; 00474 pubSubSignalingMessagesSize+= helpCall->byteLength() 00475 ); 00476 } 00477 } 00478 } 00479 resp->setLength( PUBSUB_SUBSCRIPTIONRESPONSE_L( resp )); 00480 sendRpcResponse( subCall, resp ); 00481 RECORD_STATS( 00482 ++numPubSubSignalingMessages; 00483 pubSubSignalingMessagesSize+= resp->byteLength() 00484 ); 00485 00486 if( it == responsibleSubspaces.end() ) return; 00487 00488 // FIXME: just for testing 00489 PubSubSubspaceResponsible& subspace = it->second; 00490 int iii = subspace.getTotalChildrenCount(); 00491 subspace.fixTotalChildrenCount(); 00492 if( iii != subspace.getTotalChildrenCount() ){ 00493 opp_error("Huh?"); 00494 } 00495 00496 if( !it->second.getBackupNode().isUnspecified() ){ 00497 backupMsg->setLength( PUBSUB_BACKUPSUBSCRIPTION_L( backupMsg )); 00498 RECORD_STATS( 00499 ++numPubSubSignalingMessages; 00500 pubSubSignalingMessagesSize+= backupMsg->byteLength() 00501 ); 00502 sendMessageToUDP( it->second.getBackupNode(), backupMsg ); 00503 } else { 00504 delete backupMsg; 00505 } 00506 }
void PubSubMMOG::handleSubscriptionResponse | ( | PubSubSubscriptionResponse * | subResp | ) | [protected] |
Referenced by handleRpcResponse().
00341 { 00342 if( subResp->getFailed() ) { 00343 // TODO: get new resp node... 00344 } else { 00345 if( state != READY ){ 00346 state = READY; 00347 setBootstrapedIcon(); 00348 CompReadyMessage* readyMsg = new CompReadyMessage("Overlay READY!"); 00349 readyMsg->setReady(true); 00350 readyMsg->setComp(getThisCompType()); 00351 sendDelayed( readyMsg, ceil(simulation.simTime()) - simulation.simTime(), "to_app" ); 00352 } 00353 } 00354 }
void PubSubMMOG::handleResponsibleNodeResponse | ( | PubSubResponsibleNodeResponse * | subResp | ) | [protected] |
Referenced by handleRpcResponse().
00388 { 00389 int subspaceId = subResp->getSubspaceId(); 00390 NodeHandle respNode = subResp->getResponsibleNode(); 00391 00392 std::list<PubSubSubspace>::iterator it = subscribedSubspaces.begin(); 00393 while( it != subscribedSubspaces.end() ) { 00394 if( it->getId().getId() == subspaceId) break; 00395 ++it; 00396 } 00397 if( it != subscribedSubspaces.end() ) { 00398 it->setResponsibleNode( respNode ); 00399 00400 PubSubSubscriptionCall* subCall = new PubSubSubscriptionCall("JoinSubspace"); 00401 subCall->setSubspaceId( subspaceId ); 00402 subCall->setLength( PUBSUB_SUBSCRIPTIONCALL_L( subCall )); 00403 RECORD_STATS( 00404 ++numPubSubSignalingMessages; 00405 pubSubSignalingMessagesSize+= subCall->byteLength() 00406 ); 00407 sendUdpRpcCall( respNode, subCall ); 00408 } 00409 }
void PubSubMMOG::handleTakeOver | ( | PubSubTakeOverSubspaceCall * | toCall | ) | [protected] |
Referenced by handleRpc().
00509 { 00510 PubSubSubspaceId region((int) toCall->getSubspacePos().x, (int) toCall->getSubspacePos().y, numSubspaces); 00511 00512 takeOverNewSubspace( region ); 00513 00514 PubSubTakeOverSubspaceResponse* toResp = new PubSubTakeOverSubspaceResponse("Accept subspace responsibility"); 00515 toResp->setSubspacePos( toCall->getSubspacePos() ); 00516 toResp->setLength( PUBSUB_TAKEOVERSUBSPACERESPONSE_L( toResp )); 00517 RECORD_STATS( 00518 ++numPubSubSignalingMessages; 00519 pubSubSignalingMessagesSize+= toResp->byteLength() 00520 ); 00521 sendRpcResponse( toCall, toResp ); 00522 }
void PubSubMMOG::handleHelpResponse | ( | PubSubHelpResponse * | helpResp | ) | [protected] |
Referenced by handleRpcResponse().
00704 { 00705 // lobby server answered our call for help 00706 // (i.e. he sends us a candidate for backup/intermediate nodes 00707 if( helpResp->getHelpType() == PUBSUB_BACKUP ){ 00708 PubSubBackupCall* backupCall = new PubSubBackupCall("Become my backup node!"); 00709 backupCall->setSubspaceId( helpResp->getSubspaceId() ); 00710 00711 // Find the subspace in the subspace map 00712 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 00713 it = responsibleSubspaces.find( PubSubSubspaceId(helpResp->getSubspaceId(), numSubspaces) ); 00714 if( it == responsibleSubspaces.end() ){ 00715 EV << "PubSubMMOG::handleHelpResponse@" << thisNode << ":\n" 00716 << " received helpResponse for unknown subspace" << helpResp->getSubspaceId() << "\n"; 00717 return; 00718 } 00719 PubSubSubspaceResponsible& subspace = it->second; 00720 00721 // Assume the new backup will not refuse his task 00722 subspace.setBackupNode( helpResp->getNode() ); 00723 00724 // FIXME: just for testing 00725 int iii = subspace.getTotalChildrenCount(); 00726 subspace.fixTotalChildrenCount(); 00727 if( iii != subspace.getTotalChildrenCount() ){ 00728 opp_error("Huh?"); 00729 } 00730 00731 // backup the load balancing tree 00732 backupCall->setChildrenArraySize( subspace.getTotalChildrenCount() ); 00733 backupCall->setChildrenPosArraySize( subspace.getTotalChildrenCount() ); 00734 backupCall->setIntermediatesArraySize( subspace.intermediateNodes.size() ); 00735 00736 set<NodeHandle>::iterator childIt; 00737 map<NodeHandle, bool>::iterator childMapIt; 00738 unsigned int i = 0; 00739 for( childMapIt = subspace.cachedChildren.begin(); childMapIt != subspace.cachedChildren.end(); ++childMapIt ){ 00740 backupCall->setChildren(i, childMapIt->first); 00741 backupCall->setChildrenPos(i, -2); 00742 ++i; 00743 } 00744 for( childIt = subspace.children.begin(); childIt != subspace.children.end(); ++childIt ){ 00745 backupCall->setChildren(i, *childIt); 00746 backupCall->setChildrenPos(i, -1); 00747 ++i; 00748 } 00749 for( unsigned int ii = 0; ii < subspace.intermediateNodes.size(); ++ii ){ 00750 PubSubSubspaceResponsible::IntermediateNode& iNode = subspace.intermediateNodes[ii]; 00751 backupCall->setIntermediates(ii, iNode.node); 00752 for( childIt = iNode.children.begin(); childIt != iNode.children.end(); ++childIt ){ 00753 backupCall->setChildren(i, *childIt); 00754 backupCall->setChildrenPos(i, ii); 00755 ++i; 00756 } 00757 } 00758 00759 backupCall->setLength( PUBSUB_BACKUPCALL_L( backupCall )); 00760 RECORD_STATS( 00761 ++numPubSubSignalingMessages; 00762 pubSubSignalingMessagesSize+= backupCall->byteLength() 00763 ); 00764 sendUdpRpcCall( helpResp->getNode(), backupCall ); 00765 00766 } else if( helpResp->getHelpType() == PUBSUB_INTERMEDIATE ){ 00767 PubSubIntermediateCall* intermediateCall = new PubSubIntermediateCall("Become my intermediate node!"); 00768 intermediateCall->setSubspaceId( helpResp->getSubspaceId() ); 00769 intermediateCall->setLength( PUBSUB_INTERMEDIATECALL_L( intermediateCall )); 00770 RECORD_STATS( 00771 ++numPubSubSignalingMessages; 00772 pubSubSignalingMessagesSize+= intermediateCall->byteLength() 00773 ); 00774 sendUdpRpcCall( helpResp->getNode(), intermediateCall ); 00775 } 00776 }
void PubSubMMOG::handleBackupCall | ( | PubSubBackupCall * | backupCall | ) | [protected] |
Referenced by handleRpc().
00779 { 00780 int intId = backupCall->getSubspaceId(); 00781 PubSubSubspaceId subspaceId(intId, numSubspaces); 00782 00783 // Start Heartbeat Timer 00784 PubSubTimer* parentTimeout = new PubSubTimer("ParentTimeout"); 00785 parentTimeout->setType( PUBSUB_PARENT_TIMEOUT ); 00786 parentTimeout->setSubspaceId( intId ); 00787 startTimer( parentTimeout ); 00788 00789 // insert subspace into responsible list 00790 PubSubSubspaceResponsible subspace( subspaceId ); 00791 subspace.setResponsibleNode( backupCall->getSrcNode() ); 00792 subspace.setHeartbeatTimer( parentTimeout ); 00793 00794 // recounstruct load balancing tree 00795 for( unsigned int i = 0; i < backupCall->getIntermediatesArraySize(); ++i ){ 00796 PubSubSubspaceResponsible::IntermediateNode iNode; 00797 iNode.node = backupCall->getIntermediates(i); 00798 subspace.intermediateNodes.push_back( iNode ); 00799 } 00800 for( unsigned int i = 0; i < backupCall->getChildrenArraySize(); ++i ){ 00801 int pos = backupCall->getChildrenPos( i ); 00802 if( pos == -2 ){ 00803 subspace.cachedChildren.insert( make_pair( backupCall->getChildren(i), false )); 00804 } else if( pos == -1 ){ 00805 subspace.children.insert( backupCall->getChildren(i) ); 00806 } else { 00807 subspace.intermediateNodes[pos].children.insert( backupCall->getChildren(i) ); 00808 } 00809 } 00810 00811 backupSubspaces.insert( make_pair(subspaceId, subspace) ); 00812 00813 PubSubBackupResponse* backupResp = new PubSubBackupResponse("I'll be your backup"); 00814 backupResp->setSubspaceId( intId ); 00815 backupResp->setLength( PUBSUB_BACKUPRESPONSE_L( backupResp )); 00816 RECORD_STATS( 00817 ++numPubSubSignalingMessages; 00818 pubSubSignalingMessagesSize+= backupResp->byteLength() 00819 ); 00820 sendRpcResponse( backupCall, backupResp ); 00821 }
void PubSubMMOG::handleBackupResponse | ( | PubSubBackupResponse * | backupResp | ) | [protected] |
Referenced by handleRpcResponse().
00824 { 00825 // Nothing to be done 00826 // HandleHelpResponse() already did everything important 00827 }
void PubSubMMOG::handleIntermediateCall | ( | PubSubIntermediateCall * | intermediateCall | ) | [protected] |
Referenced by handleRpc().
00830 { 00831 // insert subspace into intermediate list 00832 PubSubSubspaceId subspaceId(intermediateCall->getSubspaceId(), numSubspaces); 00833 PubSubSubspaceIntermediate subspace( subspaceId ); 00834 subspace.setResponsibleNode( intermediateCall->getSrcNode() ); 00835 subspace.setTimestamp(0); 00836 intermediateSubspaces.insert( make_pair(subspaceId, subspace) ); 00837 00838 PubSubIntermediateResponse* iResp = new PubSubIntermediateResponse("I'll be your intermediate node"); 00839 iResp->setSubspaceId( intermediateCall->getSubspaceId() ); 00840 iResp->setLength( PUBSUB_INTERMEDIATERESPONSE_L( iResp )); 00841 RECORD_STATS( 00842 ++numPubSubSignalingMessages; 00843 pubSubSignalingMessagesSize+= iResp->byteLength() 00844 ); 00845 sendRpcResponse( intermediateCall, iResp ); 00846 }
void PubSubMMOG::handleIntermediateResponse | ( | PubSubIntermediateResponse * | intermediateResp | ) | [protected] |
Referenced by handleRpcResponse().
00849 { 00850 // we found a new intermediate node for a subspace 00851 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 00852 it = responsibleSubspaces.find( PubSubSubspaceId(intermediateResp->getSubspaceId(), numSubspaces) ); 00853 if( it == responsibleSubspaces.end() ) { 00854 EV << "PubSubMMOG::handleIntermediateResponse @ " << thisNode << "\n" 00855 << " Received Intermediate Response for unknown Subspace!\n"; 00856 return; 00857 } 00858 PubSubSubspaceResponsible& subspace = it->second; 00859 PubSubSubspaceResponsible::IntermediateNode iNode; 00860 iNode.node = intermediateResp->getSrcNode(); 00861 00862 // if there is any broken intermediate node in list, replace it 00863 bool newIntermediate = true; 00864 deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit; 00865 for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){ 00866 if( iit->node.isUnspecified() ){ 00867 iit->node = iNode.node; 00868 newIntermediate = false; 00869 break; 00870 } 00871 } 00872 if( iit == subspace.intermediateNodes.end() ){ 00873 subspace.intermediateNodes.push_back( iNode ); 00874 iit = subspace.intermediateNodes.end() - 1; 00875 } 00876 00877 // inform Backup 00878 if( !subspace.getBackupNode().isUnspecified() ){ 00879 PubSubBackupIntermediateMessage* backupMsg = new PubSubBackupIntermediateMessage("Backup: new Intermediate"); 00880 backupMsg->setSubspaceId( intermediateResp->getSubspaceId() ); 00881 backupMsg->setNode( iNode.node ); 00882 backupMsg->setPos( iit - subspace.intermediateNodes.begin() ); 00883 backupMsg->setLength( PUBSUB_BACKUPINTERMEDIATE_L( backupMsg )); 00884 RECORD_STATS( 00885 ++numPubSubSignalingMessages; 00886 pubSubSignalingMessagesSize+= backupMsg->byteLength() 00887 ); 00888 sendMessageToUDP( subspace.getBackupNode(), backupMsg ); 00889 } 00890 00891 // if needed, send adopt to parent 00892 int intermediatePos = iit - subspace.intermediateNodes.begin(); 00893 int parentPos = intermediatePos/maxChildren -1; 00894 if( parentPos >= 0 && !subspace.intermediateNodes[parentPos].node.isUnspecified() ){ 00895 PubSubAdoptChildCall* adoptCall = new PubSubAdoptChildCall("Adopt (intermediate) Node"); 00896 adoptCall->setSubspaceId( intermediateResp->getSubspaceId() ); 00897 adoptCall->setChild( iit->node ); 00898 adoptCall->setLength( PUBSUB_ADOPTCHILDCALL_L( adoptCall )); 00899 RECORD_STATS( 00900 ++numPubSubSignalingMessages; 00901 pubSubSignalingMessagesSize+= adoptCall->byteLength() 00902 ); 00903 sendUdpRpcCall( subspace.intermediateNodes[parentPos].node, adoptCall ); 00904 } 00905 00906 if( newIntermediate ){ 00907 // move one child from iNodes's parent to cache 00908 if( parentPos >= 0 ) { 00909 // parent is an intermediate node 00910 PubSubSubspaceResponsible::IntermediateNode& parent = subspace.intermediateNodes[parentPos]; 00911 if( parent.children.begin() != parent.children.end() ){ 00912 bool fixNeeded = false; 00913 if( !subspace.cachedChildren.insert( make_pair( *(parent.children.begin()), false )).second ){ 00914 fixNeeded = true; 00915 } 00916 if( !subspace.getBackupNode().isUnspecified() ){ 00917 PubSubBackupSubscriptionMessage* backupMsg = new PubSubBackupSubscriptionMessage("Backup: nodes moved to cache"); 00918 backupMsg->setSubspaceId( intermediateResp->getSubspaceId() ); 00919 backupMsg->setChild( *(parent.children.begin()) ); 00920 backupMsg->setOldParent( parent.node ); 00921 backupMsg->setLength( PUBSUB_BACKUPSUBSCRIPTION_L( backupMsg )); 00922 RECORD_STATS( 00923 ++numPubSubSignalingMessages; 00924 pubSubSignalingMessagesSize+= backupMsg->byteLength() 00925 ); 00926 sendMessageToUDP( subspace.getBackupNode(), backupMsg ); 00927 } 00928 PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Node left: moved"); 00929 goneMsg->setNode( *(parent.children.begin()) ); 00930 goneMsg->setSubspaceId( intermediateResp->getSubspaceId() ); 00931 goneMsg->setLength( PUBSUB_NODELEFT_L( goneMsg )); 00932 RECORD_STATS( 00933 ++numPubSubSignalingMessages; 00934 pubSubSignalingMessagesSize+= goneMsg->byteLength() 00935 ); 00936 sendMessageToUDP( parent.node, goneMsg ); 00937 parent.children.erase( parent.children.begin() ); 00938 if( fixNeeded ){ 00939 subspace.fixTotalChildrenCount(); 00940 } 00941 } 00942 00943 } else { 00944 // we are parent 00945 if( subspace.children.begin() != subspace.children.end() ){ 00946 bool fixNeeded = false; 00947 if( !subspace.cachedChildren.insert( make_pair( *(subspace.children.begin()), false )).second ){ 00948 fixNeeded = true; 00949 } 00950 if( !subspace.getBackupNode().isUnspecified() ){ 00951 PubSubBackupSubscriptionMessage* backupMsg = new PubSubBackupSubscriptionMessage("Backup: nodes moved to cache"); 00952 backupMsg->setSubspaceId( intermediateResp->getSubspaceId() ); 00953 backupMsg->setChild( *(subspace.children.begin()) ); 00954 backupMsg->setOldParent( thisNode ); 00955 backupMsg->setLength( PUBSUB_BACKUPSUBSCRIPTION_L( backupMsg )); 00956 RECORD_STATS( 00957 ++numPubSubSignalingMessages; 00958 pubSubSignalingMessagesSize+= backupMsg->byteLength() 00959 ); 00960 sendMessageToUDP( subspace.getBackupNode(), backupMsg ); 00961 } 00962 subspace.children.erase( *(subspace.children.begin()) ); 00963 if( fixNeeded ){ 00964 subspace.fixTotalChildrenCount(); 00965 } 00966 } 00967 } 00968 } else { 00969 // send adopt for all children intermediates 00970 for( int pos = (intermediatePos+1) * maxChildren; pos < (int) subspace.intermediateNodes.size() && 00971 pos < (intermediatePos+2) * maxChildren; ++pos ){ 00972 if( subspace.intermediateNodes[pos].node.isUnspecified() ) continue; 00973 PubSubAdoptChildCall* adoptCall = new PubSubAdoptChildCall("Adopt (intermediate) Node"); 00974 adoptCall->setSubspaceId( intermediateResp->getSubspaceId() ); 00975 adoptCall->setChild( subspace.intermediateNodes[pos].node ); 00976 adoptCall->setLength( PUBSUB_ADOPTCHILDCALL_L( adoptCall )); 00977 RECORD_STATS( 00978 ++numPubSubSignalingMessages; 00979 pubSubSignalingMessagesSize+= adoptCall->byteLength() 00980 ); 00981 sendUdpRpcCall( iit->node, adoptCall ); 00982 } 00983 } 00984 00985 // move as many cached children to the new node as possible 00986 std::map<NodeHandle,bool>::iterator childIt; 00987 for( childIt = subspace.cachedChildren.begin(); childIt != subspace.cachedChildren.end(); ++childIt ){ 00988 if( childIt->second ) continue; 00989 PubSubAdoptChildCall* adoptCall = new PubSubAdoptChildCall("Adopt Node"); 00990 adoptCall->setSubspaceId( intermediateResp->getSubspaceId() ); 00991 adoptCall->setChild( childIt->first ); 00992 adoptCall->setLength( PUBSUB_ADOPTCHILDCALL_L( adoptCall )); 00993 RECORD_STATS( 00994 ++numPubSubSignalingMessages; 00995 pubSubSignalingMessagesSize+= adoptCall->byteLength() 00996 ); 00997 sendUdpRpcCall( intermediateResp->getSrcNode(), adoptCall ); 00998 childIt->second = true; 00999 if( (unsigned int) maxChildren == ++(iit->waitingChildren) ) break; 01000 } 01001 }
void PubSubMMOG::handleAdoptChildCall | ( | PubSubAdoptChildCall * | adoptCall | ) | [protected] |
Referenced by handleRpc().
01004 { 01005 std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it; 01006 it = intermediateSubspaces.find( PubSubSubspaceId(adoptCall->getSubspaceId(), numSubspaces) ); 01007 if( it == intermediateSubspaces.end() ) { 01008 EV << "PubSubMMOG::handleIntermediateResponse @ " << thisNode << "\n" 01009 << " Received Intermediate Response for unknown Subspace!\n"; 01010 cancelAndDelete( adoptCall ); 01011 return; 01012 } 01013 01014 it->second.addChild( adoptCall->getChild() ); 01015 PubSubAdoptChildResponse* adoptResp = new PubSubAdoptChildResponse("I adopted child"); 01016 adoptResp->setSubspaceId( adoptCall->getSubspaceId() ); 01017 adoptResp->setChild( adoptCall->getChild() ); 01018 adoptResp->setLength( PUBSUB_ADOPTCHILDRESPONSE_L( adoptResp )); 01019 RECORD_STATS( 01020 ++numPubSubSignalingMessages; 01021 pubSubSignalingMessagesSize+= adoptResp->byteLength() 01022 ); 01023 sendRpcResponse( adoptCall, adoptResp ); 01024 }
void PubSubMMOG::handleAdoptChildResponse | ( | PubSubAdoptChildResponse * | adoptResp | ) | [protected] |
Referenced by handleRpcResponse().
01027 { 01028 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01029 it = responsibleSubspaces.find( PubSubSubspaceId(adoptResp->getSubspaceId(), numSubspaces) ); 01030 if( it == responsibleSubspaces.end() ) { 01031 EV << "PubSubMMOG::handleAdoptChildResponse @ " << thisNode << "\n" 01032 << " Received AdoptChild Response for unknown Subspace!\n"; 01033 return; 01034 } 01035 01036 // FIXME: just for testing 01037 PubSubSubspaceResponsible& subspace = it->second; 01038 int iii = subspace.getTotalChildrenCount(); 01039 subspace.fixTotalChildrenCount(); 01040 if( iii != subspace.getTotalChildrenCount() ){ 01041 opp_error("Huh?"); 01042 } 01043 01044 // Find intermediate node in subspace 01045 deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit; 01046 for( iit = it->second.intermediateNodes.begin(); iit != it->second.intermediateNodes.end(); ++iit ){ 01047 if( !iit->node.isUnspecified() && iit->node == adoptResp->getSrcNode() ){ 01048 01049 // if adoption was for a child intermediate node, nothing is to be done 01050 int intermediatePos = iit - it->second.intermediateNodes.begin(); 01051 for( int pos = (intermediatePos+1) * maxChildren; pos < (int) it->second.intermediateNodes.size() && 01052 pos < (intermediatePos+2) * maxChildren; ++pos ) 01053 { 01054 if( !it->second.intermediateNodes[pos].node.isUnspecified() && 01055 adoptResp->getChild() == it->second.intermediateNodes[pos].node ){ 01056 return; 01057 } 01058 } 01059 01060 // child is a "real" child->remove it from cache 01061 if( !it->second.cachedChildren.erase( adoptResp->getChild() ) ){ 01062 // if node got deleted in the meantime, inform parent... 01063 PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Node left Subspace"); 01064 goneMsg->setNode( adoptResp->getChild() ); 01065 goneMsg->setSubspaceId( it->second.getId().getId() ); 01066 goneMsg->setLength( PUBSUB_NODELEFT_L( goneMsg )); 01067 RECORD_STATS( 01068 ++numPubSubSignalingMessages; 01069 pubSubSignalingMessagesSize+= goneMsg->byteLength() 01070 ); 01071 sendMessageToUDP( adoptResp->getSrcNode(), goneMsg ); 01072 return; 01073 } 01074 01075 // move child to intermediate node's childrenlist 01076 if( !iit->children.insert( adoptResp->getChild() ).second ){ 01077 // Node was already in children list, fix children count 01078 subspace.fixTotalChildrenCount(); 01079 } 01080 iit->waitingChildren--; 01081 01082 // FIXME: just for testing 01083 PubSubSubspaceResponsible& subspace = it->second; 01084 int iii = subspace.getTotalChildrenCount(); 01085 subspace.fixTotalChildrenCount(); 01086 if( iii != subspace.getTotalChildrenCount() ){ 01087 opp_error("Huh?"); 01088 } 01089 01090 // Inform Backup 01091 if( !it->second.getBackupNode().isUnspecified() ){ 01092 PubSubBackupSubscriptionMessage* backupMsg = new PubSubBackupSubscriptionMessage("Backup: node got a new parent"); 01093 backupMsg->setSubspaceId( adoptResp->getSubspaceId() ); 01094 backupMsg->setChild( adoptResp->getChild() ); 01095 backupMsg->setParent( adoptResp->getSrcNode() ); 01096 backupMsg->setLength( PUBSUB_BACKUPSUBSCRIPTION_L( backupMsg )); 01097 RECORD_STATS( 01098 ++numPubSubSignalingMessages; 01099 pubSubSignalingMessagesSize+= backupMsg->byteLength() 01100 ); 01101 sendMessageToUDP( it->second.getBackupNode(), backupMsg ); 01102 return; 01103 } 01104 } 01105 } 01106 01107 EV << "PubSubMMOG::handleAdoptChildResponse @ " << thisNode << "\n" 01108 << " Received AdoptChild Response for unknown child!\n"; 01109 }
void PubSubMMOG::handlePingCall | ( | PubSubPingCall * | hearbeatCall | ) | [protected] |
Referenced by handleRpc().
01112 { 01113 int subspaceId = pingCall->getSubspaceId(); 01114 01115 if( pingCall->getPingType() == PUBSUB_PING_BACKUP ){ 01116 // reset heartbeat timer 01117 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01118 it = backupSubspaces.find( PubSubSubspaceId(pingCall->getSubspaceId(), numSubspaces) ); 01119 if( it == backupSubspaces.end() ) { 01120 EV << "PubSubMMOG::handlePingCall @ " << thisNode << "\n" 01121 << " Received PingCall for unknown Subspace!\n"; 01122 // FIXME: Somebody thinks we are his backup. What shall we do? 01123 } else { 01124 it->second.resetHeartbeatFailCount(); 01125 startTimer( it->second.getHeartbeatTimer() ); 01126 } 01127 } 01128 01129 PubSubPingResponse* pingResp = new PubSubPingResponse("PingResponse"); 01130 pingResp->setSubspaceId( subspaceId ); 01131 pingResp->setLength( PUBSUB_PINGRESPONSE_L( pingResp )); 01132 RECORD_STATS( 01133 ++numPubSubSignalingMessages; 01134 pubSubSignalingMessagesSize+= pingResp->byteLength() 01135 ); 01136 sendRpcResponse( pingCall, pingResp ); 01137 }
void PubSubMMOG::handlePingResponse | ( | PubSubPingResponse * | pingResp | ) | [protected] |
void PubSubMMOG::takeOverNewSubspace | ( | PubSubSubspaceId | subspaceId | ) | [protected] |
Referenced by handleTakeOver().
01144 { 01145 // create a new subspace 01146 PubSubSubspaceResponsible subspace( subspaceId ); 01147 takeOverSubspace( subspace, true ); 01148 }
void PubSubMMOG::takeOverSubspace | ( | PubSubSubspaceResponsible & | subspaceId, | |
bool | isNew = false | |||
) | [protected] |
Referenced by handleParentTimeout(), and takeOverNewSubspace().
01151 { 01152 const PubSubSubspaceId& subspaceId = subspace.getId(); 01153 int intId = subspaceId.getId(); 01154 01155 subspace.fixTotalChildrenCount(); 01156 01157 NodeHandle oldNode = subspace.getResponsibleNode(); 01158 01159 // insert subspace into responsible list 01160 subspace.setResponsibleNode( thisNode ); 01161 responsibleSubspaces.insert( make_pair(subspaceId, subspace) ); 01162 01163 // request backup 01164 PubSubHelpCall* helpCall = new PubSubHelpCall("I need a backup node"); 01165 helpCall->setHelpType( PUBSUB_BACKUP ); 01166 helpCall->setSubspaceId( intId ); 01167 helpCall->setLength( PUBSUB_HELPCALL_L( helpCall )); 01168 RECORD_STATS( 01169 ++numPubSubSignalingMessages; 01170 pubSubSignalingMessagesSize+= helpCall->byteLength() 01171 ); 01172 sendUdpRpcCall( lobbyServer, helpCall ); 01173 01174 if( !isNew ) { 01175 PubSubReplacementMessage* repMsg = new PubSubReplacementMessage("I replaced the responsible node"); 01176 repMsg->setSubspaceId( intId ); 01177 repMsg->setNewResponsibleNode( thisNode ); 01178 repMsg->setLength( PUBSUB_REPLACEMENT_L( repMsg )); 01179 01180 // Inform children and lobbyserver about takeover 01181 sendMessageToChildren( subspace, repMsg, NULL, repMsg ); 01182 sendMessageToUDP( lobbyServer, repMsg ); 01183 01184 // inform lobby server over failed node 01185 PubSubFailedNodeMessage* failedNode = new PubSubFailedNodeMessage("Node failed"); 01186 failedNode->setFailedNode( oldNode ); 01187 failedNode->setLength( PUBSUB_FAILEDNODE_L( failedNode )); 01188 RECORD_STATS( 01189 ++numPubSubSignalingMessages; 01190 pubSubSignalingMessagesSize+= failedNode->byteLength() 01191 ); 01192 sendMessageToUDP( lobbyServer, failedNode ); 01193 } 01194 }
void PubSubMMOG::sendHearbeatToChildren | ( | ) | [protected] |
Referenced by handleTimerEvent().
01197 { 01198 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01199 for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it) { 01200 PubSubPingCall* bHeartbeat = new PubSubPingCall("Heartbeat Backup"); 01201 bHeartbeat->setPingType( PUBSUB_PING_BACKUP ); 01202 bHeartbeat->setSubspaceId( it->second.getId().getId() ); 01203 bHeartbeat->setLength( PUBSUB_PINGCALL_L( bHeartbeat )); 01204 01205 PubSubPingCall* iHeartbeat = new PubSubPingCall("Heartbeat Intermediate"); 01206 iHeartbeat->setPingType( PUBSUB_PING_INTERMEDIATE ); 01207 iHeartbeat->setSubspaceId( it->second.getId().getId() ); 01208 iHeartbeat->setLength( PUBSUB_PINGCALL_L( iHeartbeat )); 01209 01210 sendMessageToChildren( it->second, iHeartbeat, bHeartbeat, NULL); 01211 delete bHeartbeat; 01212 delete iHeartbeat; 01213 } 01214 }
void PubSubMMOG::sendPingToChildren | ( | ) | [protected] |
Referenced by handleTimerEvent().
01217 { 01218 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01219 for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it) { 01220 PubSubPingCall* heartbeat = new PubSubPingCall("Ping"); 01221 heartbeat->setPingType( PUBSUB_PING_CHILD ); 01222 heartbeat->setSubspaceId( it->second.getId().getId() ); 01223 heartbeat->setLength( PUBSUB_PINGCALL_L( heartbeat )); 01224 sendMessageToChildren( it->second, NULL, NULL, heartbeat ); 01225 delete heartbeat; 01226 } 01227 }
void PubSubMMOG::handleParentTimeout | ( | PubSubTimer * | timer | ) | [protected] |
Referenced by handleTimerEvent().
01230 { 01231 // our parent timed out. we have to take over the subspace... 01232 PubSubSubspaceId subspaceId(timer->getSubspaceId(), numSubspaces); 01233 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01234 it = backupSubspaces.find( subspaceId ); 01235 if( it == backupSubspaces.end() ) { 01236 delete timer; 01237 return; 01238 } 01239 01240 // increase fail count; if to high, take over subspace 01241 it->second.incHeartbeatFailCount(); 01242 if( it->second.getHeartbeatFailCount() > 1 ) { // FIXME: make it a parameter 01243 01244 // Delete Timer 01245 cancelAndDelete( timer ); 01246 it->second.setHeartbeatTimer( NULL ); 01247 01248 // Take over Subspace 01249 takeOverSubspace( it->second ); 01250 backupSubspaces.erase( it ); 01251 01252 } else { 01253 startTimer( timer ); 01254 } 01255 }
void PubSubMMOG::handleBackupCallTimeout | ( | PubSubBackupCall * | backupCall, | |
const TransportAddress & | oldNode | |||
) | [protected] |
Referenced by handleRpcTimeout().
01258 { 01259 // FIXME: cast oldNode to NodeHandle 01260 // Inform Lobbyserver over failed node 01261 PubSubFailedNodeMessage* failedNode = new PubSubFailedNodeMessage("Node failed"); 01262 failedNode->setFailedNode( oldNode ); 01263 failedNode->setLength( PUBSUB_FAILEDNODE_L( failedNode )); 01264 RECORD_STATS( 01265 ++numPubSubSignalingMessages; 01266 pubSubSignalingMessagesSize+= failedNode->byteLength() 01267 ); 01268 sendMessageToUDP( lobbyServer, failedNode ); 01269 01270 // Request new Backup 01271 PubSubHelpCall* helpCall = new PubSubHelpCall("I need a backup node"); 01272 helpCall->setHelpType( PUBSUB_BACKUP ); 01273 helpCall->setSubspaceId( backupCall->getSubspaceId() ); 01274 helpCall->setLength( PUBSUB_HELPCALL_L( helpCall )); 01275 RECORD_STATS( 01276 ++numPubSubSignalingMessages; 01277 pubSubSignalingMessagesSize+= helpCall->byteLength() 01278 ); 01279 sendUdpRpcCall( lobbyServer, helpCall ); 01280 01281 // find appropriate subspace and mark backup as failed 01282 PubSubSubspaceId subspaceId(backupCall->getSubspaceId(), numSubspaces); 01283 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01284 it = responsibleSubspaces.find( subspaceId ); 01285 if( it == responsibleSubspaces.end() ) { 01286 return; 01287 } 01288 it->second.setBackupNode( NodeHandle::UNSPECIFIED_NODE ); 01289 }
void PubSubMMOG::handlePingCallTimeout | ( | PubSubPingCall * | pingCall, | |
const TransportAddress & | oldNode | |||
) | [protected] |
Referenced by handleRpcTimeout().
01292 { 01293 // Inform Lobbyserver over failed node 01294 const NodeHandle& oldNodeHandle = dynamic_cast<const NodeHandle&>(oldNode); 01295 // FIXME: use oldNodeHandle instead of oldNode 01296 PubSubFailedNodeMessage* failedNode = new PubSubFailedNodeMessage("Node failed"); 01297 failedNode->setLength( PUBSUB_FAILEDNODE_L( failedNode )); 01298 RECORD_STATS( 01299 ++numPubSubSignalingMessages; 01300 pubSubSignalingMessagesSize+= failedNode->byteLength() 01301 ); 01302 failedNode->setFailedNode( oldNode ); 01303 sendMessageToUDP( lobbyServer, failedNode ); 01304 01305 // find appropriate subspace 01306 PubSubSubspaceId subspaceId(pingCall->getSubspaceId(), numSubspaces); 01307 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01308 it = responsibleSubspaces.find( subspaceId ); 01309 if( it == responsibleSubspaces.end() ) { 01310 return; 01311 } 01312 PubSubSubspaceResponsible& subspace = it->second; 01313 01314 if( pingCall->getPingType() == PUBSUB_PING_CHILD ){ 01315 // remove child 01316 unsubscribeChild( oldNodeHandle, subspace ); 01317 01318 } else if( pingCall->getPingType() == PUBSUB_PING_BACKUP ){ 01319 01320 // if we didn't already have (or asked for) a new backup 01321 if( !subspace.getBackupNode().isUnspecified() && 01322 subspace.getBackupNode() == oldNodeHandle ) 01323 { 01324 // our backup timed out. we have to request a new one... 01325 // delete old backup entry 01326 subspace.setBackupNode( NodeHandle::UNSPECIFIED_NODE ); 01327 01328 // Request new Backup 01329 PubSubHelpCall* helpCall = new PubSubHelpCall("I need a backup node"); 01330 helpCall->setHelpType( PUBSUB_BACKUP ); 01331 helpCall->setSubspaceId( pingCall->getSubspaceId() ); 01332 helpCall->setLength( PUBSUB_HELPCALL_L( helpCall )); 01333 RECORD_STATS( 01334 ++numPubSubSignalingMessages; 01335 pubSubSignalingMessagesSize+= helpCall->byteLength() 01336 ); 01337 sendUdpRpcCall( lobbyServer, helpCall ); 01338 } 01339 01340 } else if( pingCall->getPingType() == PUBSUB_PING_INTERMEDIATE ){ 01341 // one intermediate node timed out. we have to request a new one... 01342 // delete old intermediate entry 01343 deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit; 01344 for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){ 01345 if( !iit->node.isUnspecified() && oldNode == iit->node ) break; 01346 } 01347 if( iit == subspace.intermediateNodes.end() ) return; 01348 01349 NodeHandle oldNode = iit->node; 01350 iit->node = NodeHandle::UNSPECIFIED_NODE; 01351 01352 // inform Backup 01353 if( !subspace.getBackupNode().isUnspecified() ){ 01354 PubSubBackupIntermediateMessage* backupMsg = new PubSubBackupIntermediateMessage("Backup: Intermediate failed"); 01355 backupMsg->setSubspaceId( pingCall->getSubspaceId() ); 01356 backupMsg->setPos( iit - it->second.intermediateNodes.begin() ); 01357 backupMsg->setLength( PUBSUB_BACKUPINTERMEDIATE_L( backupMsg )); 01358 RECORD_STATS( 01359 ++numPubSubSignalingMessages; 01360 pubSubSignalingMessagesSize+= backupMsg->byteLength() 01361 ); 01362 sendMessageToUDP( subspace.getBackupNode(), backupMsg ); 01363 } 01364 01365 bool fixNeeded = false; 01366 // Take over all children until new intermediate is found. 01367 set<NodeHandle>::iterator childIt; 01368 for( childIt = iit->children.begin(); childIt != iit->children.end(); ++childIt ){ 01369 if( !subspace.cachedChildren.insert( make_pair(*childIt, false)).second ){ 01370 fixNeeded = true; 01371 } 01372 01373 // Inform Backup 01374 if( !subspace.getBackupNode().isUnspecified() ){ 01375 PubSubBackupSubscriptionMessage* backupMsg = new PubSubBackupSubscriptionMessage("Backup: nodes moved to cache"); 01376 backupMsg->setSubspaceId( pingCall->getSubspaceId() ); 01377 backupMsg->setChild( *childIt ); 01378 backupMsg->setOldParent( oldNodeHandle ); 01379 backupMsg->setLength( PUBSUB_BACKUPSUBSCRIPTION_L( backupMsg )); 01380 RECORD_STATS( 01381 ++numPubSubSignalingMessages; 01382 pubSubSignalingMessagesSize+= backupMsg->byteLength() 01383 ); 01384 sendMessageToUDP( subspace.getBackupNode(), backupMsg ); 01385 } 01386 } 01387 iit->children.clear(); 01388 if( fixNeeded ) subspace.fixTotalChildrenCount(); 01389 01390 // inform parent of intermediate node 01391 int parentPos = (iit - subspace.intermediateNodes.begin())/maxChildren -1; 01392 if( parentPos >= 0 ){ 01393 PubSubSubspaceResponsible::IntermediateNode& parent = subspace.intermediateNodes[parentPos]; 01394 if( !parent.node.isUnspecified() ){ 01395 PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Intermediate left Subspace"); 01396 goneMsg->setNode( oldNodeHandle ); 01397 goneMsg->setSubspaceId( subspace.getId().getId() ); 01398 goneMsg->setLength( PUBSUB_NODELEFT_L( goneMsg )); 01399 RECORD_STATS( 01400 ++numPubSubSignalingMessages; 01401 pubSubSignalingMessagesSize+= goneMsg->byteLength() 01402 ); 01403 sendMessageToUDP( parent.node, goneMsg ); 01404 } 01405 } 01406 01407 // Request new Intermediate 01408 PubSubHelpCall* helpCall = new PubSubHelpCall("I need an intermediate node"); 01409 helpCall->setHelpType( PUBSUB_INTERMEDIATE ); 01410 helpCall->setSubspaceId( pingCall->getSubspaceId() ); 01411 helpCall->setLength( PUBSUB_HELPCALL_L( helpCall )); 01412 RECORD_STATS( 01413 ++numPubSubSignalingMessages; 01414 pubSubSignalingMessagesSize+= helpCall->byteLength() 01415 ); 01416 sendUdpRpcCall( lobbyServer, helpCall ); 01417 } 01418 // FIXME: just for testing 01419 int iii = subspace.getTotalChildrenCount(); 01420 subspace.fixTotalChildrenCount(); 01421 if( iii != subspace.getTotalChildrenCount() ){ 01422 opp_error("Huh?"); 01423 } 01424 01425 }
void PubSubMMOG::handleSubscriptionCallTimeout | ( | PubSubSubscriptionCall * | subscriptionCall, | |
const TransportAddress & | oldNode | |||
) | [protected] |
Referenced by handleRpcTimeout().
01428 { 01429 // FIXME: cast oldNode to NodeHandle 01430 // our subscription call timed out. This means the responsible node is dead... 01431 // Inform Lobbyserver over failed node 01432 PubSubFailedNodeMessage* failedNode = new PubSubFailedNodeMessage("Node failed"); 01433 failedNode->setFailedNode( oldNode ); 01434 failedNode->setLength( PUBSUB_FAILEDNODE_L( failedNode )); 01435 RECORD_STATS( 01436 ++numPubSubSignalingMessages; 01437 pubSubSignalingMessagesSize+= failedNode->byteLength() 01438 ); 01439 sendMessageToUDP( lobbyServer, failedNode ); 01440 01441 // Ask for new responsible node 01442 PubSubResponsibleNodeCall* respCall = new PubSubResponsibleNodeCall("Request Responsible NodeHandle"); 01443 PubSubSubspaceId subspaceId( subscriptionCall->getSubspaceId(), numSubspaces); 01444 respCall->setSubspacePos( Vector2D(subspaceId.getX(), subspaceId.getY()) ); 01445 respCall->setLength( PUBSUB_RESPONSIBLENODECALL_L( respCall )); 01446 RECORD_STATS( 01447 ++numPubSubSignalingMessages; 01448 pubSubSignalingMessagesSize+= respCall->byteLength() 01449 ); 01450 sendUdpRpcCall( lobbyServer, respCall, NULL, 5, 5 ); // FIXME: Make it a parameter... 01451 }
void PubSubMMOG::handleUnsubscriptionMessage | ( | PubSubUnsubscriptionMessage * | unsMsg | ) | [protected] |
Referenced by handleUDPMessage().
00412 { 00413 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 00414 it = responsibleSubspaces.find( PubSubSubspaceId(unsMsg->getSubspaceId(), numSubspaces) ); 00415 00416 if( it != responsibleSubspaces.end() ) { 00417 unsubscribeChild( unsMsg->getSrc(), it->second ); 00418 } 00419 }
void PubSubMMOG::handleNodeLeftMessage | ( | PubSubNodeLeftMessage * | leftMsg | ) | [protected] |
Referenced by handleUDPMessage().
00422 { 00423 std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it; 00424 it = intermediateSubspaces.find( PubSubSubspaceId(leftMsg->getSubspaceId(), numSubspaces) ); 00425 00426 if( it == intermediateSubspaces.end() ) return; 00427 00428 it->second.removeChild( leftMsg->getNode() ); 00429 }
void PubSubMMOG::handleReplacementMessage | ( | PubSubReplacementMessage * | replaceMsg | ) | [protected] |
Referenced by handleUDPMessage().
01454 { 01455 PubSubSubspaceId subspaceId(replaceMsg->getSubspaceId(), numSubspaces); 01456 01457 // There's a new responsible node for a subspace 01458 // Replace the old one in the intermediateSubspaces map... 01459 std::map<PubSubSubspaceId, PubSubSubspaceIntermediate>::iterator it; 01460 it = intermediateSubspaces.find( subspaceId ); 01461 if( it != intermediateSubspaces.end() ) { 01462 it->second.setResponsibleNode( replaceMsg->getNewResponsibleNode() ); 01463 } 01464 01465 // ... and in the subsribed subspaces list 01466 std::list<PubSubSubspace>::iterator iit; 01467 for( iit = subscribedSubspaces.begin(); iit != subscribedSubspaces.end(); ++iit ){ 01468 if( iit->getId() == subspaceId ) { 01469 iit->setResponsibleNode( replaceMsg->getNewResponsibleNode() ); 01470 return; 01471 } 01472 } 01473 }
void PubSubMMOG::handleReleaseIntermediate | ( | PubSubReleaseIntermediateMessage * | releaseMsg | ) | [protected] |
Referenced by handleUDPMessage().
01476 { 01477 PubSubSubspaceId subspaceId(releaseMsg->getSubspaceId(), numSubspaces); 01478 intermediateSubspaces.erase( subspaceId ); 01479 }
void PubSubMMOG::handleIntermediateBackup | ( | PubSubBackupIntermediateMessage * | backupMsg | ) | [protected] |
Referenced by handleUDPMessage().
01482 { 01483 // find appropriate subspace 01484 PubSubSubspaceId subspaceId(backupMsg->getSubspaceId(), numSubspaces); 01485 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01486 it = backupSubspaces.find( subspaceId ); 01487 if( it == backupSubspaces.end() ) { 01488 return; 01489 } 01490 01491 if( backupMsg->getPos() >= (int) it->second.intermediateNodes.size() ){ 01492 it->second.intermediateNodes.resize( backupMsg->getPos() + 1 ); 01493 } 01494 it->second.intermediateNodes[ backupMsg->getPos() ].node = backupMsg->getNode(); 01495 }
void PubSubMMOG::handleSubscriptionBackup | ( | PubSubBackupSubscriptionMessage * | backupMsg | ) | [protected] |
Referenced by handleUDPMessage().
01498 { 01499 // Note: this funktion may break subspace's tatalChildrenCall 01500 // You have to use fixTotalChildrenCount before using the subspace 01501 // find appropriate subspace 01502 PubSubSubspaceId subspaceId(backupMsg->getSubspaceId(), numSubspaces); 01503 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01504 it = backupSubspaces.find( subspaceId ); 01505 if( it == backupSubspaces.end() ) { 01506 return; 01507 } 01508 PubSubSubspaceResponsible& subspace = it->second; 01509 01510 deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit; 01511 01512 if( !backupMsg->getOldParent().isUnspecified() ){ 01513 // oldParent set -> move child 01514 if( backupMsg->getOldParent() == subspace.getResponsibleNode() ){ 01515 // direct child -> cache 01516 subspace.removeChild( backupMsg->getChild() ); 01517 subspace.cachedChildren.insert(make_pair( backupMsg->getChild(), false) ); 01518 01519 } else { 01520 // from I -> chache 01521 for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){ 01522 // if( !iit->node.isUnspecified() && iit->node == backupMsg->getOldParent() ){ 01523 iit->children.erase( backupMsg->getChild() ); 01524 // } 01525 } 01526 subspace.cachedChildren.insert(make_pair( backupMsg->getChild(), false) ); 01527 } 01528 } else if( backupMsg->getParent().isUnspecified() ){ 01529 // parent not set -> new child to chache 01530 subspace.cachedChildren.insert(make_pair( backupMsg->getChild(), false) ); 01531 01532 } else if( backupMsg->getParent() == subspace.getResponsibleNode() ){ 01533 // new direct child 01534 subspace.addChild( backupMsg->getChild() ); 01535 } else { 01536 // move child from cache to intermediate 01537 subspace.cachedChildren.erase( backupMsg->getChild() ); 01538 01539 for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){ 01540 if( !iit->node.isUnspecified() && iit->node == backupMsg->getParent() ){ 01541 iit->children.insert( backupMsg->getChild() ); 01542 } 01543 } 01544 // FIXME: check for errors 01545 } 01546 }
void PubSubMMOG::handleUnsubscribeBackup | ( | PubSubBackupUnsubscribeMessage * | backupMsg | ) | [protected] |
Referenced by handleUDPMessage().
01549 { 01550 // Note: this funktion may break subspace's tatalChildrenCall 01551 // You have to use fixTotalChildrenCount before using the subspace 01552 // find appropriate subspace 01553 PubSubSubspaceId subspaceId(backupMsg->getSubspaceId(), numSubspaces); 01554 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01555 it = backupSubspaces.find( subspaceId ); 01556 if( it == backupSubspaces.end() ) { 01557 return; 01558 } 01559 PubSubSubspaceResponsible& subspace = it->second; 01560 01561 deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit; 01562 set<NodeHandle>::iterator childIt; 01563 01564 if( !subspace.removeChild(backupMsg->getChild()) && !subspace.cachedChildren.erase( backupMsg->getChild()) ){ 01565 for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){ 01566 iit->children.erase( backupMsg->getChild() ); 01567 } 01568 } 01569 if( !backupMsg->getIntermediate().isUnspecified() ){ 01570 // remove intermediate 01571 for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){ 01572 if( !iit->node.isUnspecified() && iit->node == backupMsg->getIntermediate() ){ 01573 for( childIt = iit->children.begin(); childIt != iit->children.end(); ++childIt ){ 01574 // FIXME: note really stable. let the resp node inform us about child moves 01575 // remove children of last intermediate 01576 if( subspace.getNumChildren() + subspace.getNumIntermediates() < maxChildren ){ 01577 // we have room for the child 01578 subspace.children.insert( *childIt ); 01579 } else { 01580 // Node has to go to some intermediate 01581 // cache it 01582 subspace.cachedChildren.insert( make_pair(*childIt, true) ); 01583 } 01584 } 01585 subspace.intermediateNodes.erase( iit ); 01586 break; 01587 } 01588 } 01589 } 01590 }
void PubSubMMOG::unsubscribeChild | ( | const NodeHandle & | node, | |
PubSubSubspaceResponsible & | subspace | |||
) | [protected] |
Referenced by handlePingCallTimeout(), and handleUnsubscriptionMessage().
01593 { 01594 PubSubBackupUnsubscribeMessage* backupMsg = new PubSubBackupUnsubscribeMessage("Backup: node left subspace"); 01595 backupMsg->setChild( node ); 01596 backupMsg->setSubspaceId( subspace.getId().getId() ); 01597 PubSubSubspaceResponsible::IntermediateNode* iNode = subspace.removeAnyChild( node ); 01598 if( iNode && !iNode->node.isUnspecified() ) { 01599 // Node is handled by an intermediate node, inform him 01600 PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Node left Subspace"); 01601 goneMsg->setNode( node ); 01602 goneMsg->setSubspaceId( subspace.getId().getId() ); 01603 goneMsg->setLength( PUBSUB_NODELEFT_L( goneMsg )); 01604 RECORD_STATS( 01605 ++numPubSubSignalingMessages; 01606 pubSubSignalingMessagesSize+= goneMsg->byteLength() 01607 ); 01608 sendMessageToUDP( iNode->node, goneMsg ); 01609 } 01610 if ( subspace.getTotalChildrenCount() < ( maxChildren - 1) * subspace.getNumIntermediates()){// FIXME: parameter when to start cleanup? 01611 // Too many "free" slots, remove one intermediate node 01612 PubSubSubspaceResponsible::IntermediateNode& liNode = subspace.intermediateNodes.back(); 01613 if( !liNode.node.isUnspecified() ){ 01614 // Inform node + lobby about release from intermediate node status 01615 PubSubReleaseIntermediateMessage* releaseMsg = new PubSubReleaseIntermediateMessage("I don't need you anymore as intermediate"); 01616 releaseMsg->setSubspaceId( subspace.getId().getId() ); 01617 releaseMsg->setLength( PUBSUB_RELEASEINTERMEDIATE_L( releaseMsg )); 01618 RECORD_STATS( 01619 ++numPubSubSignalingMessages; 01620 pubSubSignalingMessagesSize+= releaseMsg->byteLength() 01621 ); 01622 sendMessageToUDP( liNode.node, releaseMsg ); 01623 01624 PubSubHelpReleaseMessage* helpRMsg = new PubSubHelpReleaseMessage("node is not my intermediate anymore"); 01625 helpRMsg->setSubspaceId( subspace.getId().getId() ); 01626 helpRMsg->setNode( liNode.node ); 01627 helpRMsg->setLength( PUBSUB_HELPRELEASE_L( helpRMsg )); 01628 RECORD_STATS( 01629 ++numPubSubSignalingMessages; 01630 pubSubSignalingMessagesSize+= helpRMsg->byteLength() 01631 ); 01632 sendMessageToUDP( lobbyServer, helpRMsg ); 01633 01634 // inform parent of intermediate node 01635 int parentPos = (subspace.intermediateNodes.size()-1)/maxChildren -1; 01636 if( parentPos >= 0 ){ 01637 PubSubSubspaceResponsible::IntermediateNode& parent = subspace.intermediateNodes[parentPos]; 01638 if( !parent.node.isUnspecified() ){ 01639 PubSubNodeLeftMessage* goneMsg = new PubSubNodeLeftMessage("Intermediate left Subspace"); 01640 goneMsg->setNode( liNode.node ); 01641 goneMsg->setSubspaceId( subspace.getId().getId() ); 01642 goneMsg->setLength( PUBSUB_NODELEFT_L( goneMsg )); 01643 RECORD_STATS( 01644 ++numPubSubSignalingMessages; 01645 pubSubSignalingMessagesSize+= goneMsg->byteLength() 01646 ); 01647 sendMessageToUDP( parent.node, goneMsg ); 01648 } 01649 } 01650 } 01651 01652 bool fixNeeded = false; 01653 set<NodeHandle>::iterator childIt; 01654 for( childIt = liNode.children.begin(); childIt != liNode.children.end(); ++childIt ){ 01655 // remove children of last intermediate 01656 if( subspace.getNumChildren() + subspace.getNumIntermediates() < maxChildren ){ 01657 // we have room for the child 01658 if( !subspace.children.insert( *childIt ).second ) fixNeeded = true; 01659 01660 //FIXME: send backup new->toMe 01661 } else { 01662 // Node has to go to some intermediate 01663 // find intermediate with free capacities 01664 PubSubSubspaceResponsible::IntermediateNode* newINode; 01665 newINode = subspace.getNextFreeIntermediate(); 01666 01667 if( newINode && newINode->node != liNode.node ){ 01668 // cache it 01669 if( !subspace.cachedChildren.insert( make_pair(*childIt, true) ).second ) fixNeeded = true; 01670 //FIXME: send backup new->toCache 01671 01672 ++(newINode->waitingChildren); 01673 01674 // let him adopt the child 01675 PubSubAdoptChildCall* adoptCall = new PubSubAdoptChildCall("Adopt Node"); 01676 adoptCall->setSubspaceId( subspace.getId().getId() ); 01677 adoptCall->setChild( *childIt ); 01678 adoptCall->setLength( PUBSUB_ADOPTCHILDCALL_L( adoptCall )); 01679 RECORD_STATS( 01680 ++numPubSubSignalingMessages; 01681 pubSubSignalingMessagesSize+= adoptCall->byteLength() 01682 ); 01683 sendUdpRpcCall( newINode->node, adoptCall ); 01684 } else { 01685 // no intermediate found 01686 // just move child to cache and wait for a new one 01687 if( !subspace.cachedChildren.insert( make_pair(*childIt, false) ).second ) fixNeeded = true; 01688 } 01689 } 01690 } 01691 // delete node from subspace's intermediate node list 01692 subspace.intermediateNodes.pop_back(); 01693 // inform backup about deleted intermediate 01694 backupMsg->setIntermediate( liNode.node ); 01695 01696 if( fixNeeded ) subspace.fixTotalChildrenCount(); 01697 } 01698 01699 // FIXME: just for testing 01700 int iii = subspace.getTotalChildrenCount(); 01701 subspace.fixTotalChildrenCount(); 01702 if( iii != subspace.getTotalChildrenCount() ){ 01703 opp_error("Huh?"); 01704 } 01705 01706 if( !subspace.getBackupNode().isUnspecified() ){ 01707 backupMsg->setLength( PUBSUB_BACKUPUNSUBSCRIBE_L( backupMsg )); 01708 RECORD_STATS( 01709 ++numPubSubSignalingMessages; 01710 pubSubSignalingMessagesSize+= backupMsg->byteLength() 01711 ); 01712 sendMessageToUDP( subspace.getBackupNode(), backupMsg ); 01713 } else { 01714 delete backupMsg; 01715 } 01716 }
void PubSubMMOG::sendMessageToChildren | ( | PubSubSubspaceResponsible & | subspace, | |
BaseOverlayMessage * | toIntermediates, | |||
BaseOverlayMessage * | toBackup, | |||
BaseOverlayMessage * | toPlayers | |||
) | [protected] |
Referenced by sendHearbeatToChildren(), sendPingToChildren(), and takeOverSubspace().
01722 { 01723 BaseCallMessage* intermediateCall = dynamic_cast<BaseCallMessage*>(toIntermediates); 01724 BaseCallMessage* backupCall = dynamic_cast<BaseCallMessage*>(toBackup); 01725 BaseCallMessage* playerCall = dynamic_cast<BaseCallMessage*>(toPlayers); 01726 01727 std::set<NodeHandle>::iterator childIt; 01728 01729 if( toPlayers ) { 01730 // Inform all children ... 01731 for( childIt = subspace.children.begin(); childIt != subspace.children.end(); ++childIt ) { 01732 if( playerCall ){ 01733 RECORD_STATS( 01734 ++numPubSubSignalingMessages; 01735 pubSubSignalingMessagesSize+= playerCall->byteLength() 01736 ); 01737 sendUdpRpcCall( *childIt, static_cast<BaseCallMessage*>(playerCall->dup()) ); 01738 } else { 01739 RECORD_STATS( 01740 ++numPubSubSignalingMessages; 01741 pubSubSignalingMessagesSize+= toPlayers->byteLength() 01742 ); 01743 sendMessageToUDP( *childIt, static_cast<BaseOverlayMessage*>(toPlayers->dup()) ); 01744 } 01745 } 01746 // ... and all cached children ... 01747 std::map<NodeHandle, bool>::iterator cacheChildIt; 01748 for( cacheChildIt = subspace.cachedChildren.begin(); cacheChildIt != subspace.cachedChildren.end(); ++cacheChildIt ) { 01749 if( playerCall ){ 01750 RECORD_STATS( 01751 ++numPubSubSignalingMessages; 01752 pubSubSignalingMessagesSize+= playerCall->byteLength() 01753 ); 01754 sendUdpRpcCall( cacheChildIt->first, static_cast<BaseCallMessage*>(playerCall->dup()) ); 01755 } else { 01756 RECORD_STATS( 01757 ++numPubSubSignalingMessages; 01758 pubSubSignalingMessagesSize+= toPlayers->byteLength() 01759 ); 01760 sendMessageToUDP( cacheChildIt->first, static_cast<BaseOverlayMessage*>(toPlayers->dup()) ); 01761 } 01762 } 01763 } 01764 deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit; 01765 // ... all intermediate nodes ... 01766 for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ){ 01767 if( toIntermediates && !iit->node.isUnspecified() ){ 01768 if( intermediateCall ){ 01769 RECORD_STATS( 01770 ++numPubSubSignalingMessages; 01771 pubSubSignalingMessagesSize+= intermediateCall->byteLength() 01772 ); 01773 sendUdpRpcCall( iit->node, static_cast<BaseCallMessage*>(intermediateCall->dup()) ); 01774 } else { 01775 RECORD_STATS( 01776 ++numPubSubSignalingMessages; 01777 pubSubSignalingMessagesSize+= toIntermediates->byteLength() 01778 ); 01779 sendMessageToUDP( iit->node, static_cast<BaseOverlayMessage*>(toIntermediates->dup()) ); 01780 } 01781 } 01782 if( toPlayers ) { 01783 // .. and all intermediate node's children ... 01784 for( childIt = iit->children.begin(); childIt != iit->children.end(); ++childIt ){ 01785 if( playerCall ){ 01786 RECORD_STATS( 01787 ++numPubSubSignalingMessages; 01788 pubSubSignalingMessagesSize+= playerCall->byteLength() 01789 ); 01790 sendUdpRpcCall( *childIt, static_cast<BaseCallMessage*>(playerCall->dup()) ); 01791 } else { 01792 RECORD_STATS( 01793 ++numPubSubSignalingMessages; 01794 pubSubSignalingMessagesSize+= toPlayers->byteLength() 01795 ); 01796 sendMessageToUDP( *childIt, static_cast<BaseOverlayMessage*>(toPlayers->dup()) ); 01797 } 01798 } 01799 } 01800 } 01801 // ... and the backup node 01802 if( toBackup && !subspace.getBackupNode().isUnspecified() ) { 01803 if( backupCall ){ 01804 RECORD_STATS( 01805 ++numPubSubSignalingMessages; 01806 pubSubSignalingMessagesSize+= backupCall->byteLength() 01807 ); 01808 sendUdpRpcCall( subspace.getBackupNode(), static_cast<BaseCallMessage*>(backupCall->dup()) ); 01809 } else { 01810 RECORD_STATS( 01811 ++numPubSubSignalingMessages; 01812 pubSubSignalingMessagesSize+= toBackup->byteLength() 01813 ); 01814 sendMessageToUDP( subspace.getBackupNode(), static_cast<BaseOverlayMessage*>(toBackup->dup()) ); 01815 } 01816 } 01817 }
void PubSubMMOG::publishEvents | ( | ) | [protected] |
Referenced by handleTimerEvent().
01821 { 01822 // FOr all (responsible) subspaces 01823 int numRespSubspaces = responsibleSubspaces.size(); 01824 std::map<PubSubSubspaceId, PubSubSubspaceResponsible>::iterator it; 01825 for( it = responsibleSubspaces.begin(); it != responsibleSubspaces.end(); ++it ){ 01826 PubSubSubspaceResponsible& subspace = it->second; 01827 01828 // Prepare a movement list message aggregating all stored move messages 01829 PubSubMoveListMessage* moveList = new PubSubMoveListMessage("Movement list"); 01830 moveList->setTimestamp( simulation.simTime() ); 01831 moveList->setSubspaceId( subspace.getId().getId() ); 01832 moveList->setPlayerArraySize( subspace.waitingMoveMessages.size() ); 01833 moveList->setPositionArraySize( subspace.waitingMoveMessages.size() ); 01834 01835 std::deque<PubSubMoveMessage*>::iterator msgIt; 01836 int pos = 0; 01837 for( msgIt = subspace.waitingMoveMessages.begin(); msgIt != subspace.waitingMoveMessages.end(); ++msgIt ){ 01838 moveList->setPlayer( pos, (*msgIt)->getPlayer() ); 01839 moveList->setPosition( pos, (*msgIt)->getPosition() ); 01840 pos++; 01841 cancelAndDelete( *msgIt ); 01842 } 01843 subspace.waitingMoveMessages.clear(); 01844 01845 moveList->setLength( PUBSUB_MOVELIST_L( moveList )); 01846 // Send message to all direct children... 01847 for( set<NodeHandle>::iterator childIt = subspace.children.begin(); 01848 childIt != subspace.children.end(); ++childIt ) 01849 { 01850 RECORD_STATS( 01851 ++numMoveListMessages; 01852 moveListMessagesSize+= moveList->byteLength(); 01853 respMoveListMessagesSize+= (double) moveList->byteLength() / numRespSubspaces 01854 ); 01855 sendMessageToUDP( *childIt, (BaseOverlayMessage*) moveList->dup() ); 01856 } 01857 01858 //... all cached children (if messages are not too big) ... 01859 if( moveList->byteLength() < 1024 ){ // FIXME: magic number. make it a parameter, or dependant on the available bandwidth 01860 for( map<NodeHandle, bool>::iterator childIt = subspace.cachedChildren.begin(); 01861 childIt != subspace.cachedChildren.end(); ++childIt ) 01862 { 01863 RECORD_STATS( 01864 ++numMoveListMessages; 01865 moveListMessagesSize+= moveList->byteLength(); 01866 respMoveListMessagesSize+= (double) moveList->byteLength() / numRespSubspaces 01867 ); 01868 sendMessageToUDP( childIt->first, (BaseOverlayMessage*) moveList->dup() ); 01869 // ... but don't send msgs to too many cached children, as this would exhaust our bandwidth 01870 } 01871 } 01872 01873 // ... all direct intermediates and intermediates with broken parent 01874 deque<PubSubSubspaceResponsible::IntermediateNode>::iterator iit; 01875 for( iit = subspace.intermediateNodes.begin(); iit != subspace.intermediateNodes.end(); ++iit ) 01876 { 01877 int intermediatePos = iit - subspace.intermediateNodes.begin(); 01878 if( intermediatePos >= maxChildren && 01879 !subspace.intermediateNodes[intermediatePos/maxChildren -1].node.isUnspecified() ) continue; 01880 if( !iit->node.isUnspecified() ) { 01881 RECORD_STATS( 01882 ++numMoveListMessages; 01883 moveListMessagesSize+= moveList->byteLength(); 01884 respMoveListMessagesSize+= (double) moveList->byteLength() / numRespSubspaces 01885 ); 01886 sendMessageToUDP( iit->node, (BaseOverlayMessage*) moveList->dup() ); 01887 } 01888 } 01889 01890 delete moveList; 01891 } 01892 }
void PubSubMMOG::startTimer | ( | PubSubTimer * | timer | ) | [protected] |
Referenced by handleBackupCall(), handleParentTimeout(), handlePingCall(), handleTimerEvent(), and initializeOverlay().
01913 { 01914 if( !timer ) { 01915 EV << "WARNING! Trying to start NULL timer @ " << thisNode << "\n"; 01916 return; 01917 } 01918 01919 if( timer->isScheduled() ) { 01920 cancelEvent( timer ); 01921 } 01922 01923 simtime_t duration = 0; 01924 switch( timer->getType() ) { 01925 case PUBSUB_HEARTBEAT: 01926 duration = parentTimeout/2; 01927 break; 01928 case PUBSUB_CHILDPING: 01929 duration = parentTimeout*10; // FIXME: make it a parameter 01930 break; 01931 case PUBSUB_PARENT_TIMEOUT: 01932 duration = parentTimeout; 01933 break; 01934 case PUBSUB_EVENTDELIVERY: 01935 duration = 1.0/movementRate; 01936 break; 01937 } 01938 scheduleAt(simulation.simTime() + duration, timer ); 01939 }
std::list<PubSubSubspace> PubSubMMOG::subscribedSubspaces [protected] |
std::map<PubSubSubspaceId, PubSubSubspaceResponsible> PubSubMMOG::responsibleSubspaces [protected] |
Referenced by handleAdoptChildResponse(), handleBackupCallTimeout(), handleHelpResponse(), handleIntermediateResponse(), handleMoveMessage(), handlePingCallTimeout(), handleSubscriptionCall(), handleUnsubscriptionMessage(), initializeOverlay(), publishEvents(), sendHearbeatToChildren(), sendPingToChildren(), takeOverSubspace(), and ~PubSubMMOG().
std::map<PubSubSubspaceId, PubSubSubspaceResponsible> PubSubMMOG::backupSubspaces [protected] |
std::map<PubSubSubspaceId, PubSubSubspaceIntermediate> PubSubMMOG::intermediateSubspaces [protected] |
int PubSubMMOG::subspaceSize [protected] |
Referenced by handleAppMessage(), handleMove(), and initializeOverlay().
int PubSubMMOG::AOIWidth [protected] |
Referenced by handleMove(), and initializeOverlay().
int PubSubMMOG::numSubspaces [protected] |
Referenced by handleAdoptChildCall(), handleAdoptChildResponse(), handleBackupCall(), handleBackupCallTimeout(), handleHelpResponse(), handleIntermediateBackup(), handleIntermediateCall(), handleIntermediateResponse(), handleJoinResponse(), handleMove(), handleMoveListMessage(), handleMoveMessage(), handleNodeLeftMessage(), handleParentTimeout(), handlePingCall(), handlePingCallTimeout(), handleReleaseIntermediate(), handleReplacementMessage(), handleSubscriptionBackup(), handleSubscriptionCall(), handleSubscriptionCallTimeout(), handleTakeOver(), handleUnsubscribeBackup(), handleUnsubscriptionMessage(), and initializeOverlay().
int PubSubMMOG::parentTimeout [protected] |
Referenced by handleBackupCall(), initializeOverlay(), and startTimer().
int PubSubMMOG::maxChildren [protected] |
unsigned int PubSubMMOG::currentRegionX [protected] |
Referenced by handleAppMessage(), handleJoinResponse(), and handleMove().
unsigned int PubSubMMOG::currentRegionY [protected] |
Referenced by handleAppMessage(), handleJoinResponse(), and handleMove().
int PubSubMMOG::movementRate [protected] |
Referenced by handleMoveListMessage(), handleMoveMessage(), initializeOverlay(), and startTimer().
int PubSubMMOG::maxMoveDelay [protected] |
Referenced by handleMoveListMessage(), and initializeOverlay().
PubSubTimer* PubSubMMOG::heartbeatTimer [protected] |
Referenced by initializeOverlay(), and ~PubSubMMOG().
PubSubTimer* PubSubMMOG::childPingTimer [protected] |
Referenced by initializeOverlay().
PubSubTimer* PubSubMMOG::eventDeliveryTimer [protected] |
Referenced by handleMoveMessage(), and initializeOverlay().
cMessage* PubSubMMOG::joinTimer [protected] |
Referenced by handleTimerEvent(), and initializeOverlay().
TransportAddress PubSubMMOG::lobbyServer [protected] |
int PubSubMMOG::numEventsWrongTimeslot [protected] |
Referenced by finishOverlay(), handleMoveMessage(), and initializeOverlay().
int PubSubMMOG::numEventsCorrectTimeslot [protected] |
Referenced by finishOverlay(), handleMoveMessage(), and initializeOverlay().
int PubSubMMOG::numPubSubSignalingMessages [protected] |
Referenced by finishOverlay(), handleAdoptChildCall(), handleAdoptChildResponse(), handleBackupCall(), handleBackupCallTimeout(), handleHelpResponse(), handleIntermediateCall(), handleIntermediateResponse(), handleJoinResponse(), handleMove(), handlePingCall(), handlePingCallTimeout(), handleResponsibleNodeResponse(), handleSubscriptionCall(), handleSubscriptionCallTimeout(), handleTakeOver(), initializeOverlay(), sendMessageToChildren(), takeOverSubspace(), and unsubscribeChild().
int PubSubMMOG::pubSubSignalingMessagesSize [protected] |
Referenced by finishOverlay(), handleAdoptChildCall(), handleAdoptChildResponse(), handleBackupCall(), handleBackupCallTimeout(), handleHelpResponse(), handleIntermediateCall(), handleIntermediateResponse(), handleJoinResponse(), handleMove(), handlePingCall(), handlePingCallTimeout(), handleResponsibleNodeResponse(), handleSubscriptionCall(), handleSubscriptionCallTimeout(), handleTakeOver(), initializeOverlay(), sendMessageToChildren(), takeOverSubspace(), and unsubscribeChild().
int PubSubMMOG::numMoveMessages [protected] |
Referenced by finishOverlay(), handleMove(), and initializeOverlay().
int PubSubMMOG::moveMessagesSize [protected] |
Referenced by finishOverlay(), handleMove(), and initializeOverlay().
int PubSubMMOG::numMoveListMessages [protected] |
Referenced by finishOverlay(), handleMoveListMessage(), initializeOverlay(), and publishEvents().
int PubSubMMOG::moveListMessagesSize [protected] |
Referenced by finishOverlay(), handleMoveListMessage(), initializeOverlay(), and publishEvents().
int PubSubMMOG::respMoveListMessagesSize [protected] |
Referenced by finishOverlay(), initializeOverlay(), and publishEvents().
int PubSubMMOG::lostMovementLists [protected] |
Referenced by finishOverlay(), handleMoveListMessage(), and initializeOverlay().
int PubSubMMOG::receivedMovementLists [protected] |
Referenced by finishOverlay(), handleMoveListMessage(), and initializeOverlay().