OverSim
TreeManagement.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2010 Institut fuer Telematik, Universitaet Karlsruhe (TH)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 
25 #include <omnetpp.h>
26 
27 #include <GlobalNodeListAccess.h>
28 #include <NeighborCache.h>
29 #include <OverlayAccess.h>
30 #include <GlobalNodeList.h>
31 #include <PeerInfo.h>
32 #include <CommonMessages_m.h>
33 #include <GlobalViewBuilder.h> //TODO own file for AbstractTreeMsgClient
34 
35 #include "TreeManagement.h"
36 
37 
39 {
40  globalNodeList = NULL;
42  treeBuildTimer = new cMessage("treeBuildTimer");
43  currentTreeLevel = 0;
44 }
45 
47 {
48  neighborCache->cancelAndDelete(treeBuildTimer);
49 }
50 
52 {
54  treeChildNodes.clear();
56 }
57 
58 
59 void TreeManagement::init(NeighborCache* neighborCache)
60 {
61  this->neighborCache = neighborCache;
62  this->overlay = neighborCache->overlay;
64 
65  treeMgmtBuildInterval = neighborCache->par("treeMgmtBuildInterval");
68  neighborCache->par("treeMgmtChildrenTimeOut").doubleValue();
69 
70  creationTime = simTime();
71 
72  // init stats Counter
73  for(int i = 0; i < MAXTREELEVEL; i++) {
74  numTMReceived[i] = 0;
75  numTMSent[i] = 0;
76  bytesTMReceived[i] = 0;
77  bytesTMSent[i] = 0;
78  }
79 }
80 
81 
83 {
84  if(msg == treeBuildTimer) {
85  neighborCache->cancelEvent(treeBuildTimer);
88 
89  neighborCache->scheduleAt(simTime() +
90  truncnormal(treeMgmtBuildInterval,
91  deviation),
92  msg);
93  }
94 }
95 
96 
98 {
101  bytesTMReceived[currentTreeLevel] += msg->getByteLength();
102  }
103 
104  RPC_SWITCH_START( msg );
105  RPC_DELEGATE( ParentRequest, handleParentRequestRpcCall );
106  RPC_DELEGATE( ChildCheck, handleChildCheckRpcCall );
107  RPC_DELEGATE( ChildRelease, handleChildReleaseRpcCall );
108  RPC_SWITCH_END( );
109 
110  return RPC_HANDLED;
111 }
112 
113 
115  cPolymorphic* context,
116  int rpcId, simtime_t rtt)
117 {
120  bytesTMReceived[currentTreeLevel] += msg->getByteLength();
121  }
122 
123  RPC_SWITCH_START( msg );
124  RPC_ON_RESPONSE( ParentRequest ) {
125  handleParentRequestRpcResponse(_ParentRequestResponse, context,
126  rpcId, rtt);
127  }
128  RPC_ON_RESPONSE( ChildCheck ) {
129  handleChildCheckRpcResponse(_ChildCheckResponse, context,
130  rpcId, rtt);
131  }
132  RPC_SWITCH_END( );
133 
134  return;
135 }
136 
137 
139  const TransportAddress& dest,
140  cPolymorphic* context, int rpcId,
141  const OverlayKey& destKey)
142 {
143  RPC_SWITCH_START(msg)
144  RPC_ON_CALL( ChildRelease ) {
145 
146  break;
147  }
148  RPC_ON_CALL( ChildCheck ) {
149  EV << "[TreeManagement::handleRpcTimeout() @ "
151  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
152  << " Child timout: " << dest.getIp()
153  << endl;
154 
155  treeChildNodes.erase(dest);
156 
158  break;
159  }
160  RPC_ON_CALL( ParentRequest ) {
161  EV << "[TreeManagement::handleRpcTimeout() @ "
163  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
164  << " Parent timout, domainKey = " << destKey
165  << endl;
166  std::cout << "[TreeManagement::handleRpcTimeout() @ "
168  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
169  << " Parent timout, domainKey = " << destKey
170  << std::endl;
171 
175 
177  break;
178  }
179  RPC_ON_CALL( TreeApp ) {
180  EV << "[TreeManagement::handleRpcTimeout() @ "
182  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
183  << " Peer in tree timout: " << dest.getIp()
184  << " (" << destKey << ")"
185  << endl;
186 
187  if (!dest.isUnspecified() && !parentNode.isUnspecified() &&
188  (dest == parentNode)) {
189  EV << "[TreeManagement::handleRpcTimeout() @ "
191  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
192  << " TreeAppCall (sent directly to parent "
193  << dest << ") timed out, retry sending message to key " << treeDomainKey
194  << endl;
195 
196  // retry to key
199  //TODO delayed
202  msg->dup(), NULL, DEFAULT_ROUTING,
203  -1 , 0, -1, this);
204  } else std::cout << neighborCache->getThisNode().getIp() << ": " << msg->getName()
205  << " timed out to " << dest.getIp()
206  << " (" << destKey << ")"
207  << std::endl;
208  }
209  RPC_SWITCH_END( )
210 
211 
212  /*
213  // check parentNode
214  if (!destKey.isUnspecified() && destKey == treeDomainKey) {
215  treeDomainKey = OverlayKey::UNSPECIFIED_KEY;
216  overlay->deleteOverlayNeighborArrow(parentNode);
217  parentNode = NodeHandle::UNSPECIFIED_NODE;
218  std::cout << "parent timeout" << std::endl;
219  //return;
220  } else
221  // check children
222  if (dest.isUnspecified()) {
223  for (treeNodeMap::iterator it = treeChildNodes.begin();
224  it != treeChildNodes.end(); ++it) {
225  if (destKey == it->second.node.getKey()) {
226  treeChildNodes.erase(it);
227  //return;
228  }
229  }
230  } else if (dynamic_cast<ChildReleaseCall*>(msg)) {
231  //TODO there is no response...???
232  return;
233  } else std::cout << msg->getName() << std::endl;
234 
235  handleTimerEvent(treeBuildTimer);
236  */
237 }
238 
239 
241 {
242  EV << "|DD|> TreeManagement::connectToParent (=== PARENTCHECK for Node "
243  << overlay->getThisNode().getIp() <<" ===) <||" << endl;
244 
245  if(!checkParentValid()) {
246  EV << "|DD|> TreeManagement::connectToParent (Parent is not Valid) <||"
247  << endl;
248 
249  // add a new connection
251  }
252 }
253 
254 
256 {
257  if(parentNode.isUnspecified()) return;
258 
259  //TODO
261 
262  EV << "|DD|> TreeManagement::removeParentConnection (RELEASE Connection From "
263  << overlay->getThisNode().getIp()
264  << " to Parent " << parentNode.getIp() << ") <||" << endl;
265 
267 
269 }
270 
271 
273 {
274  ChildReleaseCall* childReleaseRequest = new ChildReleaseCall("ChildRelease");
275  simtime_t timeout = -1;
276 
277  childReleaseRequest->setBitLength(CHILDRELEASECALL_L(childReleaseRequest));
278 
281  bytesTMSent[currentTreeLevel] += childReleaseRequest->getByteLength();
282  }
283 
285  parentNode,
286  childReleaseRequest,
287  NULL,DEFAULT_ROUTING,
288  timeout, 0, -1, this
289  );
290 }
291 
292 
294 {
295  treeNodeMap::const_iterator nodeIterator = treeChildNodes.begin();
296  while (nodeIterator != treeChildNodes.end()) {
297  if(nodeIterator->second.lastTouch + timeOutInSeconds < simTime()) {
298  ChildCheckCall* childCheckCall = new ChildCheckCall("ChildCheckCall");
300  nodeIterator->second.node,
301  childCheckCall,
302  NULL, DEFAULT_ROUTING,
303  -1, 0, -1, this);
304  //neighborCache->pingNode(nodeIterator->second.node, -1, -1, NULL,
305  // "CheckChildAlive");
306  }
307  nodeIterator++;
308  }
309 }
310 
311 
313  cPolymorphic* context,
314  int rpcId, simtime_t rtt)
315 {
316  if (treeChildNodes.find(response->getSrcNode()) != treeChildNodes.end()) {
317  treeChildNodes.find(response->getSrcNode())->second.lastTouch = simTime();
318  }
319 }
320 
321 
322 /*
323 void TreeManagement::pingTimeout(PingCall* call, const TransportAddress& dest,
324  cPolymorphic* context, int rpcId)
325 {
326  EV << "|DD|> TreeManagement::pingTimeout() " << dest << " <||" << endl;
327  removeTreeChild(dest);
328 }
329 */
330 
331 
333 {
334  bool err = false;
335 
337  EV << "|DD|> TreeManagement::checkParentValid (Not Valid: Unspecified) <||" << endl;
338  return false;
339  }
340 
341  if(isRoot()) {
342  OverlayKey testKey = (OverlayKey::getMax()>>1);
343  if(overlay->isSiblingFor(overlay->getThisNode(), testKey ,1, &err)) {
344  //std::cout << neighborCache->getThisNode().getIp() << " is still ROOT" << std::endl;
345  EV << "[TreeManagement::checkParentValid() @ "
347  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
348  << " I'm still ROOT!"
349  << endl;
350  //std::cout << neighborCache->getThisNode().getIp() << " is still ROOT" << std::endl;
351  return true;
352  } else {
353  EV << "[TreeManagement::checkParentValid() @ "
355  << " (" << neighborCache->getThisNode().getKey().toString(16) << ")]\n"
356  << " I'm NOT longer ROOT!"
357  << endl;
358  //std::cout << simTime() << " " << neighborCache->getThisNode().getIp() << " is NOT longer ROOT" << std::endl;
359  return false;
360  }
361  }
362 
363  // 1. if my treeDomainKey is still valid
364  if(isTreeDomainKeyValid()) {
365  // 2. check if parent is responsible for my TreeDomainKey
366  bool isSiblingReturn = overlay->isSiblingFor(parentNode, treeDomainKey,1, &err);
367  if(isSiblingReturn && !err) {
368  // 3. check if I am not responsible for my TreeDomainKey
369  isSiblingReturn = overlay->isSiblingFor(overlay->getThisNode(), treeDomainKey, 1, &err);
370  if(!isSiblingReturn && !err) {
371  //std::cout << neighborCache->getThisNode().getIp() << " 3 checks passed" << std::endl;
372  EV << neighborCache->getThisNode().getIp() << " 3 checks passed" << endl;
373  return true;
374  }
375  }
376  }
377 
378  return false;
379 }
380 
381 
383 {
384  if (treeDomainKey.isUnspecified()) return false;
385 
387  return true;
388  } else {
389  return false;
390  }
391 }
392 
393 
395 {
397  return true;
398  } else {
399  return false;
400  }
401 }
402 
404 {
405  return (treeChildNodes.find(node) != treeChildNodes.end());
406 }
407 
408 
410 {
411  assert(!node.isUnspecified());
412  return (!parentNode.isUnspecified() && (node == parentNode));
413 }
414 
415 
417 {
418  cleanup();
420 }
421 
422 
424 {
426 
427  ParentRequestCall* parentReq = new ParentRequestCall("ParentRequest");
428  simtime_t timeout = -1;
429 
431 
432  parentReq->setBitLength(PARENTREQUESTCALL_L(parentReq));
433 
436  bytesTMSent[currentTreeLevel] += parentReq->getByteLength();
437  }
438 
441  parentReq,
442  NULL,DEFAULT_ROUTING,
443  timeout, 0, -1, this
444  );
445 
446  return true;
447 }
448 
449 
451 {
452 
453  removeTreeChild(msg->getSrcNode());
454 
455  delete msg;
456 }
457 
458 
460 {
461  if (parentNode.isUnspecified() || msg->getSrcNode() != parentNode) {
462  delete msg;
463  return;
464  }
465 
466  ChildCheckResponse* response = new ChildCheckResponse("ChildCheckReponse");
467  neighborCache->sendRpcResponse(msg, response);
468 }
469 
470 
472 {
473  if(treeChildNodes.empty()) return;
474 
475  //debugChildren();
476 
477  if(treeChildNodes.find(childToRemove) != treeChildNodes.end()) {
478  treeChildNodes.erase(childToRemove);
479  }
480 
481  //debugChildren();
482 }
483 
485 {
486  EV << "|DD|> TreeManagement::handleParentRequestRpcCall (ADDCHILDNODE!!! "
487  << msg->getSrcNode().getIp() << " to "
488  << overlay->getThisNode().getIp() << ") <||" << endl;
489 
490  /*
491  if (dynamic_cast<OverlayCtrlInfo*>(msg->getControlInfo())) {
492  //OverlayCtrlInfo* overlayCtrlInfo = static_cast<OverlayCtrlInfo*>(msg->getControlInfo());
493  if (msg->getDomainKey() != getResponsibleDomainKey().second) {
494  std::cout << neighborCache->getThisNode().getIp()
495  << ", msg->getDomainKey(): " << msg->getDomainKey()
496  << ", getResponsibleDomainKey().second: " << getResponsibleDomainKey().second
497  << " --> not responsible!" << std::endl;
498  //delete msg;
499  //return;
500  }
501  }
502  */
503  addChildNode(msg->getSrcNode());
504 
505  ParentRequestResponse* parentResp = new ParentRequestResponse("ParentResponse");
506  parentResp->setBitLength(PARENTREQUESTRESPONSE_L(parentResp));
507  neighborCache->sendRpcResponse(msg, parentResp);
508 }
509 
510 
512  cPolymorphic* context, int rpcId, simtime_t rtt)
513 {
514  EV << "|DD|> TreeManagement::handleParentRequestRpcResponse ("
515  << overlay->getThisNode().getIp() <<" ISCHILDOF "
516  << response->getSrcNode().getIp() << ") <||" << endl;
517 
518 
519  if(parentNode.isUnspecified() || response->getSrcNode() != parentNode) {
520  // remove old connection
522 
523  // add new connection
524  if (response->getSrcNode() == neighborCache->overlay->getThisNode()) {
525  //std::cout << simTime() << " " << neighborCache->getThisNode().getIp() << " (thinks that it) is now ROOT!" << std::endl;
526  }
527  parentNode = response->getSrcNode();
528 
529  // TODO
531  "m=m,50,0,50,0;ls=blue,1");
532 
533  //inform clients
534  for (msgClientMap::iterator it = msgClients.begin();
535  it != msgClients.end(); ++it) {
536  it->second->newParent();
537  }
538  } /*else {
539  std::cout << (parentNode.isUnspecified()?"parentNode.isUnspecified()":"NOT parentNode.isUnspecified()") << "\n"
540  << response->getSrcNode() << " " << parentNode << std::endl;
541  }*/
542 }
543 
544 
546 {
547  if (overlay->getThisNode() == childNode) return;
548  if (treeChildNodes.find(childNode) == treeChildNodes.end()) {
549  treeNodeEntry entry;
550 
551  entry.node = childNode;
552  entry.lastTouch = simTime();
553  treeChildNodes.insert(treeNodePair(childNode, entry));
554 
555  //inform clients
556  for (msgClientMap::iterator it = msgClients.begin();
557  it != msgClients.end(); ++it) {
558  it->second->newChild(childNode);
559  }
560  }
561 
562  debugChildren();
563 }
564 
566 {
567  std::stringstream shortChildMapString;
568 
569  shortChildMapString << "CL ";
570 
571  EV << "=== Children List of " << overlay->getThisNode().getIp() << "===" << endl;
572 
573  treeNodeMap::const_iterator nodeMapIterator = treeChildNodes.begin();
574 
575  while(nodeMapIterator != treeChildNodes.end()) {
576  EV << " - " << (*nodeMapIterator).first << endl;
577  shortChildMapString << (*nodeMapIterator).first.getIp() << " | ";
578  ++nodeMapIterator;
579  }
580 
581  //neighborCache->getParentModule()->getDisplayString().setTagArg("t2", 0, shortChildMapString.str().c_str());
582 
583  EV << "=====================" << endl;
584 }
585 
586 
588 {
589  NodeHandle node = overlay->getThisNode();
590  bool err = false;
591 
592  OverlayKey rightBorder = OverlayKey::getMax(); // 1
593  OverlayKey leftBorder = OverlayKey::ZERO;
594  OverlayKey testKey = OverlayKey::getMax()>>1; // middle of idSpace
595  OverlayKey domainKey = OverlayKey::getMax()>>1;
596 
597  int it = 1;
598  int maxIteration = overlay->par("keyLength");
599 
600  while(it < maxIteration) {
601 
602  domainKey = testKey;
603  testKey = (leftBorder>>1) + (rightBorder>>1);
604 
605  EV << "|DD|> TreeManagement::getResponsibleDomain (Checking: "
606  << testKey <<") <||" << endl;
607 
608  if(overlay->isSiblingFor(node, testKey,1, &err)) {
609  currentTreeLevel = it;
610  EV << "|DD|> TreeManagement::getResponsibleDomainKey ("
611  << "CURTREELEVEL: " << currentTreeLevel << ") <||" << endl;
612  return domainKey;
613  }
614 
615  if(err) {
616  EV << "|DD|> TreeManagement::getResponsibleDomain (ERROR WHILE CALLING isSiblingFor) <||" << endl;
617  }
618 
619  if(node.getKey().isBetween(leftBorder, testKey)) { // linke Seite
620  rightBorder = testKey;
621  } else if (node.getKey().isBetween((rightBorder+leftBorder)>>1,rightBorder)) {
622  leftBorder=testKey;
623  } else {
624  EV << "|DD|> TreeManagement::getResponsibleDomain (KEY IS THE BORDER!) <||" << endl;
625  }
626 
627  it++;
628  }
629 
630  return OverlayKey::ZERO;
631 }
632 
633 
635 {
637  return false;
638  }
639 
642  bytesTMSent[currentTreeLevel] += msg->getByteLength();
643  }
644 
645  /*
646  // send to key
647  neighborCache->sendRouteRpcCall(neighborCache->getThisCompType(),
648  treeDomainKey,
649  msg, NULL, DEFAULT_ROUTING,
650  -1 , 0, -1, this);
651  */
652 
653  // send directly
655  parentNode, msg, NULL, DEFAULT_ROUTING,
656  -1 , 0, -1, this);
657 
658  return true;
659 }
660 
661 
663 {
664  simtime_t timeout = -1;
665 
668  bytesTMSent[currentTreeLevel] += msg->getByteLength();
669  }
670 
671  treeNodeMap::const_iterator nodeMapIterator = treeChildNodes.begin();
672  while(nodeMapIterator != treeChildNodes.end()) {
673  /*
674  neighborCache->sendRouteRpcCall(neighborCache->getThisCompType(),
675  (*nodeMapIterator).second.node.getKey(),
676  msg->dup(),
677  NULL,DEFAULT_ROUTING,
678  timeout, 0, -1, this);
679  */
681  (*nodeMapIterator).second.node,
682  msg->dup(),
683  NULL,DEFAULT_ROUTING,
684  timeout, 0, -1, this);
685  ++nodeMapIterator;
686  }
687 
688  delete msg;
689  return true;
690 }
691 
692 
694 {
695  return parentNode;
696 }
697 
698 
700 {
701  return treeChildNodes;
702 }
703 
704 
705 void TreeManagement::addMsgClient(const char* identifier, AbstractTreeMsgClient* msgClient)
706 {
707  if(msgClients.find(identifier) == msgClients.end()) {
708  msgClients.insert(msgClientPair(identifier, msgClient));
709  }
710 
711 }
712 
713 
714 void TreeManagement::removeMsgClient(const char* identifier)
715 {
716  if(msgClients.find(identifier) != msgClients.end()) {
717  msgClients.erase(identifier);
718  }
719 }
720 
721 
723 {
724  return currentTreeLevel;
725 }
726 
727 
729 {
730  int i;
731  std::stringstream statName;
732 
734 
735  for(i = 1; i < MAXTREELEVEL; i++) {
736  if(numTMSent[i] > 0 || numTMReceived[i] > 0) {
737 
738  //int branchingFactor = 2;
739 
740  // messages sent per level
741  statName.str("");
742  statName << "TreeManagement Level " << i << " numTMSent/Node/s";
743  neighborCache->globalStatistics->addStdDev(statName.str(), (double)numTMSent[i] / SIMTIME_DBL(time) );
744 
745  statName.str("");
746  statName << "TreeManagement Level " << i << " numTMReceived/Node/s";
747  neighborCache->globalStatistics->addStdDev(statName.str(), (double)numTMReceived[i] / SIMTIME_DBL(time));
748 
749  statName.str("");
750  statName << "TreeManagement Level " << i << " numTMTotal/Node/s";
751  neighborCache->globalStatistics->addStdDev(statName.str(), ((double)numTMReceived[i] + (double)numTMSent[i]) / SIMTIME_DBL(time));
752 
753  // bytes per time send per level
754  statName.str("");
755  statName << "TreeManagement Level " << i << " bytesTMSent/Node/s";
756  neighborCache->globalStatistics->addStdDev(statName.str(), (double)bytesTMSent[i] / SIMTIME_DBL(time));
757 
758  statName.str("");
759  statName << "TreeManagement Level " << i << " bytesTMReceived/Node/s";
760  neighborCache->globalStatistics->addStdDev(statName.str(), (double)bytesTMReceived[i] / SIMTIME_DBL(time));
761 
762  statName.str("");
763  statName << "TreeManagement Level " << i << " bytesTMTotal/Node/s";
764  neighborCache->globalStatistics->addStdDev(statName.str(), ((double)bytesTMReceived[i] + (double)bytesTMSent[i]) / SIMTIME_DBL(time));
765  }
766  }
767 }
768