PastryLeafSet Class Reference

#include <PastryLeafSet.h>

Inheritance diagram for PastryLeafSet:

PastryStateObject List of all members.

Detailed Description

PastryLeafSet module.

This module contains the LeafSet of the Pastry implementation.

Author:
Felix Palmen
See also:
Pastry


Public Member Functions

void initializeSet (uint numberOfLeaves, double repairTimeout, const NodeHandle &owner)
 Initializes the leaf set.
virtual const NodeHandlegetDestinationNode (const OverlayKey &destination)
 gets the final node according to the Pastry routing scheme.
virtual const NodeHandlefindCloserNode (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 TransportAddressfailedNode (const TransportAddress &failed)
 tells the leafset that a node has failed
virtual const TransportAddressrepair (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 NodeHandlegetPredecessor (void) const
 return predecessor node for visualizing
const NodeHandlegetSuccessor (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.
PastryNewLeafsMessagegetNewLeafsMessage (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 NodeHandlegetBiggestNode (void) const
 return the node with the biggest key in the LeafSet or NodeHandle::UNSPECIFIED_NODE if LeafSet is empty
const OverlayKeygetBiggestKey (void) const
 return the biggest key in the LeafSet or OverlayKey::UNSPECIFIED_KEY if LeafSet is empty
const NodeHandlegetSmallestNode (void) const
 return the node with the smallest key in the LeafSet or NodeHandle::UNSPECIFIED_NODE if LeafSet is empty
const OverlayKeygetSmallestKey (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< NodeHandleleaves
std::vector< NodeHandle
>::iterator 
smaller
std::vector< NodeHandle
>::iterator 
bigger
std::map< TransportAddress,
PLSRepairData
awaitingRepair
bool newLeafs


Member Function Documentation

void PastryLeafSet::dumpToStateMessage ( PastryStateMessage msg  )  const [virtual]

dump content of the set to a PastryStateMessage

Parameters:
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.

Parameters:
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]

initialize watches etc.

Implements PastryStateObject.

00030 {
00031     WATCH_VECTOR(leaves);
00032 }

const TransportAddress & PastryLeafSet::failedNode ( const TransportAddress failed  )  [virtual]

tells the leafset that a node has failed

Parameters:
failed the failed node
Returns:
a node to ask for REPAIR or TransportAddress::UNSPECIFIED_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.

Parameters:
destination the destination key
optimize if set, check all nodes and return the best/closest one
Returns:
a closer NodeHandle or NodeHandle::UNSPECIFIED_NODE if none was found

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

Returns:
biggest key in the set
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

Returns:
biggest node in the set
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.

Parameters:
destination the destination key
Returns:
the NodeHandle of the final node or NodeHandle::UNSPECIFIED_NODE if given destination key is outside the leaf set

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.

Returns:
pointer to newLeafs-message or NULL
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

return predecessor node for visualizing

00066 {
00067     return *smaller;
00068 }

const OverlayKey & PastryLeafSet::getSmallestKey ( void   )  const [private]

return the smallest key in the LeafSet or OverlayKey::UNSPECIFIED_KEY if LeafSet is empty

Returns:
smallest key in the set
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

Returns:
smallest node in the set
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

return successor node for visualizing

00061 {
00062     return *bigger;
00063 }

void PastryLeafSet::initializeSet ( uint  numberOfLeaves,
double  repairTimeout,
const NodeHandle owner 
)

Initializes the leaf set.

This should be called on startup

Parameters:
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

Parameters:
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

Parameters:
destination the key to check
Returns:
true if we are closest to given key
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

check if LeafSet knows at least one node to the left and to the right

00071 {
00072     return (!(smaller->isUnspecified() || bigger->isUnspecified()));
00073 }

bool PastryLeafSet::mergeNode ( const NodeHandle node,
simtime_t  prox 
) [virtual]

merge a node into LeafSet

Parameters:
node the node to merge
prox the proximity value of the node
Returns:
true if node was merged

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

Parameters:
msg the state message of type REPAIR
prox record of proximity values matching the state message
Returns:
another node to ask for REPAIR or TransportAddress::UNSPECIFIED_NODE

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 }


Member Data Documentation

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]


The documentation for this class was generated from the following files:
Generated on Fri May 11 14:52:40 2007 for ITM OverSim by  doxygen 1.4.7