delay_pools.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:20k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: delay_pools.c,v 1.7.2.1 1999/02/14 08:35:01 wessels Exp $
  3.  *
  4.  * DEBUG: section 77    Delay Pools
  5.  * AUTHOR: David Luyer <luyer@ucs.uwa.edu.au>
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "config.h"
  35. #if DELAY_POOLS
  36. #include "squid.h"
  37. struct _class1DelayPool {
  38.     int aggregate;
  39. };
  40. struct _class2DelayPool {
  41.     int aggregate;
  42.     /* OK: -1 is terminator.  individual[255] is always host 255. */
  43.     /* 255 entries + 1 terminator byte */
  44.     unsigned char individual_map[256];
  45.     unsigned char individual_255_used;
  46.     /* 256 entries */
  47.     int individual[256];
  48. };
  49. struct _class3DelayPool {
  50.     int aggregate;
  51.     /* OK: -1 is terminator.  network[255] is always host 255. */
  52.     /* 255 entries + 1 terminator byte */
  53.     unsigned char network_map[256];
  54.     unsigned char network_255_used;
  55.     /* 256 entries */
  56.     int network[256];
  57.     /* 256 sets of (255 entries + 1 terminator byte) */
  58.     unsigned char individual_map[256][256];
  59.     /* Pack this into one bit per net */
  60.     unsigned char individual_255_used[32];
  61.     /* largest entry = (255<<8)+255 = 65535 */
  62.     int individual[65536];
  63. };
  64. typedef struct _class1DelayPool class1DelayPool;
  65. typedef struct _class2DelayPool class2DelayPool;
  66. typedef struct _class3DelayPool class3DelayPool;
  67. union _delayPool {
  68.     class1DelayPool *class1;
  69.     class2DelayPool *class2;
  70.     class3DelayPool *class3;
  71. };
  72. typedef union _delayPool delayPool;
  73. static delayPool *delay_data = NULL;
  74. static fd_set delay_no_delay;
  75. static time_t delay_pools_last_update = 0;
  76. static OBJH delayPoolStats;
  77. void
  78. delayPoolsInit(void)
  79. {
  80.     delay_pools_last_update = getCurrentTime();
  81.     FD_ZERO(&delay_no_delay);
  82.     cachemgrRegister("delay", "Delay Pool Levels", delayPoolStats, 0, 1);
  83. }
  84. void
  85. delayInitDelayData(unsigned short pools)
  86. {
  87.     if (pools) {
  88. delay_data = xcalloc(pools, sizeof(delayPool));
  89. eventAdd("delayPoolsUpdate", delayPoolsUpdate, NULL, 1.0, 1);
  90.     }
  91. }
  92. void
  93. delayFreeDelayData()
  94. {
  95.     safe_free(delay_data);
  96. }
  97. void
  98. delayCreateDelayPool(unsigned short pool, u_char class)
  99. {
  100.     switch (class) {
  101.     case 1:
  102. delay_data[pool].class1 = xmalloc(sizeof(class1DelayPool));
  103. break;
  104.     case 2:
  105. delay_data[pool].class2 = xmalloc(sizeof(class2DelayPool));
  106. break;
  107.     case 3:
  108. delay_data[pool].class3 = xmalloc(sizeof(class3DelayPool));
  109. break;
  110.     default:
  111. assert(0);
  112.     }
  113. }
  114. void
  115. delayInitDelayPool(unsigned short pool, u_char class, delaySpecSet * rates)
  116. {
  117.     /* delaySetSpec may be pointer to partial structure so MUST pass by
  118.      * reference.
  119.      */
  120.     switch (class) {
  121.     case 1:
  122. delay_data[pool].class1->aggregate = (rates->aggregate.max_bytes *
  123.     Config.Delay.initial) / 100;
  124. break;
  125.     case 2:
  126. delay_data[pool].class2->aggregate = (rates->aggregate.max_bytes *
  127.     Config.Delay.initial) / 100;
  128. delay_data[pool].class2->individual_map[0] = 255;
  129. delay_data[pool].class2->individual_255_used = 0;
  130. break;
  131.     case 3:
  132. delay_data[pool].class3->aggregate = (rates->aggregate.max_bytes *
  133.     Config.Delay.initial) / 100;
  134. delay_data[pool].class3->network_map[0] = 255;
  135. delay_data[pool].class3->network_255_used = 0;
  136. memset(&delay_data[pool].class3->individual_255_used, '',
  137.     sizeof(delay_data[pool].class3->individual_255_used));
  138. break;
  139.     default:
  140. assert(0);
  141.     }
  142. }
  143. void
  144. delayFreeDelayPool(unsigned short pool)
  145. {
  146.     /* this is a union - and all free() cares about is the pointer location */
  147.     safe_free(delay_data[pool].class1);
  148. }
  149. void
  150. delaySetNoDelay(int fd)
  151. {
  152.     FD_SET(fd, &delay_no_delay);
  153. }
  154. void
  155. delayClearNoDelay(int fd)
  156. {
  157.     FD_CLR(fd, &delay_no_delay);
  158. }
  159. int
  160. delayIsNoDelay(int fd)
  161. {
  162.     return FD_ISSET(fd, &delay_no_delay);
  163. }
  164. static delay_id
  165. delayId(unsigned short pool, unsigned short position)
  166. {
  167.     return (pool << 16) | position;
  168. }
  169. delay_id
  170. delayClient(request_t * r)
  171. {
  172.     aclCheck_t ch;
  173.     int i;
  174.     int j;
  175.     unsigned int host;
  176.     unsigned short pool, position;
  177.     unsigned char class, net;
  178.     memset(&ch, '', sizeof(ch));
  179.     ch.src_addr = r->client_addr;
  180.     ch.my_addr = r->my_addr;
  181.     ch.request = r;
  182.     for (pool = 0; pool < Config.Delay.pools; pool++) {
  183. if (aclCheckFast(Config.Delay.access[pool], &ch))
  184.     break;
  185.     }
  186.     if (pool == Config.Delay.pools)
  187. return delayId(0, 0);
  188.     class = Config.Delay.class[pool];
  189.     if (class == 0)
  190. return delayId(0, 0);
  191.     if (class == 1)
  192. return delayId(pool + 1, 0);
  193.     if (class == 2) {
  194. host = ntohl(ch.src_addr.s_addr) & 0xff;
  195. if (host == 255) {
  196.     if (!delay_data[pool].class2->individual_255_used) {
  197. delay_data[pool].class2->individual_255_used = 1;
  198. delay_data[pool].class2->individual[255] =
  199.     (Config.Delay.rates[pool]->individual.max_bytes *
  200.     Config.Delay.initial) / 100;
  201.     }
  202.     return delayId(pool + 1, 255);
  203. }
  204. for (i = 0;; i++) {
  205.     if (delay_data[pool].class2->individual_map[i] == host)
  206. break;
  207.     if (delay_data[pool].class2->individual_map[i] == 255) {
  208. delay_data[pool].class2->individual_map[i] = host;
  209. delay_data[pool].class2->individual_map[i + 1] = 255;
  210. delay_data[pool].class2->individual[i] =
  211.     (Config.Delay.rates[pool]->individual.max_bytes *
  212.     Config.Delay.initial) / 100;
  213. break;
  214.     }
  215. }
  216. return delayId(pool + 1, i);
  217.     }
  218.     /* class == 3 */
  219.     host = ntohl(ch.src_addr.s_addr) & 0xffff;
  220.     net = host >> 8;
  221.     host &= 0xff;
  222.     if (net == 255) {
  223. i = 255;
  224. if (!delay_data[pool].class3->network_255_used) {
  225.     delay_data[pool].class3->network_255_used = 1;
  226.     delay_data[pool].class3->network[255] =
  227. (Config.Delay.rates[pool]->network.max_bytes *
  228. Config.Delay.initial) / 100;
  229. }
  230.     } else {
  231. for (i = 0;; i++) {
  232.     if (delay_data[pool].class3->network_map[i] == net)
  233. break;
  234.     if (delay_data[pool].class3->network_map[i] == 255) {
  235. delay_data[pool].class3->network_map[i] = net;
  236. delay_data[pool].class3->individual_map[i][0] = 255;
  237. delay_data[pool].class3->network_map[i + 1] = 255;
  238. delay_data[pool].class3->network[i] =
  239.     (Config.Delay.rates[pool]->network.max_bytes *
  240.     Config.Delay.initial) / 100;
  241. break;
  242.     }
  243. }
  244.     }
  245.     position = i << 8;
  246.     if (host == 255) {
  247. position |= 255;
  248. if (!(delay_data[pool].class3->individual_255_used[i / 8] & (1 << (i % 8)))) {
  249.     delay_data[pool].class3->individual_255_used[i / 8] |= (1 << (i % 8));
  250.     delay_data[pool].class3->individual[position] =
  251. (Config.Delay.rates[pool]->individual.max_bytes *
  252. Config.Delay.initial) / 100;
  253. }
  254. return delayId(pool + 1, position);
  255.     }
  256.     for (j = 0;; j++) {
  257. if (delay_data[pool].class3->individual_map[i][j] == host) {
  258.     position |= j;
  259.     break;
  260. }
  261. if (delay_data[pool].class3->individual_map[i][j] == 255) {
  262.     delay_data[pool].class3->individual_map[i][j] = host;
  263.     delay_data[pool].class3->individual_map[i][j + 1] = 255;
  264.     delay_data[pool].class3->individual[position |= j] =
  265. (Config.Delay.rates[pool]->individual.max_bytes *
  266. Config.Delay.initial) / 100;
  267.     break;
  268. }
  269.     }
  270.     return delayId(pool + 1, position);
  271. }
  272. static void
  273. delayUpdateClass1(class1DelayPool * class1, delaySpecSet * rates, int incr)
  274. {
  275.     /* delaySetSpec may be pointer to partial structure so MUST pass by
  276.      * reference.
  277.      */
  278.     if (rates->aggregate.restore_bps != -1 &&
  279. (class1->aggregate += rates->aggregate.restore_bps * incr) >
  280. rates->aggregate.max_bytes)
  281. class1->aggregate = rates->aggregate.max_bytes;
  282. }
  283. static void
  284. delayUpdateClass2(class2DelayPool * class2, delaySpecSet * rates, int incr)
  285. {
  286.     int restore_bytes;
  287.     unsigned char i;
  288.     /* delaySetSpec may be pointer to partial structure so MUST pass by
  289.      * reference.
  290.      */
  291.     if (rates->aggregate.restore_bps != -1 &&
  292. (class2->aggregate += rates->aggregate.restore_bps * incr) >
  293. rates->aggregate.max_bytes)
  294. class2->aggregate = rates->aggregate.max_bytes;
  295.     if ((restore_bytes = rates->individual.restore_bps) == -1)
  296. return;
  297.     restore_bytes *= incr;
  298.     if (class2->individual_255_used)
  299. i = 255;
  300.     else
  301. i = 0;
  302.     for (;;) {
  303. if (i != 255 && class2->individual_map[i] == 255)
  304.     return;
  305. if (class2->individual[i] != rates->individual.max_bytes &&
  306.     (class2->individual[i] += restore_bytes) > rates->individual.max_bytes)
  307.     class2->individual[i] = rates->individual.max_bytes;
  308. if (++i == 255)
  309.     return;
  310.     }
  311. }
  312. static void
  313. delayUpdateClass3(class3DelayPool * class3, delaySpecSet * rates, int incr)
  314. {
  315.     int individual_restore_bytes, network_restore_bytes;
  316.     int mpos;
  317.     unsigned char i, j;
  318.     /* delaySetSpec may be pointer to partial structure so MUST pass by
  319.      * reference.
  320.      */
  321.     if (rates->aggregate.restore_bps != -1 &&
  322. (class3->aggregate += rates->aggregate.restore_bps * incr) >
  323. rates->aggregate.max_bytes)
  324. class3->aggregate = rates->aggregate.max_bytes;
  325.     /* the following line deliberately uses &, not &&, in an if statement
  326.      * to avoid conditional execution
  327.      */
  328.     if (((network_restore_bytes = rates->network.restore_bps) == -1) &
  329. ((individual_restore_bytes = rates->individual.restore_bps) == -1))
  330. return;
  331.     individual_restore_bytes *= incr;
  332.     network_restore_bytes *= incr;
  333.     if (class3->network_255_used)
  334. i = 255;
  335.     else
  336. i = 0;
  337.     for (;;) {
  338. if (i != 255 && class3->network_map[i] == 255)
  339.     return;
  340. if (individual_restore_bytes != -incr) {
  341.     mpos = i << 8;
  342.     if (class3->individual_255_used[i / 8] & (1 << (i % 8)))
  343. j = 255;
  344.     else
  345. j = 0;
  346.     for (;;) {
  347. if (j != 255 && class3->individual_map[i][j] == 255)
  348.     break;
  349. if (class3->individual[mpos] != rates->individual.max_bytes &&
  350.     (class3->individual[mpos] += individual_restore_bytes) >
  351.     rates->individual.max_bytes)
  352.     class3->individual[mpos] = rates->individual.max_bytes;
  353. mpos++;
  354. if (j == 255)
  355.     mpos -= 256;
  356. if (++j == 255)
  357.     break;
  358.     }
  359. }
  360. if (network_restore_bytes != -incr &&
  361.     class3->network[i] != rates->network.max_bytes &&
  362.     (class3->network[i] += network_restore_bytes) >
  363.     rates->network.max_bytes)
  364.     class3->network[i] = rates->network.max_bytes;
  365. if (++i == 255)
  366.     return;
  367.     }
  368. }
  369. void
  370. delayPoolsUpdate(void *unused)
  371. {
  372.     int incr = squid_curtime - delay_pools_last_update;
  373.     unsigned short i;
  374.     unsigned char class;
  375.     if (!Config.Delay.pools)
  376. return;
  377.     eventAdd("delayPoolsUpdate", delayPoolsUpdate, NULL, 1.0, 1);
  378.     if (incr < 1)
  379. return;
  380.     delay_pools_last_update = squid_curtime;
  381.     for (i = 0; i < Config.Delay.pools; i++) {
  382. class = Config.Delay.class[i];
  383. if (!class)
  384.     continue;
  385. switch (class) {
  386. case 1:
  387.     delayUpdateClass1(delay_data[i].class1, Config.Delay.rates[i], incr);
  388.     break;
  389. case 2:
  390.     delayUpdateClass2(delay_data[i].class2, Config.Delay.rates[i], incr);
  391.     break;
  392. case 3:
  393.     delayUpdateClass3(delay_data[i].class3, Config.Delay.rates[i], incr);
  394.     break;
  395. default:
  396.     assert(0);
  397. }
  398.     }
  399. }
  400. /*
  401.  * this returns the number of bytes the client is permitted. it does not take
  402.  * into account bytes already buffered - that is up to the caller.
  403.  */
  404. int
  405. delayBytesWanted(delay_id d, int min, int max)
  406. {
  407.     unsigned short position = d & 0xFFFF;
  408.     unsigned short pool = (d >> 16) - 1;
  409.     unsigned char class = (pool == 0xFFFF) ? 0 : Config.Delay.class[pool];
  410.     int nbytes = max;
  411.     switch (class) {
  412.     case 0:
  413. break;
  414.     case 1:
  415. if (Config.Delay.rates[pool]->aggregate.restore_bps != -1)
  416.     nbytes = XMIN(nbytes, delay_data[pool].class1->aggregate);
  417. break;
  418.     case 2:
  419. if (Config.Delay.rates[pool]->aggregate.restore_bps != -1)
  420.     nbytes = XMIN(nbytes, delay_data[pool].class2->aggregate);
  421. if (Config.Delay.rates[pool]->individual.restore_bps != -1)
  422.     nbytes = XMIN(nbytes, delay_data[pool].class2->individual[position]);
  423. break;
  424.     case 3:
  425. if (Config.Delay.rates[pool]->aggregate.restore_bps != -1)
  426.     nbytes = XMIN(nbytes, delay_data[pool].class3->aggregate);
  427. if (Config.Delay.rates[pool]->individual.restore_bps != -1)
  428.     nbytes = XMIN(nbytes, delay_data[pool].class3->individual[position]);
  429. if (Config.Delay.rates[pool]->network.restore_bps != -1)
  430.     nbytes = XMIN(nbytes, delay_data[pool].class3->network[position >> 8]);
  431. break;
  432.     default:
  433. fatalf("delayBytesWanted: Invalid class %dn", class);
  434. break;
  435.     }
  436.     nbytes = XMAX(min, nbytes);
  437.     return nbytes;
  438. }
  439. /*
  440.  * this records actual bytes recieved.  always recorded, even if the
  441.  * class is disabled - it's more efficient to just do it than to do all
  442.  * the checks.
  443.  */
  444. void
  445. delayBytesIn(delay_id d, int qty)
  446. {
  447.     unsigned short position = d & 0xFFFF;
  448.     unsigned short pool = (d >> 16) - 1;
  449.     unsigned char class;
  450.     if (pool == 0xFFFF)
  451. return;
  452.     class = Config.Delay.class[pool];
  453.     switch (class) {
  454.     case 1:
  455. delay_data[pool].class1->aggregate -= qty;
  456. return;
  457.     case 2:
  458. delay_data[pool].class2->aggregate -= qty;
  459. delay_data[pool].class2->individual[position] -= qty;
  460. return;
  461.     case 3:
  462. delay_data[pool].class3->aggregate -= qty;
  463. delay_data[pool].class3->network[position >> 8] -= qty;
  464. delay_data[pool].class3->individual[position] -= qty;
  465. return;
  466.     }
  467.     fatalf("delayBytesWanted: Invalid class %dn", class);
  468.     assert(0);
  469. }
  470. int
  471. delayMostBytesWanted(const MemObject * mem, int max)
  472. {
  473.     int i = 0;
  474.     int found = 0;
  475.     store_client *sc;
  476.     for (sc = mem->clients; sc; sc = sc->next) {
  477. if (sc->callback_data == NULL) /* open slot */
  478.     continue;
  479. if (sc->type != STORE_MEM_CLIENT)
  480.     continue;
  481. i = delayBytesWanted(sc->delay_id, i, max);
  482. found = 1;
  483.     }
  484.     return found ? i : max;
  485. }
  486. delay_id
  487. delayMostBytesAllowed(const MemObject * mem)
  488. {
  489.     int j;
  490.     int jmax = -1;
  491.     store_client *sc;
  492.     delay_id d = 0;
  493.     for (sc = mem->clients; sc; sc = sc->next) {
  494. if (sc->callback_data == NULL) /* open slot */
  495.     continue;
  496. if (sc->type != STORE_MEM_CLIENT)
  497.     continue;
  498. j = delayBytesWanted(sc->delay_id, 0, SQUID_TCP_SO_RCVBUF);
  499. if (j > jmax) {
  500.     jmax = j;
  501.     d = sc->delay_id;
  502. }
  503.     }
  504.     return d;
  505. }
  506. void
  507. delaySetStoreClient(StoreEntry * e, void *data, delay_id delay_id)
  508. {
  509.     store_client *sc = storeClientListSearch(e->mem_obj, data);
  510.     assert(sc != NULL);
  511.     sc->delay_id = delay_id;
  512. }
  513. static void
  514. delayPoolStatsAg(StoreEntry * sentry, delaySpecSet * rate, int ag)
  515. {
  516.     /* note - always pass delaySpecSet's by reference as may be incomplete */
  517.     if (rate->aggregate.restore_bps == -1) {
  518. storeAppendPrintf(sentry, "tAggregate:nttDisabled.nn");
  519. return;
  520.     }
  521.     storeAppendPrintf(sentry, "tAggregate:n");
  522.     storeAppendPrintf(sentry, "ttMax: %dn", rate->aggregate.max_bytes);
  523.     storeAppendPrintf(sentry, "ttRestore: %dn", rate->aggregate.restore_bps);
  524.     storeAppendPrintf(sentry, "ttCurrent: %dnn", ag);
  525. }
  526. static void
  527. delayPoolStats1(StoreEntry * sentry, unsigned short pool)
  528. {
  529.     /* must be a reference only - partially malloc()d struct */
  530.     delaySpecSet *rate = Config.Delay.rates[pool];
  531.     storeAppendPrintf(sentry, "Pool: %dntClass: 1nn", pool + 1);
  532.     delayPoolStatsAg(sentry, rate, delay_data[pool].class1->aggregate);
  533. }
  534. static void
  535. delayPoolStats2(StoreEntry * sentry, unsigned short pool)
  536. {
  537.     /* must be a reference only - partially malloc()d struct */
  538.     delaySpecSet *rate = Config.Delay.rates[pool];
  539.     class2DelayPool *class2 = delay_data[pool].class2;
  540.     unsigned char shown = 0, i;
  541.     storeAppendPrintf(sentry, "Pool: %dntClass: 2nn", pool + 1);
  542.     delayPoolStatsAg(sentry, rate, class2->aggregate);
  543.     if (rate->individual.restore_bps == -1) {
  544. storeAppendPrintf(sentry, "tIndividual:nttDisabled.nn");
  545. return;
  546.     }
  547.     storeAppendPrintf(sentry, "tIndividual:n");
  548.     storeAppendPrintf(sentry, "ttMax: %dn", rate->individual.max_bytes);
  549.     storeAppendPrintf(sentry, "ttRate: %dn", rate->individual.restore_bps);
  550.     storeAppendPrintf(sentry, "ttCurrent: ");
  551.     for (i = 0;; i++) {
  552. if (class2->individual_map[i] == 255)
  553.     break;
  554. storeAppendPrintf(sentry, "%d:%d ", class2->individual_map[i],
  555.     class2->individual[i]);
  556. shown = 1;
  557.     }
  558.     if (class2->individual_255_used) {
  559. storeAppendPrintf(sentry, "%d:%d ", 255, class2->individual[255]);
  560. shown = 1;
  561.     }
  562.     if (!shown)
  563. storeAppendPrintf(sentry, "Not used yet.");
  564.     storeAppendPrintf(sentry, "nn");
  565. }
  566. static void
  567. delayPoolStats3(StoreEntry * sentry, unsigned short pool)
  568. {
  569.     /* fully malloc()d struct in this case only */
  570.     delaySpecSet *rate = Config.Delay.rates[pool];
  571.     class3DelayPool *class3 = delay_data[pool].class3;
  572.     unsigned char shown = 0, i, j;
  573.     storeAppendPrintf(sentry, "Pool: %dntClass: 3nn", pool + 1);
  574.     delayPoolStatsAg(sentry, rate, class3->aggregate);
  575.     if (rate->network.restore_bps == -1) {
  576. storeAppendPrintf(sentry, "tNetwork:nttDisabled.");
  577.     } else {
  578. storeAppendPrintf(sentry, "tNetwork:n");
  579. storeAppendPrintf(sentry, "ttMax: %dn", rate->network.max_bytes);
  580. storeAppendPrintf(sentry, "ttRate: %dn", rate->network.restore_bps);
  581. storeAppendPrintf(sentry, "ttCurrent: ");
  582. for (i = 0;; i++) {
  583.     if (class3->network_map[i] == 255)
  584. break;
  585.     storeAppendPrintf(sentry, "%d:%d ", class3->network_map[i],
  586. class3->network[i]);
  587.     shown = 1;
  588. }
  589. if (class3->network_255_used) {
  590.     storeAppendPrintf(sentry, "%d:%d ", 255, class3->network[255]);
  591.     shown = 1;
  592. }
  593. if (!shown)
  594.     storeAppendPrintf(sentry, "Not used yet.");
  595.     }
  596.     storeAppendPrintf(sentry, "nn");
  597.     shown = 0;
  598.     if (rate->individual.restore_bps == -1) {
  599. storeAppendPrintf(sentry, "tIndividual:nttDisabled.nn");
  600. return;
  601.     }
  602.     storeAppendPrintf(sentry, "tIndividual:n");
  603.     storeAppendPrintf(sentry, "ttMax: %dn", rate->individual.max_bytes);
  604.     storeAppendPrintf(sentry, "ttRate: %dn", rate->individual.restore_bps);
  605.     for (i = 0;; i++) {
  606. if (class3->network_map[i] == 255)
  607.     break;
  608. storeAppendPrintf(sentry, "ttCurrent [Network %d]: ", class3->network_map[i]);
  609. shown = 1;
  610. for (j = 0;; j++) {
  611.     if (class3->individual_map[i][j] == 255)
  612. break;
  613.     storeAppendPrintf(sentry, "%d:%d ", class3->individual_map[i][j],
  614. class3->individual[(i << 8) | j]);
  615. }
  616. if (class3->individual_255_used[i / 8] & (1 << (i % 8))) {
  617.     storeAppendPrintf(sentry, "%d:%d ", 255, class3->individual[(i << 8) | 255]);
  618. }
  619. storeAppendPrintf(sentry, "n");
  620.     }
  621.     if (class3->network_255_used) {
  622. storeAppendPrintf(sentry, "ttCurrent [Network 255]: ");
  623. shown = 1;
  624. for (j = 0;; j++) {
  625.     if (class3->individual_map[255][j] == 255)
  626. break;
  627.     storeAppendPrintf(sentry, "%d:%d ", class3->individual_map[255][j],
  628. class3->individual[(255 << 8) | j]);
  629. }
  630. if (class3->individual_255_used[255 / 8] & (1 << (255 % 8))) {
  631.     storeAppendPrintf(sentry, "%d:%d ", 255, class3->individual[(255 << 8) | 255]);
  632. }
  633. storeAppendPrintf(sentry, "n");
  634.     }
  635.     if (!shown)
  636. storeAppendPrintf(sentry, "ttCurrent [All networks]: Not used yet.n");
  637.     storeAppendPrintf(sentry, "n");
  638. }
  639. static void
  640. delayPoolStats(StoreEntry * sentry)
  641. {
  642.     unsigned short i;
  643.     storeAppendPrintf(sentry, "Delay pools configured: %dnn", Config.Delay.pools);
  644.     for (i = 0; i < Config.Delay.pools; i++) {
  645. switch (Config.Delay.class[i]) {
  646. case 0:
  647.     storeAppendPrintf(sentry, "Pool: %dntClass: 0nn", i + 1);
  648.     storeAppendPrintf(sentry, "tMisconfigured pool.nn");
  649.     break;
  650. case 1:
  651.     delayPoolStats1(sentry, i);
  652.     break;
  653. case 2:
  654.     delayPoolStats2(sentry, i);
  655.     break;
  656. case 3:
  657.     delayPoolStats3(sentry, i);
  658.     break;
  659. default:
  660.     assert(0);
  661. }
  662.     }
  663. }
  664. #endif