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