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
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.
void findCloserNodes (const OverlayKey &destination, NodeVector *nodes)
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 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
bool balanceLeafSet ()

Private Attributes

uint numberOfLeaves
double repairTimeout
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
bool isFull
bool wasFull

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     if (!leaves.empty()) leaves.clear();
00057 
00058     // fill Set with unspecified node handles
00059     for (uint i = numberOfLeaves; i>0; i--)
00060         leaves.push_back(NodeHandle::UNSPECIFIED_NODE);
00061 
00062     // initialize iterators to mark the beginning of bigger/smaller keys
00063     // in the set
00064     bigger = leaves.begin() + (numberOfLeaves >> 1);
00065     smaller = bigger - 1;
00066 
00067     // reset repair marker:
00068     if (!awaitingRepair.empty()) awaitingRepair.clear();
00069 
00070     newLeafs = false;
00071     isFull = false;
00072     wasFull = 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         if (i->isUnspecified()) continue;
00111 
00112         // note for next line:
00113         // * dereferences iterator, & gets address of element.
00114         if (isCloser(*i, destination, *ret)) ret = &(*i);
00115     }
00116 
00117     return *ret;
00118 }

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.

00393 {
00394     std::vector<NodeHandle>::const_iterator i;
00395     const NodeHandle* ret = &NodeHandle::UNSPECIFIED_NODE;
00396 
00397     // this will only be called after getDestinationNode() returned
00398     // NodeHandle::UNSPECIFIED_NODE, so a closer Node can only be the biggest
00399     // or the smallest node in the LeafSet.
00400 
00401     const NodeHandle& smallest = getSmallestNode();
00402     const NodeHandle& biggest = getBiggestNode();
00403 
00404     if ((!smallest.isUnspecified()) &&
00405             (specialCloserCondition(smallest, destination, *ret))) {
00406         if (optimize) ret = &smallest;
00407         else return smallest;
00408     }
00409 
00410     if ((!biggest.isUnspecified()) &&
00411             (specialCloserCondition(biggest, destination, *ret))) {
00412         if (optimize) ret = &biggest;
00413         else return biggest;
00414     }
00415 
00416     return *ret;
00417 }

void PastryLeafSet::findCloserNodes ( const OverlayKey destination,
NodeVector nodes 
) [virtual]

Implements PastryStateObject.

00382 {
00383     std::vector<NodeHandle>::const_iterator it;
00384 
00385     for (it = leaves.begin(); it != leaves.end(); it++)
00386         if (!it->isUnspecified())
00387             nodes->add(*it);
00388 
00389 }

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.

00421 {
00422     std::vector<NodeHandle>::iterator i;
00423     const TransportAddress* ask;
00424     bool left = true;
00425 
00426     // search failed node in leafset:
00427     for (i = leaves.begin(); i != leaves.end(); i++) {
00428         if (i == bigger) left = false;
00429         if ((! i->isUnspecified()) && (i->ip == failed.ip)) break;
00430     }
00431 
00432     // failed node not in leafset:
00433     if (i == leaves.end()) return TransportAddress::UNSPECIFIED_NODE;
00434 
00435     overlay->callUpdate(*i, false);
00436 
00437     // remove failed node:
00438     leaves.erase(i);
00439     newLeafs = true;
00440 
00441     wasFull = isFull;
00442     isFull = false;
00443 
00444     // insert UNSPECIFIED_NODE at front or back and return correct node
00445     // to ask for repair:
00446     if (left) {
00447         leaves.insert(leaves.begin(), NodeHandle::UNSPECIFIED_NODE);
00448         bigger = leaves.begin() + (numberOfLeaves >> 1);
00449         smaller = bigger - 1;
00450         ask = static_cast<const TransportAddress*>(&(getSmallestNode()));
00451     } else {
00452         leaves.push_back(NodeHandle::UNSPECIFIED_NODE);
00453         bigger = leaves.begin() + (numberOfLeaves >> 1);
00454         smaller = bigger - 1;
00455         ask = static_cast<const TransportAddress*>(&(getBiggestNode()));
00456     }
00457     
00458     balanceLeafSet();
00459 
00460     if (! ask->isUnspecified())
00461         awaitingRepair[*ask] = PLSRepairData(simTime(), left);
00462 
00463     return *ask;
00464 }

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.

