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