PastryRoutingTable Class Reference

#include <PastryRoutingTable.h>

Inheritance diagram for PastryRoutingTable:

PastryStateObject

List of all members.


Detailed Description

Routing table module.

This module contains the routing table of the Chord implementation.

Author:
Felix Palmen
See also:
Pastry

Public Member Functions

void initializeTable (uint bitsPerDigit, double repairTimeout, const NodeHandle &owner)
 Initializes the routing table.
const NodeHandlelookupNextHop (const OverlayKey &destination)
 gets the next hop 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 routing table.
void findCloserNodes (const OverlayKey &destination, NodeVector *nodes)
virtual const
TransportAddress
failedNode (const TransportAddress &failed)
 tells the routing table that a node has failed
virtual const
TransportAddress
repair (const PastryStateMessage *msg, const PastryStateMsgProximity &prox)
 attempt to repair the routing using a received REPAIR message
virtual void dumpToStateMessage (PastryStateMessage *msg) const
 dump content of the table to a PastryStateMessage
bool mergeNode (const NodeHandle &node, simtime_t prox)
 merge a node in the RoutingTable
bool initStateFromHandleVector (const std::vector< PastryStateMsgHandle > &handles)
 initialize table from vector of PastryStateMsgHandles with STATE messages received during JOIN phase.
virtual void dumpToVector (std::vector< TransportAddress > &affected) const
 appends all routing table entries to a given vector of TransportAddresses, needed to find all Nodes to be notified after joining.

Private Member Functions

virtual void earlyInit (void)
 initialize watches etc.
void addRow (void)
 adds a new line to the routing table
uint32_t digitAt (uint n, const OverlayKey &key) const
 returns n'th pastry digit from a key
const
PastryExtendedNode
nodeAt (uint row, uint col) const
 returns routing table entry at specified position
void findNextNodeToAsk (PRTTrackRepair &track) const
 helper function, updates a PRTTrackRepair structure to point to the next node that can be asked for repair

Private Attributes

uint bitsPerDigit
double repairTimeout
uint nodesPerRow
std::vector< PRTRowrows
std::vector
< PRTTrackRepair
awaitingRepair

Member Function Documentation

void PastryRoutingTable::initializeTable ( uint  bitsPerDigit,
double  repairTimeout,
const NodeHandle owner 
)

Initializes the routing table.

This should be called on startup

Parameters:
bitsPerDigit Pastry configuration parameter
repairTimeout Pastry configuration parameter
owner the node this table belongs to
00041 {
00042     this->owner = owner;
00043     this->repairTimeout = repairTimeout;
00044     this->bitsPerDigit = bitsPerDigit;
00045     nodesPerRow = 1 << bitsPerDigit; // 2 ^ bitsPerDigit
00046 
00047     // forget old routing table contents in case of restart:
00048     if (!rows.empty()) rows.clear();
00049 
00050     // clear pending repair requests:
00051     if (!awaitingRepair.empty()) awaitingRepair.clear();
00052 
00053     // Create first row in table:
00054     addRow();
00055 }

const NodeHandle & PastryRoutingTable::lookupNextHop ( const OverlayKey destination  ) 

gets the next hop according to the Pastry routing scheme.

Parameters:
destination the destination key
Returns:
the NodeHandle of the next Node or NodeHandle::UNSPECIFIED_NODE if no next hop could be determined
00067 {
00068     if (destination == owner.key) opp_error("trying to lookup own key!");
00069 
00070     uint shl = owner.key.sharedPrefixLength(destination) / bitsPerDigit;
00071     uint digit = digitAt(shl, destination);
00072 
00073     if (shl >= rows.size())
00074     {
00075         EV << "Pastry: Unable to find next hop for " << destination
00076             << ", row is empty." << endl;
00077         return NodeHandle::UNSPECIFIED_NODE;
00078     }
00079 
00080     const PastryExtendedNode& next = nodeAt(shl, digit);
00081 
00082     if (next.node.isUnspecified())
00083     {
00084         EV << "Pastry: Unable to find next hop for " << destination <<
00085             ", routing table entry is empty." << endl;
00086     }
00087     return next.node;
00088 }

const NodeHandle & PastryRoutingTable::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 routing table.

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.

