AnyEvent-Handle-Throttle
view release on metacpan or search on metacpan
Version 0.000002005 | 2010-10-26 17:01:07Z (Tue, 26 Oct 2010) | 922dfa3
Internal/Behavioral Changes:
* Correctly deal with errors when calling sysread( ... )
Version 0.000002004 | 2010-08-25 18:16:33Z (Wed, 25 Aug 2010) | bc1ea36
API Changes/Compatibility Information:
* Adding methods for global and per-object download totals
Version 0.000002003 | 2010-07-04 01:48:52Z (Sun, 04 Jul 2010) | d908b81
Documentation/Sample Code/Test Suite/Metadata:
* Moving to META.json
* Network based (HTTP) tests are run concurrently to avoid save time
Version 0.000002002 | 2010-06-24 03:04:03Z (Thu, 24 Jun 2010) | edb30dd
API Changes/Compatibility Information:
* The entire API has changed.
- All methods have been renamed to better fit their function which has
remained the same.
* New global limits.
Documentation/Sample Code/Test Suite/Metadata:
* New tests:
- t/http_global.t tests global bandwidth limits
- t/loopback.t fallback test when the http tests fail (system config?)
* (Hopefully) Updated bugtracker and repository metadata
Notes:
* Beijing! Family! Pictures! Food! Sleep!
Version 0.000002001 | 2010-06-17 01:39:49Z (Thu, 17 Jun 2010) | 6ee738a
Resolved Issues/Bug Fixes:
* Instead of allowing unlimited transfer, an undefined download_rate
Build.PL
Changes
lib/AnyEvent/Handle/Throttle.pm
MANIFEST This list of files
META.json
README
t/http.t
t/http_default.t
t/http_global.t
t/loopback.t
$bytes = $handle->upload_speed( )
Returns the amount of data written during the previous period.
$bytes = $handle->download_speed( )
Returns the amount of data read during the previous period.
If you're using AnyEvent::Handle::Throttle to limit bandwidth and
realize you'd rather set flat limits on the total bandwidth instead of
per-handle, try these methods:
AnyEvent::Handle::Throttle->global_upload_limit( $bytes )
Sets/returns the current global upload rate in bytes per period.
AnyEvent::Handle::Throttle->global_download_limit( $bytes )
Sets/returns the current global download rate in bytes per period.
$bytes = $handle->global_upload_speed( )
Returns the amount of data written through all
AnyEvent::Handle::Throttle objects during the previous period.
$bytes = $handle->global_download_speed( )
Returns the amount of data read through all
AnyEvent::Handle::Throttle objects during the previous period.
$bytes = $handle->download_total( )
Returns the total amount of data read through the
AnyEvent::Handle::Throttle object.
$bytes = $handle->upload_total( )
Returns the total amount of data written through the
AnyEvent::Handle::Throttle object.
$bytes = $handle->global_download_total( )
Returns the total amount of data read through all
AnyEvent::Handle::Throttle objects so far.
$bytes = $handle->global_upload_total( )
Returns the total amount of data sent through all
AnyEvent::Handle::Throttle objects so far.
Notes
* The current default period is 1 second.
* On destruction, all remaining data is sent ASAP, ignoring the user
defined upload limit. This may change in the future.
Bugs
lib/AnyEvent/Handle/Throttle.pm view on Meta::CPAN
$_[1] ? $_[0]->{upload_limit} = $_[1] : $_[0]->{upload_limit};
}
sub download_limit {
$_[1] ? $_[0]->{download_limit} = $_[1] : $_[0]->{download_limit};
}
sub upload_total { $_[0]->{upload_total} }
sub download_total { $_[0]->{download_total} }
sub upload_speed { $_[0]->{upload_speed} }
sub download_speed { $_[0]->{download_speed} }
my ($global_upload_total, $global_download_total,
$global_upload_limit, $global_download_limit,
$global_upload_speed, $global_download_speed
);
my $global_period = 1;
sub global_upload_limit {
$_[1] ? $global_upload_limit = $_[1] : $global_upload_limit;
}
sub global_download_limit {
$_[1] ? $global_download_limit = $_[1] : $global_download_limit;
}
sub global_upload_total {$global_upload_total}
sub global_download_total {$global_download_total}
sub global_upload_speed {$global_upload_speed}
sub global_download_speed {$global_download_speed}
my ($global_read_size, $global_write_size,
$global__upload_speed, $global__download_speed);
my $global_reset_cb = sub {
$global_read_size = $global_download_limit;
$global_write_size = $global_upload_limit || 8 * 1024;
$global_upload_speed = $global__upload_speed;
$global_download_speed = $global__download_speed;
$global__upload_speed = $global__download_speed = 0;
};
$global_reset_cb->();
our $global_reset = AE::timer(0, $global_period, $global_reset_cb);
sub _start {
my $self = shift;
my $reset = sub {
$self->{read_size} = $self->{download_limit};
$self->{write_size} = $self->{upload_limit} || 8 * 1024;
$self->{upload_speed} = $self->{_upload_speed};
$self->{download_speed} = $self->{_download_speed};
$self->{_upload_speed} = $self->{_download_speed} = 0;
};
lib/AnyEvent/Handle/Throttle.pm view on Meta::CPAN
$self->{_reset} = AE::timer(0, $self->{_period}, $reset);
$reset->();
$self->SUPER::_start(@_);
}
sub start_read {
my ($self) = @_;
unless ($self->{_rw} || $self->{_eof} || !$self->{fh}) {
Scalar::Util::weaken $self;
$self->{_rw} = AE::io $self->{fh}, 0, sub {
my ($read) = sort grep {defined} $global_read_size,
$self->{read_size};
my ($period) = sort grep {defined} $global_period,
$self->{_period};
if (defined $read && $read <= 0) {
$self->stop_read;
return $self->{_pause_read} = AE::timer(
$period, 0,
sub {
delete $self->{_pause_read};
$self->start_read;
}
);
}
my $rbuf = \($self->{tls} ? my $buf : $self->{rbuf});
$$rbuf ||= '';
my $len = sysread $self->{fh}, $$rbuf, $read || 8192,
length $$rbuf;
if (defined $len) {
if ($len > 0) {
$self->{read_size} -= $len;
$global_read_size -= $len;
$self->{download_total} += $len;
$global_download_total += $len;
$self->{_download_speed} += $len;
$global__download_speed += $len;
$self->{_activity} = $self->{_ractivity} = AE::now;
if ($self->{tls}) {
Net::SSLeay::BIO_write($self->{_rbio}, $$rbuf);
&_dotls($self);
}
else {
$self->_drain_rbuf;
}
}
else {
lib/AnyEvent/Handle/Throttle.pm view on Meta::CPAN
sub _drain_wbuf {
my ($self) = @_;
if (!$self->{_ww} && $self->{wbuf} && length $self->{wbuf}) {
Scalar::Util::weaken $self;
my $cb;
my $poll = sub {
$self->{_ww} = AE::io $self->{fh}, 1, $cb
if length $self->{wbuf};
};
$cb = sub {
my ($write) = sort grep {defined} $global_write_size,
$self->{write_size};
my ($period) = sort grep {defined} $global_period,
$self->{_period};
if (defined $write && $write <= 0) {
if (length $self->{wbuf}) {
delete $self->{_ww};
return $self->{_pause_ww} = AE::timer(
0.5, 0,
sub {
delete $self->{_pause_write};
$poll->();
}
);
}
return 1;
}
my $len = syswrite $self->{fh}, $self->{wbuf}, $write;
if (defined $len) {
$self->{write_size} -= $len;
$global_write_size -= $len;
$self->{upload_total} += $len;
$global_upload_total += $len;
$self->{_upload_speed} += $len;
$global__upload_speed += $len;
substr $self->{wbuf}, 0, $len, "";
$self->{_activity} = $self->{_wactivity} = AE::now;
$self->{on_drain}($self)
if $self->{low_water_mark}
|| 0 >= length($self->{wbuf} || '')
+ length($self->{_tls_wbuf} || '')
&& $self->{on_drain};
delete $self->{_ww} unless length $self->{wbuf};
}
elsif ( $! != EAGAIN
lib/AnyEvent/Handle/Throttle.pm view on Meta::CPAN
Returns the amount of data read during the previous period.
=back
If you're using L<AnyEvent::Handle::Throttle|AnyEvent::Handle::Throttle> to
limit bandwidth and realize you'd rather set flat limits on the B<total>
bandwidth instead of per-handle, try these methods:
=over
=item AnyEvent::Handle::Throttle->B<global_upload_limit>( $bytes )
Sets/returns the current global upload rate in bytes per period.
=item AnyEvent::Handle::Throttle->B<global_download_limit>( $bytes )
Sets/returns the current global download rate in bytes per period.
=item $bytes = $handle->B<global_upload_speed>( )
Returns the amount of data written through all
L<AnyEvent::Handle::Throttle|AnyEvent::Handle::Throttle> objects during the
previous period.
=item $bytes = $handle->B<global_download_speed>( )
Returns the amount of data read through all
L<AnyEvent::Handle::Throttle|AnyEvent::Handle::Throttle> objects during the
previous period.
=item $bytes = $handle->B<download_total>( )
Returns the total amount of data read through the
L<AnyEvent::Handle::Throttle|AnyEvent::Handle::Throttle> object.
=item $bytes = $handle->B<upload_total>( )
Returns the total amount of data written through the
L<AnyEvent::Handle::Throttle|AnyEvent::Handle::Throttle> object.
=item $bytes = $handle->B<global_download_total>( )
Returns the total amount of data read through all
L<AnyEvent::Handle::Throttle|AnyEvent::Handle::Throttle> objects so far.
=item $bytes = $handle->B<global_upload_total>( )
Returns the total amount of data sent through all
L<AnyEvent::Handle::Throttle|AnyEvent::Handle::Throttle> objects so far.
=back
=head1 Notes
=over
t/http_global.t view on Meta::CPAN
use warnings;
use Test::More;
use AnyEvent::Impl::Perl;
use AnyEvent;
use lib '../lib';
use AnyEvent::Handle::Throttle;
$|++;
my $condvar = AnyEvent->condvar;
my ($prev, $chunks, $handle, $rbuf) = (AE::now, 0, undef, undef);
my $req = "GET / HTTP/1.0\015\012\015\012";
AnyEvent::Handle::Throttle->global_upload_limit(5);
AnyEvent::Handle::Throttle->global_download_limit(200);
TODO: {
local $TODO = 'May fail blah blah blah';
$handle = new_ok(
'AnyEvent::Handle::Throttle',
[connect => ['cpan.org', 80],
on_prepare => sub {15},
on_connect => sub { $prev = AE::now; },
on_error => sub {
note 'error ' . $_[2];
$_[0]->destroy;
t/http_global.t view on Meta::CPAN
},
on_eof => sub {
$handle->destroy;
note 'done';
$condvar->send;
},
on_drain => sub {
my $now = AE::now;
my $expected = (
int(length($req)
/ AnyEvent::Handle::Throttle->global_upload_limit
)
);
note sprintf 'Write queue is empty after %f seconds',
$now - $prev;
$prev = $now;
},
on_read => sub {
my $now = AE::now;
ok length $handle->rbuf
<= AnyEvent::Handle::Throttle->global_download_limit,
sprintf 'Chunk %d was %d bytes long...', ++$chunks,
length $handle->rbuf;
note sprintf ' ...and came %f seconds later', $now - $prev
if $chunks > 1;
$handle->rbuf() = '';
$prev = $now;
}
],
'::Throttle->new( ... ); G_up: 5, G_down: 20'
);
t/http_global.t view on Meta::CPAN
See the F<LICENSE> file included with this distribution or
L<notes on the Artistic License 2.0|http://www.perlfoundation.org/artistic_2_0_notes>
for clarification.
When separated from the distribution, all original POD documentation is
covered by the
L<Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/us/legalcode>.
See the
L<clarification of the CCA-SA3.0|http://creativecommons.org/licenses/by-sa/3.0/us/>.
=for rcs $Id: http_global.t f6b7de5 2010-08-25 18:10:39Z sanko@cpan.org $
=cut
t/loopback.t view on Meta::CPAN
);
}
);
}
);
$cv->recv;
ok($dat eq 'AAXXXYZ', 'received data') || note '$dat was: ' . $dat;
#
ok !$rd_ae->upload_total, 'reader uploaded nothing';
is $rd_ae->global_upload_total, 10132, 'reader says uploaded is 10132 bytes';
is $rd_ae->download_total, 10132,
'reader claims to have downloaded 10132 bytes';
is $rd_ae->global_download_total, 10132,
'reader claims global download was 10132 bytes';
is $wr_ae->upload_total, 10132, 'writer says it uploaded 10132 bytes';
is $wr_ae->global_upload_total, 10132, 'writer says uploaded is 10132 bytes';
ok !$wr_ae->download_total, 'writer claims to have downloaded nothing';
is $wr_ae->global_download_total, 10132,
'writer claims global download was 10132 bytes';
#
done_testing;
( run in 0.744 second using v1.01-cache-2.11-cpan-49f99fa48dc )