]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
luyer's mega delay pools rewrite -- without ugly delayPoolsReconfigure()
authorwessels <>
Sat, 30 Jan 1999 06:39:11 +0000 (06:39 +0000)
committerwessels <>
Sat, 30 Jan 1999 06:39:11 +0000 (06:39 +0000)
13 files changed:
src/HttpRequest.cc
src/cache_cf.cc
src/cf.data.pre
src/client_side.cc
src/delay_pools.cc
src/forward.cc
src/http.cc
src/protos.h
src/ssl.cc
src/structs.h
src/tunnel.cc
src/typedefs.h
src/urn.cc

index 85520965b84338201c503834e66093ca4bc68a71..b38a1bf13ce5597011010ed8429fea45e2068cc0 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpRequest.cc,v 1.22 1999/01/24 03:25:22 wessels Exp $
+ * $Id: HttpRequest.cc,v 1.23 1999/01/29 23:39:11 wessels Exp $
  *
  * DEBUG: section 73    HTTP Request
  * AUTHOR: Duane Wessels
@@ -44,9 +44,6 @@ requestCreate(method_t method, protocol_t protocol, const char *urlpath)
     if (urlpath)
        stringReset(&req->urlpath, urlpath);
     req->max_forwards = -1;
-#if DELAY_POOLS
-    req->delay_id = 0;
-#endif
     httpHeaderInit(&req->header, hoRequest);
     return req;
 }
index f25aca9b71812b3ac7ab66819b0623eb105127de..70db8658174ecfce5e466ae88a8b00042e72c4d4 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $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
@@ -64,6 +64,7 @@ static void configDoConfigure(void);
 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);
