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
00221 msg->setRoutingTableArraySize(0);
00222 return;
00223 } else {
00224 itRows = rows.begin() + row - 1;
00225 }
00226 for (itCols = itRows->begin(); itCols != itRows->end(); itCols++) {
00227 if (!itCols->node.isUnspecified()) {
00228 ++size;
00229 msg->setRoutingTable(i++, itCols->node);
00230 }
00231 }
00232 msg->setRoutingTableArraySize(size);
00233 }
00234
00235
00236 void PastryRoutingTable::dumpRowToMessage(PastryStateMessage* msg,
00237 int row) const
00238 {
00239 uint32_t i = 0;
00240 uint32_t size = 0;
00241 std::vector<PRTRow>::const_iterator itRows;
00242 PRTRow::const_iterator itCols;
00243
00244 msg->setRoutingTableArraySize(nodesPerRow);
00245 if ((row == -1) || (row > (int)rows.size())) {
00246 itRows = rows.end() - 1;
00247 } else if (row > (int)rows.size()) {
00248 EV << "asked for nonexistent row";
00249
00250 msg->setRoutingTableArraySize(0);
00251 return;
00252 } else {
00253 itRows = rows.begin() + row - 1;
00254 }
00255 for (itCols = itRows->begin(); itCols != itRows->end(); itCols++) {
00256 if (!itCols->node.isUnspecified()) {
00257 ++size;
00258 msg->setRoutingTable(i++, itCols->node);
00259 }
00260 }
00261
00262 msg->setRoutingTableArraySize(size);
00263 }
00264
00265 int PastryRoutingTable::getLastRow()
00266 {
00267 return rows.size();
00268 }
00269
00270 const TransportAddress& PastryRoutingTable::getRandomNode(int row)
00271 {
00272 std::vector<PRTRow>::const_iterator itRows;
00273 PRTRow::const_iterator itCols;
00274 uint32_t rnd;
00275
00276 itRows = rows.begin() + row;
00277 if (itRows >= rows.end()) {
00278 EV << "[PastryRoutingTable::getRandomNode()]\n"
00279 << " tried to get random Node from nonexistent row"
00280 << endl;
00281 }
00282 rnd = intuniform(0, nodesPerRow - 1, 0);
00283 itCols = itRows->begin() + rnd;
00284 while (itCols != itRows->end()) {
00285 if (!itCols->node.isUnspecified()) return itCols->node;
00286 else itCols++;
00287 }
00288 itCols = itRows->begin() + rnd;
00289 while (itCols >= itRows->begin()) {
00290 if (!itCols->node.isUnspecified()) return itCols->node;
00291 else itCols--;
00292 }
00293 return TransportAddress::UNSPECIFIED_NODE;
00294 }
00295
00296 bool PastryRoutingTable::mergeNode(const NodeHandle& node, simtime_t prox)
00297 {
00298 if (node.getKey() == owner.getKey())
00299 opp_error("trying to merge node with same key!");
00300
00301 uint32_t shl;
00302 uint32_t digit;
00303 PRTRow::iterator position;
00304
00305 shl = owner.getKey().sharedPrefixLength(node.getKey()) / bitsPerDigit;
00306 digit = digitAt(shl, node.getKey());
00307
00308 while (rows.size() <= shl) addRow();
00309 position = (rows.begin() + shl)->begin() + digit;
00310 if (position->node.isUnspecified() || (prox < position->rtt)) {
00311 EV << "[PastryRoutingTable::mergeNode()]\n"
00312 << " Node " << owner.getKey()
00313 << endl;
00314 EV << " placing node " << node.getKey() << "in row "
00315 << shl << ", col" << digit << endl;
00316 if (! position->node.isUnspecified()) {
00317 EV << " (replaced because of better proximity: "
00318 << prox << " < " << position->rtt << ")" << endl;
00319 }
00320 position->node = node;
00321 position->rtt = prox;
00322 return true;
00323 }
00324 return false;
00325 }
00326
00327 bool PastryRoutingTable::initStateFromHandleVector(const std::vector<PastryStateMsgHandle>& handles)
00328 {
00329 std::vector<PastryStateMsgHandle>::const_iterator it;
00330 int hopCheck = 0;
00331
00332 for (it = handles.begin(); it != handles.end(); ++it) {
00333 if (it->msg->getJoinHopCount() != ++hopCheck) return false;
00334 mergeState(it->msg, it->prox);
00335 }
00336 return true;
00337 }
00338
00339 void PastryRoutingTable::dumpToVector(std::vector<TransportAddress>& affected)
00340 const
00341 {
00342 std::vector<PRTRow>::const_iterator itRows;
00343 PRTRow::const_iterator itCols;
00344
00345 for (itRows = rows.begin(); itRows != rows.end(); itRows++)
00346 for (itCols = itRows->begin(); itCols != itRows->end(); itCols++)
00347 if (!itCols->node.isUnspecified())
00348 affected.push_back(itCols->node);
00349 }
00350
00351 void PastryRoutingTable::addRow(void)
00352 {
00353 PRTRow row(nodesPerRow, unspecNode());
00354
00355
00356 (row.begin() + digitAt(rows.size(), owner.getKey()))->node = owner;
00357 rows.push_back(row);
00358 }
00359
00360 std::ostream& operator<<(std::ostream& os, const PRTRow& row)
00361 {
00362 os << "Pastry IRoutingTable row {" << endl;
00363 for (PRTRow::const_iterator i = row.begin(); i != row.end(); i++) {
00364 os << " " << i->node << " ; Ping: ";
00365 if (i->rtt != SimTime::getMaxTime())
00366 os << i->rtt << endl;
00367 else os << "<unknown>" << endl;
00368 }
00369 os << " }";
00370 return os;
00371 }
00372
00373 const TransportAddress& PastryRoutingTable::failedNode(const TransportAddress& failed)
00374 {
00375 std::vector<PRTRow>::iterator itRows;
00376 PRTRow::iterator itCols;
00377 PRTTrackRepair tmpTrack;
00378
00379 bool found = false;
00380
00381
00382 for (itRows = rows.begin(); itRows != rows.end(); itRows++) {
00383 for (itCols = itRows->begin(); itCols != itRows->end(); itCols++) {
00384 if ((! itCols->node.isUnspecified()) &&
00385 (itCols->node.getAddress() == failed.getAddress())) {
00386 itCols->node = NodeHandle::UNSPECIFIED_NODE;
00387 itCols->rtt = PASTRY_PROX_UNDEF;
00388 found = true;
00389 break;
00390 }
00391 }
00392 if (found) break;
00393 }
00394
00395
00396 if (!found) return TransportAddress::UNSPECIFIED_NODE;
00397
00398
00399 tmpTrack.failedRow = itRows - rows.begin();
00400 tmpTrack.failedCol = itCols - itRows->begin();
00401 tmpTrack.node = TransportAddress::UNSPECIFIED_NODE;
00402 findNextNodeToAsk(tmpTrack);
00403 tmpTrack.timestamp = simTime();
00404
00405 if (tmpTrack.node.isUnspecified())
00406 return TransportAddress::UNSPECIFIED_NODE;
00407 awaitingRepair.push_back(tmpTrack);
00408 return awaitingRepair.back().node;
00409 }
00410
00411 const TransportAddress& PastryRoutingTable::repair(const PastryStateMessage* msg,
00412 const PastryStateMsgProximity* prox)
00413 {
00414 std::vector<PRTTrackRepair>::iterator it;
00415 simtime_t now = simTime();
00416
00417
00418 for (it = awaitingRepair.begin(); it != awaitingRepair.end();) {
00419 if (it->timestamp < (now - repairTimeout))
00420 it = awaitingRepair.erase(it);
00421 else it++;
00422 }
00423
00424
00425 if (awaitingRepair.empty()) return TransportAddress::UNSPECIFIED_NODE;
00426
00427
00428 for (it = awaitingRepair.begin(); it != awaitingRepair.end(); it++)
00429 if (it->node == msg->getSender()) break;
00430
00431
00432 if (it == awaitingRepair.end()) return TransportAddress::UNSPECIFIED_NODE;
00433
00434
00435 mergeState(msg, prox);
00436
00437
00438 if (nodeAt(it->failedRow, it->failedCol).node.isUnspecified()) {
00439
00440 findNextNodeToAsk(*it);
00441 if (it->node.isUnspecified()) {
00442
00443 EV << "[PastryRoutingTable::repair()]\n"
00444 << " RoutingTable giving up repair attempt."
00445 << endl;
00446 awaitingRepair.erase(it);
00447 return TransportAddress::UNSPECIFIED_NODE;
00448 }
00449 else return it->node;
00450 }
00451
00452
00453 EV << "[PastryRoutingTable::repair()]\n"
00454 << " RoutingTable repair was successful."
00455 << endl;
00456 return TransportAddress::UNSPECIFIED_NODE;
00457 }
00458
00459 void PastryRoutingTable::findNextNodeToAsk(PRTTrackRepair& track) const
00460 {
00461 const TransportAddress* ask;
00462
00463 if (track.node.isUnspecified()) {
00464 track.askedRow = track.failedRow;
00465 if (track.failedCol == 0)
00466 track.askedCol = 1;
00467 else
00468 track.askedCol = 0;
00469 ask = static_cast<const TransportAddress*>(
00470 &(nodeAt(track.askedRow, track.askedCol).node));
00471 track.node = *ask;
00472 if ( (! track.node.isUnspecified()) &&
00473 (track.node != owner) )
00474 return;
00475 }
00476
00477 do {
00478
00479 track.askedCol++;
00480 if ((track.askedRow == track.failedRow) &&
00481 (track.askedCol == track.failedCol)) track.askedCol++;
00482 if (track.askedCol == nodesPerRow) {
00483 if ((track.askedRow > track.askedCol) ||
00484 (track.askedRow == (rows.size() - 1))) {
00485
00486 track.node = TransportAddress::UNSPECIFIED_NODE;
00487 return;
00488 }
00489 track.askedRow++;
00490 track.askedCol = 0;
00491 }
00492
00493 ask = static_cast<const TransportAddress*>(
00494 &(nodeAt(track.askedRow, track.askedCol).node));
00495
00496
00497
00498
00499
00500
00501
00502 if (track.node.isUnspecified() ||
00503 (!ask->isUnspecified() && track.node != *ask))
00504 track.node = *ask;
00505 else track.node = TransportAddress::UNSPECIFIED_NODE;
00506 }
00507 while (track.node.isUnspecified() || (track.node == owner) );
00508 }
00509