MINOR: checks: add a new global max-spread-checks directive

This directive ensures that checks with a huge interval do not start
too far apart at the beginning.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 610a674..a1f58fb 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -464,6 +464,7 @@
    - unix-bind
 
  * Performance tuning
+   - max-spread-checks
    - maxconn
    - maxconnrate
    - maxcomprate
@@ -720,6 +721,16 @@
 3.2. Performance tuning
 -----------------------
 
+max-spread-checks <delay in milliseconds>
+  By default, haproxy tries to spread the start of health checks across the
+  smallest health check interval of all the servers in a farm. The principle is
+  to avoid hammering services running on the same server. But when using large
+  check intervals (10 seconds or more), the last servers in the farm take some
+  time before starting to be tested, which can be a problem. This parameter is
+  used to enforce an upper bound on delay between the first and the last check,
+  even if the servers' check intervals are larger. When servers run with
+  shorter intervals, their intervals will be respected though.
+
 maxconn <number>
   Sets the maximum per-process number of concurrent connections to <number>. It
   is equivalent to the command-line argument "-n". Proxies will stop accepting
diff --git a/include/types/global.h b/include/types/global.h
index 022c1b5..0d9903d 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -105,6 +105,7 @@
 	unsigned int req_count; /* request counter (HTTP or TCP session) for logs and unique_id */
 	int last_checks;
 	int spread_checks;
+	int max_spread_checks;
 	char *chroot;
 	char *pidfile;
 	char *node, *desc;		/* node name & description */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 19c5599..ec8f3ae 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -1341,6 +1341,28 @@
 			err_code |= ERR_ALERT | ERR_FATAL;
 		}
 	}
+	else if (!strcmp(args[0], "max-spread-checks")) {  /* maximum time between first and last check */
+		const char *err;
+		unsigned int val;
+
+
+		if (*(args[1]) == 0) {
+			Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+			goto out;
+		}
+
+		err = parse_time_err(args[1], &val, TIME_UNIT_MS);
+		if (err) {
+			Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+		}
+		global.max_spread_checks = val;
+		if (global.max_spread_checks < 0) {
+			Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+		}
+	}
 	else if (strcmp(args[0], "cpu-map") == 0) {  /* map a process list to a CPU set */
 #ifdef USE_CPU_AFFINITY
 		int cur_arg, i;
diff --git a/src/checks.c b/src/checks.c
index 24b763d..fceb2c7 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -1744,11 +1744,14 @@
 	t->process = process_chk;
 	t->context = check;
 
+	if (mininter < srv_getinter(check))
+		mininter = srv_getinter(check);
+
+	if (global.max_spread_checks && mininter > global.max_spread_checks)
+		mininter = global.max_spread_checks;
+
 	/* check this every ms */
-	t->expire = tick_add(now_ms,
-			     MS_TO_TICKS(((mininter &&
-					   mininter >= srv_getinter(check)) ?
-					  mininter : srv_getinter(check)) * srvpos / nbcheck));
+	t->expire = tick_add(now_ms, MS_TO_TICKS(mininter * srvpos / nbcheck));
 	check->start = now;
 	task_queue(t);