package Net::Paraget::Server;
#
# $Id: Server.pm,v 1.8 2001/05/10 04:44:42 lrclause Exp $
#
use strict;
use Class::MethodMaker
get_set => [ qw( host scheme overhead list
amount_completed work_time
total_download total_time
failures consecutive_failures
tries last_try
) ],
boolean => [ qw( disabled ) ],
list => [ qw( mirrors ) ],
new_hash_init => "hash_init",
new_with_init => 'new';
my %serverdata_element_to_datamember =
( overhead => "overhead",
disabled => "disabled",
tries => "tries",
failures => "failures",
"consecutive-failures" => "consecutive_failures",
"total-download" => "total_download",
"total-time" => "total_time",
"last-try" => "last_try",
);
sub init
{
my ($self, %args) = @_;
for my $field ( qw( amount_completed work_time total_download total_time
failures tries consecutive_failures overhead
) )
{
$self->$field(0);
}
$self->hash_init(%args);
die "Server list not initialized in init" if not $self->list();
my $serverdata = $self->list()->serverdata($self->as_string());
if ($serverdata)
{
foreach my $key ( keys %serverdata_element_to_datamember )
{
my $function_name = $serverdata_element_to_datamember{$key};
my $total = $serverdata->{$key};
$self->$function_name($serverdata->{$key});
}
$self->hash_init(%args);
}
my $total = $self->total_download();
my $consecutive_failures = $self->consecutive_failures();
$self->state( "initted", 2 );
}
sub save_state
{
my ($self) = @_;
my $serverdata = {};
foreach my $key ( keys %serverdata_element_to_datamember )
{
my $function_name = $serverdata_element_to_datamember{$key};
if (defined $self->$function_name()) {
$serverdata->{$key} = $self->$function_name();
}
}
return $serverdata;
}
sub speed
{
my ( $self, $bad_arg ) = @_;
die "You can't set speed" if defined $bad_arg;
my $distance = $self->amount_completed();
my $time = $self->work_time();
return undef unless $time;
return int( $distance / $time );
}
sub as_string
{
my ( $self ) = @_;
return $self->host_scheme_as_string($self->host(), $self->scheme());
}
# this can be called as a class method
sub host_scheme_as_string
{
my ($self, $host, $scheme) = @_;
return lc join ( '', $scheme, '://', $host );
}
sub get_mirror
{
my ( $self ) = @_;
foreach ( $self->mirrors() )
{
return $_ unless $_->disabled();
}
return undef;
}
sub time_over_interval
{
my ( $self, $interval ) = @_;
my $prev = $interval->prev();
my $prev_speed = 0;
my $prev_assignment = $prev->assignment();
$prev_speed = $prev_assignment->server->a_speed() if $prev_assignment;
my $distance = $interval->size();
my $overhead = $self->an_overhead();
my $total_speed = $self->a_speed() + $prev_speed;
my $time = $overhead + $distance / $total_speed;
return $time;
}
sub get_a
{
my ( $self, $value ) = @_;
my $average_string = "average_$value";
my $default_string = "default_$value";
my $a = ( $self->$value()
|| $self->list->$average_string()
|| $self->list->$default_string()
);
return $a;
}
sub a_speed
{
my ( $self ) = @_;
return $self->get_a( 'speed' );
}
sub an_overhead
{
my ( $self ) = @_;
return $self->get_a( 'overhead' );
}
sub id
{
my ( $self ) = @_;
$self->as_string();
}
sub info
{
my ( $self ) = @_;
return $self->id();
}
sub update_from_report
{
my ( $self, $report ) = @_;
if (not $self->amount_completed() and
$report->amount_completed())
{
# First piece of download, time up till now is overhead
$self->overhead( $self->overhead() + $report->work_time );
}
foreach my $field ( qw( amount_completed work_time ) )
{
my $prev = $self->$field() || 0;
$self->$field( $prev + $report->$field() );
}
$self->decrease_speed_history( 50 );
my $speed = $self->speed();
$speed = 'undefined' if not defined $speed;
}
# Must be called whenever a server starts downloading
sub at_start
{
my ( $self ) = @_;
$self->state( "starting", 1 );
$self->tries( $self->tries() + 1 );
$self->last_try( time() );
}
sub at_end
{
my ( $self ) = @_;
$self->total_time( $self->total_time + $self->work_time() );
$self->total_download( $self->total_download + $self->amount_completed());
}
# Exactly one of these two must be called when a server stops downloading
sub at_success
{
my ( $self ) = @_;
$self->consecutive_failures(0);
$self->at_end();
}
sub at_failure
{
my ($self) = @_;
$self->failures( $self->failures + 1 );
$self->consecutive_failures( $self->consecutive_failures + 1 );
$self->at_end();
}
sub count_able_mirrors
{
my ( $self ) = @_;
my $count = 0;
foreach my $m ( $self->mirrors() )
{
$count++ if not $m->disabled();
}
return $count;
}
sub decrease_speed_history
{
my ( $self, $decrease_to_percent ) = @_;
my $original_completed = $self->amount_completed();
my $original_time = $self->work_time();
my $multiplier = $decrease_to_percent / 100;
my $new_completed = int( $original_completed * $multiplier );
my $new_time = int( $original_time * $multiplier );
$self->amount_completed( $new_completed );
$self->work_time( $new_time );
}
sub state
{
my ( $self, $string, $priority ) = @_;
main::state( $self->as_string . ": " . $string, $priority );
}
1;
syntax highlighted by Code2HTML, v. 0.9.1