@@ -515,6 +516,174 @@ free_address(struct in_addr *addr)
     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)
 {
index eb002c7eb77b723ca85731c66c1fb4f7bd39343a..97d112264297f759cfedc26f06c05a21e91d6c40 100644 (file)
@@ -1,6 +1,6 @@
 
 #
-# $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/
@@ -2484,186 +2484,151 @@ DOC_END
 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
index cb2b96ac4712c9c7df757a3bac1e29781c949416..1f2d4642b55a8e9b6aed7741743a634c660dda82 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.cc,v 1.439 1999/01/29 23:01:04 wessels Exp $
+ * $Id: client_side.cc,v 1.440 1999/01/29 23:39:15 wessels Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -173,7 +173,7 @@ clientCreateStoreEntry(clientHttpRequest * h, method_t m, request_flags flags)
     e = storeCreateEntry(h->uri, h->log_uri, flags, m);
     storeClientListAdd(e, h);
 #if DELAY_POOLS
-    delaySetStoreClient(e, h, h->request->delay_id);
+    delaySetStoreClient(e, h, delayClient(h->request));
 #endif
     storeClientCopy(e, 0, 0, CLIENT_SOCK_SZ,
        memAllocate(MEM_CLIENT_SOCK_BUF), clientSendMoreData, h);
@@ -297,8 +297,8 @@ clientProcessExpired(void *data)
     storeClientListAdd(entry, http);
     storeClientListAdd(http->old_entry, http);
 #if DELAY_POOLS
-    delaySetStoreClient(entry, http, http->request->delay_id);
-    delaySetStoreClient(http->old_entry, http, http->request->delay_id);
+    /* delay_id is already set on original store client */
+    delaySetStoreClient(entry, http, delayClient(http->request));
 #endif
     entry->lastmod = http->old_entry->lastmod;
     debug(33, 5) ("clientProcessExpired: lastmod %d\n", (int) entry->lastmod);
@@ -792,13 +792,6 @@ clientInterpretRequestHeaders(clientHttpRequest * http)
        request->flags.cachable = 1;
     if (clientHierarchical(http))
        request->flags.hierarchical = 1;
-#if DELAY_POOLS
-    if (delayClient(http)) {
-       debug(33, 5) ("clientInterpretRequestHeaders: delay request class %d position %d\n",
-           request->delay_id >> 16,
-           request->delay_id & 0xFFFF);
-    }
-#endif
     debug(33, 5) ("clientInterpretRequestHeaders: REQ_NOCACHE = %s\n",
        request->flags.nocache ? "SET" : "NOT SET");
     debug(33, 5) ("clientInterpretRequestHeaders: REQ_CACHABLE = %s\n",
@@ -1794,7 +1787,7 @@ clientProcessRequest(clientHttpRequest * http)
        storeCreateMemObject(http->entry, http->uri, http->log_uri);
        storeClientListAdd(http->entry, http);
 #if DELAY_POOLS
-       delaySetStoreClient(http->entry, http, http->request->delay_id);
+       delaySetStoreClient(http->entry, http, delayClient(r));
 #endif
        http->entry->refcount++;
        storeClientCopy(http->entry,
index 8a93afbd472f2c68e26a151182bda68bbdc869ed..13d8f4d145c2d2b7eefe81f66e57f27f9079bc6d 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $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);
+       }
+    }
 }
 
 /*
@@ -349,32 +432,34 @@ delayPoolsInit(void)
 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:
@@ -382,8 +467,6 @@ delayBytesWanted(delay_id d, int min, int max)
        break;
     }
     nbytes = XMAX(min, nbytes);
-    assert(nbytes >= min);
-    assert(nbytes <= max);
     return nbytes;
 }
 
@@ -395,25 +478,28 @@ delayBytesWanted(delay_id d, int min, int max)
 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);
 }
 
@@ -463,4 +549,164 @@ delaySetStoreClient(StoreEntry * e, void *data, delay_id delay_id)
     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
index 06eb2b57566b640b176d589287511e92444a048c..0f3b09a2bcaec41968877d200d0cfeabc09dd59f 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: forward.cc,v 1.53 1999/01/29 21:28:12 wessels Exp $
+ * $Id: forward.cc,v 1.54 1999/01/29 23:39:18 wessels Exp $
  *
  * DEBUG: section 17    Request Forwarding
  * AUTHOR: Duane Wessels
@@ -453,14 +453,14 @@ fwdStart(int fd, StoreEntry * e, request_t * r, struct in_addr client_addr,
 }
 
 int
-fwdCheckDeferRead(int fdnotused, void *data)
+fwdCheckDeferRead(int fd, void *data)
 {
     StoreEntry *e = data;
     MemObject *mem = e->mem_obj;
     if (mem == NULL)
        return 0;
 #if DELAY_POOLS
-    if (delayMostBytesWanted(mem, 1) == 0)
+    if (!delayIsNoDelay(fd) && delayMostBytesWanted(mem, 1) == 0)
        return 1;
 #endif
     if (mem->inmem_hi - storeLowestMemReaderOffset(e) < READ_AHEAD_GAP)
index d6c29a968349fdb8ed07b4af546fa7d1b5a45cf0..2279230f5a92156ca95104c61e047eb0d1cc7d56 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: http.cc,v 1.345 1999/01/21 23:58:45 wessels Exp $
+ * $Id: http.cc,v 1.346 1999/01/29 23:39:19 wessels Exp $
  *
  * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
  * AUTHOR: Harvest Derived
@@ -58,9 +58,12 @@ static int httpCachableReply(HttpStateData *);
 static void httpMaybeRemovePublic(StoreEntry *, http_status);
 
 static void
-httpStateFree(int fdnotused, void *data)
+httpStateFree(int fd, void *data)
 {
     HttpStateData *httpState = data;
+#if DELAY_POOLS
+    delayClearNoDelay(fd);
+#endif
     if (httpState == NULL)
        return;
     storeUnlockObject(httpState->entry);
@@ -437,7 +440,13 @@ httpReadReply(int fd, void *data)
     int clen;
     size_t read_sz;
 #if DELAY_POOLS
-    delay_id delay_id = delayMostBytesAllowed(entry->mem_obj);
+    delay_id delay_id;
+
+    /* special "if" only for http (for nodelay proxy conns) */
+    if (delayIsNoDelay(fd))
+       delay_id = 0;
+    else
+       delay_id = delayMostBytesAllowed(entry->mem_obj);
 #endif
     if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
        comm_close(fd);
@@ -539,7 +548,7 @@ httpReadReply(int fd, void *data)
            pconnPush(fd, request->host, request->port);
            fwdComplete(httpState->fwd);
            httpState->fd = -1;
