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

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.

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

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.

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

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.

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

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.

00198 {
00199     if (node.key == owner.key)
00200         opp_error("trying to merge node with same key!");
00201 
00202     uint shl;
00203     uint digit;
00204     PRTRow::iterator position;
00205 
00206     shl = owner.key.sharedPrefixLength(node.key) / bitsPerDigit;
00207     digit = digitAt(shl, node.key);
00208 
00209     while (rows.size() <= shl) addRow();
00210     position = (rows.begin() + shl)->begin() + digit;
00211     if (position->node.isUnspecified() || (prox < position->rtt))
00212     {
00213         EV << "Pastry: Node " << owner.key << endl;
00214         EV << "        placing node " << node.key << "in row "
00215             << shl << ", col" << digit << endl;
00216         if (! position->node.isUnspecified())
00217         {
00218             EV << "        (replaced because of better proximity: "
00219                 << prox << " < " << position->rtt << ")" << endl;
00220         }
00221         position->node = node;
00222         position->rtt = prox;
00223         return true;
00224     }
00225     return false;
00226 }

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
00231 {
00232     std::vector<PastryStateMessage*>::const_iterator itMsg;
00233     std::vector<PastryStateMsgProximity>::const_iterator itProx;
00234     PastryStateMessage* msg;
00235     int hopCheck = 0;
00236 
00237     itProx = proximities.begin();
00238     for (itMsg = messages.begin(); itMsg != messages.end(); itMsg++)
00239     {
00240         msg = *itMsg;
00241         if (msg->getJoinHopCount() != ++hopCheck) return false;
00242         mergeState(msg, *(itProx++));
00243     }
00244     return true;
00245 }

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.

00249 {
00250     std::vector<PRTRow>::const_iterator itRows;
00251     PRTRow::const_iterator itCols;
00252 
00253     for (itRows = rows.begin(); itRows != rows.end(); itRows++)
00254         for (itCols = itRows->begin(); itCols != itRows->end(); itCols++)
00255             if (!itCols->node.isUnspecified())
00256                 affected.push_back(itCols->node);
00257 }

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

00260 {
00261     PRTRow row(nodesPerRow, unspecNode);
00262 
00263     // place own node at correct position:
00264     (row.begin() + digitAt(rows.size(), owner.key))->node = owner;
00265     rows.push_back(row);
00266 }

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


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 Tue Jul 24 16:51:19 2007 for ITM OverSim by  doxygen 1.5.1