2 * Copyright (C) 1996-2015 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 "ip/Address.h"
34 #include "MemObject.h"
35 #include "mgr/Registration.h"
36 #include "NullDelayId.h"
37 #include "SquidString.h"
38 #include "SquidTime.h"
40 #include "StoreClient.h"
42 /// \ingroup DelayPoolsInternal
43 long DelayPools::MemoryUsed
= 0;
45 /// \ingroup DelayPoolsInternal
46 class Aggregate
: public CompositePoolNode
50 typedef RefCount
<Aggregate
> Pointer
;
51 void *operator new(size_t);
52 void operator delete (void *);
55 virtual DelaySpec
*rate() {return &spec
;}
57 virtual DelaySpec
const *rate() const {return &spec
;}
59 virtual void stats(StoreEntry
* sentry
);
60 virtual void dump(StoreEntry
*entry
) const;
61 virtual void update(int incr
);
64 virtual DelayIdComposite::Pointer
id(CompositeSelectionDetails
&);
68 /// \ingroup DelayPoolsInternal
69 class AggregateId
:public DelayIdComposite
73 void *operator new(size_t);
74 void operator delete (void *);
75 AggregateId (RefCount
<Aggregate
>);
76 virtual int bytesWanted (int min
, int max
) const;
77 virtual void bytesIn(int qty
);
78 virtual void delayRead(DeferredRead
const &);
81 RefCount
<Aggregate
> theAggregate
;
84 friend class AggregateId
;
86 DelayBucket theBucket
;
90 /// \ingroup DelayPoolsInternal
91 template <class Key
, class Value
>
97 unsigned int size() const;
98 unsigned char findKeyIndex (Key
const key
) const;
99 bool indexUsed (unsigned char const index
) const;
100 unsigned int insert (Key
const key
);
102 #define IND_MAP_SZ 256
104 Key key_map
[IND_MAP_SZ
];
105 Value values
[IND_MAP_SZ
];
108 unsigned int nextMapPosition
;
111 /// \ingroup DelayPoolsInternal
112 class VectorPool
: public CompositePoolNode
116 typedef RefCount
<VectorPool
> Pointer
;
117 virtual void dump(StoreEntry
*entry
) const;
118 virtual void parse();
119 virtual void update(int incr
);
120 virtual void stats(StoreEntry
* sentry
);
122 virtual DelayIdComposite::Pointer
id(CompositeSelectionDetails
&);
123 VectorMap
<unsigned char, DelayBucket
> buckets
;
128 bool keyAllocated (unsigned char const key
) const;
129 virtual DelaySpec
*rate() {return &spec
;}
131 virtual DelaySpec
const *rate() const {return &spec
;}
133 virtual char const *label() const = 0;
135 virtual unsigned int makeKey(Ip::Address
&src_addr
) const = 0;
139 /// \ingroup DelayPoolsInternal
140 class Id
:public DelayIdComposite
144 void *operator new(size_t);
145 void operator delete (void *);
146 Id (RefCount
<VectorPool
>, int);
147 virtual int bytesWanted (int min
, int max
) const;
148 virtual void bytesIn(int qty
);
151 RefCount
<VectorPool
> theVector
;
156 /// \ingroup DelayPoolsInternal
157 class IndividualPool
: public VectorPool
161 void *operator new(size_t);
162 void operator delete(void *);
165 virtual char const *label() const {return "Individual";}
166 virtual unsigned int makeKey(Ip::Address
&src_addr
) const;
169 /// \ingroup DelayPoolsInternal
170 class ClassCNetPool
: public VectorPool
174 void *operator new(size_t);
175 void operator delete (void *);
178 virtual char const *label() const {return "Network";}
179 virtual unsigned int makeKey (Ip::Address
&src_addr
) const;
182 /* don't use remote storage for these */
183 /// \ingroup DelayPoolsInternal
188 bool individualUsed (unsigned int index
)const;
189 unsigned char findHostMapPosition (unsigned char const host
) const;
190 bool individualAllocated (unsigned char host
) const;
191 unsigned char hostPosition (DelaySpec
&rate
, unsigned char const host
);
192 void initHostIndex (DelaySpec
&rate
, unsigned char index
, unsigned char host
);
193 void update (DelaySpec
const &, int incr
);
194 void stats(StoreEntry
*)const;
197 VectorMap
<unsigned char, DelayBucket
> individuals
;
200 /// \ingroup DelayPoolsInternal
201 class ClassCHostPool
: public CompositePoolNode
205 typedef RefCount
<ClassCHostPool
> Pointer
;
206 virtual void dump(StoreEntry
*entry
) const;
207 virtual void parse();
208 virtual void update(int incr
);
209 virtual void stats(StoreEntry
* sentry
);
211 virtual DelayIdComposite::Pointer
id(CompositeSelectionDetails
&);
216 bool keyAllocated (unsigned char const key
) const;
217 virtual DelaySpec
*rate() {return &spec
;}
219 virtual DelaySpec
const *rate() const {return &spec
;}
221 virtual char const *label() const {return "Individual";}
223 virtual unsigned int makeKey(Ip::Address
&src_addr
) const;
225 unsigned char makeHostKey(Ip::Address
&src_addr
) const;
228 VectorMap
<unsigned char, ClassCBucket
> buckets
;
232 friend class ClassCHostPool::Id
;
234 /// \ingroup DelayPoolsInternal
235 class Id
:public DelayIdComposite
239 void *operator new(size_t);
240 void operator delete (void *);
241 Id (RefCount
<ClassCHostPool
>, unsigned char, unsigned char);
242 virtual int bytesWanted (int min
, int max
) const;
243 virtual void bytesIn(int qty
);
246 RefCount
<ClassCHostPool
> theClassCHost
;
247 unsigned char theNet
;
248 unsigned char theHost
;
253 Aggregate::AggregateId::delayRead(DeferredRead
const &aRead
)
255 theAggregate
->delayRead(aRead
);
259 CommonPool::operator new(size_t size
)
261 DelayPools::MemoryUsed
+= sizeof (CommonPool
);
262 return ::operator new (size
);
266 CommonPool::operator delete(void *address
)
268 DelayPools::MemoryUsed
-= sizeof(CommonPool
);
269 ::operator delete(address
);
273 CommonPool::Factory(unsigned char _class
, CompositePoolNode::Pointer
& compositeCopy
)
275 CommonPool
*result
= new CommonPool
;
283 compositeCopy
= new Aggregate
;
284 result
->typeLabel
= "1";
288 result
->typeLabel
= "2";
290 DelayVector::Pointer temp
= new DelayVector
;
291 compositeCopy
= temp
.getRaw();
292 temp
->push_back (new Aggregate
);
293 temp
->push_back(new IndividualPool
);
298 result
->typeLabel
= "3";
300 DelayVector::Pointer temp
= new DelayVector
;
301 compositeCopy
= temp
.getRaw();
302 temp
->push_back (new Aggregate
);
303 temp
->push_back (new ClassCNetPool
);
304 temp
->push_back (new ClassCHostPool
);
309 result
->typeLabel
= "4";
311 DelayVector::Pointer temp
= new DelayVector
;
312 compositeCopy
= temp
.getRaw();
313 temp
->push_back (new Aggregate
);
314 temp
->push_back (new ClassCNetPool
);
315 temp
->push_back (new ClassCHostPool
);
317 temp
->push_back (new DelayUser
);
323 result
->typeLabel
= "5";
324 compositeCopy
= new DelayTagged
;
328 fatal ("unknown delay pool class");
335 CommonPool::CommonPool()
339 ClassCBucket::update (DelaySpec
const &rate
, int incr
)
341 /* If we aren't active, don't try to update us ! */
342 assert (rate
.restore_bps
!= -1);
344 for (unsigned int j
= 0; j
< individuals
.size(); ++j
)
345 individuals
.values
[j
].update (rate
, incr
);
349 ClassCBucket::stats(StoreEntry
*sentry
)const
351 for (unsigned int j
= 0; j
< individuals
.size(); ++j
) {
352 assert (individualUsed (j
));
353 storeAppendPrintf(sentry
, " %d:",individuals
.key_map
[j
]);
354 individuals
.values
[j
].stats (sentry
);
359 ClassCBucket::findHostMapPosition (unsigned char const host
) const
361 return individuals
.findKeyIndex(host
);
365 ClassCBucket::individualUsed (unsigned int index
)const
367 return individuals
.indexUsed(index
);
371 ClassCBucket::individualAllocated (unsigned char host
) const
373 return individualUsed(findHostMapPosition (host
));
377 ClassCBucket::hostPosition (DelaySpec
&rate
, unsigned char const host
)
379 if (individualAllocated (host
))
380 return findHostMapPosition(host
);
382 assert (!individualUsed (findHostMapPosition(host
)));
384 unsigned char result
= findHostMapPosition(host
);
386 initHostIndex (rate
, result
, host
);
392 ClassCBucket::initHostIndex (DelaySpec
&rate
, unsigned char index
, unsigned char host
)
394 assert (!individualUsed(index
));
396 unsigned char const newIndex
= individuals
.insert (host
);
398 /* give the bucket a default value */
399 individuals
.values
[newIndex
].init (rate
);
403 CompositePoolNode::operator new(size_t size
)
405 DelayPools::MemoryUsed
+= sizeof (CompositePoolNode
);
406 return ::operator new (size
);
410 CompositePoolNode::operator delete (void *address
)
412 DelayPools::MemoryUsed
-= sizeof (CompositePoolNode
);
413 ::operator delete (address
);
417 Aggregate::operator new(size_t size
)
419 DelayPools::MemoryUsed
+= sizeof (Aggregate
);
420 return ::operator new (size
);
424 Aggregate::operator delete (void *address
)
426 DelayPools::MemoryUsed
-= sizeof (Aggregate
);
427 ::operator delete (address
);
430 Aggregate::Aggregate()
432 theBucket
.init (*rate());
433 DelayPools::registerForUpdates (this);
436 Aggregate::~Aggregate()
438 DelayPools::deregisterForUpdates (this);
442 Aggregate::stats(StoreEntry
* sentry
)
444 rate()->stats (sentry
, "Aggregate");
446 if (rate()->restore_bps
== -1)
449 storeAppendPrintf(sentry
, "\t\tCurrent: ");
451 theBucket
.stats(sentry
);
453 storeAppendPrintf(sentry
, "\n\n");
457 Aggregate::dump(StoreEntry
*entry
) const
459 rate()->dump (entry
);
463 Aggregate::update(int incr
)
465 theBucket
.update(*rate(), incr
);
475 DelayIdComposite::Pointer
476 Aggregate::id(CompositeSelectionDetails
&details
)
478 if (rate()->restore_bps
!= -1)
479 return new AggregateId (this);
481 return new NullDelayId
;
485 Aggregate::AggregateId::operator new(size_t size
)
487 DelayPools::MemoryUsed
+= sizeof (AggregateId
);
488 return ::operator new (size
);
492 Aggregate::AggregateId::operator delete (void *address
)
494 DelayPools::MemoryUsed
-= sizeof (AggregateId
);
495 ::operator delete (address
);
498 Aggregate::AggregateId::AggregateId(RefCount
<Aggregate
> anAggregate
) : theAggregate(anAggregate
)
502 Aggregate::AggregateId::bytesWanted (int min
, int max
) const
504 return theAggregate
->theBucket
.bytesWanted(min
, max
);
508 Aggregate::AggregateId::bytesIn(int qty
)
510 theAggregate
->theBucket
.bytesIn(qty
);
511 theAggregate
->kickReads();
514 DelayPool
*DelayPools::delay_data
= NULL
;
515 time_t DelayPools::LastUpdate
= 0;
516 unsigned short DelayPools::pools_ (0);
519 DelayPools::RegisterWithCacheManager(void)
521 Mgr::RegisterAction("delay", "Delay Pool Levels", Stats
, 0, 1);
527 LastUpdate
= getCurrentTime();
528 RegisterWithCacheManager();
532 DelayPools::InitDelayData()
537 DelayPools::delay_data
= new DelayPool
[pools()];
539 DelayPools::MemoryUsed
+= pools() * sizeof(DelayPool
);
541 eventAdd("DelayPools::Update", DelayPools::Update
, NULL
, 1.0, 1);
545 DelayPools::FreeDelayData()
547 eventDelete(DelayPools::Update
, NULL
);
548 delete[] DelayPools::delay_data
;
549 DelayPools::MemoryUsed
-= pools() * sizeof(*DelayPools::delay_data
);
554 DelayPools::Update(void *unused
)
559 eventAdd("DelayPools::Update", Update
, NULL
, 1.0, 1);
561 int incr
= squid_curtime
- LastUpdate
;
566 LastUpdate
= squid_curtime
;
568 std::vector
<Updateable
*>::iterator pos
= toUpdate
.begin();
570 while (pos
!= toUpdate
.end()) {
571 (*pos
)->update(incr
);
577 DelayPools::registerForUpdates(Updateable
*anObject
)
579 /* Assume no doubles */
580 toUpdate
.push_back(anObject
);
584 DelayPools::deregisterForUpdates (Updateable
*anObject
)
586 std::vector
<Updateable
*>::iterator pos
= toUpdate
.begin();
588 while (pos
!= toUpdate
.end() && *pos
!= anObject
) {
592 if (pos
!= toUpdate
.end()) {
593 /* move all objects down one */
594 std::vector
<Updateable
*>::iterator temp
= pos
;
597 while (pos
!= toUpdate
.end()) {
607 std::vector
<Updateable
*> DelayPools::toUpdate
;
610 DelayPools::Stats(StoreEntry
* sentry
)
614 storeAppendPrintf(sentry
, "Delay pools configured: %d\n\n", DelayPools::pools());
616 for (i
= 0; i
< DelayPools::pools(); ++i
) {
617 if (DelayPools::delay_data
[i
].theComposite().getRaw()) {
618 storeAppendPrintf(sentry
, "Pool: %d\n\tClass: %s\n\n", i
+ 1, DelayPools::delay_data
[i
].pool
->theClassTypeLabel());
619 DelayPools::delay_data
[i
].theComposite()->stats (sentry
);
621 storeAppendPrintf(sentry
, "\tMisconfigured pool.\n\n");
624 storeAppendPrintf(sentry
, "Memory Used: %d bytes\n", (int) DelayPools::MemoryUsed
);
628 DelayPools::FreePools()
630 if (!DelayPools::pools())
643 DelayPools::pools(unsigned short newPools
)
646 debugs(3, DBG_CRITICAL
, "parse_delay_pool_count: multiple delay_pools lines, aborting all previous delay_pools config");
656 template <class Key
, class Value
>
657 VectorMap
<Key
,Value
>::VectorMap() : nextMapPosition(0)
660 template <class Key
, class Value
>
662 VectorMap
<Key
,Value
>::size() const
664 return nextMapPosition
;
667 template <class Key
, class Value
>
669 VectorMap
<Key
,Value
>::insert (Key
const key
)
671 unsigned char index
= findKeyIndex (key
);
672 assert (!indexUsed(index
));
674 key_map
[index
] = key
;
682 IndividualPool::operator new(size_t size
)
684 DelayPools::MemoryUsed
+= sizeof (IndividualPool
);
685 return ::operator new (size
);
689 IndividualPool::operator delete (void *address
)
691 DelayPools::MemoryUsed
-= sizeof (IndividualPool
);
692 ::operator delete (address
);
695 VectorPool::VectorPool()
697 DelayPools::registerForUpdates (this);
700 VectorPool::~VectorPool()
702 DelayPools::deregisterForUpdates (this);
706 VectorPool::stats(StoreEntry
* sentry
)
708 rate()->stats (sentry
, label());
710 if (rate()->restore_bps
== -1) {
711 storeAppendPrintf(sentry
, "\n\n");
715 storeAppendPrintf(sentry
, "\t\tCurrent:");
717 for (unsigned int i
= 0; i
< buckets
.size(); ++i
) {
718 storeAppendPrintf(sentry
, " %d:", buckets
.key_map
[i
]);
719 buckets
.values
[i
].stats(sentry
);
723 storeAppendPrintf(sentry
, " Not used yet.");
725 storeAppendPrintf(sentry
, "\n\n");
729 VectorPool::dump(StoreEntry
*entry
) const
731 rate()->dump (entry
);
735 VectorPool::update(int incr
)
737 if (rate()->restore_bps
== -1)
740 for (unsigned int i
= 0; i
< buckets
.size(); ++i
)
741 buckets
.values
[i
].update (*rate(), incr
);
751 VectorPool::keyAllocated (unsigned char const key
) const
753 return buckets
.indexUsed(buckets
.findKeyIndex (key
));
756 template <class Key
, class Value
>
758 VectorMap
<Key
,Value
>::indexUsed (unsigned char const index
) const
760 return index
< size();
763 /** returns the used position, or the position to allocate */
764 template <class Key
, class Value
>
766 VectorMap
<Key
,Value
>::findKeyIndex (Key
const key
) const
768 for (unsigned int index
= 0; index
< size(); ++index
) {
769 assert(indexUsed(index
));
771 if (key_map
[index
] == key
)
779 DelayIdComposite::Pointer
780 VectorPool::id(CompositeSelectionDetails
&details
)
782 if (rate()->restore_bps
== -1)
783 return new NullDelayId
;
785 /* non-IPv4 are not able to provide IPv4-bitmask for this pool type key. */
786 if ( !details
.src_addr
.isIPv4() )
787 return new NullDelayId
;
789 unsigned int key
= makeKey(details
.src_addr
);
791 if (keyAllocated(key
))
792 return new Id(this, buckets
.findKeyIndex(key
));
794 unsigned char const resultIndex
= buckets
.insert(key
);
796 buckets
.values
[resultIndex
].init(*rate());
798 return new Id(this, resultIndex
);
802 VectorPool::Id::operator new(size_t size
)
804 DelayPools::MemoryUsed
+= sizeof (Id
);
805 return ::operator new (size
);
809 VectorPool::Id::operator delete(void *address
)
811 DelayPools::MemoryUsed
-= sizeof (Id
);
812 ::operator delete (address
);
815 VectorPool::Id::Id(VectorPool::Pointer aPool
, int anIndex
) : theVector (aPool
), theIndex (anIndex
)
819 VectorPool::Id::bytesWanted (int min
, int max
) const
821 return theVector
->buckets
.values
[theIndex
].bytesWanted (min
, max
);
825 VectorPool::Id::bytesIn(int qty
)
827 theVector
->buckets
.values
[theIndex
].bytesIn (qty
);
831 IndividualPool::makeKey(Ip::Address
&src_addr
) const
833 /* IPv4 required for this pool */
834 if ( !src_addr
.isIPv4() )
838 src_addr
.getInAddr(host
);
839 return (ntohl(host
.s_addr
) & 0xff);
843 ClassCNetPool::operator new(size_t size
)
845 DelayPools::MemoryUsed
+= sizeof (ClassCNetPool
);
846 return ::operator new (size
);
850 ClassCNetPool::operator delete (void *address
)
852 DelayPools::MemoryUsed
-= sizeof (ClassCNetPool
);
853 ::operator delete (address
);
857 ClassCNetPool::makeKey(Ip::Address
&src_addr
) const
859 /* IPv4 required for this pool */
860 if ( !src_addr
.isIPv4() )
864 src_addr
.getInAddr(net
);
865 return ( (ntohl(net
.s_addr
) >> 8) & 0xff);
868 ClassCHostPool::ClassCHostPool()
870 DelayPools::registerForUpdates (this);
873 ClassCHostPool::~ClassCHostPool()
875 DelayPools::deregisterForUpdates (this);
879 ClassCHostPool::stats(StoreEntry
* sentry
)
881 rate()->stats (sentry
, label());
883 if (rate()->restore_bps
== -1) {
884 storeAppendPrintf(sentry
, "\n\n");
888 for (unsigned int index
= 0; index
< buckets
.size(); ++index
) {
889 storeAppendPrintf(sentry
, "\t\tCurrent [Network %d]:", buckets
.key_map
[index
]);
890 buckets
.values
[index
].stats (sentry
);
891 storeAppendPrintf(sentry
, "\n");
895 storeAppendPrintf(sentry
, "\t\tCurrent [All networks]: Not used yet.\n");
897 storeAppendPrintf(sentry
, "\n\n");
901 ClassCHostPool::dump(StoreEntry
*entry
) const
903 rate()->dump (entry
);
907 ClassCHostPool::update(int incr
)
909 if (rate()->restore_bps
== -1)
912 for (unsigned int i
= 0; i
< buckets
.size(); ++i
)
913 buckets
.values
[i
].update (*rate(), incr
);
917 ClassCHostPool::parse()
923 ClassCHostPool::keyAllocated (unsigned char const key
) const
925 return buckets
.indexUsed(buckets
.findKeyIndex (key
));
929 ClassCHostPool::makeHostKey(Ip::Address
&src_addr
) const
931 /* IPv4 required for this pool */
932 if ( !src_addr
.isIPv4() )
935 /* Temporary bypass for IPv4-only */
937 src_addr
.getInAddr(host
);
938 return (ntohl(host
.s_addr
) & 0xff);
942 ClassCHostPool::makeKey(Ip::Address
&src_addr
) const
944 /* IPv4 required for this pool */
945 if ( !src_addr
.isIPv4() )
949 src_addr
.getInAddr(net
);
950 return ( (ntohl(net
.s_addr
) >> 8) & 0xff);
953 DelayIdComposite::Pointer
954 ClassCHostPool::id(CompositeSelectionDetails
&details
)
956 if (rate()->restore_bps
== -1)
957 return new NullDelayId
;
959 /* non-IPv4 are not able to provide IPv4-bitmask for this pool type key. */
960 if ( !details
.src_addr
.isIPv4() )
961 return new NullDelayId
;
963 unsigned int key
= makeKey (details
.src_addr
);
965 unsigned char host
= makeHostKey (details
.src_addr
);
967 unsigned char hostIndex
;
969 unsigned char netIndex
;
971 if (keyAllocated (key
))
972 netIndex
= buckets
.findKeyIndex(key
);
974 netIndex
= buckets
.insert (key
);
976 hostIndex
= buckets
.values
[netIndex
].hostPosition (*rate(), host
);
978 return new Id (this, netIndex
, hostIndex
);
982 ClassCHostPool::Id::operator new(size_t size
)
984 DelayPools::MemoryUsed
+= sizeof (Id
);
985 return ::operator new (size
);
989 ClassCHostPool::Id::operator delete (void *address
)
991 DelayPools::MemoryUsed
-= sizeof (Id
);
992 ::operator delete (address
);
995 ClassCHostPool::Id::Id (ClassCHostPool::Pointer aPool
, unsigned char aNet
, unsigned char aHost
) : theClassCHost (aPool
), theNet (aNet
), theHost (aHost
)
999 ClassCHostPool::Id::bytesWanted (int min
, int max
) const
1001 return theClassCHost
->buckets
.values
[theNet
].individuals
.values
[theHost
].bytesWanted (min
, max
);
1005 ClassCHostPool::Id::bytesIn(int qty
)
1007 theClassCHost
->buckets
.values
[theNet
].individuals
.values
[theHost
].bytesIn (qty
);
1010 #endif /* USE_DELAY_POOLS */