/*
- * $Id: cache_cf.cc,v 1.323 1999/01/29 21:36:47 wessels Exp $
+ * $Id: cache_cf.cc,v 1.324 1999/01/29 23:39:12 wessels Exp $
*
* DEBUG: section 3 Configuration File Parsing
* AUTHOR: Harvest Derived
static void parse_refreshpattern(refresh_t **);
static int parseTimeUnits(const char *unit);
static void parseTimeLine(time_t * tptr, const char *units);
+static void parse_ushort(u_short * var);
static void parse_string(char **);
static void parse_wordlist(wordlist **);
static void default_all(void);
memset(addr, '\0', sizeof(struct in_addr));
}
+#if DELAY_POOLS
+
+/* do nothing - free_delay_pool_count is the magic free function.
+ * this is why delay_pool_count isn't just marked TYPE: ushort
+ */
+#define free_delay_pool_class(X)
+#define free_delay_pool_access(X)
+#define free_delay_pool_rates(X)
+#define dump_delay_pool_class(X, Y, Z)
+#define dump_delay_pool_access(X, Y, Z)
+#define dump_delay_pool_rates(X, Y, Z)
+
+static void
+free_delay_pool_count(delayConfig * cfg)
+{
+ int i;
+
+ if (!cfg->pools)
+ return;
+ for (i = 0; i < cfg->pools; i++) {
+ if (cfg->class[i]) {
+ delayFreeDelayPool(i);
+ safe_free(cfg->rates[i]);
+ }
+ aclDestroyAccessList(&cfg->access[i]);
+ }
+ delayFreeDelayData();
+ xfree(cfg->class);
+ xfree(cfg->rates);
+ xfree(cfg->access);
+ memset(cfg, 0, sizeof(*cfg));
+}
+
+static void
+dump_delay_pool_count(StoreEntry * entry, const char *name, delayConfig cfg)
+{
+ int i;
+ LOCAL_ARRAY(char, nom, 32);
+
+ if (!cfg.pools) {
+ storeAppendPrintf(entry, "%s 0\n", name);
+ return;
+ }
+ storeAppendPrintf(entry, "%s %d\n", name, cfg.pools);
+ for (i = 0; i < cfg.pools; i++) {
+ storeAppendPrintf(entry, "delay_class %d %d\n", i + 1, cfg.class[i]);
+ snprintf(nom, 32, "delay_access %d", i + 1);
+ dump_acl_access(entry, nom, cfg.access[i]);
+ if (cfg.class[i] >= 1)
+ storeAppendPrintf(entry, "delay_parameters %d %d/%d", i + 1,
+ cfg.rates[i]->aggregate.restore_bps,
+ cfg.rates[i]->aggregate.max_bytes);
+ if (cfg.class[i] >= 3)
+ storeAppendPrintf(entry, " %d/%d",
+ cfg.rates[i]->network.restore_bps,
+ cfg.rates[i]->network.max_bytes);
+ if (cfg.class[i] >= 2)
+ storeAppendPrintf(entry, " %d/%d",
+ cfg.rates[i]->individual.restore_bps,
+ cfg.rates[i]->individual.max_bytes);
+ if (cfg.class[i] >= 1)
+ storeAppendPrintf(entry, "\n");
+ }
+}
+
+static void
+parse_delay_pool_count(delayConfig * cfg)
+{
+ if (cfg->pools) {
+ debug(3, 0) ("parse_delay_pool_count: multiple delay_pools lines, aborting all previous delay_pools config\n");
+ free_delay_pool_count(cfg);
+ }
+ parse_ushort(&cfg->pools);
+ delayInitDelayData(cfg->pools);
+ cfg->class = xcalloc(cfg->pools, sizeof(u_char));
+ cfg->rates = xcalloc(cfg->pools, sizeof(delaySpecSet *));
+ cfg->access = xcalloc(cfg->pools, sizeof(acl_access *));
+}
+
+static void
+parse_delay_pool_class(delayConfig * cfg)
+{
+ ushort pool, class;
+
+ parse_ushort(&pool);
+ if (pool < 1 || pool > cfg->pools) {
+ debug(3, 0) ("parse_delay_pool_class: Ignoring pool %d not in 1 .. %d\n", pool, cfg->pools);
+ return;
+ }
+ parse_ushort(&class);
+ if (class < 1 || class > 3) {
+ debug(3, 0) ("parse_delay_pool_class: Ignoring pool %d class %d not in 1 .. 3\n", pool, class);
+ return;
+ }
+ pool--;
+ if (cfg->class[pool]) {
+ delayFreeDelayPool(pool);
+ safe_free(cfg->rates[pool]);
+ }
+ cfg->rates[pool] = xmalloc(class * sizeof(delaySpec));
+ cfg->class[pool] = class;
+ cfg->rates[pool]->aggregate.restore_bps = cfg->rates[pool]->aggregate.max_bytes = -1;
+ if (cfg->class[pool] >= 3)
+ cfg->rates[pool]->network.restore_bps = cfg->rates[pool]->network.max_bytes = -1;
+ if (cfg->class[pool] >= 2)
+ cfg->rates[pool]->individual.restore_bps = cfg->rates[pool]->individual.max_bytes = -1;
+ delayCreateDelayPool(pool, class);
+}
+
+static void
+parse_delay_pool_rates(delayConfig * cfg)
+{
+ ushort pool, class;
+ int i;
+ delaySpec *ptr;
+ char *token;
+
+ parse_ushort(&pool);
+ if (pool < 1 || pool > cfg->pools) {
+ debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d not in 1 .. %d\n", pool, cfg->pools);
+ return;
+ }
+ pool--;
+ class = cfg->class[pool];
+ if (class == 0) {
+ debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d attempt to set rates with class not set\n", pool + 1);
+ return;
+ }
+ ptr = (delaySpec *) cfg->rates[pool];
+ /* read in "class" sets of restore,max pairs */
+ while (class--) {
+ token = strtok(NULL, "/");
+ if (token == NULL)
+ self_destruct();
+ if (sscanf(token, "%d", &i) != 1)
+ self_destruct();
+ ptr->restore_bps = i;
+ GetInteger(i);
+ ptr->max_bytes = i;
+ ptr++;
+ }
+ class = cfg->class[pool];
+ /* if class is 3, swap around network and individual */
+ if (class == 3) {
+ delaySpec tmp;
+
+ tmp = cfg->rates[pool]->individual;
+ cfg->rates[pool]->individual = cfg->rates[pool]->network;
+ cfg->rates[pool]->network = tmp;
+ }
+ /* initialize the delay pools */
+ delayInitDelayPool(pool, class, cfg->rates[pool]);
+}
+
+static void
+parse_delay_pool_access(delayConfig * cfg)
+{
+ ushort pool;
+
+ parse_ushort(&pool);
+ if (pool < 1 || pool > cfg->pools) {
+ debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d not in 1 .. %d\n", pool, cfg->pools);
+ return;
+ }
+ aclParseAccessLine(&cfg->access[pool - 1]);
+}
+#endif
+
static void
dump_http_header(StoreEntry * entry, const char *name, HttpHeaderMask header)
{
#
-# $Id: cf.data.pre,v 1.142 1999/01/29 21:28:08 wessels Exp $
+# $Id: cf.data.pre,v 1.143 1999/01/29 23:39:13 wessels Exp $
#
#
# SQUID Internet Object Cache http://squid.nlanr.net/Squid/
COMMENT_START
DELAY POOL PARAMETERS (all require DELAY_POOLS compilation option)
-----------------------------------------------------------------------------
-
- A general note on delay pools - the first matched delay pool is used,
- that is, if a request falls into class1 then it isn't checked for class2
- or class3 (and similarly a class2 request isn't checked for class3).
COMMENT_END
-NAME: delay_class1_access
-TYPE: acl_access
-DEFAULT: none
+NAME: delay_pools
+TYPE: delay_pool_count
+DEFAULT: 0
IFDEF: DELAY_POOLS
-LOC: Config.Delay.class1.access
+LOC: Config.Delay
DOC_START
- This is used to select what client requests are processed via
- the first ("class 1") delay pool. In this delay pool only the
- aggregate traffic allowance is configurable.
+ This represents the number of delay pools to be used. For example,
+ if you have one class 2 delay pool and one class 3 delays pool, you
+ have a total of 2 delay pools.
+
+delay_pools 0
DOC_END
-NAME: delay_class2_access
-TYPE: acl_access
+NAME: delay_class
+TYPE: delay_pool_class
DEFAULT: none
IFDEF: DELAY_POOLS
-LOC: Config.Delay.class2.access
+LOC: Config.Delay
DOC_START
- This is used to select what client requests are processed via
- the first ("class 2") delay pool. In this delay pool both the
- aggregate and per-host traffic allowance are configurable.
- There are 254 individual delay pools based on the last 8 bits
- of the client IP address (addresses ending in 0 and 255 are not
- permitted).
+ This defines the class of each delay pool. There must be exactly one
+ delay_class line for each delay pool. For example, to define two
+ delay pools, one of class 2 and one of class 3, the settings above
+ and here would be:
+
+delay_pools 2 # 2 delay pools
+delay_class 1 2 # pool 1 is a class 2 pool
+delay_class 2 3 # pool 2 is a class 3 pool
+
+ The delay pool classes are:
+
+ class 1 Everything is limited by a single aggregate
+ bucket.
+
+ class 2 Everything is limited by a single aggregate
+ bucket as well as an "individual" bucket chosen
+ from bits 25 through 32 of the IP address.
+
+ class 3 Everything is limited by a single aggregate
+ bucket as well as a "network" bucket chosen
+ from bits 17 through 24 of the IP address and a
+ "individual" bucket chosen from bits 17 through
+ 32 of the IP address.
+
+ NOTE: If an IP address is a.b.c.d
+ -> bits 25 through 32 are "d"
+ -> bits 17 through 24 are "c"
+ -> bits 17 through 32 are "c * 256 + d"
DOC_END
-NAME: delay_class3_access
-TYPE: acl_access
+NAME: delay_access
+TYPE: delay_pool_access
DEFAULT: none
IFDEF: DELAY_POOLS
-LOC: Config.Delay.class3.access
+LOC: Config.Delay
DOC_START
- This is used to select what client requests are processed via
- the first ("class 3") delay pool. In this delay pool, the
- aggregate, network and per-host traffic allowance are
- configurable. There are 255 network delay pools based on the
- 17th to 24th bit of the client IP address (network 255 is not
- permitted), and individual delay pools based on the last 16
- bits of the client IP address (network 255 and hosts ending in
- 0 and 255 are not permitted).
-DOC_END
+ This is used to determine which delay pool a request falls into.
+ The first matched delay pool is always used, ie, if a request falls
+ into delay pool number one, no more delay are checked, otherwise the
+ rest are checked in order of their delay pool number until they have
+ all been checked. For example, if you want some_big_clients in delay
+ pool 1 and lotsa_little_clients in delay pool 2:
-NAME: delay_class1_aggregate_restore
-TYPE: int
-DEFAULT: -1
-IFDEF: DELAY_POOLS
-COMMENT: (bps)
-LOC: Config.Delay.class1.aggregate.restore_bps
-DOC_START
- The number of bytes per second added to the class 1 aggregate
- delay pool traffic allowance (-1 to disable the delay pool).
+delay_access 1 allow some_big_clients
+delay_access 1 deny all
+delay_access 2 allow lotsa_little_clients
+delay_access 2 deny all
DOC_END
-NAME: delay_class1_aggregate_max
-TYPE: int
-DEFAULT: -1
+NAME: delay_parameters
+TYPE: delay_pool_rates
+DEFAULT: none
IFDEF: DELAY_POOLS
-COMMENT: (bytes)
-LOC: Config.Delay.class1.aggregate.max_bytes
+LOC: Config.Delay
DOC_START
- The maximum number of bytes which can be in the class 1
- aggregate delay pool traffic allowance.
-DOC_END
+ This defines the parameters for a delay pool. Each delay pool has
+ a number of "buckets" associated with it, as explained in the
+ description of delay_class. For a class 1 delay pool, the syntax is:
-NAME: delay_class2_aggregate_restore
-TYPE: int
-DEFAULT: -1
-IFDEF: DELAY_POOLS
-COMMENT: (bps)
-LOC: Config.Delay.class2.aggregate.restore_bps
-DOC_START
- The number of bytes per second added to the class 2 aggregate
- delay pool traffic allowance (-1 to disable the delay pool).
-DOC_END
+delay_parameters pool aggregate
-NAME: delay_class2_aggregate_max
-TYPE: int
-DEFAULT: -1
-IFDEF: DELAY_POOLS
-COMMENT: (bytes)
-LOC: Config.Delay.class2.aggregate.max_bytes
-DOC_START
- The maximum number of bytes which can be in the class 2
- aggregate delay pool traffic allowance.
-DOC_END
+ For a class 2 delay pool:
-NAME: delay_class2_individual_restore
-TYPE: int
-DEFAULT: -1
-IFDEF: DELAY_POOLS
-COMMENT: (bps)
-LOC: Config.Delay.class2.individual.restore_bps
-DOC_START
- The number of bytes per second added to the class 2 individual
- host delay pool traffic allowances (-1 to disable these delay
- pools).
-DOC_END
+delay_parameters pool aggregate individual
-NAME: delay_class2_individual_max
-TYPE: int
-DEFAULT: -1
-IFDEF: DELAY_POOLS
-COMMENT: (bytes)
-LOC: Config.Delay.class2.individual.max_bytes
-DOC_START
- The maximum number of bytes which can be in the class 2
- individual host delay pool traffic allowances.
-DOC_END
+ For a class 3 delay pool:
-NAME: delay_class3_aggregate_restore
-TYPE: int
-DEFAULT: -1
-IFDEF: DELAY_POOLS
-COMMENT: (bps)
-LOC: Config.Delay.class3.aggregate.restore_bps
-DOC_START
- The number of bytes per second added to the class 3 aggregate
- delay pool traffic allowance (-1 to disable the delay pool).
-DOC_END
+delay_parameters pool aggregate network individual
-NAME: delay_class3_aggregate_max
-TYPE: int
-DEFAULT: -1
-IFDEF: DELAY_POOLS
-COMMENT: (bytes)
-LOC: Config.Delay.class3.aggregate.max_bytes
-DOC_START
- The maximum number of bytes which can be in the class 3
- aggregate delay pool traffic allowance.
-DOC_END
+ The variables here are:
-NAME: delay_class3_network_restore
-TYPE: int
-DEFAULT: -1
-IFDEF: DELAY_POOLS
-COMMENT: (bps)
-LOC: Config.Delay.class3.network.restore_bps
-DOC_START
- The number of bytes per second added to the class 3 8-bit
- network delay pool traffic allowances (-1 to disable these
- delay pools).
-DOC_END
+ pool a pool number - ie, a number between 1 and the
+ number specified in delay_pools as used in
+ delay_class lines.
-NAME: delay_class3_network_max
-TYPE: int
-DEFAULT: -1
-IFDEF: DELAY_POOLS
-COMMENT: (bytes)
-LOC: Config.Delay.class3.network.max_bytes
-DOC_START
- The maximum number of bytes which can be in the class 3 8-bit
- network delay pool traffic allowances.
-DOC_END
+ aggregate the "delay parameters" for the aggregate bucket
+ (class 1, 2, 3).
-NAME: delay_class3_individual_restore
-TYPE: int
-DEFAULT: -1
-IFDEF: DELAY_POOLS
-COMMENT: (bps)
-LOC: Config.Delay.class3.individual.restore_bps
-DOC_START
- The number of bytes per second added to the class 3 individual
- host delay pool traffic allowances (-1 to disable these delay
- pools).
+ individual the "delay parameters" for the individual
+ buckets (class 2, 3).
+
+ network the "delay parameters" for the network buckets
+ (class 3).
+
+ A pair of delay parameters is written restore/maximum, where restore is
+ the number of bytes (not bits - modem and network speeds are usually
+ quoted in bits) per second placed into the bucket, and maximum is the
+ maximum number of bytes which can be in the bucket at any time.
+
+ For example, if delay pool number 1 is a class 2 delay pool as in the
+ above example, and is being used to strictly limit each host to 64kbps
+ (plus overheads), with no overall limit, the line is:
+
+delay_parameters 1 -1/-1 8000/8000
+
+ Note that the figure -1 is used to represent "unlimited".
+
+ And, if delay pool number 2 is a class 3 delay pool as in the above
+ example, and you want to limit it to a total of 256kbps (strict limit)
+ with each 8-bit network permitted 64kbps (strict limit) and each
+ individual host permitted 4800bps with a bucket maximum size of 64kb
+ to permit a decent web page to be downloaded at a decent speed
+ (if the network is not being limited due to overuse) but slow down
+ large downloads more significantly:
+
+delay_parameters 2 32000/32000 8000/8000 600/64000
+
+ There must be one delay_parameters line for each delay pool.
DOC_END
-NAME: delay_class3_individual_max
-TYPE: int
-DEFAULT: -1
+NAME: delay_initial_bucket_level
+COMMENT: (percent, 0-100)
+TYPE: ushort
+DEFAULT: 50
IFDEF: DELAY_POOLS
-COMMENT: (bytes)
-LOC: Config.Delay.class3.individual.max_bytes
+LOC: Config.Delay.initial
DOC_START
- The maximum number of bytes which can be in the class 3
- individual host delay pool traffic allowances.
+ The initial bucket percentage is used to determine how much is put
+ in each bucket when squid starts, is reconfigured, or first notices
+ a host accessing it (in class 2 and class 3, individual hosts and
+ networks only have buckets associated with them once they have been
+ "seen" by squid).
+
+delay_initial_bucket_level 50
DOC_END
NAME: incoming_icp_average
/*
- * $Id: delay_pools.cc,v 1.6 1998/11/12 06:28:02 wessels Exp $
+ * $Id: delay_pools.cc,v 1.7 1999/01/29 23:39:17 wessels Exp $
*
* DEBUG: section 77 Delay Pools
* AUTHOR: David Luyer <luyer@ucs.uwa.edu.au>
#if DELAY_POOLS
#include "squid.h"
-struct _delayData {
- int class1_aggregate;
- int class2_aggregate;
- /* 254 entries + 1 terminator byte */
- unsigned char class2_individual_map[255];
- /* 254 entries */
- int class2_individual[254];
- int class3_aggregate;
+struct _class1DelayPool {
+ int aggregate;
+};
+
+struct _class2DelayPool {
+ int aggregate;
+ /* OK: -1 is terminator. individual[255] is always host 255. */
/* 255 entries + 1 terminator byte */
- unsigned char class3_network_map[256];
- /* 255 entries */
- int class3_network[255];
- /* 255 sets of (254 entries + 1 terminator byte) */
- unsigned char class3_individual_map[255][255];
- /* largest entry = (254<<8)+253 = 65277 */
- int class3_individual[65278];
+ unsigned char individual_map[256];
+ unsigned char individual_255_used;
+ /* 256 entries */
+ int individual[256];
};
-static struct _delayData delay_data;
-static OBJH delayPoolStats;
+struct _class3DelayPool {
+ int aggregate;
+ /* OK: -1 is terminator. network[255] is always host 255. */
+ /* 255 entries + 1 terminator byte */
+ unsigned char network_map[256];
+ unsigned char network_255_used;
+ /* 256 entries */
+ int network[256];
+ /* 256 sets of (255 entries + 1 terminator byte) */
+ unsigned char individual_map[256][256];
+ /* Pack this into one bit per net */
+ unsigned char individual_255_used[32];
+ /* largest entry = (255<<8)+255 = 65535 */
+ int individual[65536];
+};
+
+typedef struct _class1DelayPool class1DelayPool;
+typedef struct _class2DelayPool class2DelayPool;
+typedef struct _class3DelayPool class3DelayPool;
+
+union _delayPool {
+ class1DelayPool *class1;
+ class2DelayPool *class2;
+ class3DelayPool *class3;
+};
+
+typedef union _delayPool delayPool;
+
+static delayPool *delay_data = NULL;
+static fd_set delay_no_delay;
static time_t delay_pools_last_update = 0;
-static delay_id delayId(unsigned char class, int position);
-static delay_id
-delayId(unsigned char class, int position)
+static OBJH delayPoolStats;
+
+void
+delayPoolsInit(void)
{
- assert(class <= 3);
- return (class << 16) | (position & 0xFFFF);
+ delay_pools_last_update = getCurrentTime();
+ FD_ZERO(&delay_no_delay);
+ cachemgrRegister("delay", "Delay Pool Levels", delayPoolStats, 0, 1);
+}
+
+void
+delayInitDelayData(unsigned short pools)
+{
+ if (pools) {
+ delay_data = xcalloc(pools, sizeof(delayPool));
+ eventAdd("delayPoolsUpdate", delayPoolsUpdate, NULL, 1.0, 1);
+ }
+}
+
+void
+delayFreeDelayData()
+{
+ safe_free(delay_data);
+}
+
+void
+delayCreateDelayPool(unsigned short pool, u_char class)
+{
+ switch (class) {
+ case 1:
+ delay_data[pool].class1 = xmalloc(sizeof(class1DelayPool));
+ break;
+ case 2:
+ delay_data[pool].class2 = xmalloc(sizeof(class2DelayPool));
+ break;
+ case 3:
+ delay_data[pool].class3 = xmalloc(sizeof(class3DelayPool));
+ break;
+ default:
+ assert(0);
+ }
+}
+
+void
+delayInitDelayPool(unsigned short pool, u_char class, delaySpecSet * rates)
+{
+ /* delaySetSpec may be pointer to partial structure so MUST pass by
+ * reference.
+ */
+ switch (class) {
+ case 1:
+ delay_data[pool].class1->aggregate = (rates->aggregate.max_bytes *
+ Config.Delay.initial) / 100;
+ break;
+ case 2:
+ delay_data[pool].class2->aggregate = (rates->aggregate.max_bytes *
+ Config.Delay.initial) / 100;
+ delay_data[pool].class2->individual_map[0] = 255;
+ delay_data[pool].class2->individual_255_used = 0;
+ break;
+ case 3:
+ delay_data[pool].class3->aggregate = (rates->aggregate.max_bytes *
+ Config.Delay.initial) / 100;
+ delay_data[pool].class3->network_map[0] = 255;
+ delay_data[pool].class3->network_255_used = 0;
+ memset(&delay_data[pool].class3->individual_255_used, '\0',
+ sizeof(delay_data[pool].class3->individual_255_used));
+ break;
+ default:
+ assert(0);
+ }
+}
+
+void
+delayFreeDelayPool(unsigned short pool)
+{
+ /* this is a union - and all free() cares about is the pointer location */
+ safe_free(delay_data[pool].class1);
+}
+
+void
+delaySetNoDelay(int fd)
+{
+ FD_SET(fd, &delay_no_delay);
+}
+
+void
+delayClearNoDelay(int fd)
+{
+ FD_CLR(fd, &delay_no_delay);
}
int
-delayClient(clientHttpRequest * http)
+delayIsNoDelay(int fd)
+{
+ return FD_ISSET(fd, &delay_no_delay);
+}
+
+static delay_id
+delayId(unsigned short pool, unsigned short position)
+{
+ return (pool << 16) | position;
+}
+
+delay_id
+delayClient(request_t *r)
{
aclCheck_t ch;
int i;
int j;
unsigned int host;
- unsigned char net;
- unsigned char class = 0;
- int position = 0;
- request_t *r = http->request;
+ unsigned short pool, position;
+ unsigned char class, net;
memset(&ch, '\0', sizeof(ch));
- ch.src_addr = http->conn->peer.sin_addr;
+ ch.src_addr = r->client_addr;
+ ch.my_addr = r->my_addr;
ch.request = r;
- if (aclCheckFast(Config.Delay.class1.access, &ch)) {
- class = 1;
- r->delay_id = delayId(class, position);
- return 1;
+ for (pool = 0; pool < Config.Delay.pools; pool++) {
+ if (aclCheckFast(Config.Delay.access[pool], &ch))
+ break;
}
- if (aclCheckFast(Config.Delay.class2.access, &ch)) {
- class = 2;
+ if (pool == Config.Delay.pools)
+ return delayId(0, 0);
+ class = Config.Delay.class[pool];
+ if (class == 0)
+ return delayId(0, 0);
+ if (class == 1)
+ return delayId(pool + 1, 0);
+ if (class == 2) {
host = ntohl(ch.src_addr.s_addr) & 0xff;
- if (host == 255 || !host) {
- debug(77, 0) ("ARGH: Delay requested for host %s\n", inet_ntoa(ch.src_addr));
- class = 0;
- r->delay_id = delayId(class, position);
- return 0;
+ if (host == 255) {
+ if (!delay_data[pool].class2->individual_255_used) {
+ delay_data[pool].class2->individual_255_used = 1;
+ delay_data[pool].class2->individual[255] =
+ (Config.Delay.rates[pool]->individual.max_bytes *
+ Config.Delay.initial) / 100;
+ }
+ return delayId(pool + 1, 255);
}
for (i = 0;; i++) {
- if (delay_data.class2_individual_map[i] == host)
+ if (delay_data[pool].class2->individual_map[i] == host)
break;
- if (delay_data.class2_individual_map[i] == 255) {
- delay_data.class2_individual_map[i] = host;
- delay_data.class2_individual_map[i + 1] = 255;
- delay_data.class2_individual[i] = Config.Delay.class2.individual.restore_bps;
+ if (delay_data[pool].class2->individual_map[i] == 255) {
+ delay_data[pool].class2->individual_map[i] = host;
+ delay_data[pool].class2->individual_map[i + 1] = 255;
+ delay_data[pool].class2->individual[i] =
+ (Config.Delay.rates[pool]->individual.max_bytes *
+ Config.Delay.initial) / 100;
break;
}
}
- position = i;
- r->delay_id = delayId(class, position);
- return 1;
+ return delayId(pool + 1, i);
}
- if (aclCheckFast(Config.Delay.class3.access, &ch)) {
- class = 3;
- host = ntohl(ch.src_addr.s_addr) & 0xffff;
- net = host >> 8;
- host &= 0xff;
- if (host == 255 || !host || net == 255) {
- debug(77, 0) ("ARGH: Delay requested for host %s\n", inet_ntoa(ch.src_addr));
- class = 0;
- r->delay_id = delayId(class, position);
- return 0;
+ /* class == 3 */
+ host = ntohl(ch.src_addr.s_addr) & 0xffff;
+ net = host >> 8;
+ host &= 0xff;
+ if (net == 255) {
+ i = 255;
+ if (!delay_data[pool].class3->network_255_used) {
+ delay_data[pool].class3->network_255_used = 1;
+ delay_data[pool].class3->network[255] =
+ (Config.Delay.rates[pool]->network.max_bytes *
+ Config.Delay.initial) / 100;
}
+ } else {
for (i = 0;; i++) {
- if (delay_data.class3_network_map[i] == net)
+ if (delay_data[pool].class3->network_map[i] == net)
break;
- if (delay_data.class3_network_map[i] == 255) {
- delay_data.class3_network_map[i] = net;
- delay_data.class3_individual_map[i][0] = 255;
- delay_data.class3_network_map[i + 1] = 255;
- delay_data.class3_network[i] = Config.Delay.class3.network.restore_bps;
+ if (delay_data[pool].class3->network_map[i] == 255) {
+ delay_data[pool].class3->network_map[i] = net;
+ delay_data[pool].class3->individual_map[i][0] = 255;
+ delay_data[pool].class3->network_map[i + 1] = 255;
+ delay_data[pool].class3->network[i] =
+ (Config.Delay.rates[pool]->network.max_bytes *
+ Config.Delay.initial) / 100;
break;
}
}
- position = i << 8;
- for (j = 0;; j++) {
- if (delay_data.class3_individual_map[i][j] == host) {
- position |= j;
- break;
- }
- if (delay_data.class3_individual_map[i][j] == 255) {
- delay_data.class3_individual_map[i][j] = host;
- delay_data.class3_individual_map[i][j + 1] = 255;
- delay_data.class3_individual[position |= j] =
- Config.Delay.class3.individual.restore_bps;
- break;
- }
+ }
+ position = i << 8;
+ if (host == 255) {
+ position |= 255;
+ if (!(delay_data[pool].class3->individual_255_used[i / 8] & (1 << (i % 8)))) {
+ delay_data[pool].class3->individual_255_used[i / 8] |= (1 << (i % 8));
+ delay_data[pool].class3->individual[position] =
+ (Config.Delay.rates[pool]->individual.max_bytes *
+ Config.Delay.initial) / 100;
}
- r->delay_id = delayId(class, position);
- return 1;
+ return delayId(pool + 1, position);
}
- class = 0;
- r->delay_id = delayId(class, position);
- return 0;
+ for (j = 0;; j++) {
+ if (delay_data[pool].class3->individual_map[i][j] == host) {
+ position |= j;
+ break;
+ }
+ if (delay_data[pool].class3->individual_map[i][j] == 255) {
+ delay_data[pool].class3->individual_map[i][j] = host;
+ delay_data[pool].class3->individual_map[i][j + 1] = 255;
+ delay_data[pool].class3->individual[position |= j] =
+ (Config.Delay.rates[pool]->individual.max_bytes *
+ Config.Delay.initial) / 100;
+ break;
+ }
+ }
+ return delayId(pool + 1, position);
}
+static void
+delayUpdateClass1(class1DelayPool * class1, delaySpecSet * rates, int incr)
+{
+ /* delaySetSpec may be pointer to partial structure so MUST pass by
+ * reference.
+ */
+ if (rates->aggregate.restore_bps != -1 &&
+ (class1->aggregate += rates->aggregate.restore_bps * incr) >
+ rates->aggregate.max_bytes)
+ class1->aggregate = rates->aggregate.max_bytes;
+}
-void
-delayPoolsUpdate(void *unused)
+static void
+delayUpdateClass2(class2DelayPool * class2, delaySpecSet * rates, int incr)
{
- int incr = squid_curtime - delay_pools_last_update;
- int i;
- int j;
- int mpos;
- int individual_restore_bytes;
- int network_restore_bytes;
- eventAdd("delayPoolsUpdate", delayPoolsUpdate, NULL, 1.0, 1);
- if (incr < 1)
+ int restore_bytes;
+ unsigned char i;
+ /* delaySetSpec may be pointer to partial structure so MUST pass by
+ * reference.
+ */
+ if (rates->aggregate.restore_bps != -1 &&
+ (class2->aggregate += rates->aggregate.restore_bps * incr) >
+ rates->aggregate.max_bytes)
+ class2->aggregate = rates->aggregate.max_bytes;
+ if ((restore_bytes = rates->individual.restore_bps) == -1)
return;
- delay_pools_last_update = squid_curtime;
- /* Increment 3 aggregate pools */
- if (Config.Delay.class1.aggregate.restore_bps != -1 &&
- (delay_data.class1_aggregate +=
- Config.Delay.class1.aggregate.restore_bps * incr) >
- Config.Delay.class1.aggregate.max_bytes)
- delay_data.class1_aggregate = Config.Delay.class1.aggregate.max_bytes;
- if (Config.Delay.class2.aggregate.restore_bps != -1 &&
- (delay_data.class2_aggregate +=
- Config.Delay.class2.aggregate.restore_bps * incr) >
- Config.Delay.class2.aggregate.max_bytes)
- delay_data.class2_aggregate = Config.Delay.class2.aggregate.max_bytes;
- if (Config.Delay.class3.aggregate.restore_bps != -1 &&
- (delay_data.class3_aggregate +=
- Config.Delay.class3.aggregate.restore_bps * incr) >
- Config.Delay.class3.aggregate.max_bytes)
- delay_data.class3_aggregate = Config.Delay.class3.aggregate.max_bytes;
- /* Increment class 2 individual pools */
- if ((individual_restore_bytes = Config.Delay.class2.individual.restore_bps) != -1) {
- individual_restore_bytes *= incr;
- for (i = 0;; i++) {
- if (delay_data.class2_individual_map[i] == 255)
- break;
- if (delay_data.class2_individual[i] == Config.Delay.class2.individual.max_bytes)
- continue;
- if ((delay_data.class2_individual[i] += individual_restore_bytes) >
- Config.Delay.class2.individual.max_bytes)
- delay_data.class2_individual[i] = Config.Delay.class2.individual.max_bytes;
- }
- }
- /* Increment class 3 individual and network pools */
- if ((network_restore_bytes = Config.Delay.class3.network.restore_bps) != -1 ||
- (individual_restore_bytes = Config.Delay.class3.individual.restore_bps) != -1) {
- individual_restore_bytes *= incr;
- network_restore_bytes *= incr;
- for (i = 0;; i++) {
- if (delay_data.class3_network_map[i] == 255)
- break;
- if (individual_restore_bytes != -incr) {
- for (j = 0, mpos = (i << 8);; j++, mpos++) {
- if (delay_data.class3_individual_map[i][j] == 255)
- break;
- if (delay_data.class3_individual[mpos] == Config.Delay.class3.individual.max_bytes)
- continue;
- if ((delay_data.class3_individual[mpos] += individual_restore_bytes) >
- Config.Delay.class3.individual.max_bytes)
- delay_data.class3_individual[mpos] = Config.Delay.class3.individual.max_bytes;
- }
- }
- if (network_restore_bytes == -incr ||
- delay_data.class3_network[i] == Config.Delay.class3.network.max_bytes)
- continue;
- if ((delay_data.class3_network[i] += network_restore_bytes) >
- Config.Delay.class3.network.max_bytes)
- delay_data.class3_network[i] = Config.Delay.class3.network.max_bytes;
- }
+ restore_bytes *= incr;
+ if (class2->individual_255_used)
+ i = 255;
+ else
+ i = 0;
+ for (;;) {
+ if (i != 255 && class2->individual_map[i] == 255)
+ return;
+ if (class2->individual[i] != rates->individual.max_bytes &&
+ (class2->individual[i] += restore_bytes) > rates->individual.max_bytes)
+ class2->individual[i] = rates->individual.max_bytes;
+ if (++i == 255)
+ return;
}
}
-
static void
-delayPoolStats(StoreEntry * sentry)
+delayUpdateClass3(class3DelayPool * class3, delaySpecSet * rates, int incr)
{
- int i;
- int j;
- storeAppendPrintf(sentry, "Class 1 Delay Pool Statistics:\n");
- if (Config.Delay.class1.aggregate.restore_bps != -1) {
- storeAppendPrintf(sentry, "\n\tAggregate:\n");
- storeAppendPrintf(sentry, "\t\tMax: %d\n",
- Config.Delay.class1.aggregate.max_bytes);
- storeAppendPrintf(sentry, "\t\tRate: %d\n",
- Config.Delay.class1.aggregate.restore_bps);
- storeAppendPrintf(sentry, "\t\tCurrent: %d\n",
- delay_data.class1_aggregate);
- } else {
- storeAppendPrintf(sentry, "\n\tAggregate:\n\tDisabled.\n");
- }
- storeAppendPrintf(sentry, "\nClass 2 Delay Pool Statistics:\n");
- if (Config.Delay.class2.aggregate.restore_bps != -1) {
- storeAppendPrintf(sentry, "\n\tAggregate:\n");
- storeAppendPrintf(sentry, "\t\tMax: %d\n",
- Config.Delay.class2.aggregate.max_bytes);
- storeAppendPrintf(sentry, "\t\tRate: %d\n",
- Config.Delay.class2.aggregate.restore_bps);
- storeAppendPrintf(sentry, "\t\tCurrent: %d\n",
- delay_data.class2_aggregate);
- } else {
- storeAppendPrintf(sentry, "\n\tAggregate:\n\tDisabled.\n");
- }
- if (Config.Delay.class2.individual.restore_bps != -1) {
- storeAppendPrintf(sentry, "\n\tIndividual:\n");
- storeAppendPrintf(sentry, "\t\tMax: %d\n",
- Config.Delay.class2.individual.max_bytes);
- storeAppendPrintf(sentry, "\t\tRate: %d\n",
- Config.Delay.class2.individual.restore_bps);
- storeAppendPrintf(sentry, "\t\tCurrent: ");
- for (i = 0;; i++) {
- if (delay_data.class2_individual_map[i] == 255)
- break;
- storeAppendPrintf(sentry, "%d:%d ",
- delay_data.class2_individual_map[i],
- delay_data.class2_individual[i]);
- }
- } else {
- storeAppendPrintf(sentry, "\n\tIndividual:\n\tDisabled.");
- }
- storeAppendPrintf(sentry, "\n\nClass 3 Delay Pool Statistics:\n");
- if (Config.Delay.class3.aggregate.restore_bps != -1) {
- storeAppendPrintf(sentry, "\n\tAggregate:\n");
- storeAppendPrintf(sentry, "\t\tMax: %d\n",
- Config.Delay.class3.aggregate.max_bytes);
- storeAppendPrintf(sentry, "\t\tRate: %d\n",
- Config.Delay.class3.aggregate.restore_bps);
- storeAppendPrintf(sentry, "\t\tCurrent: %d\n",
- delay_data.class3_aggregate);
- } else {
- storeAppendPrintf(sentry, "\n\tAggregate:\n\tDisabled.\n");
- }
- if (Config.Delay.class3.network.restore_bps != -1) {
- storeAppendPrintf(sentry, "\n\tNetwork:\n");
- storeAppendPrintf(sentry, "\t\tMax: %d\n",
- Config.Delay.class3.network.max_bytes);
- storeAppendPrintf(sentry, "\t\tRate: %d\n",
- Config.Delay.class3.network.restore_bps);
- storeAppendPrintf(sentry, "\t\tCurrent: ");
- for (i = 0;; i++) {
- if (delay_data.class3_network_map[i] == 255)
- break;
- storeAppendPrintf(sentry, "%d:%d ",
- delay_data.class3_network_map[i],
- delay_data.class3_network[i]);
- }
- } else {
- storeAppendPrintf(sentry, "\n\tNetwork:\n\tDisabled.");
- }
- if (Config.Delay.class3.individual.restore_bps != -1) {
- storeAppendPrintf(sentry, "\n\n\tIndividual:\n");
- storeAppendPrintf(sentry, "\t\tMax: %d\n",
- Config.Delay.class3.individual.max_bytes);
- storeAppendPrintf(sentry, "\t\tRate: %d\n",
- Config.Delay.class3.individual.restore_bps);
- for (i = 0;; i++) {
- if (delay_data.class3_network_map[i] == 255)
- break;
- storeAppendPrintf(sentry, "\t\tCurrent [Network %d]: ",
- delay_data.class3_network_map[i]);
- for (j = 0;; j++) {
- if (delay_data.class3_individual_map[i][j] == 255)
+ int individual_restore_bytes, network_restore_bytes;
+ int mpos;
+ unsigned char i, j;
+ /* delaySetSpec may be pointer to partial structure so MUST pass by
+ * reference.
+ */
+ if (rates->aggregate.restore_bps != -1 &&
+ (class3->aggregate += rates->aggregate.restore_bps * incr) >
+ rates->aggregate.max_bytes)
+ class3->aggregate = rates->aggregate.max_bytes;
+ /* the following line deliberately uses &, not &&, in an if statement
+ * to avoid conditional execution
+ */
+ if (((network_restore_bytes = rates->network.restore_bps) == -1) &
+ ((individual_restore_bytes = rates->individual.restore_bps) == -1))
+ return;
+ individual_restore_bytes *= incr;
+ network_restore_bytes *= incr;
+ if (class3->network_255_used)
+ i = 255;
+ else
+ i = 0;
+ for (;;) {
+ if (i != 255 && class3->network_map[i] == 255)
+ return;
+ if (individual_restore_bytes != -incr) {
+ mpos = i << 8;
+ if (class3->individual_255_used[i / 8] & (1 << (i % 8)))
+ j = 255;
+ else
+ j = 0;
+ for (;;) {
+ if (j != 255 && class3->individual_map[i][j] == 255)
+ break;
+ if (class3->individual[mpos] != rates->individual.max_bytes &&
+ (class3->individual[mpos] += individual_restore_bytes) >
+ rates->individual.max_bytes)
+ class3->individual[mpos] = rates->individual.max_bytes;
+ mpos++;
+ if (j == 255)
+ mpos -= 256;
+ if (++j == 255)
break;
- storeAppendPrintf(sentry, "%d:%d ",
- delay_data.class3_individual_map[i][j],
- delay_data.class3_individual[(i << 8) + j]);
}
- storeAppendPrintf(sentry, "\n");
}
- } else {
- storeAppendPrintf(sentry, "\n\n\tIndividual:\n\tDisabled.\n");
+ if (network_restore_bytes != -incr &&
+ class3->network[i] != rates->network.max_bytes &&
+ (class3->network[i] += network_restore_bytes) >
+ rates->network.max_bytes)
+ class3->network[i] = rates->network.max_bytes;
+ if (++i == 255)
+ return;
}
- storeAppendPrintf(sentry, "\n");
}
void
-delayPoolsInit(void)
+delayPoolsUpdate(void *unused)
{
- delay_pools_last_update = getCurrentTime();
- delay_data.class1_aggregate = Config.Delay.class1.aggregate.restore_bps;
- delay_data.class2_aggregate = Config.Delay.class2.aggregate.restore_bps;
- delay_data.class2_individual_map[0] = 255;
- delay_data.class3_aggregate = Config.Delay.class3.aggregate.restore_bps;
- delay_data.class3_network_map[0] = 255;
- cachemgrRegister("delay", "Delay Pool Levels", delayPoolStats, 0, 1);
+ int incr = squid_curtime - delay_pools_last_update;
+ unsigned short i;
+ unsigned char class;
+ if (!Config.Delay.pools)
+ return;
eventAdd("delayPoolsUpdate", delayPoolsUpdate, NULL, 1.0, 1);
+ if (incr < 1)
+ return;
+ delay_pools_last_update = squid_curtime;
+ for (i = 0; i < Config.Delay.pools; i++) {
+ class = Config.Delay.class[i];
+ if (!class)
+ continue;
+ switch (class) {
+ case 1:
+ delayUpdateClass1(delay_data[i].class1, Config.Delay.rates[i], incr);
+ break;
+ case 2:
+ delayUpdateClass2(delay_data[i].class2, Config.Delay.rates[i], incr);
+ break;
+ case 3:
+ delayUpdateClass3(delay_data[i].class3, Config.Delay.rates[i], incr);
+ break;
+ default:
+ assert(0);
+ }
+ }
}
/*
int
delayBytesWanted(delay_id d, int min, int max)
{
- int position = d & 0xFFFF;
- unsigned char class = (d & 0xFF0000) >> 16;
+ unsigned short position = d & 0xFFFF;
+ unsigned short pool = (d >> 16) - 1;
+ unsigned char class = (pool == 0xFFFF) ? 0 : Config.Delay.class[pool];
int nbytes = max;
+
switch (class) {
case 0:
break;
case 1:
- if (Config.Delay.class1.aggregate.restore_bps != -1)
- nbytes = XMIN(nbytes, delay_data.class1_aggregate);
+ if (Config.Delay.rates[pool]->aggregate.restore_bps != -1)
+ nbytes = XMIN(nbytes, delay_data[pool].class1->aggregate);
break;
case 2:
- if (Config.Delay.class2.aggregate.restore_bps != -1)
- nbytes = XMIN(nbytes, delay_data.class2_aggregate);
- if (Config.Delay.class2.individual.restore_bps != -1)
- nbytes = XMIN(nbytes, delay_data.class2_individual[position]);
+ if (Config.Delay.rates[pool]->aggregate.restore_bps != -1)
+ nbytes = XMIN(nbytes, delay_data[pool].class2->aggregate);
+ if (Config.Delay.rates[pool]->individual.restore_bps != -1)
+ nbytes = XMIN(nbytes, delay_data[pool].class2->individual[position]);
break;
case 3:
- if (Config.Delay.class3.aggregate.restore_bps != -1)
- nbytes = XMIN(nbytes, delay_data.class3_aggregate);
- if (Config.Delay.class3.individual.restore_bps != -1)
- nbytes = XMIN(nbytes, delay_data.class3_individual[position]);
- if (Config.Delay.class3.network.restore_bps != -1)
- nbytes = XMIN(nbytes, delay_data.class3_network[position >> 8]);
+ if (Config.Delay.rates[pool]->aggregate.restore_bps != -1)
+ nbytes = XMIN(nbytes, delay_data[pool].class3->aggregate);
+ if (Config.Delay.rates[pool]->individual.restore_bps != -1)
+ nbytes = XMIN(nbytes, delay_data[pool].class3->individual[position]);
+ if (Config.Delay.rates[pool]->network.restore_bps != -1)
+ nbytes = XMIN(nbytes, delay_data[pool].class3->network[position >> 8]);
break;
default:
break;
}
nbytes = XMAX(min, nbytes);
- assert(nbytes >= min);
- assert(nbytes <= max);
return nbytes;
}
void
delayBytesIn(delay_id d, int qty)
{
- int position = d & 0xFFFF;
- unsigned char class = (d & 0xFF0000) >> 16;
- if (class == 0)
+ unsigned short position = d & 0xFFFF;
+ unsigned short pool = (d >> 16) - 1;
+ unsigned char class;
+
+ if (pool == 0xFFFF)
return;
- if (class == 1) {
- delay_data.class1_aggregate -= qty;
+ class = Config.Delay.class[pool];
+ switch (class) {
+ case 1:
+ delay_data[pool].class1->aggregate -= qty;
return;
- }
- if (class == 2) {
- delay_data.class2_aggregate -= qty;
- delay_data.class2_individual[position] -= qty;
+ case 2:
+ delay_data[pool].class2->aggregate -= qty;
+ delay_data[pool].class2->individual[position] -= qty;
return;
- }
- if (class == 3) {
- delay_data.class3_aggregate -= qty;
- delay_data.class3_network[position >> 8] -= qty;
- delay_data.class3_individual[position] -= qty;
+ case 3:
+ delay_data[pool].class3->aggregate -= qty;
+ delay_data[pool].class3->network[position >> 8] -= qty;
+ delay_data[pool].class3->individual[position] -= qty;
return;
}
+ fatalf("delayBytesWanted: Invalid class %d\n", class);
assert(0);
}
sc->delay_id = delay_id;
}
+static void
+delayPoolStatsAg(StoreEntry * sentry, delaySpecSet * rate, int ag)
+{
+ /* note - always pass delaySpecSet's by reference as may be incomplete */
+ if (rate->aggregate.restore_bps == -1) {
+ storeAppendPrintf(sentry, "\tAggregate:\n\t\tDisabled.\n\n");
+ return;
+ }
+ storeAppendPrintf(sentry, "\tAggregate:\n");
+ storeAppendPrintf(sentry, "\t\tMax: %d\n", rate->aggregate.max_bytes);
+ storeAppendPrintf(sentry, "\t\tRestore: %d\n", rate->aggregate.restore_bps);
+ storeAppendPrintf(sentry, "\t\tCurrent: %d\n\n", ag);
+}
+
+static void
+delayPoolStats1(StoreEntry * sentry, unsigned short pool)
+{
+ /* must be a reference only - partially malloc()d struct */
+ delaySpecSet *rate = Config.Delay.rates[pool];
+
+ storeAppendPrintf(sentry, "Pool: %d\n\tClass: 1\n\n", pool + 1);
+ delayPoolStatsAg(sentry, rate, delay_data[pool].class1->aggregate);
+}
+
+static void
+delayPoolStats2(StoreEntry * sentry, unsigned short pool)
+{
+ /* must be a reference only - partially malloc()d struct */
+ delaySpecSet *rate = Config.Delay.rates[pool];
+ class2DelayPool *class2 = delay_data[pool].class2;
+ unsigned char shown = 0, i;
+
+ storeAppendPrintf(sentry, "Pool: %d\n\tClass: 2\n\n", pool + 1);
+ delayPoolStatsAg(sentry, rate, class2->aggregate);
+ if (rate->individual.restore_bps == -1) {
+ storeAppendPrintf(sentry, "\tIndividual:\n\t\tDisabled.\n\n");
+ return;
+ }
+ storeAppendPrintf(sentry, "\tIndividual:\n");
+ storeAppendPrintf(sentry, "\t\tMax: %d\n", rate->individual.max_bytes);
+ storeAppendPrintf(sentry, "\t\tRate: %d\n", rate->individual.restore_bps);
+ storeAppendPrintf(sentry, "\t\tCurrent: ");
+ for (i = 0;; i++) {
+ if (class2->individual_map[i] == 255)
+ break;
+ storeAppendPrintf(sentry, "%d:%d ", class2->individual_map[i],
+ class2->individual[i]);
+ shown = 1;
+ }
+ if (class2->individual_255_used) {
+ storeAppendPrintf(sentry, "%d:%d ", 255, class2->individual[255]);
+ shown = 1;
+ }
+ if (!shown)
+ storeAppendPrintf(sentry, "Not used yet.");
+ storeAppendPrintf(sentry, "\n\n");
+}
+
+static void
+delayPoolStats3(StoreEntry * sentry, unsigned short pool)
+{
+ /* fully malloc()d struct in this case only */
+ delaySpecSet *rate = Config.Delay.rates[pool];
+ class3DelayPool *class3 = delay_data[pool].class3;
+ unsigned char shown = 0, i, j;
+
+ storeAppendPrintf(sentry, "Pool: %d\n\tClass: 3\n\n", pool + 1);
+ delayPoolStatsAg(sentry, rate, class3->aggregate);
+ if (rate->network.restore_bps == -1) {
+ storeAppendPrintf(sentry, "\tNetwork:\n\t\tDisabled.");
+ } else {
+ storeAppendPrintf(sentry, "\tNetwork:\n");
+ storeAppendPrintf(sentry, "\t\tMax: %d\n", rate->network.max_bytes);
+ storeAppendPrintf(sentry, "\t\tRate: %d\n", rate->network.restore_bps);
+ storeAppendPrintf(sentry, "\t\tCurrent: ");
+ for (i = 0;; i++) {
+ if (class3->network_map[i] == 255)
+ break;
+ storeAppendPrintf(sentry, "%d:%d ", class3->network_map[i],
+ class3->network[i]);
+ shown = 1;
+ }
+ if (class3->network_255_used) {
+ storeAppendPrintf(sentry, "%d:%d ", 255, class3->network[255]);
+ shown = 1;
+ }
+ if (!shown)
+ storeAppendPrintf(sentry, "Not used yet.");
+ }
+ storeAppendPrintf(sentry, "\n\n");
+ shown = 0;
+ if (rate->individual.restore_bps == -1) {
+ storeAppendPrintf(sentry, "\tIndividual:\n\t\tDisabled.\n\n");
+ return;
+ }
+ storeAppendPrintf(sentry, "\tIndividual:\n");
+ storeAppendPrintf(sentry, "\t\tMax: %d\n", rate->individual.max_bytes);
+ storeAppendPrintf(sentry, "\t\tRate: %d\n", rate->individual.restore_bps);
+ for (i = 0;; i++) {
+ if (class3->network_map[i] == 255)
+ break;
+ storeAppendPrintf(sentry, "\t\tCurrent [Network %d]: ", class3->network_map[i]);
+ shown = 1;
+ for (j = 0;; j++) {
+ if (class3->individual_map[i][j] == 255)
+ break;
+ storeAppendPrintf(sentry, "%d:%d ", class3->individual_map[i][j],
+ class3->individual[(i << 8) | j]);
+ }
+ if (class3->individual_255_used[i / 8] & (1 << (i % 8))) {
+ storeAppendPrintf(sentry, "%d:%d ", 255, class3->individual[(i << 8) | 255]);
+ }
+ storeAppendPrintf(sentry, "\n");
+ }
+ if (class3->network_255_used) {
+ storeAppendPrintf(sentry, "\t\tCurrent [Network 255]: ");
+ shown = 1;
+ for (j = 0;; j++) {
+ if (class3->individual_map[255][j] == 255)
+ break;
+ storeAppendPrintf(sentry, "%d:%d ", class3->individual_map[255][j],
+ class3->individual[(255 << 8) | j]);
+ }
+ if (class3->individual_255_used[255 / 8] & (1 << (255 % 8))) {
+ storeAppendPrintf(sentry, "%d:%d ", 255, class3->individual[(255 << 8) | 255]);
+ }
+ storeAppendPrintf(sentry, "\n");
+ }
+ if (!shown)
+ storeAppendPrintf(sentry, "\t\tCurrent [All networks]: Not used yet.\n");
+ storeAppendPrintf(sentry, "\n");
+}
+
+static void
+delayPoolStats(StoreEntry * sentry)
+{
+ unsigned short i;
+
+ storeAppendPrintf(sentry, "Delay pools configured: %d\n\n", Config.Delay.pools);
+ for (i = 0; i < Config.Delay.pools; i++) {
+ switch (Config.Delay.class[i]) {
+ case 0:
+ storeAppendPrintf(sentry, "Pool: %d\n\tClass: 0\n\n", i + 1);
+ storeAppendPrintf(sentry, "\tMisconfigured pool.\n\n");
+ break;
+ case 1:
+ delayPoolStats1(sentry, i);
+ break;
+ case 2:
+ delayPoolStats2(sentry, i);
+ break;
+ case 3:
+ delayPoolStats3(sentry, i);
+ break;
+ default:
+ assert(0);
+ }
+ }
+}
+
#endif