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 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 routing table.
virtual const TransportAddressfailedNode (const TransportAddress &failed)
 tells the routing table that a node has failed
virtual const TransportAddressrepair (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 initStateFromMsgVector (const std::vector< PastryStateMessage * > &messages, const std::vector< PastryStateMsgProximity > &proximities)
 initialize table from vector of PastryStateMessages 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 PastryExtendedNodenodeAt (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< PRTTrackRepairawaitingRepair


Member Function Documentation

void PastryRoutingTable::addRow ( void   )  [private]

adds a new line to the routing table

00252 {
00253     PRTRow row(nodesPerRow, unspecNode);
00254 
00255     // place own node at correct position:
00256     (row.begin() + digitAt(rows.size(), owner.key))->node = owner;
00257     rows.push_back(row);
00258 }

uint32_t PastryRoutingTable::digitAt ( uint  n,
const OverlayKey key 
) const [inline, 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 }

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.

00180 {
00181     uint i = 0;
00182     std::vector<PRTRow>::const_iterator itRows;
00183     PRTRow::const_iterator itCols;
00184 
00185     msg->setRoutingTableArraySize(rows.size() * nodesPerRow);
00186 
00187     for (itRows = rows.begin(); itRows != rows.end(); itRows++)
00188         for (itCols = itRows->begin(); itCols != itRows->end(); itCols++)
00189             msg->setRoutingTable(i++, itCols->node);
00190 }

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.

00241 {
00242     std::vector<PRTRow>::const_iterator itRows;
00243     PRTRow::const_iterator itCols;
00244 
00245     for (itRows = rows.begin(); itRows != rows.end(); itRows++)
00246         for (itCols = itRows->begin(); itCols != itRows->end(); itCols++)
00247             if (!itCols->node.isUnspecified())
00248                 affected.push_back(itCols->node);
00249 }

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

initialize watches etc.

Implements PastryStateObject.

00035 {
00036     WATCH_VECTOR(rows);
00037 }

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.

00271 {
00272     std::vector<PRTRow>::iterator itRows;
00273     PRTRow::iterator itCols;
00274     PRTTrackRepair tmpTrack;
00275     
00276     bool found = false;
00277 
00278     // find node in table:
00279     for (itRows = rows.begin(); itRows != rows.end(); itRows++)
00280     {
00281         for (itCols = itRows->begin(); itCols != itRows->end(); itCols++)
00282         {
00283             if ((! itCols->node.isUnspecified()) &&
00284                     (itCols->node.ip == failed.ip))
00285             {
00286                 itCols->node = NodeHandle::UNSPECIFIED_NODE;
00287                 itCols->rtt = PASTRY_PROX_UNDEF;
00288                 found = true;
00289                 break;
00290             }
00291         }
00292         if (found) break;
00293     }
00294 
00295     // not found, nothing to do:
00296     if (!found) return TransportAddress::UNSPECIFIED_NODE;
00297 
00298     // else fill temporary record:
00299     tmpTrack.failedRow = itRows - rows.begin();
00300     tmpTrack.failedCol = itCols - itRows->begin();
00301     tmpTrack.node = TransportAddress::UNSPECIFIED_NODE;
00302     findNextNodeToAsk(tmpTrack);
00303     tmpTrack.timestamp = simTime();
00304 
00305     if (tmpTrack.node.isUnspecified())
00306         return TransportAddress::UNSPECIFIED_NODE;
00307     awaitingRepair.push_back(tmpTrack);
00308     return awaitingRepair.back().node;
00309 }

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.

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

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
00360 {
00361     const TransportAddress* ask;
00362 
00363     if (track.node.isUnspecified())
00364     {
00365         track.askedRow = track.failedRow;
00366         if (track.failedCol == 0)
00367             track.askedCol = 1;
00368         else
00369             track.askedCol = 0;
00370         ask = static_cast<const TransportAddress*>(
00371                 &(nodeAt(track.askedRow, track.askedCol).node));
00372         track.node = *ask;
00373         if (! track.node.isUnspecified()) return;
00374     }
00375 
00376     do
00377     {
00378         // point to next possible position in routing table:
00379         track.askedCol++;
00380         if ((track.askedRow == track.failedRow) &&
00381                 (track.askedCol == track.failedCol)) track.askedCol++;
00382         if (track.askedCol == nodesPerRow)
00383         {
00384             if ((track.askedRow > track.askedCol) ||
00385                     (track.askedRow == (rows.size() - 1)))
00386             {
00387                 // no more nodes that could be asked, give up:
00388                 track.node = TransportAddress::UNSPECIFIED_NODE;
00389                 return;
00390             }
00391             track.askedRow++;
00392             track.askedCol = 0;
00393         }
00394 
00395         ask = static_cast<const TransportAddress*>(
00396                 &(nodeAt(track.askedRow, track.askedCol).node));
00397         track.node = *ask;
00398     }
00399     while (track.node.isUnspecified());
00400 }

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 }

bool PastryRoutingTable::initStateFromMsgVector ( const std::vector< PastryStateMessage * > &  messages,
const std::vector< PastryStateMsgProximity > &  proximities 
)

initialize table from vector of PastryStateMessages received during JOIN phase.

The vector has to be sorted by JoinHopCount of the messages

Parameters:
messages the vector of PastryStateMessages
proximities a vector of corresponding proximity tables
Returns:
true on success
00223 {
00224     std::vector<PastryStateMessage*>::const_iterator itMsg;
00225     std::vector<PastryStateMsgProximity>::const_iterator itProx;
00226     PastryStateMessage* msg;
00227     int hopCheck = 0;
00228 
00229     itProx = proximities.begin();
00230     for (itMsg = messages.begin(); itMsg != messages.end(); itMsg++)
00231     {
00232         msg = *itMsg;
00233         if (msg->getJoinHopCount() != ++hopCheck) return false;
00234         mergeState(msg, *(itProx++));
00235     }
00236     return true;
00237 }

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     uint shl = owner.key.sharedPrefixLength(destination) / bitsPerDigit;
00069     uint digit = digitAt(shl, destination);
00070 
00071     if (shl >= rows.size())
00072     {
00073         EV << "Pastry: Unable to find next hop for " << destination
00074             << ", row is empty." << endl;
00075         return NodeHandle::UNSPECIFIED_NODE;
00076     }
00077 
00078     const PastryExtendedNode& next = nodeAt(shl, digit);
00079 
00080     if (next.node.isUnspecified())
00081     {
00082         EV << "Pastry: Unable to find next hop for " << destination <<
00083             ", routing table entry is empty." << endl;
00084     }
00085     return next.node;
00086 }

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.