-           httpStateFree(-1, httpState);
+           httpStateFree(fd, httpState);
        } else {
            /* Wait for EOF condition */
            commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
@@ -863,11 +872,9 @@ httpStart(FwdState * fwd)
        if (httpState->peer->options.proxy_only)
            storeReleaseRequest(httpState->entry);
 #if DELAY_POOLS
-       if (httpState->peer->options.no_delay) {
-           proxy_req->delay_id = 0;
-       } else {
-           proxy_req->delay_id = orig_req->delay_id;
-       }
+       assert(delayIsNoDelay(fd) == 0);
+       if (httpState->peer->options.no_delay)
+           delaySetNoDelay(fd);
 #endif
     } else {
        httpState->request = requestLink(orig_req);
index 4087a5e274306a403047339e70fc56bfc94b6a3e..49b8f09aa1ec4c0eb28599ad434b64f542b24663 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: protos.h,v 1.313 1999/01/29 21:28:19 wessels Exp $
+ * $Id: protos.h,v 1.314 1999/01/29 23:39:21 wessels Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -1103,14 +1103,23 @@ extern peer *carpSelectParent(request_t *);
 #endif
 
 #if DELAY_POOLS
-extern int delayClient(clientHttpRequest *);
 extern void delayPoolsInit(void);
+extern void delayInitDelayData(unsigned short pools);
+extern void delayFreeDelayData();
+extern void delayCreateDelayPool(unsigned short pool, u_char class);
+extern void delayInitDelayPool(unsigned short pool, u_char class, delaySpecSet * rates);
+extern void delayFreeDelayPool(unsigned short pool);
+extern void delayPoolsReconfigure();
+extern void delaySetNoDelay(int fd);
+extern void delayClearNoDelay(int fd);
+extern int delayIsNoDelay(int fd);
+extern delay_id delayClient(request_t *);
 extern EVH delayPoolsUpdate;
-extern int delayMostBytesWanted(const MemObject * mem, int max);
-extern int delayMostBytesAllowed(const MemObject * mem);
+extern int delayBytesWanted(delay_id d, int min, int max);
 extern void delayBytesIn(delay_id, int qty);
+extern int delayMostBytesWanted(const MemObject * mem, int max);
+extern delay_id delayMostBytesAllowed(const MemObject * mem);
 extern void delaySetStoreClient(StoreEntry * e, void *data, delay_id delay_id);
-extern int delayBytesWanted(delay_id d, int min, int max);
 #endif
 
 /* helper.c */
index 41ed8ba78d75fe0b79ddd7a254129afb0215d9a8..3830a95ab52d955dc0f3bb77c2c65f93310e7de2 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ssl.cc,v 1.91 1998/12/05 00:54:40 wessels Exp $
+ * $Id: ssl.cc,v 1.92 1999/01/29 23:39:23 wessels Exp $
  *
  * DEBUG: section 26    Secure Sockets Layer Proxy
  * AUTHOR: Duane Wessels
@@ -47,6 +47,9 @@ typedef struct {
     } client, server;
     size_t *size_ptr;          /* pointer to size in an ConnStateData for logging */
     int proxying;
+#if DELAY_POOLS
+    delay_id delay_id;
+#endif
 } SslStateData;
 
 static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n";
@@ -111,8 +114,8 @@ sslStateFree(SslStateData * sslState)
 static int
 sslDeferServerRead(int fdnotused, void *data)
 {
-    request_t *r = data;
-    return delayBytesWanted(r->delay_id, 0, 1) == 0;
+    SslStateData *s = data;
+    return delayBytesWanted(s->delay_id, 0, 1) == 0;
 }
 #endif
 
@@ -154,7 +157,7 @@ sslSetSelect(SslStateData * sslState)
         * no data flowing in the other direction.  Hence the argument of
         * 1 as min.
         */
-       read_sz = delayBytesWanted(sslState->request->delay_id, 1, read_sz);
+       read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz);
 #endif
        if (sslState->server.len < read_sz) {
            /* Have room to read more */
@@ -183,7 +186,7 @@ sslReadServer(int fd, void *data)
        fd, read_sz, sslState->server.len);
     errno = 0;
 #if DELAY_POOLS
-    read_sz = delayBytesWanted(sslState->request->delay_id, 1, read_sz);
+    read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz);
 #endif
     Counter.syscalls.sock.reads++;
     len = read(fd, sslState->server.buf + sslState->server.len, read_sz);
@@ -191,7 +194,7 @@ sslReadServer(int fd, void *data)
     if (len > 0) {
        fd_bytes(fd, len, FD_READ);
 #if DELAY_POOLS
-       delayBytesIn(sslState->request->delay_id, len);
+       delayBytesIn(sslState->delay_id, len);
 #endif
        kb_incr(&Counter.server.all.kbytes_in, len);
        kb_incr(&Counter.server.other.kbytes_in, len);
@@ -391,7 +394,7 @@ sslConnectDone(int fdnotused, int status, void *data)
            sslTimeout,
            sslState);
 #if DELAY_POOLS
