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