]> git.ipfire.org Git - thirdparty/squid.git/blame - src/delay_pools.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / delay_pools.cc
CommitLineData
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 44long DelayPools::MemoryUsed = 0;
45
63be0a78 46/// \ingroup DelayPoolsInternal
62e76326 47class Aggregate : public CompositePoolNode
48{
49
50public:
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
67private:
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 92template <class Key, class Value>
62e76326 93class VectorMap
94{
95
96public:
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
108private:
b67e2c8c 109 unsigned int nextMapPosition;
110};
efd900cb 111
63be0a78 112/// \ingroup DelayPoolsInternal
62e76326 113class VectorPool : public CompositePoolNode
114{
115
116public:
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
128protected:
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 158class IndividualPool : public VectorPool
159{
160
161public:
b67e2c8c 162 void *operator new(size_t);
b1fb3348 163 void operator delete(void *);
62e76326 164
165protected:
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 171class ClassCNetPool : public VectorPool
172{
173
174public:
b67e2c8c 175 void *operator new(size_t);
176 void operator delete (void *);
62e76326 177
178protected:
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 185class ClassCBucket
186{
187
188public:
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 202class ClassCHostPool : public CompositePoolNode
203{
204
205public:
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
216protected:
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 253void
254Aggregate::AggregateId::delayRead(DeferredRead const &aRead)
255{
256 theAggregate->delayRead(aRead);
257}
b67e2c8c 258
259void *
260CommonPool::operator new(size_t size)
261{
262 DelayPools::MemoryUsed += sizeof (CommonPool);
263 return ::operator new (size);
b6a2f15e 264}
265
b67e2c8c 266void
b1fb3348 267CommonPool::operator delete(void *address)
b6a2f15e 268{
b1fb3348
AJ
269 DelayPools::MemoryUsed -= sizeof(CommonPool);
270 ::operator delete(address);
b6a2f15e 271}
272
b67e2c8c 273CommonPool *
274CommonPool::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 336CommonPool::CommonPool()
337{}
59715b38 338
339void
b67e2c8c 340ClassCBucket::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
349void
350ClassCBucket::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
359unsigned char
360ClassCBucket::findHostMapPosition (unsigned char const host) const
361{
362 return individuals.findKeyIndex(host);
363}
364
365bool
366ClassCBucket::individualUsed (unsigned int index)const
367{
368 return individuals.indexUsed(index);
369}
370
371bool
372ClassCBucket::individualAllocated (unsigned char host) const
373{
374 return individualUsed(findHostMapPosition (host));
b6a2f15e 375}
376
b67e2c8c 377unsigned char
378ClassCBucket::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
392void
b67e2c8c 393ClassCBucket::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
403void *
404CompositePoolNode::operator new(size_t size)
405{
406 DelayPools::MemoryUsed += sizeof (CompositePoolNode);
407 return ::operator new (size);
b6a2f15e 408}
409
410void
b67e2c8c 411CompositePoolNode::operator delete (void *address)
b6a2f15e 412{
b67e2c8c 413 DelayPools::MemoryUsed -= sizeof (CompositePoolNode);
414 ::operator delete (address);
b6a2f15e 415}
416
b67e2c8c 417void *
418Aggregate::operator new(size_t size)
419{
420 DelayPools::MemoryUsed += sizeof (Aggregate);
421 return ::operator new (size);
59715b38 422}
423
424void
b67e2c8c 425Aggregate::operator delete (void *address)
59715b38 426{
b67e2c8c 427 DelayPools::MemoryUsed -= sizeof (Aggregate);
428 ::operator delete (address);
59715b38 429}
430
b67e2c8c 431Aggregate::Aggregate()
432{
433 theBucket.init (*rate());
434 DelayPools::registerForUpdates (this);
435}
436
437Aggregate::~Aggregate()
438{
439 DelayPools::deregisterForUpdates (this);
59715b38 440}
441
442void
b67e2c8c 443Aggregate::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
457void
b67e2c8c 458Aggregate::dump(StoreEntry *entry) const
59715b38 459{
b67e2c8c 460 rate()->dump (entry);
59715b38 461}
462
463void
b67e2c8c 464Aggregate::update(int incr)
59715b38 465{
b67e2c8c 466 theBucket.update(*rate(), incr);
a46d2c0e 467 kickReads();
447e176b 468}
95e36d02 469
b67e2c8c 470void
471Aggregate::parse()
59715b38 472{
b67e2c8c 473 rate()->parse();
59715b38 474}
475
b67e2c8c 476DelayIdComposite::Pointer
1e5562e3 477Aggregate::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 485void *
486Aggregate::AggregateId::operator new(size_t size)
95e36d02 487{
b67e2c8c 488 DelayPools::MemoryUsed += sizeof (AggregateId);
489 return ::operator new (size);
95e36d02 490}
491
b67e2c8c 492void
493Aggregate::AggregateId::operator delete (void *address)
494{
495 DelayPools::MemoryUsed -= sizeof (AggregateId);
496 ::operator delete (address);
95e36d02 497}
498
75566ba2 499Aggregate::AggregateId::AggregateId(RefCount<Aggregate> anAggregate) : theAggregate(anAggregate)
62e76326 500{}
95e36d02 501
447e176b 502int
b67e2c8c 503Aggregate::AggregateId::bytesWanted (int min, int max) const
447e176b 504{
b67e2c8c 505 return theAggregate->theBucket.bytesWanted(min, max);
506}
59715b38 507
b67e2c8c 508void
509Aggregate::AggregateId::bytesIn(int qty)
510{
511 theAggregate->theBucket.bytesIn(qty);
a46d2c0e 512 theAggregate->kickReads();
b67e2c8c 513}
447e176b 514
b67e2c8c 515DelayPool *DelayPools::delay_data = NULL;
b67e2c8c 516time_t DelayPools::LastUpdate = 0;
517unsigned short DelayPools::pools_ (0);
447e176b 518
b67e2c8c 519void
6b7d87bb 520DelayPools::RegisterWithCacheManager(void)
b67e2c8c 521{
8822ebee 522 Mgr::RegisterAction("delay", "Delay Pool Levels", Stats, 0, 1);
62ee09ca 523}
524
525void
6b7d87bb 526DelayPools::Init()
62ee09ca 527{
6b7d87bb
FC
528 LastUpdate = getCurrentTime();
529 RegisterWithCacheManager();
b67e2c8c 530}
447e176b 531
b67e2c8c 532void
533DelayPools::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 545void
546DelayPools::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 554void
555DelayPools::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 577void
578DelayPools::registerForUpdates(Updateable *anObject)
579{
580 /* Assume no doubles */
581 toUpdate.push_back(anObject);
582}
583
584void
585DelayPools::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 608std::vector<Updateable *> DelayPools::toUpdate;
b67e2c8c 609
447e176b 610void
b67e2c8c 611DelayPools::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 628void
629DelayPools::FreePools()
59715b38 630{
b67e2c8c 631 if (!DelayPools::pools())
62e76326 632 return;
633
b67e2c8c 634 FreeDelayData();
635}
636
637unsigned short
62e76326 638DelayPools::pools()
b67e2c8c 639{
640 return pools_;
641}
642
643void
f45dd259 644DelayPools::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
657template <class Key, class Value>
658VectorMap<Key,Value>::VectorMap() : nextMapPosition(0)
62e76326 659{}
b67e2c8c 660
661template <class Key, class Value>
62e76326 662unsigned int
b67e2c8c 663VectorMap<Key,Value>::size() const
664{
665 return nextMapPosition;
666}
62e76326 667
b67e2c8c 668template <class Key, class Value>
669unsigned int
670VectorMap<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
682void *
683IndividualPool::operator new(size_t size)
684{
685 DelayPools::MemoryUsed += sizeof (IndividualPool);
686 return ::operator new (size);
687}
688
689void
690IndividualPool::operator delete (void *address)
691{
692 DelayPools::MemoryUsed -= sizeof (IndividualPool);
693 ::operator delete (address);
59715b38 694}
695
b67e2c8c 696VectorPool::VectorPool()
697{
698 DelayPools::registerForUpdates (this);
59715b38 699}
700
b67e2c8c 701VectorPool::~VectorPool()
59715b38 702{
b67e2c8c 703 DelayPools::deregisterForUpdates (this);
704}
59715b38 705
b67e2c8c 706void
707VectorPool::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 729void
730VectorPool::dump(StoreEntry *entry) const
731{
732 rate()->dump (entry);
733}
734
735void
736VectorPool::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
745void
746VectorPool::parse()
747{
748 rate()->parse();
749}
750
751bool
752VectorPool::keyAllocated (unsigned char const key) const
753{
754 return buckets.indexUsed(buckets.findKeyIndex (key));
755}
756
757template <class Key, class Value>
758bool
759VectorMap<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 765template <class Key, class Value>
766unsigned char
767VectorMap<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
780DelayIdComposite::Pointer
1e5562e3 781VectorPool::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
802void *
803VectorPool::Id::operator new(size_t size)
804{
805 DelayPools::MemoryUsed += sizeof (Id);
806 return ::operator new (size);
807}
808
809void
b1fb3348 810VectorPool::Id::operator delete(void *address)
b67e2c8c 811{
812 DelayPools::MemoryUsed -= sizeof (Id);
813 ::operator delete (address);
814}
815
b1fb3348 816VectorPool::Id::Id(VectorPool::Pointer aPool, int anIndex) : theVector (aPool), theIndex (anIndex)
62e76326 817{}
b67e2c8c 818
819int
820VectorPool::Id::bytesWanted (int min, int max) const
821{
822 return theVector->buckets.values[theIndex].bytesWanted (min, max);
823}
824
825void
826VectorPool::Id::bytesIn(int qty)
827{
828 theVector->buckets.values[theIndex].bytesIn (qty);
829}
830
871899ca 831unsigned int
b7ac5457 832IndividualPool::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
843void *
844ClassCNetPool::operator new(size_t size)
845{
846 DelayPools::MemoryUsed += sizeof (ClassCNetPool);
847 return ::operator new (size);
848}
849
850void
851ClassCNetPool::operator delete (void *address)
852{
853 DelayPools::MemoryUsed -= sizeof (ClassCNetPool);
854 ::operator delete (address);
855}
856
871899ca 857unsigned int
b7ac5457 858ClassCNetPool::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 869ClassCHostPool::ClassCHostPool()
870{
871 DelayPools::registerForUpdates (this);
872}
873
874ClassCHostPool::~ClassCHostPool()
875{
876 DelayPools::deregisterForUpdates (this);
877}
878
879void
880ClassCHostPool::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 901void
902ClassCHostPool::dump(StoreEntry *entry) const
59715b38 903{
b67e2c8c 904 rate()->dump (entry);
905}
59715b38 906
b67e2c8c 907void
908ClassCHostPool::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
917void
918ClassCHostPool::parse()
919{
920 rate()->parse();
921}
922
923bool
924ClassCHostPool::keyAllocated (unsigned char const key) const
925{
926 return buckets.indexUsed(buckets.findKeyIndex (key));
927}
928
871899ca 929unsigned char
b7ac5457 930ClassCHostPool::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 942unsigned int
b7ac5457 943ClassCHostPool::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 954DelayIdComposite::Pointer
1e5562e3 955ClassCHostPool::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
982void *
983ClassCHostPool::Id::operator new(size_t size)
984{
985 DelayPools::MemoryUsed += sizeof (Id);
986 return ::operator new (size);
987}
988
989void
990ClassCHostPool::Id::operator delete (void *address)
991{
992 DelayPools::MemoryUsed -= sizeof (Id);
993 ::operator delete (address);
994}
995
b67e2c8c 996ClassCHostPool::Id::Id (ClassCHostPool::Pointer aPool, unsigned char aNet, unsigned char aHost) : theClassCHost (aPool), theNet (aNet), theHost (aHost)
62e76326 997{}
b67e2c8c 998
999int
1000ClassCHostPool::Id::bytesWanted (int min, int max) const
1001{
1002 return theClassCHost->buckets.values[theNet].individuals.values[theHost].bytesWanted (min, max);
1003}
1004
1005void
1006ClassCHostPool::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