MEDIUM: backend: add the 'first' balancing algorithm

The principle behind this load balancing algorithm was first imagined
and modeled by Steen Larsen then iteratively refined through several
work sessions until it would totally address its original goal.

The purpose of this algorithm is to always use the smallest number of
servers so that extra servers can be powered off during non-intensive
hours. Additional tools may be used to do that work, possibly by
locally monitoring the servers' activity.

The first server with available connection slots receives the connection.
The servers are choosen from the lowest numeric identifier to the highest
(see server parameter "id"), which defaults to the server's position in
the farm. Once a server reaches its maxconn value, the next server is used.
It does not make sense to use this algorithm without setting maxconn. Note
that it can however make sense to use minconn so that servers are not used
at full load before starting new servers, and so that introduction of new
servers requires a progressively increasing load (the number of servers
would more or less follow the square root of the load until maxconn is
reached). This algorithm ignores the server weight, and is more beneficial
to long sessions such as RDP or IMAP than HTTP, though it can be useful
there too.
diff --git a/src/backend.c b/src/backend.c
index 5dbdec3..32eea68 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1,7 +1,7 @@
 /*
  * Backend variables and functions.
  *
- * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
+ * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -31,6 +31,7 @@
 #include <proto/backend.h>
 #include <proto/frontend.h>
 #include <proto/lb_chash.h>
+#include <proto/lb_fas.h>
 #include <proto/lb_fwlc.h>
 #include <proto/lb_fwrr.h>
 #include <proto/lb_map.h>
@@ -512,6 +513,10 @@
 			srv = fwrr_get_next_server(s->be, prev_srv);
 			break;
 
+		case BE_LB_LKUP_FSTREE:
+			srv = fas_get_next_server(s->be, prev_srv);
+			break;
+
 		case BE_LB_LKUP_LCTREE:
 			srv = fwlc_get_next_server(s->be, prev_srv);
 			break;
@@ -1173,6 +1178,8 @@
 		return "roundrobin";
 	else if (algo == BE_LB_ALGO_SRR)
 		return "static-rr";
+	else if (algo == BE_LB_ALGO_FAS)
+		return "first";
 	else if (algo == BE_LB_ALGO_LC)
 		return "leastconn";
 	else if (algo == BE_LB_ALGO_SH)
@@ -1213,6 +1220,10 @@
 		curproxy->lbprm.algo &= ~BE_LB_ALGO;
 		curproxy->lbprm.algo |= BE_LB_ALGO_SRR;
 	}
+	else if (!strcmp(args[0], "first")) {
+		curproxy->lbprm.algo &= ~BE_LB_ALGO;
+		curproxy->lbprm.algo |= BE_LB_ALGO_FAS;
+	}
 	else if (!strcmp(args[0], "leastconn")) {
 		curproxy->lbprm.algo &= ~BE_LB_ALGO;
 		curproxy->lbprm.algo |= BE_LB_ALGO_LC;