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);