-       commSetDefer(sslState->server.fd, sslDeferServerRead, sslState->request);
+       commSetDefer(sslState->server.fd, sslDeferServerRead, sslState);
 #endif
     }
 }
@@ -424,6 +427,9 @@ sslStart(int fd, const char *url, request_t * request, size_t * size_ptr)
     }
     sslState = xcalloc(1, sizeof(SslStateData));
     cbdataAdd(sslState, cbdataXfree, 0);
+#if DELAY_POOLS
+    sslState->delay_id = delayClient(request);
+#endif
     sslState->url = xstrdup(url);
     sslState->request = requestLink(request);
     sslState->size_ptr = size_ptr;
@@ -517,6 +523,11 @@ sslPeerSelectComplete(FwdServer * fs, void *data)
     } else {
        sslState->port = CACHE_HTTP_PORT;
     }
+#if DELAY_POOLS
+    /* no point using the delayIsNoDelay stuff since ssl is nice and simple */
+    if (g && g->options.no_delay)
+       sslState->delay_id = 0;
+#endif
     commConnectStart(sslState->server.fd,
        sslState->host,
        sslState->port,
index 82306569b681a103349fa8ce4bea422964add3b8..274b8afa21efb9966162533073791447a068175b 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.275 1999/01/29 23:01:07 wessels Exp $
+ * $Id: structs.h,v 1.276 1999/01/29 23:39:24 wessels Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -190,11 +190,28 @@ struct _relist {
 };
 
 #if DELAY_POOLS
-struct _delay_spec {
+struct _delaySpec {
     int restore_bps;
     int max_bytes;
 };
 
+/* malloc()'d only as far as used (class * sizeof(delaySpec)!
+ * order of elements very important!
+ */
+struct _delaySpecSet {
+    delaySpec aggregate;
+    delaySpec individual;
+    delaySpec network;
+};
+
+struct _delayConfig {
+    unsigned short pools;
+    unsigned short initial;
+    unsigned char *class;
+    delaySpecSet **rates;
+    acl_access **access;
+};
+
 #endif
 
 struct _SquidConfig {
@@ -403,23 +420,7 @@ struct _SquidConfig {
        size_t limit;
     } MemPools;
 #if DELAY_POOLS
-    struct {
-       struct {
-           struct _delay_spec aggregate;
-           acl_access *access;
-       } class1;
-       struct {
-           struct _delay_spec aggregate;
-           struct _delay_spec individual;
-           acl_access *access;
-       } class2;
-       struct {
-           struct _delay_spec aggregate;
-           struct _delay_spec individual;
-           struct _delay_spec network;
-           acl_access *access;
-       } class3;
-    } Delay;
+    delayConfig Delay;
 #endif
     struct {
        int icp_average;
@@ -1307,9 +1308,6 @@ struct _request_t {
     size_t body_sz;
     HierarchyLogEntry hier;
     err_type err_type;
-#if DELAY_POOLS
-    delay_id delay_id;
-#endif
     char *peer_login;          /* Configured peer login:password */
 };
 
index 87ceffc36ca73438b1fdb4e60bd0c8deeb020c84..6e9938315a33a09391a96fac9350436f8cce3e2f 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: tunnel.cc,v 1.91 1998/12/05 00:54:40 wessels Exp $
+ * $Id: tunnel.cc,v 1.92 1999/01/29 23:39:23 wessels Exp $
  *
  * DEBUG: section 26    Secure Sockets Layer Proxy
  * AUTHOR: Duane Wessels
@@ -47,6 +47,9 @@ typedef struct {
     } client, server;
     size_t *size_ptr;          /* pointer to size in an ConnStateData for logging */
     int proxying;
+#if DELAY_POOLS
+    delay_id delay_id;
+#endif
 } SslStateData;
 
 static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n";
@@ -111,8 +114,8 @@ sslStateFree(SslStateData * sslState)
 static int
 sslDeferServerRead(int fdnotused, void *data)
 {
-    request_t *r = data;
-    return delayBytesWanted(r->delay_id, 0, 1) == 0;
+    SslStateData *s = data;
+    return delayBytesWanted(s->delay_id, 0, 1) == 0;
 }
 #endif
 
@@ -154,7 +157,7 @@ sslSetSelect(SslStateData * sslState)
         * no data flowing in the other direction.  Hence the argument of
         * 1 as min.
         */
-       read_sz = delayBytesWanted(sslState->request->delay_id, 1, read_sz);
+       read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz);
 #endif
        if (sslState->server.len < read_sz) {
            /* Have room to read more */
@@ -183,7 +186,7 @@ sslReadServer(int fd, void *data)
        fd, read_sz, sslState->server.len);
     errno = 0;
 #if DELAY_POOLS
-    read_sz = delayBytesWanted(sslState->request->delay_id, 1, read_sz);
+    read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz);
 #endif
     Counter.syscalls.sock.reads++;
     len = read(fd, sslState->server.buf + sslState->server.len, read_sz);
@@ -191,7 +194,7 @@ sslReadServer(int fd, void *data)
     if (len > 0) {
        fd_bytes(fd, len, FD_READ);
 #if DELAY_POOLS
-       delayBytesIn(sslState->request->delay_id, len);
+       delayBytesIn(sslState->delay_id, len);
 #endif
        kb_incr(&Counter.server.all.kbytes_in, len);
        kb_incr(&Counter.server.other.kbytes_in, len);
@@ -391,7 +394,7 @@ sslConnectDone(int fdnotused, int status, void *data)
            sslTimeout,
            sslState);
 #if DELAY_POOLS
-       commSetDefer(sslState->server.fd, sslDeferServerRead, sslState->request);
+       commSetDefer(sslState->server.fd, sslDeferServerRead, sslState);
 #endif
     }
 }
