3 * $Id: delay_pools.cc,v 1.12 1999/12/30 17:36:30 wessels Exp $
5 * DEBUG: section 77 Delay Pools
6 * AUTHOR: David Luyer <luyer@ucs.uwa.edu.au>
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
41 struct _class1DelayPool
{
45 struct _class2DelayPool
{
47 /* OK: -1 is terminator. individual[255] is always host 255. */
48 /* 255 entries + 1 terminator byte */
49 unsigned char individual_map
[256];
50 unsigned char individual_255_used
;
55 struct _class3DelayPool
{
57 /* OK: -1 is terminator. network[255] is always host 255. */
58 /* 255 entries + 1 terminator byte */
59 unsigned char network_map
[256];
60 unsigned char network_255_used
;
63 /* 256 sets of (255 entries + 1 terminator byte) */
64 unsigned char individual_map
[256][256];
65 /* Pack this into one bit per net */
66 unsigned char individual_255_used
[32];
67 /* largest entry = (255<<8)+255 = 65535 */
68 int individual
[65536];
71 typedef struct _class1DelayPool class1DelayPool
;
72 typedef struct _class2DelayPool class2DelayPool
;
73 typedef struct _class3DelayPool class3DelayPool
;
76 class1DelayPool
*class1
;
77 class2DelayPool
*class2
;
78 class3DelayPool
*class3
;
81 typedef union _delayPool delayPool
;
83 static delayPool
*delay_data
= NULL
;
84 static fd_set delay_no_delay
;
85 static time_t delay_pools_last_update
= 0;
86 static hash_table
*delay_id_ptr_hash
= NULL
;
88 static OBJH delayPoolStats
;
91 delayIdPtrHash(const void *key
, unsigned int n
)
93 /* Hashes actual POINTER VALUE.
94 * Assumes <= 256 hash buckets & even hash size.
95 * Assumes the most variation in pointers to inside
96 * medium size objects occurs in the 2nd and 3rd
97 * least significant bytes.
99 const char *ptr
= (char *) &key
;
100 #if SIZEOF_VOID_P == 4
101 return (ptr
[1] ^ ptr
[2]) & (n
- 1);
102 #elif SIZEOF_VOID_P == 8
104 return (ptr
[5] ^ ptr
[6]) & (n
- 1);
106 return (ptr
[1] ^ ptr
[2]) & (n
- 1);
109 #error What kind of a sick architecture are you on anyway?
114 delayIdPtrHashCmp(const void *a
, const void *b
)
117 * Compare POINTER VALUE.
118 * Note, we can't subtract void pointers, but we don't need
119 * to anyway. All we need is a test for equality.
127 delay_pools_last_update
= getCurrentTime();
128 FD_ZERO(&delay_no_delay
);
129 cachemgrRegister("delay", "Delay Pool Levels", delayPoolStats
, 0, 1);
133 delayInitDelayData(unsigned short pools
)
137 delay_data
= xcalloc(pools
, sizeof(delayPool
));
138 eventAdd("delayPoolsUpdate", delayPoolsUpdate
, NULL
, 1.0, 1);
139 delay_id_ptr_hash
= hash_create(delayIdPtrHashCmp
, 256, delayIdPtrHash
);
143 delayIdZero(void *hlink
)
145 hash_link
*h
= hlink
;
146 delay_id
*id
= (delay_id
*) h
->key
;
152 delayFreeDelayData(void)
154 safe_free(delay_data
);
155 if (!delay_id_ptr_hash
)
157 hashFreeItems(delay_id_ptr_hash
, delayIdZero
);
158 hashFreeMemory(delay_id_ptr_hash
);
159 delay_id_ptr_hash
= NULL
;
163 delayRegisterDelayIdPtr(delay_id
* loc
)
166 if (!delay_id_ptr_hash
)
170 lnk
= xmalloc(sizeof(hash_link
));
171 lnk
->key
= (char *) loc
;
172 hash_join(delay_id_ptr_hash
, lnk
);
176 delayUnregisterDelayIdPtr(delay_id
* loc
)
179 if (!delay_id_ptr_hash
)
182 * If we went through a reconfigure, then all the delay_id's
183 * got set to zero, and they were removed from our hash
188 lnk
= hash_lookup(delay_id_ptr_hash
, loc
);
190 hash_remove_link(delay_id_ptr_hash
, lnk
);
195 delayCreateDelayPool(unsigned short pool
, u_char
class)
199 delay_data
[pool
].class1
= xmalloc(sizeof(class1DelayPool
));
202 delay_data
[pool
].class2
= xmalloc(sizeof(class2DelayPool
));
205 delay_data
[pool
].class3
= xmalloc(sizeof(class3DelayPool
));
213 delayInitDelayPool(unsigned short pool
, u_char
class, delaySpecSet
* rates
)
215 /* delaySetSpec may be pointer to partial structure so MUST pass by
220 delay_data
[pool
].class1
->aggregate
= (rates
->aggregate
.max_bytes
*
221 Config
.Delay
.initial
) / 100;
224 delay_data
[pool
].class2
->aggregate
= (rates
->aggregate
.max_bytes
*
225 Config
.Delay
.initial
) / 100;
226 delay_data
[pool
].class2
->individual_map
[0] = 255;
227 delay_data
[pool
].class2
->individual_255_used
= 0;
230 delay_data
[pool
].class3
->aggregate
= (rates
->aggregate
.max_bytes
*
231 Config
.Delay
.initial
) / 100;
232 delay_data
[pool
].class3
->network_map
[0] = 255;
233 delay_data
[pool
].class3
->network_255_used
= 0;
234 memset(&delay_data
[pool
].class3
->individual_255_used
, '\0',
235 sizeof(delay_data
[pool
].class3
->individual_255_used
));
243 delayFreeDelayPool(unsigned short pool
)
245 /* this is a union - and all free() cares about is the pointer location */
246 safe_free(delay_data
[pool
].class1
);
250 delaySetNoDelay(int fd
)
252 FD_SET(fd
, &delay_no_delay
);
256 delayClearNoDelay(int fd
)
258 FD_CLR(fd
, &delay_no_delay
);
262 delayIsNoDelay(int fd
)
264 return FD_ISSET(fd
, &delay_no_delay
);
268 delayId(unsigned short pool
, unsigned short position
)
270 return (pool
<< 16) | position
;
274 delayClient(request_t
* r
)
280 unsigned short pool
, position
;
281 unsigned char class, net
;
283 memset(&ch
, '\0', sizeof(ch
));
284 ch
.src_addr
= r
->client_addr
;
285 ch
.my_addr
= r
->my_addr
;
286 ch
.my_port
= r
->my_port
;
288 for (pool
= 0; pool
< Config
.Delay
.pools
; pool
++) {
289 if (aclCheckFast(Config
.Delay
.access
[pool
], &ch
))
292 if (pool
== Config
.Delay
.pools
)
293 return delayId(0, 0);
294 class = Config
.Delay
.class[pool
];
296 return delayId(0, 0);
298 return delayId(pool
+ 1, 0);
300 host
= ntohl(ch
.src_addr
.s_addr
) & 0xff;
302 if (!delay_data
[pool
].class2
->individual_255_used
) {
303 delay_data
[pool
].class2
->individual_255_used
= 1;
304 delay_data
[pool
].class2
->individual
[255] =
305 (Config
.Delay
.rates
[pool
]->individual
.max_bytes
*
306 Config
.Delay
.initial
) / 100;
308 return delayId(pool
+ 1, 255);
311 if (delay_data
[pool
].class2
->individual_map
[i
] == host
)
313 if (delay_data
[pool
].class2
->individual_map
[i
] == 255) {
314 delay_data
[pool
].class2
->individual_map
[i
] = host
;
315 delay_data
[pool
].class2
->individual_map
[i
+ 1] = 255;
316 delay_data
[pool
].class2
->individual
[i
] =
317 (Config
.Delay
.rates
[pool
]->individual
.max_bytes
*
318 Config
.Delay
.initial
) / 100;
322 return delayId(pool
+ 1, i
);
325 host
= ntohl(ch
.src_addr
.s_addr
) & 0xffff;
330 if (!delay_data
[pool
].class3
->network_255_used
) {
331 delay_data
[pool
].class3
->network_255_used
= 1;
332 delay_data
[pool
].class3
->network
[255] =
333 (Config
.Delay
.rates
[pool
]->network
.max_bytes
*
334 Config
.Delay
.initial
) / 100;
338 if (delay_data
[pool
].class3
->network_map
[i
] == net
)
340 if (delay_data
[pool
].class3
->network_map
[i
] == 255) {
341 delay_data
[pool
].class3
->network_map
[i
] = net
;
342 delay_data
[pool
].class3
->individual_map
[i
][0] = 255;
343 delay_data
[pool
].class3
->network_map
[i
+ 1] = 255;
344 delay_data
[pool
].class3
->network
[i
] =
345 (Config
.Delay
.rates
[pool
]->network
.max_bytes
*
346 Config
.Delay
.initial
) / 100;
354 if (!(delay_data
[pool
].class3
->individual_255_used
[i
/ 8] & (1 << (i
% 8)))) {
355 delay_data
[pool
].class3
->individual_255_used
[i
/ 8] |= (1 << (i
% 8));
356 delay_data
[pool
].class3
->individual
[position
] =
357 (Config
.Delay
.rates
[pool
]->individual
.max_bytes
*
358 Config
.Delay
.initial
) / 100;
360 return delayId(pool
+ 1, position
);
363 if (delay_data
[pool
].class3
->individual_map
[i
][j
] == host
) {
367 if (delay_data
[pool
].class3
->individual_map
[i
][j
] == 255) {
368 delay_data
[pool
].class3
->individual_map
[i
][j
] = host
;
369 delay_data
[pool
].class3
->individual_map
[i
][j
+ 1] = 255;
370 delay_data
[pool
].class3
->individual
[position
|= j
] =
371 (Config
.Delay
.rates
[pool
]->individual
.max_bytes
*
372 Config
.Delay
.initial
) / 100;
376 return delayId(pool
+ 1, position
);
380 delayUpdateClass1(class1DelayPool
* class1
, delaySpecSet
* rates
, int incr
)
382 /* delaySetSpec may be pointer to partial structure so MUST pass by
385 if (rates
->aggregate
.restore_bps
!= -1 &&
386 (class1
->aggregate
+= rates
->aggregate
.restore_bps
* incr
) >
387 rates
->aggregate
.max_bytes
)
388 class1
->aggregate
= rates
->aggregate
.max_bytes
;
392 delayUpdateClass2(class2DelayPool
* class2
, delaySpecSet
* rates
, int incr
)
396 /* delaySetSpec may be pointer to partial structure so MUST pass by
399 if (rates
->aggregate
.restore_bps
!= -1 &&
400 (class2
->aggregate
+= rates
->aggregate
.restore_bps
* incr
) >
401 rates
->aggregate
.max_bytes
)
402 class2
->aggregate
= rates
->aggregate
.max_bytes
;
403 if ((restore_bytes
= rates
->individual
.restore_bps
) == -1)
405 restore_bytes
*= incr
;
406 if (class2
->individual_255_used
)
411 if (i
!= 255 && class2
->individual_map
[i
] == 255)
413 if (class2
->individual
[i
] != rates
->individual
.max_bytes
&&
414 (class2
->individual
[i
] += restore_bytes
) > rates
->individual
.max_bytes
)
415 class2
->individual
[i
] = rates
->individual
.max_bytes
;
422 delayUpdateClass3(class3DelayPool
* class3
, delaySpecSet
* rates
, int incr
)
424 int individual_restore_bytes
, network_restore_bytes
;
427 /* delaySetSpec may be pointer to partial structure so MUST pass by
430 if (rates
->aggregate
.restore_bps
!= -1 &&
431 (class3
->aggregate
+= rates
->aggregate
.restore_bps
* incr
) >
432 rates
->aggregate
.max_bytes
)
433 class3
->aggregate
= rates
->aggregate
.max_bytes
;
434 /* the following line deliberately uses &, not &&, in an if statement
435 * to avoid conditional execution
437 if (((network_restore_bytes
= rates
->network
.restore_bps
) == -1) &
438 ((individual_restore_bytes
= rates
->individual
.restore_bps
) == -1))
440 individual_restore_bytes
*= incr
;
441 network_restore_bytes
*= incr
;
442 if (class3
->network_255_used
)
447 if (i
!= 255 && class3
->network_map
[i
] == 255)
449 if (individual_restore_bytes
!= -incr
) {
451 if (class3
->individual_255_used
[i
/ 8] & (1 << (i
% 8)))
456 if (j
!= 255 && class3
->individual_map
[i
][j
] == 255)
458 if (class3
->individual
[mpos
] != rates
->individual
.max_bytes
&&
459 (class3
->individual
[mpos
] += individual_restore_bytes
) >
460 rates
->individual
.max_bytes
)
461 class3
->individual
[mpos
] = rates
->individual
.max_bytes
;
469 if (network_restore_bytes
!= -incr
&&
470 class3
->network
[i
] != rates
->network
.max_bytes
&&
471 (class3
->network
[i
] += network_restore_bytes
) >
472 rates
->network
.max_bytes
)
473 class3
->network
[i
] = rates
->network
.max_bytes
;
480 delayPoolsUpdate(void *unused
)
482 int incr
= squid_curtime
- delay_pools_last_update
;
485 if (!Config
.Delay
.pools
)
487 eventAdd("delayPoolsUpdate", delayPoolsUpdate
, NULL
, 1.0, 1);
490 delay_pools_last_update
= squid_curtime
;
491 for (i
= 0; i
< Config
.Delay
.pools
; i
++) {
492 class = Config
.Delay
.class[i
];
497 delayUpdateClass1(delay_data
[i
].class1
, Config
.Delay
.rates
[i
], incr
);
500 delayUpdateClass2(delay_data
[i
].class2
, Config
.Delay
.rates
[i
], incr
);
503 delayUpdateClass3(delay_data
[i
].class3
, Config
.Delay
.rates
[i
], incr
);
512 * this returns the number of bytes the client is permitted. it does not take
513 * into account bytes already buffered - that is up to the caller.
516 delayBytesWanted(delay_id d
, int min
, int max
)
518 unsigned short position
= d
& 0xFFFF;
519 unsigned short pool
= (d
>> 16) - 1;
520 unsigned char class = (pool
== 0xFFFF) ? 0 : Config
.Delay
.class[pool
];
528 if (Config
.Delay
.rates
[pool
]->aggregate
.restore_bps
!= -1)
529 nbytes
= XMIN(nbytes
, delay_data
[pool
].class1
->aggregate
);
533 if (Config
.Delay
.rates
[pool
]->aggregate
.restore_bps
!= -1)
534 nbytes
= XMIN(nbytes
, delay_data
[pool
].class2
->aggregate
);
535 if (Config
.Delay
.rates
[pool
]->individual
.restore_bps
!= -1)
536 nbytes
= XMIN(nbytes
, delay_data
[pool
].class2
->individual
[position
]);
540 if (Config
.Delay
.rates
[pool
]->aggregate
.restore_bps
!= -1)
541 nbytes
= XMIN(nbytes
, delay_data
[pool
].class3
->aggregate
);
542 if (Config
.Delay
.rates
[pool
]->individual
.restore_bps
!= -1)
543 nbytes
= XMIN(nbytes
, delay_data
[pool
].class3
->individual
[position
]);
544 if (Config
.Delay
.rates
[pool
]->network
.restore_bps
!= -1)
545 nbytes
= XMIN(nbytes
, delay_data
[pool
].class3
->network
[position
>> 8]);
549 fatalf("delayBytesWanted: Invalid class %d\n", class);
552 nbytes
= XMAX(min
, nbytes
);
557 * this records actual bytes recieved. always recorded, even if the
558 * class is disabled - it's more efficient to just do it than to do all
562 delayBytesIn(delay_id d
, int qty
)
564 unsigned short position
= d
& 0xFFFF;
565 unsigned short pool
= (d
>> 16) - 1;
570 class = Config
.Delay
.class[pool
];
573 delay_data
[pool
].class1
->aggregate
-= qty
;
576 delay_data
[pool
].class2
->aggregate
-= qty
;
577 delay_data
[pool
].class2
->individual
[position
] -= qty
;
580 delay_data
[pool
].class3
->aggregate
-= qty
;
581 delay_data
[pool
].class3
->network
[position
>> 8] -= qty
;
582 delay_data
[pool
].class3
->individual
[position
] -= qty
;
585 fatalf("delayBytesWanted: Invalid class %d\n", class);
590 delayMostBytesWanted(const MemObject
* mem
, int max
)
595 for (sc
= mem
->clients
; sc
; sc
= sc
->next
) {
596 if (sc
->callback_data
== NULL
) /* open slot */
598 if (sc
->type
!= STORE_MEM_CLIENT
)
600 i
= delayBytesWanted(sc
->delay_id
, i
, max
);
603 return found
? i
: max
;
607 delayMostBytesAllowed(const MemObject
* mem
)
613 for (sc
= mem
->clients
; sc
; sc
= sc
->next
) {
614 if (sc
->callback_data
== NULL
) /* open slot */
616 if (sc
->type
!= STORE_MEM_CLIENT
)
618 j
= delayBytesWanted(sc
->delay_id
, 0, SQUID_TCP_SO_RCVBUF
);
628 delaySetStoreClient(StoreEntry
* e
, void *data
, delay_id delay_id
)
630 store_client
*sc
= storeClientListSearch(e
->mem_obj
, data
);
632 sc
->delay_id
= delay_id
;
633 delayRegisterDelayIdPtr(&sc
->delay_id
);
637 delayPoolStatsAg(StoreEntry
* sentry
, delaySpecSet
* rate
, int ag
)
639 /* note - always pass delaySpecSet's by reference as may be incomplete */
640 if (rate
->aggregate
.restore_bps
== -1) {
641 storeAppendPrintf(sentry
, "\tAggregate:\n\t\tDisabled.\n\n");
644 storeAppendPrintf(sentry
, "\tAggregate:\n");
645 storeAppendPrintf(sentry
, "\t\tMax: %d\n", rate
->aggregate
.max_bytes
);
646 storeAppendPrintf(sentry
, "\t\tRestore: %d\n", rate
->aggregate
.restore_bps
);
647 storeAppendPrintf(sentry
, "\t\tCurrent: %d\n\n", ag
);
651 delayPoolStats1(StoreEntry
* sentry
, unsigned short pool
)
653 /* must be a reference only - partially malloc()d struct */
654 delaySpecSet
*rate
= Config
.Delay
.rates
[pool
];
656 storeAppendPrintf(sentry
, "Pool: %d\n\tClass: 1\n\n", pool
+ 1);
657 delayPoolStatsAg(sentry
, rate
, delay_data
[pool
].class1
->aggregate
);
661 delayPoolStats2(StoreEntry
* sentry
, unsigned short pool
)
663 /* must be a reference only - partially malloc()d struct */
664 delaySpecSet
*rate
= Config
.Delay
.rates
[pool
];
665 class2DelayPool
*class2
= delay_data
[pool
].class2
;
666 unsigned char shown
= 0, i
;
668 storeAppendPrintf(sentry
, "Pool: %d\n\tClass: 2\n\n", pool
+ 1);
669 delayPoolStatsAg(sentry
, rate
, class2
->aggregate
);
670 if (rate
->individual
.restore_bps
== -1) {
671 storeAppendPrintf(sentry
, "\tIndividual:\n\t\tDisabled.\n\n");
674 storeAppendPrintf(sentry
, "\tIndividual:\n");
675 storeAppendPrintf(sentry
, "\t\tMax: %d\n", rate
->individual
.max_bytes
);
676 storeAppendPrintf(sentry
, "\t\tRate: %d\n", rate
->individual
.restore_bps
);
677 storeAppendPrintf(sentry
, "\t\tCurrent: ");
679 if (class2
->individual_map
[i
] == 255)
681 storeAppendPrintf(sentry
, "%d:%d ", class2
->individual_map
[i
],
682 class2
->individual
[i
]);
685 if (class2
->individual_255_used
) {
686 storeAppendPrintf(sentry
, "%d:%d ", 255, class2
->individual
[255]);
690 storeAppendPrintf(sentry
, "Not used yet.");
691 storeAppendPrintf(sentry
, "\n\n");
695 delayPoolStats3(StoreEntry
* sentry
, unsigned short pool
)
697 /* fully malloc()d struct in this case only */
698 delaySpecSet
*rate
= Config
.Delay
.rates
[pool
];
699 class3DelayPool
*class3
= delay_data
[pool
].class3
;
700 unsigned char shown
= 0, i
, j
;
702 storeAppendPrintf(sentry
, "Pool: %d\n\tClass: 3\n\n", pool
+ 1);
703 delayPoolStatsAg(sentry
, rate
, class3
->aggregate
);
704 if (rate
->network
.restore_bps
== -1) {
705 storeAppendPrintf(sentry
, "\tNetwork:\n\t\tDisabled.");
707 storeAppendPrintf(sentry
, "\tNetwork:\n");
708 storeAppendPrintf(sentry
, "\t\tMax: %d\n", rate
->network
.max_bytes
);
709 storeAppendPrintf(sentry
, "\t\tRate: %d\n", rate
->network
.restore_bps
);
710 storeAppendPrintf(sentry
, "\t\tCurrent: ");
712 if (class3
->network_map
[i
] == 255)
714 storeAppendPrintf(sentry
, "%d:%d ", class3
->network_map
[i
],
718 if (class3
->network_255_used
) {
719 storeAppendPrintf(sentry
, "%d:%d ", 255, class3
->network
[255]);
723 storeAppendPrintf(sentry
, "Not used yet.");
725 storeAppendPrintf(sentry
, "\n\n");
727 if (rate
->individual
.restore_bps
== -1) {
728 storeAppendPrintf(sentry
, "\tIndividual:\n\t\tDisabled.\n\n");
731 storeAppendPrintf(sentry
, "\tIndividual:\n");
732 storeAppendPrintf(sentry
, "\t\tMax: %d\n", rate
->individual
.max_bytes
);
733 storeAppendPrintf(sentry
, "\t\tRate: %d\n", rate
->individual
.restore_bps
);
735 if (class3
->network_map
[i
] == 255)
737 storeAppendPrintf(sentry
, "\t\tCurrent [Network %d]: ", class3
->network_map
[i
]);
740 if (class3
->individual_map
[i
][j
] == 255)
742 storeAppendPrintf(sentry
, "%d:%d ", class3
->individual_map
[i
][j
],
743 class3
->individual
[(i
<< 8) | j
]);
745 if (class3
->individual_255_used
[i
/ 8] & (1 << (i
% 8))) {
746 storeAppendPrintf(sentry
, "%d:%d ", 255, class3
->individual
[(i
<< 8) | 255]);
748 storeAppendPrintf(sentry
, "\n");
750 if (class3
->network_255_used
) {
751 storeAppendPrintf(sentry
, "\t\tCurrent [Network 255]: ");
754 if (class3
->individual_map
[255][j
] == 255)
756 storeAppendPrintf(sentry
, "%d:%d ", class3
->individual_map
[255][j
],
757 class3
->individual
[(255 << 8) | j
]);
759 if (class3
->individual_255_used
[255 / 8] & (1 << (255 % 8))) {
760 storeAppendPrintf(sentry
, "%d:%d ", 255, class3
->individual
[(255 << 8) | 255]);
762 storeAppendPrintf(sentry
, "\n");
765 storeAppendPrintf(sentry
, "\t\tCurrent [All networks]: Not used yet.\n");
766 storeAppendPrintf(sentry
, "\n");
770 delayPoolStats(StoreEntry
* sentry
)
774 storeAppendPrintf(sentry
, "Delay pools configured: %d\n\n", Config
.Delay
.pools
);
775 for (i
= 0; i
< Config
.Delay
.pools
; i
++) {
776 switch (Config
.Delay
.class[i
]) {
778 storeAppendPrintf(sentry
, "Pool: %d\n\tClass: 0\n\n", i
+ 1);
779 storeAppendPrintf(sentry
, "\tMisconfigured pool.\n\n");
782 delayPoolStats1(sentry
, i
);
785 delayPoolStats2(sentry
, i
);
788 delayPoolStats3(sentry
, i
);