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