3 * $Id: delay_pools.cc,v 1.46 2006/05/29 00:15:02 robertc Exp $
5 * DEBUG: section 77 Delay Pools
6 * AUTHOR: Robert Collins <robertc@squid-cache.org>
7 * Based upon original delay pools code by
8 * David Luyer <david@luyer.net>
10 * SQUID Web Proxy Cache http://www.squid-cache.org/
11 * ----------------------------------------------------------
13 * Squid is the result of efforts by numerous individuals from
14 * the Internet community; see the CONTRIBUTORS file for full
15 * details. Many organizations have provided support for Squid's
16 * development; see the SPONSORS file for full details. Squid is
17 * Copyrighted (C) 2001 by the Regents of the University of
18 * California; see the COPYRIGHT file for full details. Squid
19 * incorporates software developed and/or copyrighted by other
20 * sources; see the CREDITS file for full details.
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
37 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
44 #include "CacheManager.h"
45 #include "DelaySpec.h"
46 #include "DelayPools.h"
47 #include "StoreClient.h"
49 #include "MemObject.h"
50 #include "client_side_request.h"
51 #include "ConfigParser.h"
54 #include "SquidString.h"
55 #include "SquidTime.h"
56 #include "CommonPool.h"
57 #include "CompositePoolNode.h"
58 #include "DelayPool.h"
59 #include "DelayVector.h"
60 #include "NullDelayId.h"
61 #include "DelayBucket.h"
62 #include "DelayUser.h"
63 #include "DelayTagged.h"
65 long DelayPools::MemoryUsed
= 0;
67 class Aggregate
: public CompositePoolNode
71 typedef RefCount
<Aggregate
> Pointer
;
72 void *operator new(size_t);
73 void operator delete (void *);
76 virtual DelaySpec
*rate() {return &spec
;}
78 virtual DelaySpec
const *rate() const {return &spec
;}
80 virtual void stats(StoreEntry
* sentry
);
81 virtual void dump(StoreEntry
*entry
) const;
82 virtual void update(int incr
);
85 virtual DelayIdComposite::Pointer
id(CompositeSelectionDetails
&);
89 class AggregateId
:public DelayIdComposite
93 void *operator new(size_t);
94 void operator delete (void *);
95 AggregateId (RefCount
<Aggregate
>);
96 virtual int bytesWanted (int min
, int max
) const;
97 virtual void bytesIn(int qty
);
98 virtual void delayRead(DeferredRead
const &);
101 RefCount
<Aggregate
> theAggregate
;
104 friend class AggregateId
;
106 DelayBucket theBucket
;
110 template <class Key
, class Value
>
117 unsigned int size() const;
118 unsigned char findKeyIndex (Key
const key
) const;
119 bool indexUsed (unsigned char const index
) const;
120 unsigned int insert (Key
const key
);
122 #define IND_MAP_SZ 256
124 Key key_map
[IND_MAP_SZ
];
125 Value values
[IND_MAP_SZ
];
128 unsigned int nextMapPosition
;
131 class VectorPool
: public CompositePoolNode
135 typedef RefCount
<VectorPool
> Pointer
;
136 virtual void dump(StoreEntry
*entry
) const;
137 virtual void parse();
138 virtual void update(int incr
);
139 virtual void stats(StoreEntry
* sentry
);
141 virtual DelayIdComposite::Pointer
id(CompositeSelectionDetails
&);
142 VectorMap
<unsigned char, DelayBucket
> buckets
;
147 bool keyAllocated (unsigned char const key
) const;
148 virtual DelaySpec
*rate() {return &spec
;}
150 virtual DelaySpec
const *rate() const {return &spec
;}
152 virtual char const *label() const = 0;
154 virtual unsigned int const makeKey (struct IN_ADDR
&src_addr
) const = 0;
158 class Id
:public DelayIdComposite
162 void *operator new(size_t);
163 void operator delete (void *);
164 Id (RefCount
<VectorPool
>, int);
165 virtual int bytesWanted (int min
, int max
) const;
166 virtual void bytesIn(int qty
);
169 RefCount
<VectorPool
> theVector
;
174 class IndividualPool
: public VectorPool
178 void *operator new(size_t);
179 void operator delete (void *);
182 virtual char const *label() const {return "Individual";}
184 virtual unsigned int const makeKey (struct IN_ADDR
&src_addr
) const;
188 class ClassCNetPool
: public VectorPool
192 void *operator new(size_t);
193 void operator delete (void *);
196 virtual char const *label() const {return "Network";}
198 virtual unsigned int const makeKey (struct IN_ADDR
&src_addr
) const;
201 /* don't use remote storage for these */
207 bool individualUsed (unsigned int index
)const;
208 unsigned char findHostMapPosition (unsigned char const host
) const;
209 bool individualAllocated (unsigned char host
) const;
210 unsigned char hostPosition (DelaySpec
&rate
, unsigned char const host
);
211 void initHostIndex (DelaySpec
&rate
, unsigned char index
, unsigned char host
);
212 void update (DelaySpec
const &, int incr
);
213 void stats(StoreEntry
*)const;
216 VectorMap
<unsigned char, DelayBucket
> individuals
;
219 class ClassCHostPool
: public CompositePoolNode
223 typedef RefCount
<ClassCHostPool
> Pointer
;
224 virtual void dump(StoreEntry
*entry
) const;
225 virtual void parse();
226 virtual void update(int incr
);
227 virtual void stats(StoreEntry
* sentry
);
229 virtual DelayIdComposite::Pointer
id(CompositeSelectionDetails
&);
234 bool keyAllocated (unsigned char const key
) const;
235 virtual DelaySpec
*rate() {return &spec
;}
237 virtual DelaySpec
const *rate() const {return &spec
;}
239 virtual char const *label() const {return "Individual";}
241 virtual unsigned int const makeKey (struct IN_ADDR
&src_addr
) const;
243 unsigned char const makeHostKey (struct IN_ADDR
&src_addr
) const;
246 VectorMap
<unsigned char, ClassCBucket
> buckets
;
250 friend class ClassCHostPool::Id
;
252 class Id
:public DelayIdComposite
256 void *operator new(size_t);
257 void operator delete (void *);
258 Id (RefCount
<ClassCHostPool
>, unsigned char, unsigned char);
259 virtual int bytesWanted (int min
, int max
) const;
260 virtual void bytesIn(int qty
);
263 RefCount
<ClassCHostPool
> theClassCHost
;
264 unsigned char theNet
;
265 unsigned char theHost
;
270 Aggregate::AggregateId::delayRead(DeferredRead
const &aRead
)
272 theAggregate
->delayRead(aRead
);
276 CommonPool::operator new(size_t size
)
278 DelayPools::MemoryUsed
+= sizeof (CommonPool
);
279 return ::operator new (size
);
283 CommonPool::operator delete (void *address
)
285 DelayPools::MemoryUsed
-= sizeof (CommonPool
);
286 ::operator delete (address
);
290 CommonPool::Factory(unsigned char _class
, CompositePoolNode::Pointer
& compositeCopy
)
292 CommonPool
*result
= new CommonPool
;
300 compositeCopy
= new Aggregate
;
301 result
->typeLabel
= "1";
305 result
->typeLabel
= "2";
307 DelayVector::Pointer temp
= new DelayVector
;
308 compositeCopy
= temp
.getRaw();
309 temp
->push_back (new Aggregate
);
310 temp
->push_back(new IndividualPool
);
316 result
->typeLabel
= "3";
318 DelayVector::Pointer temp
= new DelayVector
;
319 compositeCopy
= temp
.getRaw();
320 temp
->push_back (new Aggregate
);
321 temp
->push_back (new ClassCNetPool
);
322 temp
->push_back (new ClassCHostPool
);
328 result
->typeLabel
= "4";
330 DelayVector::Pointer temp
= new DelayVector
;
331 compositeCopy
= temp
.getRaw();
332 temp
->push_back (new Aggregate
);
333 temp
->push_back (new ClassCNetPool
);
334 temp
->push_back (new ClassCHostPool
);
335 temp
->push_back (new DelayUser
);
341 result
->typeLabel
= "5";
342 compositeCopy
= new DelayTagged
;
346 fatal ("unknown delay pool class");
353 CommonPool::CommonPool()
357 ClassCBucket::update (DelaySpec
const &rate
, int incr
)
359 /* If we aren't active, don't try to update us ! */
360 assert (rate
.restore_bps
!= -1);
362 for (unsigned char j
= 0; j
< individuals
.size(); ++j
)
363 individuals
.values
[j
].update (rate
, incr
);
367 ClassCBucket::stats(StoreEntry
*sentry
)const
369 for (unsigned int j
= 0; j
< individuals
.size(); ++j
) {
370 assert (individualUsed (j
));
371 storeAppendPrintf(sentry
, " %d:",individuals
.key_map
[j
]);
372 individuals
.values
[j
].stats (sentry
);
377 ClassCBucket::findHostMapPosition (unsigned char const host
) const
379 return individuals
.findKeyIndex(host
);
383 ClassCBucket::individualUsed (unsigned int index
)const
385 return individuals
.indexUsed(index
);
389 ClassCBucket::individualAllocated (unsigned char host
) const
391 return individualUsed(findHostMapPosition (host
));
395 ClassCBucket::hostPosition (DelaySpec
&rate
, unsigned char const host
)
397 if (individualAllocated (host
))
398 return findHostMapPosition(host
);
400 assert (!individualUsed (findHostMapPosition(host
)));
402 unsigned char result
= findHostMapPosition(host
);
404 initHostIndex (rate
, result
, host
);
410 ClassCBucket::initHostIndex (DelaySpec
&rate
, unsigned char index
, unsigned char host
)
412 assert (!individualUsed(index
));
414 unsigned char const newIndex
= individuals
.insert (host
);
416 /* give the bucket a default value */
417 individuals
.values
[newIndex
].init (rate
);
421 CompositePoolNode::operator new(size_t size
)
423 DelayPools::MemoryUsed
+= sizeof (CompositePoolNode
);
424 return ::operator new (size
);
428 CompositePoolNode::operator delete (void *address
)
430 DelayPools::MemoryUsed
-= sizeof (CompositePoolNode
);
431 ::operator delete (address
);
435 Aggregate::operator new(size_t size
)
437 DelayPools::MemoryUsed
+= sizeof (Aggregate
);
438 return ::operator new (size
);
442 Aggregate::operator delete (void *address
)
444 DelayPools::MemoryUsed
-= sizeof (Aggregate
);
445 ::operator delete (address
);
448 Aggregate::Aggregate()
450 theBucket
.init (*rate());
451 DelayPools::registerForUpdates (this);
454 Aggregate::~Aggregate()
456 DelayPools::deregisterForUpdates (this);
460 Aggregate::stats(StoreEntry
* sentry
)
462 rate()->stats (sentry
, "Aggregate");
464 if (rate()->restore_bps
== -1)
467 storeAppendPrintf(sentry
, "\t\tCurrent: ");
469 theBucket
.stats(sentry
);
471 storeAppendPrintf(sentry
, "\n\n");
475 Aggregate::dump(StoreEntry
*entry
) const
477 rate()->dump (entry
);
481 Aggregate::update(int incr
)
483 theBucket
.update(*rate(), incr
);
493 DelayIdComposite::Pointer
495 Aggregate::id(CompositeSelectionDetails
&details
)
497 if (rate()->restore_bps
!= -1)
498 return new AggregateId (this);
500 return new NullDelayId
;
504 Aggregate::AggregateId::operator new(size_t size
)
506 DelayPools::MemoryUsed
+= sizeof (AggregateId
);
507 return ::operator new (size
);
511 Aggregate::AggregateId::operator delete (void *address
)
513 DelayPools::MemoryUsed
-= sizeof (AggregateId
);
514 ::operator delete (address
);
517 Aggregate::AggregateId::AggregateId(RefCount
<Aggregate
> anAggregate
) : theAggregate(anAggregate
)
521 Aggregate::AggregateId::bytesWanted (int min
, int max
) const
523 return theAggregate
->theBucket
.bytesWanted(min
, max
);
527 Aggregate::AggregateId::bytesIn(int qty
)
529 theAggregate
->theBucket
.bytesIn(qty
);
530 theAggregate
->kickReads();
533 DelayPool
*DelayPools::delay_data
= NULL
;
534 time_t DelayPools::LastUpdate
= 0;
535 unsigned short DelayPools::pools_ (0);
540 LastUpdate
= getCurrentTime();
544 DelayPools::RegisterWithCacheManager(CacheManager
& manager
)
546 manager
.registerAction("delay", "Delay Pool Levels", Stats
, 0, 1);
550 DelayPools::InitDelayData()
555 DelayPools::delay_data
= new DelayPool
[pools()];
557 DelayPools::MemoryUsed
+= pools() * sizeof(DelayPool
);
559 eventAdd("DelayPools::Update", DelayPools::Update
, NULL
, 1.0, 1);
563 DelayPools::FreeDelayData()
565 eventDelete(DelayPools::Update
, NULL
);
566 delete[] DelayPools::delay_data
;
567 DelayPools::MemoryUsed
-= pools() * sizeof(*DelayPools::delay_data
);
572 DelayPools::Update(void *unused
)
577 eventAdd("DelayPools::Update", Update
, NULL
, 1.0, 1);
579 int incr
= squid_curtime
- LastUpdate
;
584 LastUpdate
= squid_curtime
;
586 Vector
<Updateable
*>::iterator pos
= toUpdate
.begin();
588 while (pos
!= toUpdate
.end()) {
589 (*pos
)->update(incr
);
595 DelayPools::registerForUpdates(Updateable
*anObject
)
597 /* Assume no doubles */
598 toUpdate
.push_back(anObject
);
602 DelayPools::deregisterForUpdates (Updateable
*anObject
)
604 Vector
<Updateable
*>::iterator pos
= toUpdate
.begin();
606 while (pos
!= toUpdate
.end() && *pos
!= anObject
) {
610 if (pos
!= toUpdate
.end()) {
611 /* move all objects down one */
612 Vector
<Updateable
*>::iterator temp
= pos
;
615 while (pos
!= toUpdate
.end()) {
625 Vector
<Updateable
*> DelayPools::toUpdate
;
628 DelayPools::Stats(StoreEntry
* sentry
)
632 storeAppendPrintf(sentry
, "Delay pools configured: %d\n\n", DelayPools::pools());
634 for (i
= 0; i
< DelayPools::pools(); ++i
) {
635 if (DelayPools::delay_data
[i
].theComposite().getRaw()) {
636 storeAppendPrintf(sentry
, "Pool: %d\n\tClass: %s\n\n", i
+ 1, DelayPools::delay_data
[i
].pool
->theClassTypeLabel());
637 DelayPools::delay_data
[i
].theComposite()->stats (sentry
);
639 storeAppendPrintf(sentry
, "\tMisconfigured pool.\n\n");
642 storeAppendPrintf(sentry
, "Memory Used: %d bytes\n", (int) DelayPools::MemoryUsed
);
646 DelayPools::FreePools()
648 if (!DelayPools::pools())
661 DelayPools::pools (u_short newPools
)
664 debug(3, 0) ("parse_delay_pool_count: multiple delay_pools lines, aborting all previous delay_pools config\n");
674 template <class Key
, class Value
>
675 VectorMap
<Key
,Value
>::VectorMap() : nextMapPosition(0)
678 template <class Key
, class Value
>
680 VectorMap
<Key
,Value
>::size() const
682 return nextMapPosition
;
685 template <class Key
, class Value
>
687 VectorMap
<Key
,Value
>::insert (Key
const key
)
689 unsigned char index
= findKeyIndex (key
);
690 assert (!indexUsed(index
));
692 key_map
[index
] = key
;
700 IndividualPool::operator new(size_t size
)
702 DelayPools::MemoryUsed
+= sizeof (IndividualPool
);
703 return ::operator new (size
);
707 IndividualPool::operator delete (void *address
)
709 DelayPools::MemoryUsed
-= sizeof (IndividualPool
);
710 ::operator delete (address
);
713 VectorPool::VectorPool()
715 DelayPools::registerForUpdates (this);
718 VectorPool::~VectorPool()
720 DelayPools::deregisterForUpdates (this);
724 VectorPool::stats(StoreEntry
* sentry
)
726 rate()->stats (sentry
, label());
728 if (rate()->restore_bps
== -1) {
729 storeAppendPrintf(sentry
, "\n\n");
733 storeAppendPrintf(sentry
, "\t\tCurrent:");
735 for (unsigned int i
= 0; i
< buckets
.size(); i
++) {
736 storeAppendPrintf(sentry
, " %d:", buckets
.key_map
[i
]);
737 buckets
.values
[i
].stats(sentry
);
741 storeAppendPrintf(sentry
, " Not used yet.");
743 storeAppendPrintf(sentry
, "\n\n");
747 VectorPool::dump(StoreEntry
*entry
) const
749 rate()->dump (entry
);
753 VectorPool::update(int incr
)
755 if (rate()->restore_bps
== -1)
758 for (unsigned int i
= 0; i
< buckets
.size(); ++i
)
759 buckets
.values
[i
].update (*rate(), incr
);
769 VectorPool::keyAllocated (unsigned char const key
) const
771 return buckets
.indexUsed(buckets
.findKeyIndex (key
));
774 template <class Key
, class Value
>
776 VectorMap
<Key
,Value
>::indexUsed (unsigned char const index
) const
778 return index
< size();
781 /* returns the used position, or the position to allocate */
782 template <class Key
, class Value
>
784 VectorMap
<Key
,Value
>::findKeyIndex (Key
const key
) const
786 for (unsigned int index
= 0; index
< size(); ++index
) {
787 assert (indexUsed (index
));
789 if (key_map
[index
] == key
)
797 DelayIdComposite::Pointer
799 VectorPool::id(CompositeSelectionDetails
&details
)
801 if (rate()->restore_bps
== -1)
802 return new NullDelayId
;
804 unsigned int key
= makeKey (details
.src_addr
);
806 if (keyAllocated (key
))
807 return new Id (this, buckets
.findKeyIndex(key
));
809 unsigned char const resultIndex
= buckets
.insert(key
);
811 buckets
.values
[resultIndex
].init (*rate());
813 return new Id(this, resultIndex
);
817 VectorPool::Id::operator new(size_t size
)
819 DelayPools::MemoryUsed
+= sizeof (Id
);
820 return ::operator new (size
);
824 VectorPool::Id::operator delete (void *address
)
826 DelayPools::MemoryUsed
-= sizeof (Id
);
827 ::operator delete (address
);
830 VectorPool::Id::Id (VectorPool::Pointer aPool
, int anIndex
) : theVector (aPool
), theIndex (anIndex
)
834 VectorPool::Id::bytesWanted (int min
, int max
) const
836 return theVector
->buckets
.values
[theIndex
].bytesWanted (min
, max
);
840 VectorPool::Id::bytesIn(int qty
)
842 theVector
->buckets
.values
[theIndex
].bytesIn (qty
);
848 IndividualPool::makeKey (struct IN_ADDR
&src_addr
) const
851 host
= ntohl(src_addr
.s_addr
) & 0xff;
856 ClassCNetPool::operator new(size_t size
)
858 DelayPools::MemoryUsed
+= sizeof (ClassCNetPool
);
859 return ::operator new (size
);
863 ClassCNetPool::operator delete (void *address
)
865 DelayPools::MemoryUsed
-= sizeof (ClassCNetPool
);
866 ::operator delete (address
);
871 ClassCNetPool::makeKey (struct IN_ADDR
&src_addr
) const
874 net
= (ntohl(src_addr
.s_addr
) >> 8) & 0xff;
879 ClassCHostPool::ClassCHostPool()
881 DelayPools::registerForUpdates (this);
884 ClassCHostPool::~ClassCHostPool()
886 DelayPools::deregisterForUpdates (this);
890 ClassCHostPool::stats(StoreEntry
* sentry
)
892 rate()->stats (sentry
, label());
894 if (rate()->restore_bps
== -1) {
895 storeAppendPrintf(sentry
, "\n\n");
899 for (unsigned int index
= 0; index
< buckets
.size(); ++index
) {
900 storeAppendPrintf(sentry
, "\t\tCurrent [Network %d]:", buckets
.key_map
[index
]);
901 buckets
.values
[index
].stats (sentry
);
902 storeAppendPrintf(sentry
, "\n");
906 storeAppendPrintf(sentry
, "\t\tCurrent [All networks]: Not used yet.\n");
908 storeAppendPrintf(sentry
, "\n\n");
912 ClassCHostPool::dump(StoreEntry
*entry
) const
914 rate()->dump (entry
);
918 ClassCHostPool::update(int incr
)
920 if (rate()->restore_bps
== -1)
923 for (unsigned int i
= 0; i
< buckets
.size(); ++i
)
924 buckets
.values
[i
].update (*rate(), incr
);
928 ClassCHostPool::parse()
934 ClassCHostPool::keyAllocated (unsigned char const key
) const
936 return buckets
.indexUsed(buckets
.findKeyIndex (key
));
941 ClassCHostPool::makeHostKey (struct IN_ADDR
&src_addr
) const
944 host
= ntohl(src_addr
.s_addr
) & 0xff;
950 ClassCHostPool::makeKey (struct IN_ADDR
&src_addr
) const
953 net
= (ntohl(src_addr
.s_addr
) >> 8) & 0xff;
957 DelayIdComposite::Pointer
959 ClassCHostPool::id(CompositeSelectionDetails
&details
)
961 if (rate()->restore_bps
== -1)
962 return new NullDelayId
;
964 unsigned int key
= makeKey (details
.src_addr
);
966 unsigned char host
= makeHostKey (details
.src_addr
);
968 unsigned char hostIndex
;
970 unsigned char netIndex
;
972 if (keyAllocated (key
))
973 netIndex
= buckets
.findKeyIndex(key
);
975 netIndex
= buckets
.insert (key
);
977 hostIndex
= buckets
.values
[netIndex
].hostPosition (*rate(), host
);
979 return new Id (this, netIndex
, hostIndex
);
983 ClassCHostPool::Id::operator new(size_t size
)
985 DelayPools::MemoryUsed
+= sizeof (Id
);
986 return ::operator new (size
);
990 ClassCHostPool::Id::operator delete (void *address
)
992 DelayPools::MemoryUsed
-= sizeof (Id
);
993 ::operator delete (address
);
996 ClassCHostPool::Id::Id (ClassCHostPool::Pointer aPool
, unsigned char aNet
, unsigned char aHost
) : theClassCHost (aPool
), theNet (aNet
), theHost (aHost
)
1000 ClassCHostPool::Id::bytesWanted (int min
, int max
) const
1002 return theClassCHost
->buckets
.values
[theNet
].individuals
.values
[theHost
].bytesWanted (min
, max
);
1006 ClassCHostPool::Id::bytesIn(int qty
)
1008 theClassCHost
->buckets
.values
[theNet
].individuals
.values
[theHost
].bytesIn (qty
);