[MINOR] acl: add new keyword "connslots"

I'm in the process of setting up one haproxy instance now, and I find
the following acl option useful. I'm not too sure why this option has
not been available before, but I find this useful for my own usage, so
I'm submitting this patch in the hope that it will be useful as well.

The basic idea is to be able to measure the available connection slots
still available (connection, + queue) - anything beyond that can be
redirected to a different backend. 'connslots' = number of available
server connection slots, + number of available server queue slots. In
the case where we encounter srv maxconn = 0, or srv maxqueue = 0 (in
which case we dont need to care about connslots) the value you get is
-1. Note also that this code does not take care of dynamic connections
at this point in time.

The reason why I'm using this new acl (as opposed to 'nbsrv') is that
'nbsrv' only measures servers that are actually *down*. Whereas this
other acl is more fine-grained, and looks into the number of conn
slots available as well.

diff --git a/doc/configuration.txt b/doc/configuration.txt
index 596f2ab..f37981b 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -3764,6 +3764,27 @@
   to handle some load. It is useful to report a failure when combined with
   "monitor fail".
 
+connslots <integer>
+connslots(backend) <integer>
+  The basic idea here is to be able to measure the number of connection "slots"
+  still available (connection, + queue) - so that anything beyond that (intended
+  usage; see "use_backend" keyword) can be redirected to a different backend.
+
+  'connslots' = number of available server connection slots, + number of available
+  server queue slots.
+
+  *Note that while "dst_conn" may be used, "connslots" comes in especially useful
+  when you have a case of traffic going to one single ip, splitting into multiple
+  backends (perhaps using acls to do name-based load balancing) - and you want to
+  be able to differentiate between different backends, and their "connslots"
+  available.  Also, whereas "nbsrv" only measures servers that are actually *down*,
+  this acl is more fine-grained - and looks into the number of conn slots available
+  as well.
+
+  *OTHER CAVEATS AND NOTES: at this point in time, the code does not take care of
+  dynamic connections. Also, if any of the server maxconn, or maxqueue is 0, then
+  this acl clearly does not make sense - in which case the value returned will be -1.
+
 
 2.3.5.2) Matching contents at Layer 4
 -------------------------------------
diff --git a/src/backend.c b/src/backend.c
index 986c070..c8a84be 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -2048,10 +2048,47 @@
 	return 1;
 }
 
+/* set test->i to the number of enabled servers on the proxy */
+static int
+acl_fetch_connslots(struct proxy *px, struct session *l4, void *l7, int dir,
+		    struct acl_expr *expr, struct acl_test *test)
+{
+	struct server *iterator;
+	test->flags = ACL_TEST_F_VOL_TEST;
+	if (expr->arg_len) {
+		/* another proxy was designated, we must look for it */
+		for (px = proxy; px; px = px->next)
+			if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
+				break;
+	}
+	if (!px)
+		return 0;
+
+	test->i = 0;
+	iterator = px->srv;
+	while (iterator) {
+		if ((iterator->state & 1) == 0) {
+			iterator = iterator->next;
+			continue;
+		}
+		if (iterator->maxconn == 0 || iterator->maxqueue == 0) {
+			test->i = -1;
+			return 1;
+		}
+
+		test->i += (iterator->maxconn - iterator->cur_sess)
+			+  (iterator->maxqueue - iterator->nbpend);
+		iterator = iterator->next;
+	}
+
+	return 1;
+}
+
 
 /* Note: must not be declared <const> as its list will be overwritten */
 static struct acl_kw_list acl_kws = {{ },{
-	{ "nbsrv",   acl_parse_int,   acl_fetch_nbsrv,    acl_match_int, ACL_USE_NOTHING },
+	{ "nbsrv",    acl_parse_int,   acl_fetch_nbsrv,     acl_match_int, ACL_USE_NOTHING },
+	{ "connlots", acl_parse_int,   acl_fetch_connslots, acl_match_int, ACL_USE_NOTHING },
 	{ NULL, NULL, NULL, NULL },
 }};