OverSim
Koorde.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2007 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 
23 #include <IPAddressResolver.h>
24 #include <IPvXAddress.h>
25 #include <IInterfaceTable.h>
26 #include <IPv4InterfaceData.h>
27 #include <GlobalStatistics.h>
28 
29 #include "Koorde.h"
30 
31 using namespace std;
32 
33 namespace oversim {
34 
35 Define_Module(Koorde);
36 
37 void Koorde::initializeOverlay(int stage)
38 {
39  // because of IPAddressResolver, we need to wait until interfaces
40  // are registered, address auto-assignment takes place etc.
41  if (stage != MIN_STAGE_OVERLAY)
42  return;
43 
44  // fetch some parameters
45  deBruijnDelay = par("deBruijnDelay");
46  deBruijnListSize = par("deBruijnListSize");
47  shiftingBits = par("shiftingBits");
48  useOtherLookup = par("useOtherLookup");
49  useSucList = par("useSucList");
50  setupDeBruijnBeforeJoin = par("setupDeBruijnBeforeJoin");
51  setupDeBruijnAtJoin = par("setupDeBruijnAtJoin");
52 
53  // init flags
54  breakLookup = false;
55 
56  // some local variables
57  deBruijnNumber = 0;
58  deBruijnNodes = new NodeHandle[deBruijnListSize];
59 
60  // statistics
61  deBruijnCount = 0;
62  deBruijnBytesSent = 0;
63 
64  // add some watches
65  WATCH(deBruijnNumber);
66  WATCH(deBruijnNode);
67 
68  // timer messages
69  deBruijn_timer = new cMessage("deBruijn_timer");
70 
71  Chord::initializeOverlay(stage);
72 }
73 
74 Koorde::~Koorde()
75 {
76  cancelAndDelete(deBruijn_timer);
77 }
78 
79 void Koorde::changeState(int toState)
80 {
81  Chord::changeState(toState);
82 
83  switch(state) {
84  case INIT:
85  // init de Bruijn nodes
86  deBruijnNode = NodeHandle::UNSPECIFIED_NODE;
87 
88  for (int i=0; i < deBruijnListSize; i++) {
89  deBruijnNodes[i] = NodeHandle::UNSPECIFIED_NODE;
90  }
91 
92  updateTooltip();
93  break;
94  case JOIN:
95  if (setupDeBruijnBeforeJoin) {
96  // setup de bruijn node before joining the ring
97  cancelEvent(join_timer);
98  cancelEvent(deBruijn_timer);
99  scheduleAt(simTime(), deBruijn_timer);
100  } else if (setupDeBruijnAtJoin) {
101  cancelEvent(deBruijn_timer);
102  scheduleAt(simTime(), deBruijn_timer);
103  }
104  break;
105  case READY:
106  // init de Bruijn Protocol
107  cancelEvent(deBruijn_timer);
108  scheduleAt(simTime(), deBruijn_timer);
109 
110  // since we don't need the fixfingers protocol in Koorde cancel timer
111  cancelEvent(fixfingers_timer);
112  break;
113  default:
114  break;
115  }
116 
117 }
118 
119 void Koorde::handleTimerEvent(cMessage* msg)
120 {
121  if (msg->isName("deBruijn_timer")) {
122  handleDeBruijnTimerExpired();
123  } else if (msg->isName("fixfingers_timer")) {
124  handleFixFingersTimerExpired(msg);
125  } else {
126  Chord::handleTimerEvent(msg);
127  }
128 }
129 
130 bool Koorde::handleFailedNode(const TransportAddress& failed)
131 {
132  if (!deBruijnNode.isUnspecified()) {
133  if (failed == deBruijnNode) {
134  deBruijnNode = deBruijnNodes[0];
135  for (int i = 0; i < deBruijnNumber - 1; i++) {
136  deBruijnNodes[i] = deBruijnNodes[i+1];
137  }
138 
139  if (deBruijnNumber > 0) {
140  deBruijnNodes[deBruijnNumber - 1] = NodeHandle::UNSPECIFIED_NODE;
141  --deBruijnNumber;
142  }
143  } else {
144  bool removed = false;
145  for (int i = 0; i < deBruijnNumber - 1; i++) {
146  if ((!deBruijnNodes[i].isUnspecified()) &&
147  (failed == deBruijnNodes[i])) {
148  removed = true;
149  }
150  if (removed ||
151  ((!deBruijnNodes[deBruijnNumber - 1].isUnspecified())
152  && failed == deBruijnNodes[deBruijnNumber - 1])) {
153  deBruijnNodes[deBruijnNumber - 1] =
155  --deBruijnNumber;
156  }
157  }
158  }
159  }
160 
161  return Chord::handleFailedNode(failed);
162 }
163 
164 void Koorde::handleDeBruijnTimerExpired()
165 {
166  OverlayKey lookup = thisNode.getKey() << shiftingBits;
167 
168  if (state == READY) {
169  if (successorList->getSize() > 0) {
170  // look for some nodes before our actual de-bruijn key
171  // to have redundancy if our de-bruijn node fails
172  lookup -= (successorList->getSuccessor(successorList->getSize() /
173  2).getKey() - thisNode.getKey());
174  }
175 
176  if (lookup.isBetweenR(thisNode.getKey(),
177  successorList->getSuccessor().getKey())
178  || successorList->isEmpty()) {
179 
180  int sucNum = successorList->getSize();
181  if (sucNum > deBruijnListSize)
182  sucNum = deBruijnListSize;
183 
184  deBruijnNode = thisNode;
185  for (int i = 0; i < sucNum; i++) {
186  deBruijnNodes[i] = successorList->getSuccessor(i);
187  deBruijnNumber = i+1;
188  }
189 
190  updateTooltip();
191  } else if (lookup.isBetweenR(predecessorNode.getKey(),
192  thisNode.getKey())) {
193  int sucNum = successorList->getSize();
194  if ((sucNum + 1) > deBruijnListSize)
195  sucNum = deBruijnListSize - 1;
196 
197  deBruijnNode = predecessorNode;
198  deBruijnNodes[0] = thisNode;
199  for (int i = 0; i < sucNum; i++) {
200  deBruijnNodes[i+1] = successorList->getSuccessor(i);
201  deBruijnNumber = i+2;
202  }
203 
204  updateTooltip();
205  } else {
206  DeBruijnCall* call = new DeBruijnCall("DeBruijnCall");
207  call->setDestKey(lookup);
208  call->setBitLength(DEBRUIJNCALL_L(call));
209 
210  sendRouteRpcCall(OVERLAY_COMP, TransportAddress(deBruijnNode),
211  call->getDestKey(), call, NULL,
213  }
214 
215  cancelEvent(deBruijn_timer);
216  scheduleAt(simTime() + deBruijnDelay, deBruijn_timer);
217  } else {
218  if (setupDeBruijnBeforeJoin || setupDeBruijnAtJoin) {
219  DeBruijnCall* call = new DeBruijnCall("DeBruijnCall");
220  call->setDestKey(lookup);
221  call->setBitLength(DEBRUIJNCALL_L(call));
222 
223  sendRouteRpcCall(OVERLAY_COMP, bootstrapNode, call->getDestKey(),
224  call, NULL, DEFAULT_ROUTING);
225 
226  scheduleAt(simTime() + deBruijnDelay, deBruijn_timer);
227  }
228  }
229 }
230 
231 #if 0
232 void Koorde::handleFixFingersTimerExpired(cMessage* msg)
233 {
234  // just in case not all timers from Chord code could be canceled
235 }
236 #endif
237 
238 
239 void Koorde::handleUDPMessage(BaseOverlayMessage* msg)
240 {
241  Chord::handleUDPMessage(msg);
242 }
243 
244 
245 bool Koorde::handleRpcCall(BaseCallMessage* msg)
246 {
247  if (state == READY) {
248  // delegate messages
249  RPC_SWITCH_START( msg )
250  RPC_DELEGATE( DeBruijn, handleRpcDeBruijnRequest );
251  RPC_SWITCH_END( )
252 
253  if (RPC_HANDLED) return true;
254  } else {
255  EV << "[Koorde::handleRpcCall() @ " << thisNode.getIp()
256  << " (" << thisNode.getKey().toString(16) << ")]\n"
257  << " Received RPC call and state != READY!"
258  << endl;
259  }
260 
261  return Chord::handleRpcCall(msg);
262 }
263 
264 void Koorde::handleRpcResponse(BaseResponseMessage* msg,
265  cPolymorphic* context,
266  int rpcId, simtime_t rtt)
267 {
268  Chord::handleRpcResponse(msg, context, rpcId, rtt);
269 
270  RPC_SWITCH_START( msg )
271  RPC_ON_RESPONSE( DeBruijn ) {
272  handleRpcDeBruijnResponse(_DeBruijnResponse);
273  EV << "[Koorde::handleRpcResponse() @ " << thisNode.getIp()
274  << " (" << thisNode.getKey().toString(16) << ")]\n"
275  << " DeBruijn RPC Response received: id=" << rpcId
276  << "\n msg=" << *_DeBruijnResponse << " rtt=" << rtt
277  << endl;
278  break;
279  }
280  RPC_SWITCH_END( )
281 }
282 
283 void Koorde::handleRpcTimeout(BaseCallMessage* msg,
284  const TransportAddress& dest,
285  cPolymorphic* context, int rpcId,
286  const OverlayKey& destKey)
287 {
288  Chord::handleRpcTimeout(msg, dest, context, rpcId, destKey);
289 
290  RPC_SWITCH_START( msg )
291  RPC_ON_CALL( DeBruijn ) {
292  handleDeBruijnTimeout(_DeBruijnCall);
293  EV << "[Koorde::handleRpcTimeout() @ " << thisNode.getIp()
294  << " (" << thisNode.getKey().toString(16) << ")]\n"
295  << " DeBruijn RPC Call timed out: id=" << rpcId
296  << "\n msg=" << *_DeBruijnCall
297  << endl;
298  break;
299  }
300  RPC_SWITCH_END( )
301 }
302 
303 
304 void Koorde::handleRpcJoinResponse(JoinResponse* joinResponse)
305 {
306  Chord::handleRpcJoinResponse(joinResponse);
307 
308  // has to be canceled in Koorde
309  cancelEvent(fixfingers_timer);
310 
311  // immediate deBruijn protocol
312  cancelEvent(deBruijn_timer);
313  scheduleAt(simTime(), deBruijn_timer);
314 }
315 
316 
317 void Koorde::rpcJoin(JoinCall* joinCall)
318 {
319  Chord::rpcJoin(joinCall);
320 
321  if (predecessorNode == successorList->getSuccessor()) {
322  // second node join -> need to setup our de bruijn node
323  handleDeBruijnTimerExpired();
324  }
325 }
326 
327 
328 void Koorde::handleRpcDeBruijnRequest(DeBruijnCall* deBruijnCall)
329 {
330  // The key lies between thisNode and its predecessor and
331  // because routing the message to the predecessor of a key
332  // is near to impossible we set the deBruijnNodes here
333  // and the information is as actual as the predecessor pointer.
334  //
335  // If this is the only node in the ring, it is the temporary de bruijn
336  // node for the joining node.
337  if ((predecessorNode.isUnspecified() && successorList->isEmpty())
338  || deBruijnCall->getDestKey().isBetweenR(predecessorNode.getKey(),
339  thisNode.getKey())) {
340  DeBruijnResponse* deBruijnResponse =
341  new DeBruijnResponse("DeBruijnResponse");
342 
343  if (predecessorNode.isUnspecified()) {
344  deBruijnResponse->setDBNode(thisNode);
345  } else {
346  deBruijnResponse->setDBNode(predecessorNode);
347  }
348 
349  int sucNum = successorList->getSize() + 1;
350  deBruijnResponse->setSucNum(sucNum);
351  deBruijnResponse->setSucNodeArraySize(sucNum);
352 
353  deBruijnResponse->setSucNode(0, thisNode);
354  for (int k = 1; k < sucNum; k++) {
355  deBruijnResponse->setSucNode(k, successorList->getSuccessor(k-1));
356  }
357  deBruijnResponse->setBitLength(DEBRUIJNRESPONSE_L(deBruijnResponse));
358 
359  sendRpcResponse(deBruijnCall, deBruijnResponse);
360  } else if (deBruijnCall->getDestKey().isBetweenR(thisNode.getKey(),
361  successorList->getSuccessor().getKey())) {
362  error("Koorde::handleRpcDeBruijnRequest() - unknown error.");
363  } else {
364  error("Koorde::handleRpcDeBruijnRequest() - "
365  "Request couldn't be delivered!");
366  }
367 }
368 
369 void Koorde::handleRpcDeBruijnResponse(DeBruijnResponse* deBruijnResponse)
370 {
371  int sucNum = deBruijnResponse->getSucNum();
372  if (sucNum > deBruijnListSize)
373  sucNum = deBruijnListSize;
374 
375  for (int i = 0; i < sucNum; i++) {
376  deBruijnNodes[i] = deBruijnResponse->getSucNode(i);
377  deBruijnNumber = i+1;
378  }
379 
380  deBruijnNode = deBruijnResponse->getDBNode();
381 
382  updateTooltip();
383 
384  if (setupDeBruijnBeforeJoin && (state == JOIN)) {
385  // now that we have a valid de bruijn node it's time to join the ring
386  if (!join_timer->isScheduled()) {
387  scheduleAt(simTime(), join_timer);
388  }
389  }
390 }
391 
392 void Koorde::handleDeBruijnTimeout(DeBruijnCall* deBruijnCall)
393 {
394  if (setupDeBruijnBeforeJoin && (state == JOIN)) {
395  // failed to set initial de bruijn node
396  // -> get a new bootstrap node and try again
397  changeState(JOIN);
398  return;
399  }
400 
401  cancelEvent(deBruijn_timer);
402  scheduleAt(simTime(), deBruijn_timer);
403 }
404 
405 NodeVector* Koorde::findNode(const OverlayKey& key,
406  int numRedundantNodes,
407  int numSiblings,
408  BaseOverlayMessage* msg)
409 {
410  // TODO: return redundant nodes for iterative routing
411  // TODO: try to always calculate optimal routing key (if e.g.
412  // the originator didn't have its deBruijnNode set already, the
413  // routing key may be very far away on the ring)
414  NodeVector* nextHop = new NodeVector();
415  KoordeFindNodeExtMessage *findNodeExt = NULL;
416 
417  if (state != READY)
418  return nextHop;
419 
420  if (msg != NULL) {
421  if (!msg->hasObject("findNodeExt")) {
422  findNodeExt = new KoordeFindNodeExtMessage("findNodeExt");
424  findNodeExt->setStep(1);
425  findNodeExt->setBitLength(KOORDEFINDNODEEXTMESSAGE_L);
426  msg->addObject( findNodeExt );
427  }
428 
429  findNodeExt = (KoordeFindNodeExtMessage*) msg->getObject("findNodeExt");
430  }
431 
432  if (key.isUnspecified()) {
433  error("Koorde::findNode() - direct Messaging is no longer in use.");
434  } else if (key.isBetweenR(predecessorNode.getKey(), thisNode.getKey())) {
435  // the message is destined for this node
436  nextHop->push_back(thisNode);
437  } else if (key.isBetweenR(thisNode.getKey(),
438  successorList->getSuccessor().getKey())){
439  // the message destined for our successor
440  nextHop->push_back(successorList->getSuccessor());
441  } else {
442  // if useOtherLookup is enabled we try to use
443  // our successor list to get to the key
444  if (useOtherLookup) {
445  NodeHandle tmpNode = walkSuccessorList(key);
446  if (tmpNode !=
447  successorList->getSuccessor(successorList->getSize() - 1)) {
448  nextHop->push_back(tmpNode);
449  } else {
450  NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt);
451  if (tmpHandle != thisNode || breakLookup) {
452  nextHop->push_back(tmpHandle);
453  breakLookup = false;
454  } else {
455  return findNode(key, numRedundantNodes, numSiblings, msg);
456  }
457  }
458  } else {
459  // find next hop using either the de Bruijn node and
460  // its successors or our own successors
461  NodeHandle tmpHandle = findDeBruijnHop(key, findNodeExt);
462  if (tmpHandle != thisNode || breakLookup) {
463  nextHop->push_back(tmpHandle);
464  breakLookup = false;
465  } else {
466  return findNode(key, numRedundantNodes, numSiblings, msg);
467  }
468  }
469  }
470  return nextHop;
471 }
472 
473 NodeHandle Koorde::findDeBruijnHop(const OverlayKey& destKey,
474  KoordeFindNodeExtMessage* findNodeExt)
475 {
476  if (findNodeExt->getRouteKey().isUnspecified()) {
477  if (!deBruijnNode.isUnspecified()) {
478  int step;
479  findNodeExt->setRouteKey(findStartKey(thisNode.getKey(),
480  successorList->getSuccessor().getKey(), destKey,
481  step));
482  findNodeExt->setStep(step);
483  } else {
484  breakLookup = true;
485  return successorList->getSuccessor();
486  }
487  }
488 
489  // check if the route key falls in our responsibility or
490  // else forward the message to our successor
491  if (findNodeExt->getRouteKey().isBetweenR(thisNode.getKey(),
492  successorList->getSuccessor().getKey())) {
493  if ((unsigned int)findNodeExt->getStep() > destKey.getLength())
494  error("Koorde::findDeBruijnHop - Bounding error: "
495  "trying to get non existing bit out of overlay key!");
496 
497  // update the route key
498  OverlayKey add = OverlayKey(destKey.getBit(destKey.getLength() -
499  findNodeExt->getStep()));
500  for (int i = 1; i < shiftingBits; i++) {
501  add = (add << 1) + OverlayKey(destKey.getBit(destKey.getLength() -
502  findNodeExt->getStep() - i));
503  }
504 
505  OverlayKey routeKey = (findNodeExt->getRouteKey()<<shiftingBits) + add;
506  findNodeExt->setRouteKey(routeKey);
507  findNodeExt->setStep(findNodeExt->getStep() + shiftingBits);
508 
509  if (deBruijnNode.isUnspecified()) {
510  breakLookup = true;
511  if (useSucList)
512  return walkSuccessorList(findNodeExt->getRouteKey());
513  else
514  return successorList->getSuccessor();
515  }
516 
517  // check if the new route key falls between our
518  // de Bruijn node and its successor
519  if (deBruijnNumber > 0) {
520  if (findNodeExt->getRouteKey().isBetweenR(deBruijnNode.getKey(),
521  deBruijnNodes[0].getKey())) {
522  return deBruijnNode;
523  } else {
524  // otherwise check if the route key falls between
525  // our de Bruijn successors
526  NodeHandle nextHop = walkDeBruijnList(findNodeExt->
527  getRouteKey());
528  return nextHop;
529  }
530  } else {
531  return deBruijnNode;
532  }
533  } else {
534  breakLookup = true;
535  // if optimization is set search the successor list and
536  // de bruijn node to find "good" next hop
537  if (useSucList) {
538  if (deBruijnNode.isUnspecified()) {
539  return walkSuccessorList(findNodeExt->getRouteKey());
540  } else {
541  NodeHandle tmpHandle =
542  walkSuccessorList(findNodeExt->getRouteKey());
543 
544  // todo: optimization - check complete deBruijnList
545  if (deBruijnNode.getKey().isBetween(tmpHandle.getKey(),
546  findNodeExt->getRouteKey())) {
547  return deBruijnNode;
548  } else {
549  return tmpHandle;
550  }
551  }
552  } else
553  return successorList->getSuccessor();
554  }
555 }
556 
557 
558 const NodeHandle& Koorde::walkDeBruijnList(const OverlayKey& key)
559 {
560  if (deBruijnNumber == 0)
562 
563  for (int i = 0; i < deBruijnNumber-1; i++) {
564  if (key.isBetweenR(deBruijnNodes[i].getKey(),deBruijnNodes[i+1].getKey())) {
565  return deBruijnNodes[i];
566  }
567  }
568 
569  return deBruijnNodes[deBruijnNumber-1];
570 }
571 
572 const NodeHandle& Koorde::walkSuccessorList(const OverlayKey& key)
573 {
574  for (unsigned int i = 0; i < successorList->getSize()-1; i++) {
575  if (key.isBetweenR(successorList->getSuccessor(i).getKey(),
576  successorList->getSuccessor(i+1).getKey())) {
577  return successorList->getSuccessor(i);
578  }
579  }
580 
581  return successorList->getSuccessor(successorList->getSize()-1);
582 }
583 
584 void Koorde::updateTooltip()
585 {
586  //
587  // Updates the tooltip display strings.
588  //
589 
590  if (ev.isGUI()) {
591  std::stringstream ttString;
592 
593  // show our predecessor, successor and de Bruijn node in tooltip
594  ttString << "Pred "<< predecessorNode << endl << "This "
595  << thisNode << endl
596  << "Suc " << successorList->getSuccessor() << endl
597  << "DeBr " << deBruijnNode << endl;
598  ttString << "List ";
599 
600  for (unsigned int i = 0; i < successorList->getSize(); i++) {
601  ttString << successorList->getSuccessor(i).getIp() << " ";
602  }
603 
604  ttString << endl;
605  ttString << "DList ";
606 
607  for (int i = 0; i < deBruijnNumber; i++) {
608  ttString << deBruijnNodes[i].getIp() << " ";
609  }
610 
611  ttString << endl;
612 
613  getParentModule()->getParentModule()->
614  getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
615  getParentModule()->getDisplayString().setTagArg("tt", 0,
616  ttString.str().c_str());
617  getDisplayString().setTagArg("tt", 0, ttString.str().c_str());
618 
619  // draw an arrow to our current successor
620  showOverlayNeighborArrow(successorList->getSuccessor(), true,
621  "m=m,50,0,50,0;ls=red,1");
622  }
623 }
624 
625 
626 void Koorde::finishOverlay()
627 {
628  // statistics
629  simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
630 
631  if (time >= GlobalStatistics::MIN_MEASURED) {
632  globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Messages/s",
633  deBruijnCount / time);
634  globalStatistics->addStdDev("Koorde: Sent DEBRUIJN Bytes/s",
635  deBruijnBytesSent / time);
636  }
637 
638  Chord::finishOverlay();
639 }
640 
641 void Koorde::recordOverlaySentStats(BaseOverlayMessage* msg)
642 {
643  Chord::recordOverlaySentStats(msg);
644 
645  BaseOverlayMessage* innerMsg = msg;
646  while (innerMsg->getType() != APPDATA &&
647  innerMsg->getEncapsulatedPacket() != NULL) {
648  innerMsg =
649  static_cast<BaseOverlayMessage*>(innerMsg->getEncapsulatedPacket());
650  }
651 
652  switch (innerMsg->getType()) {
653  case RPC: {
654  if ((dynamic_cast<DeBruijnCall*>(innerMsg) != NULL) ||
655  (dynamic_cast<DeBruijnResponse*>(innerMsg) != NULL)) {
656  RECORD_STATS(deBruijnCount++; deBruijnBytesSent +=
657  msg->getByteLength());
658  }
659  break;
660  }
661  }
662 }
663 
664 OverlayKey Koorde::findStartKey(const OverlayKey& startKey,
665  const OverlayKey& endKey,
666  const OverlayKey& destKey,
667  int& step)
668 {
669  OverlayKey diffKey, newStart, tmpDest, newKey, powKey;
670  int nBits;
671 
672  if (startKey == endKey)
673  return startKey;
674 
675  diffKey = endKey - startKey;
676  nBits = diffKey.log_2();
677 
678  if (nBits < 0) {
679  nBits = 0;
680  }
681 
682  while ((startKey.getLength() - nBits) % shiftingBits != 0) {
683  nBits--;
684  }
685 
686  step = nBits + 1;
687 
688 #if 0
689  // TODO: work in progress to find better start key
690  uint shared;
691  for (shared = 0; shared < (startKey.getLength() - nBits); shared += shiftingBits) {
692  if (destKey.sharedPrefixLength(startKey << shared) >= (startKey.getLength() - nBits - shared)) {
693  break;
694  }
695  }
696 
697  uint nBits2 = startKey.getLength() - shared;
698 
699  newStart = (startKey >> nBits2) << nBits2;
700 
701  tmpDest = destKey >> (destKey.getLength() - nBits2);
702  newKey = tmpDest + newStart;
703 
704  std::cout << "startKey: " << startKey.toString(2) << endl
705  << "endKey : " << endKey.toString(2) << endl
706  << "diff : " << (endKey-startKey).toString(2) << endl
707  << "newKey : " << newKey.toString(2) << endl
708  << "destKey : " << destKey.toString(2) << endl
709  << "nbits : " << nBits << endl
710  << "nbits2 : " << nBits2 << endl;
711 
712  // is the new constructed route key bigger than our start key return it
713  if (newKey.isBetweenR(startKey, endKey)) {
714  std::cout << "HIT" << endl;
715  return newKey;
716  } else {
717  nBits2 -= shiftingBits;
718  newStart = (startKey >> nBits2) << nBits2;
719 
720  tmpDest = destKey >> (destKey.getLength() - nBits2);
721  newKey = tmpDest + newStart;
722 
723  if (newKey.isBetweenR(startKey, endKey)) {
724  std::cout << "startKey: " << startKey.toString(2) << endl
725  << "endKey : " << endKey.toString(2) << endl
726  << "diff : " << (endKey-startKey).toString(2) << endl
727  << "newKey : " << newKey.toString(2) << endl
728  << "destKey : " << destKey.toString(2) << endl
729  << "nbits : " << nBits << endl
730  << "nbits2 : " << nBits2 << endl;
731  std::cout << "HIT2" << endl;
732  return newKey;
733  }
734  }
735 
736  std::cout << "MISS" << endl;
737 #endif
738 
739  newStart = (startKey >> nBits) << nBits;
740 
741  tmpDest = destKey >> (destKey.getLength() - nBits);
742  newKey = tmpDest + newStart;
743 
744  // is the new constructed route key bigger than our start key return it
745  if (newKey.isBetweenR(startKey, endKey)) {
746  return newKey;
747  }
748 
749  // If the part of the destination key smaller than the one of
750  // the original key add pow(nBits) (this is the first bit where
751  // the start key and end key differ) to the new constructed key
752  // and check if it's between start and end key.
753  newKey += powKey.pow2(nBits);
754 
755  if (newKey.isBetweenR(startKey, endKey)) {
756  return newKey;
757  } else {
758  // this part should not be called
759  throw cRuntimeError("Koorde::findStartKey(): Invalid start key");
761  }
762 }
763 
764 void Koorde::findFriendModules()
765 {
766  successorList = check_and_cast<ChordSuccessorList*>
767  (getParentModule()->getSubmodule("successorList"));
768 }
769 
770 void Koorde::initializeFriendModules()
771 {
772  // initialize successor list
773  successorList->initializeList(par("successorListSize"), thisNode, this);
774 }
775 
776 }; //namespace
777