MINOR: stats: report server's user-configured weight next to effective weight

The "weight" column on the stats page is somewhat confusing when using
slowstart becaue it reports the effective weight, without being really
explicit about it. In some situations the user-configured weight is more
relevant (especially with long slowstarts where it's important to know
if the configured weight is correct).

This adds a new uweight stat which reports a server's user-configured
weight, and in a backend it receives the sum of all servers' uweights.
In addition it adds the mention of "effective" in a few descriptions
for the "weight" column (help and doc).

As a result, the list of servers in a backend is now always scanned
when dumping the stats. But this is not a problem given that these
servers are already scanned anyway and for way heavier processing.
diff --git a/doc/management.txt b/doc/management.txt
index 3031420..308e725 100644
--- a/doc/management.txt
+++ b/doc/management.txt
@@ -1009,7 +1009,7 @@
      server. The server value counts the number of times that server was
      switched away from.
  17. status [LFBS]: status (UP/DOWN/NOLB/MAINT/MAINT(via)/MAINT(resolution)...)
- 18. weight [..BS]: total weight (backend), server weight (server)
+ 18. weight [..BS]: total effective weight (backend), effective weight (server)
  19. act [..BS]: number of active servers (backend), server is active (server)
  20. bck [..BS]: number of backup servers (backend), server is backup (server)
  21. chkfail [...S]: number of failed checks. (Only counts checks failed when
@@ -1130,6 +1130,7 @@
  96. safe_conn_cur [...S]: current number of safe idle connections
  97. used_conn_cur [...S]: current number of connections in use
  98. need_conn_est [...S]: estimated needed number of connections
+ 99. uweight [..BS]: total user weight (backend), server user weight (server)
 
 For all other statistics domains, the presence or the order of the fields are
 not guaranteed. In this case, the header line should always be used to parse
diff --git a/include/haproxy/backend-t.h b/include/haproxy/backend-t.h
index bb8ec6f..3e30240 100644
--- a/include/haproxy/backend-t.h
+++ b/include/haproxy/backend-t.h
@@ -147,6 +147,7 @@
 	int algo;			/* load balancing algorithm and variants: BE_LB_* */
 	int tot_wact, tot_wbck;		/* total effective weights of active and backup servers */
 	int tot_weight;			/* total effective weight of servers participating to LB */
+	int tot_uweight;		/* total user weight of servers participating to LB (for reporting) */
 	int tot_used;			/* total number of servers used for LB */
 	int wmult;			/* ratio between user weight and effective weight */
 	int wdiv;			/* ratio between effective weight and user weight */
@@ -156,8 +157,8 @@
 	int   arg_opt1;			/* extra option 1 for the LB algo (algo-specific) */
 	int   arg_opt2;			/* extra option 2 for the LB algo (algo-specific) */
 	int   arg_opt3;			/* extra option 3 for the LB algo (algo-specific) */
-	struct server *fbck;		/* first backup server when !PR_O_USE_ALL_BK, or NULL */
 	__decl_thread(HA_RWLOCK_T lock);
+	struct server *fbck;		/* first backup server when !PR_O_USE_ALL_BK, or NULL */
 
 	/* Call backs for some actions. Any of them may be NULL (thus should be ignored). */
 	void (*update_server_eweight)(struct server *);  /* to be called after eweight change */
diff --git a/include/haproxy/stats-t.h b/include/haproxy/stats-t.h
index 8b69a0b..af9b971 100644
--- a/include/haproxy/stats-t.h
+++ b/include/haproxy/stats-t.h
@@ -434,6 +434,7 @@
 	ST_F_SAFE_CONN_CUR,
 	ST_F_USED_CONN_CUR,
 	ST_F_NEED_CONN_EST,
+	ST_F_UWEIGHT,
 
 	/* must always be the last one */
 	ST_F_TOTAL_FIELDS
diff --git a/src/stats.c b/src/stats.c
index a332e7c..82e2b1f 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -169,7 +169,7 @@
 	[ST_F_WRETR]                         = { .name = "wretr",                       .desc = "Total number of server connection retries since the worker process started" },
 	[ST_F_WREDIS]                        = { .name = "wredis",                      .desc = "Total number of server redispatches due to connection failures since the worker process started" },
 	[ST_F_STATUS]                        = { .name = "status",                      .desc = "Frontend/listen status: OPEN/WAITING/FULL/STOP; backend: UP/DOWN; server: last check status" },
-	[ST_F_WEIGHT]                        = { .name = "weight",                      .desc = "Server weight, or sum of active servers' weights for a backend" },
+	[ST_F_WEIGHT]                        = { .name = "weight",                      .desc = "Server's effective weight, or sum of active servers' effective weights for a backend" },
 	[ST_F_ACT]                           = { .name = "act",                         .desc = "Total number of active UP servers with a non-zero weight" },
 	[ST_F_BCK]                           = { .name = "bck",                         .desc = "Total number of backup UP servers with a non-zero weight" },
 	[ST_F_CHKFAIL]                       = { .name = "chkfail",                     .desc = "Total number of failed individual health checks per server/backend, since the worker process started" },
@@ -250,6 +250,7 @@
 	[ST_F_SAFE_CONN_CUR]                 = { .name = "safe_conn_cur",               .desc = "Current number of safe idle connections"},
 	[ST_F_USED_CONN_CUR]                 = { .name = "used_conn_cur",               .desc = "Current number of connections in use"},
 	[ST_F_NEED_CONN_EST]                 = { .name = "need_conn_est",               .desc = "Estimated needed number of connections"},
+	[ST_F_UWEIGHT]                       = { .name = "uweight",                     .desc = "Server's user weight, or sum of active servers' user weights for a backend" },
 };
 
 /* one line of info */
