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