00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include "PastryRoutingTable.h"
00025
00026 Define_Module(PastryRoutingTable);
00027
00028 uint32_t PastryRoutingTable::digitAt(uint32_t n,
00029 const OverlayKey& key) const
00030 {
00031 return key.getBitRange(OverlayKey::getLength() - ++n * bitsPerDigit, bitsPerDigit);
00032 }
00033
00034 void PastryRoutingTable::earlyInit(void)
00035 {
00036 WATCH_VECTOR(rows);
00037 }
00038
00039 void PastryRoutingTable::initializeTable(uint32_t bitsPerDigit,
00040 double repairTimeout,
00041 const NodeHandle& owner)
00042 {
00043 this->owner = owner;
00044 this->repairTimeout = repairTimeout;
00045 this->bitsPerDigit = bitsPerDigit;
00046 nodesPerRow = 1 << bitsPerDigit;
00047
00048
00049 if (!rows.empty()) rows.clear();
00050
00051
00052 if (!awaitingRepair.empty()) awaitingRepair.clear();
00053
00054
00055 addRow();
00056 }
00057
00058 const PastryExtendedNode& PastryRoutingTable::nodeAt(uint32_t row, uint32_t col) const
00059 {
00060 if (rows.size() <= row) return unspecNode();
00061 if (col >= nodesPerRow) return unspecNode();
00062
00063 return *((rows.begin()+row)->begin()+col);
00064 }
00065
00066 const NodeHandle& PastryRoutingTable::lookupNextHop(const OverlayKey& destination)
00067 {
00068 if (destination == owner.getKey()) opp_error("trying to lookup own key!");
00069
00070 uint32_t shl = owner.getKey().sharedPrefixLength(destination) / bitsPerDigit;
00071 uint32_t digit = digitAt(shl, destination);
00072
00073 if (shl >= rows.size()) {
00074 EV << "Pastry: Unable to find next hop for " << destination
00075 << ", row is empty." << endl;
00076 return NodeHandle::UNSPECIFIED_NODE;
00077 }
00078
00079 const PastryExtendedNode& next = nodeAt(shl, digit);
00080
00081 if (next.node.isUnspecified()) {
00082 EV << "Pastry: Unable to find next hop for " << destination <<
00083 ", routing table entry is empty." << endl;
00084 }
00085 return next.node;
00086 }
00087
00088 const NodeHandle& PastryRoutingTable::findCloserNode(const OverlayKey& destination,
00089 bool optimize)
00090 {
00091 if (destination == owner.getKey())
00092 opp_error("trying to find closer node to own key!");
00093
00094 const PastryExtendedNode* entry;
00095
00096 if (optimize) {
00097
00098
00099
00100
00101 const NodeHandle* ret = &NodeHandle::UNSPECIFIED_NODE;
00102
00103
00104
00105 int shl = owner.getKey().sharedPrefixLength(destination) / bitsPerDigit;
00106 int digit = digitAt(shl, destination);
00107 int x = digitAt(shl, owner.getKey());
00108
00109
00110 int n = nodesPerRow;
00111 int a = digit - 1;
00112 int b = digit + 1;
00113
00114 while ((a >= 0) || (b < n)) {
00115
00116
00117 if (a == x) a = -1;
00118 if (b == x) b = n;
00119
00120 if (a >= 0) {
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 entry = &(nodeAt(shl, b));
00129 if ((!entry->node.isUnspecified()) &&
00130 specialCloserCondition(entry->node, destination, *ret))
00131 ret = &(entry->node);
00132 b++;
00133 }
00134 }
00135
00136
00137 if (shl != 0) {
00138
00139 x = digitAt(--shl, owner.getKey());
00140
00141 if (destination < owner.getKey()) {
00142 entry = &(nodeAt(shl, digit - 1));
00143 if ((!entry->node.isUnspecified()) &&
00144 specialCloserCondition(entry->node, destination, *ret))
00145 ret = &(entry->node);
00146 } else {
00147 entry = &(nodeAt(shl, digit + 1));
00148 if ((!entry->node.isUnspecified()) &&
00149 specialCloserCondition(entry->node, destination, *ret))
00150 ret = &(entry->node);
00151 }
00152 }
00153
00154 return *ret;
00155 } else {
00156
00157 for (uint32_t y = 0; y < rows.size(); ++y) {
00158 for (uint32_t x = 0; x < nodesPerRow; ++x) {
00159 entry = &(nodeAt(y, x));
00160 if ((!entry->node.isUnspecified()) &&
00161 specialCloserCondition(entry->node, destination))
00162 return entry->node;
00163 }
00164 }
00165
00166 return NodeHandle::UNSPECIFIED_NODE;
00167 }
00168 }
00169
00170 void PastryRoutingTable::findCloserNodes(const OverlayKey& destination,
00171 NodeVector* nodes)
00172 {
00173
00174 const PastryExtendedNode* entry;
00175
00176 for (uint32_t y = 0; y < rows.size(); ++y) {
00177 for (uint32_t x = 0; x < nodesPerRow; ++x) {
00178 entry = &(nodeAt(y, x));
00179 if (!entry->node.isUnspecified()
00180 )
00181 nodes->add(entry->node);
00182 }
00183 }
00184 }
00185
00186 void PastryRoutingTable::dumpToStateMessage(PastryStateMessage* msg) const
00187 {
00188 uint32_t i = 0;
00189 uint32_t size = 0;
00190 std::vector<PRTRow>::const_iterator itRows;
00191 PRTRow::const_iterator itCols;
00192
00193 msg->setRoutingTableArraySize(rows.size() * nodesPerRow);
00194
00195 for (itRows = rows.begin(); itRows != rows.end(); itRows++) {
00196 for (itCols = itRows->begin(); itCols != itRows->end(); itCols++) {
00197 if (!itCols->node.isUnspecified()) {
00198 ++size;
00199 msg->setRoutingTable(i++, itCols->node);
00200 }
00201 }
00202 }
00203 msg->setRoutingTableArraySize(size);
00204
00205 }
00206
00207 void PastryRoutingTable::dumpRowToMessage(PastryRoutingRowMessage* msg,
00208 int row) const
00209 {
00210 uint32_t i = 0;
00211 uint32_t size = 0;
00212 std::vector<PRTRow>::const_iterator itRows;
00213 PRTRow::const_iterator itCols;
00214
00215 msg->setRoutingTableArraySize(nodesPerRow);
00216 if (row == -1) {
00217 itRows = rows.end() - 1;
00218 } else if (row > (int)rows.size()) {
00219 EV << "asked for nonexistent row";
00220 return;
00221 } else {
00222 itRows = rows.begin() + row - 1;
00223 }
00224 for (itCols = itRows->begin(); itCols != itRows->end(); itCols++) {
00225 if (!itCols->node.isUnspecified()) {
00226 ++size;
00227 msg->setRoutingTable(i++, itCols->node);
00228 }
00229 }
00230 msg->setRoutingTableArraySize(size);
00231 }
00232
00233
00234 void PastryRoutingTable::dumpRowToMessage(PastryStateMessage* msg,
00235 int row) const
00236 {
00237 uint32_t i = 0;
00238 uint32_t size = 0;
00239 std::vector<PRTRow>::const_iterator itRows;
00240 PRTRow::const_iterator itCols;
00241
00242 msg->setRoutingTableArraySize(nodesPerRow);
00243 if ((row == -1) || (row > (int)rows.size())) {
00244 itRows = rows.end() - 1;
00245 } else if (row > (int)rows.size()) {
00246 EV << "asked for nonexistent row";
00247 return;
00248 } else {
00249 itRows = rows.begin() + row - 1;
00250 }
00251 for (itCols = itRows->begin(); itCols != itRows->end(); itCols++) {
00252 if (!itCols->node.isUnspecified()) {
00253 ++size;
00254 msg->setRoutingTable(i++, itCols->node);
00255 }
00256 }
00257 }
00258
00259 int PastryRoutingTable::getLastRow()
00260 {
00261 return rows.size();
00262 }
00263
00264 const TransportAddress& PastryRoutingTable::getRandomNode(int row)
00265 {
00266 std::vector<PRTRow>::const_iterator itRows;
00267 PRTRow::const_iterator itCols;
00268 uint32_t rnd;
00269
00270 itRows = rows.begin() + row;
00271 if (itRows >= rows.end()) {
00272 EV << "[PastryRoutingTable::getRandomNode()]\n"
00273 << " tried to get random Node from nonexistent row"
00274 << endl;
00275 }
00276 rnd = intuniform(0, nodesPerRow - 1, 0);
00277 itCols = itRows->begin() + rnd;
00278 while (itCols != itRows->end()) {
00279 if (!itCols->node.isUnspecified()) return itCols->node;
00280 else itCols++;
00281 }
00282 itCols = itRows->begin() + rnd;
00283 while (itCols >= itRows->begin()) {
00284 if (!itCols->node.isUnspecified()) return itCols->node;
00285 else itCols--;
00286 }
00287 return TransportAddress::UNSPECIFIED_NODE;
00288 }
00289
00290 bool PastryRoutingTable::mergeNode(const NodeHandle& node, simtime_t prox)
00291 {
00292 if (node.getKey() == owner.getKey())
00293 opp_error("trying to merge node with same key!");
00294
00295 uint32_t shl;
00296 uint32_t digit;
00297 PRTRow::iterator position;
00298
00299 shl = owner.getKey().sharedPrefixLength(node.getKey()) / bitsPerDigit;
00300 digit = digitAt(shl, node.getKey());
00301
00302 while (rows.size() <= shl) addRow();
00303 position = (rows.begin() + shl)->begin() + digit;
00304 if (position->node.isUnspecified() || (prox < position->rtt)) {
00305 EV << "[PastryRoutingTable::mergeNode()]\n"
00306 << " Node " << owner.getKey()
00307 << endl;
00308 EV << " placing node " << node.getKey() << "in row "
00309 << shl << ", col" << digit << endl;
00310 if (! position->node.isUnspecified()) {
00311 EV << " (replaced because of better proximity: "
00312 << prox << " < " << position->rtt << ")" << endl;
00313 }
00314 position->node = node;
00315 position->rtt = prox;
00316 return true;
00317 }
00318 return false;
00319 }
00320
00321 bool PastryRoutingTable::initStateFromHandleVector(const std::vector<PastryStateMsgHandle>& handles)
00322 {
00323 std::vector<PastryStateMsgHandle>::const_iterator it;
00324 int hopCheck = 0;
00325
00326 for (it = handles.begin(); it != handles.end(); ++it) {
00327 if (it->msg->getJoinHopCount() != ++hopCheck) return false;
00328 mergeState(it->msg, it->prox);
00329 }
00330 return true;
00331 }
00332
00333 void PastryRoutingTable::dumpToVector(std::vector<TransportAddress>& affected)
00334 const
00335 {
00336 std::vector<PRTRow>::const_iterator itRows;
00337 PRTRow::const_iterator itCols;
00338
00339 for (itRows = rows.begin(); itRows != rows.end(); itRows++)
00340 for (itCols = itRows->begin(); itCols != itRows->end(); itCols++)
00341 if (!itCols->node.isUnspecified())
00342 affected.push_back(itCols->node);
00343 }
00344
00345 void PastryRoutingTable::addRow(void)
00346 {
00347 PRTRow row(nodesPerRow, unspecNode());
00348
00349
00350 (row.begin() + digitAt(rows.size(), owner.getKey()))->node = owner;
00351 rows.push_back(row);
00352 }
00353
00354 std::ostream& operator<<(std::ostream& os, const PRTRow& row)
00355 {
00356 os << "Pastry IRoutingTable row {" << endl;
00357 for (PRTRow::const_iterator i = row.begin(); i != row.end(); i++) {
00358 os << " " << i->node << " ; Ping: ";
00359 if (i->rtt != SimTime::getMaxTime())
00360 os << i->rtt << endl;
00361 else os << "<unknown>" << endl;
00362 }
00363 os << " }";
00364 return os;
00365 }
00366
00367 const TransportAddress& PastryRoutingTable::failedNode(const TransportAddress& failed)
00368 {
00369 std::vector<PRTRow>::iterator itRows;
00370 PRTRow::iterator itCols;
00371 PRTTrackRepair tmpTrack;
00372
00373 bool found = false;
00374
00375
00376 for (itRows = rows.begin(); itRows != rows.end(); itRows++) {
00377 for (itCols = itRows->begin(); itCols != itRows->end(); itCols++) {
00378 if ((! itCols->node.isUnspecified()) &&
00379 (itCols->node.getAddress() == failed.getAddress())) {
00380 itCols->node = NodeHandle::UNSPECIFIED_NODE;
00381 itCols->rtt = PASTRY_PROX_UNDEF;
00382 found = true;
00383 break;
00384 }
00385 }
00386 if (found) break;
00387 }
00388
00389
00390 if (!found) return TransportAddress::UNSPECIFIED_NODE;
00391
00392
00393 tmpTrack.failedRow = itRows - rows.begin();
00394 tmpTrack.failedCol = itCols - itRows->begin();
00395 tmpTrack.node = TransportAddress::UNSPECIFIED_NODE;
00396 findNextNodeToAsk(tmpTrack);
00397 tmpTrack.timestamp = simTime();
00398
00399 if (tmpTrack.node.isUnspecified())
00400 return TransportAddress::UNSPECIFIED_NODE;
00401 awaitingRepair.push_back(tmpTrack);
00402 return awaitingRepair.back().node;
00403 }
00404
00405 const TransportAddress& PastryRoutingTable::repair(const PastryStateMessage* msg,
00406 const PastryStateMsgProximity* prox)
00407 {
00408 std::vector<PRTTrackRepair>::iterator it;
00409 simtime_t now = simTime();
00410
00411
00412 for (it = awaitingRepair.begin(); it != awaitingRepair.end();) {
00413 if (it->timestamp < (now - repairTimeout))
00414 it = awaitingRepair.erase(it);
00415 else it++;
00416 }
00417
00418
00419 if (awaitingRepair.empty()) return TransportAddress::UNSPECIFIED_NODE;
00420
00421
00422 for (it = awaitingRepair.begin(); it != awaitingRepair.end(); it++)
00423 if (it->node == msg->getSender()) break;
00424
00425
00426 if (it == awaitingRepair.end()) return TransportAddress::UNSPECIFIED_NODE;
00427
00428
00429 mergeState(msg, prox);
00430
00431
00432 if (nodeAt(it->failedRow, it->failedCol).node.isUnspecified()) {
00433
00434 findNextNodeToAsk(*it);
00435 if (it->node.isUnspecified()) {
00436
00437 EV << "[PastryRoutingTable::repair()]\n"
00438 << " RoutingTable giving up repair attempt."
00439 << endl;
00440 awaitingRepair.erase(it);
00441 return TransportAddress::UNSPECIFIED_NODE;
00442 }
00443 else return it->node;
00444 }
00445
00446
00447 EV << "[PastryRoutingTable::repair()]\n"
00448 << " RoutingTable repair was successful."
00449 << endl;
00450 return TransportAddress::UNSPECIFIED_NODE;
00451 }
00452
00453 void PastryRoutingTable::findNextNodeToAsk(PRTTrackRepair& track) const
00454 {
00455 const TransportAddress* ask;
00456
00457 if (track.node.isUnspecified()) {
00458 track.askedRow = track.failedRow;
00459 if (track.failedCol == 0)
00460 track.askedCol = 1;
00461 else
00462 track.askedCol = 0;
00463 ask = static_cast<const TransportAddress*>(
00464 &(nodeAt(track.askedRow, track.askedCol).node));
00465 track.node = *ask;
00466 if ( (! track.node.isUnspecified()) &&
00467 (track.node != owner) )
00468 return;
00469 }
00470
00471 do {
00472
00473 track.askedCol++;
00474 if ((track.askedRow == track.failedRow) &&
00475 (track.askedCol == track.failedCol)) track.askedCol++;
00476 if (track.askedCol == nodesPerRow) {
00477 if ((track.askedRow > track.askedCol) ||
00478 (track.askedRow == (rows.size() - 1))) {
00479
00480 track.node = TransportAddress::UNSPECIFIED_NODE;
00481 return;
00482 }
00483 track.askedRow++;
00484 track.askedCol = 0;
00485 }
00486
00487 ask = static_cast<const TransportAddress*>(
00488 &(nodeAt(track.askedRow, track.askedCol).node));
00489
00490
00491
00492
00493
00494
00495
00496 if (track.node.isUnspecified() ||
00497 (!ask->isUnspecified() && track.node != *ask))
00498 track.node = *ask;
00499 else track.node = TransportAddress::UNSPECIFIED_NODE;
00500 }
00501 while (track.node.isUnspecified() || (track.node == owner) );
00502 }
00503