simplecache.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * simplecache.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: simplecache.cc,v 1.2 2005/08/25 18:58:05 johnh Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 //
00047 // Other copyrights might apply to parts of this software and are so
00048 // noted when applicable.
00049 
00050 /* simplecache.cc
00051    cache used in the mobicom 98 submission.  see the paper for a description
00052    Ported from CMU/Monarch's code, appropriate copyright applies.  
00053 */
00054 
00055 #ifdef DSR_SIMPLECACHE
00056 
00057 extern "C" {
00058 #include <stdio.h>
00059 #include <stdarg.h>
00060 };
00061 
00062 #undef DEBUG
00063 
00064 #include <god.h>
00065 #include "path.h"
00066 #include "routecache.h"
00067 #ifdef DSR_CACHE_STATS
00068 #include "cache_stats.h"
00069 #endif
00070 
00071 
00072 /* invariants
00073 
00074    - no path contains an id more than once
00075    - all paths start with the id of our node (MAC_id or net_id)
00076 */
00077 
00078 #define fout stdout
00079 
00080 static const int verbose = 0;
00081 static const int verbose_debug = 0;
00082 
00083 /*===============================================================
00084   function selectors
00085 ----------------------------------------------------------------*/
00086 bool cache_ignore_hints = false;     // ignore all hints?
00087 bool cache_use_overheard_routes = true; 
00088 // if we are A, and we over hear a rt Z Y (X) W V U, do we add route
00089 // A X W V U to the cache?
00090 
00091 
00092 /*===============================================================
00093   Class declaration
00094 ----------------------------------------------------------------*/
00095 class MobiCache;
00096 
00097 class Cache {
00098 friend class MobiCache;
00099 
00100 public:
00101   Cache(char *name, int size, MobiCache *rtcache);
00102   ~Cache();
00103 
00104   int pickVictim(int exclude = -1);
00105   // returns the index of a suitable victim in the cache
00106   // will spare the life of exclude
00107   bool searchRoute(const ID& dest, int& i, Path &path, int &index);
00108   // look for dest in cache, starting at index, 
00109   //if found, rtn true with path s.t. cache[index] == path && path[i] == dest
00110   Path* addRoute(Path &route, int &prefix_len);
00111   // rtns a pointer the path in the cache that we added
00112   void noticeDeadLink(const ID&from, const ID& to);
00113   // the link from->to isn't working anymore, purge routes containing
00114   // it from the cache
00115 
00116 private:
00117   Path *cache;
00118   int size;
00119   int victim_ptr;       // next victim for eviction
00120   MobiCache *routecache;
00121   char *name;
00122 };
00123 
00125 
00126 class MobiCache : public RouteCache {
00127 friend class Cache;
00128 friend class MobiHandler;
00129 
00130 public:
00131   MobiCache(const ID& MAC_id, const ID& net_id,int psize = 30,int ssize = 34 );
00132   MobiCache();
00133   ~MobiCache();
00134   void noticeDeadLink(const ID&from, const ID& to, Time t);
00135   // the link from->to isn't working anymore, purge routes containing
00136   // it from the cache
00137   void noticeRouteUsed(const Path& route, Time t,
00138                const ID& who_from);
00139   // tell the cache about a route we saw being used
00140   void addRoute(const Path& route, Time t, const ID& who_from);
00141   // add this route to the cache (presumably we did a route request
00142   // to find this route and don't want to lose it)
00143   bool findRoute(ID dest, Path& route, int for_use = 0);
00144   // if there is a cached path from us to dest returns true and fills in
00145   // the route accordingly. returns false otherwise
00146   // if for_use, then we assume that the node really wants to keep 
00147   // the returned route so it will be promoted to primary storage if not there
00148   // already
00149   int command(int argc, const char*const* argv);
00150 
00151 protected:
00152   Cache *secondary_cache; /* routes we've learned via a speculative process
00153                  that might not pan out */
00154 
00155 #ifdef DSR_CACHE_STATS
00156   void periodic_checkCache(void);
00157   void checkRoute(Path *p, int action, int prefix_len);
00158   void checkRoute(Path &p, int&, int&, double&, int&, int&, double &);
00159 #endif
00160 };
00161 
00162 
00163 RouteCache *
00164 makeRouteCache()
00165 {
00166   return new MobiCache();
00167 }
00168 
00169 
00170 /*===============================================================
00171   OTcl definition
00172 ----------------------------------------------------------------*/
00173 static class MobiCacheClass : public TclClass {
00174 public:
00175         MobiCacheClass() : TclClass("MobiCache") {}
00176         TclObject* create(int, const char*const*) {
00177                 return (new MobiCache);
00178         }
00179 } class_MobiCache;
00180 
00181 /*===============================================================
00182  Constructors
00183 ----------------------------------------------------------------*/
00184 MobiCache::MobiCache(): RouteCache()
00185 {
00186   secondary_cache = new Cache("secondary", 10000, this);
00187   assert(secondary_cache != NULL);
00188 #ifdef DSR_CACHE_STATS
00189     stat.reset();
00190 #endif
00191 }
00192 
00193 MobiCache::~MobiCache()
00194 {
00195   delete secondary_cache;
00196 }
00197 
00198 int
00199 MobiCache::command(int argc, const char*const* argv)
00200 {
00201   if(argc == 2 && strcasecmp(argv[1], "startdsr") == 0)
00202     { 
00203       if (ID(1,::IP) == net_id) 
00204     trace("Sconfig %.5f using MOBICACHE", Scheduler::instance().clock());
00205       // FALL-THROUGH
00206     }
00207   return RouteCache::command(argc, argv);
00208 }
00209 
00210 #ifdef DSR_CACHE_STATS
00211 
00212 void
00213 MobiCache::periodic_checkCache()
00214 {
00215   int c;
00216   int route_count = 0;
00217   int route_bad_count = 0;
00218   int subroute_count = 0;
00219   int subroute_bad_count = 0;
00220   int link_bad_count = 0;
00221   double link_bad_time = 0.0;
00222   int link_bad_tested = 0;
00223   int link_good_tested = 0;
00224 
00225   for(c = 0; c < secondary_cache->size; c++)
00226     {
00227       int x = 0;
00228 
00229       if (secondary_cache->cache[c].length() == 0) continue;
00230 
00231       checkRoute(secondary_cache->cache[c],
00232                  x,
00233                  link_bad_count,
00234                  link_bad_time,
00235                  link_bad_tested,
00236                  link_good_tested,
00237          stat.link_good_time);
00238 
00239       route_count += 1;
00240       route_bad_count += x ? 1 : 0;
00241 
00242       subroute_count += secondary_cache->cache[c].length() - 1;
00243       subroute_bad_count += x;
00244     }
00245 
00246   // lifetime of good link is (total time) / (total num links - num bad links)
00247   stat.link_good_time = stat.link_good_time / (subroute_count - link_bad_count);
00248 
00249   trace("SRC %.9f _%s_ cache-summary %d %d %d %d | %d %.9f %d %d | %d %d %d %d %d | %d %d %d %d %d | %d %d %d %d %d %d %.9f",
00250     Scheduler::instance().clock(), net_id.dump(),
00251         route_count,
00252         route_bad_count,
00253         subroute_count,
00254         subroute_bad_count,
00255 
00256         link_bad_count,
00257         link_bad_count ? link_bad_time/link_bad_count : 0.0,
00258         link_bad_tested,
00259         link_good_tested,
00260 
00261         stat.route_add_count,
00262         stat.route_add_bad_count,
00263         stat.subroute_add_count,
00264         stat.subroute_add_bad_count,
00265         stat.link_add_tested,
00266              
00267         stat.route_notice_count,
00268         stat.route_notice_bad_count,
00269         stat.subroute_notice_count,
00270         stat.subroute_notice_bad_count,
00271         stat.link_notice_tested,
00272              
00273         stat.route_find_count,
00274     stat.route_find_for_me,
00275         stat.route_find_bad_count,
00276         stat.route_find_miss_count,
00277         stat.subroute_find_count,
00278         stat.subroute_find_bad_count,
00279 
00280     stat.link_good_time);
00281   stat.reset();
00282 }
00283 
00284 #endif /* DSR_CACHE_STATS */
00285 
00286 /*===============================================================
00287   member functions
00288 ----------------------------------------------------------------*/
00289 
00290 void
00291 MobiCache::addRoute(const Path& route, Time t, const ID& who_from)
00292 // add this route to the cache (presumably we did a route request
00293 // to find this route and don't want to lose it)
00294 // who_from is the id of the routes provider
00295 {
00296   Path rt;
00297 
00298   if(pre_addRoute(route, rt, t, who_from) == 0)
00299     return;
00300 
00301   // must call addRoute before checkRoute
00302   int prefix_len = 0;
00303 
00304 #ifdef DSR_CACHE_STATS
00305   Path *p = secondary_cache->addRoute(rt, prefix_len);
00306   checkRoute(p, ACTION_ADD_ROUTE, prefix_len);
00307 #else
00308   (void) secondary_cache->addRoute(rt, prefix_len);
00309 #endif
00310 }
00311 
00312 void
00313 MobiCache::noticeDeadLink(const ID&from, const ID& to, Time)
00314   // the link from->to isn't working anymore, purge routes containing
00315   // it from the cache
00316 {
00317   if(verbose_debug)
00318     trace("SRC %.9f _%s_ dead link %s->%s",
00319       Scheduler::instance().clock(), net_id.dump(),
00320       from.dump(), to.dump());
00321   
00322   secondary_cache->noticeDeadLink(from, to);
00323   return;
00324 }
00325 
00326 
00327 void
00328 MobiCache::noticeRouteUsed(const Path& p, Time t, const ID& who_from)
00329 // tell the cache about a route we saw being used
00330 {
00331   Path stub;
00332   if(pre_noticeRouteUsed(p, stub, t, who_from) == 0)
00333     return;
00334 
00335   int prefix_len = 0;
00336 
00337 #ifdef DSR_CACHE_STATS
00338   Path *p0 = secondary_cache->addRoute(stub, prefix_len);
00339   checkRoute(p0, ACTION_NOTICE_ROUTE, prefix_len);
00340 #else
00341   (void) secondary_cache->addRoute(stub, prefix_len);
00342 #endif
00343 }
00344 
00345 bool
00346 MobiCache::findRoute(ID dest, Path& route, int for_me)
00347 // if there is a cached path from us to dest returns true and fills in
00348 // the route accordingly. returns false otherwise
00349 // if for_me, then we assume that the node really wants to keep 
00350 // the returned route so it will be promoted to primary storage if not there
00351 // already
00352 {
00353   Path path;
00354   int min_index = -1;
00355   int min_length = MAX_SR_LEN + 1;
00356   int min_cache = 0;        // 2 == primary, 1 = secondary
00357   int index;
00358   int len;
00359 
00360   assert(!(net_id == invalid_addr));
00361 
00362   index = 0;
00363   while (secondary_cache->searchRoute(dest, len, path, index))
00364     {
00365       if (len < min_length)
00366     {
00367       min_index = index;
00368       min_cache = 1;
00369       min_length = len;
00370       route = path;
00371     }
00372       index++;
00373     }
00374 
00375   if (min_cache) 
00376     {
00377       route.setLength(min_length + 1);
00378       if (verbose_debug)
00379     trace("SRC %.9f _%s_ $hit for %s in %s %s",
00380           Scheduler::instance().clock(), net_id.dump(),
00381           dest.dump(), min_cache == 1 ? "secondary" : "primary",
00382           route.dump());    
00383 #ifdef DSR_CACHE_STATS
00384       int bad = checkRoute_logall(&route, ACTION_FIND_ROUTE, 0);      
00385       stat.route_find_count += 1;
00386       if (for_me) stat.route_find_for_me += 1;
00387       stat.route_find_bad_count += bad ? 1 : 0;
00388       stat.subroute_find_count += route.length() - 1;
00389       stat.subroute_find_bad_count += bad;
00390 #endif
00391       return true;
00392     }
00393   else
00394     {
00395       if (verbose_debug)
00396         trace("SRC %.9f _%s_ find-route [%d] %s->%s miss %d %.9f",
00397               Scheduler::instance().clock(), net_id.dump(),
00398               0, net_id.dump(), dest.dump(), 0, 0.0);
00399 #ifdef DSR_CACHE_STATS
00400       stat.route_find_count += 1;
00401       if (for_me) stat.route_find_for_me += 1;
00402       stat.route_find_miss_count += 1;
00403 #endif
00404       return false;
00405     }
00406 }
00407 
00408 /*===========================================================================
00409   class Cache routines
00410 ---------------------------------------------------------------------------*/
00411 
00412 Cache::Cache(char *name, int size, MobiCache *rtcache)
00413 {
00414   this->name = name;
00415   this->size = size;
00416   cache = new Path[size];
00417   routecache = rtcache;
00418   victim_ptr = 0;
00419 }
00420 
00421 Cache::~Cache() 
00422 {
00423   delete[] cache;
00424 }
00425 
00426 bool 
00427 Cache::searchRoute(const ID& dest, int& i, Path &path, int &index)
00428   // look for dest in cache, starting at index, 
00429   //if found, return true with path s.t. cache[index] == path && path[i] == dest
00430 {
00431   for (; index < size; index++)
00432     for (int n = 0 ; n < cache[index].length(); n++)
00433       if (cache[index][n] == dest) 
00434     {
00435       i = n;
00436       path = cache[index];
00437       return true;
00438     }
00439   return false;
00440 }
00441 
00442 Path*
00443 Cache::addRoute(Path & path, int &common_prefix_len)
00444 {
00445   int index, m, n;
00446   int victim;
00447 
00448   // see if this route is already in the cache
00449   for (index = 0 ; index < size ; index++)
00450     { // for all paths in the cache
00451       for (n = 0 ; n < cache[index].length() ; n ++)
00452     { // for all nodes in the path
00453       if (n >= path.length()) break;
00454       if (cache[index][n] != path[n]) break;
00455     }
00456       if (n == cache[index].length()) 
00457     { // new rt completely contains cache[index] (or cache[index] is empty)
00458           common_prefix_len = n;
00459           for ( ; n < path.length() ; n++)
00460             cache[index].appendToPath(path[n]);
00461       if (verbose_debug)
00462         routecache->trace("SRC %.9f _%s_ %s suffix-rule (len %d/%d) %s",
00463           Scheduler::instance().clock(), routecache->net_id.dump(),
00464               name, n, path.length(), path.dump()); 
00465       goto done;
00466     }
00467       else if (n == path.length())
00468     { // new route already contained in the cache
00469           common_prefix_len = n;
00470       if (verbose_debug)
00471         routecache->trace("SRC %.9f _%s_ %s prefix-rule (len %d/%d) %s",
00472           Scheduler::instance().clock(), routecache->net_id.dump(),
00473           name, n, cache[index].length(), cache[index].dump()); 
00474       goto done;
00475     }
00476       else 
00477     { // keep looking at the rest of the cache 
00478     }
00479     } 
00480 
00481   // there are some new goodies in the new route
00482   victim = pickVictim();
00483   if(verbose_debug) {
00484     routecache->trace("SRC %.9f _%s_ %s evicting %s",
00485               Scheduler::instance().clock(), routecache->net_id.dump(),
00486               name, cache[victim].dump());  
00487     routecache->trace("SRC %.9f _%s_ while adding %s",
00488               Scheduler::instance().clock(), routecache->net_id.dump(),
00489               path.dump()); 
00490   }
00491   cache[victim].reset();
00492   CopyIntoPath(cache[victim], path, 0, path.length() - 1);
00493   common_prefix_len = 0;
00494   index = victim; // remember which cache line we stuck the path into
00495 
00496 done:
00497 
00498 #ifdef DEBUG
00499   {
00500     Path &p = path;
00501     int c;
00502     char buf[1000];
00503     char *ptr = buf;
00504     ptr += sprintf(buf,"Sdebug %.9f _%s_ adding ", 
00505            Scheduler::instance().clock(), routecache->net_id.dump());
00506     for (c = 0 ; c < p.length(); c++)
00507       ptr += sprintf(ptr,"%s [%d %.9f] ",p[c].dump(), p[c].link_type, p[c].t);
00508     routecache->trace(buf);
00509   }
00510 #endif //DEBUG
00511 
00512   // freshen all the timestamps on the links in the cache
00513   for (m = 0 ; m < size ; m++)
00514     { // for all paths in the cache
00515 
00516 #ifdef DEBUG
00517   {
00518     if (cache[m].length() == 0) continue;
00519 
00520     Path &p = cache[m];
00521     int c;
00522     char buf[1000];
00523     char *ptr = buf;
00524     ptr += sprintf(buf,"Sdebug %.9f _%s_ checking ", 
00525            Scheduler::instance().clock(), routecache->net_id.dump());
00526     for (c = 0 ; c < p.length(); c++)
00527       ptr += sprintf(ptr,"%s [%d %.9f] ",p[c].dump(), p[c].link_type, p[c].t);
00528     routecache->trace(buf);
00529   }
00530 #endif //DEBUG
00531       
00532       for (n = 0 ; n < cache[m].length() - 1 ; n ++)
00533     { // for all nodes in the path
00534       if (n >= path.length() - 1) break;
00535       if (cache[m][n] != path[n]) break;
00536       if (cache[m][n+1] == path[n+1])
00537         { // freshen the timestamps and type of the link          
00538 
00539 #ifdef DEBUG
00540 routecache->trace("Sdebug %.9f _%s_ freshening %s->%s to %d %.9f",
00541           Scheduler::instance().clock(), routecache->net_id.dump(),
00542           path[n].dump(), path[n+1].dump(), path[n].link_type,
00543           path[n].t);
00544 #endif //DEBUG
00545 
00546           cache[m][n].t = path[n].t;
00547           cache[m][n].link_type = path[n].link_type;
00548           /* NOTE: we don't check to see if we're turning a TESTED
00549          into an UNTESTED link.  Last change made rules -dam 5/19/98 */
00550         }
00551     }
00552     }
00553   return &cache[index];
00554 }
00555 
00556 
00557 void
00558 Cache::noticeDeadLink(const ID&from, const ID& to)
00559   // the link from->to isn't working anymore, purge routes containing
00560   // it from the cache
00561 {  
00562   for (int p = 0 ; p < size ; p++)
00563     { // for all paths in the cache
00564       for (int n = 0 ; n < (cache[p].length()-1) ; n ++)
00565     { // for all nodes in the path
00566       if (cache[p][n] == from && cache[p][n+1] == to)
00567         {
00568           if(verbose_debug)
00569         routecache->trace("SRC %.9f _%s_ %s truncating %s %s",
00570                                   Scheduler::instance().clock(),
00571                                   routecache->net_id.dump(),
00572                                   name, cache[p].dump(),
00573                                   cache[p].owner().dump());
00574 #ifdef DSR_CACHE_STATS
00575               routecache->checkRoute(&cache[p], ACTION_CHECK_CACHE, 0);
00576               routecache->checkRoute_logall(&cache[p], ACTION_DEAD_LINK, n);
00577 #endif        
00578           if (n == 0)
00579         cache[p].reset();        // kill the whole path
00580           else {
00581         cache[p].setLength(n+1); // truncate the path here
00582                 cache[p][n].log_stat = LS_UNLOGGED;
00583               }
00584 
00585           if(verbose_debug)
00586         routecache->trace("SRC %.9f _%s_ to %s %s",
00587               Scheduler::instance().clock(), routecache->net_id.dump(),
00588               cache[p].dump(), cache[p].owner().dump());
00589 
00590           break;
00591         } // end if this is a dead link
00592     } // end for all nodes
00593     } // end for all paths
00594   return;
00595 }
00596 
00597 int
00598 Cache::pickVictim(int exclude)
00599 // returns the index of a suitable victim in the cache
00600 // never return exclude as the victim, but rather spare their life
00601 {
00602   for(int c = 0; c < size ; c++)
00603     if (cache[c].length() == 0) return c;
00604   
00605   int victim = victim_ptr;
00606   while (victim == exclude)
00607     {
00608       victim_ptr = (victim_ptr+1 == size) ? 0 : victim_ptr+1;
00609       victim = victim_ptr;
00610     }
00611   victim_ptr = (victim_ptr+1 == size) ? 0 : victim_ptr+1;
00612 
00613 #ifdef DSR_CACHE_STATS
00614   routecache->checkRoute(&cache[victim], ACTION_CHECK_CACHE, 0);
00615   int bad = routecache->checkRoute_logall(&cache[victim], ACTION_EVICT, 0);
00616   routecache->trace("SRC %.9f _%s_ evicting %d %d %s",
00617                     Scheduler::instance().clock(), routecache->net_id.dump(),
00618                     cache[victim].length() - 1, bad, name);
00619 #endif
00620   return victim;
00621 }
00622 
00623 #ifdef DSR_CACHE_STATS
00624 
00625 /*
00626  * Called only for the once-per-second cache check.
00627  */
00628 void
00629 MobiCache::checkRoute(Path & p,
00630                       int & subroute_bad_count,
00631                       int & link_bad_count,
00632                       double & link_bad_time,
00633                       int & link_bad_tested,
00634                       int & link_good_tested,
00635               double & link_good_time)
00636 {
00637   int c;
00638   int flag = 0;
00639 
00640   if(p.length() == 0)
00641     return;
00642   assert(p.length() >= 2);
00643 
00644   for (c = 0; c < p.length() - 1; c++)
00645     {
00646       assert(LS_UNLOGGED == p[c].log_stat || LS_LOGGED == p[c].log_stat );
00647       if (God::instance()->hops(p[c].getNSAddr_t(), p[c+1].getNSAddr_t()) != 1)
00648     { // the link's dead
00649           if(p[c].log_stat == LS_UNLOGGED)
00650         {
00651           trace("SRC %.9f _%s_ check-cache [%d %d] %s->%s dead %d %.9f",
00652             Scheduler::instance().clock(), net_id.dump(),
00653             p.length(), c, p[c].dump(), p[c+1].dump(),
00654                     p[c].link_type, p[c].t);
00655           p[c].log_stat = LS_LOGGED;
00656         }
00657           if(flag == 0)
00658             {
00659               subroute_bad_count += p.length() - c - 1;
00660               flag = 1;
00661             }
00662           link_bad_count += 1;
00663           link_bad_time += Scheduler::instance().clock() - p[c].t;
00664           link_bad_tested += (p[c].link_type == LT_TESTED) ? 1 : 0;
00665     }
00666       else
00667         {
00668       
00669       link_good_time += Scheduler::instance().clock() - p[c].t;
00670       
00671           if(p[c].log_stat == LS_LOGGED)
00672             {
00673               trace("SRC %.9f _%s_ resurrected-link [%d %d] %s->%s dead %d %.9f",
00674                     Scheduler::instance().clock(), net_id.dump(),
00675                     p.length(), c, p[c].dump(), p[c+1].dump(),
00676                     p[c].link_type, p[c].t);
00677               p[c].log_stat = LS_UNLOGGED;
00678             }
00679           link_good_tested += (p[c].link_type == LT_TESTED) ? 1 : 0;
00680         }
00681     }
00682 }
00683 
00684 void
00685 MobiCache::checkRoute(Path *p, int action, int prefix_len)
00686 {
00687   int c;
00688   int subroute_bad_count = 0;
00689   int tested = 0;
00690 
00691   if(p->length() == 0)
00692     return;
00693   assert(p->length() >= 2);
00694 
00695   assert(action == ACTION_ADD_ROUTE ||
00696          action == ACTION_CHECK_CACHE ||
00697          action == ACTION_NOTICE_ROUTE);
00698 
00699   for (c = 0; c < p->length() - 1; c++)
00700     {
00701       if (God::instance()->hops((*p)[c].getNSAddr_t(),
00702                                 (*p)[c+1].getNSAddr_t()) != 1)
00703     { // the link's dead
00704           if((*p)[c].log_stat == LS_UNLOGGED)
00705             {
00706               trace("SRC %.9f _%s_ %s [%d %d] %s->%s dead %d %.9f",
00707                     Scheduler::instance().clock(), net_id.dump(),
00708                     action_name[action], p->length(), c,
00709                     (*p)[c].dump(), (*p)[c+1].dump(),
00710                     (*p)[c].link_type, (*p)[c].t);
00711 
00712               (*p)[c].log_stat = LS_LOGGED;
00713             }
00714 
00715           if(subroute_bad_count == 0)
00716             subroute_bad_count = p->length() - c - 1;
00717     }
00718       else
00719         {
00720           if((*p)[c].log_stat == LS_LOGGED)
00721             {
00722               trace("SRC %.9f _%s_ resurrected-link [%d %d] %s->%s dead %d %.9f",
00723                     Scheduler::instance().clock(), net_id.dump(),
00724                     p->length(), c, (*p)[c].dump(), (*p)[c+1].dump(),
00725                     (*p)[c].link_type, (*p)[c].t);
00726               (*p)[c].log_stat = LS_UNLOGGED;
00727             }
00728         }
00729       tested += (*p)[c].link_type == LT_TESTED ? 1 : 0;
00730     }
00731 
00732   /*
00733    * Add Route or Notice Route actually did something
00734    */
00735   if(prefix_len < p->length())
00736     {
00737       switch(action)
00738         {
00739         case ACTION_ADD_ROUTE:
00740           stat.route_add_count += 1;
00741           stat.route_add_bad_count += subroute_bad_count ? 1 : 0;
00742           stat.subroute_add_count += p->length() - prefix_len - 1;
00743           stat.subroute_add_bad_count += subroute_bad_count;
00744           stat.link_add_tested += tested;
00745           break;
00746 
00747         case ACTION_NOTICE_ROUTE:
00748           stat.route_notice_count += 1;
00749           stat.route_notice_bad_count += subroute_bad_count ? 1 : 0;
00750           stat.subroute_notice_count += p->length() - prefix_len - 1;
00751           stat.subroute_notice_bad_count += subroute_bad_count;
00752           stat.link_notice_tested += tested;
00753           break;
00754         }
00755     }
00756 }
00757 #endif /* DSR_CACHE_STATS */
00758 
00759 #endif /* DSR_SIMPLECACHE */

Generated on Tue Mar 6 16:47:51 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6