00092 {
00093     if (destination == owner.key)
00094         opp_error("trying to find closer node to own key!");
00095 
00096     const PastryExtendedNode* entry;
00097 
00098     if (optimize)
00099     {
00100         // pointer to later return value, initialize to unspecified, so
00101         // the specialCloserCondition() check will be done against our own
00102         // node as long as no node closer to the destination than our own was
00103         // found.
00104         const NodeHandle* ret = &NodeHandle::UNSPECIFIED_NODE;
00105 
00106         // a numerically closer node can only be found in the row containing
00107         // nodes with the same prefix length and in the row above.
00108         int shl = owner.key.sharedPrefixLength(destination) / bitsPerDigit;
00109         int digit = digitAt(shl, destination);
00110         int x = digitAt(shl, owner.key); // position index of own node
00111 
00112         // first try the row with same prefix length:
00113         int n = nodesPerRow;
00114         int a = digit - 1; // position index of search to the left
00115         int b = digit + 1; // position index of search to the right
00116 
00117         while ((a >= 0) || (b < n))
00118         {
00119             // no need to continue search in one direction when own entry is
00120             // reached:
00121             if (a == x) a = -1;
00122             if (b == x) b = n;
00123 
00124             if (a >= 0)
00125             {
00126                 entry = &(nodeAt(shl, a));
00127                 if ((!entry->node.isUnspecified()) &&
00128                         specialCloserCondition(entry->node, destination, *ret))
00129                     ret = &(entry->node);
00130                 a--;
00131             }
00132             if (b < n)
00133             {
00134                 entry = &(nodeAt(shl, b));
00135                 if ((!entry->node.isUnspecified()) &&
00136                         specialCloserCondition(entry->node, destination, *ret))
00137                     ret = &(entry->node);
00138                 b++;
00139             }
00140         }
00141 
00142         // it this was not the first row, two more nodes to check:
00143         if (shl != 0)
00144         {
00145             // go up one row:
00146             x = digitAt(--shl, owner.key);
00147 
00148             if (destination < owner.key)
00149             {
00150                 entry = &(nodeAt(shl, digit - 1));
00151                 if ((!entry->node.isUnspecified()) && 
00152                         specialCloserCondition(entry->node, destination, *ret))
00153                     ret = &(entry->node);
00154             }
00155             else
00156             {
00157                 entry = &(nodeAt(shl, digit + 1));
00158                 if ((!entry->node.isUnspecified()) && 
00159                         specialCloserCondition(entry->node, destination, *ret))
00160                     ret = &(entry->node);
00161             }
00162         }
00163 
00164         return *ret; // still unspecified if no closer node was found
00165     }
00166     else
00167     {
00168         // no optimization, return the first closer node found
00169         for (uint y = 0; y < rows.size(); ++y)
00170         {
00171             for (uint x = 0; x < nodesPerRow; ++x)
00172             {
00173                 entry = &(nodeAt(y, x));
00174                 if ((!entry->node.isUnspecified()) &&
00175                         specialCloserCondition(entry->node, destination))
00176                     return entry->node;
00177             }
00178         }
00179 
00180         return NodeHandle::UNSPECIFIED_NODE;
00181     }
00182 }

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

Implements PastryStateObject.

00186 {
00187     //TODO
00188     const PastryExtendedNode* entry;
00189 
00190     for (uint y = 0; y < rows.size(); ++y) {
00191         for (uint x = 0; x < nodesPerRow; ++x) {
00192             entry = &(nodeAt(y, x));
00193             if (!entry->node.isUnspecified()
00194                 /* && specialCloserCondition(entry->node, destination)*/)
00195                 nodes->add(entry->node);
00196         }
00197     }
00198 }

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

tells the routing table that a node has failed

Parameters:
failed the failed node
Returns:
a node to ask for REPAIR or TransportAddress::UNSPECIFIED_NODE

Implements PastryStateObject.

00290 {
00291     std::vector<PRTRow>::iterator itRows;
00292     PRTRow::iterator itCols;
00293     PRTTrackRepair tmpTrack;
00294     
00295     bool found = false;
00296 
00297     // find node in table:
00298     for (itRows = rows.begin(); itRows != rows.end(); itRows++)
00299     {
00300         for (itCols = itRows->begin(); itCols != itRows->end(); itCols++)
00301         {
00302             if ((! itCols->node.isUnspecified()) &&
00303                     (itCols->node.ip == failed.ip))
00304             {
00305                 itCols->node = NodeHandle::UNSPECIFIED_NODE;
00306                 itCols->rtt = PASTRY_PROX_UNDEF;
00307                 found = true;
00308                 break;
00309             }
00310         }
00311         if (found) break;
00312     }
00313 
00314     // not found, nothing to do:
00315     if (!found) return TransportAddress::UNSPECIFIED_NODE;
00316 
00317     // else fill temporary record:
00318     tmpTrack.failedRow = itRows - rows.begin();
00319     tmpTrack.failedCol = itCols - itRows->begin();
00320     tmpTrack.node = TransportAddress::UNSPECIFIED_NODE;
00321     findNextNodeToAsk(tmpTrack);
00322     tmpTrack.timestamp = simTime();
00323 
00324     if (tmpTrack.node.isUnspecified())
00325         return TransportAddress::UNSPECIFIED_NODE;
00326     awaitingRepair.push_back(tmpTrack);
00327     return awaitingRepair.back().node;
00328 }