00193 {
00194     uint shl;
00195     uint digit;
00196     PRTRow::iterator position;
00197 
00198     shl = owner.key.sharedPrefixLength(node.key) / bitsPerDigit;
00199     digit = digitAt(shl, node.key);
00200 
00201     while (rows.size() <= shl) addRow();
00202     position = (rows.begin() + shl)->begin() + digit;
00203     if (position->node.isUnspecified() || (prox < position->rtt))
00204     {
00205         EV << "Pastry: Node " << owner.key << endl;
00206         EV << "        placing node " << node.key << "in row "
00207             << shl << ", col" << digit << endl;
00208         if (! position->node.isUnspecified())
00209         {
00210             EV << "        (replaced because of better proximity: "
00211                 << prox << " < " << position->rtt << ")" << endl;
00212         }
00213         position->node = node;
00214         position->rtt = prox;
00215         return true;
00216     }
00217     return false;
00218 }

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 }

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.

00313 {
00314     std::vector<PRTTrackRepair>::iterator it;
00315     simtime_t now = simTime();
00316 
00317     // first eliminate outdated entries in awaitingRepair:
00318     for (it = awaitingRepair.begin(); it != awaitingRepair.end();)
00319     {
00320         if (it->timestamp < (now - repairTimeout))
00321             it = awaitingRepair.erase(it);
00322         else it++;
00323     }
00324 
00325     // don't expect any more repair messages:
00326     if (awaitingRepair.empty()) return TransportAddress::UNSPECIFIED_NODE;
00327 
00328     // look for source node in our list:
00329     for (it = awaitingRepair.begin(); it != awaitingRepair.end(); it++)
00330         if (it->node == msg->getSender()) break;
00331 
00332     // if not found, return from function:
00333     if (it == awaitingRepair.end()) return TransportAddress::UNSPECIFIED_NODE;
00334 
00335     // merge state:
00336     mergeState(msg, prox);
00337 
00338     // repair not yet done?
00339     if (nodeAt(it->failedRow, it->failedCol).node.isUnspecified())
00340     {
00341         // ask next node
00342         findNextNodeToAsk(*it);
00343         if (it->node.isUnspecified())
00344         {
00345             // no more nodes to ask, give up:
00346             EV << "Pastry: RoutingTable giving up repair attempt." << endl;
00347             awaitingRepair.erase(it);
00348             return TransportAddress::UNSPECIFIED_NODE;
00349         }
00350         else return it->node;
00351     }
00352     
00353     // repair done: clean up
00354     EV << "Pastry: RoutingTable repair was successful." << endl;
00355     awaitingRepair.erase(it);
00356     return TransportAddress::UNSPECIFIED_NODE;
00357 }


Member Data Documentation

std::vector<PRTTrackRepair> PastryRoutingTable::awaitingRepair [private]

uint PastryRoutingTable::bitsPerDigit [private]

uint PastryRoutingTable::nodesPerRow [private]

double PastryRoutingTable::repairTimeout [private]

std::vector<PRTRow> PastryRoutingTable::rows [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