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