]> git.ipfire.org Git - thirdparty/squid.git/blob - src/delay_pools.cc
Luyers finished delay pools patch
[thirdparty/squid.git] / src / delay_pools.cc
1
2 /*
3 * $Id: delay_pools.cc,v 1.2 1998/08/14 09:22:34 wessels Exp $
4 *
5 * DEBUG: section 77 Delay Pools
6 * AUTHOR: David Luyer <luyer@ucs.uwa.edu.au>
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
10 *
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.
19 *
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.
24 *
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.
29 *
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.
33 *
34 */
35
36 #include "config.h"
37
38 #if DELAY_POOLS
39 #include "squid.h"
40
41
42 struct _delayData {
43 int class1_aggregate;
44 int class2_aggregate;
45 /* 254 entries + 1 terminator byte */
46 unsigned char class2_individual_map[255];
47 /* 254 entries */
48 int class2_individual[254];
49 int class3_aggregate;
50 /* 255 entries + 1 terminator byte */
51 unsigned char class3_network_map[256];
52 /* 255 entries */
53 int class3_network[255];
54 /* 255 sets of (254 entries + 1 terminator byte) */
55 unsigned char class3_individual_map[255][255];
56 /* largest entry = (254<<8)+253 = 65277 */
57 int class3_individual[65278];
58 };
59
60 static struct _delayData delay_data;
61 static OBJH delayPoolStats;
62 static delay_id delayId(unsigned char class, int position);
63
64 static delay_id
65 delayId(unsigned char class, int position)
66 {
67 assert(class <= 3);
68 return (class << 16) | (position & 0xFFFF);
69 }
70
71 int
72 delayClient(clientHttpRequest * http)
73 {
74 aclCheck_t ch;
75 int i, j;
76 unsigned int host;
77 unsigned char net;
78 unsigned char class = 0;
79 int position = 0;
80 request_t *r = http->request;
81
82 memset(&ch, '\0', sizeof(ch));
83 ch.src_addr = http->conn->peer.sin_addr;
84 ch.request = r;
85 if (aclCheckFast(Config.Delay.class1.access, &ch)) {
86 class = 1;
87 r->delay_id = delayId(class, position);
88 return 1;
89 }
90 if (aclCheckFast(Config.Delay.class2.access, &ch)) {
91 class = 2;
92 host = ntohl(ch.src_addr.s_addr) & 0xff;
93 if (host == 255 || !host) {
94 debug(77, 0) ("ARGH: Delay requested for host %s\n", inet_ntoa(ch.src_addr));
95 class = 0;
96 r->delay_id = delayId(class, position);
97 return 0;
98 }
99 for (i = 0;; i++) {
100 if (delay_data.class2_individual_map[i] == host)
101 break;
102 if (delay_data.class2_individual_map[i] == 255) {
103 delay_data.class2_individual_map[i] = host;
104 delay_data.class2_individual_map[i + 1] = 255;
105 delay_data.class2_individual[i] = Config.Delay.class2.individual.restore_bps;
106 break;
107 }
108 }
109 position = i;
110 r->delay_id = delayId(class, position);
111 return 1;
112 }
113 if (aclCheckFast(Config.Delay.class3.access, &ch)) {
114 class = 3;
115 host = ntohl(ch.src_addr.s_addr) & 0xffff;
116 net = host >> 8;
117 host &= 0xff;
118 if (host == 255 || !host || net == 255) {
119 debug(77, 0) ("ARGH: Delay requested for host %s\n", inet_ntoa(ch.src_addr));
120 class = 0;
121 r->delay_id = delayId(class, position);
122 return 0;
123 }
124 for (i = 0;; i++) {
125 if (delay_data.class3_network_map[i] == net)
126 break;
127 if (delay_data.class3_network_map[i] == 255) {
128 delay_data.class3_network_map[i] = net;
129 delay_data.class3_individual_map[i][0] = 255;
130 delay_data.class3_network_map[i + 1] = 255;
131 delay_data.class3_network[i] = Config.Delay.class3.network.restore_bps;
132 break;
133 }
134 }
135 position = i << 8;
136 for (j = 0;; j++) {
137 if (delay_data.class3_individual_map[i][j] == host) {
138 position |= j;
139 break;
140 }
141 if (delay_data.class3_individual_map[i][j] == 255) {
142 delay_data.class3_individual_map[i][j] = host;
143 delay_data.class3_individual_map[i][j + 1] = 255;
144 delay_data.class3_individual[position |= j] =
145 Config.Delay.class3.individual.restore_bps;
146 break;
147 }
148 }
149 r->delay_id = delayId(class, position);
150 return 1;
151 }
152 class = 0;
153 r->delay_id = delayId(class, position);
154 return 0;
155 }
156
157
158 void
159 delayPoolsUpdate(int incr)
160 {
161 int i;
162 int j;
163 int mpos;
164 int individual_restore_bytes;
165 int network_restore_bytes;
166 /* Increment 3 aggregate pools */
167 if (Config.Delay.class1.aggregate.restore_bps != -1 &&
168 (delay_data.class1_aggregate +=
169 Config.Delay.class1.aggregate.restore_bps * incr) >
170 Config.Delay.class1.aggregate.max_bytes)
171 delay_data.class1_aggregate = Config.Delay.class1.aggregate.max_bytes;
172 if (Config.Delay.class2.aggregate.restore_bps != -1 &&
173 (delay_data.class2_aggregate +=
174 Config.Delay.class2.aggregate.restore_bps * incr) >
175 Config.Delay.class2.aggregate.max_bytes)
176 delay_data.class2_aggregate = Config.Delay.class2.aggregate.max_bytes;
177 if (Config.Delay.class3.aggregate.restore_bps != -1 &&
178 (delay_data.class3_aggregate +=
179 Config.Delay.class3.aggregate.restore_bps * incr) >
180 Config.Delay.class3.aggregate.max_bytes)
181 delay_data.class3_aggregate = Config.Delay.class3.aggregate.max_bytes;
182 /* Increment class 2 individual pools */
183 if ((individual_restore_bytes = Config.Delay.class2.individual.restore_bps) != -1) {
184 individual_restore_bytes *= incr;
185 for (i = 0;; i++) {
186 if (delay_data.class2_individual_map[i] == 255)
187 break;
188 if (delay_data.class2_individual[i] == Config.Delay.class2.individual.max_bytes)
189 continue;
190 if ((delay_data.class2_individual[i] += individual_restore_bytes) >
191 Config.Delay.class2.individual.max_bytes)
192 delay_data.class2_individual[i] = Config.Delay.class2.individual.max_bytes;
193 }
194 }
195 /* Increment class 3 individual and network pools */
196 if ((network_restore_bytes = Config.Delay.class3.network.restore_bps) != -1 ||
197 (individual_restore_bytes = Config.Delay.class3.individual.restore_bps) != -1) {
198 individual_restore_bytes *= incr;
199 network_restore_bytes *= incr;
200 for (i = 0;; i++) {
201 if (delay_data.class3_network_map[i] == 255)
202 break;
203 if (individual_restore_bytes != -incr) {
204 for (j = 0, mpos = (i << 8);; j++, mpos++) {
205 if (delay_data.class3_individual_map[i][j] == 255)
206 break;
207 if (delay_data.class3_individual[mpos] == Config.Delay.class3.individual.max_bytes)
208 continue;
209 if ((delay_data.class3_individual[mpos] += individual_restore_bytes) >
210 Config.Delay.class3.individual.max_bytes)
211 delay_data.class3_individual[mpos] = Config.Delay.class3.individual.max_bytes;
212 }
213 }
214 if (network_restore_bytes == -incr ||
215 delay_data.class3_network[i] == Config.Delay.class3.network.max_bytes)
216 continue;
217 if ((delay_data.class3_network[i] += network_restore_bytes) >
218 Config.Delay.class3.network.max_bytes)
219 delay_data.class3_network[i] = Config.Delay.class3.network.max_bytes;
220 }
221 }
222 }
223
224
225 static void
226 delayPoolStats(StoreEntry * sentry)
227 {
228 int i;
229 int j;
230 storeAppendPrintf(sentry, "Class 1 Delay Pool Statistics:\n");
231 if (Config.Delay.class1.aggregate.restore_bps != -1) {
232 storeAppendPrintf(sentry, "\n\tAggregate:\n");
233 storeAppendPrintf(sentry, "\t\tMax: %d\n",
234 Config.Delay.class1.aggregate.max_bytes);
235 storeAppendPrintf(sentry, "\t\tRate: %d\n",
236 Config.Delay.class1.aggregate.restore_bps);
237 storeAppendPrintf(sentry, "\t\tCurrent: %d\n",
238 delay_data.class1_aggregate);
239 } else {
240 storeAppendPrintf(sentry, "\n\tAggregate:\n\tDisabled.\n");
241 }
242 storeAppendPrintf(sentry, "\nClass 2 Delay Pool Statistics:\n");
243 if (Config.Delay.class2.aggregate.restore_bps != -1) {
244 storeAppendPrintf(sentry, "\n\tAggregate:\n");
245 storeAppendPrintf(sentry, "\t\tMax: %d\n",
246 Config.Delay.class2.aggregate.max_bytes);
247 storeAppendPrintf(sentry, "\t\tRate: %d\n",
248 Config.Delay.class2.aggregate.restore_bps);
249 storeAppendPrintf(sentry, "\t\tCurrent: %d\n",
250 delay_data.class2_aggregate);
251 } else {
252 storeAppendPrintf(sentry, "\n\tAggregate:\n\tDisabled.\n");
253 }
254 if (Config.Delay.class2.individual.restore_bps != -1) {
255 storeAppendPrintf(sentry, "\n\tIndividual:\n");
256 storeAppendPrintf(sentry, "\t\tMax: %d\n",
257 Config.Delay.class2.individual.max_bytes);
258 storeAppendPrintf(sentry, "\t\tRate: %d\n",
259 Config.Delay.class2.individual.restore_bps);
260 storeAppendPrintf(sentry, "\t\tCurrent: ");
261 for (i = 0;; i++) {
262 if (delay_data.class2_individual_map[i] == 255)
263 break;
264 storeAppendPrintf(sentry, "%d:%d ",
265 delay_data.class2_individual_map[i],
266 delay_data.class2_individual[i]);
267 }
268 } else {
269 storeAppendPrintf(sentry, "\n\tIndividual:\n\tDisabled.");
270 }
271 storeAppendPrintf(sentry, "\n\nClass 3 Delay Pool Statistics:\n");
272 if (Config.Delay.class3.aggregate.restore_bps != -1) {
273 storeAppendPrintf(sentry, "\n\tAggregate:\n");
274 storeAppendPrintf(sentry, "\t\tMax: %d\n",
275 Config.Delay.class3.aggregate.max_bytes);
276 storeAppendPrintf(sentry, "\t\tRate: %d\n",
277 Config.Delay.class3.aggregate.restore_bps);
278 storeAppendPrintf(sentry, "\t\tCurrent: %d\n",
279 delay_data.class3_aggregate);
280 } else {
281 storeAppendPrintf(sentry, "\n\tAggregate:\n\tDisabled.\n");
282 }
283 if (Config.Delay.class3.network.restore_bps != -1) {
284 storeAppendPrintf(sentry, "\n\tNetwork:\n");
285 storeAppendPrintf(sentry, "\t\tMax: %d\n",
286 Config.Delay.class3.network.max_bytes);
287 storeAppendPrintf(sentry, "\t\tRate: %d\n",
288 Config.Delay.class3.network.restore_bps);
289 storeAppendPrintf(sentry, "\t\tCurrent: ");
290 for (i = 0;; i++) {
291 if (delay_data.class3_network_map[i] == 255)
292 break;
293 storeAppendPrintf(sentry, "%d:%d ",
294 delay_data.class3_network_map[i],
295 delay_data.class3_network[i]);
296 }
297 } else {
298 storeAppendPrintf(sentry, "\n\tNetwork:\n\tDisabled.");
299 }
300 if (Config.Delay.class3.individual.restore_bps != -1) {
301 storeAppendPrintf(sentry, "\n\n\tIndividual:\n");
302 storeAppendPrintf(sentry, "\t\tMax: %d\n",
303 Config.Delay.class3.individual.max_bytes);
304 storeAppendPrintf(sentry, "\t\tRate: %d\n",
305 Config.Delay.class3.individual.restore_bps);
306 for (i = 0;; i++) {
307 if (delay_data.class3_network_map[i] == 255)
308 break;
309 storeAppendPrintf(sentry, "\t\tCurrent [Network %d]: ",
310 delay_data.class3_network_map[i]);
311 for (j = 0;; j++) {
312 if (delay_data.class3_individual_map[i][j] == 255)
313 break;
314 storeAppendPrintf(sentry, "%d:%d ",
315 delay_data.class3_individual_map[i][j],
316 delay_data.class3_individual[(i << 8) + j]);
317 }
318 storeAppendPrintf(sentry, "\n");
319 }
320 } else {
321 storeAppendPrintf(sentry, "\n\n\tIndividual:\n\tDisabled.\n");
322 }
323 storeAppendPrintf(sentry, "\n");
324 }
325
326 void
327 delayPoolsInit(void)
328 {
329 delay_pools_last_update = getCurrentTime();
330 delay_data.class1_aggregate = Config.Delay.class1.aggregate.restore_bps;
331 delay_data.class2_aggregate = Config.Delay.class2.aggregate.restore_bps;
332 delay_data.class2_individual_map[0] = 255;
333 delay_data.class3_aggregate = Config.Delay.class3.aggregate.restore_bps;
334 delay_data.class3_network_map[0] = 255;
335 cachemgrRegister("delay", "Delay Pool Levels", delayPoolStats, 0, 1);
336 }
337
338 /*
339 * this returns the number of bytes the client is permitted. it does not take
340 * into account bytes already buffered - that is up to the caller.
341 */
342 int
343 delayBytesWanted(delay_id d, int max)
344 {
345 int position = d & 0xFFFF;
346 unsigned char class = (d & 0xFF0000) >> 16;
347 int nbytes = max;
348 switch (class) {
349 case 0:
350 break;
351
352 case 1:
353 if (Config.Delay.class1.aggregate.restore_bps != -1)
354 nbytes = XMIN(nbytes, delay_data.class1_aggregate);
355 break;
356
357 case 2:
358 if (Config.Delay.class2.aggregate.restore_bps != -1)
359 nbytes = XMIN(nbytes, delay_data.class2_aggregate);
360 if (Config.Delay.class2.individual.restore_bps != -1)
361 nbytes = XMIN(nbytes, delay_data.class2_individual[position]);
362 break;
363
364 case 3:
365 if (Config.Delay.class3.aggregate.restore_bps != -1)
366 nbytes = XMIN(nbytes, delay_data.class3_aggregate);
367 if (Config.Delay.class3.individual.restore_bps != -1)
368 nbytes = XMIN(nbytes, delay_data.class3_individual[position]);
369 if (Config.Delay.class3.network.restore_bps != -1)
370 nbytes = XMIN(nbytes, delay_data.class3_network[position >> 8]);
371 break;
372
373 default:
374 fatalf("delayBytesWanted: Invalid class %d\n", class);
375 break;
376 }
377 assert(nbytes > 0);
378 assert(nbytes <= max);
379 return nbytes;
380 }
381
382 /*
383 * this records actual bytes recieved. always recorded, even if the
384 * class is disabled - see above for all the cases which would be needed
385 * to efficiently not record it, so it's just ignored if not wanted.
386 */
387 void
388 delayBytesIn(delay_id d, int qty)
389 {
390 int position = d & 0xFFFF;
391 unsigned char class = (d & 0xFF0000) >> 16;
392 if (class == 0)
393 return;
394 if (class == 1) {
395 delay_data.class1_aggregate -= qty;
396 return;
397 }
398 if (class == 2) {
399 delay_data.class2_aggregate -= qty;
400 delay_data.class3_individual[position] -= qty;
401 return;
402 }
403 if (class == 3) {
404 delay_data.class3_aggregate -= qty;
405 delay_data.class3_network[position >> 8] -= qty;
406 delay_data.class3_individual[position] -= qty;
407 return;
408 }
409 assert(0);
410 }
411
412 int
413 delayMostBytesWanted(const MemObject * mem, int max)
414 {
415 int i = 0;
416 store_client *sc;
417 for (sc = mem->clients; sc; sc = sc->next) {
418 if (sc->callback_data == NULL) /* open slot */
419 continue;
420 if (sc->type != STORE_MEM_CLIENT)
421 continue;
422 i = XMAX(delayBytesWanted(sc->delay_id, max), i);
423 }
424 return i;
425 }
426
427 delay_id
428 delayMostBytesAllowed(const MemObject * mem)
429 {
430 int j;
431 int jmax = 0;
432 store_client *sc;
433 delay_id d = 0;
434 for (sc = mem->clients; sc; sc = sc->next) {
435 if (sc->callback_data == NULL) /* open slot */
436 continue;
437 if (sc->type != STORE_MEM_CLIENT)
438 continue;
439 j = delayBytesWanted(sc->delay_id, SQUID_TCP_SO_RCVBUF);
440 if (j > jmax) {
441 jmax = j;
442 d = sc->delay_id;
443 }
444 }
445 return d;
446 }
447
448 void
449 delaySetStoreClient(StoreEntry * e, void *data, delay_id delay_id)
450 {
451 store_client *sc = storeClientListSearch(e->mem_obj, data);
452 assert(sc != NULL);
453 sc->delay_id = delay_id;
454 }
455
456 #endif