00468 {
00469     std::map<TransportAddress, PLSRepairData>::iterator it;
00470     const TransportAddress* ask;
00471     bool left;
00472 
00473     simtime_t now = simTime();
00474 
00475     // first eliminate outdated entries in awaitingRepair:
00476     for (it = awaitingRepair.begin(); it != awaitingRepair.end();) {
00477         if (it->second.ts < (now - repairTimeout)) {
00478             //std::cout << "awaitingRepair.erase" << std::endl;     
00479             awaitingRepair.erase(it++);
00480         }
00481         else it++;
00482     }
00483 
00484     // don't expect any more repair messages:
00485     if (awaitingRepair.empty()) return TransportAddress::UNSPECIFIED_NODE;
00486 
00487     // look for source node in our list:
00488     if ( (it = awaitingRepair.find(msg->getSender())) == awaitingRepair.end() )
00489         return TransportAddress::UNSPECIFIED_NODE;
00490 
00491     // which side of the LeafSet is affected:
00492     left = it->second.left;
00493 
00494     // remove source node from list:
00495     awaitingRepair.erase(it);
00496 
00497     // merge info from repair message:
00498     if (mergeState(msg, prox) || isFull || !wasFull) {
00499         EV << "Pastry: LeafSet repair was successful." << endl;
00500         return TransportAddress::UNSPECIFIED_NODE;
00501     } else {
00502         // repair did not succeed, try again:
00503         ask = &( left ? getSmallestNode() : getBiggestNode() );
00504         if (ask->isUnspecified() || *ask == msg->getSender()) {
00505             EV << "Pastry: LeafSet giving up repair attempt." << endl;
00506             return TransportAddress::UNSPECIFIED_NODE;
00507         } else {
00508             awaitingRepair[*ask] = PLSRepairData(simTime(), left);
00509         }
00510         //assert(*ask != msg->getSender());
00511         return *ask;
00512     }
00513 }

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
00121 {
00122     // check for simple cases first
00123     if (owner.key == destination) {
00124         return true;
00125     }
00126 
00127     if (bigger->isUnspecified() && smaller->isUnspecified()) {
00128         return true;
00129     }
00130 
00131     // check if the next bigger or smaller node in the set is closer
00132     // than own node
00133     bool biggerIsCloser = false;
00134     bool smallerIsCloser = false;
00135 
00136     if (! bigger->isUnspecified()) {
00137         biggerIsCloser = isCloser(*bigger, destination);
00138     }
00139     if (! smaller->isUnspecified()) {
00140         smallerIsCloser = isCloser(*smaller, destination);
00141     }
00142 
00143     // return true if both are not closer
00144     return ((!biggerIsCloser) && (!smallerIsCloser));
00145 }

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.

00148 {
00149     uint i = 0;
00150     std::vector<NodeHandle>::const_iterator it;
00151 
00152     msg->setLeafSetArraySize(numberOfLeaves);
00153     for (it = leaves.begin(); it != leaves.end(); it++)
00154         msg->setLeafSet(i++, *it);
00155 }

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.

