00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00025 #include <cassert>
00026
00027 #include <TransportAddress.h>
00028 #include <NodeHandle.h>
00029 #include <PeerInfo.h>
00030 #include <GlobalStatisticsAccess.h>
00031 #include <CoordMessages_m.h>
00032 #include <GlobalNodeListAccess.h>
00033 #include <hashWatch.h>
00034
00035 #include "NeighborCache.h"
00036
00037
00038 const std::vector<double> NeighborCache::coordsDummy;
00039
00040 std::ostream& operator<<(std::ostream& os,
00041 const NeighborCache::NeighborCacheEntry& entry)
00042 {
00043 if (entry.rttState == NeighborCache::RTTSTATE_VALID) {
00044 os << entry.rtt;
00045 } else {
00046 if (entry.rttState == NeighborCache::RTTSTATE_TIMEOUT) os << "TIMEOUT";
00047 else if (entry.rttState == NeighborCache::RTTSTATE_UNKNOWN) os << "UNKNOWN";
00048 else if (entry.rttState == NeighborCache::RTTSTATE_WAITING) os << "WAITING";
00049 }
00050 os << " (inserted: " << entry.insertTime;
00051
00052 os << ", #contexts: "
00053 << entry.waitingContexts.size();
00054
00055 if (!entry.nodeRef.isUnspecified()) os << ", <KEY>";
00056
00057
00058
00059 os << ")";
00060
00061 return os;
00062 }
00063
00064
00065 Define_Module(NeighborCache);
00066
00067 void NeighborCache::initializeApp(int stage)
00068 {
00069 if (stage == MAX_STAGE_COMPONENTS) {
00070 neighborCache.clear();
00071 WATCH_UNORDERED_MAP(neighborCache);
00072
00073 enableNeighborCache = par("enableNeighborCache");
00074 rttExpirationTime = par("rttExpirationTime");
00075 maxSize = par("maxSize");
00076 doDiscovery = par("doDiscovery");
00077 ncsSendBackOwnCoords = par("ncsSendBackOwnCoords");
00078
00079
00080 std::string temp = par("defaultQueryType").stdstringValue();
00081 if (temp == "exact")
00082 defaultQueryType = NEIGHBORCACHE_EXACT;
00083 else if (temp == "exact_timeout")
00084 defaultQueryType = NEIGHBORCACHE_EXACT_TIMEOUT;
00085 else if (temp == "available")
00086 defaultQueryType = NEIGHBORCACHE_AVAILABLE;
00087 else if (temp == "estimated")
00088 defaultQueryType = NEIGHBORCACHE_ESTIMATED;
00089 else throw cRuntimeError((std::string("Wrong query type: ")
00090 + temp).c_str());
00091
00092 temp = par("defaultQueryTypeI").stdstringValue();
00093 if (temp == "available")
00094 defaultQueryTypeI = NEIGHBORCACHE_AVAILABLE;
00095 else if (temp == "estimated")
00096 defaultQueryTypeI = NEIGHBORCACHE_ESTIMATED;
00097 else throw cRuntimeError((std::string("Wrong query type (I): ")
00098 + temp).c_str());
00099
00100 temp = par("defaultQueryTypeQ").stdstringValue();
00101 if (temp == "exact")
00102 defaultQueryTypeQ = NEIGHBORCACHE_EXACT;
00103 else if (temp == "exact_timeout")
00104 defaultQueryTypeQ = NEIGHBORCACHE_EXACT_TIMEOUT;
00105 else if (temp == "query")
00106 defaultQueryTypeQ = NEIGHBORCACHE_QUERY;
00107 else throw cRuntimeError((std::string("Wrong query type (Q): ")
00108 + temp).c_str());
00109
00110 temp = par("ncsType").stdstringValue();
00111 if (temp == "none") ncs = NULL;
00112 else if (temp == "vivaldi") ncs = new Vivaldi();
00113 else if (temp == "svivaldi") ncs = new SVivaldi();
00114 else if (temp == "gnp") ncs = new Nps();
00115 else if (temp == "nps") ncs = new Nps();
00116 else if (temp == "simple") ncs = new SimpleNcs();
00117 else throw cRuntimeError((std::string("Wrong NCS type: ")
00118 + temp).c_str());
00119
00120 globalStatistics = GlobalStatisticsAccess().get();
00121
00122 misses = 0;
00123 hits = 0;
00124
00125 rttHistory = par("rttHistory");
00126 timeoutAccuracyLimit = par("timeoutAccuracyLimit");
00127
00128 numMsg = 0;
00129 absoluteError = 0.0;
00130 relativeError = 0.0;
00131 numRttErrorToHigh = 0;
00132 numRttErrorToLow = 0;
00133 lastAbsoluteErrorPerNode.clear();
00134 WATCH(absoluteError);
00135 WATCH(relativeError);
00136 WATCH(numMsg);
00137 } else if (stage == MIN_STAGE_TIER_1) {
00138 if (ncs) ncs->init(this);
00139 }
00140 }
00141
00142
00143 void NeighborCache::finishApp()
00144 {
00145 if ((misses + hits) != 0) {
00146 globalStatistics
00147 ->addStdDev("NeighborCache: Ping hit rate",
00148 ((double)hits / (double)(misses + hits)));
00149 }
00150
00151 if (ncs && numMsg > 0) {
00152 globalStatistics->addStdDev("NeighborCache: NCS absolute RTT error",
00153 absoluteError / (double)numMsg);
00154 globalStatistics->addStdDev("NeighborCache: NCS relative RTT error",
00155 relativeError / (double)numMsg);
00156 globalStatistics->addStdDev("NeighborCache: number of messages/s",
00157 numMsg / SIMTIME_DBL(simTime() - creationTime));
00158 globalStatistics->addStdDev("NeighborCache: NCS percentage of RTT errors to high",
00159 (double)numRttErrorToHigh / (double)numMsg);
00160 globalStatistics->addStdDev("NeighborCache: NCS percentage of RTT errors to low",
00161 (double)numRttErrorToLow / (double)numMsg);
00162 }
00163 }
00164
00165
00166 NeighborCache::~NeighborCache()
00167 {
00168 delete ncs;
00169 }
00170
00171 bool NeighborCache::insertNodeContext(const TransportAddress& handle,
00172 cPolymorphic* context,
00173 ProxListener* rpcListener,
00174 int rpcId)
00175 {
00176 if (!enableNeighborCache) return false;
00177 if (neighborCache.count(handle) == 0) {
00178 NeighborCacheEntry& entry = neighborCache[handle];
00179
00180 entry.insertTime = simTime();
00181 entry.rttState = RTTSTATE_WAITING;
00182
00183 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime,
00184 handle));
00185
00186 cleanupCache();
00187
00188 assert(neighborCache.size() == neighborCacheExpireMap.size());
00189 return false;
00190 } else {
00191 NeighborCacheEntry& entry = neighborCache[handle];
00192
00193
00194 if (entry.rttState == RTTSTATE_WAITING) {
00195 WaitingContext temp(rpcListener, context, rpcId);
00196 entry.waitingContexts.push_back(temp);
00197
00198 return true;
00199 } else {
00200 if (entry.waitingContexts.size() > 0) {
00201 throw cRuntimeError("not waiting for response,"
00202 " but additional contexts found!");
00203 }
00204
00205 updateEntry(handle, entry.insertTime);
00206
00207 entry.rttState = RTTSTATE_WAITING;
00208 entry.insertTime = simTime();
00209
00210 return false;
00211 }
00212 }
00213 }
00214
00215
00216 NeighborCache::WaitingContexts NeighborCache::getNodeContexts(const TransportAddress& handle)
00217 {
00218 if (neighborCache.count(handle) == 0)
00219 throw cRuntimeError("NeighborCache error!");
00220 WaitingContexts temp = neighborCache[handle].waitingContexts;
00221 neighborCache[handle].waitingContexts.clear();
00222
00223 return temp;
00224 }
00225
00226
00227 void NeighborCache::setNodeTimeout(const TransportAddress& handle)
00228 {
00229
00230
00231 if (neighborCache.count(handle) == 0) {
00232 NeighborCacheEntry& entry = neighborCache[handle];
00233
00234 entry.insertTime = simTime();
00235 entry.rttState = RTTSTATE_TIMEOUT;
00236
00237 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime,
00238 handle));
00239 cleanupCache();
00240 } else {
00241 NeighborCacheEntry& entry = neighborCache[handle];
00242
00243 updateEntry(handle, entry.insertTime);
00244
00245 entry.insertTime = simTime();
00246 entry.rttState = RTTSTATE_TIMEOUT;
00247
00248 WaitingContexts waitingContexts = getNodeContexts(handle);
00249
00250 for (uint32_t i = 0; i < waitingContexts.size(); ++i) {
00251 assert(waitingContexts[i].proxListener || !waitingContexts[i].proxContext);
00252 if (waitingContexts[i].proxListener) {
00253 waitingContexts[i].proxListener->proxCallback(handle,
00254 waitingContexts[i].id,
00255 waitingContexts[i].proxContext,
00256 Prox::PROX_TIMEOUT);
00257 }
00258 }
00259 }
00260 assert(neighborCache.size() == neighborCacheExpireMap.size());
00261 }
00262
00263
00264 void NeighborCache::updateNode(const NodeHandle& add, simtime_t rtt,
00265 const NodeHandle& srcRoute,
00266 AbstractNcsNodeInfo* ncsInfo)
00267 {
00268 Enter_Method_Silent();
00269
00270 EV << "[NeighborCache::updateNode() @ " << thisNode.getIp()
00271 << " (" << thisNode.getKey().toString(16) << ")]\n"
00272 << " inserting rtt(" << rtt << ") of node " << add.getIp()
00273 << endl;
00274
00275 if (rtt <= 0) {
00276 delete ncsInfo;
00277 return;
00278 }
00279
00280 bool deleteInfo = false;
00281
00282
00283 if (neighborCache.count(add) == 0) {
00284 NeighborCacheEntry& entry = neighborCache[add];
00285
00286 entry.insertTime = simTime();
00287 entry.rtt = rtt;
00288 entry.rttState = RTTSTATE_VALID;
00289 entry.nodeRef = add;
00290 entry.coordsInfo = ncsInfo;
00291 entry.lastRtts.push_back(rtt);
00292
00293 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime, add));
00294
00295 cleanupCache();
00296 } else {
00297 updateEntry(add, neighborCache[add].insertTime);
00298
00299 NeighborCacheEntry& entry = neighborCache[add];
00300
00301 entry.insertTime = simTime();
00302 if (entry.rttState != RTTSTATE_VALID || entry.rtt > rtt)
00303 entry.rtt = rtt;
00304 entry.rttState = RTTSTATE_VALID;
00305 entry.nodeRef = add;
00306
00307 entry.lastRtts.push_back(rtt);
00308 if (entry.lastRtts.size() > rttHistory) {
00309 entry.lastRtts.pop_front();
00310 }
00311
00312 if (ncsInfo) {
00313 if (entry.coordsInfo) {
00314 entry.coordsInfo->update(*ncsInfo);
00315 deleteInfo = true;
00316 } else {
00317 entry.coordsInfo = ncsInfo;
00318 }
00319 }
00320
00321 WaitingContexts waitingContexts = getNodeContexts(add);
00322
00323 for (uint32_t i = 0; i < waitingContexts.size(); ++i) {
00324 if (waitingContexts[i].proxListener) {
00325 waitingContexts[i].proxListener
00326 ->proxCallback(add,
00327 waitingContexts[i].id,
00328 waitingContexts[i].proxContext,
00329 Prox(rtt, 1));
00330 }
00331 }
00332 }
00333 assert(neighborCache.size() == neighborCacheExpireMap.size());
00334
00335 calcRttError(add, rtt);
00336
00337 if (ncs) ncs->processCoordinates(rtt, *ncsInfo);
00338
00339
00340 if (deleteInfo) delete ncsInfo;
00341 }
00342
00343
00344 void NeighborCache::updateNcsInfo(const TransportAddress& node,
00345 AbstractNcsNodeInfo* ncsInfo)
00346 {
00347 Enter_Method_Silent();
00348
00349 EV << "[NeighborCache::updateNcsInfo() @ " << thisNode.getIp()
00350 << " (" << thisNode.getKey().toString(16) << ")]\n"
00351 << " inserting new NcsInfo of node " << node.getIp()
00352 << endl;
00353
00354 if (neighborCache.count(node) == 0) {
00355 NeighborCacheEntry& entry = neighborCache[node];
00356
00357 entry.insertTime = simTime();
00358 entry.coordsInfo = ncsInfo;
00359
00360 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime, node));
00361
00362 cleanupCache();
00363 } else {
00364 updateEntry(node, neighborCache[node].insertTime);
00365
00366 NeighborCacheEntry& entry = neighborCache[node];
00367
00368 if (ncsInfo) {
00369 if (entry.coordsInfo) {
00370 entry.coordsInfo->update(*ncsInfo);
00371 delete ncsInfo;
00372 } else {
00373 entry.coordsInfo = ncsInfo;
00374 }
00375 }
00376 }
00377 }
00378
00379
00380 NeighborCache::Rtt NeighborCache::getNodeRtt(const TransportAddress &add)
00381 {
00382
00383 if (!enableNeighborCache ||
00384 add.isUnspecified() ||
00385 (neighborCache.count(add) == 0)) {
00386 misses++;
00387 return std::make_pair(0.0, RTTSTATE_UNKNOWN);
00388 }
00389
00390 NeighborCacheEntry &entry = neighborCache[add];
00391
00392 if (entry.rttState == RTTSTATE_WAITING ||
00393 entry.rttState == RTTSTATE_UNKNOWN)
00394 return std::make_pair(entry.rtt, entry.rttState);
00395
00396 if ((simTime() - entry.insertTime) >= rttExpirationTime) {
00397 entry.rttState = RTTSTATE_UNKNOWN;
00398 return std::make_pair(entry.rtt, RTTSTATE_UNKNOWN);
00399 }
00400 hits++;
00401 assert(!(entry.rtt == 0.0 && entry.rttState == RTTSTATE_VALID));
00402 return std::make_pair(entry.rtt, entry.rttState);
00403 }
00404
00405
00406 const NodeHandle& NeighborCache::getNodeHandle(const TransportAddress &add)
00407 {
00408 if (neighborCache.count(add) == 0) {
00409 throw cRuntimeError("NeighborCache.cc: getNodeHandle was asked for "
00410 "a non-existent node reference.");
00411 }
00412 return neighborCache[add].nodeRef;
00413 }
00414
00415
00416 bool NeighborCache::cleanupCache()
00417 {
00418 bool result = false;
00419 uint32_t size = neighborCache.size();
00420
00421 if (size > maxSize) {
00422 neighborCacheExpireMapIterator it;
00423 for (uint32_t i = 0; i < (size - (maxSize / 2)); ++i) {
00424 it = neighborCacheExpireMap.begin();
00425 if ((neighborCache[it->second].rttState == RTTSTATE_WAITING) ||
00426 (neighborCache[it->second].insertTime == simTime())) {
00427 break;
00428 }
00429 neighborCache.erase(it->second);
00430 neighborCacheExpireMap.erase(it);
00431 result = true;
00432 }
00433 }
00434 assert(neighborCache.size() == neighborCacheExpireMap.size());
00435 return result;
00436 }
00437
00438
00439 void NeighborCache::updateEntry(const TransportAddress& address,
00440 simtime_t insertTime)
00441 {
00442 neighborCacheExpireMapIterator it =
00443 neighborCacheExpireMap.lower_bound(insertTime);
00444 while (it->second != address) ++it;
00445 neighborCacheExpireMap.erase(it);
00446 neighborCacheExpireMap.insert(std::make_pair(simTime(),
00447 address));
00448 assert(neighborCache.size() == neighborCacheExpireMap.size());
00449 }
00450
00451
00452 TransportAddress NeighborCache::getNearestNode(uint8_t maxLayer)
00453 {
00454 TransportAddress nearestNode = TransportAddress::UNSPECIFIED_NODE;
00455 simtime_t nearestNodeRtt = MAXTIME;
00456 NeighborCacheIterator it;
00457
00458 for(it = neighborCache.begin(); it != neighborCache.end(); it++ ) {
00459 if (it->second.rtt < nearestNodeRtt &&
00460 it->second.rtt > 0
00461
00462 ) {
00463 nearestNode.setIp(it->first.getIp());
00464 nearestNodeRtt = it->second.rtt;
00465 nearestNode.setPort(it->second.nodeRef.getPort());
00466 }
00467 }
00468
00469 return nearestNode;
00470 }
00471
00472
00473 bool NeighborCache::isEntry(const TransportAddress &node)
00474 {
00475 if (neighborCache.count(node) > 0) return true;
00476 return false;
00477 }
00478
00479
00480
00481 double NeighborCache::getAvgAbsPredictionError()
00482 {
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 double absoluteDiff = 0;
00507 uint32_t numNeighbors = 0;
00508 uint32_t sampleSize = 32;
00509
00510 for (std::map<simtime_t, TransportAddress>::reverse_iterator it =
00511 neighborCacheExpireMap.rbegin();
00512 it != neighborCacheExpireMap.rend() &&
00513 numNeighbors < sampleSize; ++it) {
00514 NeighborCacheEntry& cacheEntry = neighborCache[it->second];
00515
00516 double dist = ncs->getOwnNcsInfo().getDistance(*cacheEntry.coordsInfo);
00517
00518 if (dist != 0 && cacheEntry.rttState == RTTSTATE_VALID) {
00519 double predictionError = fabs(dist - SIMTIME_DBL(cacheEntry.rtt));
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530 numNeighbors++;
00531 absoluteDiff += predictionError;
00532 }
00533 }
00534 assert(numNeighbors != 0);
00535 absoluteDiff /= numNeighbors;
00536
00537 return (absoluteDiff > 1.0) ? 1.0 : absoluteDiff;
00538 }
00539
00540
00541 void NeighborCache::handleReadyMessage(CompReadyMessage* readyMsg)
00542 {
00543 if (readyMsg->getReady() && readyMsg->getComp() == BOOTSTRAPLIST_COMP) {
00544 if (doDiscovery) {
00545
00546
00547
00548
00549
00550 } else {
00551 sendReadyMessage();
00552 }
00553 }
00554 delete readyMsg;
00555 }
00556
00557
00558 void NeighborCache::handleTimerEvent(cMessage* msg)
00559 {
00560 if (ncs) {
00561 ncs->handleTimerEvent(msg);
00562 }
00563 }
00564
00565
00566 bool NeighborCache::handleRpcCall(BaseCallMessage* msg)
00567 {
00568 if (ncs) {
00569 return ncs->handleRpcCall(msg);
00570 }
00571
00572 return false;
00573 }
00574
00575
00576
00577 Prox NeighborCache::getProx(const TransportAddress &node,
00578 NeighborCacheQueryType type,
00579 int rpcId,
00580 ProxListener *listener,
00581 cPolymorphic *contextPointer)
00582 {
00583 Enter_Method("getProx()");
00584
00585 if (!enableNeighborCache) {
00586 queryProx(node, rpcId, listener, contextPointer);
00587 return Prox::PROX_UNKNOWN;
00588 }
00589
00590 if (node == overlay->getThisNode()) {
00591 delete contextPointer;
00592 return Prox::PROX_SELF;
00593 }
00594
00595 bool sendQuery = false;
00596 Prox result = Prox::PROX_UNKNOWN;
00597 Rtt rtt = getNodeRtt(node);
00598
00599
00600 if (type == NEIGHBORCACHE_DEFAULT) type = defaultQueryType;
00601 else if (type == NEIGHBORCACHE_DEFAULT_IMMEDIATELY) type = defaultQueryTypeI;
00602 else if (type == NEIGHBORCACHE_DEFAULT_QUERY) type = defaultQueryTypeQ;
00603
00604 switch(type) {
00605 case NEIGHBORCACHE_EXACT:
00606 if (rtt.second == RTTSTATE_TIMEOUT) {
00607
00608 sendQuery = true;
00609 } else if (rtt.second == RTTSTATE_WAITING) {
00610
00611 sendQuery = true;
00612 } else if (rtt.second == RTTSTATE_UNKNOWN) {
00613
00614 sendQuery = true;
00615 } else {
00616
00617 result = rtt.first;
00618 }
00619 break;
00620 case NEIGHBORCACHE_EXACT_TIMEOUT:
00621 if (rtt.second == RTTSTATE_TIMEOUT) {
00622
00623 result = Prox::PROX_TIMEOUT;
00624 } else if (rtt.second == RTTSTATE_WAITING) {
00625
00626 sendQuery = true;
00627 } else if (rtt.second == RTTSTATE_UNKNOWN) {
00628
00629 sendQuery = true;
00630 } else {
00631
00632 result = rtt.first;
00633 }
00634 break;
00635 case NEIGHBORCACHE_ESTIMATED:
00636 if (rtt.second == RTTSTATE_TIMEOUT) {
00637
00638 result = Prox::PROX_TIMEOUT;
00639 } else if (rtt.second == RTTSTATE_WAITING) {
00640
00641 result = estimateProx(node);
00642 } else if (rtt.second == RTTSTATE_UNKNOWN) {
00643
00644 result = estimateProx(node);
00645 } else {
00646
00647 result = rtt.first;
00648 }
00649 break;
00650 case NEIGHBORCACHE_AVAILABLE:
00651 if (rtt.second == RTTSTATE_TIMEOUT) {
00652
00653 result = Prox::PROX_TIMEOUT;
00654 } else if ((rtt.second == RTTSTATE_WAITING) ||
00655 (rtt.second == RTTSTATE_UNKNOWN)) {
00656
00657 } else {
00658
00659 result = rtt.first;
00660 }
00661 break;
00662 case NEIGHBORCACHE_QUERY:
00663
00664 sendQuery = true;
00665 break;
00666 default:
00667 throw cRuntimeError("Unknown query type!");
00668 break;
00669
00670 }
00671 if (sendQuery) {
00672 if (!insertNodeContext(node, contextPointer, listener, rpcId)) {
00673 queryProx(node, rpcId, listener, contextPointer);
00674 }
00675 } else delete contextPointer;
00676
00677 return result;
00678 }
00679
00680 Prox NeighborCache::estimateProx(const TransportAddress &node)
00681 {
00682 Enter_Method("estimateProx()");
00683
00684 Rtt rtt = getNodeRtt(node);
00685
00686 if (rtt.second != RTTSTATE_UNKNOWN) return rtt.first;
00687
00688 if (ncs && neighborCache.count(node)) {
00689 return getCoordinateBasedProx(node);
00690 }
00691
00692 return Prox::PROX_UNKNOWN;
00693 }
00694
00695 void NeighborCache::queryProx(const TransportAddress &node,
00696 int rpcId,
00697 ProxListener *listener,
00698 cPolymorphic *contextPointer)
00699 {
00700 Enter_Method("queryProx()");
00701
00702 WaitingContext temp(listener, contextPointer, rpcId);
00703
00704 if (neighborCache.count(node) == 0) {
00705 NeighborCacheEntry& entry = neighborCache[node];
00706
00707 entry.waitingContexts.push_back(temp);
00708 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime, node));
00709 cleanupCache();
00710 } else {
00711 NeighborCacheEntry& entry = neighborCache[node];
00712 entry.waitingContexts.push_back(temp);
00713 }
00714 assert(neighborCache.size() == neighborCacheExpireMap.size());
00715
00716
00717 pingNode(node, -1, 0, NULL, "PING");
00718 }
00719
00720 Prox NeighborCache::getCoordinateBasedProx(const TransportAddress& node)
00721 {
00722 if (ncs && isEntry(node)) {
00723 const AbstractNcsNodeInfo* temp = getNodeCoordsInfo(node);
00724 if (temp) return ncs->getCoordinateBasedProx(*temp);
00725 }
00726 return Prox::PROX_UNKNOWN;
00727 }
00728
00729
00730 const AbstractNcsNodeInfo* NeighborCache::getNodeCoordsInfo(const TransportAddress &node)
00731 {
00732 if (neighborCache.count(node) == 0) {
00733 throw cRuntimeError("NeighborCache.cc: getNodeCoords was asked for "
00734 "a non-existent node reference.");
00735 }
00736 return neighborCache[node].coordsInfo;
00737 }
00738
00739
00740 void NeighborCache::calcRttError(const NodeHandle& handle, simtime_t rtt)
00741 {
00742 if (!ncs) return;
00743
00744
00745 if (!globalStatistics->isMeasuring()) return;
00746
00747 Prox prox = getCoordinateBasedProx(handle);
00748 if (prox == Prox::PROX_UNKNOWN) return;
00749
00750
00751 double tempRttError = prox.proximity - SIMTIME_DBL(rtt);
00752
00753 if (tempRttError < 0){
00754 tempRttError *= -1;
00755 ++numRttErrorToLow;
00756 } else ++numRttErrorToHigh;
00757
00758 numMsg++;
00759 absoluteError += tempRttError;
00760 relativeError += tempRttError / SIMTIME_DBL(rtt);
00761
00762 globalStatistics->recordOutVector("NCS: absolute Rtt Error",
00763 tempRttError);
00764 globalStatistics->recordOutVector("NCS: relative Rtt Error",
00765 (tempRttError / SIMTIME_DBL(rtt)));
00766 }
00767
00768
00769 std::pair<simtime_t, simtime_t> NeighborCache::getMeanVarRtt(const TransportAddress &node,
00770 bool returnVar)
00771 {
00772 if (neighborCache.count(node) == 0) {
00773 throw cRuntimeError("NeighborCache.cc: getMeanVarRtt was asked for"
00774 "a non-existent node reference.");
00775 }
00776
00777 uint16_t size = neighborCache[node].lastRtts.size();
00778 if (size == 0) return std::make_pair(-1.0,-1.0);
00779
00780 simtime_t rttSum = 0;
00781 for (int i = 0; i < size; i++){
00782 rttSum += neighborCache[node].lastRtts[i];
00783 }
00784 simtime_t meanRtt = rttSum / size;
00785 if (!returnVar) {
00786 return std::make_pair(meanRtt, -1.0);
00787 }
00788 if (size == 1) {
00789 return std::make_pair(meanRtt, 0.0);
00790 }
00791
00792 double sum = 0.0;
00793 for (int i = 0; i < size; i++){
00794 simtime_t tempRtt = neighborCache[node].lastRtts.at(i) - meanRtt;
00795 sum += (SIMTIME_DBL(tempRtt) * SIMTIME_DBL(tempRtt));
00796 }
00797
00798 return std::make_pair(meanRtt, (sum / size));
00799 }
00800
00801
00802 simtime_t NeighborCache::getNodeTimeout(const NodeHandle &node)
00803 {
00804 simtime_t timeout = getRttBasedTimeout(node);
00805 if (timeout == -1 && ncs) return getNcsBasedTimeout(node);
00806 return timeout;
00807 }
00808
00809
00810
00811 simtime_t NeighborCache::getRttBasedTimeout(const NodeHandle &node)
00812 {
00813 simtime_t timeout = -1;
00814
00815
00816 if (isEntry(node)) {
00817 std::pair<simtime_t, simtime_t> temp = getMeanVarRtt(node, true);
00818 simtime_t meanRtt = temp.first;
00819 simtime_t varRtt = temp.second;
00820
00821
00822 if (meanRtt == -1) return -1;
00823 if (varRtt > 0) {
00824
00825 timeout = meanRtt + 4 * varRtt;
00826 } else {
00827
00828 timeout = meanRtt * 1.2;
00829 }
00830
00831 timeout *= RTT_TIMEOUT_ADJUSTMENT;
00832
00833 }
00834 return timeout;
00835 }
00836
00837
00838 simtime_t NeighborCache::getNcsBasedTimeout(const NodeHandle &node)
00839 {
00840 double timeout = -1;
00841 Prox prox = Prox::PROX_UNKNOWN;
00842
00843
00844 if (isEntry(node)) {
00845 prox = getProx(node, NEIGHBORCACHE_ESTIMATED);
00846
00847 if (prox != Prox::PROX_UNKNOWN && prox != Prox::PROX_TIMEOUT &&
00848 prox.proximity > 0 && prox.accuracy > timeoutAccuracyLimit) {
00849 timeout = prox.proximity + (6 * (1 - prox.accuracy));
00850 timeout += NCS_TIMEOUT_CONSTANT;
00851 } else return -1;
00852
00853 if ( timeout < 0)
00854 return -1;
00855 }
00856 return timeout;
00857 }
00858