const TransportAddress & PastryRoutingTable::repair ( const PastryStateMessage *  msg,
const PastryStateMsgProximity prox 
) [virtual]

attempt to repair the routing 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.

00332 {
00333     std::vector<PRTTrackRepair>::iterator it;
00334     simtime_t now = simTime();
00335 
00336     // first eliminate outdated entries in awaitingRepair:
00337     for (it = awaitingRepair.begin(); it != awaitingRepair.end();)
00338     {
00339         if (it->timestamp < (now - repairTimeout))
00340             it = awaitingRepair.erase(it);
00341         else it++;
00342     }
00343 
00344     // don't expect any more repair messages:
00345     if (awaitingRepair.empty()) return TransportAddress::UNSPECIFIED_NODE;
00346 
00347     // look for source node in our list:
00348     for (it = awaitingRepair.begin(); it != awaitingRepair.end(); it++)
00349         if (it->node == msg->getSender()) break;
00350 
00351     // if not found, return from function:
00352     if (it == awaitingRepair.end()) return TransportAddress::UNSPECIFIED_NODE;
00353 
00354     // merge state:
00355     mergeState(msg, prox);
00356 
00357     // repair not yet done?
00358     if (nodeAt(it->failedRow, it->failedCol).node.isUnspecified())
00359     {
00360         // ask next node
00361         findNextNodeToAsk(*it);
00362         if (it->node.isUnspecified())
00363         {
00364             // no more nodes to ask, give up:
00365             EV << "Pastry: RoutingTable giving up repair attempt." << endl;
00366             awaitingRepair.erase(it);
00367             return TransportAddress::UNSPECIFIED_NODE;
00368         }
00369         else return it->node;
00370     }
00371     
00372     // repair done: clean up
00373     EV << "Pastry: RoutingTable repair was successful." << endl;
00374     awaitingRepair.erase(it);
00375     return TransportAddress::UNSPECIFIED_NODE;
00376 }

void PastryRoutingTable::dumpToStateMessage ( PastryStateMessage *  msg  )  const [virtual]

dump content of the table to a PastryStateMessage

Parameters:
msg the PastryStateMessage to be filled with entries

Implements PastryStateObject.

00201 {
00202     uint i = 0;
00203     std::vector<PRTRow>::const_iterator itRows;
00204     PRTRow::const_iterator itCols;
00205 
00206     msg->setRoutingTableArraySize(rows.size() * nodesPerRow);
00207 
00208     for (itRows = rows.begin(); itRows != rows.end(); itRows++)
00209         for (itCols = itRows->begin(); itCols != itRows->end(); itCols++)
00210             msg->setRoutingTable(i++, itCols->node);
00211 }

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

merge a node in the RoutingTable

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

Implements PastryStateObject.

00214 {
00215     if (node.key == owner.key)
00216         opp_error("trying to merge node with same key!");
00217 
00218     uint shl;
00219     uint digit;
00220     PRTRow::iterator position;
00221 
00222     shl = owner.key.sharedPrefixLength(node.key) / bitsPerDigit;
00223     digit = digitAt(shl, node.key);
00224 
00225     while (rows.size() <= shl) addRow();
00226     position = (rows.begin() + shl)->begin() + digit;
00227     if (position->node.isUnspecified() || (prox < position->rtt))
00228     {
00229         EV << "Pastry: Node " << owner.key << endl;
00230         EV << "        placing node " << node.key << "in row "
00231             << shl << ", col" << digit << endl;
00232         if (! position->node.isUnspecified())
00233         {
00234             EV << "        (replaced because of better proximity: "
00235                 << prox << " < " << position->rtt << ")" << endl;
00236         }
00237         position->node = node;
00238         position->rtt = prox;
00239         return true;
00240     }
00241     return false;
00242 }

bool PastryRoutingTable::initStateFromHandleVector ( const std::vector< PastryStateMsgHandle > &  handles  ) 

initialize table from vector of PastryStateMsgHandles with STATE messages received during JOIN phase.

The vector has to be sorted by JoinHopCount of the messages

Parameters:
handles the vector of PastryStateMsgHandles
Returns:
true on success
00246 {
00247     std::vector<PastryStateMsgHandle>::const_iterator it;
00248     int hopCheck = 0;
00249 
00250     for (it = handles.begin(); it != handles.end(); ++it)
00251     {
00252         if (it->msg->getJoinHopCount() != ++hopCheck) return false;
00253         mergeState(it->msg, *(it->prox));
00254     }
00255     return true;
00256 }