00203 {
00204     std::vector<NodeHandle>::iterator it, it_left, it_right;
00205     const OverlayKey* last_left = &(owner.key);
00206     const OverlayKey* last_right = &(owner.key);
00207 
00208     it_left = smaller;
00209     it_right = bigger;
00210 
00211     // avoid duplicates
00212     for (it = leaves.begin(); it != leaves.end(); ++it) {
00213         if (it->isUnspecified()) {
00214             isFull = false;
00215             continue;
00216         }
00217         if (it->key == node.key) return false;
00218     }
00219 
00220     // look for correct position in left and right half of leafset
00221     while (true) {
00222         if(!isFull) {
00223             // both sides free
00224             if(it_left->key.isUnspecified() &&
00225                it_right->key.isUnspecified()) {
00226                 insertLeaf(it_left, node);
00227                 return true;
00228             }
00229             if (it_left->key.isUnspecified() &&
00230                 !node.key.isBetween(*last_right, it_right->key)) {
00231                 // end of smaller entries found
00232                 insertLeaf(it_left, node);
00233                 return true;
00234             }
00235             if (it_right->key.isUnspecified() &&
00236                 !node.key.isBetween(it_left->key, *last_left)) {
00237                 // end of bigger entries found
00238                 insertLeaf(it_right, node);
00239                 return true;
00240             }
00241         }
00242         // left side
00243         if (node.key.isBetween(it_left->key, *last_left)) {
00244             // found correct position for inserting the new entry between
00245             // existing ones
00246             insertLeaf(it_left, node); 
00247             return true;
00248         } 
00249         // right side
00250         if (node.key.isBetween(*last_right, it_right->key)) {
00251             // found correct position for inserting the new entry between
00252             // existing ones
00253             insertLeaf(it_right, node);
00254             return true;
00255         }
00256 
00257         last_right = &(it_right->key);
00258         ++it_right;
00259         
00260         if (it_right == leaves.end()) break;
00261 
00262         last_left = &(it_left->key);
00263         --it_left;
00264     }
00265     return false;
00266 }

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.

00348 {
00349     std::vector<NodeHandle>::const_iterator it;
00350 
00351     for (it = leaves.begin(); it != leaves.end(); it++)
00352         if (!it->isUnspecified())
00353             affected.push_back(*it);
00354 }

NodeVector * PastryLeafSet::createSiblingVector ( const OverlayKey key,
int  numSiblings 
) const

00159 {
00160     std::vector<NodeHandle>::const_iterator it;
00161 
00162     // create temporary comparator
00163     KeyDistanceComparator<KeyRingMetric>* comp =
00164         new KeyDistanceComparator<KeyRingMetric>( key );
00165 
00166     // create result vector
00167     NodeVector* result = new NodeVector( numSiblings, comp );
00168 
00169     result->add(owner);
00170 
00171     for (it = leaves.begin(); it != leaves.end(); it++) {
00172         if (!it->isUnspecified()) {
00173             result->add(*it);
00174         }
00175     }
00176 
00177     delete comp;
00178 
00179 //    cout << "Siblings for key: " << key << " num: " << numSiblings << endl << *result << endl;
00180 
00181     if (!isValid()) {
00182         return result;
00183     }
00184 
00185     // if the leafset is not full, we could have a very small network
00186     // => return true (FIXME hack)
00187     if (leaves.front().isUnspecified() || leaves.back().isUnspecified()) {
00188         return result;
00189     }
00190 
00191     if ( (result->contains(getBiggestKey()))
00192             || (result->contains(getSmallestKey()))) {
00193 
00194 //              cout << "PastryLeafSet: Don't know all siblings..." << endl;
00195         delete result;
00196         return NULL;
00197     }
00198 
00199     return result;
00200 }

PastryNewLeafsMessage * PastryLeafSet::getNewLeafsMessage ( void   ) 

generates a newLeafs-message if LeafSet changed since last call to this method.

