NeighborCache.h

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 
00026 #ifndef __NEIGHBORCACHE_H_
00027 #define __NEIGHBORCACHE_H_
00028 
00029 #include <omnetpp.h>
00030 
00031 #include <map>
00032 #include <cfloat>
00033 #include <deque>
00034 
00035 #include <BaseApp.h>
00036 #include <NodeHandle.h>
00037 #include <CoordinateSystem.h>
00038 #include <Nps.h>
00039 #include <Vivaldi.h>
00040 #include <SVivaldi.h>
00041 #include <SimpleNcs.h>
00042 #include <ProxNodeHandle.h>
00043 #include <HashFunc.h>
00044 
00045 class GlobalStatistics;
00046 class TransportAddress;
00047 class RpcListener;
00048 
00049 
00050 // Prox stuff
00051 enum NeighborCacheQueryType {
00052     NEIGHBORCACHE_AVAILABLE,     //< RTT, timeout, or unknown (no query)
00053     NEIGHBORCACHE_EXACT,         //< RTT or query
00054     NEIGHBORCACHE_EXACT_TIMEOUT, //< RTT, timeout, or query
00055     NEIGHBORCACHE_ESTIMATED,     //< RTT or estimated
00056     NEIGHBORCACHE_QUERY,         //< only query, return unknown
00057     // default
00058     NEIGHBORCACHE_DEFAULT,       //< available, exact, exact_timeout or estimated
00059     NEIGHBORCACHE_DEFAULT_IMMEDIATELY, //< return a result immediately (available or estimated)
00060     NEIGHBORCACHE_DEFAULT_QUERY  //< do a query if needed (exact, exact_timeout, or query)
00061 };
00062 
00063 class ProxListener {
00064 public:
00065     virtual void proxCallback(const TransportAddress& node, int rpcId,
00066                               cPolymorphic *contextPointer, Prox prox) = 0;
00067 };
00068 
00069 class NeighborCache : public BaseApp
00070 {
00071     friend class Nps;
00072 
00073 private:
00074     // parameters
00075     bool enableNeighborCache;
00076     bool doDiscovery;
00077     simtime_t rttExpirationTime;
00078     uint32_t maxSize;
00079 
00080     uint32_t misses;
00081     uint32_t hits;
00082 
00083     bool cleanupCache();
00084 
00085     void updateEntry(const TransportAddress& address,
00086                      simtime_t insertTime);
00087 
00088     AbstractNcs* ncs;
00089     bool ncsSendBackOwnCoords;
00090 
00091     NeighborCacheQueryType defaultQueryType;
00092     NeighborCacheQueryType defaultQueryTypeI;
00093     NeighborCacheQueryType defaultQueryTypeQ;
00094 
00095     Prox getCoordinateBasedProx(const TransportAddress& node);
00096 
00097     cMessage* landmarkTimer;
00098 
00099     static const std::vector<double> coordsDummy;
00100 
00101     //Stuff needed to calculate a mean RTT to a specific node
00102     void calcRttError(const NodeHandle &handle, simtime_t rtt);
00103     std::map<TransportAddress, std::vector<double> > lastAbsoluteErrorPerNode;
00104     uint32_t numMsg;
00105     double absoluteError;
00106     double relativeError;
00107     uint32_t numRttErrorToHigh;
00108     uint32_t numRttErrorToLow;
00109     uint32_t rttHistory;
00110     double timeoutAccuracyLimit;
00111 
00112     struct WaitingContext
00113     {
00114         WaitingContext() { proxListener = NULL; proxContext = NULL; };
00115         WaitingContext(ProxListener* listener,
00116                        cPolymorphic* context,
00117                        uint32_t id)
00118             : proxListener(listener), proxContext(context), id(id) { };
00119         ProxListener* proxListener;
00120         cPolymorphic* proxContext;
00121         uint32_t id;
00122     };
00123     typedef std::vector<WaitingContext> WaitingContexts;
00124 
00125     // ping context stuff
00126     bool insertNodeContext(const TransportAddress& handle,
00127                            cPolymorphic* context,
00128                            ProxListener* rpcListener,
00129                            int rpcId);
00130 
00131     NeighborCache::WaitingContexts getNodeContexts(const TransportAddress& handle);
00132 
00133     enum NeighborCacheRttState {
00134         RTTSTATE_VALID,
00135         RTTSTATE_UNKNOWN,
00136         RTTSTATE_TIMEOUT,
00137         RTTSTATE_WAITING
00138     };
00139 
00140     typedef std::pair<simtime_t, NeighborCacheRttState> Rtt;
00141 
00142     Rtt getNodeRtt(const TransportAddress& add);
00143 
00144     static const double RTT_TIMEOUT_ADJUSTMENT = 1.3;
00145     static const double NCS_TIMEOUT_CONSTANT = 0.25;
00146 
00147 protected:
00148     GlobalStatistics* globalStatistics;
00149 
00150     struct NeighborCacheEntry {
00151         NeighborCacheEntry() { insertTime = simTime();
00152                                rttState = RTTSTATE_UNKNOWN;
00153                                coordsInfo = NULL; };
00154 
00155         ~NeighborCacheEntry() {
00156             delete coordsInfo;
00157             for (uint16_t i = 0; i < waitingContexts.size(); ++i) {
00158                 delete waitingContexts[i].proxContext;
00159             }
00160         };
00161 
00162         simtime_t  insertTime;
00163         simtime_t  rtt;
00164         NeighborCacheRttState rttState;
00165         std::deque<simtime_t> lastRtts;
00166         NodeHandle nodeRef;
00167         NodeHandle srcRoute;
00168         AbstractNcsNodeInfo* coordsInfo;
00169 
00170         WaitingContexts waitingContexts;
00171     };
00172 
00173     UNORDERED_MAP<TransportAddress, NeighborCacheEntry> neighborCache;
00174     typedef UNORDERED_MAP<TransportAddress, NeighborCacheEntry>::iterator NeighborCacheIterator;
00175     typedef UNORDERED_MAP<TransportAddress, NeighborCacheEntry>::const_iterator NeighborCacheConstIterator;
00176 
00177     std::multimap<simtime_t, TransportAddress> neighborCacheExpireMap;
00178     typedef std::multimap<simtime_t, TransportAddress>::iterator neighborCacheExpireMapIterator;
00179 
00180     void initializeApp(int stage);
00181 
00182     void finishApp();
00183 
00184     virtual CompType getThisCompType() { return NEIGHBORCACHE_COMP; };
00185 
00186     void handleReadyMessage(CompReadyMessage* readyMsg);
00187 
00188     void handleTimerEvent(cMessage* msg);
00189 
00196     void queryProx(const TransportAddress &node,
00197                    int rpcId,
00198                    ProxListener *listener,
00199                    cPolymorphic *contextPointer);
00200 
00204     bool handleRpcCall(BaseCallMessage* msg);
00205 
00206     simtime_t getRttBasedTimeout(const NodeHandle &node);
00207     simtime_t getNcsBasedTimeout(const NodeHandle &node);
00208 
00209 public:
00210     ~NeighborCache();
00211 
00212     inline bool isEnabled() { return enableNeighborCache; };
00213 
00214     bool sendBackOwnCoords() { return (ncsSendBackOwnCoords && ncs != NULL); };
00215 
00216     const AbstractNcs& getNcsAccess() const {
00217         if (!ncs) throw cRuntimeError("No NCS activated");
00218         else return *ncs;
00219     };
00220 
00221     const NodeHandle& getOverlayThisNode() { return overlay->getThisNode(); };
00222 
00223     uint16_t getNeighborCacheSize() { return neighborCache.size(); };
00224 
00225     // getter for specific node information
00226     bool isEntry(const TransportAddress& node);
00227     simtime_t getNodeAge(const TransportAddress& handle);
00228     const NodeHandle& getNodeHandle(const TransportAddress &add);
00229 
00236     simtime_t getNodeTimeout(const NodeHandle &node);
00237 
00238     // getter for general node information
00239     TransportAddress getNearestNode(uint8_t maxLayer);
00240     double getAvgAbsPredictionError();
00241 
00242     // setter for specific node information
00243     void updateNode(const NodeHandle &add, simtime_t rtt,
00244                     const NodeHandle& srcRoute = NodeHandle::UNSPECIFIED_NODE,
00245                     AbstractNcsNodeInfo* ncsInfo = NULL);
00246     void updateNcsInfo(const TransportAddress& node,
00247                        AbstractNcsNodeInfo* ncsInfo);
00248     void setNodeTimeout(const TransportAddress& handle);
00249 
00271     Prox getProx(const TransportAddress &node,
00272                  NeighborCacheQueryType type = NEIGHBORCACHE_AVAILABLE,
00273                  int rpcId = -1,
00274                  ProxListener *listener = NULL,
00275                  cPolymorphic *contextPointer = NULL);
00276 
00284     Prox estimateProx(const TransportAddress &node);
00285 
00292     const AbstractNcsNodeInfo* getNodeCoordsInfo(const TransportAddress &node);
00293 
00294     //calculate mean RTT to a specific node
00295     //simtime_t getMeanRtt(const TransportAddress &node);
00296     //calculate variance of the RTT to a specific node
00297     //double getVarRtt(const TransportAddress &node, simtime_t &meanRtt);
00298 
00299     std::pair<simtime_t, simtime_t> getMeanVarRtt(const TransportAddress &node,
00300                                                   bool returnVar);
00301 
00302     friend std::ostream& operator<<(std::ostream& os,
00303                                     const NeighborCacheEntry& entry);
00304 };
00305 
00306 #endif
00307