OverSim
PastryLeafSet.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2012 Institute of Telematics, Karlsruhe Institute of Technology (KIT)
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 
24 #include "PastryLeafSet.h"
25 #include "PastryTypes.h"
26 #include "NodeVector.h"
27 
28 #if 0
29 #define LEAF_TEST() \
30  do {\
31  uint32_t count = 0;\
32  uint32_t i = 0, j = leaves.size() - 1;\
33  while (leaves[i].isUnspecified() && i < j) ++i;\
34  while (leaves[j].isUnspecified() && i < j) --j;\
35  if (i == j) break;\
36  if (!owner.getKey().isBetween(leaves[(leaves.size() / 2) - 1].getKey(),\
37  leaves[leaves.size() / 2].getKey()))\
38  ASSERT2(false, "leafset broken!");\
39  for (uint32_t ci = i + 1; ci < j; ++ci) {\
40  if (leaves[ci - 1].getKey() >= leaves[ci].getKey()) {\
41  count++;\
42  }\
43  }\
44  if (leaves[j].getKey() >= leaves[i].getKey()) count++;\
45  ASSERT2(count <= 1, "leafset broken!");\
46  } while (false);
47 #else
48 #define LEAF_TEST() {}
49 #endif
50 
51 
53 
54 
56 {
57  WATCH_VECTOR(leaves);
58 }
59 
60 
61 void PastryLeafSet::initializeSet(uint32_t numberOfLeaves,
62  uint32_t bitsPerDigit,
63  simtime_t repairTimeout,
64  const NodeHandle& owner,
65  BasePastry *overlay)
66 {
67  if (numberOfLeaves % 2) throw "numberOfLeaves must be even.";
68 
69  this->owner = owner;
70  this->numberOfLeaves = numberOfLeaves;
71  this->repairTimeout = repairTimeout;
72  this->bitsPerDigit = bitsPerDigit;
73  this->overlay = overlay;
74 
75  if (!leaves.empty()) leaves.clear();
76 
77  // fill Set with unspecified node handles
78  for (uint32_t i = numberOfLeaves; i>0; i--)
80 
81  // initialize iterators to mark the beginning of bigger/smaller keys
82  // in the set
83  bigger = leaves.begin() + (numberOfLeaves >> 1);
84  smaller = bigger - 1;
85 
86  // reset repair marker:
87  if (!awaitingRepair.empty()) awaitingRepair.clear();
88 
89  newLeafs = false;
90  isFull = false;
91  wasFull = false;
92 }
93 
94 
96 {
97  return *bigger;
98 }
99 
100 
102 {
103  return *smaller;
104 }
105 
106 
108 {
109  return (!(smaller->isUnspecified() || bigger->isUnspecified()));
110 }
111 
112 
114 {
115  std::vector<NodeHandle>::const_iterator i;
116  const OverlayKey* smallest;
117  const OverlayKey* biggest;
119 
120  // check whether destination is inside leafSet:
121 
122  smallest = &(getSmallestKey());
123  biggest = &(getBiggestKey());
124  if (smallest->isUnspecified()) smallest = &(owner.getKey());
125  if (biggest->isUnspecified()) biggest = &(owner.getKey());
126 
127  if (!destination.isBetweenLR(*smallest, *biggest)) return *ret;
128 
129  // find the closest node:
130 
131  for (i = leaves.begin(); i != leaves.end(); i++) {
132  if (i->isUnspecified()) continue;
133 
134  // note for next line:
135  // * dereferences iterator, & gets address of element.
136  if (isCloser(*i, destination, *ret)) ret = &(*i);
137  }
138 
139  return *ret;
140 }
141 
142 
143 bool PastryLeafSet::isClosestNode(const OverlayKey& destination) const
144 {
145  // check for simple cases first
146  if (owner.getKey() == destination) {
147  return true;
148  }
149 
150  if (bigger->isUnspecified() && smaller->isUnspecified()) {
151  return true;
152  }
153 
154  // check if the next bigger or smaller node in the set is closer
155  // than own node
156  bool biggerIsCloser = false;
157  bool smallerIsCloser = false;
158 
159  if (! bigger->isUnspecified()) {
160  biggerIsCloser = isCloser(*bigger, destination);
161  }
162  if (! smaller->isUnspecified()) {
163  smallerIsCloser = isCloser(*smaller, destination);
164  }
165 
166  // return true if both are not closer
167  return ((!biggerIsCloser) && (!smallerIsCloser));
168 }
169 
170 
172 {
173  uint32_t i = 0;
174  uint32_t size = 0;
175  std::vector<NodeHandle>::const_iterator it;
176 
178  for (it = leaves.begin(); it != leaves.end(); it++) {
179  if (!it->isUnspecified()) {
180  ++size;
181  msg->setLeafSet(i++, *it);
182  }
183  }
184  msg->setLeafSetArraySize(size);
185 }
186 
187 
189 {
190  uint32_t rnd;
191  int i;
192 
193  rnd = intuniform(0, numberOfLeaves - 1, 0);
194  i = rnd;
195 
196  while (i < (int)leaves.size()) {
197  if (!leaves[i].isUnspecified()) return leaves[i];
198  else i++;
199  }
200  i = rnd;
201  while (i >= 0) {
202  if (!leaves[i].isUnspecified()) return leaves[i];
203  else i--;
204  }
205  EV << "Leafset::getRandomNode() returns UNSPECIFIED_NODE"
206  "Leafset empty??" << endl;
207 
209 }
210 
211 
213  int numSiblings) const
214 {
215  std::vector<NodeHandle>::const_iterator it;
216 
217  // create temporary comparator
220 
221  // create result vector
222  NodeVector* result = new NodeVector( numSiblings, comp );
223 
224  result->add(owner);
225 
226  for (it = leaves.begin(); it != leaves.end(); it++) {
227  if (!it->isUnspecified()) {
228  result->add(*it);
229  }
230  }
231 
232  delete comp;
233 
234  if (!isValid()) {
235  return result;
236  }
237 
238  // if the leafset is not full, we could have a very small network
239  // => return true (FIXME hack)
240  if (leaves.front().isUnspecified() || leaves.back().isUnspecified()) {
241  return result;
242  }
243 
244  if ((result->contains(getBiggestKey())) ||
245  (result->contains(getSmallestKey()))) {
246  delete result;
247  return NULL;
248  }
249 
250  return result;
251 }
252 
253 
254 bool PastryLeafSet::mergeNode(const NodeHandle& node, simtime_t prox)
255 {
256  assert(node != overlay->getThisNode());
257 
258  std::vector<NodeHandle>::iterator it, it_left, it_right;
259  const OverlayKey* last_left = &(owner.getKey());
260  const OverlayKey* last_right = &(owner.getKey());
261 
262  it_left = smaller;
263  it_right = bigger;
264 
265  // avoid duplicates
266  for (it = leaves.begin(); it != leaves.end(); ++it) {
267  if (it->isUnspecified()) {
268  isFull = false;
269  continue;
270  }
271  if (it->getKey() == node.getKey()) return false;
272  }
273 
274  // look for correct position in left and right half of leafset
275  while (true) {
276  if(!isFull) {
277  // both sides free
278  if(it_left->getKey().isUnspecified() &&
279  it_right->getKey().isUnspecified()) {
280  insertLeaf(it_left, node);
281  return true;
282  }
283  if (it_left->getKey().isUnspecified() &&
284  !node.getKey().isBetween(*last_right, it_right->getKey())) {
285  // end of smaller entries found
286  insertLeaf(it_left, node);
287  return true;
288  }
289  if (it_right->getKey().isUnspecified() &&
290  !node.getKey().isBetween(it_left->getKey(), *last_left)) {
291  // end of bigger entries found
292  insertLeaf(it_right, node);
293  return true;
294  }
295  }
296  // left side
297  if (node.getKey().isBetween(it_left->getKey(), *last_left)) {
298  // found correct position for inserting the new entry between
299  // existing ones
300  insertLeaf(it_left, node);
301  return true;
302  }
303  // right side
304  if (node.getKey().isBetween(*last_right, it_right->getKey())) {
305  // found correct position for inserting the new entry between
306  // existing ones
307  insertLeaf(it_right, node);
308  return true;
309  }
310 
311  last_right = &(it_right->getKey());
312  ++it_right;
313 
314  if (it_right == leaves.end()) break;
315 
316  last_left = &(it_left->getKey());
317  --it_left;
318  }
319  return false;
320 }
321 
322 
323 void PastryLeafSet::insertLeaf(std::vector<NodeHandle>::iterator& it,
324  const NodeHandle& node)
325 {
326  assert(node != overlay->getThisNode());
327 
328  LEAF_TEST();
329  bool issmaller = (it <= smaller);
330  if (issmaller) {
331  leaves.insert(++it, node);
332 
333  if (!leaves.front().isUnspecified()) {
334  assert(leaves.front() != node);
335 
336  if (leaves.back().isUnspecified()) {
337  leaves.back() = leaves.front();
338  EV << "[PastryLeafSet::insertLeaf() @ " << overlay->getThisNode().getIp()
339  << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
340  << " " << leaves.front().getIp() << " switched sides"
341  << endl;
342  } else {
343  EV << "[PastryLeafSet::insertLeaf() @ " << overlay->getThisNode().getIp()
344  << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
345  << " " << leaves.front().getIp() << " replaced with " << node.getIp()
346  << endl;
347  }
348  } else {
349  EV << "[PastryLeafSet::insertLeaf() @ " << overlay->getThisNode().getIp()
350  << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
351  << " " << node.getIp() << " added"
352  << endl;
353  }
354 
355  leaves.erase(leaves.begin());
356 
357 
358  } else {
359  leaves.insert(it, node);
360 
361  if (!leaves.back().isUnspecified()) {
362  assert(leaves.back() != node);
363 
364  if (leaves.front().isUnspecified()) {
365  leaves.front() = leaves.back();
366 
367  EV << "[PastryLeafSet::insertLeaf() @ " << overlay->getThisNode().getIp()
368  << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
369  << " " << leaves.back().getIp() << " switched sides"
370  << endl;
371  } else {
372 
373  EV << " [PastryLeafSet::insertLeaf() @ " << overlay->getThisNode().getIp()
374  << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
375  << " " << leaves.back().getIp() << " replaced with " << node.getIp()
376  << endl;
377  }
378  } else {
379  EV << "[PastryLeafSet::insertLeaf() @ " << overlay->getThisNode().getIp()
380  << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
381  << " " << node.getIp() << " added"
382  << endl;
383  }
384 
385  leaves.pop_back();
386  }
387 
388  if (!leaves.front().isUnspecified() &&
389  !leaves.back().isUnspecified()) {
390  isFull = true;
391  } else {
392  isFull = false;
393  }
394 
395  newLeafs = true;
396  bigger = leaves.begin() + (numberOfLeaves >> 1);
397  smaller = bigger - 1;
398 
399  // ensure balance in leafset
400  if (!isFull) {
401  balanceLeafSet();
402  }
403  LEAF_TEST();
404 }
405 
406 
408 {
409  if (isFull ||
410  (!leaves.front().isUnspecified() &&
411  !(leaves.end() - 2)->isUnspecified()) ||
412  (!leaves.back().isUnspecified() &&
413  !(leaves.begin() + 1)->isUnspecified()))
414  return false;
415 
416  std::vector<NodeHandle>::iterator it_left, it_right;
417 
418  for (it_left = smaller, it_right = bigger;
419  it_right != leaves.end(); --it_left, ++it_right) {
420  if (it_left->isUnspecified()) {
421  if (it_right->isUnspecified() ||
422  (it_right + 1) == leaves.end() ||
423  (it_right + 1)->isUnspecified()) return false;
424  *it_left = *(it_right + 1);
425  *(it_right + 1) = NodeHandle::UNSPECIFIED_NODE;
426  return true;
427  } else if (it_right->isUnspecified()) {
428 
429  if (it_left == leaves.begin() ||
430  (it_left - 1)->isUnspecified()) return false;
431  *it_right = *(it_left - 1);
432  *(it_left - 1) = NodeHandle::UNSPECIFIED_NODE;
433  return true;
434  }
435  }
436  throw cRuntimeError("This should not happen!");
437  return false;
438 }
439 
440 
441 void PastryLeafSet::dumpToVector(std::vector<TransportAddress>& affected) const
442 {
443  std::vector<NodeHandle>::const_iterator it;
444 
445  for (it = leaves.begin(); it != leaves.end(); it++)
446  if (!it->isUnspecified())
447  affected.push_back(*it);
448 }
449 
450 
452 {
453  std::vector<NodeHandle>::const_iterator i = leaves.begin();
454  while ((i->isUnspecified()) && (i != smaller)) i++;
455  assert(i->isUnspecified() || *i != overlay->getThisNode());
456  return *i;
457 }
458 
459 
461 {
462  return getSmallestNode().getKey();
463 }
464 
465 
467 {
468  std::vector<NodeHandle>::const_iterator i = leaves.end()-1;
469  while ((i->isUnspecified()) && (i != bigger)) i--;
470  assert(i->isUnspecified() || *i != overlay->getThisNode());
471  return *i;
472 }
473 
474 
476 {
477  return getBiggestNode().getKey();
478 }
479 
480 
482  NodeVector* nodes)
483 {
484  std::vector<NodeHandle>::const_iterator it;
485 
486  for (it = leaves.begin(); it != leaves.end(); it++)
487  if (!it->isUnspecified())
488  nodes->add(*it);
489 }
490 
491 
493  bool optimize)
494 {
495  std::vector<NodeHandle>::const_iterator i;
497 
498  // this will only be called after getDestinationNode() returned
499  // NodeHandle::UNSPECIFIED_NODE, so a closer Node can only be the biggest
500  // or the smallest node in the LeafSet.
501 
502  const NodeHandle& smallest = getSmallestNode();
503  const NodeHandle& biggest = getBiggestNode();
504 
505  if ((!smallest.isUnspecified()) &&
506  (specialCloserCondition(smallest, destination, *ret))) {
507  if (optimize) ret = &smallest;
508  else return smallest;
509  }
510 
511  if ((!biggest.isUnspecified()) &&
512  (specialCloserCondition(biggest, destination, *ret))) {
513  if (optimize) ret = &biggest;
514  else return biggest;
515  }
516 
517  return *ret;
518 }
519 
520 
522 {
523  std::vector<NodeHandle>::iterator i;
524  const TransportAddress* ask;
525  bool left = true;
526 
527  // search failed node in leafset:
528  for (i = leaves.begin(); i != leaves.end(); i++) {
529  if (i == bigger) left = false;
530  if ((! i->isUnspecified()) && (i->getIp() == failed.getIp())) break;
531  }
532 
533  // failed node not in leafset:
534  if (i == leaves.end()) return TransportAddress::UNSPECIFIED_NODE;
535 
536  overlay->callUpdate(*i, false);
537 
538  // remove failed node:
539  leaves.erase(i);
540  newLeafs = true;
541 
542  wasFull = isFull;
543  isFull = false;
544 
545  // insert UNSPECIFIED_NODE at front or back and return correct node
546  // to ask for repair:
547  if (left) {
548  leaves.insert(leaves.begin(), NodeHandle::UNSPECIFIED_NODE);
549  bigger = leaves.begin() + (numberOfLeaves >> 1);
550  smaller = bigger - 1;
551  ask = static_cast<const TransportAddress*>(&(getSmallestNode()));
552  } else {
554  bigger = leaves.begin() + (numberOfLeaves >> 1);
555  smaller = bigger - 1;
556  ask = static_cast<const TransportAddress*>(&(getBiggestNode()));
557  }
558 
559  assert(ask->isUnspecified() || *ask != overlay->getThisNode());
560 
561  balanceLeafSet();
562  LEAF_TEST();
563 
564  assert(ask->isUnspecified() || *ask != overlay->getThisNode());
565 
566  if (! ask->isUnspecified())
567  awaitingRepair[*ask] = PLSRepairData(simTime(), left);
568 
569  return *ask;
570 }
571 
572 
574  const PastryStateMsgProximity* prox)
575 {
576  std::map<TransportAddress, PLSRepairData>::iterator it;
577  const TransportAddress* ask;
578  bool left;
579 
580  simtime_t now = simTime();
581 
582  // first eliminate outdated entries in awaitingRepair:
583  for (it = awaitingRepair.begin(); it != awaitingRepair.end();) {
584  if (it->second.ts < (now - repairTimeout)) {
585  awaitingRepair.erase(it++);
586  }
587  else it++;
588  }
589 
590  // don't expect any more repair messages:
592 
593  // look for source node in our list:
594  if ( (it = awaitingRepair.find(msg->getSender())) == awaitingRepair.end() )
596 
597  // which side of the LeafSet is affected:
598  left = it->second.left;
599 
600  // remove source node from list:
601  awaitingRepair.erase(it);
602 
603  // merge info from repair message:
604  if (mergeState(msg, prox) || isFull || !wasFull) {
605  EV << "[PastryLeafSet::repair()]\n"
606  << " LeafSet repair was successful."
607  << endl;
609  } else {
610  // repair did not succeed, try again:
611  ask = &( left ? getSmallestNode() : getBiggestNode() );
612  if (ask->isUnspecified() || *ask == msg->getSender()) {
613  EV << "[PastryLeafSet::repair()]\n"
614  << " LeafSet giving up repair attempt."
615  << endl;
617  } else {
618  awaitingRepair[*ask] = PLSRepairData(simTime(), left);
619  }
620  return *ask;
621  }
622 }
623 
624 
626 {
627  std::vector<NodeHandle>::const_iterator it;
629  uint32_t i = 0;
630 
631  if (! newLeafs) return NULL;
632  newLeafs = false;
633 
634  msg = new PastryNewLeafsMessage("PastryNewLeafs");
635 
637  for (it = leaves.begin(); it != leaves.end(); it++)
638  msg->setLeafs(i++, *it);
639 
640  msg->setBitLength(PASTRYNEWLEAFS_L(msg));
641  return msg;
642 }
643 
644 
646 {
647  std::vector<OverlayKey> temp;
648  for (uint8_t i = 0; i < leaves.size() / 2; ++i) {
649  if (!leaves[i].isUnspecified()) {
650  temp.push_back(leaves[i].getKey());
651  }
652  }
653  temp.push_back(owner.getKey());
654  for (uint8_t i = leaves.size() / 2; i < leaves.size(); ++i) {
655  if (!leaves[i].isUnspecified()) {
656  temp.push_back(leaves[i].getKey());
657  }
658  }
659 
660  uint8_t num = 2;
661  uint8_t l = 1;
662  while (num < temp.size()) {
663  num *= 2;
664  ++l;
665  }
666  num /= 2;
667  --l;
668 
669 
671  for (uint8_t i = 0; i < num; ++i) {
672  //distances.push_back(KeyRingMetric().distance(temp[i], temp[i+1]));
673  mean += (KeyRingMetric().distance(temp[i], temp[i+1]) >> l);
674  }
675 
676  return mean;
677 }
678 
679 
681  const PastryStateMsgProximity* prox)
682 {
683  // LS to temp vector
684  std::vector<NodeHandle> temp = leaves; //getNodeHandleVector();
685 
686  bool result = PastryStateObject::mergeState(msg, prox);
687 
688  // nothing changed -> return without sending updates
689  if (!result) return false;
690 
691  // compare modified vector with temp
692  const std::vector<NodeHandle>& current = leaves; //getNodeHandleVector();
693 
694  // send updates (first "left", then "joined")
695  for (std::vector<NodeHandle>::const_iterator it = temp.begin();
696  it != temp.end(); ++it) {
697  if (it->isUnspecified()) continue;
698  std::vector<NodeHandle>::const_iterator it2;
699  for (it2 = current.begin(); it2 != current.end(); ++it2) {
700  if (it2->isUnspecified()) continue;
701  if (*it2 == *it) break;
702  }
703  if (it2 == current.end()) {
704  overlay->callUpdate(*it, false);
705  }
706  }
707  for (std::vector<NodeHandle>::const_iterator it = current.begin();
708  it != current.end(); ++it) {
709  if (it->isUnspecified()) continue;
710  std::vector<NodeHandle>::const_iterator it2;
711  for (it2 = temp.begin(); it2 != temp.end(); ++it2) {
712  if (it2->isUnspecified()) continue;
713  if (*it2 == *it) break;
714  }
715  if (it2 == temp.end()) {
716  overlay->callUpdate(*it, true);
717  }
718  }
719 
720  return result;
721 }