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