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