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