AnyEvent-Handle-Throttle

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

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

MANIFEST  view on Meta::CPAN

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

README  view on Meta::CPAN

    $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 )