NeighborCache.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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     //WATCH_MAP(neighborCache);
00091     WATCH_UNORDERED_MAP(neighborCache);
00092 
00093     enableNeighborCache = par("enableNeighborCache");
00094     rttExpirationTime = par("rttExpirationTime");
00095     maxSize = par("maxSize");
00096 
00097     // set default query types
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     // nps/gnp init
00129     enableNps = par("enableNps");
00130     if (enableNps) {
00131         nps = new Nps();
00132         nps->initNps(this);
00133         //TODO joinOnApplicationRequest
00134     } else {
00135         nps = NULL;
00136     }
00137 
00138     // vivaldi init
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     //TODO
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     countGetProxTotal = 0.0;
00168     countGetProxSuccessful = 0.0;
00169     relativeGetProx = 0.0;
00170 
00171     countCheckEntryTotal = 0.0;
00172     countCheckEntrySuccessful = 0.0;
00173     relativeCheckEntry = 0.0;
00174     */
00175     //-------
00176 
00177     //lastProxRpcId = 0;
00178     //proxCacheListener.parent = this;
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     //TODO
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 //    globalStatistics->addStdDev("NeighborCache: percentage of Successful getProx operation",
00205 //                                relativeGetProx);
00206 //    globalStatistics->addStdDev("NeighborCache: total getProx operation",
00207 //                                countGetProxTotal);
00208 //    globalStatistics->addStdDev("NeighborCache: Successful getProx operation",
00209 //                                countGetProxSuccessful);
00210 //    globalStatistics->addStdDev("NeighborCache: Successful checkEntry operation",
00211 //                                countCheckEntrySuccessful);
00212 //    globalStatistics->addStdDev("NeighborCache: total checkEntry operation",
00213 //                                countCheckEntryTotal);
00214 //    globalStatistics->addStdDev("NeighborCache: percentage of Successful checkEntry operation",
00215 //                                relativeCheckEntry);
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         // waiting?
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; //TODO broose
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) { //TODO
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     //TODO
00457     //--------
00458     calcRttError(add, rtt);
00459     //--------
00460     if (enableVivaldi) vivaldi->processCoordinates(rtt, coords, error);
00461 }
00462 
00463 //TODO duplicated code
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     // cache disabled or entry not there
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     // entry expired
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 // coordinate stuff
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                 // get the relevant data of this landmark.
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++ ) { //TODO find
00636         if (it->first == node) {
00637             return true;
00638         }
00639     }
00640     return false;
00641 }
00642 
00643 // Vivaldi stuff
00644 double NeighborCache::getAvgAbsPredictionError(std::vector<double>& coord,
00645                                                uint32_t sampleSize)
00646 {
00647     //TODO version roth
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     // old version
00667     /*
00668     if (neighborCache.size() < 2 || sampleSize == 0) return 1.0;
00669 
00670     double absoluteDiff = 0;
00671     uint32_t numNeighbors = 0;
00672 
00673     //for (std::map<IPvXAddress, NeighborCacheEntry>::iterator it =
00674     //     neighborCache.begin(); it != neighborCache.end(); ++it) {
00675     for (std::map<simtime_t, IPvXAddress>::reverse_iterator it =
00676          neighborCacheExpireMap.rbegin();
00677          it != neighborCacheExpireMap.rend() &&
00678          numNeighbors < sampleSize; ++it) {
00679         NeighborCacheEntry& cacheEntry = neighborCache[it->second];
00680         double dist = 0;
00681         for (uint32_t i = 0; i < cacheEntry.coordsInfo.coordinates.size(); i++) {
00682             dist += pow(coord[i] - cacheEntry.coordsInfo.coordinates[i], 2);
00683         }
00684         dist = sqrt(dist);
00685 
00686         if (dist != 0 && cacheEntry.rtt > 0) {
00687             double predictionError = fabs(dist - SIMTIME_DBL(cacheEntry.rtt));
00688 
00689             //test: error weighted
00690             //if (it->second.coordErr < 1) {
00691             //    predictionError /= it->second.coordErr;
00692             //}
00693             //test: age weighted
00694             //if ((simTime() - it->second.insertTime) > 1) {
00695             //    predictionError /= (simTime() - it->second.insertTime);
00696             //}
00697 
00698             numNeighbors++;
00699             absoluteDiff += predictionError;
00700         }
00701     }
00702     assert(numNeighbors != 0);
00703     absoluteDiff /= numNeighbors;
00704 
00705     return (absoluteDiff > 1.0) ? 1.0 : absoluteDiff;
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         //if (discovery)
00725     RPC_SWITCH_END( );
00726 
00727     return RPC_HANDLED;
00728 }
00729 
00730 
00731 
00732 // Prox stuff
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     //countGetProxTotal++;
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                 // if timeout, return unknown, and send a query!
00757                 sendQuery = true;
00758             } else if (rtt.second == RTTSTATE_WAITING) {
00759                 // if a query was sent, return UNKNOWN
00760                 sendQuery = true; //just inserting a context, no real ping is sent
00761             } else if (rtt.second == RTTSTATE_UNKNOWN) {
00762                 // if no entry known, send a query and return UNKNOWN
00763                 sendQuery = true;
00764             } else {
00765                 // else, return whatever we have
00766                 result = rtt.first;
00767             }
00768             break;
00769         case NEIGHBORCACHE_EXACT_TIMEOUT:
00770             if (rtt.second == RTTSTATE_TIMEOUT) {
00771                 // if timeout, return that
00772                 result = Prox::PROX_TIMEOUT;
00773             } else if (rtt.second == RTTSTATE_WAITING) {
00774                 // if a query was sent, return UNKNOWN
00775                 sendQuery = true; //just inserting a context, no real ping is sent
00776             } else if (rtt.second == RTTSTATE_UNKNOWN) {
00777                 // if no entry known, send a query and return UNKNOWN
00778                 sendQuery = true;
00779             } else {
00780                 // else, return whatever we have
00781                 result = rtt.first;
00782             }
00783             break;
00784         case NEIGHBORCACHE_ESTIMATED:
00785             if (rtt.second == RTTSTATE_TIMEOUT) {
00786                 // if timeout, return that
00787                 result = Prox::PROX_TIMEOUT;
00788             } else if (rtt.second == RTTSTATE_WAITING) {
00789                 // if a query was sent, return an estimate
00790                 result = estimateProx(node);
00791             } else if (rtt.second == RTTSTATE_UNKNOWN) {
00792                 // if no entry known, return an estimate
00793                 result = estimateProx(node);
00794             } else {
00795                 // else return whatever we have
00796                 result = rtt.first;
00797             }
00798             break;
00799         case NEIGHBORCACHE_AVAILABLE:
00800             if (rtt.second == RTTSTATE_TIMEOUT) {
00801                 // if timeout, return that.
00802                 result = Prox::PROX_TIMEOUT;
00803             } else if ((rtt.second == RTTSTATE_WAITING) ||
00804                        (rtt.second == RTTSTATE_UNKNOWN)) {
00805                 // if a query was sent or entry unknown, return UNKNOWN
00806             } else {
00807                 // else return what we have
00808                 result = rtt.first;
00809             }
00810             break;
00811         case NEIGHBORCACHE_QUERY:
00812             // simply send a query and return UNKNOWN
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) { //Vivaldi
00876         return vivaldi->getCoordinateBasedProx(getNodeCoordsInfo(node));
00877     } else if (enableNps){ //NPS
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 //TODO roth
00923 void NeighborCache::calcRttError(const NodeHandle& handle, simtime_t rtt)
00924 {
00925     if (!enableVivaldi && !enableNps)
00926         return;
00927 
00928     //calculate absloute rtt error of the last message
00929     //double tempRttError = SIMTIME_DBL(getNodePredictedRtt(handle) - rtt);
00930     double tempRttError = getCoordinateBasedProx(handle).proximity - SIMTIME_DBL(rtt);
00931 
00932 
00933     lastAbsoluteErrorPerNode[handle].push_back(fabs(tempRttError));
00934     //      lastAbsoluteErrorPerNode[handle.ip].push_back(SIMTIME_DBL(rtt));
00935     if(lastAbsoluteErrorPerNode[handle].size() > (uint32_t)rttErrorHistory)
00936         lastAbsoluteErrorPerNode[handle].erase(lastAbsoluteErrorPerNode[handle].begin());
00937 
00938     // Check if data collection can start
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     //countCheckEntryTotal++;
00960     if (neighborCache.count(node) == 0) {
00961         return false;
00962 
00963     }
00964     //countCheckEntrySuccessful++;
00965     //relativeCheckEntry = countCheckEntrySuccessful /
00966     //countCheckEntryTotal * 100;
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 }

Generated on Tue Sep 8 17:26:53 2009 for OverSim by  doxygen 1.5.8