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 <Vivaldi.h>
00032 #include <CoordMessages_m.h>
00033 #include <GlobalNodeListAccess.h>
00034 #include <hashWatch.h>
00035
00036 #include "NeighborCache.h"
00037
00038
00039 const std::vector<double> NeighborCache::coordsDummy;
00040
00041 std::ostream& operator<<(std::ostream& os,
00042 const NeighborCache::NeighborCacheEntry& entry)
00043 {
00044 if (entry.rttState == NeighborCache::RTTSTATE_VALID) {
00045 os << entry.rtt;
00046 } else {
00047 if (entry.rttState == NeighborCache::RTTSTATE_TIMEOUT) os << "TIMEOUT";
00048 else if (entry.rttState == NeighborCache::RTTSTATE_UNKNOWN) os << "UNKNOWN";
00049 else if (entry.rttState == NeighborCache::RTTSTATE_WAITING) os << "WAITING";
00050 }
00051 os << " (inserted: " << entry.insertTime;
00052
00053 if (entry.waitingContexts != NULL) {
00054 os << ", #contexts: "
00055 << entry.waitingContexts->pingContexts.size();
00056 }
00057 if (!entry.nodeRef.isUnspecified()) os << ", <KEY>";
00058
00059 if (entry.coordsInfo.coordinates.size() > 0) {
00060 if (entry.coordsInfo.npsLayer >= 0) {
00061 os << ", NPS layer: "
00062 << (int)entry.coordsInfo.npsLayer;
00063 }
00064 os << ", coords: <";
00065 for (uint32_t i = 0; i < entry.coordsInfo.coordinates.size(); ++i) {
00066 if (i != 0) os << ", ";
00067 os << entry.coordsInfo.coordinates[i];
00068 }
00069 if (entry.coordsInfo.coordErr >= 0) {
00070 os << ", E: "
00071 << entry.coordsInfo.coordErr;
00072 }
00073 os << ">";
00074 }
00075 os << ")";
00076
00077 return os;
00078 }
00079
00080
00081 Define_Module(NeighborCache);
00082
00083 void NeighborCache::initializeApp(int stage)
00084 {
00085 if (stage != MIN_STAGE_COMPONENTS) {
00086 return;
00087 }
00088
00089 neighborCache.clear();
00090
00091 WATCH_UNORDERED_MAP(neighborCache);
00092
00093 enableNeighborCache = par("enableNeighborCache");
00094 rttExpirationTime = par("rttExpirationTime");
00095 maxSize = par("maxSize");
00096
00097
00098 std::string temp = par("defaultQueryType").stdstringValue();
00099 if (temp == "exact")
00100 defaultQueryType = NEIGHBORCACHE_EXACT;
00101 else if (temp == "exact_timeout")
00102 defaultQueryType = NEIGHBORCACHE_EXACT_TIMEOUT;
00103 else if (temp == "available")
00104 defaultQueryType = NEIGHBORCACHE_AVAILABLE;
00105 else if (temp == "estimated")
00106 defaultQueryType = NEIGHBORCACHE_ESTIMATED;
00107 else throw cRuntimeError((std::string("Wrong query type: ")
00108 + temp).c_str());
00109
00110 temp = par("defaultQueryTypeI").stdstringValue();
00111 if (temp == "available")
00112 defaultQueryTypeI = NEIGHBORCACHE_AVAILABLE;
00113 else if (temp == "estimated")
00114 defaultQueryTypeI = NEIGHBORCACHE_ESTIMATED;
00115 else throw cRuntimeError((std::string("Wrong query type (I): ")
00116 + temp).c_str());
00117
00118 temp = par("defaultQueryTypeQ").stdstringValue();
00119 if (temp == "exact")
00120 defaultQueryTypeQ = NEIGHBORCACHE_EXACT;
00121 else if (temp == "exact_timeout")
00122 defaultQueryTypeQ = NEIGHBORCACHE_EXACT_TIMEOUT;
00123 else if (temp == "query")
00124 defaultQueryTypeQ = NEIGHBORCACHE_QUERY;
00125 else throw cRuntimeError((std::string("Wrong query type (Q): ")
00126 + temp).c_str());
00127
00128
00129 enableNps = par("enableNps");
00130 if (enableNps) {
00131 nps = new Nps();
00132 nps->initNps(this);
00133
00134 } else {
00135 nps = NULL;
00136 }
00137
00138
00139 enableVivaldi = par("enableVivaldi");
00140 if (enableVivaldi) {
00141 vivaldi = new Vivaldi();
00142 vivaldi->initVivaldi(this);
00143 } else {
00144 vivaldi = NULL;
00145 }
00146
00147 globalStatistics = GlobalStatisticsAccess().get();
00148
00149 misses = 0;
00150 hits = 0;
00151
00152
00153
00154 rttErrorHistory = par("rttErrorHistory");
00155 rttHistory = par("rttHistory");
00156 numMsg = 0;
00157 absoluteError = 0.0;
00158 relativeError = 0.0;
00159 numRttErrorToHigh = 0;
00160 numRttErrorToLow = 0;
00161 lastAbsoluteErrorPerNode.clear();
00162 WATCH(absoluteError);
00163 WATCH(relativeError);
00164 WATCH(numMsg);
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 }
00181
00182 void NeighborCache::finishApp()
00183 {
00184 if ((misses + hits) != 0) {
00185 globalStatistics
00186 ->addStdDev("NeighborCache: Ping hit rate",
00187 ((double)hits / (double)(misses + hits)));
00188 }
00189
00190
00191
00192 if (numMsg > 0 && (enableVivaldi || enableNps)) {
00193 globalStatistics->addStdDev("NeighborCache: absolute RTT error",
00194 absoluteError / numMsg);
00195 globalStatistics->addStdDev("NeighborCache: relative RTT error",
00196 relativeError / numMsg);
00197 globalStatistics->addStdDev("NeighborCache: number of messages/s",
00198 numMsg / SIMTIME_DBL(simTime() - creationTime));
00199 globalStatistics->addStdDev("NeighborCache: percentage of RTT errors to high",
00200 (double)numRttErrorToHigh / (double)numMsg);
00201 globalStatistics->addStdDev("NeighborCache: percentage of RTT errors to low",
00202 (double)numRttErrorToLow / (double)numMsg);
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 }
00218
00219
00220 NeighborCache::~NeighborCache()
00221 {
00222 delete nps;
00223 delete vivaldi;
00224
00225 for (NeighborCacheIterator it = neighborCache.begin();
00226 it != neighborCache.end(); ++it) {
00227 if (it->second.waitingContexts) {
00228 for (uint32_t i = 0;
00229 i < it->second.waitingContexts->pingContexts.size(); ++i) {
00230 delete it->second.waitingContexts->pingContexts[i];
00231 }
00232
00233 delete it->second.waitingContexts;
00234 }
00235 }
00236 }
00237
00238 bool NeighborCache::insertNodeContext(const TransportAddress& handle,
00239 cPolymorphic* context,
00240 ProxListener* rpcListener,
00241 int rpcId)
00242 {
00243 if (!enableNeighborCache) return false;
00244 if (neighborCache.count(handle) == 0) {
00245 NeighborCacheEntry entry;
00246
00247 entry.insertTime = simTime();
00248 entry.rttState = RTTSTATE_WAITING;
00249 entry.nodeRef = NodeHandle::UNSPECIFIED_NODE;
00250 entry.coordsInfo.coordErr = 1;
00251 entry.coordsInfo.npsLayer = -1;
00252 entry.rttCounter = 0;
00253
00254 neighborCache[handle] = entry;
00255 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime,
00256 handle));
00257
00258 cleanupCache();
00259
00260 assert(neighborCache.size() == neighborCacheExpireMap.size());
00261 return false;
00262 } else {
00263 NeighborCacheEntry& entry = neighborCache[handle];
00264
00265
00266 if (entry.rttState == RTTSTATE_WAITING) {
00267 assert(entry.proxContext != NULL);
00268 if (entry.waitingContexts == NULL)
00269 entry.waitingContexts = new WaitingContexts();
00270 entry.waitingContexts->pingContexts.push_back(context);
00271 entry.waitingContexts->pingListeners.push_back(rpcListener);
00272 entry.waitingContexts->pingIds.push_back(rpcId);
00273
00274 return true;
00275 } else {
00276 if (entry.waitingContexts != NULL &&
00277 entry.waitingContexts->pingContexts.size() != 0) {
00278 throw cRuntimeError("not waiting for response,"
00279 " but additional contexts found!");
00280 }
00281
00282 updateEntry(handle, entry.insertTime);
00283
00284 assert(entry.waitingContexts == NULL && entry.proxContext == NULL);
00285
00286 entry.rttState = RTTSTATE_WAITING;
00287 entry.insertTime = simTime();
00288 entry.nodeRef = NodeHandle::UNSPECIFIED_NODE;
00289
00290 return false;
00291 }
00292 }
00293 }
00294
00295
00296 NeighborCache::WaitingContexts* NeighborCache::getNodeContexts(const TransportAddress& handle)
00297 {
00298 if (!enableNeighborCache) {
00299 assert(neighborCache.count(handle) == 0 ||
00300 neighborCache[handle].waitingContexts == NULL);
00301 return NULL;
00302 }
00303 if (neighborCache.count(handle) == 0)
00304 throw cRuntimeError("NeighborCache error!");
00305 WaitingContexts* temp = neighborCache[handle].waitingContexts;
00306 neighborCache[handle].waitingContexts = NULL;
00307
00308 return temp;
00309 }
00310
00311
00312 void NeighborCache::setNodeTimeout(const TransportAddress& handle)
00313 {
00314 if (!enableNeighborCache) return;
00315
00316 if (neighborCache.count(handle) == 0) {
00317 NeighborCacheEntry entry;
00318
00319 entry.insertTime = simTime();
00320 entry.rttState = RTTSTATE_TIMEOUT;
00321 entry.nodeRef = NodeHandle::UNSPECIFIED_NODE;
00322 entry.coordsInfo.npsLayer = -1;
00323 entry.coordsInfo.coordErr = -1;
00324 entry.rttCounter = 0;
00325
00326 neighborCache[handle] = entry;
00327 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime,
00328 handle));
00329 cleanupCache();
00330 } else {
00331 NeighborCacheEntry& entry = neighborCache[handle];
00332
00333 assert(!(entry.proxContext == NULL && entry.waitingContexts != NULL));
00334
00335 updateEntry(handle, entry.insertTime);
00336
00337 entry.insertTime = simTime();
00338 entry.rttState = RTTSTATE_TIMEOUT;
00339
00340 if (entry.proxContext) {
00341 WaitingContexts* waitingContexts = getNodeContexts(handle);
00342
00343 ProxContext* context = entry.proxContext;
00344 entry.proxContext = NULL;
00345
00346 if (context && context->listener) {
00347 context->listener->proxCallback(handle, context->rpcId,
00348 context->contextPointer,
00349 Prox::PROX_TIMEOUT);
00350
00351 if (waitingContexts) {
00352 for (uint32_t i = 0; i < waitingContexts->size(); ++i) {
00353 if (waitingContexts->pingListeners[i]) {
00354 waitingContexts->pingListeners[i]
00355 ->proxCallback(handle,
00356 waitingContexts->pingIds[i],
00357 waitingContexts->pingContexts[i],
00358 Prox::PROX_TIMEOUT);
00359 }
00360 }
00361 }
00362 }
00363 delete context;
00364 delete waitingContexts;
00365 }
00366 }
00367 assert(neighborCache.size() == neighborCacheExpireMap.size());
00368 }
00369
00370
00371 void NeighborCache::updateNode(const NodeHandle& add, simtime_t rtt,
00372 const NodeHandle& srcRoute,
00373 const std::vector<double>& coords,
00374 double error)
00375 {
00376 EV << "[NeighborCache::updateNode() @ " << thisNode.getAddress()
00377 << " (" << thisNode.getKey().toString(16) << ")]\n"
00378 << " inserting rtt(" << rtt << ") of node " << add.getAddress()
00379 << endl;
00380
00381 if (rtt <= 0) return;
00382
00383 if (enableNeighborCache) {
00384 if (neighborCache.count(add) == 0) {
00385 NeighborCacheEntry entry;
00386
00387 entry.insertTime = simTime();
00388 entry.rtt = rtt;
00389 entry.rttState = RTTSTATE_VALID;
00390 entry.nodeRef = add;
00391 entry.coordsInfo.npsLayer = -1;
00392 entry.coordsInfo.coordinates = coords;
00393 entry.coordsInfo.coordErr = error;
00394 entry.lastRtts.push_back(rtt);
00395 entry.rttCounter = 1;
00396
00397 neighborCache[add] = entry;
00398 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime,
00399 add));
00400
00401 cleanupCache();
00402 } else {
00403 updateEntry(add, neighborCache[add].insertTime);
00404
00405 NeighborCacheEntry& entry = neighborCache[add];
00406
00407 entry.insertTime = simTime();
00408 if (entry.rttState != RTTSTATE_VALID || entry.rtt > rtt)
00409 entry.rtt = rtt;
00410 entry.rttState = RTTSTATE_VALID;
00411 entry.nodeRef = add;
00412
00413 if (entry.rttCounter < rttHistory) {
00414 entry.lastRtts.push_back(rtt);
00415 } else {
00416 entry.lastRtts.at((entry.rttCounter % rttHistory)) = rtt;
00417 }
00418
00419 entry.rttCounter += 1;
00420
00421 if (entry.coordsInfo.coordErr > error) {
00422 entry.coordsInfo.coordinates = coords;
00423 entry.coordsInfo.coordErr = error;
00424 }
00425
00426 if (entry.proxContext) {
00427 WaitingContexts* waitingContexts = getNodeContexts(add);
00428
00429 ProxContext* context = entry.proxContext;
00430 entry.proxContext = NULL;
00431
00432 if (context && context->listener) {
00433 context->listener->proxCallback(add, context->rpcId,
00434 context->contextPointer,
00435 Prox(rtt, 1));
00436
00437 if (waitingContexts) {
00438 for (uint32_t i = 0; i < waitingContexts->size(); ++i) {
00439 if (waitingContexts->pingListeners[i]) {
00440 waitingContexts->pingListeners[i]
00441 ->proxCallback(add,
00442 waitingContexts->pingIds[i],
00443 waitingContexts->pingContexts[i],
00444 Prox(rtt, 1));
00445 }
00446 }
00447 }
00448 }
00449 delete context;
00450 delete waitingContexts;
00451 }
00452 assert(entry.proxContext == NULL && entry.waitingContexts == NULL);
00453 }
00454 assert(neighborCache.size() == neighborCacheExpireMap.size());
00455 }
00456
00457
00458 calcRttError(add, rtt);
00459
00460 if (enableVivaldi) vivaldi->processCoordinates(rtt, coords, error);
00461 }
00462
00463
00464 void NeighborCache::setNodeLayer(const NodeHandle& add, int8_t layer)
00465 {
00466 if (!enableNeighborCache) return;
00467
00468 if (neighborCache.count(add) == 0) {
00469 NeighborCacheEntry entry;
00470
00471 entry.insertTime = simTime();
00472 entry.nodeRef = add;
00473 entry.coordsInfo.npsLayer = layer;
00474 entry.coordsInfo.coordErr = 1;
00475 entry.rttCounter = 0;
00476
00477 neighborCache[add] = entry;
00478 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime, add));
00479
00480 cleanupCache();
00481 } else {
00482 updateEntry(add, neighborCache[add].insertTime);
00483
00484 neighborCache[add].insertTime = simTime();
00485 neighborCache[add].nodeRef = add;
00486 neighborCache[add].coordsInfo.npsLayer = layer;
00487 }
00488 }
00489
00490
00491 NeighborCache::Rtt NeighborCache::getNodeRtt(const TransportAddress &add)
00492 {
00493
00494 if (!enableNeighborCache ||
00495 add.isUnspecified() ||
00496 (neighborCache.count(add) == 0)) {
00497 misses++;
00498 return std::make_pair(0.0, RTTSTATE_UNKNOWN);
00499 }
00500
00501 NeighborCacheEntry &entry = neighborCache[add];
00502
00503 if (entry.rttState == RTTSTATE_WAITING ||
00504 entry.rttState == RTTSTATE_UNKNOWN)
00505 return std::make_pair(entry.rtt, entry.rttState);
00506
00507 if ((simTime() - entry.insertTime) >= rttExpirationTime) {
00508 assert(entry.waitingContexts == NULL);
00509 entry.rttState = RTTSTATE_UNKNOWN;
00510 return std::make_pair(entry.rtt, RTTSTATE_UNKNOWN);
00511 }
00512 hits++;
00513 assert(!(entry.rtt == 0.0 && entry.rttState == RTTSTATE_VALID));
00514 return std::make_pair(entry.rtt, entry.rttState);
00515 }
00516
00517
00518 const NodeHandle& NeighborCache::getNodeHandle(const TransportAddress &add)
00519 {
00520 if (neighborCache.count(add) == 0) {
00521 throw cRuntimeError("NeighborCache.cc: getNodeHandle was asked for "
00522 "a non-existent node reference.");
00523 }
00524 return neighborCache[add].nodeRef;
00525 }
00526
00527 bool NeighborCache::cleanupCache()
00528 {
00529 bool result = false;
00530 uint32_t size = neighborCache.size();
00531
00532 if (size > maxSize) {
00533 neighborCacheExpireMapIterator it;
00534 for (uint32_t i = 0; i < (size - (maxSize / 2)); ++i) {
00535 it = neighborCacheExpireMap.begin();
00536 if ((neighborCache[it->second].rttState == RTTSTATE_WAITING) ||
00537 (neighborCache[it->second].insertTime == simTime())) {
00538 break;
00539 }
00540 neighborCache.erase(it->second);
00541 neighborCacheExpireMap.erase(it);
00542 result = true;
00543 }
00544 }
00545 assert(neighborCache.size() == neighborCacheExpireMap.size());
00546 return result;
00547 }
00548
00549 void NeighborCache::updateEntry(const TransportAddress& address,
00550 simtime_t insertTime)
00551 {
00552 neighborCacheExpireMapIterator it =
00553 neighborCacheExpireMap.lower_bound(insertTime);
00554 while (it->second != address) ++it;
00555 neighborCacheExpireMap.erase(it);
00556 neighborCacheExpireMap.insert(std::make_pair(simTime(),
00557 address));
00558 assert(neighborCache.size() == neighborCacheExpireMap.size());
00559 }
00560
00561
00562 std::vector<LandmarkDataEntry> NeighborCache::getLandmarkData(const std::vector<TransportAddress>& landmarkSet) const
00563 {
00564 std::vector<LandmarkDataEntry> returnVector;
00565 NeighborCacheConstIterator it;
00566
00567 for(it = neighborCache.begin(); it != neighborCache.end(); it++ ) {
00568 for (uint i = 0; i < landmarkSet.size(); i++) {
00569 if (it->first == landmarkSet[i]) {
00570
00571 LandmarkDataEntry thisEntry =
00572 { it->second.rtt,
00573 it->second.coordsInfo.npsLayer,
00574 it->second.coordsInfo.coordinates,
00575 &it->first.getAddress() };
00576 returnVector.push_back(thisEntry);
00577 }
00578 }
00579 }
00580 return returnVector;
00581 }
00582
00583 bool NeighborCache::setLandmarkSet(uint8_t howManyLM, uint8_t maxLayer,
00584 std::vector<TransportAddress>* landmarkSet)
00585 {
00586 landmarkSet->clear();
00587 NeighborCacheIterator it;
00588 uint availableLM = 0;
00589 TransportAddress landmark;
00590 for(it = neighborCache.begin(); it != neighborCache.end(); it++ ) {
00591 landmark.setAddress(it->first.getAddress());
00592 landmark.setPort(it->second.nodeRef.getPort());
00593 if (it->second.coordsInfo.npsLayer < maxLayer) {
00594 availableLM++;
00595 landmarkSet->push_back(landmark);
00596 }
00597 }
00598 if (availableLM < howManyLM) {
00599 return false;
00600 } else {
00601 uint i = availableLM;
00602 while (i > howManyLM) {
00603 uint randomNumber = (intuniform(0, landmarkSet->size()));
00604 landmarkSet->erase(landmarkSet->begin() + randomNumber);
00605 i--;
00606 }
00607 return true;
00608 }
00609 }
00610
00611
00612 TransportAddress NeighborCache::getNearestNode(uint8_t maxLayer)
00613 {
00614 TransportAddress nearestNode = TransportAddress::UNSPECIFIED_NODE;
00615 simtime_t nearestNodeRtt = MAXTIME;
00616 NeighborCacheIterator it;
00617 if (neighborCache.size() > 1) {
00618 for(it = neighborCache.begin(); it != neighborCache.end(); it++ ) {
00619 if (it->second.rtt < nearestNodeRtt &&
00620 it->second.rtt > 0 &&
00621 it->second.coordsInfo.npsLayer < maxLayer+1 &&
00622 it->second.coordsInfo.npsLayer > 0) {
00623 nearestNode.setAddress(it->first.getAddress());
00624 nearestNodeRtt = it->second.rtt;
00625 nearestNode.setPort(it->second.nodeRef.getPort());
00626 }
00627 }
00628 }
00629 return nearestNode;
00630 }
00631
00632 bool NeighborCache::isEntry(const TransportAddress &node)
00633 {
00634 NeighborCacheIterator it;
00635 for(it = neighborCache.begin(); it != neighborCache.end(); it++ ) {
00636 if (it->first == node) {
00637 return true;
00638 }
00639 }
00640 return false;
00641 }
00642
00643
00644 double NeighborCache::getAvgAbsPredictionError(std::vector<double>& coord,
00645 uint32_t sampleSize)
00646 {
00647
00648 double absoluteDiff = 0.0;
00649 uint32_t numNeighbors = 0;
00650 uint32_t i;
00651
00652 for (std::map<TransportAddress, std::vector<double> >::iterator it =
00653 lastAbsoluteErrorPerNode.begin(); it != lastAbsoluteErrorPerNode.end();
00654 it++) {
00655 double tempAbsoluteDiff = 0.0;
00656 for (i = 0; i < it->second.size(); i++) {
00657 tempAbsoluteDiff += it->second.at(i);
00658 }
00659 absoluteDiff += (tempAbsoluteDiff / it->second.size());
00660 numNeighbors++;
00661 }
00662
00663 absoluteDiff /= numNeighbors;
00664 return (absoluteDiff > 1.0) ? 1.0 : absoluteDiff;
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 }
00708
00709
00710 void NeighborCache::handleTimerEvent(cMessage* msg)
00711 {
00712 if (nps) {
00713 nps->handleTimerEvent(msg);
00714 }
00715 }
00716
00717
00718 bool NeighborCache::handleRpcCall(BaseCallMessage* msg)
00719 {
00720 RPC_SWITCH_START( msg );
00721 if (nps) {
00722 RPC_DELEGATE( CoordsReq, nps->coordsReqRpc );
00723 }
00724
00725 RPC_SWITCH_END( );
00726
00727 return RPC_HANDLED;
00728 }
00729
00730
00731
00732
00733
00734 Prox NeighborCache::getProx(const TransportAddress &node,
00735 NeighborCacheQueryType type,
00736 int rpcId,
00737 ProxListener *listener,
00738 cPolymorphic *contextPointer)
00739 {
00740 Enter_Method("getProx()");
00741
00742 if (node == overlay->getThisNode()) return Prox::PROX_SELF;
00743
00744 bool sendQuery = false;
00745 Prox result = Prox::PROX_UNKNOWN;
00746 Rtt rtt = getNodeRtt(node);
00747
00748
00749 if (type == NEIGHBORCACHE_DEFAULT) type = defaultQueryType;
00750 else if (type == NEIGHBORCACHE_DEFAULT_IMMEDIATELY) type = defaultQueryTypeI;
00751 else if (type == NEIGHBORCACHE_DEFAULT_QUERY) type = defaultQueryTypeQ;
00752
00753 switch(type) {
00754 case NEIGHBORCACHE_EXACT:
00755 if (rtt.second == RTTSTATE_TIMEOUT) {
00756
00757 sendQuery = true;
00758 } else if (rtt.second == RTTSTATE_WAITING) {
00759
00760 sendQuery = true;
00761 } else if (rtt.second == RTTSTATE_UNKNOWN) {
00762
00763 sendQuery = true;
00764 } else {
00765
00766 result = rtt.first;
00767 }
00768 break;
00769 case NEIGHBORCACHE_EXACT_TIMEOUT:
00770 if (rtt.second == RTTSTATE_TIMEOUT) {
00771
00772 result = Prox::PROX_TIMEOUT;
00773 } else if (rtt.second == RTTSTATE_WAITING) {
00774
00775 sendQuery = true;
00776 } else if (rtt.second == RTTSTATE_UNKNOWN) {
00777
00778 sendQuery = true;
00779 } else {
00780
00781 result = rtt.first;
00782 }
00783 break;
00784 case NEIGHBORCACHE_ESTIMATED:
00785 if (rtt.second == RTTSTATE_TIMEOUT) {
00786
00787 result = Prox::PROX_TIMEOUT;
00788 } else if (rtt.second == RTTSTATE_WAITING) {
00789
00790 result = estimateProx(node);
00791 } else if (rtt.second == RTTSTATE_UNKNOWN) {
00792
00793 result = estimateProx(node);
00794 } else {
00795
00796 result = rtt.first;
00797 }
00798 break;
00799 case NEIGHBORCACHE_AVAILABLE:
00800 if (rtt.second == RTTSTATE_TIMEOUT) {
00801
00802 result = Prox::PROX_TIMEOUT;
00803 } else if ((rtt.second == RTTSTATE_WAITING) ||
00804 (rtt.second == RTTSTATE_UNKNOWN)) {
00805
00806 } else {
00807
00808 result = rtt.first;
00809 }
00810 break;
00811 case NEIGHBORCACHE_QUERY:
00812
00813 sendQuery = true;
00814 break;
00815 default:
00816 throw cRuntimeError("Unknown query type!");
00817 break;
00818
00819 }
00820 if (sendQuery) {
00821 if (!insertNodeContext(node, contextPointer, listener, rpcId)) {
00822 queryProx(node, rpcId, listener, contextPointer);
00823 }
00824 } else delete contextPointer;
00825
00826 return result;
00827 }
00828
00829 Prox NeighborCache::estimateProx(const TransportAddress &node)
00830 {
00831 Enter_Method("estimateProx()");
00832
00833 Rtt rtt = getNodeRtt(node);
00834
00835 if (rtt.second != RTTSTATE_UNKNOWN) return rtt.first;
00836
00837 if ((enableVivaldi || enableNps) && neighborCache.count(node)) {
00838 return getCoordinateBasedProx(node.getAddress());
00839 }
00840
00841 return Prox::PROX_UNKNOWN;
00842 }
00843
00844 void NeighborCache::queryProx(const TransportAddress &node,
00845 int rpcId,
00846 ProxListener *listener,
00847 cPolymorphic *contextPointer)
00848 {
00849 Enter_Method("queryProx()");
00850
00851 ProxContext* context = new ProxContext;
00852 context->rpcId = rpcId;
00853 context->listener = listener;
00854 context->contextPointer = contextPointer;
00855
00856 if (neighborCache.count(node) == 0) {
00857 NeighborCacheEntry entry;
00858 entry.proxContext = context;
00859 neighborCache[node] = entry;
00860 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime,
00861 node));
00862 cleanupCache();
00863 } else {
00864 NeighborCacheEntry& entry = neighborCache[node];
00865 if (entry.proxContext != NULL) throw cRuntimeError("double proxContext");
00866 entry.proxContext = context;
00867 }
00868 assert(neighborCache.size() == neighborCacheExpireMap.size());
00869
00870 pingNode(node, -1, 0, NULL, "PING");
00871 }
00872
00873 Prox NeighborCache::getCoordinateBasedProx(const TransportAddress& node)
00874 {
00875 if (enableVivaldi) {
00876 return vivaldi->getCoordinateBasedProx(getNodeCoordsInfo(node));
00877 } else if (enableNps){
00878 return nps->getCoordinateBasedProx(getNodeCoordsInfo(node));
00879 } else return Prox::PROX_UNKNOWN;
00880 }
00881
00882
00883 const NodeCoordsInfo& NeighborCache::getNodeCoordsInfo(const TransportAddress &node)
00884 {
00885 if (neighborCache.count(node) == 0) {
00886 throw cRuntimeError("NeighborCache.cc: getNodeCoords was asked for "
00887 "a non-existent node reference.");
00888 }
00889 return neighborCache[node].coordsInfo;
00890 }
00891
00892 void NeighborCache::setNodeCoordsInfo(const TransportAddress& handle,
00893 const NodeCoordsInfo& coords)
00894 {
00895 if (!enableNeighborCache) return;
00896 if (neighborCache.count(handle) == 0) {
00897 NeighborCacheEntry entry;
00898
00899 entry.insertTime = simTime();
00900 entry.rttState = RTTSTATE_UNKNOWN;
00901 entry.nodeRef = NodeHandle::UNSPECIFIED_NODE;
00902 entry.coordsInfo = coords;
00903 entry.rttCounter = 0;
00904
00905 neighborCache[handle] = entry;
00906 neighborCacheExpireMap.insert(std::make_pair(entry.insertTime,
00907 handle));
00908
00909 cleanupCache();
00910 } else {
00911 NeighborCacheEntry& entry = neighborCache[handle];
00912
00913 updateEntry(handle, entry.insertTime);
00914
00915 entry.insertTime = simTime();
00916 if (entry.coordsInfo.coordErr > coords.coordErr)
00917 entry.coordsInfo = coords;
00918 }
00919 assert(neighborCache.size() == neighborCacheExpireMap.size());
00920 }
00921
00922
00923 void NeighborCache::calcRttError(const NodeHandle& handle, simtime_t rtt)
00924 {
00925 if (!enableVivaldi && !enableNps)
00926 return;
00927
00928
00929
00930 double tempRttError = getCoordinateBasedProx(handle).proximity - SIMTIME_DBL(rtt);
00931
00932
00933 lastAbsoluteErrorPerNode[handle].push_back(fabs(tempRttError));
00934
00935 if(lastAbsoluteErrorPerNode[handle].size() > (uint32_t)rttErrorHistory)
00936 lastAbsoluteErrorPerNode[handle].erase(lastAbsoluteErrorPerNode[handle].begin());
00937
00938
00939 if(!globalStatistics->isMeasuring()) return;
00940
00941 if(tempRttError < 0){
00942 tempRttError *=-1;
00943 numRttErrorToLow++;
00944 }else numRttErrorToHigh++;
00945
00946
00947 numMsg++;
00948 absoluteError += tempRttError;
00949 relativeError += tempRttError/SIMTIME_DBL(rtt);
00950
00951 globalStatistics->recordOutVector("Vivaldi: absolute Rtt Error",
00952 tempRttError);
00953 globalStatistics->recordOutVector("Vivaldi: relative Rtt Error",
00954 (tempRttError/SIMTIME_DBL(rtt)));
00955 }
00956
00957 bool NeighborCache::checkEntry(const TransportAddress &node)
00958 {
00959
00960 if (neighborCache.count(node) == 0) {
00961 return false;
00962
00963 }
00964
00965
00966
00967 return true;
00968 }
00969
00970 simtime_t NeighborCache::getMeanRtt(const TransportAddress &node)
00971 {
00972 int size = 0;
00973 simtime_t rttSum = 0;
00974 if (neighborCache.count(node) == 0) {
00975 throw cRuntimeError("NeighborCache.cc: getMeanRtt was asked for"
00976 "a non-existent node reference.");
00977 }
00978
00979 size = neighborCache[node].lastRtts.size();
00980
00981 neighborCache[node].coordsInfo;
00982
00983 for (int i = 0; i < size; i++){
00984 rttSum += neighborCache[node].lastRtts.at(i);
00985 }
00986 return (rttSum / size);
00987 }
00988
00989
00990 double NeighborCache::getVarRtt(const TransportAddress &node, simtime_t &meanRtt)
00991 {
00992 int size = 0;
00993 double sum = 0.0;
00994 simtime_t tempRtt;
00995
00996 if (neighborCache.count(node) == 0) {
00997 throw cRuntimeError("NeighborCache.cc: getMeanRtt was asked for"
00998 "a non-existent node reference.");
00999 }
01000
01001 meanRtt = getMeanRtt(node);
01002 size = neighborCache[node].lastRtts.size();
01003 for (int i = 0; i < size; i++){
01004 tempRtt = neighborCache[node].lastRtts.at(i) - meanRtt;
01005 sum += (SIMTIME_DBL(tempRtt) * SIMTIME_DBL(tempRtt));
01006 }
01007
01008 if (size < 2) {
01009 return 0;
01010 }
01011
01012 if (size == 0) return -1;
01013 return (sum / (size -1));
01014 }