2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 77 Delay Pools */
12 \defgroup DelayPoolsInternal Delay Pools Internal
13 \ingroup DelayPoolsAPI
19 #include "client_side_request.h"
20 #include "comm/Connection.h"
21 #include "CommonPool.h"
22 #include "CompositePoolNode.h"
23 #include "ConfigParser.h"
24 #include "DelayBucket.h"
26 #include "DelayPool.h"
27 #include "DelayPools.h"
28 #include "DelaySpec.h"
29 #include "DelayTagged.h"
30 #include "DelayUser.h"
31 #include "DelayVector.h"
33 #include "http/Stream.h"
34 #include "ip/Address.h"
35 #include "MemObject.h"
36 #include "mgr/Registration.h"
37 #include "NullDelayId.h"
38 #include "SquidString.h"
39 #include "SquidTime.h"
41 #include "StoreClient.h"
43 /// \ingroup DelayPoolsInternal
44 long DelayPools::MemoryUsed
= 0;
46 /// \ingroup DelayPoolsInternal
47 class Aggregate
: public CompositePoolNode
51 typedef RefCount
<Aggregate
> Pointer
;
52 void *operator new(size_t);
53 void operator delete (void *);
56 virtual DelaySpec
*rate() {return &spec
;}
58 virtual DelaySpec
const *rate() const {return &spec
;}
60 virtual void stats(StoreEntry
* sentry
);
61 virtual void dump(StoreEntry
*entry
) const;
62 virtual void update(int incr
);
65 virtual DelayIdComposite::Pointer
id(CompositeSelectionDetails
&);
69 /// \ingroup DelayPoolsInternal
70 class AggregateId
:public DelayIdComposite
74 void *operator new(size_t);
75 void operator delete (void *);
76 AggregateId (RefCount
<Aggregate
>);
77 virtual int bytesWanted (int min
, int max
) const;
78 virtual void bytesIn(int qty
);
79 virtual void delayRead(DeferredRead
const &);
82 RefCount
<Aggregate
> theAggregate
;
85 friend class AggregateId
;
87 DelayBucket theBucket
;
91 /// \ingroup DelayPoolsInternal
92 template <class Key
, class Value
>
98 unsigned int size() const;
99 unsigned char findKeyIndex (Key
const key
) const;
100 bool indexUsed (unsigned char const index
) const;
101 unsigned int insert (Key
const key
);
103 #define IND_MAP_SZ 256
105 Key key_map
[IND_MAP_SZ
];
106 Value values
[IND_MAP_SZ
];
109 unsigned int nextMapPosition
;
112 /// \ingroup DelayPoolsInternal
113 class VectorPool
: public CompositePoolNode
117 typedef RefCount
<VectorPool
> Pointer
;
118 virtual void dump(StoreEntry
*entry
) const;
119 virtual void parse();
120 virtual void update(int incr
);
121 virtual void stats(StoreEntry
* sentry
);
123 virtual DelayIdComposite::Pointer
id(CompositeSelectionDetails
&);
124 VectorMap
<unsigned char, DelayBucket
> buckets
;
129 bool keyAllocated (unsigned char const key
) const;
130 virtual DelaySpec
*rate() {return &spec
;}
132 virtual DelaySpec
const *rate() const {return &spec
;}
134 virtual char const *label() const = 0;
136 virtual unsigned int makeKey(Ip::Address
&src_addr
) const = 0;
140 /// \ingroup DelayPoolsInternal
141 class Id
:public DelayIdComposite
145 void *operator new(size_t);
146 void operator delete (void *);
147 Id (RefCount
<VectorPool
>, int);
148 virtual int bytesWanted (int min
, int max
) const;
149 virtual void bytesIn(int qty
);
152 RefCount
<VectorPool
> theVector
;
157 /// \ingroup DelayPoolsInternal
158 class IndividualPool
: public VectorPool
162 void *operator new(size_t);
163 void operator delete(void *);
166 virtual char const *label() const {return "Individual";}
167 virtual unsigned int makeKey(Ip::Address
&src_addr
) const;
170 /// \ingroup DelayPoolsInternal
171 class ClassCNetPool
: public VectorPool
175 void *operator new(size_t);
176 void operator delete (void *);
179 virtual char const *label() const {return "Network";}
180 virtual unsigned int makeKey (Ip::Address
&src_addr
) const;
183 /* don't use remote storage for these */
184 /// \ingroup DelayPoolsInternal
189 bool individualUsed (unsigned int index
)const;
190 unsigned char findHostMapPosition (unsigned char const host
) const;
191 bool individualAllocated (unsigned char host
) const;
192 unsigned char hostPosition (DelaySpec
&rate
, unsigned char const host
);
193 void initHostIndex (DelaySpec
&rate
, unsigned char index
, unsigned char host
);
194 void update (DelaySpec
const &, int incr
);
195 void stats(StoreEntry
*)const;
198 VectorMap
<unsigned char, DelayBucket
> individuals
;
201 /// \ingroup DelayPoolsInternal
202 class ClassCHostPool
: public CompositePoolNode
206 typedef RefCount
<ClassCHostPool
> Pointer
;
207 virtual void dump(StoreEntry
*entry
) const;
208 virtual void parse();
209 virtual void update(int incr
);
210 virtual void stats(StoreEntry
* sentry
);
212 virtual DelayIdComposite::Pointer
id(CompositeSelectionDetails
&);
217 bool keyAllocated (unsigned char const key
) const;
218 virtual DelaySpec
*rate() {return &spec
;}
220 virtual DelaySpec
const *rate() const {return &spec
;}
222 virtual char const *label() const {return "Individual";}
224 virtual unsigned int makeKey(Ip::Address
&src_addr
) const;
226 unsigned char makeHostKey(Ip::Address
&src_addr
) const;
229 VectorMap
<unsigned char, ClassCBucket
> buckets
;
233 friend class ClassCHostPool::Id
;
235 /// \ingroup DelayPoolsInternal
236 class Id
:public DelayIdComposite
240 void *operator new(size_t);
241 void operator delete (void *);
242 Id (RefCount
<ClassCHostPool
>, unsigned char, unsigned char);
243 virtual int bytesWanted (int min
, int max
) const;
244 virtual void bytesIn(int qty
);
247 RefCount
<ClassCHostPool
> theClassCHost
;
248 unsigned char theNet
;
249 unsigned char theHost
;
254 Aggregate::AggregateId::delayRead(DeferredRead
const &aRead
)
256 theAggregate
->delayRead(aRead
);
260 CommonPool::operator new(size_t size
)
262 DelayPools::MemoryUsed
+= sizeof (CommonPool
);
263 return ::operator new (size
);
267 CommonPool::operator delete(void *address
)
269 DelayPools::MemoryUsed
-= sizeof(CommonPool
);
270 ::operator delete(address
);
274 CommonPool::Factory(unsigned char _class
, CompositePoolNode::Pointer
& compositeCopy
)
276 CommonPool
*result
= new CommonPool
;
284 compositeCopy
= new Aggregate
;
285 result
->typeLabel
= "1";
289 result
->typeLabel
= "2";
291 DelayVector::Pointer temp
= new DelayVector
;
292 compositeCopy
= temp
.getRaw();
293 temp
->push_back (new Aggregate
);
294 temp
->push_back(new IndividualPool
);
299 result
->typeLabel
= "3";
301 DelayVector::Pointer temp
= new DelayVector
;
302 compositeCopy
= temp
.getRaw();
303 temp
->push_back (new Aggregate
);
304 temp
->push_back (new ClassCNetPool
);
305 temp
->push_back (new ClassCHostPool
);
310 result
->typeLabel
= "4";
312 DelayVector::Pointer temp
= new DelayVector
;
313 compositeCopy
= temp
.getRaw();
314 temp
->push_back (new Aggregate
);
315 temp
->push_back (new ClassCNetPool
);
316 temp
->push_back (new ClassCHostPool
);
318 temp
->push_back (new DelayUser
);
324 result
->typeLabel
= "5";
325 compositeCopy
= new DelayTagged
;
329 fatal ("unknown delay pool class");
336 CommonPool::CommonPool()
340 ClassCBucket::update (DelaySpec
const &rate
, int incr
)
342 /* If we aren't active, don't try to update us ! */
343 assert (rate
.restore_bps
!= -1);
345 for (unsigned int j
= 0; j
< individuals
.size(); ++j
)
346 individuals
.values
[j
].update (rate
, incr
);
350 ClassCBucket::stats(StoreEntry
*sentry
)const
352 for (unsigned int j
= 0; j
< individuals
.size(); ++j
) {
353 assert (individualUsed (j
));
354 storeAppendPrintf(sentry
, " %d:",individuals
.key_map
[j
]);
355 individuals
.values
[j
].stats (sentry
);
360 ClassCBucket::findHostMapPosition (unsigned char const host
) const
362 return individuals
.findKeyIndex(host
);
366 ClassCBucket::individualUsed (unsigned int index
)const
368 return individuals
.indexUsed(index
);
372 ClassCBucket::individualAllocated (unsigned char host
) const
374 return individualUsed(findHostMapPosition (host
));
378 ClassCBucket::hostPosition (DelaySpec
&rate
, unsigned char const host
)
380 if (individualAllocated (host
))
381 return findHostMapPosition(host
);
383 assert (!individualUsed (findHostMapPosition(host
)));
385 unsigned char result
= findHostMapPosition(host
);
387 initHostIndex (rate
, result
, host
);
393 ClassCBucket::initHostIndex (DelaySpec
&rate
, unsigned char index
, unsigned char host
)
395 assert (!individualUsed(index
));
397 unsigned char const newIndex
= individuals
.insert (host
);
399 /* give the bucket a default value */
400 individuals
.values
[newIndex
].init (rate
);
404 CompositePoolNode::operator new(size_t size
)
406 DelayPools::MemoryUsed
+= sizeof (CompositePoolNode
);
407 return ::operator new (size
);
411 CompositePoolNode::operator delete (void *address
)
413 DelayPools::MemoryUsed
-= sizeof (CompositePoolNode
);
414 ::operator delete (address
);
418 Aggregate::operator new(size_t size
)
420 DelayPools::MemoryUsed
+= sizeof (Aggregate
);
421 return ::operator new (size
);
425 Aggregate::operator delete (void *address
)
427 DelayPools::MemoryUsed
-= sizeof (Aggregate
);
428 ::operator delete (address
);
431 Aggregate::Aggregate()
433 theBucket
.init (*rate());
434 DelayPools::registerForUpdates (this);
437 Aggregate::~Aggregate()
439 DelayPools::deregisterForUpdates (this);
443 Aggregate::stats(StoreEntry
* sentry
)
445 rate()->stats (sentry
, "Aggregate");
447 if (rate()->restore_bps
== -1)
450 storeAppendPrintf(sentry
, "\t\tCurrent: ");
452 theBucket
.stats(sentry
);
454 storeAppendPrintf(sentry
, "\n\n");
458 Aggregate::dump(StoreEntry
*entry
) const
460 rate()->dump (entry
);
464 Aggregate::update(int incr
)
466 theBucket
.update(*rate(), incr
);
476 DelayIdComposite::Pointer
477 Aggregate::id(CompositeSelectionDetails
&details
)
479 if (rate()->restore_bps
!= -1)
480 return new AggregateId (this);
482 return new NullDelayId
;
486 Aggregate::AggregateId::operator new(size_t size
)
488 DelayPools::MemoryUsed
+= sizeof (AggregateId
);
489 return ::operator new (size
);
493 Aggregate::AggregateId::operator delete (void *address
)
495 DelayPools::MemoryUsed
-= sizeof (AggregateId
);
496 ::operator delete (address
);
499 Aggregate::AggregateId::AggregateId(RefCount
<Aggregate
> anAggregate
) : theAggregate(anAggregate
)
503 Aggregate::AggregateId::bytesWanted (int min
, int max
) const
505 return theAggregate
->theBucket
.bytesWanted(min
, max
);
509 Aggregate::AggregateId::bytesIn(int qty
)
511 theAggregate
->theBucket
.bytesIn(qty
);
512 theAggregate
->kickReads();
515 DelayPool
*DelayPools::delay_data
= NULL
;
516 time_t DelayPools::LastUpdate
= 0;
517 unsigned short DelayPools::pools_ (0);
520 DelayPools::RegisterWithCacheManager(void)
522 Mgr::RegisterAction("delay", "Delay Pool Levels", Stats
, 0, 1);
528 LastUpdate
= getCurrentTime();
529 RegisterWithCacheManager();
533 DelayPools::InitDelayData()
538 DelayPools::delay_data
= new DelayPool
[pools()];
540 DelayPools::MemoryUsed
+= pools() * sizeof(DelayPool
);
542 eventAdd("DelayPools::Update", DelayPools::Update
, NULL
, 1.0, 1);
546 DelayPools::FreeDelayData()
548 eventDelete(DelayPools::Update
, NULL
);
549 delete[] DelayPools::delay_data
;
550 DelayPools::MemoryUsed
-= pools() * sizeof(*DelayPools::delay_data
);
555 DelayPools::Update(void *unused
)
560 eventAdd("DelayPools::Update", Update
, NULL
, 1.0, 1);
562 int incr
= squid_curtime
- LastUpdate
;
567 LastUpdate
= squid_curtime
;
569 std::vector
<Updateable
*>::iterator pos
= toUpdate
.begin();
571 while (pos
!= toUpdate
.end()) {
572 (*pos
)->update(incr
);
578 DelayPools::registerForUpdates(Updateable
*anObject
)
580 /* Assume no doubles */
581 toUpdate
.push_back(anObject
);
585 DelayPools::deregisterForUpdates (Updateable
*anObject
)
587 std::vector
<Updateable
*>::iterator pos
= toUpdate
.begin();
589 while (pos
!= toUpdate
.end() && *pos
!= anObject
) {
593 if (pos
!= toUpdate
.end()) {
594 /* move all objects down one */
595 std::vector
<Updateable
*>::iterator temp
= pos
;
598 while (pos
!= toUpdate
.end()) {
608 std::vector
<Updateable
*> DelayPools::toUpdate
;
611 DelayPools::Stats(StoreEntry
* sentry
)
615 storeAppendPrintf(sentry
, "Delay pools configured: %d\n\n", DelayPools::pools());
617 for (i
= 0; i
< DelayPools::pools(); ++i
) {
618 if (DelayPools::delay_data
[i
].theComposite().getRaw()) {
619 storeAppendPrintf(sentry
, "Pool: %d\n\tClass: %s\n\n", i
+ 1, DelayPools::delay_data
[i
].pool
->theClassTypeLabel());
620 DelayPools::delay_data
[i
].theComposite()->stats (sentry
);
622 storeAppendPrintf(sentry
, "\tMisconfigured pool.\n\n");
625 storeAppendPrintf(sentry
, "Memory Used: %d bytes\n", (int) DelayPools::MemoryUsed
);
629 DelayPools::FreePools()
631 if (!DelayPools::pools())
644 DelayPools::pools(unsigned short newPools
)
647 debugs(3, DBG_CRITICAL
, "parse_delay_pool_count: multiple delay_pools lines, aborting all previous delay_pools config");
657 template <class Key
, class Value
>
658 VectorMap
<Key
,Value
>::VectorMap() : nextMapPosition(0)
661 template <class Key
, class Value
>
663 VectorMap
<Key
,Value
>::size() const
665 return nextMapPosition
;
668 template <class Key
, class Value
>
670 VectorMap
<Key
,Value
>::insert (Key
const key
)
672 unsigned char index
= findKeyIndex (key
);
673 assert (!indexUsed(index
));
675 key_map
[index
] = key
;
683 IndividualPool::operator new(size_t size
)
685 DelayPools::MemoryUsed
+= sizeof (IndividualPool
);
686 return ::operator new (size
);
690 IndividualPool::operator delete (void *address
)
692 DelayPools::MemoryUsed
-= sizeof (IndividualPool
);
693 ::operator delete (address
);
696 VectorPool::VectorPool()
698 DelayPools::registerForUpdates (this);
701 VectorPool::~VectorPool()
703 DelayPools::deregisterForUpdates (this);
707 VectorPool::stats(StoreEntry
* sentry
)
709 rate()->stats (sentry
, label());
711 if (rate()->restore_bps
== -1) {
712 storeAppendPrintf(sentry
, "\n\n");
716 storeAppendPrintf(sentry
, "\t\tCurrent:");
718 for (unsigned int i
= 0; i
< buckets
.size(); ++i
) {
719 storeAppendPrintf(sentry
, " %d:", buckets
.key_map
[i
]);
720 buckets
.values
[i
].stats(sentry
);
724 storeAppendPrintf(sentry
, " Not used yet.");
726 storeAppendPrintf(sentry
, "\n\n");
730 VectorPool::dump(StoreEntry
*entry
) const
732 rate()->dump (entry
);
736 VectorPool::update(int incr
)
738 if (rate()->restore_bps
== -1)
741 for (unsigned int i
= 0; i
< buckets
.size(); ++i
)
742 buckets
.values
[i
].update (*rate(), incr
);
752 VectorPool::keyAllocated (unsigned char const key
) const
754 return buckets
.indexUsed(buckets
.findKeyIndex (key
));
757 template <class Key
, class Value
>
759 VectorMap
<Key
,Value
>::indexUsed (unsigned char const index
) const
761 return index
< size();
764 /** returns the used position, or the position to allocate */
765 template <class Key
, class Value
>
767 VectorMap
<Key
,Value
>::findKeyIndex (Key
const key
) const
769 for (unsigned int index
= 0; index
< size(); ++index
) {
770 assert(indexUsed(index
));
772 if (key_map
[index
] == key
)
780 DelayIdComposite::Pointer
781 VectorPool::id(CompositeSelectionDetails
&details
)
783 if (rate()->restore_bps
== -1)
784 return new NullDelayId
;
786 /* non-IPv4 are not able to provide IPv4-bitmask for this pool type key. */
787 if ( !details
.src_addr
.isIPv4() )
788 return new NullDelayId
;
790 unsigned int key
= makeKey(details
.src_addr
);
792 if (keyAllocated(key
))
793 return new Id(this, buckets
.findKeyIndex(key
));
795 unsigned char const resultIndex
= buckets
.insert(key
);
797 buckets
.values
[resultIndex
].init(*rate());
799 return new Id(this, resultIndex
);
803 VectorPool::Id::operator new(size_t size
)
805 DelayPools::MemoryUsed
+= sizeof (Id
);
806 return ::operator new (size
);
810 VectorPool::Id::operator delete(void *address
)
812 DelayPools::MemoryUsed
-= sizeof (Id
);
813 ::operator delete (address
);
816 VectorPool::Id::Id(VectorPool::Pointer aPool
, int anIndex
) : theVector (aPool
), theIndex (anIndex
)
820 VectorPool::Id::bytesWanted (int min
, int max
) const
822 return theVector
->buckets
.values
[theIndex
].bytesWanted (min
, max
);
826 VectorPool::Id::bytesIn(int qty
)
828 theVector
->buckets
.values
[theIndex
].bytesIn (qty
);
832 IndividualPool::makeKey(Ip::Address
&src_addr
) const
834 /* IPv4 required for this pool */
835 if ( !src_addr
.isIPv4() )
839 src_addr
.getInAddr(host
);
840 return (ntohl(host
.s_addr
) & 0xff);
844 ClassCNetPool::operator new(size_t size
)
846 DelayPools::MemoryUsed
+= sizeof (ClassCNetPool
);
847 return ::operator new (size
);
851 ClassCNetPool::operator delete (void *address
)
853 DelayPools::MemoryUsed
-= sizeof (ClassCNetPool
);
854 ::operator delete (address
);
858 ClassCNetPool::makeKey(Ip::Address
&src_addr
) const
860 /* IPv4 required for this pool */
861 if ( !src_addr
.isIPv4() )
865 src_addr
.getInAddr(net
);
866 return ( (ntohl(net
.s_addr
) >> 8) & 0xff);
869 ClassCHostPool::ClassCHostPool()
871 DelayPools::registerForUpdates (this);
874 ClassCHostPool::~ClassCHostPool()
876 DelayPools::deregisterForUpdates (this);
880 ClassCHostPool::stats(StoreEntry
* sentry
)
882 rate()->stats (sentry
, label());
884 if (rate()->restore_bps
== -1) {
885 storeAppendPrintf(sentry
, "\n\n");
889 for (unsigned int index
= 0; index
< buckets
.size(); ++index
) {
890 storeAppendPrintf(sentry
, "\t\tCurrent [Network %d]:", buckets
.key_map
[index
]);
891 buckets
.values
[index
].stats (sentry
);
892 storeAppendPrintf(sentry
, "\n");
896 storeAppendPrintf(sentry
, "\t\tCurrent [All networks]: Not used yet.\n");
898 storeAppendPrintf(sentry
, "\n\n");
902 ClassCHostPool::dump(StoreEntry
*entry
) const
904 rate()->dump (entry
);
908 ClassCHostPool::update(int incr
)
910 if (rate()->restore_bps
== -1)
913 for (unsigned int i
= 0; i
< buckets
.size(); ++i
)
914 buckets
.values
[i
].update (*rate(), incr
);
918 ClassCHostPool::parse()
924 ClassCHostPool::keyAllocated (unsigned char const key
) const
926 return buckets
.indexUsed(buckets
.findKeyIndex (key
));
930 ClassCHostPool::makeHostKey(Ip::Address
&src_addr
) const
932 /* IPv4 required for this pool */
933 if ( !src_addr
.isIPv4() )
936 /* Temporary bypass for IPv4-only */
938 src_addr
.getInAddr(host
);
939 return (ntohl(host
.s_addr
) & 0xff);
943 ClassCHostPool::makeKey(Ip::Address
&src_addr
) const
945 /* IPv4 required for this pool */
946 if ( !src_addr
.isIPv4() )
950 src_addr
.getInAddr(net
);
951 return ( (ntohl(net
.s_addr
) >> 8) & 0xff);
954 DelayIdComposite::Pointer
955 ClassCHostPool::id(CompositeSelectionDetails
&details
)
957 if (rate()->restore_bps
== -1)
958 return new NullDelayId
;
960 /* non-IPv4 are not able to provide IPv4-bitmask for this pool type key. */
961 if ( !details
.src_addr
.isIPv4() )
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
);
1011 #endif /* USE_DELAY_POOLS */