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.
NodeVectorcreateSiblingVector (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 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
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< NodeHandleleaves
std::vector< NodeHandle
>::iterator 
smaller
std::vector< NodeHandle
>::iterator 
bigger
std::map< TransportAddress,
PLSRepairData
awaitingRepair
bool newLeafs


Member Function Documentation

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

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.

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.

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.

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

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

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.

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

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

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

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

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

return predecessor node for visualizing

00081 {
00082     return *smaller;
00083 }

const NodeHandle & PastryLeafSet::getSuccessor ( void   )  const

return successor node for visualizing

00076 {
00077     return *bigger;
00078 }

bool PastryLeafSet::isValid ( void   )  const

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

00086 {
00087     return (!(smaller->isUnspecified() || bigger->isUnspecified()));
00088 }

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.

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.

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

initialize watches etc.

Implements PastryStateObject.

00042 {
00043     WATCH_VECTOR(leaves);
00044 }

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

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

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

Returns:
smallest key in the set
00320 {
00321     return getSmallestNode().key;
00322 }

bool PastryLeafSet::isLeft ( const OverlayKey key  )  const [inline, private]

test if a given key should be placed on the left or on the right side of the leaf set

Parameters:
key key to test
Returns:
true if key belongs to the left
00280 {
00281     return key.isBetweenL(opposite, owner.key);
00282 }

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
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 }


Member Data Documentation

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]


The documentation for this class was generated from the following files:
Generated on Tue Jul 24 16:51:19 2007 for ITM OverSim by  doxygen 1.5.1