package LWP::StdSched; use strict; use vars qw($DEBUG); sub new { my($class, $ua) = @_; bless {}, $class; } sub reschedule { my($self, $ua) = @_; my $gconn = 0; # number of connections my $gsconn = 0; # number of connections to start my @idle; my @start; for my $server ($ua->servers) { my $sid = $server->id; my($req,$conn,$iconn, $max_conn) = $server->c_status; if ($req && $conn) { # Let's see if any of the existing connections can # absorb the request queue. print STDERR "$sid->activate_connections\n" if $DEBUG; $server->activate_connections; ($req,$conn,$iconn, $max_conn) = $server->c_status; } # Calculate how many connections we would like to start for # this server my $sconn = $req - $conn; # one connection per request my $max_start = $max_conn - $conn; $sconn = $max_start if $max_conn && $sconn > $max_start; $sconn = 0 if $sconn < 0; print STDERR "SCHED $sid R=$req C=$conn I=$iconn ($max_conn) S=$sconn\n" if $DEBUG; $gconn += $conn; $gsconn += $sconn; push(@idle, [$iconn, $server]) if $iconn && !$sconn; push(@start, [$sconn, $server]) if $sconn; } my $conn_limit = $ua->max_conn; unless (!$conn_limit) { # There is no global limit to care about, so just start all we have for (@start) { my($no, $server) = @$_; for (1..$no) { print STDERR $server->id, "->create_connection\n" if $DEBUG; $server->create_connection; } } return; } # must ensure that we don't exceed global conn_limit while (@idle && $gconn + $gsconn > $conn_limit) { # we have reached global limit, but have idle connections that # we can kill off first my($no, $server) = @{ shift(@idle) }; print STDERR $server->id, "->stop_idle\n" if $DEBUG; $server->stop_idle; $gconn -= $no; } # Start server connections until we reach limit. # XXX the problem with this approach is that some servers can starve. START_UP: for (@start) { my($no, $server) = @$_; for (1..$no) { print STDERR $server->id, "->create_connection\n" if $DEBUG; $server->create_connection; last START_UP if ++$gconn >= $conn_limit; } } } 1;