Returns:
pointer to newLeafs-message or NULL
00516 {
00517     std::vector<NodeHandle>::const_iterator it;
00518     PastryNewLeafsMessage* msg;
00519     uint i = 0;
00520 
00521     if (! newLeafs) return NULL;
00522     newLeafs = false;
00523 
00524     msg = new PastryNewLeafsMessage("PastryNewLeafs");
00525 
00526     msg->setLeafsArraySize(numberOfLeaves);
00527     for (it = leaves.begin(); it != leaves.end(); it++)
00528         msg->setLeafs(i++, *it);
00529 
00530     msg->setLength(PASTRYNEWLEAFS_L(msg));
00531     return msg;
00532 }

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
00369 {
00370     std::vector<NodeHandle>::const_iterator i = leaves.end()-1;
00371     while ((i->isUnspecified()) && (i != bigger)) i--;
00372     return *i;
00373 }

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
00376 {
00377     return getBiggestNode().key;
00378 }

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
00357 {
00358     std::vector<NodeHandle>::const_iterator i = leaves.begin();
00359     while ((i->isUnspecified()) && (i != smaller)) i++;
00360     return *i;
00361 }

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
00364 {
00365     return getSmallestNode().key;
00366 }

bool PastryLeafSet::isLeft ( const OverlayKey key  )  const [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

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
00270 {
00271     bool issmaller = (it <= smaller);
00272     if (issmaller) {
00273         if (!leaves.front().isUnspecified())  {
00274             overlay->callUpdate(leaves.front(), false);
00275         }
00276         overlay->callUpdate(node, true);
00277 
00278         leaves.insert(++it, node);
00279         NodeHandle& temp = leaves.front();
00280         if (!temp.isUnspecified() && leaves.back().isUnspecified()) {
00281             leaves.back() = temp;
00282         }
00283         leaves.erase(leaves.begin());
00284 
00285 
00286     } else {
00287         if (!leaves.back().isUnspecified())  {
00288             overlay->callUpdate(leaves.back(), false);
00289         }
00290         overlay->callUpdate(node, true);
00291 
00292         leaves.insert(it, node);
00293         NodeHandle& temp = leaves.back();
00294         if (!temp.isUnspecified() && leaves.front().isUnspecified()) {
00295             leaves.front() = temp;
00296         }
00297         leaves.pop_back();
00298     }
00299 
00300     if (!leaves.front().isUnspecified() &&
00301         !leaves.back().isUnspecified()) {
00302         isFull = true;
00303     } else isFull = false;
00304 
00305     newLeafs = true;
00306     bigger = leaves.begin() + (numberOfLeaves >> 1);
00307     smaller = bigger - 1;
00308 
00309     // ensure balance in leafset
00310     if (!isFull) {
00311         balanceLeafSet();
00312     }
00313 }

bool PastryLeafSet::balanceLeafSet (  )  [private]

00316 {
00317     if (isFull ||
00318         (!leaves.front().isUnspecified() &&
00319          !(leaves.end() - 2)->isUnspecified()) ||
00320         (!leaves.back().isUnspecified() &&
00321          !(leaves.begin() + 1)->isUnspecified())) 
00322         return false;
00323    
00324     std::vector<NodeHandle>::iterator it_left, it_right;
00325 
00326     for (it_left = smaller, it_right = bigger;
00327          it_right != leaves.end(); --it_left, ++it_right) {
00328         if (it_left->isUnspecified()) {
00329             if (it_right->isUnspecified() ||
00330                 (it_right + 1) == leaves.end() ||
00331                 (it_right + 1)->isUnspecified()) return false;
00332             *it_left = *(it_right + 1);
00333             *(it_right + 1) = NodeHandle::UNSPECIFIED_NODE;
00334             return true;
00335         } else if (it_right->isUnspecified()) {
00336 
00337             if (it_left == leaves.begin() ||
00338                 (it_left - 1)->isUnspecified()) return false;
00339             *it_right = *(it_left - 1);
00340             *(it_left - 1) = NodeHandle::UNSPECIFIED_NODE;
00341             return true;
00342         }
00343     }
00344     return false; // should not happen
00345 }


Member Data Documentation

uint PastryLeafSet::numberOfLeaves [private]

double PastryLeafSet::repairTimeout [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]

bool PastryLeafSet::isFull [private]

bool PastryLeafSet::wasFull [private]


The documentation for this class was generated from the following files:
Generated on Thu Apr 17 13:19:30 2008 for ITM OverSim by  doxygen 1.5.3