AnyEvent-BitTorrent
view release on metacpan - search on metacpan
view release on metacpan or search on metacpan
lib/AnyEvent/BitTorrent.pm view on Meta::CPAN
has size => (is => 'ro',
lazy => 1,
builder => '_build_size',
isa => Int,
init_arg => undef
);
sub _build_size {
my $s = shift;
my $ret = 0;
$ret += $_->{length} for @{$s->files};
AE::log debug => '_build_size() => ' . $ret;
$ret;
}
sub _open {
my ($s, $i, $m) = @_;
AE::log
trace => 'Opening file #%d (%s) for %s',
$i, $s->files->[$i]->{path}, $m;
return 1 if $s->files->[$i]->{mode} eq $m;
if (defined $s->files->[$i]->{fh}) {
AE::log trace => 'Closing %s', $s->files->[$i]->{fh};
flock $s->files->[$i]->{fh}, LOCK_UN;
close $s->files->[$i]->{fh};
$s->files->[$i]->{fh} = ();
}
if ($m eq 'r') {
AE::log trace => 'Opening %s to read', $s->files->[$i]->{path};
sysopen($s->files->[$i]->{fh}, $s->files->[$i]->{path}, O_RDONLY)
|| return;
flock($s->files->[$i]->{fh}, LOCK_SH) || return;
weaken $s unless isweak $s;
my $x = $i;
$s->files->[$x]->{timeout}
= AE::timer(500, 0, sub { $s // return; $s->_open($x, 'c') });
}
elsif ($m eq 'w') {
AE::log trace => 'Opening %s to write', $s->files->[$i]->{path};
my @split = File::Spec->splitdir($s->files->[$i]->{path});
pop @split; # File name itself
my $dir = File::Spec->catdir(@split);
File::Path::mkpath($dir) if !-d $dir;
sysopen($s->files->[$i]->{fh},
$s->files->[$i]->{path},
O_WRONLY | O_CREAT)
|| return;
flock $s->files->[$i]->{fh}, LOCK_EX;
truncate $s->files->[$i]->{fh}, $s->files->[$i]->{length}
if -s $s->files->[$i]->{fh}
!= $s->files->[$i]->{length}; # XXX - pre-allocate files
weaken $s unless isweak $s;
my $x = $i;
$s->files->[$x]->{timeout}
= AE::timer(60, 0, sub { $s // return; $s->_open($x, 'c') });
}
elsif ($m eq 'c') { $s->files->[$i]->{timeout} = () }
else {return}
return $s->files->[$i]->{mode} = $m;
}
has piece_cache => (is => 'ro', isa => HashRef, default => sub { {} });
sub _cache_path {
my $s = shift;
File::Spec->catfile($s->basedir,
(scalar @{$s->files} == 1 ? () : $s->name),
'~ABPartFile_-'
. uc(substr(unpack('H*', $s->infohash), 0, 10))
. '.dat'
);
}
sub _write_cache {
my ($s, $f, $o, $d) = @_;
my $path = $s->_cache_path;
AE::log
debug =>
'Attempting to store %d bytes to cache file (%s) [$f=%s, $o=%s]',
length($d), $path, $f, $o;
my @split = File::Spec->splitdir($path);
pop @split; # File name itself
my $dir = File::Spec->catdir(@split);
File::Path::mkpath($dir) if !-d $dir;
sysopen(my ($fh), $path, O_WRONLY | O_CREAT)
|| return;
flock $fh, LOCK_EX;
my $pos = sysseek $fh, 0, SEEK_CUR;
my $w = syswrite $fh, $d;
flock $fh, LOCK_UN;
close $fh;
$s->piece_cache->{$f}{$o} = $pos;
AE::log debug => 'Wrote %d bytes to cache file', $w;
return $w;
}
sub _read_cache {
my ($s, $f, $o, $l) = @_;
$s->piece_cache->{$f} // return;
$s->piece_cache->{$f}{$o} // return;
my $path = $s->_cache_path;
AE::log
debug =>
'Attempting to read %d bytes from cache file (%s) [$f=%s, $o=%s]',
$l, $path, $f, $o;
sysopen(my ($fh), $path, O_RDONLY)
|| return;
flock $fh, LOCK_SH;
sysseek $fh, $s->piece_cache->{$f}{$o}, SEEK_SET;
my $w = sysread $fh, my ($d), $l;
flock $fh, LOCK_UN;
close $fh;
return $d;
}
sub _read {
my ($s, $index, $offset, $length) = @_;
AE::log
debug =>
'Attempting to read %d bytes from piece %d starting at %d bytes',
$length, $index, $offset;
my $data = '';
view all matches for this distributionview release on metacpan - search on metacpan
( run in 2.130 seconds using v1.00-cache-2.02-grep-82fe00e-cpan-72ae3ad1e6da )