@@ -1327,12 +1328,12 @@
 			chunk_appendf(out, "</td><td>");
 
 		chunk_appendf(out,
-		              /* weight */
-		              "</td><td class=ac>%d</td>"
+		              /* weight / uweight */
+		              "</td><td class=ac>%d/%d</td>"
 		              /* act, bck */
 		              "<td class=ac>%s</td><td class=ac>%s</td>"
 		              "",
-		              stats[ST_F_WEIGHT].u.u32,
+		              stats[ST_F_WEIGHT].u.u32, stats[ST_F_UWEIGHT].u.u32,
 		              stats[ST_F_BCK].u.u32 ? "-" : "Y",
 		              stats[ST_F_BCK].u.u32 ? "Y" : "-");
 
@@ -1537,7 +1538,7 @@
 		               * if the backend has known working servers or if it has no server at
 		               * all (eg: for stats). Then we display the total weight, number of
 		               * active and backups. */
-		              "<td class=ac>%s %s</td><td class=ac>&nbsp;</td><td class=ac>%d</td>"
+		              "<td class=ac>%s %s</td><td class=ac>&nbsp;</td><td class=ac>%d/%d</td>"
 		              "<td class=ac>%d</td><td class=ac>%d</td>"
 		              "",
 		              U2H(stats[ST_F_DREQ].u.u64), U2H(stats[ST_F_DRESP].u.u64),
@@ -1548,7 +1549,7 @@
 		              (long long)stats[ST_F_WRETR].u.u64, (long long)stats[ST_F_WREDIS].u.u64,
 		              human_time(stats[ST_F_LASTCHG].u.u32, 1),
 		              strcmp(field_str(stats, ST_F_STATUS), "DOWN") ? field_str(stats, ST_F_STATUS) : "<font color=\"red\"><b>DOWN</b></font>",
-		              stats[ST_F_WEIGHT].u.u32,
+		              stats[ST_F_WEIGHT].u.u32, stats[ST_F_UWEIGHT].u.u32,
 		              stats[ST_F_ACT].u.u32, stats[ST_F_BCK].u.u32);
 
 		chunk_appendf(out,
@@ -1963,6 +1964,7 @@
 	stats[ST_F_STATUS]   = mkf_str(FO_STATUS, fld_status);
 	stats[ST_F_LASTCHG]  = mkf_u32(FN_AGE, now.tv_sec - sv->last_change);
 	stats[ST_F_WEIGHT]   = mkf_u32(FN_AVG, (sv->cur_eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv);
+	stats[ST_F_UWEIGHT]  = mkf_u32(FN_AVG, sv->uweight);
 	stats[ST_F_ACT]      = mkf_u32(FO_STATUS, (sv->flags & SRV_F_BACKUP) ? 0 : 1);
 	stats[ST_F_BCK]      = mkf_u32(FO_STATUS, (sv->flags & SRV_F_BACKUP) ? 1 : 0);
 
@@ -2151,20 +2153,29 @@
 	struct buffer *out = get_trash_chunk();
 	const struct server *srv;
 	int nbup, nbsrv;
+	int totuw;
 	char *fld;
 
 	if (len < ST_F_TOTAL_FIELDS)
 		return 0;
 
+	totuw = 0;
 	nbup = nbsrv = 0;
-	if (flags & (STAT_HIDE_MAINT|STAT_HIDE_DOWN)) {
-		for (srv = px->srv; srv; srv = srv->next) {
-			if (srv->cur_state != SRV_ST_STOPPED)
-				nbup++;
-			nbsrv++;
+	for (srv = px->srv; srv; srv = srv->next) {
+		if (srv->cur_state != SRV_ST_STOPPED) {
+			nbup++;
+			if (srv_currently_usable(srv) &&
+			    (!px->srv_act ^ !(srv->flags & SRV_F_BACKUP)))
+				totuw += srv->uweight;
 		}
+		nbsrv++;
 	}
 
+	HA_RWLOCK_RDLOCK(LBPRM_LOCK, &px->lbprm.lock);
+	if (!px->srv_act && px->lbprm.fbck)
+		totuw = px->lbprm.fbck->uweight;
+	HA_RWLOCK_RDUNLOCK(LBPRM_LOCK, &px->lbprm.lock);
+
 	stats[ST_F_PXNAME]   = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, px->id);
 	stats[ST_F_SVNAME]   = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, "BACKEND");
 	stats[ST_F_MODE]     = mkf_str(FO_CONFIG|FS_SERVICE, proxy_mode_str(px->mode));
@@ -2194,6 +2205,7 @@
 
 	stats[ST_F_STATUS]   = mkf_str(FO_STATUS, fld);
 	stats[ST_F_WEIGHT]   = mkf_u32(FN_AVG, (px->lbprm.tot_weight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv);
+	stats[ST_F_UWEIGHT]  = mkf_u32(FN_AVG, totuw);
 	stats[ST_F_ACT]      = mkf_u32(0, px->srv_act);
 	stats[ST_F_BCK]      = mkf_u32(0, px->srv_bck);
 	stats[ST_F_CHKDOWN]  = mkf_u64(FN_COUNTER, px->down_trans);