/usr/local/CPAN/LWPng-alpha/LWP/StdSched.pm


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;