#include "leastconn"

unsigned Leastconn::target(struct in_addr clientip,
			   BackendVector &targetlist) {

    PROFILE("Leastconn::target");
    msg("Starting least-connections dispatcher\n");

    if (config.debug()) {
	ostringstream o;
	o << "Back end target list:";
	for (unsigned i = 0; i < targetlist.size(); i++)
	    o << ' ' << targetlist[i];
	o << '\n';
	debugmsg(o.str());
    }
    
    bool found = false;
    unsigned best_weighted = 0, t = 0;

    for (unsigned i = 0; i < targetlist.size(); i++) {
	if (! balancer.backend(targetlist[i]).available()) {
	    debugmsg("Back end " <<
		     balancer.backend(targetlist[i]).description() << 
		     " is NOT available\n");
	    continue;
	}
	unsigned connections = balancer.backend(targetlist[i]).connections();
	unsigned anticipated = IPStore::anticipated(targetlist[i]);
	unsigned adjweight   = balancer.backend(targetlist[i]).adjustedweight();
	unsigned this_weight = (connections + anticipated) * adjweight;
	ostringstream o;

	if (config.debug())
	    o << "Back end " << balancer.backend(targetlist[i]).description()
	      << ": connections=" << connections
	      << ", anticipated=" << anticipated
	      << ", adjweight=" << adjweight
	      << ", thisweight=" << this_weight;
	
	if (!found || this_weight < best_weighted) {
	    t = targetlist[i];
	    best_weighted = this_weight;
	    found = true;
	    debugmsg(o.str() << " is best so far\n");
	} else
	    debugmsg(o.str() <<  " skipped, got a better one\n");
    }

    if (!found)
	throw Error("Least-connections algorithm: no available back ends");
    return (t);
}
