package Net::Paraget::Client;
#
# $Id: Client.pm,v 1.5 2001/05/10 03:46:08 lrclause Exp $
#
use strict;
use English;
use Carp;
use IO::File;
use File::Basename;
use File::Spec;
use Net::Paraget::PerformanceReport;
use Class::MethodMaker
get_set => [ qw( assignment output_file
start_time end_time
pid return_code
manager
)
],
boolean => [ qw( started cleanedup
no_further_updates
)
],
new_hash_init => [ qw( new hash_init ) ];
sub state
{
my ( $self, $string, $priority ) = @_;
main::state( 'client ' . $self->info() . ": " . $string, $priority );
}
sub info
{
my ( $self ) = @_;
my $assignment_info = $self->assignment->info();
my $output_file = $self->output_file();
my $pid = $self->pid() || 'none';
my $return_code = $self->return_code() || 'none';
return "assignment $assignment_info, return code $return_code";
}
sub start
{
my ( $self ) = @_;
if ( $self->started() )
{
carp "client already started with pid ", $self->pid;
return;
}
my $assignment = $self->assignment();
my $manager = $self->manager();
my $url_basename = basename $assignment->file();
my $offset = $assignment->interval->start();
my $output_basename = "$url_basename.$offset";
my $outfile = File::Spec->catfile( $manager->tmp_dir(), $output_basename );
$self->output_file( $outfile );
# clear out the file beforehand
my $f = IO::File->new( ">$outfile" )
or die "cannot open $outfile for writing";
$f->close();
$self->state( "starting", 1 );
my $pid = fork;
defined $pid or die "error forking: $ERRNO";
if ( $pid != 0 )
{
$self->hash_init( pid => $pid,
started => 1,
start_time => time,
);
$assignment->server()->at_start();
return;
}
my $url = $assignment->mirror->url()."/".$assignment->file();
my $program = $manager->child_program();
exec ( $program,
'--url', $url,
'--offset', $offset,
'--output', $outfile,
'--size', $manager->authoritative_size(),
)
or exit 1;
}
sub cleanup
{
my ( $self ) = @_;
if ( $self->cleanedup() )
{
return;
}
$self->end_time( time );
waitpid $self->pid(), 0;
$self->return_code( $CHILD_ERROR << 8 );
$self->set_cleanedup();
if ($self->had_error()) {
$self->assignment()->server()->at_failure();
} else {
$self->assignment()->server()->at_success();
}
}
sub amount_completed
{
my ( $self ) = @_;
return -s $self->output_file() || 0;
}
sub elapsed_time
{
my ( $self ) = @_;
return 0 unless $self->start_time();
return $self->end_time() - $self->start_time() if $self->cleanedup();
return time - $self->start_time();
}
sub stop
{
my ( $self ) = @_;
if ( not $self->alive() )
{
$self->cleanup();
return;
}
my $pid = $self->pid();
my @signals = qw( INT TERM KILL );
foreach my $signal ( @signals )
{
if ( kill $signal, $pid )
{
$self->cleanup();
return;
}
warn "error killing process $pid with $signal: $ERRNO"
if $self->alive();
}
warn "error: failed to kill process $pid: $ERRNO";
}
sub alive
{
my ( $self ) = @_;
return ( $self->pid() and kill 0, $self->pid() );
}
sub checkup
{
my ( $self ) = @_;
$self->cleanup() unless $self->alive() or $self->cleanedup();
}
sub speed
{
my ( $self ) = @_;
my $elapsed_time = $self->elapsed_time();
return undef if $elapsed_time == 0;
return $self->amount_completed() / $elapsed_time;
}
sub report
{
my ( $self ) = @_;
my $r = Net::Paraget::PerformanceReport->new
( assignment => $self->assignment(),
work_time => $self->elapsed_time(),
amount_completed => $self->amount_completed(),
had_error => $self->had_error,
);
return $r;
}
sub had_error
{
my ( $self ) = @_;
return 0 unless $self->cleanedup();
return ( $self->return_code() != 0 and not $self->fulfilled_assignment() );
}
sub further_updates
{
my ( $self ) = @_;
return not $self->no_further_updates();
}
sub fulfilled_assignment
{
my ( $self ) = @_;
my $interval = $self->assignment->interval();
my $end = $interval->extendable_to();
my $need = $end - $interval->start();
return $self->amount_completed() >= $need;
}
sub estimated_time_to_completion
{
my ( $self ) = @_;
my $speed = $self->speed();
my $completed_size = $self->amount_completed();
my $total_size = $self->assignment->interval->size();
my $amount_left = $total_size - $completed_size;
return undef if not $speed;
return $amount_left / $speed;
}
1;
syntax highlighted by Code2HTML, v. 0.9.1