AnyEvent-Curl-Multi

 view release on metacpan or  search on metacpan

lib/AnyEvent/Curl/Multi.pm  view on Meta::CPAN

    }

    # Initialize easy curl handle
    my $id = refaddr $easy_h;
    my ($response, $header);
    $easy_h->setopt(CURLOPT_WRITEDATA, \$response);
    $easy_h->setopt(CURLOPT_WRITEHEADER, \$header);
    $easy_h->setopt(CURLOPT_PRIVATE, $id);

    my $obj = {
        easy_h => $easy_h,
        req => $req,
        response => \$response,
        header => \$header,
        cv => AE::cv,
    };

    push @{$self->{queue}}, $obj;

    $self->_dequeue;

    return bless $obj, 'AnyEvent::Curl::Multi::Handle';
}

sub _dequeue {
    my $self = shift;

    while ($self->{max_concurrency} == 0 || 
           scalar keys %{$self->{state}} < $self->{max_concurrency}) {
        if (my $dequeued = shift @{$self->{queue}}) {
            $self->{state}->{refaddr($dequeued->{easy_h})} = $dequeued;
            # Add it to our multi handle
            $self->{multi_h}->add_handle($dequeued->{easy_h});
        } else {
            last;
        }
    }
    
    # Start our timer
    $self->{timer_w} = AE::timer(0, 0.5, sub { $self->_perform });
}

sub _perform {
    my $self = shift;

    $self->{multi_h}->perform;

    while (my ($id, $rv) = $self->{multi_h}->info_read) {
        if ($id) {
            my $state = $self->{state}->{$id};
            my $req = $state->{req};
            my $easy_h = $state->{easy_h};
            my $stats = {
                total_time => $easy_h->getinfo(CURLINFO_TOTAL_TIME),
                dns_time => $easy_h->getinfo(CURLINFO_NAMELOOKUP_TIME),
                connect_time => $easy_h->getinfo(CURLINFO_CONNECT_TIME),
                start_transfer_time => 
                    $easy_h->getinfo(CURLINFO_STARTTRANSFER_TIME),
                download_bytes => 
                    $easy_h->getinfo(CURLINFO_SIZE_DOWNLOAD),
                upload_bytes => $easy_h->getinfo(CURLINFO_SIZE_UPLOAD),
            };
            if ($rv) {
                # Error
                $state->{cv}->croak($easy_h->errbuf);
                $req->event('error', $easy_h->errbuf, $stats) 
                    if $req->can('event');
                $self->event('error', $req, $easy_h->errbuf, $stats);
            } else {
                # libcurl appends subsequent response headers to the buffer
                # when following redirects.  We need to remove all but the
                # most recent header before we parse the response.
                my $last_header = (split(/\r?\n\r?\n/, 
                                   ${$state->{header}}))[-1];
                my $response = HTTP::Response->parse($last_header . 
                                                     "\n\n" . 
                                                     ${$state->{response}});
                $req->uri($easy_h->getinfo(CURLINFO_EFFECTIVE_URL));
                $response->request($req);
                $state->{cv}->send($response, $stats);
                $req->event('response', $response, $stats) 
                    if $req->can('event');
                $self->event('response', $req, $response, $stats);
            }
            delete $self->{state}->{$id};
            $self->_dequeue;
        }
    }

    # We must recalculate the number of active handles here, because
    # a user-provided callback may have added a new one.
    my $active_handles = scalar keys %{$self->{state}};
    if (! $active_handles) {
        # Nothing left to do - no point keeping the watchers around anymore.
        delete $self->{timer_w};
        delete $self->{io_w};
        return;
    }

    # Re-establish all I/O watchers
    foreach my $fd (keys %{$self->{io_w}}) {
        delete $self->{io_w}->{$fd};
    }

    my ($readfds, $writefds, $errfds) = $self->{multi_h}->fdset;

    foreach my $fd (@$writefds) {
        $self->{io_w}->{$fd} ||= AE::io($fd, 1, sub { $self->_perform }); 
    }
    foreach my $fd (@$readfds) {
        $self->{io_w}->{$fd} ||= AE::io($fd, 0, sub { $self->_perform }); 
    }
}

sub _gen_easy_h {
    my $self = shift;
    my $req = shift;
    my %opts = @_;

    my $easy_h = WWW::Curl::Easy->new;
    $easy_h->setopt(CURLOPT_URL, $req->uri);



( run in 2.091 seconds using v1.01-cache-2.11-cpan-b16cb0d3907 )