@@ -424,6 +427,9 @@ sslStart(int fd, const char *url, request_t * request, size_t * size_ptr)
     }
     sslState = xcalloc(1, sizeof(SslStateData));
     cbdataAdd(sslState, cbdataXfree, 0);
+#if DELAY_POOLS
+    sslState->delay_id = delayClient(request);
+#endif
     sslState->url = xstrdup(url);
     sslState->request = requestLink(request);
     sslState->size_ptr = size_ptr;
@@ -517,6 +523,11 @@ sslPeerSelectComplete(FwdServer * fs, void *data)
     } else {
        sslState->port = CACHE_HTTP_PORT;
     }
+#if DELAY_POOLS
+    /* no point using the delayIsNoDelay stuff since ssl is nice and simple */
+    if (g && g->options.no_delay)
+       sslState->delay_id = 0;
+#endif
     commConnectStart(sslState->server.fd,
        sslState->host,
        sslState->port,
index d183022bbc8751856ab904466be9779e3acfd046..872c907a102c888bcac71f91905c86daca3fa660 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: typedefs.h,v 1.85 1999/01/24 02:23:00 wessels Exp $
+ * $Id: typedefs.h,v 1.86 1999/01/29 23:39:25 wessels Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -167,6 +167,12 @@ typedef variable_list *(oid_ParseFn) (variable_list *, snint *);
 typedef struct _snmp_request_t snmp_request_t;
 #endif
 
+#if DELAY_POOLS
+typedef struct _delayConfig delayConfig;
+typedef struct _delaySpecSet delaySpecSet;
+typedef struct _delaySpec delaySpec;
+#endif
+
 /* define AIOCB even without USE_ASYNC_IO */
 typedef void AIOCB(int fd, void *, int aio_return, int aio_errno);
 typedef void CWCB(int fd, char *, size_t size, int flag, void *data);
@@ -232,7 +238,7 @@ typedef char HttpHeaderMask[8];
 typedef void (*ObjPackMethod) (void *obj, Packer * p);
 
 #if DELAY_POOLS
-typedef int delay_id;
+typedef unsigned int delay_id;
 #endif
 
 #if USE_HTCP
index e6405c27f502b15ffe1089a9009d1ea2550e53e7..a059434e5ba6831662689ced793515c2a541866d 100644 (file)
@@ -1,7 +1,7 @@
 
 /*
  *
- * $Id: urn.cc,v 1.51 1999/01/29 21:28:22 wessels Exp $
+ * $Id: urn.cc,v 1.52 1999/01/29 23:39:25 wessels Exp $
  *
  * DEBUG: section 52    URN Parsing
  * AUTHOR: Kostas Anagnostakis
@@ -144,8 +144,7 @@ urnStart(request_t * r, StoreEntry * e)
        storeClientListAdd(urlres_e, urnState);
     }
 #if DELAY_POOLS
-    urlres_r->delay_id = r->delay_id;
-    delaySetStoreClient(urlres_e, urnState, r->delay_id);
+    delaySetStoreClient(urlres_e, urnState, 0);
 #endif
     urnState->urlres_e = urlres_e;
     urnState->urlres_r = requestLink(urlres_r);