mobicache.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:24k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * mobicache.cc
  3.  * Copyright (C) 2000 by the University of Southern California
  4.  * $Id: mobicache.cc,v 1.7 2006/02/21 15:20:18 mahrenho Exp $
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License,
  8.  * version 2, as published by the Free Software Foundation.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  18.  *
  19.  *
  20.  * The copyright of this module includes the following
  21.  * linking-with-specific-other-licenses addition:
  22.  *
  23.  * In addition, as a special exception, the copyright holders of
  24.  * this module give you permission to combine (via static or
  25.  * dynamic linking) this module with free software programs or
  26.  * libraries that are released under the GNU LGPL and with code
  27.  * included in the standard release of ns-2 under the Apache 2.0
  28.  * license or under otherwise-compatible licenses with advertising
  29.  * requirements (or modified versions of such code, with unchanged
  30.  * license).  You may copy and distribute such a system following the
  31.  * terms of the GNU GPL for this module and the licenses of the
  32.  * other code concerned, provided that you include the source code of
  33.  * that other code when and as the GNU GPL requires distribution of
  34.  * source code.
  35.  *
  36.  * Note that people who make modified versions of this module
  37.  * are not obligated to grant this special exception for their
  38.  * modified versions; it is their choice whether to do so.  The GNU
  39.  * General Public License gives permission to release a modified
  40.  * version without this exception; this exception also makes it
  41.  * possible to release a modified version which carries forward this
  42.  * exception.
  43.  *
  44.  */
  45. //
  46. // Other copyrights might apply to parts of this software and are so
  47. // noted when applicable.
  48. //
  49. /* mobicache.cc
  50.    cache used in the mobicom 98 submission.  see the paper for a description
  51.    Ported from CMU/Monarch's code, appropriate copyright applies.  
  52. */
  53. //#ifdef DSR_MOBICACHE
  54. extern "C" {
  55. #include <stdio.h>
  56. #include <stdarg.h>
  57. }
  58. #undef DEBUG
  59. #include <god.h>
  60. #include "path.h"
  61. #include "routecache.h"
  62. #ifdef DSR_CACHE_STATS
  63. #include "cache_stats.h"
  64. #endif
  65. /* invariants
  66.    - no path contains an id more than once
  67.    - all paths start with the id of our node (MAC_id or net_id)
  68. */
  69. #define fout stdout
  70. static const int verbose = 0;
  71. static const int verbose_debug = 0;
  72. /*===============================================================
  73.   function selectors
  74. ----------------------------------------------------------------*/
  75. bool cache_ignore_hints = false;     // ignore all hints?
  76. bool cache_use_overheard_routes = true; 
  77. // if we are A, and we over hear a rt Z Y (X) W V U, do we add route
  78. // A X W V U to the cache?
  79. /*===============================================================
  80.   Class declaration
  81. ----------------------------------------------------------------*/
  82. class MobiCache;
  83. class Cache {
  84. friend class MobiCache;
  85. public:
  86.   Cache(char *name, int size, MobiCache *rtcache);
  87.   ~Cache();
  88.   int pickVictim(int exclude = -1);
  89.   // returns the index of a suitable victim in the cache
  90.   // will spare the life of exclude
  91.   bool searchRoute(const ID& dest, int& i, Path &path, int &index);
  92.   // look for dest in cache, starting at index, 
  93.   //if found, rtn true with path s.t. cache[index] == path && path[i] == dest
  94.   Path* addRoute(Path &route, int &prefix_len);
  95.   // rtns a pointer the path in the cache that we added
  96.   void noticeDeadLink(const ID&from, const ID& to);
  97.   // the link from->to isn't working anymore, purge routes containing
  98.   // it from the cache
  99. private:
  100.   Path *cache;
  101.   int size;
  102.   int victim_ptr; // next victim for eviction
  103.   MobiCache *routecache;
  104.   char *name;
  105. };
  106. ///////////////////////////////////////////////////////////////////////////
  107. class MobiCache : public RouteCache {
  108. friend class Cache;
  109. friend class MobiHandler;
  110. public:
  111.   MobiCache(const ID& MAC_id, const ID& net_id,int psize = 30,int ssize = 34 );
  112.   MobiCache();
  113.   ~MobiCache();
  114.   void noticeDeadLink(const ID&from, const ID& to, Time t);
  115.   // the link from->to isn't working anymore, purge routes containing
  116.   // it from the cache
  117.   void noticeRouteUsed(const Path& route, Time t,
  118.        const ID& who_from);
  119.   // tell the cache about a route we saw being used
  120.   void addRoute(const Path& route, Time t, const ID& who_from);
  121.   // add this route to the cache (presumably we did a route request
  122.   // to find this route and don't want to lose it)
  123.   bool findRoute(ID dest, Path& route, int for_use = 0);
  124.   // if there is a cached path from us to dest returns true and fills in
  125.   // the route accordingly. returns false otherwise
  126.   // if for_use, then we assume that the node really wants to keep 
  127.   // the returned route so it will be promoted to primary storage if not there
  128.   // already
  129.   int command(int argc, const char*const* argv);
  130. protected:
  131.   Cache *primary_cache;   /* routes that we are using, or that we have reason
  132.      to believe we really want to hold on to */
  133.   Cache *secondary_cache; /* routes we've learned via a speculative process
  134.      that might not pan out */
  135. #ifdef DSR_CACHE_STATS
  136.   void periodic_checkCache(void);
  137.   void checkRoute(Path *p, int action, int prefix_len);
  138.   void checkRoute(Path &p, int&, int&, double&, int&, int&, double &);
  139. #endif
  140. };
  141. RouteCache *
  142. makeRouteCache()
  143. {
  144.   return new MobiCache();
  145. }
  146. /*===============================================================
  147.   OTcl definition
  148. ----------------------------------------------------------------*/
  149. static class MobiCacheClass : public TclClass {
  150. public:
  151.         MobiCacheClass() : TclClass("MobiCache") {}
  152.         TclObject* create(int, const char*const*) {
  153.                 return (new MobiCache);
  154.         }
  155. } class_MobiCache;
  156. /*===============================================================
  157.  Constructors
  158. ----------------------------------------------------------------*/
  159. MobiCache::MobiCache(): RouteCache()
  160. {
  161.   primary_cache = new Cache("primary", 30, this);
  162.   secondary_cache = new Cache("secondary", 64, this);
  163.   //secondary_cache = new Cache("secondary", 10000, this);
  164.   assert(primary_cache != NULL && secondary_cache != NULL);
  165. #ifdef DSR_CACHE_STATS
  166. stat.reset();
  167. #endif
  168. }
  169. MobiCache::~MobiCache()
  170. {
  171.   delete primary_cache;
  172.   delete secondary_cache;
  173. }
  174. int
  175. MobiCache::command(int argc, const char*const* argv)
  176. {
  177.   if(argc == 2 && strcasecmp(argv[1], "startdsr") == 0)
  178.     { 
  179.       if (ID(1,::IP) == net_id) 
  180. trace("Sconfig %.5f using MOBICACHE", Scheduler::instance().clock());
  181.       // FALL-THROUGH
  182.     }
  183.   return RouteCache::command(argc, argv);
  184. }
  185. #ifdef DSR_CACHE_STATS
  186. void
  187. MobiCache::periodic_checkCache()
  188. {
  189.   int c;
  190.   int route_count = 0;
  191.   int route_bad_count = 0;
  192.   int subroute_count = 0;
  193.   int subroute_bad_count = 0;
  194.   int link_bad_count = 0;
  195.   double link_bad_time = 0.0;
  196.   int link_bad_tested = 0;
  197.   int link_good_tested = 0;
  198.   for(c = 0; c < primary_cache->size; c++)
  199.     {
  200.       int x = 0;
  201.       if (primary_cache->cache[c].length() == 0) continue;
  202.       checkRoute(primary_cache->cache[c],
  203.                  x,
  204.                  link_bad_count,
  205.                  link_bad_time,
  206.                  link_bad_tested,
  207.                  link_good_tested,
  208.  stat.link_good_time);
  209.       route_count += 1;
  210.       route_bad_count += x ? 1 : 0;
  211.       
  212.       subroute_count += primary_cache->cache[c].length() - 1;
  213.       subroute_bad_count += x;
  214.     }
  215.   for(c = 0; c < secondary_cache->size; c++)
  216.     {
  217.       int x = 0;
  218.       if (secondary_cache->cache[c].length() == 0) continue;
  219.       checkRoute(secondary_cache->cache[c],
  220.                  x,
  221.                  link_bad_count,
  222.                  link_bad_time,
  223.                  link_bad_tested,
  224.                  link_good_tested,
  225.  stat.link_good_time);
  226.       route_count += 1;
  227.       route_bad_count += x ? 1 : 0;
  228.       subroute_count += secondary_cache->cache[c].length() - 1;
  229.       subroute_bad_count += x;
  230.     }
  231.   // lifetime of good link is (total time) / (total num links - num bad links)
  232.   stat.link_good_time = stat.link_good_time / (subroute_count - link_bad_count);
  233.   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",
  234. Scheduler::instance().clock(), net_id.dump(),
  235.         route_count,
  236.         route_bad_count,
  237.         subroute_count,
  238.         subroute_bad_count,
  239.         link_bad_count,
  240.         link_bad_count ? link_bad_time/link_bad_count : 0.0,
  241.         link_bad_tested,
  242.         link_good_tested,
  243.         stat.route_add_count,
  244.         stat.route_add_bad_count,
  245.         stat.subroute_add_count,
  246.         stat.subroute_add_bad_count,
  247.         stat.link_add_tested,
  248.              
  249.         stat.route_notice_count,
  250.         stat.route_notice_bad_count,
  251.         stat.subroute_notice_count,
  252.         stat.subroute_notice_bad_count,
  253.         stat.link_notice_tested,
  254.              
  255.         stat.route_find_count,
  256. stat.route_find_for_me,
  257.         stat.route_find_bad_count,
  258.         stat.route_find_miss_count,
  259.         stat.subroute_find_count,
  260.         stat.subroute_find_bad_count,
  261. stat.link_good_time);
  262.   stat.reset();
  263. }
  264. #endif /* DSR_CACHE_STATS */
  265. /*===============================================================
  266.   member functions
  267. ----------------------------------------------------------------*/
  268. void
  269. MobiCache::addRoute(const Path& route, Time t, const ID& who_from)
  270. // add this route to the cache (presumably we did a route request
  271. // to find this route and don't want to lose it)
  272. // who_from is the id of the routes provider
  273. {
  274.   Path rt;
  275.   if(pre_addRoute(route, rt, t, who_from) == 0)
  276.     return;
  277.   // must call addRoute before checkRoute
  278.   int prefix_len = 0;
  279. #ifdef DSR_CACHE_STATS
  280.   Path *p = primary_cache->addRoute(rt, prefix_len);
  281.   checkRoute(p, ACTION_ADD_ROUTE, prefix_len);
  282. #else
  283.   (void) primary_cache->addRoute(rt, prefix_len);
  284. #endif
  285. }
  286. void
  287. MobiCache::noticeDeadLink(const ID&from, const ID& to, Time)
  288.   // the link from->to isn't working anymore, purge routes containing
  289.   // it from the cache
  290. {
  291.   if(verbose_debug)
  292.     trace("SRC %.9f _%s_ dead link %s->%s",
  293.   Scheduler::instance().clock(), net_id.dump(),
  294.   from.dump(), to.dump());
  295.   
  296.   primary_cache->noticeDeadLink(from, to);
  297.   secondary_cache->noticeDeadLink(from, to);
  298.   return;
  299. }
  300. void
  301. MobiCache::noticeRouteUsed(const Path& p, Time t, const ID& who_from)
  302. // tell the cache about a route we saw being used
  303. {
  304.   Path stub;
  305.   if(pre_noticeRouteUsed(p, stub, t, who_from) == 0)
  306.     return;
  307.   int prefix_len = 0;
  308. #ifdef DSR_CACHE_STATS
  309.   Path *p0 = secondary_cache->addRoute(stub, prefix_len);
  310.   checkRoute(p0, ACTION_NOTICE_ROUTE, prefix_len);
  311. #else
  312.   (void) secondary_cache->addRoute(stub, prefix_len);
  313. #endif
  314. }
  315. bool
  316. MobiCache::findRoute(ID dest, Path& route, int for_me)
  317. // if there is a cached path from us to dest returns true and fills in
  318. // the route accordingly. returns false otherwise
  319. // if for_me, then we assume that the node really wants to keep 
  320. // the returned route so it will be promoted to primary storage if not there
  321. // already
  322. {
  323.   Path path;
  324.   int min_index = -1;
  325.   int min_length = MAX_SR_LEN + 1;
  326.   int min_cache = 0; // 2 == primary, 1 = secondary
  327.   int index;
  328.   int len;
  329.   assert(!(net_id == invalid_addr));
  330.   index = 0;
  331.   while (primary_cache->searchRoute(dest, len, path, index))
  332.     {
  333.       min_cache = 2;
  334.       if (len < min_length)
  335. {
  336.   min_length = len;
  337.   route = path;
  338. }
  339.       index++;
  340.     }
  341.   
  342.   index = 0;
  343.   while (secondary_cache->searchRoute(dest, len, path, index))
  344.     {
  345.       if (len < min_length)
  346. {
  347.   min_index = index;
  348.   min_cache = 1;
  349.   min_length = len;
  350.   route = path;
  351. }
  352.       index++;
  353.     }
  354.   if (min_cache == 1 && for_me)
  355.     { // promote the found route to the primary cache
  356.       int prefix_len;
  357.  
  358.       primary_cache->addRoute(secondary_cache->cache[min_index], prefix_len);
  359.       // no need to run checkRoute over the Path* returned from
  360.       // addRoute() because whatever was added was already in
  361.       // the cache.
  362.       //   prefix_len = 0
  363.       //        - victim was selected in primary cache
  364.       //        - data should be "silently" migrated from primary to the
  365.       //          secondary cache
  366.       //   prefix_len > 0
  367.       //        - there were two copies of the first prefix_len routes
  368.       //          in the cache, but after the migration, there will be
  369.       //          only one.
  370.       //        - log the first prefix_len bytes of the secondary cache
  371.       //          entry as "evicted"
  372.       if(prefix_len > 0)
  373.         {
  374.           secondary_cache->cache[min_index].setLength(prefix_len);
  375. #ifdef DSR_CACHE_STATS
  376.           checkRoute_logall(&secondary_cache->cache[min_index], 
  377.                             ACTION_EVICT, 0);
  378. #endif
  379.         }
  380.       secondary_cache->cache[min_index].setLength(0); // kill route
  381.     }
  382.   if (min_cache) 
  383.     {
  384.       route.setLength(min_length + 1);
  385.       if (verbose_debug)
  386. trace("SRC %.9f _%s_ $hit for %s in %s %s",
  387.       Scheduler::instance().clock(), net_id.dump(),
  388.       dest.dump(), min_cache == 1 ? "secondary" : "primary",
  389.       route.dump());
  390. #ifdef DSR_CACHE_STATS
  391.       int bad = checkRoute_logall(&route, ACTION_FIND_ROUTE, 0);      
  392.       stat.route_find_count += 1;
  393.       if (for_me) stat.route_find_for_me += 1;
  394.       stat.route_find_bad_count += bad ? 1 : 0;
  395.       stat.subroute_find_count += route.length() - 1;
  396.       stat.subroute_find_bad_count += bad;
  397. #endif
  398.       return true;
  399.     }
  400.   else
  401.     {
  402.       if (verbose_debug)
  403.         trace("SRC %.9f _%s_ find-route [%d] %s->%s miss %d %.9f",
  404.               Scheduler::instance().clock(), net_id.dump(),
  405.               0, net_id.dump(), dest.dump(), 0, 0.0);
  406. #ifdef DSR_CACHE_STATS
  407.       stat.route_find_count += 1;
  408.       if (for_me) stat.route_find_for_me += 1;
  409.       stat.route_find_miss_count += 1;
  410. #endif
  411.       return false;
  412.     }
  413. }
  414. /*===========================================================================
  415.   class Cache routines
  416. ---------------------------------------------------------------------------*/
  417. Cache::Cache(char *name, int size, MobiCache *rtcache)
  418. {
  419.   this->name = name;
  420.   this->size = size;
  421.   cache = new Path[size];
  422.   routecache = rtcache;
  423.   victim_ptr = 0;
  424. }
  425. Cache::~Cache() 
  426. {
  427.   delete[] cache;
  428. }
  429. bool 
  430. Cache::searchRoute(const ID& dest, int& i, Path &path, int &index)
  431.   // look for dest in cache, starting at index, 
  432.   //if found, return true with path s.t. cache[index] == path && path[i] == dest
  433. {
  434.   for (; index < size; index++)
  435.     for (int n = 0 ; n < cache[index].length(); n++)
  436.       if (cache[index][n] == dest) 
  437. {
  438.   i = n;
  439.   path = cache[index];
  440.   return true;
  441. }
  442.   return false;
  443. }
  444. Path*
  445. Cache::addRoute(Path & path, int &common_prefix_len)
  446. {
  447.   int index, m, n;
  448.   int victim;
  449.   // see if this route is already in the cache
  450.   for (index = 0 ; index < size ; index++)
  451.     { // for all paths in the cache
  452.       for (n = 0 ; n < cache[index].length() ; n ++)
  453. { // for all nodes in the path
  454.   if (n >= path.length()) break;
  455.   if (cache[index][n] != path[n]) break;
  456. }
  457.       if (n == cache[index].length()) 
  458. { // new rt completely contains cache[index] (or cache[index] is empty)
  459.           common_prefix_len = n;
  460.           for ( ; n < path.length() ; n++)
  461.             cache[index].appendToPath(path[n]);
  462.   if (verbose_debug)
  463.     routecache->trace("SRC %.9f _%s_ %s suffix-rule (len %d/%d) %s",
  464.           Scheduler::instance().clock(), routecache->net_id.dump(),
  465.               name, n, path.length(), path.dump());
  466.   goto done;
  467. }
  468.       else if (n == path.length())
  469. { // new route already contained in the cache
  470.           common_prefix_len = n;
  471.   if (verbose_debug)
  472.     routecache->trace("SRC %.9f _%s_ %s prefix-rule (len %d/%d) %s",
  473.           Scheduler::instance().clock(), routecache->net_id.dump(),
  474.       name, n, cache[index].length(), cache[index].dump());
  475.   goto done;
  476. }
  477.       else 
  478. { // keep looking at the rest of the cache 
  479. }
  480.     } 
  481.   // there are some new goodies in the new route
  482.   victim = pickVictim();
  483.   if(verbose_debug) {
  484.     routecache->trace("SRC %.9f _%s_ %s evicting %s",
  485.       Scheduler::instance().clock(), routecache->net_id.dump(),
  486.       name, cache[victim].dump());
  487.     routecache->trace("SRC %.9f _%s_ while adding %s",
  488.       Scheduler::instance().clock(), routecache->net_id.dump(),
  489.       path.dump());
  490.   }
  491.   cache[victim].reset();
  492.   CopyIntoPath(cache[victim], path, 0, path.length() - 1);
  493.   common_prefix_len = 0;
  494.   index = victim; // remember which cache line we stuck the path into
  495. done:
  496. #ifdef DEBUG
  497.   {
  498.     Path &p = path;
  499.     int c;
  500.     char buf[1000];
  501.     char *ptr = buf;
  502.     ptr += sprintf(buf,"Sdebug %.9f _%s_ adding ", 
  503.    Scheduler::instance().clock(), routecache->net_id.dump());
  504.     for (c = 0 ; c < p.length(); c++)
  505.       ptr += sprintf(ptr,"%s [%d %.9f] ",p[c].dump(), p[c].link_type, p[c].t);
  506.     routecache->trace(buf);
  507.   }
  508. #endif //DEBUG
  509.   // freshen all the timestamps on the links in the cache
  510.   for (m = 0 ; m < size ; m++)
  511.     { // for all paths in the cache
  512. #ifdef DEBUG
  513.   {
  514.     if (cache[m].length() == 0) continue;
  515.     Path &p = cache[m];
  516.     int c;
  517.     char buf[1000];
  518.     char *ptr = buf;
  519.     ptr += sprintf(buf,"Sdebug %.9f _%s_ checking ", 
  520.    Scheduler::instance().clock(), routecache->net_id.dump());
  521.     for (c = 0 ; c < p.length(); c++)
  522.       ptr += sprintf(ptr,"%s [%d %.9f] ",p[c].dump(), p[c].link_type, p[c].t);
  523.     routecache->trace(buf);
  524.   }
  525. #endif //DEBUG
  526.       
  527.       for (n = 0 ; n < cache[m].length() - 1 ; n ++)
  528. { // for all nodes in the path
  529.   if (n >= path.length() - 1) break;
  530.   if (cache[m][n] != path[n]) break;
  531.   if (cache[m][n+1] == path[n+1])
  532.     { // freshen the timestamps and type of the link       
  533. #ifdef DEBUG
  534. routecache->trace("Sdebug %.9f _%s_ freshening %s->%s to %d %.9f",
  535.   Scheduler::instance().clock(), routecache->net_id.dump(),
  536.   path[n].dump(), path[n+1].dump(), path[n].link_type,
  537.   path[n].t);
  538. #endif //DEBUG
  539.       cache[m][n].t = path[n].t;
  540.       cache[m][n].link_type = path[n].link_type;
  541.       /* NOTE: we don't check to see if we're turning a TESTED
  542.  into an UNTESTED link.  Last change made rules -dam 5/19/98 */
  543.     }
  544. }
  545.     }
  546.   return &cache[index];
  547. }
  548. void
  549. Cache::noticeDeadLink(const ID&from, const ID& to)
  550.   // the link from->to isn't working anymore, purge routes containing
  551.   // it from the cache
  552. {  
  553.   for (int p = 0 ; p < size ; p++)
  554.     { // for all paths in the cache
  555.       for (int n = 0 ; n < (cache[p].length()-1) ; n ++)
  556. { // for all nodes in the path
  557.   if (cache[p][n] == from && cache[p][n+1] == to)
  558.     {
  559.       if(verbose_debug)
  560. routecache->trace("SRC %.9f _%s_ %s truncating %s %s",
  561.                                   Scheduler::instance().clock(),
  562.                                   routecache->net_id.dump(),
  563.                                   name, cache[p].dump(),
  564.                                   cache[p].owner().dump());
  565. #ifdef DSR_CACHE_STATS
  566.               routecache->checkRoute(&cache[p], ACTION_CHECK_CACHE, 0);
  567.               routecache->checkRoute_logall(&cache[p], ACTION_DEAD_LINK, n);
  568. #endif       
  569.       if (n == 0)
  570. cache[p].reset();        // kill the whole path
  571.       else {
  572. cache[p].setLength(n+1); // truncate the path here
  573.                 cache[p][n].log_stat = LS_UNLOGGED;
  574.               }
  575.       if(verbose_debug)
  576. routecache->trace("SRC %.9f _%s_ to %s %s",
  577.       Scheduler::instance().clock(), routecache->net_id.dump(),
  578.       cache[p].dump(), cache[p].owner().dump());
  579.       break;
  580.     } // end if this is a dead link
  581. } // end for all nodes
  582.     } // end for all paths
  583.   return;
  584. }
  585. int
  586. Cache::pickVictim(int exclude)
  587. // returns the index of a suitable victim in the cache
  588. // never return exclude as the victim, but rather spare their life
  589. {
  590.   for(int c = 0; c < size ; c++)
  591.     if (cache[c].length() == 0) return c;
  592.   
  593.   int victim = victim_ptr;
  594.   while (victim == exclude)
  595.     {
  596.       victim_ptr = (victim_ptr+1 == size) ? 0 : victim_ptr+1;
  597.       victim = victim_ptr;
  598.     }
  599.   victim_ptr = (victim_ptr+1 == size) ? 0 : victim_ptr+1;
  600. #ifdef DSR_CACHE_STATS
  601.   routecache->checkRoute(&cache[victim], ACTION_CHECK_CACHE, 0);
  602.   int bad = routecache->checkRoute_logall(&cache[victim], ACTION_EVICT, 0);
  603.   routecache->trace("SRC %.9f _%s_ evicting %d %d %s",
  604.                     Scheduler::instance().clock(), routecache->net_id.dump(),
  605.                     cache[victim].length() - 1, bad, name);
  606. #endif
  607.   return victim;
  608. }
  609. #ifdef DSR_CACHE_STATS
  610. /*
  611.  * Called only for the once-per-second cache check.
  612.  */
  613. void
  614. MobiCache::checkRoute(Path & p,
  615.                       int & subroute_bad_count,
  616.                       int & link_bad_count,
  617.                       double & link_bad_time,
  618.                       int & link_bad_tested,
  619.                       int & link_good_tested,
  620.       double & link_good_time)
  621. {
  622.   int c;
  623.   int flag = 0;
  624.   if(p.length() == 0)
  625.     return;
  626.   assert(p.length() >= 2);
  627.   for (c = 0; c < p.length() - 1; c++)
  628.     {
  629.       assert(LS_UNLOGGED == p[c].log_stat || LS_LOGGED == p[c].log_stat );
  630.       if (God::instance()->hops(p[c].getNSAddr_t(), p[c+1].getNSAddr_t()) != 1)
  631. { // the link's dead
  632.           if(p[c].log_stat == LS_UNLOGGED)
  633.     {
  634.       trace("SRC %.9f _%s_ check-cache [%d %d] %s->%s dead %d %.9f",
  635.     Scheduler::instance().clock(), net_id.dump(),
  636.     p.length(), c, p[c].dump(), p[c+1].dump(),
  637.                     p[c].link_type, p[c].t);
  638.       p[c].log_stat = LS_LOGGED;
  639.     }
  640.           if(flag == 0)
  641.             {
  642.               subroute_bad_count += p.length() - c - 1;
  643.               flag = 1;
  644.             }
  645.           link_bad_count += 1;
  646.           link_bad_time += Scheduler::instance().clock() - p[c].t;
  647.           link_bad_tested += (p[c].link_type == LT_TESTED) ? 1 : 0;
  648. }
  649.       else
  650.         {
  651.   
  652.   link_good_time += Scheduler::instance().clock() - p[c].t;
  653.   
  654.           if(p[c].log_stat == LS_LOGGED)
  655.             {
  656.               trace("SRC %.9f _%s_ resurrected-link [%d %d] %s->%s dead %d %.9f",
  657.                     Scheduler::instance().clock(), net_id.dump(),
  658.                     p.length(), c, p[c].dump(), p[c+1].dump(),
  659.                     p[c].link_type, p[c].t);
  660.               p[c].log_stat = LS_UNLOGGED;
  661.             }
  662.           link_good_tested += (p[c].link_type == LT_TESTED) ? 1 : 0;
  663.         }
  664.     }
  665. }
  666. void
  667. MobiCache::checkRoute(Path *p, int action, int prefix_len)
  668. {
  669.   int c;
  670.   int subroute_bad_count = 0;
  671.   int tested = 0;
  672.   if(p->length() == 0)
  673.     return;
  674.   assert(p->length() >= 2);
  675.   assert(action == ACTION_ADD_ROUTE ||
  676.          action == ACTION_CHECK_CACHE ||
  677.          action == ACTION_NOTICE_ROUTE);
  678.   for (c = 0; c < p->length() - 1; c++)
  679.     {
  680.       if (God::instance()->hops((*p)[c].getNSAddr_t(),
  681.                                 (*p)[c+1].getNSAddr_t()) != 1)
  682. { // the link's dead
  683.           if((*p)[c].log_stat == LS_UNLOGGED)
  684.             {
  685.               trace("SRC %.9f _%s_ %s [%d %d] %s->%s dead %d %.9f",
  686.                     Scheduler::instance().clock(), net_id.dump(),
  687.                     action_name[action], p->length(), c,
  688.                     (*p)[c].dump(), (*p)[c+1].dump(),
  689.                     (*p)[c].link_type, (*p)[c].t);
  690.               (*p)[c].log_stat = LS_LOGGED;
  691.             }
  692.           if(subroute_bad_count == 0)
  693.             subroute_bad_count = p->length() - c - 1;
  694. }
  695.       else
  696.         {
  697.           if((*p)[c].log_stat == LS_LOGGED)
  698.             {
  699.               trace("SRC %.9f _%s_ resurrected-link [%d %d] %s->%s dead %d %.9f",
  700.                     Scheduler::instance().clock(), net_id.dump(),
  701.                     p->length(), c, (*p)[c].dump(), (*p)[c+1].dump(),
  702.                     (*p)[c].link_type, (*p)[c].t);
  703.               (*p)[c].log_stat = LS_UNLOGGED;
  704.             }
  705.         }
  706.       tested += (*p)[c].link_type == LT_TESTED ? 1 : 0;
  707.     }
  708.   /*
  709.    * Add Route or Notice Route actually did something
  710.    */
  711.   if(prefix_len < p->length())
  712.     {
  713.       switch(action)
  714.         {
  715.         case ACTION_ADD_ROUTE:
  716.           stat.route_add_count += 1;
  717.           stat.route_add_bad_count += subroute_bad_count ? 1 : 0;
  718.           stat.subroute_add_count += p->length() - prefix_len - 1;
  719.           stat.subroute_add_bad_count += subroute_bad_count;
  720.           stat.link_add_tested += tested;
  721.           break;
  722.         case ACTION_NOTICE_ROUTE:
  723.           stat.route_notice_count += 1;
  724.           stat.route_notice_bad_count += subroute_bad_count ? 1 : 0;
  725.           stat.subroute_notice_count += p->length() - prefix_len - 1;
  726.           stat.subroute_notice_bad_count += subroute_bad_count;
  727.           stat.link_notice_tested += tested;
  728.           break;
  729.         }
  730.     }
  731. }
  732. #endif /* DSR_CACHE_STATS */
  733. //#endif /* DSR_MOBICACHE */