24 #include <NotifierConsts.h> 
   49     maxChildren = par(
"maxChildren");
 
   50     if( maxChildren < 5 ){
 
   51         throw new cRuntimeError(
"To allow a proper quad-tree, maxChildren has to be 5 or bigger");
 
   53     AOIWidth = par(
"AOIWidth");
 
   57     areaDimension = par(
"areaDimension");
 
   60     joinTimer = 
new cMessage(
"joinTimer");
 
   61     pingTimer = 
new cMessage(
"pingTimer");
 
   62     pingInterval = par(
"pingInterval");
 
   63     scheduleAt( simTime() + pingInterval, pingTimer );
 
   76     treeMaintenanceMessages = 0;
 
   77     treeMaintenanceBytes = 0;
 
   82     WATCH_MAP( ntreeNodes );
 
   88     if( state == SHUTDOWN ){
 
  103                                    cPolymorphic* context, 
int rpcId,
 
  106     if( state == SHUTDOWN ){
 
  111         EV << 
"[NTree::handleRpcResponse() @ " << thisNode.getIp()
 
  112             << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  113             << 
"    Received a NTreeJoin RPC Response: id=" << rpcId << 
"\n" 
  114             << 
"    msg=" << *_NTreeJoinResponse << 
" rtt=" << rtt
 
  116         handleJoinResponse( _NTreeJoinResponse );
 
  120         EV << 
"[NTree::handleRpcResponse() @ " << thisNode.getIp()
 
  121             << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  122             << 
"    Received a NTreePing RPC Response: id=" << rpcId << 
"\n" 
  123             << 
"    msg=" << *_NTreePingResponse << 
" rtt=" << rtt
 
  125         handlePingResponse( _NTreePingResponse, dynamic_cast<NTreePingContext*>(context) );
 
  129         EV << 
"[NTree::handleRpcResponse() @ " << thisNode.getIp()
 
  130             << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  131             << 
"    Received a NTreeDivide RPC Response: id=" << rpcId << 
"\n" 
  132             << 
"    msg=" << *_NTreeDivideResponse << 
" rtt=" << rtt
 
  134         handleDivideResponse( _NTreeDivideResponse, check_and_cast<NTreeGroupDivideContextPtr*>(context)->ptr );
 
  143                                    cPolymorphic* context, 
int rpcId,
 
  146     if( state == SHUTDOWN ){
 
  151         EV << 
"[NTree::handleRpcTimeout() @ " << thisNode.getIp()
 
  152            << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  153            << 
"    Ping RPC Call timed out: id=" << rpcId << 
"\n" 
  154            << 
"    msg=" << *_NTreePingCall
 
  155            << 
"    oldNode=" << dest
 
  157         handlePingCallTimeout( _NTreePingCall, dest, dynamic_cast<NTreePingContext*>(context) );
 
  161         EV << 
"[NTree::handleRpcTimeout() @ " << thisNode.getIp()
 
  162            << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  163            << 
"    Join RPC Call timed out: id=" << rpcId << 
"\n" 
  164            << 
"    msg=" << *_NTreeJoinCall
 
  165            << 
"    oldNode=" << dest
 
  167         handleJoinCallTimeout( _NTreeJoinCall, dest );
 
  171         EV << 
"[NTree::handleRpcTimeout() @ " << thisNode.getIp()
 
  172            << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  173            << 
"    Ping RPC Call timed out: id=" << rpcId << 
"\n" 
  174            << 
"    msg=" << *_NTreeDivideCall
 
  175            << 
"    oldNode=" << dest
 
  177         handleDivideCallTimeout( _NTreeDivideCall, dest, check_and_cast<NTreeGroupDivideContextPtr*>(context)->ptr );
 
  187     if( state == SHUTDOWN ){
 
  192         handleMoveMessage( moveMsg );
 
  195         handleAddMessage( addMsg );
 
  198         handleDeleteMessage( deleteMsg );
 
  200     } 
else if( 
NTreeLeaveMessage* leaveMsg = dynamic_cast<NTreeLeaveMessage*>(msg) ){
 
  201         handleLeaveMessage( leaveMsg );
 
  204         handleCollapseMessage( collapseMsg );
 
  207         handleReplaceMessage( replaceMsg );
 
  210         handleTakeOverMessage( takeMsg );
 
  217     if( state == SHUTDOWN ){
 
  220     if( msg == joinTimer ) {
 
  224         msg->
setComp(getThisCompType());
 
  225         send( msg, 
"appOut");
 
  230         send( gameMsg, 
"appOut");
 
  231     } 
else if( msg == pingTimer ){
 
  233         checkParentTimeout();
 
  234         scheduleAt( simTime() + pingInterval, pingTimer );
 
  241         if( state == READY ) {
 
  242             handleMove( posMsg );
 
  243         } 
else if ( state == JOIN ) {
 
  247             msg->
setComp(getThisCompType());
 
  248             send( msg, 
"appOut");
 
  249         } 
else if ( state == INIT ) {
 
  256                 groups.push_front(grp);
 
  260                 root.
group = &groups.front();
 
  261                 ntreeNodes.insert(make_pair(initialScope,root));
 
  262                 changeState( READY );
 
  266                 position = posMsg->getPosition();
 
  270                 sendUdpRpcCall( bootstrapNode, joinMsg );
 
  273             setBootstrapedIcon();
 
  284     std::list<NTreeGroup>::iterator grpIt = findGroup( joinCall->
getPosition() );
 
  285     if( grpIt != groups.end() ) {
 
  287         if( grpIt->leader == thisNode ) {
 
  291             grpAdd->
setOrigin( grpIt->scope.origin );
 
  295                     treeMaintenanceMessages += grpIt->members.size();
 
  296                     treeMaintenanceBytes += grpIt->members.size()*grpAdd->getByteLength();
 
  298             sendToGroup( *grpIt, grpAdd );
 
  300             grpIt->members.insert( joinCall->
getSrcNode() );
 
  303             joinResp->
setOrigin( grpIt->scope.origin );
 
  304             joinResp->
setSize( grpIt->scope.size );
 
  307             for( std::set<NodeHandle>::iterator it = grpIt->members.begin(); it != grpIt->members.end(); ++it ) {
 
  312             sendRpcResponse( joinCall, joinResp );
 
  315             if( grpIt->members.size() > maxChildren && !grpIt->dividePending && grpIt->scope.size > 2*AOIWidth ){
 
  316                 EV << 
"[NTree::handleJoinCall() @ " << thisNode.getIp()
 
  317                     << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  318                     << 
"    Group got too big. Trying to divide group\n";
 
  319                 grpIt->dividePending = 
true;
 
  320                 std::map<NTreeScope,NTreeNode>::iterator nit = ntreeNodes.find( grpIt->scope );
 
  321                 if( nit == ntreeNodes.end() ){
 
  322                     EV << 
"    Host is leader of a group, but not NTreeNode of that group.\n" 
  323                         << 
"    This should not happen. Dropping group\n";
 
  324                     if( currentGroup == &(*grpIt) ){
 
  327                     groups.erase( grpIt );
 
  330                 EV << 
"    Sending divide calls\n";
 
  332                 divideCall->
setOrigin( nit->second.scope.origin );
 
  333                 divideCall->
setSize( nit->second.scope.size );
 
  337                 divideContext->
nodeScope = nit->second.scope;
 
  341                 unsigned int numMembers = grpIt->members.
size();
 
  342                 unsigned int numbers[numMembers];
 
  343                 for( i = 0; i < numMembers; ++i ) numbers[i] = i;
 
  344                 unsigned int upperbound = numMembers;
 
  345                 for (i = 0; i < 4; ++i)
 
  348                     unsigned int index = intuniform(0, upperbound);
 
  349                     std::set<NodeHandle>::iterator newChild = grpIt->members.begin();
 
  350                     std::advance( newChild, numbers[index] );
 
  352                     if( *newChild == thisNode ) { 
 
  359                         contextPtr->
ptr = divideContext;
 
  360                         sendUdpRpcCall( *newChild, msg, contextPtr);
 
  362                                 treeMaintenanceMessages++;
 
  363                                 treeMaintenanceBytes += msg->getByteLength();
 
  367                     swap(numbers[index], numbers[upperbound]);
 
  374             sendMessageToUDP( grpIt->leader, joinCall );
 
  379     routeViaNTree( joinCall->
getPosition(), joinCall, true );
 
  384     EV << 
"[NTree::handleJoinResponse() @ " << thisNode.getIp()
 
  385         << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  386         << 
"    JOIN ACK for group " << joinResp->
getOrigin()
 
  387         << 
"-" << joinResp->
getSize() << 
"\n";
 
  388     std::list<NTreeGroup>::iterator git = findGroup( joinResp->
getOrigin(), joinResp->
getSize() );
 
  391     for( std::list<NTreeGroup>::iterator it = groups.begin(); it != groups.end(); ++it ){
 
  392         if( it != git && (it->isInScope( groupScope.origin ) || groupScope.contains( it->scope.origin ) )){
 
  394             EV << 
"    Conflicting group found. Ignoring JOIN ACK\n";
 
  398             if( state != READY ){
 
  399                 changeState( READY );
 
  406     if( git != groups.end() ){
 
  407         if( git->leader != thisNode ) {
 
  408             EV << 
"    Group already known. Refreshing member list\n";
 
  409             git->members.clear();
 
  412             EV << 
"    Group already known; and I'm leader of that group. Ignoring ACK\n";
 
  419         groups.push_front(grp);
 
  420         git = groups.begin();
 
  426         git->members.insert( joinResp->
getMembers(i) );
 
  430     if( state != READY ){
 
  431         changeState( READY );
 
  438     if( state != READY ){
 
  439         EV << 
"    Overlay not ready. Trying to re-join overlay\n";
 
  456         sendToGroup( *currentGroup, moveMsg, 
true);
 
  458                 movesSend += currentGroup->members.size();
 
  459                 moveBytes += moveMsg->getByteLength() * currentGroup->members.size();
 
  460                 globalStatistics->addStdDev( 
"NTree: Area size", currentGroup->scope.size );
 
  465     if( !currentGroup || !currentGroup->isInScope( position ) ){
 
  466         std::list<NTreeGroup>::iterator it = findGroup( position );
 
  467         if( it != groups.end() ) {
 
  468             sendToGroup( *it, moveMsg, 
true );
 
  469             currentGroup = &(*it);
 
  471                     movesSend += currentGroup->members.size();
 
  472                     moveBytes += moveMsg->getByteLength() * currentGroup->members.size();
 
  475             EV << 
"[NTree::handleMove() @ " << thisNode.getIp()
 
  476                 << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  477                 << 
"WARNING: no group for new position. Some updates may get lost!\n";
 
  478             joinGroup( position );
 
  494         if(area.
contains( position + aoiRight )) joinGroup(position + aoiRight);
 
  495         if(area.
contains( position - aoiRight )) joinGroup(position - aoiRight);
 
  496         if(area.
contains( position + aoiTop )) joinGroup(position + aoiTop);
 
  497         if(area.
contains( position - aoiTop )) joinGroup(position - aoiTop);
 
  498         if(area.
contains( position + (aoiRight + aoiTop)/sqrt(2))) joinGroup(position + (aoiRight + aoiTop)/sqrt(2));
 
  499         if(area.
contains( position + (aoiRight - aoiTop)/sqrt(2))) joinGroup(position + (aoiRight - aoiTop)/sqrt(2));
 
  500         if(area.
contains( position - (aoiRight + aoiTop)/sqrt(2))) joinGroup(position - (aoiRight + aoiTop)/sqrt(2));
 
  501         if(area.
contains( position - (aoiRight - aoiTop)/sqrt(2))) joinGroup(position - (aoiRight - aoiTop)/sqrt(2));
 
  503         if( scope.
contains( position + aoiRight )) leaveGroup( scope.
origin + groupRight );
 
  504         if( scope.
contains( position - aoiRight )) leaveGroup( scope.
origin - groupRight );
 
  505         if( scope.
contains( position + aoiTop )) leaveGroup( scope.
origin + groupTop );
 
  506         if( scope.
contains( position - aoiTop )) leaveGroup( scope.
origin - groupTop );
 
  507         if( scope.
contains( position + (aoiRight + aoiTop)/sqrt(2))) leaveGroup( scope.
origin + groupRight + groupTop);
 
  508         if( scope.
contains( position + (aoiRight - aoiTop)/sqrt(2))) leaveGroup( scope.
origin + groupRight - groupTop);
 
  509         if( scope.
contains( position - (aoiRight + aoiTop)/sqrt(2))) leaveGroup( scope.
origin - groupRight + groupTop);
 
  510         if( scope.
contains( position - (aoiRight - aoiTop)/sqrt(2))) leaveGroup( scope.
origin - groupRight - groupTop);
 
  516     std::list<NTreeGroup>::iterator it = findGroup( addMsg->
getOrigin() );
 
  517     if( it == groups.end() ){
 
  518         EV << 
"[NTree::handleAddMessage() @ " << thisNode.getIp()
 
  519             << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  520             << 
"    Received add message for unknown group scope=" << addMsg->
getOrigin() << 
"\n";
 
  523     EV << 
"[NTree::handleAddMessage() @ " << thisNode.getIp()
 
  524         << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  525         << 
"    Received add message for group scope=" << addMsg->
getOrigin() << 
"\n" 
  527     it->members.insert( addMsg->
getPlayer() );
 
  532     std::list<NTreeGroup>::iterator it = findGroup( deleteMsg->
getOrigin(), deleteMsg->
getSize() );
 
  534     if( it == groups.end() ) 
return;
 
  538     ntreeNodes.erase( it->scope );
 
  541     if( it->isInScope(position) ){
 
  547                 joinBytes += joinCall->getByteLength();
 
  549         sendMessage( deleteMsg->
getNewChild( it->scope.origin.getQuadrant( position )), joinCall);
 
  553     if( currentGroup == &(*it) ) currentGroup = NULL;
 
  559     std::list<NTreeGroup>::iterator it = findGroup( leaveMsg->
getPosition() );
 
  560     if( it != groups.end() ){
 
  561         it->members.erase( leaveMsg->
getPlayer() );
 
  565     for( it = groups.begin(); it != groups.end(); ++it ){
 
  566         if( it->members.find( leaveMsg->
getPlayer() ) != it->members.end() ){
 
  576     send(gameMsg, 
"appOut");
 
  581     EV << 
"[NTree::handleCollapseMessage() @ " << thisNode.getIp()
 
  582         << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  583         << 
"    Got collapse message for group " << collapseMsg->
getOrigin() << 
"\n";
 
  585     std::map<NTreeScope,NTreeNode>::iterator it = findNTreeNode( collapseMsg->
getOrigin(), collapseMsg->
getSize() );
 
  586     if( it != ntreeNodes.end() ){
 
  587         if( it->second.group ){
 
  588             EV << 
"    Informing group\n";
 
  593             for( 
unsigned int i = 0; i < 4; ++i ){
 
  598                     treeMaintenanceMessages += it->second.group->members.size();
 
  599                     treeMaintenanceBytes += it->second.group->members.size()*delMsg->getByteLength();
 
  601             sendToGroup( *it->second.group, delMsg );
 
  603             if( currentGroup && *currentGroup == *it->second.group ){
 
  606             groups.remove( *it->second.group );
 
  610             EV << 
"    Informing children\n";
 
  611             for( 
unsigned int i = 0; i < 4; ++i ){
 
  612                 EV << 
"    ==> " << it->second.children[i] << 
"\n";
 
  613                 collapseMsg->
setOrigin( it->second.scope.getSubScope(i).origin );
 
  614                 collapseMsg->
setSize( it->second.scope.getSubScope(i).size );
 
  616                         treeMaintenanceMessages++;
 
  617                         treeMaintenanceBytes += collapseMsg->getByteLength();
 
  619                 sendMessage( it->second.children[i], collapseMsg->
dup() );
 
  623         ntreeNodes.erase( it );
 
  638     send(gameMsg, 
"appOut");
 
  640             globalStatistics->addStdDev(
 
  642                 SIMTIME_DBL(simTime()) - SIMTIME_DBL(moveMsg->getCreationTime())
 
  654         myScope = origScope.
getSubScope( nodePing->getQuadrant() );
 
  656         std::map<NTreeScope,NTreeNode>::iterator it = ntreeNodes.find( myScope );
 
  657         if( it != ntreeNodes.end() ){
 
  660             if( nodePing->getParent().isUnspecified() ) it->second.parentIsRoot = 
true;
 
  661             for( 
unsigned int i = 0; i < 4; ++i ){
 
  662                 it->second.siblings[i] = nodePing->getSiblings(i);
 
  664             it->second.lastPing = simTime();
 
  668             if( it->second.group ){
 
  673                 for( std::set<NodeHandle>::iterator childIt = it->second.group->members.begin();
 
  674                         childIt != it->second.group->members.end(); ++childIt ){
 
  680                 unsigned int aggChildCount = 0;
 
  682                 for( 
unsigned int i = 0; i < 4; ++i ){
 
  683                     aggChildCount += it->second.aggChildCount[i];
 
  684                     nodeResp->
setMembers( i, it->second.children[i] );
 
  689             sendRpcResponse( nodePing, nodeResp );
 
  695         std::list<NTreeGroup>::iterator it = findGroup( pingCall->
getOrigin(), pingCall->
getSize() );
 
  696         if( it != groups.end() ){
 
  703         sendRpcResponse( pingCall, pingResp );
 
  711         std::map<NTreeScope,NTreeNode>::iterator it = ntreeNodes.find( context->
nodeScope );
 
  712         if( it != ntreeNodes.end() && !it->second.group){
 
  714             if( it->second.children[context->
quadrant] == nodePing->getSrcNode() ){
 
  715                 it->second.aggChildCount[context->
quadrant] = nodePing->getAggChildCount();
 
  716                 it->second.childChildren[context->
quadrant].clear();
 
  717                 for( 
unsigned int ii = 0; ii < nodePing->getMembersArraySize(); ++ii ){
 
  718                     it->second.childChildren[context->
quadrant].insert( nodePing->getMembers( ii ) );
 
  722                 unsigned int aggChildCount = 0;
 
  723                 for( 
unsigned int i = 0; i < 4; ++i ){
 
  724                     if( !it->second.aggChildCount[i] ) {
 
  725                         aggChildCount = maxChildren;
 
  729                     aggChildCount += it->second.aggChildCount[i];
 
  731                 if( aggChildCount*2 < maxChildren ){
 
  746         std::map<NTreeScope,NTreeNode>::iterator it = ntreeNodes.find( context->
nodeScope );
 
  747         if( it != ntreeNodes.end() && !it->second.group){
 
  749             if( oldNode == it->second.children[context->
quadrant ]){
 
  755                 replaceMsg->
setIsLeaf( it->second.childChildren[context->
quadrant].size() != 4 ||
 
  756                         (it->second.childChildren[context->
quadrant].size() == it->second.aggChildCount[context->
quadrant]) );
 
  759                 for( std::set<NodeHandle>::iterator cit = it->second.childChildren[context->
quadrant].begin();
 
  760                         cit != it->second.childChildren[context->
quadrant].end(); ++cit ){
 
  767                 std::set<NodeHandle> invalidNodes;
 
  768                 invalidNodes.insert( thisNode );
 
  769                 if( !it->second.parent.isUnspecified() ){
 
  770                     invalidNodes.insert( it->second.parent );
 
  773                     for( 
unsigned int i = 0; i < 4; ++i ){
 
  777                 const NodeHandle& dest = getRandomNode( invalidNodes );
 
  779                         treeMaintenanceMessages++;
 
  780                         treeMaintenanceBytes += replaceMsg->getByteLength();
 
  782                 sendMessage(dest, replaceMsg );
 
  788         for( std::list<NTreeGroup>::iterator it = groups.begin(); it != groups.end(); ++it ){
 
  790             for( std::set<NodeHandle>::iterator mit = it->members.begin(); mit != it->members.end(); ++mit ){
 
  791                 if( oldNode == *mit ){
 
  796                     sendToGroup( *it, leaveMsg );
 
  798                     it->members.erase( mit );
 
  808     EV << 
"[NTree::handleDivide() @ " << thisNode.getIp()
 
  809         << 
" (" << thisNode.getKey().toString(16) << 
")]\n";
 
  810     std::list<NTreeGroup>::iterator it = findGroup( divideCall->
getOrigin(), divideCall->
getSize() );
 
  811     if( it == groups.end() ){
 
  812         EV << 
"    Received divide message for unknown group scope=" << divideCall->
getOrigin() << 
"\n";
 
  814         EV << 
"    Divide group " << it->scope << 
"\n";
 
  824     ntreeNodes.erase( oldScope );
 
  828     newGroup.
leader = thisNode;
 
  829     newGroup.
members.insert(thisNode);
 
  830     groups.push_front(newGroup);
 
  831     if( it != groups.end() ){
 
  832         if( currentGroup == &(*it) ){
 
  833             currentGroup = &groups.front();
 
  841     newNode.
group = &groups.front();
 
  842     ntreeNodes.insert(make_pair(newScope,newNode));
 
  849             treeMaintenanceMessages++;
 
  850             treeMaintenanceBytes += divideResp->getByteLength();
 
  852     sendRpcResponse( divideCall, divideResp );
 
  858     for( 
unsigned int i = 0; i < 4; ++i ){
 
  864     divideNode( context );
 
  870     std::set<NodeHandle> invalidNodes;
 
  871     invalidNodes.insert( thisNode );
 
  872     NodeHandle dest = getRandomNode( invalidNodes );
 
  874             treeMaintenanceMessages++;
 
  875             treeMaintenanceBytes += divideCall->getByteLength();
 
  878     contextPtr->
ptr = context;
 
  879     sendUdpRpcCall( dest, divideCall->
dup(), contextPtr );
 
  884     EV << 
"[NTree::handleReplaceMessage() @ " << thisNode.getIp()
 
  885         << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
  886         << 
"    Was asked to replace " << replaceMsg->
getOldNode() << 
" for group " << replaceMsg->
getOrigin() << 
"\n";
 
  890     newNode.parent = replaceMsg->
getParent();
 
  893         std::list<NTreeGroup>::iterator it = findGroup( replaceMsg->
getOrigin(), replaceMsg->
getSize() );
 
  894         if( it == groups.end() ){
 
  897             groups.push_front( newGrp );
 
  900         it->leader = thisNode;
 
  901         it->members.insert( thisNode );
 
  905         newNode.group = &(*it);
 
  907         for( 
unsigned int i = 0; i < 4; ++i ){
 
  912     ntreeNodes.insert(make_pair(newScope,newNode));
 
  918     takeMsg->
setSize( newScope.size );
 
  921     sendMessage( newNode.parent, takeMsg->
dup() );
 
  924             treeMaintenanceMessages+=2;
 
  925             treeMaintenanceBytes += 2*takeMsg->getByteLength();
 
  929                 treeMaintenanceMessages += newNode.group->members.size();
 
  930                 treeMaintenanceBytes += newNode.group->members.size()*takeMsg->getByteLength();
 
  932         sendToGroup( *newNode.group, takeMsg );
 
  934         for( 
unsigned int i = 0; i < 4; ++i ){
 
  936                     treeMaintenanceMessages++;
 
  937                     treeMaintenanceBytes += takeMsg->getByteLength();
 
  939             sendMessage( newNode.children[i], takeMsg->
dup() );
 
  949     std::list<NTreeGroup>::iterator git = findGroup( takeMsg->
getOrigin(), takeMsg->
getSize() );
 
  950     if( git != groups.end() ){
 
  956     for(std::map<NTreeScope,NTreeNode>::iterator it = ntreeNodes.begin(); it != ntreeNodes.end(); ++it ){
 
  958         if( takeMsg->
getSize() == it->second.scope.size*2.0 ){
 
  959             for( 
unsigned int i = 0; i < 4; ++i ){
 
  960                 if( takeScope.getSubScope(i) == it->first ){
 
  961                     it->second.parent = takeMsg->
getPlayer();
 
  965         } 
else if( takeMsg->
getSize()*2.0 == it->second.scope.size && !it->second.group ){
 
  966             for( 
unsigned int i = 0; i < 4; ++i ){
 
  967                 if( it->first.getSubScope(i) == takeScope ){
 
  968                     it->second.children[i] = takeMsg->
getPlayer();
 
  971         } 
else if( it->second.scope == takeScope && takeMsg->
getPlayer() != thisNode ){
 
  973             ntreeNodes.erase( it );
 
  982     for(std::map<NTreeScope,NTreeNode>::iterator it = ntreeNodes.begin(); it != ntreeNodes.end(); ++it ){
 
  985         replaceMsg->
setOrigin( it->second.scope.origin );
 
  986         replaceMsg->
setSize( it->second.scope.size );
 
  987         replaceMsg->
setParent( it->second.parent );
 
  988         if( it->second.group ){
 
  992             for( std::set<NodeHandle>::iterator mit = it->second.group->members.begin(); mit != it->second.group->members.end(); ++mit ){
 
  999             for( 
unsigned int i = 0; i < 4; ++i ){
 
 1000                 replaceMsg->
setChildren(i, it->second.children[i] );
 
 1006         std::set<NodeHandle> invalidNodes;
 
 1007         invalidNodes.insert( thisNode );
 
 1008         if( !it->second.parent.isUnspecified() ){
 
 1009             invalidNodes.insert( it->second.parent );
 
 1011         if( !it->second.group ) {
 
 1012             for( 
unsigned int i = 0; i < 4; ++i ){
 
 1013                 invalidNodes.insert( it->second.children[i] );
 
 1016         const NodeHandle& dest = getRandomNode( invalidNodes );
 
 1020                 treeMaintenanceMessages++;
 
 1021                 treeMaintenanceBytes += replaceMsg->getByteLength();
 
 1023         sendMessage( dest, replaceMsg );
 
 1025     while( groups.size() ){
 
 1027         leaveGroup( groups.begin()->scope.origin, true );
 
 1032     currentGroup = NULL;
 
 1033     changeState( SHUTDOWN );
 
 1038     for(std::map<NTreeScope,NTreeNode>::iterator it = ntreeNodes.begin(); it != ntreeNodes.end(); ++it ){
 
 1041         if( it->second.group ){
 
 1044             pingCall->
setOrigin( it->second.scope.origin );
 
 1045             pingCall->
setSize( it->second.scope.size );
 
 1046             pingCall->
setParent( it->second.parent );
 
 1048             sendToGroup( *it->second.group, pingCall );
 
 1051             pingCall->
setOrigin( it->second.scope.origin );
 
 1052             pingCall->
setSize( it->second.scope.size );
 
 1053             pingCall->
setParent( it->second.parent );
 
 1055             for( i = 0; i < 4; ++i ){
 
 1056                 pingCall->
setSiblings(i, it->second.children[i] );
 
 1060             for( i = 0; i < 4; ++i ){
 
 1062                 sendUdpRpcCall( it->second.children[i], pingCall->
dup(), 
new NTreePingContext(it->second.scope, i) );
 
 1073     for(std::map<NTreeScope,NTreeNode>::iterator it = ntreeNodes.begin(); it != ntreeNodes.end(); ){
 
 1074         if( it->second.parent.isUnspecified() || (it->second.lastPing == 0) ) {
 
 1078         if( it->second.lastPing + pingInterval + pingInterval < simTime() ){
 
 1080             EV << 
"[NTree::checkParentTimeout() @ " << thisNode.getIp()
 
 1081                 << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
 1082                 << 
"    Parent for node" << it->second << 
" timed out\n";
 
 1085             if( it->second.parentIsRoot ) {
 
 1086                 if( it->second.siblings[0] == thisNode ){
 
 1087                     EV << 
"    Parent was root. Replacing him\n";
 
 1090                     replaceMsg->
setSize( areaDimension );
 
 1095                     std::set<NodeHandle> invalidNodes;
 
 1096                     for( 
unsigned int i = 0; i < 4; ++i ){
 
 1097                         replaceMsg->
setChildren( i, it->second.siblings[i] );
 
 1098                         invalidNodes.insert( replaceMsg->
getChildren(i) );
 
 1102                     const NodeHandle& dest = getRandomNode( invalidNodes );
 
 1104                             treeMaintenanceMessages++;
 
 1105                             treeMaintenanceBytes += replaceMsg->getByteLength();
 
 1107                     sendMessage(dest, replaceMsg );
 
 1112                 if( it->second.group ){
 
 1113                     if( currentGroup && *currentGroup == *it->second.group ){
 
 1114                         currentGroup = NULL;
 
 1116                     groups.remove( *it->second.group );
 
 1118                 ntreeNodes.erase( it++ );
 
 1128     EV << 
"[NTree::divideNode() @ " << thisNode.getIp()
 
 1129         << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
 1130         << 
"    Trying to divide node " << context->
nodeScope << 
"\n";
 
 1131     std::map<NTreeScope,NTreeNode>::iterator it = ntreeNodes.find( context->
nodeScope );
 
 1132     if( it == ntreeNodes.end() ){
 
 1133         EV << 
"    However, node is not in the list of known nodes\n";
 
 1136     if( !it->second.group ){
 
 1137         EV << 
"    However, node has no known group attached\n";
 
 1145     for( 
unsigned int i = 0; i < 4; ++i ){
 
 1150             treeMaintenanceMessages+= it->second.group->members.size();
 
 1151             treeMaintenanceBytes += it->second.group->members.size()*delMsg->getByteLength();
 
 1153     sendToGroup( *it->second.group, delMsg );
 
 1156     if( currentGroup && *currentGroup == *it->second.group ){
 
 1157         currentGroup = NULL;
 
 1159     groups.remove( *it->second.group );
 
 1160     it->second.group= NULL;
 
 1163     for( 
unsigned int i = 0; i < 4; ++i ){
 
 1164         it->second.children[i] = context->
newChild[i];
 
 1170     EV << 
"[NTree::CollapseTree() @ " << thisNode.getIp()
 
 1171         << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
 1172         << 
"    Collapsing tree" << node->second << 
"\n";
 
 1178     for( 
unsigned int i = 0; i < 4; ++i ){
 
 1179         collapseMsg->
setOrigin( node->second.scope.getSubScope(i).origin );
 
 1180         collapseMsg->
setSize( node->second.scope.getSubScope(i).size );
 
 1182                 treeMaintenanceMessages++;
 
 1183                 treeMaintenanceBytes += collapseMsg->getByteLength();
 
 1186         sendMessage( node->second.children[i], collapseMsg->
dup() );
 
 1189         node->second.childChildren[i].clear();
 
 1190         node->second.aggChildCount[i] = 0;
 
 1196     newGroup.
leader = thisNode;
 
 1197     newGroup.
members.insert( thisNode );
 
 1198     groups.push_front( newGroup );
 
 1200     node->second.group = &(groups.front());
 
 1205     std::list<NTreeGroup>::iterator grpIt = findGroup( position );
 
 1206     if( grpIt == groups.end() ) {
 
 1212                 joinBytes += joinCall->getByteLength();
 
 1214         routeViaNTree( position, joinCall );
 
 1220     std::list<NTreeGroup>::iterator grpIt = findGroup( position );
 
 1222     if( grpIt != groups.end() && (grpIt->leader != thisNode || force) ) {
 
 1227         sendToGroup( *grpIt, leaveMsg );
 
 1229         if( currentGroup == &(*grpIt) ){
 
 1230             EV << 
"[NTree::leaveGroup() @ " << thisNode.getIp()
 
 1231                 << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
 1232                 << 
"    WARNING: Leaving group " << position << 
"\n" 
 1233                 << 
"    This group is marked as current group!\n";
 
 1234             currentGroup = NULL;
 
 1236         groups.erase( grpIt );
 
 1243     if( ntreeNodes.size() ) {
 
 1245         std::map<NTreeScope,NTreeNode>::iterator it = findNTreeNode( pos );
 
 1246         if( it != ntreeNodes.end() ){
 
 1248             dest = it->second.getChildForPos( pos );
 
 1251             dest = ntreeNodes.begin()->second.parent;
 
 1256             dest = currentGroup->leader;
 
 1257         } 
else if( groups.size() ){
 
 1258             dest = groups.begin()->leader;
 
 1260             EV << 
"[NTree::routeViaNTree() @ " << thisNode.
getIp()
 
 1261                 << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
 1262                 << 
"    No ntree node and no group known. Dropping message & re-join!\n";
 
 1263             changeState( INIT );
 
 1268     if( forward && dest == thisNode ) {
 
 1269         EV << 
"[NTree::routeViaNTree() @ " << thisNode.getIp()
 
 1270             << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
 1271             << 
"    Trying to route message " << msg << 
" to myself\n" 
 1272             << 
"    This will result in a loop. Dropping message\n";
 
 1275         sendMessage( dest, msg, forward );
 
 1282     EV << 
"[NTree::sendToGroup() @ " << thisNode.getIp()
 
 1283         << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
 1284         << 
"    Send message " << msg << 
"\n" 
 1285         << 
"    to group scope=" << grp.
scope.
origin << 
"\n";
 
 1291     for( std::set<NodeHandle>::iterator it = grp.begin(); it != grp.end(); ++it ){
 
 1292         sendMessage( *it, msg->dup(), false );
 
 1294     if (!keepMsg) 
delete msg;
 
 1301         EV << 
"[NTree::sendMessage() @ " << thisNode.getIp()
 
 1302             << 
" (" << thisNode.getKey().toString(16) << 
")]\n" 
 1303             << 
"    WARNING: Trying to send message " << msg
 
 1304             << 
"    to unspecified destination. Dropping packet!\n";
 
 1311     if( rpc && !forward ){
 
 1319         sendMessageToUDP( dest, msg );
 
 1327             if( !joinTimer->isScheduled() ) {
 
 1328                 scheduleAt( ceil(simTime() + (simtime_t) par(
"joinDelay")), joinTimer );
 
 1334             setBootstrapedIcon();
 
 1335             if( !currentGroup && groups.size() ) currentGroup = &groups.front();
 
 1336             setOverlayReady( 
true );
 
 1341             setOverlayReady( 
false );
 
 1346             cancelAndDelete( pingTimer );
 
 1348             setOverlayReady( 
false );
 
 1351     setBootstrapedIcon();
 
 1357         if(state == READY) {
 
 1358             getParentModule()->getParentModule()->getDisplayString().setTagArg(
"i2", 1, 
"green");
 
 1359             getDisplayString().setTagArg(
"i", 1, 
"green");
 
 1361         else if(state == JOIN) {
 
 1362             getParentModule()->getParentModule()->getDisplayString().setTagArg(
"i2", 1, 
"yellow");
 
 1363             getDisplayString().setTagArg(
"i", 1, 
"yellow");
 
 1366             getParentModule()->getParentModule()->getDisplayString().setTagArg(
"i2", 1, 
"red");
 
 1367             getDisplayString().setTagArg(
"i", 1, 
"red");
 
 1374     for( std::list<NTreeGroup>::iterator it = groups.begin(); it != groups.end(); ++it ){
 
 1375         if( it->isInScope( pos ) ) 
return it;
 
 1377     return groups.end();
 
 1382     for( std::list<NTreeGroup>::iterator it = groups.begin(); it != groups.end(); ++it ){
 
 1383         if( it->scope.origin == pos && it->scope.size == size ) 
return it;
 
 1385     return groups.end();
 
 1390     double size = areaDimension + 1;
 
 1391     std::map<NTreeScope,NTreeNode>::iterator bestNode = ntreeNodes.end();
 
 1392     for( std::map<NTreeScope,NTreeNode>::iterator it = ntreeNodes.begin(); it != ntreeNodes.end(); ++it ){
 
 1393         if( it->second.isInScope( pos ) && it->second.scope.size < size ){
 
 1395             size = bestNode->second.scope.size;
 
 1403     return ntreeNodes.find( 
NTreeScope( pos, size ) );
 
 1412         dest = globalNodeList->getRandomNode();
 
 1414         for( std::set<NodeHandle>::iterator it = invalidNodes.begin(); it != invalidNodes.end(); ++it ){
 
 1426     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
 
 1428     globalStatistics->addStdDev(
"NTree: Joins send per second", joinsSend / time );
 
 1429     globalStatistics->addStdDev(
"NTree: Join bytes send per second", joinBytes / time );
 
 1430     globalStatistics->addStdDev(
"NTree: Join timeouts per second", joinTimeout / time );
 
 1431     globalStatistics->addStdDev(
"NTree: Tree maintenance messages send per second", treeMaintenanceMessages / time );
 
 1432     globalStatistics->addStdDev(
"NTree: Tree maintenance bytes send per second", treeMaintenanceBytes / time );
 
 1433     globalStatistics->addStdDev(
"NTree: Move messages send per second", movesSend / time );
 
 1434     globalStatistics->addStdDev(
"NTree: Move bytes send per second", moveBytes / time );
 
 1435     globalStatistics->addStdDev(
"NTree: Tree collapsed per second", collapseCount / time );
 
 1436     globalStatistics->addStdDev(
"NTree: Tree divides per second", divideCount / time );
 
 1441     cancelAndDelete(joinTimer);
 
 1442     cancelAndDelete(pingTimer);