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