AnyEvent-MultiDownload
view release on metacpan or search on metacpan
lib/AnyEvent/MultiDownload.pm view on Meta::CPAN
$first_task->{size} = 0;
$first_task->{ctx} = undef;
$self->first_request(++$retry);
undef $w;
});
AE::log debug => "å°å $url çå 0 ä¸è½½åºé, éè¯";
return;
}
return $self->cv->send((
sprintf("Status: %s, Reason: %s.", $status ? $status : '500', $hdr->{Reason} ? $hdr->{Reason} : ' '),
$hdr)
);
}
}
sub shuffle_url {
my $self = shift;
my $urls = $self->url_status;
return (shuffle keys %$urls)[0];
}
sub on_body {
my ($self, $task) = @_;
return sub {
my ($partial_body, $hdr) = @_;
return 0 unless ($hdr->{Status} == 206 || $hdr->{Status} == 200);
my $len = length($partial_body);
# ä¸»è¦æ¯ç¨äºè§£å³ç¬¬ä¸ä¸ªåä¼è¶
è¿åçä½ç½®
if ( $task->{size} + $len > $self->block_size ) {
my $spsize = $len - ( $task->{size} + $len - $self->block_size );
$partial_body = substr($partial_body, 0, $spsize);
$len = $spsize;
}
$self->fh->start_range($task->{pos});
$self->fh->add_chunk($partial_body);
if ( $self->digest ) {
$task->{ctx} ||= AnyEvent::Digest->new($self->digest);
$task->{ctx}->add_async($partial_body);
}
$task->{pos} += $len;
$task->{size} += $len;
return 1;
}
}
sub fetch_block {
my ($self, $task, $retry) = @_;
$retry ||= 0;
my $url = $self->shuffle_url;
my $ev; $ev = http_get $url,
timeout => $self->timeout,
recurse => $self->recurse,
persistent => 1,
keepalive => 1,
headers => {
%{ $self->headers },
Range => $task->{range}
},
on_body => $self->on_body($task),
sub {
my ($hdl, $hdr) = @_;
my $status = $hdr->{Status};
undef $ev;
# æåä¸è½½å°çæµç¨
# 1. éè¦å¯¹æ¯å¤§å°æ¯å¦ä¸è´, æ¥ç对æ¯åè¾æ£
# 2. å¼å§ä¸ä¸ä¸ªä»»å¡çä¸è½½
# 3. å½ååå°±éåº, ä¸ç¶ä¸é¢ä¼éè¯
if ( $status == 200 || $status == 206 ) { # 第ä¸ä¸ªå, è¿äºä¸ªé½æå¯è½
# not ok åè¾æ£ä¸ç¸ç | ç´æ¥å¤±è´¥
return $self->cv->send(("The $task->{block} block the compared failure", $hdr))
if ($task->{size} != ( $task->{tail} -$task->{ofs} + 1 )
or !$self->on_block_finish->($hdl, $task, $self->digest ? $task->{ctx}->hexdigest : ''));
my $block_task = shift @{ $self->tasks };
# 宿, æ è®°ç»ææ¬æ¬¡è¯·æ±
# ok 大å°ç¸ç, åè¾æ£ç¸ç, å½ååä¸è½½å®æ, å¼å§ä¸è½½æ°ç
AE::log debug => "å°å $url çå $task->{block} ä¸è½½å®æ $$";
# å¤çæ¥ä¸æ¥çä¸ä¸ªè¯·æ±
$block_task ? $self->fetch_block($block_task) : $self->cv->end;
return;
}
# æ¯å¦éè¯çæµç¨
my $error = sprintf(
"Block %s the size is wrong, expect the size: %s actual size: %s, The %s try again, Status: %s, Reason: %s.",
$task->{block},
$self->block_size,
$task->{size},
$retry,
$status ? $status : '500',
$hdr->{Reason} ? $hdr->{Reason} : ' ', );
AE::log warn => $error;
# 失败
# 妿æå¯è½è¿è¿æ¥ä¸çååº, å°±éè¦éè¯, ç´å°è¾¾å°éè¯, 妿ä¸å¯è½è¿æ¥çååº, å°±ç´æ¥å¿«éçéåº
return $self->cv->send(($error, $hdr))
if $status !~ /^(59.|503|500|502|200|206|)$/ or $retry > $self->max_retries;
$self->retry($task, $retry);
}
};
sub retry {
my ($self, $task, $retry) = @_;
my $w;$w = AE::timer( $self->retry_interval, 0, sub {
$task->{pos} = $task->{ofs}; # é䏿¬åæ¶è¦ seek åé¶
$task->{size} = 0;
$task->{ctx} = undef;
$self->fetch_block( $task, ++$retry );
undef $w;
});
}
sub split_range {
( run in 0.624 second using v1.01-cache-2.11-cpan-df04353d9ac )