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