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, Pastry *overlay)
 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
Pastryoverlay
 pointer to the main pastry module
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,
Pastry overlay 
)

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

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.

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.

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.

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

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

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.

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

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

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

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

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

return predecessor node for visualizing

00082 {
00083     return *smaller;
00084 }

const NodeHandle & PastryLeafSet::getSuccessor ( void   )  const

return successor node for visualizing

00077 {
00078     return *bigger;
00079 }

bool PastryLeafSet::isValid ( void   )  const

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

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

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.

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.

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

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

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

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

Returns:
smallest key in the set
00330 {
00331     return getSmallestNode().key;
00332 }

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
00281 {
00282     return key.isBetweenL(opposite, owner.key);
00283 }

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


Member Data Documentation

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]


The documentation for this class was generated from the following files:
Generated on Wed Sep 26 12:13:02 2007 for ITM OverSim by  doxygen 1.5.1