ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/myhttpd/tbf.pl
Revision: 1.1
Committed: Sun May 19 21:00:48 2002 UTC (22 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 package tbf;
2    
3     # kind of token-bucket-filter
4    
5     my $max_per_client = 1e5;
6    
7     sub new {
8     my $class = shift;
9     my %arg = @_;
10     my $self = bless \%arg, $class;
11    
12     $self->{maxbucket} ||= $self->{rate} * 3; # max 3s bucket
13     $self->{minbucket} ||= $self->{rate}; # minimum bucket to share
14     $self->{interval} ||= $::BUFSIZE / $max_per_client; # good default interval
15    
16     if ($self->{rate}) {
17     $self->{w} = Event->timer(hard => 1, after => 0, interval => $self->{interval}, repeat => 1, cb => sub {
18     $self->inject($self->{rate} * $self->{interval});
19     });
20     } else {
21     die "chaining not yet implemented\n";
22     }
23    
24     $self;
25     }
26    
27     sub DESTROY {
28     my $self = shift;
29    
30     $self->{w}->cancel;
31     }
32    
33     sub inject {
34     my ($self, $bytes) = @_;
35    
36     $self->{bucket} += $bytes;
37    
38     while ($self->{bucket} >= $self->{minbucket}) {
39     if ($self->{waitw}) {
40     my $rate = $self->{bucket} / $self->{waitw};
41    
42     for my $v (values %{$self->{waitq}}) {
43     $self->{bucket} -= $rate * $v->[0];
44     $v->[1] += $rate * $v->[0];
45    
46     if ($v->[1] >= $v->[2]) {
47     $self->{bucket} += $v->[1] - $v->[2];
48     $v->[3]->();
49     }
50     }
51    
52     } else {
53     if ($self->{maxbucket} < $self->{bucket}) {
54     ::slog (9, "unused bandwith: ".($self->{bucket} - $self->{maxbucket}));#d#
55     $self->{bucket} = $self->{maxbucket};
56     }
57     }
58    
59     last;
60     }
61     }
62    
63     my $_tbf_id;
64    
65     sub request {
66     my ($self, $bytes, $weight) = @_;
67    
68     $weight ||= 1;
69    
70     if ($self->{waitw} || $self->{bucket} < $bytes || 1) {
71     my $coro = $Coro::current;
72     my $id = $_tbf_id++;
73    
74     $self->{waitw} += $weight;
75     $self->{waitq}{$id} = [$weight, 0, $bytes, sub {
76     delete $self->{waitq}{$id};
77     $self->{waitw} -= $weight;
78     $coro->ready;
79     }];
80    
81     Coro::schedule;
82     } else {
83     $self->{bucket} -= $bytes;
84     }
85     }
86    
87     1;