]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: checks: improve handling of the servers tracking chain
authorWilly Tarreau <w@1wt.eu>
Wed, 11 Dec 2013 14:27:05 +0000 (15:27 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 14 Dec 2013 15:02:18 +0000 (16:02 +0100)
Server tracking uses the same "tracknext" list for servers tracking
another one and for the servers being tracked. This caused an issue
which was fixed by commit f39c71c ([CRITICAL] fix server state tracking:
it was O(n!) instead of O(n)), consisting in ensuring that a server is
being checked before walking down the list, so that we don't propagate
the up/down information via servers being part of the track chain.

But the root cause is the fact that all servers share the same list.
The correct solution consists in having a list head for the tracked
servers and a list of next tracking servers. This simplifies the
propagation logic, especially for the case where status changes might
be passed to individual servers via the CLI.

include/types/server.h
src/cfgparse.c
src/checks.c

index 05d47835ecf67aa6dc5199be769036c247584a67..a3775a7c889351a66c213ba9554d70c9d8aa2a23 100644 (file)
@@ -158,7 +158,9 @@ struct server {
 
        struct conn_src conn_src;               /* connection source settings */
 
-       struct server *tracknext, *track;       /* next server in a tracking list, tracked server */
+       struct server *track;                   /* the server we're currently tracking, if any */
+       struct server *trackers;                /* the list of servers tracking us, if any */
+       struct server *tracknext;               /* next server tracking <track> in <track>'s trackers list */
        char *trackit;                          /* temporary variable to make assignment deferrable */
        int consecutive_errors;                 /* current number of consecutive errors */
        int consecutive_errors_limit;           /* number of consecutive errors that triggers an event */
index 579dbcc530a7d7e915d9ab3ea5b1e81c1cc7013e..aa8bb90cf2d53e9af83b777c5c3eadf908314e91 100644 (file)
@@ -7044,8 +7044,8 @@ out_uri_auth_compat:
                                }
 
                                newsrv->track = srv;
-                               newsrv->tracknext = srv->tracknext;
-                               srv->tracknext = newsrv;
+                               newsrv->tracknext = srv->trackers;
+                               srv->trackers = newsrv;
 
                                free(newsrv->trackit);
                                newsrv->trackit = NULL;
index 4af3db726178f54815b7e8d6098a0ec4a218a8fb..069d06d448f2bbc41a1d506cfe04fb1120d694b9 100644 (file)
@@ -455,11 +455,10 @@ void set_server_down(struct check *check)
 
                s->counters.down_trans++;
 
-               if (s->state & SRV_CHECKED)
-                       for (srv = s->tracknext; srv; srv = srv->tracknext)
-                               if (!(srv->state & SRV_MAINTAIN))
-                                       /* Only notify tracking servers that are not already in maintenance. */
-                                       set_server_down(&srv->check);
+               for (srv = s->trackers; srv; srv = srv->tracknext)
+                       if (!(srv->state & SRV_MAINTAIN))
+                               /* Only notify tracking servers that are not already in maintenance. */
+                               set_server_down(&srv->check);
        }
 
        check->health = 0; /* failure */
@@ -531,11 +530,10 @@ void set_server_up(struct check *check) {
                Warning("%s.\n", trash.str);
                send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
 
-               if (s->state & SRV_CHECKED)
-                       for (srv = s->tracknext; srv; srv = srv->tracknext)
-                               if (!(srv->state & SRV_MAINTAIN))
-                                       /* Only notify tracking servers if they're not in maintenance. */
-                                       set_server_up(&srv->check);
+               for (srv = s->trackers; srv; srv = srv->tracknext)
+                       if (!(srv->state & SRV_MAINTAIN))
+                               /* Only notify tracking servers if they're not in maintenance. */
+                               set_server_up(&srv->check);
        }
 
        if (check->health >= check->rise)
@@ -576,9 +574,8 @@ static void set_server_disabled(struct check *check) {
        if (!s->proxy->srv_bck && !s->proxy->srv_act)
                set_backend_down(s->proxy);
 
-       if (s->state & SRV_CHECKED)
-               for(srv = s->tracknext; srv; srv = srv->tracknext)
-                       set_server_disabled(&srv->check);
+       for (srv = s->trackers; srv; srv = srv->tracknext)
+               set_server_disabled(&srv->check);
 }
 
 static void set_server_enabled(struct check *check) {
@@ -610,9 +607,8 @@ static void set_server_enabled(struct check *check) {
        Warning("%s.\n", trash.str);
        send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
 
-       if (s->state & SRV_CHECKED)
-               for(srv = s->tracknext; srv; srv = srv->tracknext)
-                       set_server_enabled(&srv->check);
+       for (srv = s->trackers; srv; srv = srv->tracknext)
+               set_server_enabled(&srv->check);
 }
 
 static void check_failed(struct check *check)