]>
Commit | Line | Data |
---|---|---|
95e36d02 | 1 | |
2 | /* | |
62ee09ca | 3 | * $Id: delay_pools.cc,v 1.46 2006/05/29 00:15:02 robertc Exp $ |
95e36d02 | 4 | * |
5 | * DEBUG: section 77 Delay Pools | |
b67e2c8c | 6 | * AUTHOR: Robert Collins <robertc@squid-cache.org> |
7 | * Based upon original delay pools code by | |
8 | * David Luyer <david@luyer.net> | |
95e36d02 | 9 | * |
2b6662ba | 10 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
95e36d02 | 11 | * ---------------------------------------------------------- |
12 | * | |
2b6662ba | 13 | * Squid is the result of efforts by numerous individuals from |
14 | * the Internet community; see the CONTRIBUTORS file for full | |
15 | * details. Many organizations have provided support for Squid's | |
16 | * development; see the SPONSORS file for full details. Squid is | |
17 | * Copyrighted (C) 2001 by the Regents of the University of | |
18 | * California; see the COPYRIGHT file for full details. Squid | |
19 | * incorporates software developed and/or copyrighted by other | |
20 | * sources; see the CREDITS file for full details. | |
95e36d02 | 21 | * |
22 | * This program is free software; you can redistribute it and/or modify | |
23 | * it under the terms of the GNU General Public License as published by | |
24 | * the Free Software Foundation; either version 2 of the License, or | |
25 | * (at your option) any later version. | |
26 | * | |
27 | * This program is distributed in the hope that it will be useful, | |
28 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
29 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
30 | * GNU General Public License for more details. | |
31 | * | |
32 | * You should have received a copy of the GNU General Public License | |
33 | * along with this program; if not, write to the Free Software | |
34 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. | |
35 | * | |
b67e2c8c | 36 | * |
37 | * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org> | |
95e36d02 | 38 | */ |
39 | ||
40 | #include "config.h" | |
41 | ||
42 | #if DELAY_POOLS | |
43 | #include "squid.h" | |
62ee09ca | 44 | #include "CacheManager.h" |
b67e2c8c | 45 | #include "DelaySpec.h" |
46 | #include "DelayPools.h" | |
fc582e0f | 47 | #include "StoreClient.h" |
01a13aec | 48 | #include "Store.h" |
528b2c61 | 49 | #include "MemObject.h" |
50 | #include "client_side_request.h" | |
a80a77cf | 51 | #include "ConfigParser.h" |
b67e2c8c | 52 | #include "DelayId.h" |
53 | #include "Array.h" | |
54 | #include "SquidString.h" | |
985c86bc | 55 | #include "SquidTime.h" |
b67e2c8c | 56 | #include "CommonPool.h" |
57 | #include "CompositePoolNode.h" | |
58 | #include "DelayPool.h" | |
59 | #include "DelayVector.h" | |
60 | #include "NullDelayId.h" | |
61 | #include "DelayBucket.h" | |
62 | #include "DelayUser.h" | |
1e5562e3 | 63 | #include "DelayTagged.h" |
95e36d02 | 64 | |
b67e2c8c | 65 | long DelayPools::MemoryUsed = 0; |
66 | ||
62e76326 | 67 | class Aggregate : public CompositePoolNode |
68 | { | |
69 | ||
70 | public: | |
b67e2c8c | 71 | typedef RefCount<Aggregate> Pointer; |
72 | void *operator new(size_t); | |
73 | void operator delete (void *); | |
b67e2c8c | 74 | Aggregate(); |
75 | ~Aggregate(); | |
76 | virtual DelaySpec *rate() {return &spec;} | |
62e76326 | 77 | |
b67e2c8c | 78 | virtual DelaySpec const *rate() const {return &spec;} |
62e76326 | 79 | |
b67e2c8c | 80 | virtual void stats(StoreEntry * sentry); |
81 | virtual void dump(StoreEntry *entry) const; | |
82 | virtual void update(int incr); | |
83 | virtual void parse(); | |
62e76326 | 84 | |
1e5562e3 | 85 | virtual DelayIdComposite::Pointer id(CompositeSelectionDetails &); |
62e76326 | 86 | |
87 | private: | |
88 | ||
89 | class AggregateId:public DelayIdComposite | |
90 | { | |
91 | ||
92 | public: | |
93 | void *operator new(size_t); | |
94 | void operator delete (void *); | |
75566ba2 | 95 | AggregateId (RefCount<Aggregate>); |
62e76326 | 96 | virtual int bytesWanted (int min, int max) const; |
97 | virtual void bytesIn(int qty); | |
a46d2c0e | 98 | virtual void delayRead(DeferredRead const &); |
62e76326 | 99 | |
100 | private: | |
75566ba2 | 101 | RefCount<Aggregate> theAggregate; |
b67e2c8c | 102 | }; |
62e76326 | 103 | |
f5e92ca2 | 104 | friend class AggregateId; |
105 | ||
b67e2c8c | 106 | DelayBucket theBucket; |
107 | DelaySpec spec; | |
59715b38 | 108 | }; |
109 | ||
b67e2c8c | 110 | template <class Key, class Value> |
62e76326 | 111 | |
112 | class VectorMap | |
113 | { | |
114 | ||
115 | public: | |
b67e2c8c | 116 | VectorMap(); |
117 | unsigned int size() const; | |
118 | unsigned char findKeyIndex (Key const key) const; | |
119 | bool indexUsed (unsigned char const index) const; | |
120 | unsigned int insert (Key const key); | |
62e76326 | 121 | |
efd900cb | 122 | #define IND_MAP_SZ 256 |
62e76326 | 123 | |
b67e2c8c | 124 | Key key_map[IND_MAP_SZ]; |
125 | Value values[IND_MAP_SZ]; | |
62e76326 | 126 | |
127 | private: | |
b67e2c8c | 128 | unsigned int nextMapPosition; |
129 | }; | |
efd900cb | 130 | |
62e76326 | 131 | class VectorPool : public CompositePoolNode |
132 | { | |
133 | ||
134 | public: | |
b67e2c8c | 135 | typedef RefCount<VectorPool> Pointer; |
136 | virtual void dump(StoreEntry *entry) const; | |
137 | virtual void parse(); | |
138 | virtual void update(int incr); | |
139 | virtual void stats(StoreEntry * sentry); | |
62e76326 | 140 | |
1e5562e3 | 141 | virtual DelayIdComposite::Pointer id(CompositeSelectionDetails &); |
b67e2c8c | 142 | VectorMap<unsigned char, DelayBucket> buckets; |
143 | VectorPool(); | |
144 | ~VectorPool(); | |
62e76326 | 145 | |
146 | protected: | |
b67e2c8c | 147 | bool keyAllocated (unsigned char const key) const; |
148 | virtual DelaySpec *rate() {return &spec;} | |
62e76326 | 149 | |
b67e2c8c | 150 | virtual DelaySpec const *rate() const {return &spec;} |
62e76326 | 151 | |
b67e2c8c | 152 | virtual char const *label() const = 0; |
62e76326 | 153 | |
ddfcbc22 | 154 | virtual unsigned int const makeKey (struct IN_ADDR &src_addr) const = 0; |
b67e2c8c | 155 | |
156 | DelaySpec spec; | |
62e76326 | 157 | |
158 | class Id:public DelayIdComposite | |
159 | { | |
160 | ||
161 | public: | |
162 | void *operator new(size_t); | |
163 | void operator delete (void *); | |
75566ba2 | 164 | Id (RefCount<VectorPool>, int); |
62e76326 | 165 | virtual int bytesWanted (int min, int max) const; |
166 | virtual void bytesIn(int qty); | |
167 | ||
168 | private: | |
75566ba2 | 169 | RefCount<VectorPool> theVector; |
62e76326 | 170 | int theIndex; |
b67e2c8c | 171 | }; |
95e36d02 | 172 | }; |
173 | ||
62e76326 | 174 | class IndividualPool : public VectorPool |
175 | { | |
176 | ||
177 | public: | |
b67e2c8c | 178 | void *operator new(size_t); |
179 | void operator delete (void *); | |
62e76326 | 180 | |
181 | protected: | |
b67e2c8c | 182 | virtual char const *label() const {return "Individual";} |
62e76326 | 183 | |
ddfcbc22 | 184 | virtual unsigned int const makeKey (struct IN_ADDR &src_addr) const; |
b67e2c8c | 185 | |
59715b38 | 186 | }; |
187 | ||
62e76326 | 188 | class ClassCNetPool : public VectorPool |
189 | { | |
190 | ||
191 | public: | |
b67e2c8c | 192 | void *operator new(size_t); |
193 | void operator delete (void *); | |
62e76326 | 194 | |
195 | protected: | |
b67e2c8c | 196 | virtual char const *label() const {return "Network";} |
62e76326 | 197 | |
ddfcbc22 | 198 | virtual unsigned int const makeKey (struct IN_ADDR &src_addr) const; |
b67e2c8c | 199 | }; |
59715b38 | 200 | |
b67e2c8c | 201 | /* don't use remote storage for these */ |
62e76326 | 202 | |
203 | class ClassCBucket | |
204 | { | |
205 | ||
206 | public: | |
b67e2c8c | 207 | bool individualUsed (unsigned int index)const; |
208 | unsigned char findHostMapPosition (unsigned char const host) const; | |
209 | bool individualAllocated (unsigned char host) const; | |
210 | unsigned char hostPosition (DelaySpec &rate, unsigned char const host); | |
211 | void initHostIndex (DelaySpec &rate, unsigned char index, unsigned char host); | |
212 | void update (DelaySpec const &, int incr); | |
213 | void stats(StoreEntry *)const; | |
62e76326 | 214 | |
b67e2c8c | 215 | DelayBucket net; |
216 | VectorMap<unsigned char, DelayBucket> individuals; | |
59715b38 | 217 | }; |
218 | ||
62e76326 | 219 | class ClassCHostPool : public CompositePoolNode |
220 | { | |
221 | ||
222 | public: | |
b67e2c8c | 223 | typedef RefCount<ClassCHostPool> Pointer; |
224 | virtual void dump(StoreEntry *entry) const; | |
225 | virtual void parse(); | |
226 | virtual void update(int incr); | |
227 | virtual void stats(StoreEntry * sentry); | |
62e76326 | 228 | |
1e5562e3 | 229 | virtual DelayIdComposite::Pointer id(CompositeSelectionDetails &); |
b67e2c8c | 230 | ClassCHostPool(); |
231 | ~ClassCHostPool(); | |
62e76326 | 232 | |
233 | protected: | |
b67e2c8c | 234 | bool keyAllocated (unsigned char const key) const; |
235 | virtual DelaySpec *rate() {return &spec;} | |
62e76326 | 236 | |
b67e2c8c | 237 | virtual DelaySpec const *rate() const {return &spec;} |
62e76326 | 238 | |
b67e2c8c | 239 | virtual char const *label() const {return "Individual";} |
62e76326 | 240 | |
ddfcbc22 | 241 | virtual unsigned int const makeKey (struct IN_ADDR &src_addr) const; |
62e76326 | 242 | |
ddfcbc22 | 243 | unsigned char const makeHostKey (struct IN_ADDR &src_addr) const; |
b67e2c8c | 244 | |
245 | DelaySpec spec; | |
246 | VectorMap<unsigned char, ClassCBucket> buckets; | |
62e76326 | 247 | |
0353e724 | 248 | class Id; |
249 | ||
250 | friend class ClassCHostPool::Id; | |
251 | ||
62e76326 | 252 | class Id:public DelayIdComposite |
253 | { | |
254 | ||
255 | public: | |
256 | void *operator new(size_t); | |
257 | void operator delete (void *); | |
75566ba2 | 258 | Id (RefCount<ClassCHostPool>, unsigned char, unsigned char); |
62e76326 | 259 | virtual int bytesWanted (int min, int max) const; |
260 | virtual void bytesIn(int qty); | |
261 | ||
262 | private: | |
75566ba2 | 263 | RefCount<ClassCHostPool> theClassCHost; |
62e76326 | 264 | unsigned char theNet; |
265 | unsigned char theHost; | |
b67e2c8c | 266 | }; |
267 | }; | |
268 | ||
a46d2c0e | 269 | void |
270 | Aggregate::AggregateId::delayRead(DeferredRead const &aRead) | |
271 | { | |
272 | theAggregate->delayRead(aRead); | |
273 | } | |
b67e2c8c | 274 | |
275 | void * | |
276 | CommonPool::operator new(size_t size) | |
277 | { | |
278 | DelayPools::MemoryUsed += sizeof (CommonPool); | |
279 | return ::operator new (size); | |
b6a2f15e | 280 | } |
281 | ||
b67e2c8c | 282 | void |
283 | CommonPool::operator delete (void *address) | |
b6a2f15e | 284 | { |
b67e2c8c | 285 | DelayPools::MemoryUsed -= sizeof (CommonPool); |
286 | ::operator delete (address); | |
b6a2f15e | 287 | } |
288 | ||
b67e2c8c | 289 | CommonPool * |
290 | CommonPool::Factory(unsigned char _class, CompositePoolNode::Pointer& compositeCopy) | |
291 | { | |
292 | CommonPool *result = new CommonPool; | |
62e76326 | 293 | |
b67e2c8c | 294 | switch (_class) { |
62e76326 | 295 | |
296 | case 0: | |
297 | break; | |
298 | ||
299 | case 1: | |
300 | compositeCopy = new Aggregate; | |
301 | result->typeLabel = "1"; | |
302 | break; | |
303 | ||
304 | case 2: | |
305 | result->typeLabel = "2"; | |
306 | { | |
307 | DelayVector::Pointer temp = new DelayVector; | |
308 | compositeCopy = temp.getRaw(); | |
309 | temp->push_back (new Aggregate); | |
310 | temp->push_back(new IndividualPool); | |
311 | } | |
312 | ||
313 | break; | |
314 | ||
315 | case 3: | |
316 | result->typeLabel = "3"; | |
317 | { | |
318 | DelayVector::Pointer temp = new DelayVector; | |
319 | compositeCopy = temp.getRaw(); | |
320 | temp->push_back (new Aggregate); | |
321 | temp->push_back (new ClassCNetPool); | |
322 | temp->push_back (new ClassCHostPool); | |
323 | } | |
324 | ||
325 | break; | |
326 | ||
327 | case 4: | |
328 | result->typeLabel = "4"; | |
329 | { | |
330 | DelayVector::Pointer temp = new DelayVector; | |
331 | compositeCopy = temp.getRaw(); | |
332 | temp->push_back (new Aggregate); | |
333 | temp->push_back (new ClassCNetPool); | |
334 | temp->push_back (new ClassCHostPool); | |
335 | temp->push_back (new DelayUser); | |
336 | } | |
337 | ||
338 | break; | |
339 | ||
1e5562e3 | 340 | case 5: |
341 | result->typeLabel = "5"; | |
342 | compositeCopy = new DelayTagged; | |
343 | break; | |
344 | ||
62e76326 | 345 | default: |
b67e2c8c | 346 | fatal ("unknown delay pool class"); |
62e76326 | 347 | return NULL; |
b67e2c8c | 348 | }; |
349 | ||
350 | return result; | |
351 | } | |
352 | ||
62e76326 | 353 | CommonPool::CommonPool() |
354 | {} | |
59715b38 | 355 | |
356 | void | |
b67e2c8c | 357 | ClassCBucket::update (DelaySpec const &rate, int incr) |
59715b38 | 358 | { |
b67e2c8c | 359 | /* If we aren't active, don't try to update us ! */ |
360 | assert (rate.restore_bps != -1); | |
361 | ||
362 | for (unsigned char j = 0; j < individuals.size(); ++j) | |
62e76326 | 363 | individuals.values[j].update (rate, incr); |
b67e2c8c | 364 | } |
365 | ||
366 | void | |
367 | ClassCBucket::stats(StoreEntry *sentry)const | |
368 | { | |
369 | for (unsigned int j = 0; j < individuals.size(); ++j) { | |
62e76326 | 370 | assert (individualUsed (j)); |
371 | storeAppendPrintf(sentry, " %d:",individuals.key_map[j]); | |
372 | individuals.values[j].stats (sentry); | |
b67e2c8c | 373 | } |
374 | } | |
375 | ||
376 | unsigned char | |
377 | ClassCBucket::findHostMapPosition (unsigned char const host) const | |
378 | { | |
379 | return individuals.findKeyIndex(host); | |
380 | } | |
381 | ||
382 | bool | |
383 | ClassCBucket::individualUsed (unsigned int index)const | |
384 | { | |
385 | return individuals.indexUsed(index); | |
386 | } | |
387 | ||
388 | bool | |
389 | ClassCBucket::individualAllocated (unsigned char host) const | |
390 | { | |
391 | return individualUsed(findHostMapPosition (host)); | |
b6a2f15e | 392 | } |
393 | ||
b67e2c8c | 394 | unsigned char |
395 | ClassCBucket::hostPosition (DelaySpec &rate, unsigned char const host) | |
b6a2f15e | 396 | { |
b67e2c8c | 397 | if (individualAllocated (host)) |
62e76326 | 398 | return findHostMapPosition(host); |
b67e2c8c | 399 | |
400 | assert (!individualUsed (findHostMapPosition(host))); | |
62e76326 | 401 | |
b67e2c8c | 402 | unsigned char result = findHostMapPosition(host); |
62e76326 | 403 | |
b67e2c8c | 404 | initHostIndex (rate, result, host); |
62e76326 | 405 | |
b67e2c8c | 406 | return result; |
59715b38 | 407 | } |
408 | ||
409 | void | |
b67e2c8c | 410 | ClassCBucket::initHostIndex (DelaySpec &rate, unsigned char index, unsigned char host) |
59715b38 | 411 | { |
b67e2c8c | 412 | assert (!individualUsed(index)); |
62e76326 | 413 | |
b67e2c8c | 414 | unsigned char const newIndex = individuals.insert (host); |
415 | ||
416 | /* give the bucket a default value */ | |
417 | individuals.values[newIndex].init (rate); | |
418 | } | |
419 | ||
420 | void * | |
421 | CompositePoolNode::operator new(size_t size) | |
422 | { | |
423 | DelayPools::MemoryUsed += sizeof (CompositePoolNode); | |
424 | return ::operator new (size); | |
b6a2f15e | 425 | } |
426 | ||
427 | void | |
b67e2c8c | 428 | CompositePoolNode::operator delete (void *address) |
b6a2f15e | 429 | { |
b67e2c8c | 430 | DelayPools::MemoryUsed -= sizeof (CompositePoolNode); |
431 | ::operator delete (address); | |
b6a2f15e | 432 | } |
433 | ||
b67e2c8c | 434 | void * |
435 | Aggregate::operator new(size_t size) | |
436 | { | |
437 | DelayPools::MemoryUsed += sizeof (Aggregate); | |
438 | return ::operator new (size); | |
59715b38 | 439 | } |
440 | ||
441 | void | |
b67e2c8c | 442 | Aggregate::operator delete (void *address) |
59715b38 | 443 | { |
b67e2c8c | 444 | DelayPools::MemoryUsed -= sizeof (Aggregate); |
445 | ::operator delete (address); | |
59715b38 | 446 | } |
447 | ||
b67e2c8c | 448 | Aggregate::Aggregate() |
449 | { | |
450 | theBucket.init (*rate()); | |
451 | DelayPools::registerForUpdates (this); | |
452 | } | |
453 | ||
454 | Aggregate::~Aggregate() | |
455 | { | |
456 | DelayPools::deregisterForUpdates (this); | |
59715b38 | 457 | } |
458 | ||
459 | void | |
b67e2c8c | 460 | Aggregate::stats(StoreEntry * sentry) |
59715b38 | 461 | { |
b67e2c8c | 462 | rate()->stats (sentry, "Aggregate"); |
62e76326 | 463 | |
b67e2c8c | 464 | if (rate()->restore_bps == -1) |
62e76326 | 465 | return; |
466 | ||
b67e2c8c | 467 | storeAppendPrintf(sentry, "\t\tCurrent: "); |
62e76326 | 468 | |
b67e2c8c | 469 | theBucket.stats(sentry); |
62e76326 | 470 | |
b67e2c8c | 471 | storeAppendPrintf(sentry, "\n\n"); |
59715b38 | 472 | } |
473 | ||
474 | void | |
b67e2c8c | 475 | Aggregate::dump(StoreEntry *entry) const |
59715b38 | 476 | { |
b67e2c8c | 477 | rate()->dump (entry); |
59715b38 | 478 | } |
479 | ||
480 | void | |
b67e2c8c | 481 | Aggregate::update(int incr) |
59715b38 | 482 | { |
b67e2c8c | 483 | theBucket.update(*rate(), incr); |
a46d2c0e | 484 | kickReads(); |
447e176b | 485 | } |
95e36d02 | 486 | |
b67e2c8c | 487 | void |
488 | Aggregate::parse() | |
59715b38 | 489 | { |
b67e2c8c | 490 | rate()->parse(); |
59715b38 | 491 | } |
492 | ||
b67e2c8c | 493 | DelayIdComposite::Pointer |
62e76326 | 494 | |
1e5562e3 | 495 | Aggregate::id(CompositeSelectionDetails &details) |
59715b38 | 496 | { |
b67e2c8c | 497 | if (rate()->restore_bps != -1) |
62e76326 | 498 | return new AggregateId (this); |
b67e2c8c | 499 | else |
62e76326 | 500 | return new NullDelayId; |
59715b38 | 501 | } |
502 | ||
b67e2c8c | 503 | void * |
504 | Aggregate::AggregateId::operator new(size_t size) | |
95e36d02 | 505 | { |
b67e2c8c | 506 | DelayPools::MemoryUsed += sizeof (AggregateId); |
507 | return ::operator new (size); | |
95e36d02 | 508 | } |
509 | ||
b67e2c8c | 510 | void |
511 | Aggregate::AggregateId::operator delete (void *address) | |
512 | { | |
513 | DelayPools::MemoryUsed -= sizeof (AggregateId); | |
514 | ::operator delete (address); | |
95e36d02 | 515 | } |
516 | ||
75566ba2 | 517 | Aggregate::AggregateId::AggregateId(RefCount<Aggregate> anAggregate) : theAggregate(anAggregate) |
62e76326 | 518 | {} |
95e36d02 | 519 | |
447e176b | 520 | int |
b67e2c8c | 521 | Aggregate::AggregateId::bytesWanted (int min, int max) const |
447e176b | 522 | { |
b67e2c8c | 523 | return theAggregate->theBucket.bytesWanted(min, max); |
524 | } | |
59715b38 | 525 | |
b67e2c8c | 526 | void |
527 | Aggregate::AggregateId::bytesIn(int qty) | |
528 | { | |
529 | theAggregate->theBucket.bytesIn(qty); | |
a46d2c0e | 530 | theAggregate->kickReads(); |
b67e2c8c | 531 | } |
447e176b | 532 | |
b67e2c8c | 533 | DelayPool *DelayPools::delay_data = NULL; |
b67e2c8c | 534 | time_t DelayPools::LastUpdate = 0; |
535 | unsigned short DelayPools::pools_ (0); | |
447e176b | 536 | |
b67e2c8c | 537 | void |
538 | DelayPools::Init() | |
539 | { | |
540 | LastUpdate = getCurrentTime(); | |
62ee09ca | 541 | } |
542 | ||
543 | void | |
544 | DelayPools::RegisterWithCacheManager(CacheManager & manager) | |
545 | { | |
546 | manager.registerAction("delay", "Delay Pool Levels", Stats, 0, 1); | |
b67e2c8c | 547 | } |
447e176b | 548 | |
b67e2c8c | 549 | void |
550 | DelayPools::InitDelayData() | |
551 | { | |
552 | if (!pools()) | |
62e76326 | 553 | return; |
554 | ||
b67e2c8c | 555 | DelayPools::delay_data = new DelayPool[pools()]; |
62e76326 | 556 | |
b67e2c8c | 557 | DelayPools::MemoryUsed += pools() * sizeof(DelayPool); |
62e76326 | 558 | |
b67e2c8c | 559 | eventAdd("DelayPools::Update", DelayPools::Update, NULL, 1.0, 1); |
560 | } | |
447e176b | 561 | |
b67e2c8c | 562 | void |
563 | DelayPools::FreeDelayData() | |
564 | { | |
dbdd8f13 | 565 | eventDelete(DelayPools::Update, NULL); |
b67e2c8c | 566 | delete[] DelayPools::delay_data; |
567 | DelayPools::MemoryUsed -= pools() * sizeof(*DelayPools::delay_data); | |
568 | pools_ = 0; | |
447e176b | 569 | } |
570 | ||
b67e2c8c | 571 | void |
572 | DelayPools::Update(void *unused) | |
573 | { | |
574 | if (!pools()) | |
62e76326 | 575 | return; |
576 | ||
b67e2c8c | 577 | eventAdd("DelayPools::Update", Update, NULL, 1.0, 1); |
62e76326 | 578 | |
b67e2c8c | 579 | int incr = squid_curtime - LastUpdate; |
62e76326 | 580 | |
b67e2c8c | 581 | if (incr < 1) |
62e76326 | 582 | return; |
583 | ||
b67e2c8c | 584 | LastUpdate = squid_curtime; |
62e76326 | 585 | |
b67e2c8c | 586 | Vector<Updateable *>::iterator pos = toUpdate.begin(); |
62e76326 | 587 | |
b67e2c8c | 588 | while (pos != toUpdate.end()) { |
62e76326 | 589 | (*pos)->update(incr); |
590 | ++pos; | |
447e176b | 591 | } |
447e176b | 592 | } |
593 | ||
b67e2c8c | 594 | void |
595 | DelayPools::registerForUpdates(Updateable *anObject) | |
596 | { | |
597 | /* Assume no doubles */ | |
598 | toUpdate.push_back(anObject); | |
599 | } | |
600 | ||
601 | void | |
602 | DelayPools::deregisterForUpdates (Updateable *anObject) | |
603 | { | |
604 | Vector<Updateable *>::iterator pos = toUpdate.begin(); | |
62e76326 | 605 | |
b67e2c8c | 606 | while (pos != toUpdate.end() && *pos != anObject) { |
62e76326 | 607 | ++pos; |
447e176b | 608 | } |
62e76326 | 609 | |
b67e2c8c | 610 | if (pos != toUpdate.end()) { |
62e76326 | 611 | /* move all objects down one */ |
612 | Vector<Updateable *>::iterator temp = pos; | |
613 | ++pos; | |
614 | ||
615 | while (pos != toUpdate.end()) { | |
616 | *temp = *pos; | |
617 | ++temp; | |
618 | ++pos; | |
619 | } | |
620 | ||
621 | toUpdate.pop_back(); | |
447e176b | 622 | } |
447e176b | 623 | } |
624 | ||
b67e2c8c | 625 | Vector<Updateable *> DelayPools::toUpdate; |
626 | ||
447e176b | 627 | void |
b67e2c8c | 628 | DelayPools::Stats(StoreEntry * sentry) |
447e176b | 629 | { |
b67e2c8c | 630 | unsigned short i; |
631 | ||
632 | storeAppendPrintf(sentry, "Delay pools configured: %d\n\n", DelayPools::pools()); | |
62e76326 | 633 | |
b67e2c8c | 634 | for (i = 0; i < DelayPools::pools(); ++i) { |
62e76326 | 635 | if (DelayPools::delay_data[i].theComposite().getRaw()) { |
636 | storeAppendPrintf(sentry, "Pool: %d\n\tClass: %s\n\n", i + 1, DelayPools::delay_data[i].pool->theClassTypeLabel()); | |
637 | DelayPools::delay_data[i].theComposite()->stats (sentry); | |
638 | } else | |
639 | storeAppendPrintf(sentry, "\tMisconfigured pool.\n\n"); | |
b67e2c8c | 640 | } |
62e76326 | 641 | |
b67e2c8c | 642 | storeAppendPrintf(sentry, "Memory Used: %d bytes\n", (int) DelayPools::MemoryUsed); |
447e176b | 643 | } |
644 | ||
b67e2c8c | 645 | void |
646 | DelayPools::FreePools() | |
59715b38 | 647 | { |
b67e2c8c | 648 | if (!DelayPools::pools()) |
62e76326 | 649 | return; |
650 | ||
b67e2c8c | 651 | FreeDelayData(); |
652 | } | |
653 | ||
654 | unsigned short | |
62e76326 | 655 | DelayPools::pools() |
b67e2c8c | 656 | { |
657 | return pools_; | |
658 | } | |
659 | ||
660 | void | |
661 | DelayPools::pools (u_short newPools) | |
662 | { | |
663 | if (pools()) { | |
62e76326 | 664 | debug(3, 0) ("parse_delay_pool_count: multiple delay_pools lines, aborting all previous delay_pools config\n"); |
665 | FreePools(); | |
59715b38 | 666 | } |
62e76326 | 667 | |
b67e2c8c | 668 | pools_ = newPools; |
62e76326 | 669 | |
b67e2c8c | 670 | if (pools()) |
62e76326 | 671 | InitDelayData(); |
b67e2c8c | 672 | } |
673 | ||
674 | template <class Key, class Value> | |
675 | VectorMap<Key,Value>::VectorMap() : nextMapPosition(0) | |
62e76326 | 676 | {} |
b67e2c8c | 677 | |
678 | template <class Key, class Value> | |
62e76326 | 679 | unsigned int |
b67e2c8c | 680 | VectorMap<Key,Value>::size() const |
681 | { | |
682 | return nextMapPosition; | |
683 | } | |
62e76326 | 684 | |
b67e2c8c | 685 | template <class Key, class Value> |
686 | unsigned int | |
687 | VectorMap<Key,Value>::insert (Key const key) | |
688 | { | |
689 | unsigned char index = findKeyIndex (key); | |
690 | assert (!indexUsed(index)); | |
691 | ||
692 | key_map[index] = key; | |
693 | ||
694 | ++nextMapPosition; | |
695 | ||
696 | return index; | |
697 | } | |
698 | ||
699 | void * | |
700 | IndividualPool::operator new(size_t size) | |
701 | { | |
702 | DelayPools::MemoryUsed += sizeof (IndividualPool); | |
703 | return ::operator new (size); | |
704 | } | |
705 | ||
706 | void | |
707 | IndividualPool::operator delete (void *address) | |
708 | { | |
709 | DelayPools::MemoryUsed -= sizeof (IndividualPool); | |
710 | ::operator delete (address); | |
59715b38 | 711 | } |
712 | ||
b67e2c8c | 713 | VectorPool::VectorPool() |
714 | { | |
715 | DelayPools::registerForUpdates (this); | |
59715b38 | 716 | } |
717 | ||
b67e2c8c | 718 | VectorPool::~VectorPool() |
59715b38 | 719 | { |
b67e2c8c | 720 | DelayPools::deregisterForUpdates (this); |
721 | } | |
59715b38 | 722 | |
b67e2c8c | 723 | void |
724 | VectorPool::stats(StoreEntry * sentry) | |
725 | { | |
726 | rate()->stats (sentry, label()); | |
62e76326 | 727 | |
b67e2c8c | 728 | if (rate()->restore_bps == -1) { |
62e76326 | 729 | storeAppendPrintf(sentry, "\n\n"); |
730 | return; | |
59715b38 | 731 | } |
62e76326 | 732 | |
b67e2c8c | 733 | storeAppendPrintf(sentry, "\t\tCurrent:"); |
62e76326 | 734 | |
b67e2c8c | 735 | for (unsigned int i = 0; i < buckets.size(); i++) { |
62e76326 | 736 | storeAppendPrintf(sentry, " %d:", buckets.key_map[i]); |
737 | buckets.values[i].stats(sentry); | |
59715b38 | 738 | } |
62e76326 | 739 | |
b67e2c8c | 740 | if (!buckets.size()) |
62e76326 | 741 | storeAppendPrintf(sentry, " Not used yet."); |
742 | ||
59715b38 | 743 | storeAppendPrintf(sentry, "\n\n"); |
744 | } | |
745 | ||
b67e2c8c | 746 | void |
747 | VectorPool::dump(StoreEntry *entry) const | |
748 | { | |
749 | rate()->dump (entry); | |
750 | } | |
751 | ||
752 | void | |
753 | VectorPool::update(int incr) | |
754 | { | |
755 | if (rate()->restore_bps == -1) | |
62e76326 | 756 | return; |
757 | ||
b67e2c8c | 758 | for (unsigned int i = 0; i< buckets.size(); ++i) |
62e76326 | 759 | buckets.values[i].update (*rate(), incr); |
b67e2c8c | 760 | } |
761 | ||
762 | void | |
763 | VectorPool::parse() | |
764 | { | |
765 | rate()->parse(); | |
766 | } | |
767 | ||
768 | bool | |
769 | VectorPool::keyAllocated (unsigned char const key) const | |
770 | { | |
771 | return buckets.indexUsed(buckets.findKeyIndex (key)); | |
772 | } | |
773 | ||
774 | template <class Key, class Value> | |
775 | bool | |
776 | VectorMap<Key,Value>::indexUsed (unsigned char const index) const | |
777 | { | |
b67e2c8c | 778 | return index < size(); |
779 | } | |
780 | ||
781 | /* returns the used position, or the position to allocate */ | |
782 | template <class Key, class Value> | |
783 | unsigned char | |
784 | VectorMap<Key,Value>::findKeyIndex (Key const key) const | |
785 | { | |
786 | for (unsigned int index = 0; index < size(); ++index) { | |
62e76326 | 787 | assert (indexUsed (index)); |
788 | ||
789 | if (key_map[index] == key) | |
790 | return index; | |
59715b38 | 791 | } |
62e76326 | 792 | |
b67e2c8c | 793 | /* not in map */ |
794 | return size(); | |
795 | } | |
796 | ||
797 | DelayIdComposite::Pointer | |
62e76326 | 798 | |
1e5562e3 | 799 | VectorPool::id(CompositeSelectionDetails &details) |
b67e2c8c | 800 | { |
801 | if (rate()->restore_bps == -1) | |
62e76326 | 802 | return new NullDelayId; |
b67e2c8c | 803 | |
1e5562e3 | 804 | unsigned int key = makeKey (details.src_addr); |
b67e2c8c | 805 | |
806 | if (keyAllocated (key)) | |
62e76326 | 807 | return new Id (this, buckets.findKeyIndex(key)); |
808 | ||
b67e2c8c | 809 | unsigned char const resultIndex = buckets.insert(key); |
62e76326 | 810 | |
b67e2c8c | 811 | buckets.values[resultIndex].init (*rate()); |
62e76326 | 812 | |
b67e2c8c | 813 | return new Id(this, resultIndex); |
814 | } | |
815 | ||
816 | void * | |
817 | VectorPool::Id::operator new(size_t size) | |
818 | { | |
819 | DelayPools::MemoryUsed += sizeof (Id); | |
820 | return ::operator new (size); | |
821 | } | |
822 | ||
823 | void | |
824 | VectorPool::Id::operator delete (void *address) | |
825 | { | |
826 | DelayPools::MemoryUsed -= sizeof (Id); | |
827 | ::operator delete (address); | |
828 | } | |
829 | ||
b67e2c8c | 830 | VectorPool::Id::Id (VectorPool::Pointer aPool, int anIndex) : theVector (aPool), theIndex (anIndex) |
62e76326 | 831 | {} |
b67e2c8c | 832 | |
833 | int | |
834 | VectorPool::Id::bytesWanted (int min, int max) const | |
835 | { | |
836 | return theVector->buckets.values[theIndex].bytesWanted (min, max); | |
837 | } | |
838 | ||
839 | void | |
840 | VectorPool::Id::bytesIn(int qty) | |
841 | { | |
842 | theVector->buckets.values[theIndex].bytesIn (qty); | |
843 | } | |
844 | ||
a46d2c0e | 845 | |
b67e2c8c | 846 | unsigned int const |
62e76326 | 847 | |
ddfcbc22 | 848 | IndividualPool::makeKey (struct IN_ADDR &src_addr) const |
b67e2c8c | 849 | { |
850 | unsigned int host; | |
851 | host = ntohl(src_addr.s_addr) & 0xff; | |
852 | return host; | |
853 | } | |
854 | ||
855 | void * | |
856 | ClassCNetPool::operator new(size_t size) | |
857 | { | |
858 | DelayPools::MemoryUsed += sizeof (ClassCNetPool); | |
859 | return ::operator new (size); | |
860 | } | |
861 | ||
862 | void | |
863 | ClassCNetPool::operator delete (void *address) | |
864 | { | |
865 | DelayPools::MemoryUsed -= sizeof (ClassCNetPool); | |
866 | ::operator delete (address); | |
867 | } | |
868 | ||
b67e2c8c | 869 | unsigned int const |
62e76326 | 870 | |
ddfcbc22 | 871 | ClassCNetPool::makeKey (struct IN_ADDR &src_addr) const |
b67e2c8c | 872 | { |
873 | unsigned int net; | |
874 | net = (ntohl(src_addr.s_addr) >> 8) & 0xff; | |
875 | return net; | |
876 | } | |
877 | ||
878 | ||
879 | ClassCHostPool::ClassCHostPool() | |
880 | { | |
881 | DelayPools::registerForUpdates (this); | |
882 | } | |
883 | ||
884 | ClassCHostPool::~ClassCHostPool() | |
885 | { | |
886 | DelayPools::deregisterForUpdates (this); | |
887 | } | |
888 | ||
889 | void | |
890 | ClassCHostPool::stats(StoreEntry * sentry) | |
891 | { | |
892 | rate()->stats (sentry, label()); | |
62e76326 | 893 | |
b67e2c8c | 894 | if (rate()->restore_bps == -1) { |
62e76326 | 895 | storeAppendPrintf(sentry, "\n\n"); |
896 | return; | |
59715b38 | 897 | } |
b67e2c8c | 898 | |
899 | for (unsigned int index = 0; index < buckets.size(); ++index) { | |
62e76326 | 900 | storeAppendPrintf(sentry, "\t\tCurrent [Network %d]:", buckets.key_map[index]); |
901 | buckets.values[index].stats (sentry); | |
902 | storeAppendPrintf(sentry, "\n"); | |
59715b38 | 903 | } |
b67e2c8c | 904 | |
905 | if (!buckets.size()) | |
62e76326 | 906 | storeAppendPrintf(sentry, "\t\tCurrent [All networks]: Not used yet.\n"); |
b67e2c8c | 907 | |
908 | storeAppendPrintf(sentry, "\n\n"); | |
59715b38 | 909 | } |
910 | ||
b67e2c8c | 911 | void |
912 | ClassCHostPool::dump(StoreEntry *entry) const | |
59715b38 | 913 | { |
b67e2c8c | 914 | rate()->dump (entry); |
915 | } | |
59715b38 | 916 | |
b67e2c8c | 917 | void |
918 | ClassCHostPool::update(int incr) | |
919 | { | |
920 | if (rate()->restore_bps == -1) | |
62e76326 | 921 | return; |
922 | ||
b67e2c8c | 923 | for (unsigned int i = 0; i< buckets.size(); ++i) |
62e76326 | 924 | buckets.values[i].update (*rate(), incr); |
b67e2c8c | 925 | } |
926 | ||
927 | void | |
928 | ClassCHostPool::parse() | |
929 | { | |
930 | rate()->parse(); | |
931 | } | |
932 | ||
933 | bool | |
934 | ClassCHostPool::keyAllocated (unsigned char const key) const | |
935 | { | |
936 | return buckets.indexUsed(buckets.findKeyIndex (key)); | |
937 | } | |
938 | ||
939 | unsigned char const | |
62e76326 | 940 | |
ddfcbc22 | 941 | ClassCHostPool::makeHostKey (struct IN_ADDR &src_addr) const |
b67e2c8c | 942 | { |
943 | unsigned int host; | |
944 | host = ntohl(src_addr.s_addr) & 0xff; | |
945 | return host; | |
946 | } | |
947 | ||
948 | unsigned int const | |
62e76326 | 949 | |
ddfcbc22 | 950 | ClassCHostPool::makeKey (struct IN_ADDR &src_addr) const |
b67e2c8c | 951 | { |
952 | unsigned int net; | |
953 | net = (ntohl(src_addr.s_addr) >> 8) & 0xff; | |
954 | return net; | |
955 | } | |
62e76326 | 956 | |
b67e2c8c | 957 | DelayIdComposite::Pointer |
62e76326 | 958 | |
1e5562e3 | 959 | ClassCHostPool::id(CompositeSelectionDetails &details) |
b67e2c8c | 960 | { |
961 | if (rate()->restore_bps == -1) | |
62e76326 | 962 | return new NullDelayId; |
b67e2c8c | 963 | |
1e5562e3 | 964 | unsigned int key = makeKey (details.src_addr); |
62e76326 | 965 | |
1e5562e3 | 966 | unsigned char host = makeHostKey (details.src_addr); |
b67e2c8c | 967 | |
968 | unsigned char hostIndex; | |
62e76326 | 969 | |
b67e2c8c | 970 | unsigned char netIndex; |
62e76326 | 971 | |
b67e2c8c | 972 | if (keyAllocated (key)) |
62e76326 | 973 | netIndex = buckets.findKeyIndex(key); |
b67e2c8c | 974 | else |
62e76326 | 975 | netIndex = buckets.insert (key); |
b67e2c8c | 976 | |
977 | hostIndex = buckets.values[netIndex].hostPosition (*rate(), host); | |
62e76326 | 978 | |
b67e2c8c | 979 | return new Id (this, netIndex, hostIndex); |
980 | } | |
981 | ||
982 | void * | |
983 | ClassCHostPool::Id::operator new(size_t size) | |
984 | { | |
985 | DelayPools::MemoryUsed += sizeof (Id); | |
986 | return ::operator new (size); | |
987 | } | |
988 | ||
989 | void | |
990 | ClassCHostPool::Id::operator delete (void *address) | |
991 | { | |
992 | DelayPools::MemoryUsed -= sizeof (Id); | |
993 | ::operator delete (address); | |
994 | } | |
995 | ||
b67e2c8c | 996 | ClassCHostPool::Id::Id (ClassCHostPool::Pointer aPool, unsigned char aNet, unsigned char aHost) : theClassCHost (aPool), theNet (aNet), theHost (aHost) |
62e76326 | 997 | {} |
b67e2c8c | 998 | |
999 | int | |
1000 | ClassCHostPool::Id::bytesWanted (int min, int max) const | |
1001 | { | |
1002 | return theClassCHost->buckets.values[theNet].individuals.values[theHost].bytesWanted (min, max); | |
1003 | } | |
1004 | ||
1005 | void | |
1006 | ClassCHostPool::Id::bytesIn(int qty) | |
1007 | { | |
1008 | theClassCHost->buckets.values[theNet].individuals.values[theHost].bytesIn (qty); | |
59715b38 | 1009 | } |
1010 | ||
95e36d02 | 1011 | #endif |
b67e2c8c | 1012 |