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