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