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

通讯编程

开发平台:

Visual C++

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