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