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;