#include <PastryLeafSet.h>
Inheritance diagram for PastryLeafSet:
This module contains the LeafSet of the Pastry implementation.
Public Member Functions | |
void | initializeSet (uint numberOfLeaves, double repairTimeout, const NodeHandle &owner, Pastry *overlay) |
Initializes the leaf set. | |
virtual const NodeHandle & | getDestinationNode (const OverlayKey &destination) |
gets the final node according to the Pastry routing scheme. | |
virtual const NodeHandle & | findCloserNode (const OverlayKey &destination, bool optimize=false) |
try to find a node numerically closer to a given key with the same shared prefix as the current node in the leaf set. | |
virtual const TransportAddress & | failedNode (const TransportAddress &failed) |
tells the leafset that a node has failed | |
virtual const TransportAddress & | repair (const PastryStateMessage *msg, const PastryStateMsgProximity &prox) |
attempt to repair the leafset using a received REPAIR message | |
bool | isClosestNode (const OverlayKey &destination) const |
checks if we are the closest node to key destination in the overlay | |
virtual void | dumpToStateMessage (PastryStateMessage *msg) const |
dump content of the set to a PastryStateMessage | |
bool | mergeNode (const NodeHandle &node, simtime_t prox) |
merge a node into LeafSet | |
const NodeHandle & | getPredecessor (void) const |
return predecessor node for visualizing | |
const NodeHandle & | getSuccessor (void) const |
return successor node for visualizing | |
bool | isValid (void) const |
check if LeafSet knows at least one node to the left and to the right | |
virtual void | dumpToVector (std::vector< TransportAddress > &affected) const |
appends all leaf set entries to a given vector of TransportAddresses, needed to find all Nodes to be notified after joining. | |
NodeVector * | createSiblingVector (const OverlayKey &key, int numSiblings) const |
PastryNewLeafsMessage * | getNewLeafsMessage (void) |
generates a newLeafs-message if LeafSet changed since last call to this method. | |
Private Member Functions | |
virtual void | earlyInit (void) |
initialize watches etc. | |
const NodeHandle & | getBiggestNode (void) const |
return the node with the biggest key in the LeafSet or NodeHandle::UNSPECIFIED_NODE if LeafSet is empty | |
const OverlayKey & | getBiggestKey (void) const |
return the biggest key in the LeafSet or OverlayKey::UNSPECIFIED_KEY if LeafSet is empty | |
const NodeHandle & | getSmallestNode (void) const |
return the node with the smallest key in the LeafSet or NodeHandle::UNSPECIFIED_NODE if LeafSet is empty | |
const OverlayKey & | getSmallestKey (void) const |
return the smallest key in the LeafSet or OverlayKey::UNSPECIFIED_KEY if LeafSet is empty | |
bool | isLeft (const OverlayKey &key) const |
test if a given key should be placed on the left or on the right side of the leaf set | |
void | insertLeaf (std::vector< NodeHandle >::iterator &it, const NodeHandle &node) |
insert a leaf at a given position | |
Private Attributes | |
uint | numberOfLeaves |
double | repairTimeout |
OverlayKey | opposite |
Pastry * | overlay |
pointer to the main pastry module | |
std::vector< NodeHandle > | leaves |
std::vector< NodeHandle >::iterator | smaller |
std::vector< NodeHandle >::iterator | bigger |
std::map< TransportAddress, PLSRepairData > | awaitingRepair |
bool | newLeafs |
void PastryLeafSet::initializeSet | ( | uint | numberOfLeaves, | |
double | repairTimeout, | |||
const NodeHandle & | owner, | |||
Pastry * | overlay | |||
) |
Initializes the leaf set.
This should be called on startup
numberOfLeaves | Pastry configuration parameter | |
repairTimeout | Pastry configuration parameter | |
owner | the node this table belongs to | |
overlay | pointer to the pastry main module |
00048 { 00049 if (numberOfLeaves % 2) throw "numberOfLeaves must be even."; 00050 00051 this->owner = owner; 00052 this->numberOfLeaves = numberOfLeaves; 00053 this->repairTimeout = repairTimeout; 00054 this->overlay = overlay; 00055 00056 // calculate opposite key needed by isLeft() 00057 opposite = owner.key ^ (OverlayKey::ONE << (OverlayKey::getLength() - 1)); 00058 00059 if (!leaves.empty()) leaves.clear(); 00060 00061 // fill Set with unspecified node handles 00062 for (uint i = numberOfLeaves; i>0; i--) 00063 leaves.push_back(NodeHandle::UNSPECIFIED_NODE); 00064 00065 // initialize iterators to mark the beginning of bigger/smaller keys 00066 // in the set 00067 bigger = leaves.begin() + (numberOfLeaves >> 1); 00068 smaller = bigger - 1; 00069 00070 // reset repair marker: 00071 if (!awaitingRepair.empty()) awaitingRepair.clear(); 00072 00073 newLeafs = false; 00074 }
const NodeHandle & PastryLeafSet::getDestinationNode | ( | const OverlayKey & | destination | ) | [virtual] |
gets the final node according to the Pastry routing scheme.
destination | the destination key |
Reimplemented from PastryStateObject.
00093 { 00094 std::vector<NodeHandle>::const_iterator i; 00095 const OverlayKey* smallest; 00096 const OverlayKey* biggest; 00097 const NodeHandle* ret = &NodeHandle::UNSPECIFIED_NODE; 00098 00099 // check whether destination is inside leafSet: 00100 00101 smallest = &(getSmallestKey()); 00102 biggest = &(getBiggestKey()); 00103 if (smallest->isUnspecified()) smallest = &(owner.key); 00104 if (biggest->isUnspecified()) biggest = &(owner.key); 00105 00106 if (!destination.isBetweenLR(*smallest, *biggest)) return *ret; 00107 00108 // find the closest node: 00109 00110 for (i = leaves.begin(); i != leaves.end(); i++) 00111 { 00112 if (i->isUnspecified()) continue; 00113 00114 // note for next line: 00115 // * dereferences iterator, & gets address of element. 00116 if (isCloser(*i, destination, *ret)) ret = &(*i); 00117 } 00118 00119 return *ret; 00120 }
const NodeHandle & PastryLeafSet::findCloserNode | ( | const OverlayKey & | destination, | |
bool | optimize = false | |||
) | [virtual] |
try to find a node numerically closer to a given key with the same shared prefix as the current node in the leaf set.
this method is to be called, when a regular next hop couldn't be found or wasn't reachable.
destination | the destination key | |
optimize | if set, check all nodes and return the best/closest one |
Implements PastryStateObject.
00348 { 00349 std::vector<NodeHandle>::const_iterator i; 00350 const NodeHandle* ret = &NodeHandle::UNSPECIFIED_NODE; 00351 00352 // this will only be called after getDestinationNode() returned 00353 // NodeHandle::UNSPECIFIED_NODE, so a closer Node can only be the biggest 00354 // or the smallest node in the LeafSet. 00355 00356 const NodeHandle& smallest = getSmallestNode(); 00357 const NodeHandle& biggest = getBiggestNode(); 00358 00359 if ((!smallest.isUnspecified()) && 00360 (specialCloserCondition(smallest, destination, *ret))) 00361 { 00362 if (optimize) ret = &smallest; 00363 else return smallest; 00364 } 00365 00366 if ((!biggest.isUnspecified()) && 00367 (specialCloserCondition(biggest, destination, *ret))) 00368 { 00369 if (optimize) ret = &biggest; 00370 else return biggest; 00371 } 00372 00373 return *ret; 00374 }
const TransportAddress & PastryLeafSet::failedNode | ( | const TransportAddress & | failed | ) | [virtual] |
tells the leafset that a node has failed
failed | the failed node |
Implements PastryStateObject.
00378 { 00379 std::vector<NodeHandle>::iterator i; 00380 const TransportAddress* ask; 00381 bool left = true; 00382 00383 // search failed node in leafset: 00384 for (i = leaves.begin(); i != leaves.end(); i++) 00385 { 00386 if (i == bigger) left = false; 00387 if ((! i->isUnspecified()) && (i->ip == failed.ip)) break; 00388 } 00389 00390 // failed node not in leafset: 00391 if (i == leaves.end()) return TransportAddress::UNSPECIFIED_NODE; 00392 00393 overlay->callUpdate(*i, false); 00394 00395 // remove failed node: 00396 leaves.erase(i); 00397 newLeafs = true; 00398 00399 // insert UNSPECIFIED_NODE at front or back and return correct node 00400 // to ask for repair: 00401 if (left) 00402 { 00403 leaves.insert(leaves.begin(), NodeHandle::UNSPECIFIED_NODE); 00404 bigger = leaves.begin() + (numberOfLeaves >> 1); 00405 smaller = bigger - 1; 00406 ask = static_cast<const TransportAddress*>(&(getSmallestNode())); 00407 } 00408 else 00409 { 00410 leaves.push_back(NodeHandle::UNSPECIFIED_NODE); 00411 bigger = leaves.begin() + (numberOfLeaves >> 1); 00412 smaller = bigger - 1; 00413 ask = static_cast<const TransportAddress*>(&(getBiggestNode())); 00414 } 00415 00416 if (! ask->isUnspecified()) 00417 awaitingRepair[*ask] = PLSRepairData(simTime(), left); 00418 00419 return *ask; 00420 }
const TransportAddress & PastryLeafSet::repair | ( | const PastryStateMessage * | msg, | |
const PastryStateMsgProximity & | prox | |||
) | [virtual] |
attempt to repair the leafset using a received REPAIR message
msg | the state message of type REPAIR | |
prox | record of proximity values matching the state message |
Reimplemented from PastryStateObject.
00424 { 00425 std::map<TransportAddress, PLSRepairData>::iterator it; 00426 const TransportAddress* ask; 00427 bool left; 00428 00429 simtime_t now = simTime(); 00430 00431 // first eliminate outdated entries in awaitingRepair: 00432 for (it = awaitingRepair.begin(); it != awaitingRepair.end();) 00433 { 00434 if (it->second.ts < (now - repairTimeout)) 00435 awaitingRepair.erase(it++); 00436 else it++; 00437 } 00438 00439 // don't expect any more repair messages: 00440 if (awaitingRepair.empty()) return TransportAddress::UNSPECIFIED_NODE; 00441 00442 // look for source node in our list: 00443 if ( (it = awaitingRepair.find(msg->getSender())) == awaitingRepair.end() ) 00444 return TransportAddress::UNSPECIFIED_NODE; 00445 00446 // which side of the LeafSet is affected: 00447 left = it->second.left; 00448 00449 // remove source node from list: 00450 awaitingRepair.erase(it); 00451 00452 // merge info from repair message: 00453 if (mergeState(msg, prox)) 00454 { 00455 EV << "Pastry: LeafSet repair was successful." << endl; 00456 return TransportAddress::UNSPECIFIED_NODE; 00457 } 00458 else 00459 { 00460 // repair did not succeed, try again: 00461 ask = &( left ? getSmallestNode() : getBiggestNode() ); 00462 if (ask->isUnspecified()) 00463 { 00464 EV << "Pastry: LeafSet giving up repair attempt." << endl; 00465 } 00466 else 00467 { 00468 awaitingRepair[*ask] = PLSRepairData(simTime(), left); 00469 } 00470 return *ask; 00471 } 00472 }
bool PastryLeafSet::isClosestNode | ( | const OverlayKey & | destination | ) | const |
checks if we are the closest node to key destination in the overlay
destination | the key to check |
00123 { 00124 // check for simple cases first 00125 if (owner.key == destination) 00126 { 00127 return true; 00128 } 00129 00130 if (bigger->isUnspecified() && smaller->isUnspecified()) 00131 { 00132 return true; 00133 } 00134 00135 // check if the next bigger or smaller node in the set is closer 00136 // than own node 00137 bool biggerIsCloser = false; 00138 bool smallerIsCloser = false; 00139 00140 if (! bigger->isUnspecified()) 00141 { 00142 biggerIsCloser = isCloser(*bigger, destination); 00143 } 00144 if (! smaller->isUnspecified()) 00145 { 00146 smallerIsCloser = isCloser(*smaller, destination); 00147 } 00148 00149 // return true if both are not closer 00150 return ((!biggerIsCloser) && (!smallerIsCloser)); 00151 }
void PastryLeafSet::dumpToStateMessage | ( | PastryStateMessage * | msg | ) | const [virtual] |
dump content of the set to a PastryStateMessage
msg | the PastryStateMessage to be filled with entries |
Implements PastryStateObject.
00154 { 00155 uint i = 0; 00156 std::vector<NodeHandle>::const_iterator it; 00157 00158 msg->setLeafSetArraySize(numberOfLeaves); 00159 for (it = leaves.begin(); it != leaves.end(); it++) 00160 msg->setLeafSet(i++, *it); 00161 }
bool PastryLeafSet::mergeNode | ( | const NodeHandle & | node, | |
simtime_t | prox | |||
) | [virtual] |
merge a node into LeafSet
node | the node to merge | |
prox | the proximity value of the node |
Implements PastryStateObject.
00210 { 00211 std::vector<NodeHandle>::iterator it; 00212 bool ret = false; 00213 const OverlayKey* last = &(owner.key); 00214 00215 if (isLeft(node.key)) 00216 { 00217 // look for correct position in left half of leafset 00218 it = smaller; 00219 while (true) 00220 { 00221 if (it->key.isUnspecified()) 00222 { 00223 // end of smaller entries found 00224 insertLeaf(it, node); 00225 ret = true; 00226 break; 00227 } 00228 else if (it->key == node.key) 00229 { 00230 // found the same entry, exit loop without doing anything 00231 break; 00232 } 00233 else if (node.key.isBetween(it->key, *last)) 00234 { 00235 // found correct position for inserting the new entry between 00236 // existing ones 00237 insertLeaf(it, node); 00238 ret = true; 00239 break; 00240 } 00241 00242 // continue processing the loop 00243 if (it == leaves.begin()) break; 00244 last = &(it->key); 00245 --it; 00246 } 00247 } 00248 else 00249 { 00250 // look for correct position in right half of leafset, 00251 // details are the same as above. 00252 it = bigger; 00253 00254 while (it != leaves.end()) 00255 { 00256 if (it->key.isUnspecified()) 00257 { 00258 insertLeaf(it, node); 00259 ret = true; 00260 break; 00261 } 00262 else if (it->key == node.key) 00263 { 00264 break; 00265 } 00266 else if (node.key.isBetween(*last, it->key)) 00267 { 00268 insertLeaf(it, node); 00269 ret = true; 00270 break; 00271 } 00272 last = &(it->key); 00273 ++it; 00274 } 00275 } 00276 00277 return ret; 00278 }
const NodeHandle & PastryLeafSet::getPredecessor | ( | void | ) | const |
const NodeHandle & PastryLeafSet::getSuccessor | ( | void | ) | const |
bool PastryLeafSet::isValid | ( | void | ) | const |
void PastryLeafSet::dumpToVector | ( | std::vector< TransportAddress > & | affected | ) | const [virtual] |
appends all leaf set entries to a given vector of TransportAddresses, needed to find all Nodes to be notified after joining.
affected | the vector to fill with leaf set entries |
Implements PastryStateObject.
00314 { 00315 std::vector<NodeHandle>::const_iterator it; 00316 00317 for (it = leaves.begin(); it != leaves.end(); it++) 00318 if (!it->isUnspecified()) 00319 affected.push_back(*it); 00320 }
NodeVector * PastryLeafSet::createSiblingVector | ( | const OverlayKey & | key, | |
int | numSiblings | |||
) | const |
00165 { 00166 std::vector<NodeHandle>::const_iterator it; 00167 00168 // create temporary comparator 00169 KeyDistanceComparator<KeyRingMetric>* comp = 00170 new KeyDistanceComparator<KeyRingMetric>( key ); 00171 00172 // create result vector 00173 NodeVector* result = new NodeVector( numSiblings, comp ); 00174 00175 result->add(owner); 00176 00177 for (it = leaves.begin(); it != leaves.end(); it++) { 00178 if (!it->isUnspecified()) { 00179 result->add(*it); 00180 } 00181 } 00182 00183 delete comp; 00184 00185 // cout << "Siblings for key: " << key << " num: " << numSiblings << endl << *result << endl; 00186 00187 if (!isValid()) { 00188 return result; 00189 } 00190 00191 // if the leafset is not full, we could have a very small network 00192 // => return true (FIXME hack) 00193 if (leaves.begin()->isUnspecified() || (leaves.end()-1)->isUnspecified()) { 00194 return result; 00195 } 00196 00197 if ( (result->contains(getBiggestKey())) 00198 || (result->contains(getSmallestKey()))) { 00199 00200 // cout << "PastryLeafSet: Don't know all siblings..." << endl; 00201 delete result; 00202 return NULL; 00203 } 00204 00205 return result; 00206 }
PastryNewLeafsMessage * PastryLeafSet::getNewLeafsMessage | ( | void | ) |
generates a newLeafs-message if LeafSet changed since last call to this method.
00475 { 00476 std::vector<NodeHandle>::const_iterator it; 00477 PastryNewLeafsMessage* msg; 00478 uint i = 0; 00479 00480 if (! newLeafs) return NULL; 00481 newLeafs = false; 00482 00483 msg = new PastryNewLeafsMessage("PastryNewLeafs"); 00484 00485 msg->setLeafsArraySize(numberOfLeaves); 00486 for (it = leaves.begin(); it != leaves.end(); it++) 00487 msg->setLeafs(i++, *it); 00488 00489 msg->setLength(PASTRYNEWLEAFS_L(msg)); 00490 return msg; 00491 }
void PastryLeafSet::earlyInit | ( | void | ) | [private, virtual] |
const NodeHandle & PastryLeafSet::getBiggestNode | ( | void | ) | const [private] |
return the node with the biggest key in the LeafSet or NodeHandle::UNSPECIFIED_NODE if LeafSet is empty
00335 { 00336 std::vector<NodeHandle>::const_iterator i = leaves.end()-1; 00337 while ((i->isUnspecified()) && (i != bigger)) i--; 00338 return *i; 00339 }
const OverlayKey & PastryLeafSet::getBiggestKey | ( | void | ) | const [private] |
return the biggest key in the LeafSet or OverlayKey::UNSPECIFIED_KEY if LeafSet is empty
00342 { 00343 return getBiggestNode().key; 00344 }
const NodeHandle & PastryLeafSet::getSmallestNode | ( | void | ) | const [private] |
return the node with the smallest key in the LeafSet or NodeHandle::UNSPECIFIED_NODE if LeafSet is empty
00323 { 00324 std::vector<NodeHandle>::const_iterator i = leaves.begin(); 00325 while ((i->isUnspecified()) && (i != smaller)) i++; 00326 return *i; 00327 }
const OverlayKey & PastryLeafSet::getSmallestKey | ( | void | ) | const [private] |
return the smallest key in the LeafSet or OverlayKey::UNSPECIFIED_KEY if LeafSet is empty
00330 { 00331 return getSmallestNode().key; 00332 }
bool PastryLeafSet::isLeft | ( | const OverlayKey & | key | ) | const [inline, private] |
void PastryLeafSet::insertLeaf | ( | std::vector< NodeHandle >::iterator & | it, | |
const NodeHandle & | node | |||
) | [private] |
insert a leaf at a given position
it | iterator where to insert the new leaf | |
node | NodeHandle of new leaf |
00287 { 00288 bool issmaller = (it <= smaller); 00289 if (issmaller) 00290 { 00291 if (!leaves.begin()->isUnspecified()) { 00292 overlay->callUpdate(*leaves.begin(), false); 00293 } 00294 overlay->callUpdate(node, true); 00295 leaves.insert(++it, node); 00296 leaves.erase(leaves.begin()); 00297 } 00298 else 00299 { 00300 if (!leaves.back().isUnspecified()) { 00301 overlay->callUpdate(leaves.back(), false); 00302 } 00303 overlay->callUpdate(node, true); 00304 00305 leaves.insert(it, node); 00306 leaves.pop_back(); 00307 } 00308 newLeafs = true; 00309 bigger = leaves.begin() + (numberOfLeaves >> 1); 00310 smaller = bigger - 1; 00311 }
uint PastryLeafSet::numberOfLeaves [private] |
double PastryLeafSet::repairTimeout [private] |
OverlayKey PastryLeafSet::opposite [private] |
Pastry* PastryLeafSet::overlay [private] |
pointer to the main pastry module
std::vector<NodeHandle> PastryLeafSet::leaves [private] |
std::vector<NodeHandle>::iterator PastryLeafSet::smaller [private] |
std::vector<NodeHandle>::iterator PastryLeafSet::bigger [private] |
std::map<TransportAddress, PLSRepairData> PastryLeafSet::awaitingRepair [private] |
bool PastryLeafSet::newLeafs [private] |