#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. | |
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 | |
void | insertLeaf (std::vector< NodeHandle >::iterator &it, const NodeHandle &node) |
insert a leaf at a given position | |
Private Attributes | |
uint | numberOfLeaves |
double | repairTimeout |
std::vector< NodeHandle > | leaves |
std::vector< NodeHandle >::iterator | smaller |
std::vector< NodeHandle >::iterator | bigger |
std::map< TransportAddress, PLSRepairData > | awaitingRepair |
bool | newLeafs |
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.
00138 { 00139 uint i = 0; 00140 std::vector<NodeHandle>::const_iterator it; 00141 00142 msg->setLeafSetArraySize(numberOfLeaves); 00143 for (it = leaves.begin(); it != leaves.end(); it++) 00144 msg->setLeafSet(i++, *it); 00145 }
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.
00247 { 00248 std::vector<NodeHandle>::const_iterator it; 00249 00250 for (it = leaves.begin(); it != leaves.end(); it++) 00251 if (!it->isUnspecified()) 00252 affected.push_back(*it); 00253 }
void PastryLeafSet::earlyInit | ( | void | ) | [private, virtual] |
const TransportAddress & PastryLeafSet::failedNode | ( | const TransportAddress & | failed | ) | [virtual] |
tells the leafset that a node has failed
failed | the failed node |
Implements PastryStateObject.
00311 { 00312 std::vector<NodeHandle>::iterator i; 00313 const TransportAddress* ask; 00314 bool left = true; 00315 00316 // search failed node in leafset: 00317 for (i = leaves.begin(); i != leaves.end(); i++) 00318 { 00319 if (i == bigger) left = false; 00320 if ((! i->isUnspecified()) && (i->ip == failed.ip)) break; 00321 } 00322 00323 // failed node not in leafset: 00324 if (i == leaves.end()) return TransportAddress::UNSPECIFIED_NODE; 00325 00326 // remove failed node: 00327 leaves.erase(i); 00328 newLeafs = true; 00329 00330 // insert UNSPECIFIED_NODE at front or back and return correct node 00331 // to ask for repair: 00332 if (left) 00333 { 00334 leaves.insert(leaves.begin(), NodeHandle::UNSPECIFIED_NODE); 00335 bigger = leaves.begin() + (numberOfLeaves >> 1); 00336 smaller = bigger - 1; 00337 ask = static_cast<const TransportAddress*>(&(getSmallestNode())); 00338 } 00339 else 00340 { 00341 leaves.push_back(NodeHandle::UNSPECIFIED_NODE); 00342 bigger = leaves.begin() + (numberOfLeaves >> 1); 00343 smaller = bigger - 1; 00344 ask = static_cast<const TransportAddress*>(&(getBiggestNode())); 00345 } 00346 00347 if (! ask->isUnspecified()) 00348 awaitingRepair[*ask] = PLSRepairData(simTime(), left); 00349 00350 return *ask; 00351 }
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.
00281 { 00282 std::vector<NodeHandle>::const_iterator i; 00283 const NodeHandle* ret = &NodeHandle::UNSPECIFIED_NODE; 00284 00285 // this will only be called after getDestinationNode() returned 00286 // NodeHandle::UNSPECIFIED_NODE, so a closer Node can only be the biggest 00287 // or the smallest node in the LeafSet. 00288 00289 const NodeHandle& smallest = getSmallestNode(); 00290 const NodeHandle& biggest = getBiggestNode(); 00291 00292 if ((!smallest.isUnspecified()) && 00293 (specialCloserCondition(smallest, destination, *ret))) 00294 { 00295 if (optimize) ret = &smallest; 00296 else return smallest; 00297 } 00298 00299 if ((!biggest.isUnspecified()) && 00300 (specialCloserCondition(biggest, destination, *ret))) 00301 { 00302 if (optimize) ret = &biggest; 00303 else return biggest; 00304 } 00305 00306 return *ret; 00307 }
const OverlayKey & PastryLeafSet::getBiggestKey | ( | void | ) | const [private] |
return the biggest key in the LeafSet or OverlayKey::UNSPECIFIED_KEY if LeafSet is empty
00275 { 00276 return getBiggestNode().key; 00277 }
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
00268 { 00269 std::vector<NodeHandle>::const_iterator i = leaves.end()-1; 00270 while ((i->isUnspecified()) && (i != bigger)) i--; 00271 return *i; 00272 }
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.
00077 { 00078 std::vector<NodeHandle>::const_iterator i; 00079 const OverlayKey* smallest; 00080 const OverlayKey* biggest; 00081 const NodeHandle* ret = &NodeHandle::UNSPECIFIED_NODE; 00082 00083 // check whether destination is inside leafSet: 00084 00085 smallest = &(getSmallestKey()); 00086 biggest = &(getBiggestKey()); 00087 if (smallest->isUnspecified()) smallest = &(owner.key); 00088 if (biggest->isUnspecified()) biggest = &(owner.key); 00089 00090 if (!destination.isBetweenLR(*smallest, *biggest)) return *ret; 00091 00092 // find the closest node: 00093 00094 for (i = leaves.begin(); i != leaves.end(); i++) 00095 { 00096 if (i->isUnspecified()) continue; 00097 00098 // note for next line: 00099 // * dereferences iterator, & gets address of element. 00100 if (isCloser(*i, destination, *ret)) ret = &(*i); 00101 } 00102 00103 return *ret; 00104 }
PastryNewLeafsMessage * PastryLeafSet::getNewLeafsMessage | ( | void | ) |
generates a newLeafs-message if LeafSet changed since last call to this method.
00406 { 00407 std::vector<NodeHandle>::const_iterator it; 00408 PastryNewLeafsMessage* msg; 00409 uint i = 0; 00410 00411 if (! newLeafs) return NULL; 00412 newLeafs = false; 00413 00414 msg = new PastryNewLeafsMessage("PastryNewLeafs"); 00415 00416 msg->setLeafsArraySize(numberOfLeaves); 00417 for (it = leaves.begin(); it != leaves.end(); it++) 00418 msg->setLeafs(i++, *it); 00419 00420 msg->setLength(PASTRYNEWLEAFS_L(msg)); 00421 return msg; 00422 }
const NodeHandle & PastryLeafSet::getPredecessor | ( | void | ) | const |
const OverlayKey & PastryLeafSet::getSmallestKey | ( | void | ) | const [private] |
return the smallest key in the LeafSet or OverlayKey::UNSPECIFIED_KEY if LeafSet is empty
00263 { 00264 return getSmallestNode().key; 00265 }
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
00256 { 00257 std::vector<NodeHandle>::const_iterator i = leaves.begin(); 00258 while ((i->isUnspecified()) && (i != smaller)) i++; 00259 return *i; 00260 }
const NodeHandle & PastryLeafSet::getSuccessor | ( | void | ) | const |
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 |
00036 { 00037 if (numberOfLeaves % 2) throw "numberOfLeaves must be even."; 00038 00039 this->owner = owner; 00040 this->numberOfLeaves = numberOfLeaves; 00041 this->repairTimeout = repairTimeout; 00042 00043 if (!leaves.empty()) leaves.clear(); 00044 00045 // fill Set with unspecified node handles 00046 for (uint i = numberOfLeaves; i>0; i--) 00047 leaves.push_back(NodeHandle::UNSPECIFIED_NODE); 00048 00049 // initialize iterators to mark the beginning of bigger/smaller keys 00050 // in the set 00051 bigger = leaves.begin() + (numberOfLeaves >> 1); 00052 smaller = bigger - 1; 00053 00054 // reset repair marker: 00055 if (!awaitingRepair.empty()) awaitingRepair.clear(); 00056 00057 newLeafs = false; 00058 }
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 |
00229 { 00230 bool issmaller = (it <= smaller); 00231 if (issmaller) 00232 { 00233 leaves.insert(++it, node); 00234 leaves.erase(leaves.begin()); 00235 } 00236 else 00237 { 00238 leaves.insert(it, node); 00239 leaves.pop_back(); 00240 } 00241 newLeafs = true; 00242 bigger = leaves.begin() + (numberOfLeaves >> 1); 00243 smaller = bigger - 1; 00244 }
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 |
00107 { 00108 // check for simple cases first 00109 if (owner.key == destination) 00110 { 00111 return true; 00112 } 00113 00114 if (bigger->isUnspecified() && smaller->isUnspecified()) 00115 { 00116 return true; 00117 } 00118 00119 // check if the next bigger or smaller node in the set is closer 00120 // than own node 00121 bool biggerIsCloser = false; 00122 bool smallerIsCloser = false; 00123 00124 if (! bigger->isUnspecified()) 00125 { 00126 biggerIsCloser = isCloser(*bigger, destination); 00127 } 00128 if (! smaller->isUnspecified()) 00129 { 00130 smallerIsCloser = isCloser(*smaller, destination); 00131 } 00132 00133 // return true if both are not closer 00134 return ((!biggerIsCloser) && (!smallerIsCloser)); 00135 }
bool PastryLeafSet::isValid | ( | void | ) | const |
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.
00148 { 00149 std::vector<NodeHandle>::iterator it; 00150 bool ret = false; 00151 bool seenoverflow = false; 00152 const OverlayKey* last = &(owner.key); 00153 00154 // look for correct position in "smaller" half of leafset 00155 it = smaller; 00156 while (true) 00157 { 00158 if (it->key.isUnspecified()) 00159 { 00160 // end of smaller entries found 00161 if (!seenoverflow || (node.key < *last)) 00162 { 00163 // new entry can be put here if 00164 // - the key is smaller than the last seen in leafset 00165 // - or the 0 was not crossed yet 00166 insertLeaf(it, node); 00167 ret = true; 00168 } 00169 break; 00170 } 00171 else if (it->key == node.key) 00172 { 00173 // found the same entry, exit loop without doing anything 00174 break; 00175 } 00176 else if (node.key.isBetween(it->key, *last)) 00177 { 00178 // found correct position for inserting the new entry between 00179 // existing ones 00180 insertLeaf(it, node); 00181 ret = true; 00182 break; 00183 } 00184 00185 // continue processing the loop 00186 else if (it->key > *last) seenoverflow = true; 00187 if (it == leaves.begin()) break; 00188 last = &(it->key); 00189 --it; 00190 } 00191 00192 // look for correct position in "bigger" half of leafset, 00193 // details are the same as above. 00194 last = &(owner.key); 00195 seenoverflow = false; 00196 it = bigger; 00197 00198 while (it != leaves.end()) 00199 { 00200 if (it->key.isUnspecified()) 00201 { 00202 if (!seenoverflow || (node.key > *last)) 00203 { 00204 insertLeaf(it, node); 00205 ret = true; 00206 } 00207 break; 00208 } 00209 else if (it->key == node.key) 00210 { 00211 break; 00212 } 00213 else if (node.key.isBetween(*last, it->key)) 00214 { 00215 insertLeaf(it, node); 00216 ret = true; 00217 break; 00218 } 00219 else if (it->key < *last) seenoverflow = true; 00220 last = &(it->key); 00221 ++it; 00222 } 00223 00224 return ret; 00225 }
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.
00355 { 00356 std::map<TransportAddress, PLSRepairData>::iterator it; 00357 const TransportAddress* ask; 00358 bool left; 00359 00360 simtime_t now = simTime(); 00361 00362 // first eliminate outdated entries in awaitingRepair: 00363 for (it = awaitingRepair.begin(); it != awaitingRepair.end();) 00364 { 00365 if (it->second.ts < (now - repairTimeout)) 00366 awaitingRepair.erase(it++); 00367 else it++; 00368 } 00369 00370 // don't expect any more repair messages: 00371 if (awaitingRepair.empty()) return TransportAddress::UNSPECIFIED_NODE; 00372 00373 // look for source node in our list: 00374 if ( (it = awaitingRepair.find(msg->getSender())) == awaitingRepair.end() ) 00375 return TransportAddress::UNSPECIFIED_NODE; 00376 00377 // which side of the LeafSet is affected: 00378 left = it->second.left; 00379 00380 // remove source node from list: 00381 awaitingRepair.erase(it); 00382 00383 // merge info from repair message: 00384 if (mergeState(msg, prox)) 00385 { 00386 EV << "Pastry: LeafSet repair was successful." << endl; 00387 return TransportAddress::UNSPECIFIED_NODE; 00388 } 00389 else 00390 { 00391 // repair did not succeed, try again: 00392 ask = &( left ? getSmallestNode() : getBiggestNode() ); 00393 if (ask->isUnspecified()) 00394 { 00395 EV << "Pastry: LeafSet giving up repair attempt." << endl; 00396 } 00397 else 00398 { 00399 awaitingRepair[*ask] = PLSRepairData(simTime(), left); 00400 } 00401 return *ask; 00402 } 00403 }
std::map<TransportAddress, PLSRepairData> PastryLeafSet::awaitingRepair [private] |
std::vector<NodeHandle>::iterator PastryLeafSet::bigger [private] |
std::vector<NodeHandle> PastryLeafSet::leaves [private] |
bool PastryLeafSet::newLeafs [private] |
uint PastryLeafSet::numberOfLeaves [private] |
double PastryLeafSet::repairTimeout [private] |
std::vector<NodeHandle>::iterator PastryLeafSet::smaller [private] |