void PastryRoutingTable::dumpToVector ( std::vector< TransportAddress > &  affected  )  const [virtual]

appends all routing table entries to a given vector of TransportAddresses, needed to find all Nodes to be notified after joining.

Parameters:
affected the vector to fill with routing table entries

Implements PastryStateObject.

00260 {
00261     std::vector<PRTRow>::const_iterator itRows;
00262     PRTRow::const_iterator itCols;
00263 
00264     for (itRows = rows.begin(); itRows != rows.end(); itRows++)
00265         for (itCols = itRows->begin(); itCols != itRows->end(); itCols++)
00266             if (!itCols->node.isUnspecified())
00267                 affected.push_back(itCols->node);
00268 }

void PastryRoutingTable::earlyInit ( void   )  [private, virtual]

initialize watches etc.

Implements PastryStateObject.

00035 {
00036     WATCH_VECTOR(rows);
00037 }

void PastryRoutingTable::addRow ( void   )  [private]

adds a new line to the routing table

00271 {
00272     PRTRow row(nodesPerRow, unspecNode);
00273 
00274     // place own node at correct position:
00275     (row.begin() + digitAt(rows.size(), owner.key))->node = owner;
00276     rows.push_back(row);
00277 }

uint32_t PastryRoutingTable::digitAt ( uint  n,
const OverlayKey key 
) const [private]

returns n'th pastry digit from a key

Parameters:
n which digit to return
key extract digit from this key
Returns:
a pastry digit
00030 {
00031     return key.get(OverlayKey::getLength() - ++n*bitsPerDigit, bitsPerDigit);
00032 }

const PastryExtendedNode & PastryRoutingTable::nodeAt ( uint  row,
uint  col 
) const [private]

returns routing table entry at specified position

Parameters:
row the number of the row
col the number of the column
00058 {
00059     if (rows.size() <= row) return unspecNode;
00060     if (col >= nodesPerRow) return unspecNode;
00061 
00062     return *((rows.begin()+row)->begin()+col);
00063 }

void PastryRoutingTable::findNextNodeToAsk ( PRTTrackRepair track  )  const [private]

helper function, updates a PRTTrackRepair structure to point to the next node that can be asked for repair

Parameters:
track the PRTTrackRepair structure
00379 {
00380     const TransportAddress* ask;
00381 
00382     if (track.node.isUnspecified())
00383     {
00384         track.askedRow = track.failedRow;
00385         if (track.failedCol == 0)
00386             track.askedCol = 1;
00387         else
00388             track.askedCol = 0;
00389         ask = static_cast<const TransportAddress*>(
00390                 &(nodeAt(track.askedRow, track.askedCol).node));
00391         track.node = *ask;
00392         if ( (! track.node.isUnspecified()) &&
00393                 (track.node != owner) )
00394             return;
00395     }
00396 
00397     do
00398     {
00399         // point to next possible position in routing table:
00400         track.askedCol++;
00401         if ((track.askedRow == track.failedRow) &&
00402                 (track.askedCol == track.failedCol)) track.askedCol++;
00403         if (track.askedCol == nodesPerRow)
00404         {
00405             if ((track.askedRow > track.askedCol) ||
00406                     (track.askedRow == (rows.size() - 1)))
00407             {
00408                 // no more nodes that could be asked, give up:
00409                 track.node = TransportAddress::UNSPECIFIED_NODE;
00410                 return;
00411             }
00412             track.askedRow++;
00413             track.askedCol = 0;
00414         }
00415 
00416         ask = static_cast<const TransportAddress*>(
00417                 &(nodeAt(track.askedRow, track.askedCol).node));
00418        
00419 //         if (!ask->isUnspecified() && !track.node.isUnspecified() && track.node == *ask)
00420 //             std::cout << "burp! " << owner.key << " " << (static_cast<const NodeHandle*>(ask))->key << "\n("
00421 //                       << track.failedRow << ", " << track.failedCol << ") -> ("
00422 //                       << track.askedRow << ", " << track.askedCol << ")"
00423 //                       << std::endl;
00424         
00425         if(track.node.isUnspecified() ||
00426            (!ask->isUnspecified() && track.node != *ask)) track.node = *ask; //only happens if track.node == owner
00427         else track.node = TransportAddress::UNSPECIFIED_NODE;
00428     }
00429     while (track.node.isUnspecified() || (track.node == owner) );
00430 }


Member Data Documentation

uint PastryRoutingTable::bitsPerDigit [private]

double PastryRoutingTable::repairTimeout [private]

uint PastryRoutingTable::nodesPerRow [private]

std::vector<PRTRow> PastryRoutingTable::rows [private]

std::vector<PRTTrackRepair> PastryRoutingTable::awaitingRepair [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