[-]
[+]
|
Changed |
_service
|
@@ -3,5 +3,5 @@
- <param name="protocol">http</param><param name="host">haproxy.1wt.eu</param><param name="path">/download/1.5/src/devel/haproxy-1.5-dev25.tar.gz</param></service>
+ <param name="protocol">http</param><param name="host">haproxy.1wt.eu</param><param name="path">/download/1.5/src/devel/haproxy-1.5-dev26.tar.gz</param></service>
</services>
\ No newline at end of file
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/CHANGELOG
^
|
@@ -1,6 +1,65 @@
ChangeLog :
===========
+2014/05/28 : 1.5-dev26
+ - BUG/MEDIUM: polling: fix possible CPU hogging of worker processes after receiving SIGUSR1.
+ - BUG/MINOR: stats: fix a typo on a closing tag for a server tracking another one
+ - OPTIM: stats: avoid the calculation of a useless link on tracking servers in maintenance
+ - MINOR: fix a few memory usage errors
+ - CONTRIB: halog: Filter input lines by date and time through timestamp
+ - MINOR: ssl: SSL_CTX_set_options() and SSL_CTX_set_mode() take a long, not an int
+ - BUG/MEDIUM: regex: fix risk of buffer overrun in exp_replace()
+ - MINOR: acl: set "str" as default match for strings
+ - DOC: Add some precisions about acl default matching method
+ - MEDIUM: acl: strenghten the option parser to report invalid options
+ - BUG/MEDIUM: config: a stats-less config crashes in 1.5-dev25
+ - BUG/MINOR: checks: tcp-check must not stop on '\0' for binary checks
+ - MINOR: stats: improve alignment of color codes to save one line of header
+ - MINOR: checks: simplify and improve reporting of state changes when using log-health-checks
+ - MINOR: server: remove the SRV_DRAIN flag which can always be deduced
+ - MINOR: server: use functions to detect state changes and to update them
+ - MINOR: server: create srv_was_usable() from srv_is_usable() and use a pointer
+ - BUG/MINOR: stats: do not report "100%" in the thottle column when server is draining
+ - BUG/MAJOR: config: don't free valid regex memory
+ - BUG/MEDIUM: session: don't clear CF_READ_NOEXP if analysers are not called
+ - BUG/MINOR: stats: tracking servers may incorrectly report an inherited DRAIN status
+ - MEDIUM: proxy: make timeout parser a bit stricter
+ - REORG/MEDIUM: server: split server state and flags in two different variables
+ - REORG/MEDIUM: server: move the maintenance bits out of the server state
+ - MAJOR: server: use states instead of flags to store the server state
+ - REORG: checks: put the functions in the appropriate files !
+ - MEDIUM: server: properly support and propagate the maintenance status
+ - MEDIUM: server: allow multi-level server tracking
+ - CLEANUP: checks: rename the server_status_printf function
+ - MEDIUM: checks: simplify server up/down/nolb transitions
+ - MAJOR: checks: move health checks changes to set_server_check_status()
+ - MINOR: server: make the status reporting function support a reason
+ - MINOR: checks: simplify health check reporting functions
+ - MINOR: server: implement srv_set_stopped()
+ - MINOR: server: implement srv_set_running()
+ - MINOR: server: implement srv_set_stopping()
+ - MEDIUM: checks: simplify failure notification using srv_set_stopped()
+ - MEDIUM: checks: simplify success notification using srv_set_running()
+ - MEDIUM: checks: simplify stopping mode notification using srv_set_stopping()
+ - MEDIUM: stats: report a server's own state instead of the tracked one's
+ - MINOR: server: make use of srv_is_usable() instead of checking eweight
+ - MAJOR: checks: add support for a new "drain" administrative mode
+ - MINOR: stats: use the admin flags for soft enable/disable/stop/start on the web page
+ - MEDIUM: stats: introduce new actions to simplify admin status management
+ - MINOR: cli: introduce a new "set server" command
+ - MINOR: stats: report a distinct output for DOWN caused by agent
+ - MINOR: checks: support specific check reporting for the agent
+ - MINOR: checks: support a neutral check result
+ - BUG/MINOR: cli: "agent" was missing from the "enable"/"disable" help message
+ - MEDIUM: cli: add support for enabling/disabling health checks.
+ - MEDIUM: stats: report down caused by agent prior to reporting up
+ - MAJOR: agent: rework the response processing and support additional actions
+ - MINOR: stats: improve the stats web page to support more actions
+ - CONTRIB: halog: avoid calling time/localtime/mktime for each line
+ - DOC: document the workarouds for Google Chrome's bogus pre-connect
+ - MINOR: stats: report SSL key computations per second
+ - MINOR: stats: add counters for SSL cache lookups and misses
+
2014/05/10 : 1.5-dev25
- MEDIUM: connection: Implement and extented PROXY Protocol V2
- MINOR: ssl: clean unused ACLs declarations
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/README
^
|
@@ -1,9 +1,9 @@
----------------------
HAProxy how-to
----------------------
- version 1.5-dev25
+ version 1.5-dev26
willy tarreau
- 2014/05/10
+ 2014/05/28
1) How to build it
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/SUBVERS
^
|
@@ -1,2 +1,2 @@
--a339395
+-2e85840
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/VERDATE
^
|
@@ -1,2 +1,2 @@
-2014-05-10 15:16:43 +0200
-2014/05/10
+2014-05-28 17:50:53 +0200
+2014/05/28
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/VERSION
^
|
@@ -1 +1 @@
-1.5-dev25
+1.5-dev26
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/contrib/halog/halog.c
^
|
@@ -18,6 +18,7 @@
#include <string.h>
#include <unistd.h>
#include <ctype.h>
+#include <time.h>
#include <eb32tree.h>
#include <eb64tree.h>
@@ -116,7 +117,10 @@
#define FILT_COUNT_COOK_CODES 0x40000000
#define FILT_COUNT_IP_COUNT 0x80000000
+#define FILT2_TIMESTAMP 0x01
+
unsigned int filter = 0;
+unsigned int filter2 = 0;
unsigned int filter_invert = 0;
const char *line;
int linenum = 0;
@@ -144,7 +148,7 @@
" halog [-q] [-c] [-m <lines>]\n"
" {-cc|-gt|-pct|-st|-tc|-srv|-u|-uc|-ue|-ua|-ut|-uao|-uto|-uba|-ubt|-ic}\n"
" [-s <skip>] [-e|-E] [-H] [-rt|-RT <time>] [-ad <delay>] [-ac <count>]\n"
- " [-v] [-Q|-QS] [-tcn|-TCN <termcode>] [ -hs|-HS [min][:[max]] ] < log\n"
+ " [-v] [-Q|-QS] [-tcn|-TCN <termcode>] [ -hs|-HS [min][:[max]] ] [ -time [min][:[max]] ] < log\n"
"\n",
msg ? msg : ""
);
@@ -170,6 +174,8 @@
" -hs|-HS <[min][:][max]> only match requests with HTTP status codes within/not\n"
" within min..max. Any of them may be omitted. Exact\n"
" code is checked for if no ':' is specified.\n"
+ " -time <[min][:max]> only match requests recorded between timestamps.\n"
+ " Any of them may be omitted.\n"
"Modifiers\n"
" -v invert the input filtering condition\n"
" -q don't report errors/warnings\n"
@@ -521,6 +527,157 @@
return -1;
}
+/* Convert "[04/Dec/2008:09:49:40.555]" to an unix timestamp.
+ * It returns -1 for all unparsable values. The parser
+ * looks ugly but gcc emits far better code that way.
+ */
+int convert_date_to_timestamp(const char *field)
+{
+ unsigned int d, mo, y, h, m, s;
+ unsigned char c;
+ const char *b, *e;
+ time_t rawtime;
+ static struct tm * timeinfo;
+ static int last_res;
+
+ d = mo = y = h = m = s = 0;
+ e = field;
+
+ c = *(e++); // remove '['
+ /* day + '/' */
+ while (1) {
+ c = *(e++) - '0';
+ if (c > 9)
+ break;
+ d = d * 10 + c;
+ if (c == (unsigned char)(0 - '0'))
+ goto out_err;
+ }
+
+ /* month + '/' */
+ c = *(e++);
+ if (c =='F') {
+ mo = 2;
+ e = e+3;
+ } else if (c =='S') {
+ mo = 9;
+ e = e+3;
+ } else if (c =='O') {
+ mo = 10;
+ e = e+3;
+ } else if (c =='N') {
+ mo = 11;
+ e = e+3;
+ } else if (c == 'D') {
+ mo = 12;
+ e = e+3;
+ } else if (c == 'A') {
+ c = *(e++);
+ if (c == 'p') {
+ mo = 4;
+ e = e+2;
+ } else if (c == 'u') {
+ mo = 8;
+ e = e+2;
+ } else
+ goto out_err;
+ } else if (c == 'J') {
+ c = *(e++);
+ if (c == 'a') {
+ mo = 1;
+ e = e+2;
+ } else if (c == 'u') {
+ c = *(e++);
+ if (c == 'n') {
+ mo = 6;
+ e = e+1;
+ } else if (c == 'l') {
+ mo = 7;
+ e++;
+ }
+ } else
+ goto out_err;
+ } else if (c == 'M') {
+ e++;
+ c = *(e++);
+ if (c == 'r') {
+ mo = 3;
+ e = e+1;
+ } else if (c == 'y') {
+ mo = 5;
+ e = e+1;
+ } else
+ goto out_err;
+ } else
+ goto out_err;
+
+ /* year + ':' */
+ while (1) {
+ c = *(e++) - '0';
+ if (c > 9)
+ break;
+ y = y * 10 + c;
+ if (c == (unsigned char)(0 - '0'))
+ goto out_err;
+ }
+
+ /* hour + ':' */
+ b = e;
+ while (1) {
+ c = *(e++) - '0';
+ if (c > 9)
+ break;
+ h = h * 10 + c;
+ }
+ if (c == (unsigned char)(0 - '0'))
+ goto out_err;
+
+ /* minute + ':' */
+ b = e;
+ while (1) {
+ c = *(e++) - '0';
+ if (c > 9)
+ break;
+ m = m * 10 + c;
+ }
+ if (c == (unsigned char)(0 - '0'))
+ goto out_err;
+
+ /* second + '.' or ']' */
+ b = e;
+ while (1) {
+ c = *(e++) - '0';
+ if (c > 9)
+ break;
+ s = s * 10 + c;
+ }
+
+ if (likely(timeinfo)) {
+ if (timeinfo->tm_min == m &&
+ timeinfo->tm_hour == h &&
+ timeinfo->tm_mday == d &&
+ timeinfo->tm_mon == mo - 1 &&
+ timeinfo->tm_year == y - 1900)
+ return last_res + s;
+ }
+ else {
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+ }
+
+ timeinfo->tm_sec = 0;
+ timeinfo->tm_min = m;
+ timeinfo->tm_hour = h;
+ timeinfo->tm_mday = d;
+ timeinfo->tm_mon = mo - 1;
+ timeinfo->tm_year = y - 1900;
+ last_res = mktime(timeinfo);
+
+ return last_res + s;
+ out_err:
+ return -1;
+}
+
void truncated_line(int linenum, const char *line)
{
if (!(filter & FILT_QUIET))
@@ -537,9 +694,11 @@
struct eb32_node *n;
struct url_stat *ustat = NULL;
int val, test;
+ uint uval;
int filter_acc_delay = 0, filter_acc_count = 0;
int filter_time_resp = 0;
int filt_http_status_low = 0, filt_http_status_high = 0;
+ int filt2_timestamp_low = 0, filt2_timestamp_high = 0;
int skip_fields = 1;
void (*line_filter)(const char *accept_field, const char *time_field, struct timer **tptr) = NULL;
@@ -641,6 +800,21 @@
filt_http_status_low = *str ? atol(str) : 0;
filt_http_status_high = *sep ? atol(sep) : 65535;
}
+ else if (strcmp(argv[0], "-time") == 0) {
+ char *sep, *str;
+
+ if (argc < 2) die("missing option for -time ([min]:[max])");
+ filter2 |= FILT2_TIMESTAMP;
+
+ argc--; argv++;
+ str = *argv;
+ sep = strchr(str, ':'); /* [min]:[max] */
+ filt2_timestamp_low = *str ? atol(str) : 0;
+ if (!sep)
+ filt2_timestamp_high = 0xFFFFFFFF;
+ else
+ filt2_timestamp_high = atol(++sep);
+ }
else if (strcmp(argv[0], "-u") == 0)
filter |= FILT_COUNT_URL_ONLY;
else if (strcmp(argv[0], "-uc") == 0)
@@ -713,7 +887,8 @@
#endif
if (!line_filter && /* FILT_COUNT_ONLY ( see above), and no input filter (see below) */
- !(filter & (FILT_HTTP_ONLY|FILT_TIME_RESP|FILT_ERRORS_ONLY|FILT_HTTP_STATUS|FILT_QUEUE_ONLY|FILT_QUEUE_SRV_ONLY|FILT_TERM_CODE_NAME))) {
+ !(filter & (FILT_HTTP_ONLY|FILT_TIME_RESP|FILT_ERRORS_ONLY|FILT_HTTP_STATUS|FILT_QUEUE_ONLY|FILT_QUEUE_SRV_ONLY|FILT_TERM_CODE_NAME)) &&
+ !(filter2 & (FILT2_TIMESTAMP))) {
/* read the whole file at once first, ignore it if inverted output */
if (!filter_invert)
while ((lines_max < 0 || lines_out < lines_max) && fgets2(stdin) != NULL)
@@ -751,6 +926,11 @@
continue;
}
+ if (filter2 & FILT2_TIMESTAMP) {
+ uval = convert_date_to_timestamp(accept_field);
+ test &= (uval>=filt2_timestamp_low && uval<=filt2_timestamp_high) ;
+ }
+
if (filter & FILT_HTTP_ONLY) {
/* only report lines with at least 4 timers */
if (!time_field) {
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/doc/configuration.txt
^
|
@@ -4,7 +4,7 @@
----------------------
version 1.5
willy tarreau
- 2014/05/10
+ 2014/05/28
This document covers the configuration language as implemented in the version
@@ -2487,6 +2487,7 @@
Example :
errorfile 400 /etc/haproxy/errorfiles/400badreq.http
+ errorfile 408 /dev/null # workaround Chrome pre-connect bug
errorfile 403 /etc/haproxy/errorfiles/403forbid.http
errorfile 503 /etc/haproxy/errorfiles/503sorry.http
@@ -4377,20 +4378,27 @@
option log-health-checks
no option log-health-checks
- Enable or disable logging of health checks
+ Enable or disable logging of health checks status updates
May be used in sections : defaults | frontend | listen | backend
yes | no | yes | yes
Arguments : none
- Enable health checks logging so it possible to check for example what
- was happening before a server crash. Failed health check are logged if
- server is UP and succeeded health checks if server is DOWN, so the amount
- of additional information is limited.
-
- If health check logging is enabled no health check status is printed
- when servers is set up UP/DOWN/ENABLED/DISABLED.
-
- See also: "log" and section 8 about logging.
+ By default, failed health check are logged if server is UP and successful
+ health checks are logged if server is DOWN, so the amount of additional
+ information is limited.
+
+ When this option is enabled, any change of the health check status or to
+ the server's health will be logged, so that it becomes possible to know
+ that a server was failing occasional checks before crashing, or exactly when
+ it failed to respond a valid HTTP status, then when the port started to
+ reject connections, then when the server stopped responding at all.
+
+ Note that status changes not caused by health checks (eg: enable/disable on
+ the CLI) are intentionally not logged by this option.
+
+ See also: "option httpchk", "option ldap-check", "option mysql-check",
+ "option pgsql-check", "option redis-check", "option smtpchk",
+ "option tcp-check", "log" and section 8 about logging.
option log-separate-errors
@@ -7681,7 +7689,13 @@
this abuse because it is an inactivity timeout, which means that if the
attacker sends one character every now and then, the timeout will not
trigger. With the HTTP request timeout, no matter what speed the client
- types, the request will be aborted if it does not complete in time.
+ types, the request will be aborted if it does not complete in time. When the
+ timeout expires, an HTTP 408 response is sent to the client to inform it
+ about the problem, and the connection is closed. The logs will report
+ termination codes "cR". Some recent browsers are having problems with this
+ standard, well-documented behaviour, so it might be needed to hide the 408
+ code using "errorfile 408 /dev/null". See more details in the explanations of
+ the "cR" termination code in section 8.5.
Note that this timeout only applies to the header part of the request, and
not to any data. As soon as the empty line is received, this timeout is not
@@ -7699,7 +7713,7 @@
effect, unless the frontend is in TCP mode, in which case the HTTP backend's
timeout will be used.
- See also : "timeout http-keep-alive", "timeout client".
+ See also : "errorfile", "timeout http-keep-alive", "timeout client".
timeout queue <timeout>
@@ -8462,40 +8476,56 @@
agent-check
Enable an auxiliary agent check which is run independently of a regular
- health check. An agent health check is performed by making a TCP
- connection to the port set by the "agent-port" parameter" and reading
- an ASCII string. The string should have one of the following forms:
-
- * An ASCII representation of an positive integer percentage.
- e.g. "75%"
+ health check. An agent health check is performed by making a TCP connection
+ to the port set by the "agent-port" parameter and reading an ASCII string.
+ The string is made of a series of words delimited by spaces, tabs or commas
+ in any order, optionally terminated by '\r' and/or '\n', each consisting of :
+ - An ASCII representation of a positive integer percentage, e.g. "75%".
Values in this format will set the weight proportional to the initial
weight of a server as configured when haproxy starts.
- * The string "drain".
-
- This will cause the weight of a server to be set to 0, and thus it will
- not accept any new connections other than those that are accepted via
- persistence.
-
- * The string "down", optionally followed by a description string.
-
- Mark the server as down and log the description string as the reason.
+ - The word "ready". This will turn the server's administrative state to the
+ READY mode, thus cancelling any DRAIN or MAINT state
- * The string "stopped", optionally followed by a description string.
-
- This currently has the same behaviour as "down".
-
- * The string "fail", optionally followed by a description string.
-
- This currently has the same behaviour as "down".
+ - The word "drain". This will turn the server's administrative state to the
+ DRAIN mode, thus it will not accept any new connections other than those
+ that are accepted via persistence.
+
+ - The word "maint". This will turn the server's administrative state to the
+ MAINT mode, thus it will not accept any new connections at all, and health
+ checks will be stopped.
+
+ - The words "down", "failed", or "stopped", optionally followed by a
+ description string after a sharp ('#'). All of these mark the server's
+ operating state as DOWN, but since the word itself is reported on the stats
+ page, the difference allows an administrator to know if the situation was
+ expected or not : the service may intentionally be stopped, may appear up
+ but fail some validity tests, or may be seen as down (eg: missing process,
+ or port not responding).
+
+ - The word "up" sets back the server's operating state as UP if health checks
+ also report that the service is accessible.
+
+ Parameters which are not advertised by the agent are not changed. For
+ example, an agent might be designed to monitor CPU usage and only report a
+ relative weight and never interact with the operating status. Similarly, an
+ agent could be designed as an end-user interface with 3 radio buttons
+ allowing an administrator to change only the administrative state. However,
+ it is important to consider that only the agent may revert its own actions,
+ so if a server is set to DRAIN mode or to DOWN state using the agent, the
+ agent must implement the other equivalent actions to bring the service into
+ operations again.
Failure to connect to the agent is not considered an error as connectivity
is tested by the regular health check which is enabled by the "check"
- parameter.
+ parameter. Warning though, it is not a good idea to stop an agent after it
+ reports "down", since only an agent reporting "up" will be able to turn the
+ server up again. Note that the CLI on the Unix stats socket is also able to
+ force an agent's result in order to workaround a bogus agent if needed.
- Requires the ""agent-port" parameter to be set.
- See also the "agent-check" parameter.
+ Requires the "agent-port" parameter to be set. See also the "agent-inter"
+ parameter.
Supported in default-server: No
@@ -8992,10 +9022,10 @@
Supported in default-server: No
track [<proxy>/]<server>
- This option enables ability to set the current state of the server by
- tracking another one. Only a server with checks enabled can be tracked
- so it is not possible for example to track a server that tracks another
- one. If <proxy> is omitted the current one is used. If disable-on-404 is
+ This option enables ability to set the current state of the server by tracking
+ another one. It is possible to track a server which itself tracks another
+ server, provided that at the end of the chain, a server has health checks
+ enabled. If <proxy> is omitted the current one is used. If disable-on-404 is
used, it has to be enabled on both proxies.
Supported in default-server: No
@@ -9202,6 +9232,29 @@
The resulting sample is of the type of the last converter applied to the list,
which defaults to the type of the sample fetch method.
+Each sample or converter returns data of a specific type, specified with its
+keyword in this documentation. When an ACL is declared using a standard sample
+fetch method, certain types automatically involved a default matching method
+which are summarized in the table below :
+
+ +---------------------+-----------------+
+ | Sample or converter | Default |
+ | output type | matching method |
+ +---------------------+-----------------+
+ | boolean | bool |
+ +---------------------+-----------------+
+ | integer | int |
+ +---------------------+-----------------+
+ | ip | ip |
+ +---------------------+-----------------+
+ | string | str |
+ +---------------------+-----------------+
+ | binary | none, use "-m" |
+ +---------------------+-----------------+
+
+Note that in order to match a binary samples, it is mandatory to specify a
+matching method, see below.
+
The ACL engine can match these types against patterns of the following types :
- boolean
- integer or integer range
@@ -9353,27 +9406,28 @@
acl alternate3 hdr(host) -m beg www.
-The table below summarizes the compatibility matrix between sample types
-and the pattern types to fetch against. It indicates for each compatible
-combination the name of the matching method to be used, prefixed with "*" when
-the method is implicit and will work by default without "-m".
+The table below summarizes the compatibility matrix between sample or converter
+types and the pattern types to fetch against. It indicates for each compatible
+combination the name of the matching method to be used, surrounded with angle
+brackets ">" and "<" when the method is the default one and will work by
+default without "-m".
+-------------------------------------------------+
| Input sample type |
+----------------------+---------+---------+---------+---------+---------+
- | pattern type | boolean | integer | IP | string | binary |
+ | pattern type | boolean | integer | ip | string | binary |
+----------------------+---------+---------+---------+---------+---------+
| none (presence only) | found | found | found | found | found |
+----------------------+---------+---------+---------+---------+---------+
- | none (boolean value) | *bool | bool | | bool | |
+ | none (boolean value) |> bool <| bool | | bool | |
+----------------------+---------+---------+---------+---------+---------+
- | integer (value) | int | *int | int | int | |
+ | integer (value) | int |> int <| int | int | |
+----------------------+---------+---------+---------+---------+---------+
| integer (length) | len | len | len | len | len |
+----------------------+---------+---------+---------+---------+---------+
- | IP address | | | *ip | ip | ip |
+ | IP address | | |> ip <| ip | ip |
+----------------------+---------+---------+---------+---------+---------+
- | exact string | str | str | str | str | str |
+ | exact string | str | str | str |> str <| str |
+----------------------+---------+---------+---------+---------+---------+
| prefix | beg | beg | beg | beg | beg |
+----------------------+---------+---------+---------+---------+---------+
@@ -12482,7 +12536,20 @@
client side for PPPoE networks which cannot transport full-sized
packets, or by clients sending requests by hand and not typing fast
enough, or forgetting to enter the empty line at the end of the
- request. The HTTP status code is likely a 408 here.
+ request. The HTTP status code is likely a 408 here. Note: recently,
+ some browsers such as Google Chrome started to break the deployed Web
+ infrastructure by aggressively implementing a new "pre-connect"
+ feature, consisting in sending connections to sites recently visited
+ without sending any request on them until the user starts to browse
+ the site. This mechanism causes massive disruption among resource-
+ limited servers, and causes a lot of 408 errors in HAProxy logs.
+ Worse, some people report that sometimes the browser displays the 408
+ error when the user expects to see the actual content (Mozilla fixed
+ this bug in 2004, while Chrome users continue to report it in 2014),
+ so in this case, using "errorfile 408 /dev/null" can be used as a
+ workaround. More information on the subject is available here :
+ https://bugzilla.mozilla.org/show_bug.cgi?id=248827
+ https://code.google.com/p/chromium/issues/detail?id=85229
CT The client aborted while its session was tarpitted. It is important to
check if this happens on valid requests, in order to be sure that no
@@ -13123,6 +13190,15 @@
This command is restricted and can only be issued on sockets configured for
level "admin".
+disable health <backend>/<server>
+ Mark the primary health check as temporarily stopped. This will disable
+ sending of health checks, and the last health check result will be ignored.
+ The server will be in unchecked state and considered UP unless an auxiliary
+ agent check forces it down.
+
+ This command is restricted and can only be issued on sockets configured for
+ level "admin".
+
disable server <backend>/<server>
Mark the server DOWN for maintenance. In this mode, no more checks will be
performed on the server until it leaves maintenance.
@@ -13160,6 +13236,13 @@
This command is restricted and can only be issued on sockets configured for
level "admin".
+enable health <backend>/<server>
+ Resume a primary health check that was temporarily stopped. This will enable
+ sending of health checks again. Please see "disable health" for details.
+
+ This command is restricted and can only be issued on sockets configured for
+ level "admin".
+
enable server <backend>/<server>
If the server was previously marked as DOWN for maintenance, this marks the
server UP and checks are re-enabled.
@@ -13277,6 +13360,30 @@
is passed in number of sessions per second sent to the SSL stack. It applies
before the handshake in order to protect the stack against handshake abuses.
+set server <backend>/<server> agent [ up | down ]
+ Force a server's agent to a new state. This can be useful to immediately
+ switch a server's state regardless of some slow agent checks for example.
+ Note that the change is propagated to tracking servers if any.
+
+set server <backend>/<server> health [ up | stopping | down ]
+ Force a server's health to a new state. This can be useful to immediately
+ switch a server's state regardless of some slow health checks for example.
+ Note that the change is propagated to tracking servers if any.
+
+set server <backend>/<server> state [ ready | drain | maint ]
+ Force a server's administrative state to a new state. This can be useful to
+ disable load balancing and/or any traffic to a server. Setting the state to
+ "ready" puts the server in normal mode, and the command is the equivalent of
+ the "enable server" command. Setting the state to "maint" disables any traffic
+ to the server as well as any health checks. This is the equivalent of the
+ "disable server" command. Setting the mode to "drain" only removes the server
+ from load balancing but still allows it to be checked and to accept new
+ persistent connections. Changes are propagated to tracking servers if any.
+
+set server <backend>/<server> weight <weight>[%]
+ Change a server's weight to the value passed in argument. This is the exact
+ equivalent of the "set weight" command below.
+
set table <table> key <key> [data.<data_type> <value>]*
Create or update a stick-table entry in the table. If the key is not present,
an entry is inserted. See stick-table in section 4.2 to find all possible
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/examples/haproxy.spec
^
|
@@ -1,6 +1,6 @@
Summary: HA-Proxy is a TCP/HTTP reverse proxy for high availability environments
Name: haproxy
-Version: 1.5-dev25
+Version: 1.5-dev26
Release: 1
License: GPL
Group: System Environment/Daemons
@@ -76,6 +76,9 @@
%attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name}
%changelog
+* Wed May 28 2014 Willy Tarreau <w@1wt.eu>
+- updated to 1.5-dev26
+
* Sat May 10 2014 Willy Tarreau <w@1wt.eu>
- updated to 1.5-dev25
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/include/common/regex.h
^
|
@@ -79,7 +79,7 @@
* The function return 1 is succes case, else return 0 and err is filled.
*/
int regex_comp(const char *str, struct my_regex *regex, int cs, int cap, char **err);
-int exp_replace(char *dst, char *src, const char *str, const regmatch_t *matches);
+int exp_replace(char *dst, uint dst_size, char *src, const char *str, const regmatch_t *matches);
const char *check_replace_string(const char *str);
const char *chain_regex(struct hdr_exp **head, const regex_t *preg,
int action, const char *replace, void *cond);
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/include/proto/backend.h
^
|
@@ -52,20 +52,79 @@
be->be_counters.last_sess = now.tv_sec;
}
-/* This function returns non-zero if a server with the given weight and state
- * is usable for LB, otherwise zero.
+/* This function returns non-zero if the designated server is usable for LB
+ * according to its current weight and current state. Otherwise it returns 0.
*/
-static inline int srv_is_usable(int state, int weight)
+static inline int srv_is_usable(const struct server *srv)
{
- if (!weight)
+ enum srv_state state = srv->state;
+
+ if (!srv->eweight)
+ return 0;
+ if (srv->admin & SRV_ADMF_MAINT)
+ return 0;
+ if (srv->admin & SRV_ADMF_DRAIN)
+ return 0;
+ switch (state) {
+ case SRV_ST_STARTING:
+ case SRV_ST_RUNNING:
+ return 1;
+ case SRV_ST_STOPPING:
+ case SRV_ST_STOPPED:
+ return 0;
+ }
+ return 0;
+}
+
+/* This function returns non-zero if the designated server was usable for LB
+ * according to its current weight and previous state. Otherwise it returns 0.
+ */
+static inline int srv_was_usable(const struct server *srv)
+{
+ enum srv_state state = srv->prev_state;
+
+ if (!srv->prev_eweight)
+ return 0;
+ if (srv->prev_admin & SRV_ADMF_MAINT)
return 0;
- if (state & (SRV_GOINGDOWN | SRV_MAINTAIN))
+ if (srv->prev_admin & SRV_ADMF_DRAIN)
return 0;
- if (!(state & SRV_RUNNING))
+ switch (state) {
+ case SRV_ST_STARTING:
+ case SRV_ST_RUNNING:
+ return 1;
+ case SRV_ST_STOPPING:
+ case SRV_ST_STOPPED:
return 0;
- return 1;
+ }
+ return 0;
}
+/* This function commits the current server state and weight onto the previous
+ * ones in order to detect future changes.
+ */
+static inline void srv_lb_commit_status(struct server *srv)
+{
+ srv->prev_state = srv->state;
+ srv->prev_admin = srv->admin;
+ srv->prev_eweight = srv->eweight;
+}
+
+/* This function returns true when a server has experienced a change since last
+ * commit on its state or weight, otherwise zero.
+ */
+static inline int srv_lb_status_changed(const struct server *srv)
+{
+ return (srv->state != srv->prev_state ||
+ srv->admin != srv->prev_admin ||
+ srv->eweight != srv->prev_eweight);
+}
+
+/* sends a log message when a backend goes down, and also sets last
+ * change date.
+ */
+void set_backend_down(struct proxy *be);
+
#endif /* _PROTO_BACKEND_H */
/*
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/include/proto/checks.h
^
|
@@ -27,8 +27,6 @@
const char *get_check_status_description(short check_status);
const char *get_check_status_info(short check_status);
-void set_server_down(struct check *check);
-void set_server_up(struct check *check);
int start_checks();
void __health_adjust(struct server *s, short status);
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/include/proto/fd.h
^
|
@@ -335,6 +335,7 @@
fdtab[fd].ev = 0;
fdtab[fd].new = 1;
fdtab[fd].linger_risk = 0;
+ fdtab[fd].cloned = 0;
if (fd + 1 > maxfd)
maxfd = fd + 1;
}
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/include/proto/queue.h
^
|
@@ -42,7 +42,8 @@
void pendconn_free(struct pendconn *p);
void process_srv_queue(struct server *s);
unsigned int srv_dynamic_maxconn(const struct server *s);
-
+int pendconn_redistribute(struct server *s);
+int pendconn_grab_from_px(struct server *s);
/* Returns the first pending connection for server <s>, which may be NULL if
@@ -75,7 +76,7 @@
* for and if/else usage.
*/
static inline int may_dequeue_tasks(const struct server *s, const struct proxy *p) {
- return (s && (s->nbpend || (p->nbpend && srv_is_usable(s->state, s->eweight))) &&
+ return (s && (s->nbpend || (p->nbpend && srv_is_usable(s))) &&
(!s->maxconn || s->cur_sess < srv_dynamic_maxconn(s)));
}
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/include/proto/server.h
^
|
@@ -96,17 +96,110 @@
const char *weight_str);
/*
- * Update the server's drain state to reflect its user-weight. This is not
- * done immediately to allow a discrepancy between the server's user-weight
- * and drains state to control logging of changes in the drain state.
+ * Return true if the server has a zero user-weight, meaning it's in draining
+ * mode (ie: not taking new non-persistent connections).
*/
-static inline void set_server_drain_state(struct server *s)
+static inline int server_is_draining(const struct server *s)
{
- if (!s->uweight)
- s->state |= SRV_DRAIN;
- else
- s->state &= ~SRV_DRAIN;
+ return !s->uweight || (s->admin & SRV_ADMF_DRAIN);
}
+
+/* Shutdown all connections of a server. The caller must pass a termination
+ * code in <why>, which must be one of SN_ERR_* indicating the reason for the
+ * shutdown.
+ */
+void srv_shutdown_sessions(struct server *srv, int why);
+
+/* Shutdown all connections of all backup servers of a proxy. The caller must
+ * pass a termination code in <why>, which must be one of SN_ERR_* indicating
+ * the reason for the shutdown.
+ */
+void srv_shutdown_backup_sessions(struct proxy *px, int why);
+
+/* Appends some information to a message string related to a server going UP or
+ * DOWN. If both <forced> and <reason> are null and the server tracks another
+ * one, a "via" information will be provided to know where the status came from.
+ * If <reason> is non-null, the entire string will be appended after a comma and
+ * a space (eg: to report some information from the check that changed the state).
+ * If <xferred> is non-negative, some information about requeued sessions are
+ * provided.
+ */
+void srv_append_status(struct chunk *msg, struct server *s, const char *reason, int xferred, int forced);
+
+/* Marks server <s> down, regardless of its checks' statuses, notifies by all
+ * available means, recounts the remaining servers on the proxy and transfers
+ * queued sessions whenever possible to other servers. It automatically
+ * recomputes the number of servers, but not the map. Maintenance servers are
+ * ignored. It reports <reason> if non-null as the reason for going down. Note
+ * that it makes use of the trash to build the log strings, so <reason> must
+ * not be placed there.
+ */
+void srv_set_stopped(struct server *s, const char *reason);
+
+/* Marks server <s> up regardless of its checks' statuses and provided it isn't
+ * in maintenance. Notifies by all available means, recounts the remaining
+ * servers on the proxy and tries to grab requests from the proxy. It
+ * automatically recomputes the number of servers, but not the map. Maintenance
+ * servers are ignored. It reports <reason> if non-null as the reason for going
+ * up. Note that it makes use of the trash to build the log strings, so <reason>
+ * must not be placed there.
+ */
+void srv_set_running(struct server *s, const char *reason);
+
+/* Marks server <s> stopping regardless of its checks' statuses and provided it
+ * isn't in maintenance. Notifies by all available means, recounts the remaining
+ * servers on the proxy and tries to grab requests from the proxy. It
+ * automatically recomputes the number of servers, but not the map. Maintenance
+ * servers are ignored. It reports <reason> if non-null as the reason for going
+ * up. Note that it makes use of the trash to build the log strings, so <reason>
+ * must not be placed there.
+ */
+void srv_set_stopping(struct server *s, const char *reason);
+
+/* Enables admin flag <mode> (among SRV_ADMF_*) on server <s>. This is used to
+ * enforce either maint mode or drain mode. It is not allowed to set more than
+ * one flag at once. The equivalent "inherited" flag is propagated to all
+ * tracking servers. Maintenance mode disables health checks (but not agent
+ * checks). When either the flag is already set or no flag is passed, nothing
+ * is done.
+ */
+void srv_set_admin_flag(struct server *s, enum srv_admin mode);
+
+/* Disables admin flag <mode> (among SRV_ADMF_*) on server <s>. This is used to
+ * stop enforcing either maint mode or drain mode. It is not allowed to set more
+ * than one flag at once. The equivalent "inherited" flag is propagated to all
+ * tracking servers. Leaving maintenance mode re-enables health checks. When
+ * either the flag is already cleared or no flag is passed, nothing is done.
+ */
+void srv_clr_admin_flag(struct server *s, enum srv_admin mode);
+
+/* Puts server <s> into maintenance mode, and propagate that status down to all
+ * tracking servers.
+ */
+static inline void srv_adm_set_maint(struct server *s)
+{
+ srv_set_admin_flag(s, SRV_ADMF_FMAINT);
+ srv_clr_admin_flag(s, SRV_ADMF_FDRAIN);
+}
+
+/* Puts server <s> into drain mode, and propagate that status down to all
+ * tracking servers.
+ */
+static inline void srv_adm_set_drain(struct server *s)
+{
+ srv_set_admin_flag(s, SRV_ADMF_FDRAIN);
+ srv_clr_admin_flag(s, SRV_ADMF_FMAINT);
+}
+
+/* Puts server <s> into ready mode, and propagate that status down to all
+ * tracking servers.
+ */
+static inline void srv_adm_set_ready(struct server *s)
+{
+ srv_clr_admin_flag(s, SRV_ADMF_FDRAIN);
+ srv_clr_admin_flag(s, SRV_ADMF_FMAINT);
+}
+
/*
* Local variables:
* c-indent-level: 8
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/include/types/checks.h
^
|
@@ -29,6 +29,7 @@
*/
enum chk_result {
CHK_RES_UNKNOWN = 0, /* initialized to this by default */
+ CHK_RES_NEUTRAL, /* valid check but no status information */
CHK_RES_FAILED, /* check failed */
CHK_RES_PASSED, /* check succeeded and server is fully up again */
CHK_RES_CONDPASS, /* check reports the server doesn't want new sessions */
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/include/types/fd.h
^
|
@@ -86,6 +86,7 @@
unsigned char new:1; /* 1 if this fd has just been created */
unsigned char updated:1; /* 1 if this fd is already in the update list */
unsigned char linger_risk:1; /* 1 if we must kill lingering before closing */
+ unsigned char cloned:1; /* 1 if a cloned socket, requires EPOLL_CTL_DEL on close */
};
/* less often used information */
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/include/types/global.h
^
|
@@ -90,11 +90,15 @@
struct freq_ctr conn_per_sec;
struct freq_ctr sess_per_sec;
struct freq_ctr ssl_per_sec;
+ struct freq_ctr ssl_fe_keys_per_sec;
+ struct freq_ctr ssl_be_keys_per_sec;
struct freq_ctr comp_bps_in; /* bytes per second, before http compression */
struct freq_ctr comp_bps_out; /* bytes per second, after http compression */
int cps_lim, cps_max;
int sps_lim, sps_max;
int ssl_lim, ssl_max;
+ int ssl_fe_keys_max, ssl_be_keys_max;
+ unsigned int shctx_lookups, shctx_misses;
int comp_rate_lim; /* HTTP compression rate limit */
int maxpipes; /* max # of pipes */
int maxsock; /* max # of sockets */
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/include/types/proto_http.h
^
|
@@ -307,16 +307,6 @@
HTTP_ERR_SIZE
};
-/* Actions available for the stats admin forms */
-enum {
- ST_ADM_ACTION_NONE = 0,
- ST_ADM_ACTION_DISABLE,
- ST_ADM_ACTION_ENABLE,
- ST_ADM_ACTION_STOP,
- ST_ADM_ACTION_START,
- ST_ADM_ACTION_SHUTDOWN,
-};
-
/* status codes available for the stats admin page */
enum {
STAT_STATUS_INIT = 0,
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/include/types/server.h
^
|
@@ -43,18 +43,48 @@
#include <types/checks.h>
+/* server states. Only SRV_ST_DOWN indicates a down server. */
+enum srv_state {
+ SRV_ST_STOPPED = 0, /* the server is down. Please keep set to zero. */
+ SRV_ST_STARTING, /* the server is warming up (up but throttled) */
+ SRV_ST_RUNNING, /* the server is fully up */
+ SRV_ST_STOPPING, /* the server is up but soft-stopping (eg: 404) */
+};
+
+/* Administrative status : a server runs in one of these 3 stats :
+ * - READY : normal mode
+ * - DRAIN : takes no new visitor, equivalent to weight == 0
+ * - MAINT : maintenance mode, no more traffic nor health checks.
+ *
+ * Each server may be in maintenance by itself or may inherit this status from
+ * another server it tracks. It can also be in drain mode by itself or inherit
+ * it from another server. Let's store these origins here as flags. These flags
+ * are combined this way :
+ *
+ * FMAINT IMAINT FDRAIN IDRAIN Resulting state
+ * 0 0 0 0 READY
+ * 0 0 0 1 DRAIN
+ * 0 0 1 x DRAIN
+ * 0 1 x x MAINT
+ * 1 x x x MAINT
+ *
+ * This can be simplified this way :
+ *
+ * state_str = (state & MAINT) ? "MAINT" : (state & DRAIN) : "DRAIN" : "READY"
+ */
+enum srv_admin {
+ SRV_ADMF_FMAINT = 0x1, /* the server was explicitly forced into maintenance */
+ SRV_ADMF_IMAINT = 0x2, /* the server has inherited the maintenance status from a tracked server */
+ SRV_ADMF_MAINT = 0x3, /* mask to check if any maintenance flag is present */
+ SRV_ADMF_FDRAIN = 0x4, /* the server was explicitly forced into drain state */
+ SRV_ADMF_IDRAIN = 0x8, /* the server has inherited the drain status from a tracked server */
+ SRV_ADMF_DRAIN = 0xC, /* mask to check if any drain flag is present */
+};
+
/* server flags */
-#define SRV_RUNNING 0x0001 /* the server is UP */
-#define SRV_BACKUP 0x0002 /* this server is a backup server */
-#define SRV_MAPPORTS 0x0004 /* this server uses mapped ports */
-/* unused: 0x0008 */
-/* unused: 0x0010 */
-#define SRV_GOINGDOWN 0x0020 /* this server says that it's going down (404) */
-#define SRV_WARMINGUP 0x0040 /* this server is warming up after a failure */
-#define SRV_MAINTAIN 0x0080 /* this server is in maintenance mode */
-#define SRV_DRAIN 0x0100 /* this server has been requested to drain its connections */
-/* unused: 0x0200, 0x0400, 0x0800 */
-#define SRV_NON_STICK 0x1000 /* never add connections allocated to this server to a stick table */
+#define SRV_F_BACKUP 0x0001 /* this server is a backup server */
+#define SRV_F_MAPPORTS 0x0002 /* this server uses mapped ports */
+#define SRV_F_NON_STICK 0x0004 /* never add connections allocated to this server to a stick table */
/* configured server options for send-proxy (server->pp_opts) */
#define SRV_PP_V1 0x0001 /* proxy protocol version 1 */
@@ -104,9 +134,10 @@
struct server {
enum obj_type obj_type; /* object type == OBJ_TYPE_SERVER */
+ enum srv_state state, prev_state; /* server state among SRV_ST_* */
+ enum srv_admin admin, prev_admin; /* server maintenance status : SRV_ADMF_* */
+ unsigned char flags; /* server flags (SRV_F_*) */
struct server *next;
- int state; /* server state (SRV_*) */
- int prev_state; /* server state before last change (SRV_*) */
int cklen; /* the len of the cookie, to speed up checks */
int rdr_len; /* the length of the redirection prefix */
char *cookie; /* the id set in the cookie */
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/acl.c
^
|
@@ -415,6 +415,14 @@
expr->pat.prune = pat_prune_fcts[PAT_MATCH_IP];
expr->pat.expect_type = pat_match_types[PAT_MATCH_IP];
break;
+ case SMP_T_STR:
+ expr->pat.parse = pat_parse_fcts[PAT_MATCH_STR];
+ expr->pat.index = pat_index_fcts[PAT_MATCH_STR];
+ expr->pat.match = pat_match_fcts[PAT_MATCH_STR];
+ expr->pat.delete = pat_delete_fcts[PAT_MATCH_STR];
+ expr->pat.prune = pat_prune_fcts[PAT_MATCH_STR];
+ expr->pat.expect_type = pat_match_types[PAT_MATCH_STR];
+ break;
}
}
@@ -444,11 +452,11 @@
is_loaded = 0;
unique_id = -1;
while (**args == '-') {
- if ((*args)[1] == 'i')
+ if (strcmp(*args, "-i") == 0)
patflags |= PAT_MF_IGNORE_CASE;
- else if ((*args)[1] == 'n')
+ else if (strcmp(*args, "-n") == 0)
patflags |= PAT_MF_NO_DNS;
- else if ((*args)[1] == 'u') {
+ else if (strcmp(*args, "-u") == 0) {
unique_id = strtol(args[1], &error, 10);
if (*error != '\0') {
memprintf(err, "the argument of -u must be an integer");
@@ -463,7 +471,7 @@
args++;
}
- else if ((*args)[1] == 'f') {
+ else if (strcmp(*args, "-f") == 0) {
if (!expr->pat.parse) {
memprintf(err, "matching method must be specified first (using '-m') when using a sample fetch of this type ('%s')", expr->kw);
goto out_free_expr;
@@ -474,7 +482,7 @@
is_loaded = 1;
args++;
}
- else if ((*args)[1] == 'm') {
+ else if (strcmp(*args, "-m") == 0) {
int idx;
if (is_loaded) {
@@ -501,15 +509,18 @@
expr->pat.expect_type = pat_match_types[idx];
args++;
}
- else if ((*args)[1] == 'M') {
+ else if (strcmp(*args, "-M") == 0) {
load_as_map = 1;
}
- else if ((*args)[1] == '-') {
+ else if (strcmp(*args, "--") == 0) {
args++;
break;
}
- else
+ else {
+ memprintf(err, "'%s' is not a valid ACL option. Please use '--' before any pattern beginning with a '-'", args[0]);
+ goto out_free_expr;
break;
+ }
args++;
}
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/auth.c
^
|
@@ -134,6 +134,7 @@
if (!ag) {
Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
curuserlist->name, group, curuser->user);
+ free(groups);
return ERR_ALERT | ERR_FATAL;
}
@@ -142,7 +143,8 @@
if (!grl) {
Alert("userlist '%s': no more memory when trying to allocate the user groups.\n",
curuserlist->name);
- return ERR_ALERT | ERR_FATAL;
+ free(groups);
+ return ERR_ALERT | ERR_FATAL;
}
grl->group = ag;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/backend.c
^
|
@@ -39,11 +39,13 @@
#include <proto/lb_fwlc.h>
#include <proto/lb_fwrr.h>
#include <proto/lb_map.h>
+#include <proto/log.h>
#include <proto/obj_type.h>
#include <proto/payload.h>
#include <proto/protocol.h>
#include <proto/proto_http.h>
#include <proto/proto_tcp.h>
+#include <proto/proxy.h>
#include <proto/queue.h>
#include <proto/sample.h>
#include <proto/server.h>
@@ -97,10 +99,10 @@
px->lbprm.tot_wact = px->lbprm.tot_wbck = 0;
px->lbprm.fbck = NULL;
for (srv = px->srv; srv != NULL; srv = srv->next) {
- if (!srv_is_usable(srv->state, srv->eweight))
+ if (!srv_is_usable(srv))
continue;
- if (srv->state & SRV_BACKUP) {
+ if (srv->flags & SRV_F_BACKUP) {
if (!px->srv_bck &&
!(px->options & PR_O_USE_ALL_BK))
px->lbprm.fbck = srv;
@@ -547,7 +549,7 @@
(!s->be->max_ka_queue ||
server_has_room(__objt_server(conn->target)) ||
(__objt_server(conn->target)->nbpend + 1) < s->be->max_ka_queue))) &&
- srv_is_usable(__objt_server(conn->target)->state, __objt_server(conn->target)->eweight)) {
+ srv_is_usable(__objt_server(conn->target))) {
/* This session was relying on a server in a previous request
* and the proxy has "option prefer-current-server" set, so
* let's try to reuse the same server.
@@ -767,7 +769,7 @@
/* if this server remaps proxied ports, we'll use
* the port the client connected to with an offset. */
- if ((objt_server(s->target)->state & SRV_MAPPORTS) && cli_conn) {
+ if ((objt_server(s->target)->flags & SRV_F_MAPPORTS) && cli_conn) {
int base_port;
conn_get_to_addr(cli_conn);
@@ -1193,6 +1195,18 @@
return 0;
}
+/* sends a log message when a backend goes down, and also sets last
+ * change date.
+ */
+void set_backend_down(struct proxy *be)
+{
+ be->last_change = now.tv_sec;
+ be->down_trans++;
+
+ Alert("%s '%s' has no server available!\n", proxy_type_str(be), be->id);
+ send_log(be, LOG_EMERG, "%s %s has no server available!\n", proxy_type_str(be), be->id);
+}
+
/* Apply RDP cookie persistence to the current session. For this, the function
* tries to extract an RDP cookie from the request buffer, and look for the
* matching server in the list. If the server is found, it is assigned to the
@@ -1242,7 +1256,7 @@
while (srv) {
if (srv->addr.ss_family == AF_INET &&
memcmp(&addr, &(srv->addr), sizeof(addr)) == 0) {
- if ((srv->state & SRV_RUNNING) || (px->options & PR_O_PERSIST)) {
+ if ((srv->state != SRV_ST_STOPPED) || (px->options & PR_O_PERSIST)) {
/* we found the server and it is usable */
s->flags |= SN_DIRECT | SN_ASSIGNED;
s->target = &srv->obj_type;
@@ -1489,8 +1503,8 @@
smp->flags = SMP_F_VOL_TEST;
smp->type = SMP_T_BOOL;
- if (!(srv->state & SRV_MAINTAIN) &&
- (!(srv->check.state & CHK_ST_CONFIGURED) || (srv->state & SRV_RUNNING)))
+ if (!(srv->admin & SRV_ADMF_MAINT) &&
+ (!(srv->check.state & CHK_ST_CONFIGURED) || (srv->state != SRV_ST_STOPPED)))
smp->data.uint = 1;
else
smp->data.uint = 0;
@@ -1512,7 +1526,7 @@
smp->data.uint = 0;
for (iterator = args->data.prx->srv; iterator; iterator = iterator->next) {
- if ((iterator->state & SRV_RUNNING) == 0)
+ if (iterator->state == SRV_ST_STOPPED)
continue;
if (iterator->maxconn == 0 || iterator->maxqueue == 0) {
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/cfgparse.c
^
|
@@ -1505,6 +1505,10 @@
}
+/* This function createss a new req* or rsp* rule to the proxy. It compiles the
+ * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
+ * ERR_FATAL in case of error.
+ */
static int create_cond_regex_rule(const char *file, int line,
struct proxy *px, int dir, int action, int flags,
const char *cmd, const char *reg, const char *repl,
@@ -1513,41 +1517,41 @@
regex_t *preg = NULL;
char *errmsg = NULL;
const char *err;
- int err_code = 0;
+ int ret_code = 0;
struct acl_cond *cond = NULL;
if (px == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
- err_code |= ERR_ALERT | ERR_FATAL;
+ ret_code |= ERR_ALERT | ERR_FATAL;
goto err;
}
if (*reg == 0) {
Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
- err_code |= ERR_ALERT | ERR_FATAL;
+ ret_code |= ERR_ALERT | ERR_FATAL;
goto err;
}
if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
- err_code |= ERR_WARN;
+ ret_code |= ERR_WARN;
if (cond_start &&
(strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
file, line, cmd, errmsg);
- err_code |= ERR_ALERT | ERR_FATAL;
+ ret_code |= ERR_ALERT | ERR_FATAL;
goto err;
}
}
else if (cond_start && **cond_start) {
Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
file, line, cmd, *cond_start);
- err_code |= ERR_ALERT | ERR_FATAL;
+ ret_code |= ERR_ALERT | ERR_FATAL;
goto err;
}
- err_code |= warnif_cond_conflicts(cond,
+ ret_code |= warnif_cond_conflicts(cond,
(dir == SMP_OPT_DIR_REQ) ?
((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
@@ -1556,13 +1560,13 @@
preg = calloc(1, sizeof(regex_t));
if (!preg) {
Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
- err_code = ERR_ALERT | ERR_FATAL;
+ ret_code = ERR_ALERT | ERR_FATAL;
goto err;
}
if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
- err_code = ERR_ALERT | ERR_FATAL;
+ ret_code = ERR_ALERT | ERR_FATAL;
goto err;
}
@@ -1571,19 +1575,21 @@
if (repl && err) {
Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
file, line, cmd, *err);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto err;
+ ret_code |= ERR_ALERT | ERR_FATAL;
+ goto err_free;
}
if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
- err_code |= ERR_WARN;
+ ret_code |= ERR_WARN;
- free(errmsg);
- return err_code;
+ return ret_code;
+
+ err_free:
+ regfree(preg);
err:
- free(errmsg);
free(preg);
- return err_code;
+ free(errmsg);
+ return ret_code;
}
/*
@@ -6557,7 +6563,7 @@
if (newsrv->trackit) {
struct proxy *px;
- struct server *srv;
+ struct server *srv, *loop;
char *pname, *sname;
pname = newsrv->trackit;
@@ -6591,11 +6597,24 @@
goto next_srv;
}
- if (!(srv->check.state & CHK_ST_CONFIGURED)) {
+ if (!(srv->check.state & CHK_ST_CONFIGURED) &&
+ !(srv->agent.state & CHK_ST_CONFIGURED) &&
+ !srv->track && !srv->trackit) {
Alert("config : %s '%s', server '%s': unable to use %s/%s for "
- "tracking as it does not have checks enabled.\n",
- proxy_type_str(curproxy), curproxy->id,
- newsrv->id, px->id, srv->id);
+ "tracking as it does not have any check nor agent enabled.\n",
+ proxy_type_str(curproxy), curproxy->id,
+ newsrv->id, px->id, srv->id);
+ cfgerr++;
+ goto next_srv;
+ }
+
+ for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
+
+ if (loop) {
+ Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
+ "belongs to a tracking chain looping back to %s/%s.\n",
+ proxy_type_str(curproxy), curproxy->id,
+ newsrv->id, px->id, srv->id, px->id, loop->id);
cfgerr++;
goto next_srv;
}
@@ -6611,8 +6630,9 @@
}
/* if the other server is forced disabled, we have to do the same here */
- if (srv->state & SRV_MAINTAIN) {
- newsrv->state &= ~SRV_RUNNING;
+ if (srv->admin & SRV_ADMF_MAINT) {
+ newsrv->admin |= SRV_ADMF_IMAINT;
+ newsrv->state = SRV_ST_STOPPED;
newsrv->check.health = 0;
newsrv->agent.health = 0;
}
@@ -6748,7 +6768,7 @@
err_code |= ERR_WARN;
}
- if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
+ if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
proxy_type_str(curproxy), curproxy->id, newsrv->id);
err_code |= ERR_WARN;
@@ -6950,7 +6970,7 @@
}
/* Check multi-process mode compatibility */
- if (global.nbproc > 1) {
+ if (global.nbproc > 1 && global.stats_fe) {
list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
unsigned long mask;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/checks.c
^
|
@@ -66,6 +66,8 @@
[HCHK_STATUS_INI] = { CHK_RES_UNKNOWN, "INI", "Initializing" },
[HCHK_STATUS_START] = { /* SPECIAL STATUS*/ },
+ /* Below we have finished checks */
+ [HCHK_STATUS_CHECKED] = { CHK_RES_NEUTRAL, "CHECKED", "No status change" },
[HCHK_STATUS_HANA] = { CHK_RES_FAILED, "HANA", "Health analyze" },
[HCHK_STATUS_SOCKERR] = { CHK_RES_FAILED, "SOCKERR", "Socket error" },
@@ -155,51 +157,45 @@
return analyze_statuses[HANA_STATUS_UNKNOWN].desc;
}
-static void server_status_printf(struct chunk *msg, struct server *s, struct check *check, int xferred) {
- if (s->track)
- chunk_appendf(msg, " via %s/%s",
- s->track->proxy->id, s->track->id);
+/* Builds a string containing some information about the health check's result.
+ * The output string is allocated from the trash chunks. If the check is NULL,
+ * NULL is returned. This is designed to be used when emitting logs about health
+ * checks.
+ */
+static const char *check_reason_string(struct check *check)
+{
+ struct chunk *msg;
- if (check) {
- chunk_appendf(msg, ", reason: %s", get_check_status_description(check->status));
+ if (!check)
+ return NULL;
- if (check->status >= HCHK_STATUS_L57DATA)
- chunk_appendf(msg, ", code: %d", check->code);
+ msg = get_trash_chunk();
+ chunk_printf(msg, "reason: %s", get_check_status_description(check->status));
- if (*check->desc) {
- struct chunk src;
+ if (check->status >= HCHK_STATUS_L57DATA)
+ chunk_appendf(msg, ", code: %d", check->code);
- chunk_appendf(msg, ", info: \"");
+ if (*check->desc) {
+ struct chunk src;
- chunk_initlen(&src, check->desc, 0, strlen(check->desc));
- chunk_asciiencode(msg, &src, '"');
+ chunk_appendf(msg, ", info: \"");
- chunk_appendf(msg, "\"");
- }
+ chunk_initlen(&src, check->desc, 0, strlen(check->desc));
+ chunk_asciiencode(msg, &src, '"');
- if (check->duration >= 0)
- chunk_appendf(msg, ", check duration: %ldms", check->duration);
+ chunk_appendf(msg, "\"");
}
- if (xferred >= 0) {
- if (!(s->state & SRV_RUNNING))
- chunk_appendf(msg, ". %d active and %d backup servers left.%s"
- " %d sessions active, %d requeued, %d remaining in queue",
- s->proxy->srv_act, s->proxy->srv_bck,
- (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
- s->cur_sess, xferred, s->nbpend);
- else
- chunk_appendf(msg, ". %d active and %d backup servers online.%s"
- " %d sessions requeued, %d total in queue",
- s->proxy->srv_act, s->proxy->srv_bck,
- (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
- xferred, s->nbpend);
- }
+ if (check->duration >= 0)
+ chunk_appendf(msg, ", check duration: %ldms", check->duration);
+
+ return msg->str;
}
/*
* Set check->status, update check->duration and fill check->result with
- * an adequate CHK_RES_* value.
+ * an adequate CHK_RES_* value. The new check->health is computed based
+ * on the result.
*
* Show information in logs about failed health check if server is UP
* or succeeded health checks if server is DOWN.
@@ -207,6 +203,8 @@
static void set_server_check_status(struct check *check, short status, const char *desc)
{
struct server *s = check->server;
+ short prev_status = check->status;
+ int report = 0;
if (status == HCHK_STATUS_START) {
check->result = CHK_RES_UNKNOWN; /* no result yet */
@@ -236,415 +234,152 @@
tv_zero(&check->start);
}
- /* Failure to connect to the agent as a secondary check should not
- * cause the server to be marked down. So only log status changes
- * for HCHK_STATUS_* statuses */
- if ((check->state & CHK_ST_AGENT) && check->status < HCHK_STATUS_L7TOUT)
+ /* no change is expected if no state change occurred */
+ if (check->result == CHK_RES_NEUTRAL)
return;
- if (s->proxy->options2 & PR_O2_LOGHCHKS &&
- (((check->health != 0) && (check->result == CHK_RES_FAILED)) ||
- (((check->health != check->rise + check->fall - 1) ||
- (!s->uweight && !(s->state & SRV_DRAIN)) ||
- (s->uweight && (s->state & SRV_DRAIN))) &&
- (check->result >= CHK_RES_PASSED)) ||
- ((s->state & SRV_GOINGDOWN) && (check->result != CHK_RES_CONDPASS)) ||
- (!(s->state & SRV_GOINGDOWN) && (check->result == CHK_RES_CONDPASS)))) {
-
- int health, rise, fall, state;
-
- chunk_reset(&trash);
-
- /* FIXME begin: calculate local version of the health/rise/fall/state */
- health = check->health;
- rise = check->rise;
- fall = check->fall;
- state = s->state;
-
- switch (check->result) {
- case CHK_RES_FAILED:
- if (health > rise) {
- health--; /* still good */
- } else {
- if (health == rise)
- state &= ~(SRV_RUNNING | SRV_GOINGDOWN);
-
- health = 0;
- }
- break;
+ report = 0;
- case CHK_RES_PASSED:
- case CHK_RES_CONDPASS:
- if (health < rise + fall - 1) {
- health++; /* was bad, stays for a while */
+ switch (check->result) {
+ case CHK_RES_FAILED:
+ /* Failure to connect to the agent as a secondary check should not
+ * cause the server to be marked down.
+ */
+ if ((!(check->state & CHK_ST_AGENT) ||
+ (check->status >= HCHK_STATUS_L7TOUT)) &&
+ (check->health >= check->rise)) {
+ s->counters.failed_checks++;
+ report = 1;
+ check->health--;
+ if (check->health < check->rise)
+ check->health = 0;
+ }
+ break;
- if (health == rise)
- state |= SRV_RUNNING;
+ case CHK_RES_PASSED:
+ case CHK_RES_CONDPASS: /* "condpass" cannot make the first step but it OK after a "passed" */
+ if ((check->health < check->rise + check->fall - 1) &&
+ (check->result == CHK_RES_PASSED || check->health > 0)) {
+ report = 1;
+ check->health++;
+
+ if (check->health >= check->rise)
+ check->health = check->rise + check->fall - 1; /* OK now */
+ }
- if (health >= rise)
- health = rise + fall - 1; /* OK now */
- }
+ /* clear consecutive_errors if observing is enabled */
+ if (s->onerror)
+ s->consecutive_errors = 0;
+ break;
- /* clear consecutive_errors if observing is enabled */
- if (s->onerror)
- s->consecutive_errors = 0;
- break;
- default:
- break;
- }
+ default:
+ break;
+ }
- chunk_appendf(&trash,
- "Health check for %sserver %s/%s %s%s",
- s->state & SRV_BACKUP ? "backup " : "",
+ if (s->proxy->options2 & PR_O2_LOGHCHKS &&
+ (status != prev_status || report)) {
+ chunk_printf(&trash,
+ "%s check for %sserver %s/%s %s%s",
+ (check->state & CHK_ST_AGENT) ? "Agent" : "Health",
+ s->flags & SRV_F_BACKUP ? "backup " : "",
s->proxy->id, s->id,
(check->result == CHK_RES_CONDPASS) ? "conditionally ":"",
- (check->result >= CHK_RES_PASSED) ? "succeeded":"failed");
+ (check->result >= CHK_RES_PASSED) ? "succeeded" : "failed");
- server_status_printf(&trash, s, check, -1);
+ srv_append_status(&trash, s, check_reason_string(check), -1, 0);
chunk_appendf(&trash, ", status: %d/%d %s",
- (state & SRV_RUNNING) ? (health - rise + 1) : (health),
- (state & SRV_RUNNING) ? (fall) : (rise),
- (state & SRV_RUNNING)?(s->eweight?"UP":"DRAIN"):"DOWN");
+ (check->health >= check->rise) ? check->health - check->rise + 1 : check->health,
+ (check->health >= check->rise) ? check->fall : check->rise,
+ (check->health >= check->rise) ? (s->uweight ? "UP" : "DRAIN") : "DOWN");
Warning("%s.\n", trash.str);
send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
}
}
-/* sends a log message when a backend goes down, and also sets last
- * change date.
+/* Marks the check <check>'s server down if the current check is already failed
+ * and the server is not down yet nor in maintenance.
*/
-static void set_backend_down(struct proxy *be)
+static void check_notify_failure(struct check *check)
{
- be->last_change = now.tv_sec;
- be->down_trans++;
-
- Alert("%s '%s' has no server available!\n", proxy_type_str(be), be->id);
- send_log(be, LOG_EMERG, "%s %s has no server available!\n", proxy_type_str(be), be->id);
-}
-
-/* Redistribute pending connections when a server goes down. The number of
- * connections redistributed is returned.
- */
-static int redistribute_pending(struct server *s)
-{
- struct pendconn *pc, *pc_bck, *pc_end;
- int xferred = 0;
+ struct server *s = check->server;
- FOREACH_ITEM_SAFE(pc, pc_bck, &s->pendconns, pc_end, struct pendconn *, list) {
- struct session *sess = pc->sess;
- if ((sess->be->options & (PR_O_REDISP|PR_O_PERSIST)) == PR_O_REDISP &&
- !(sess->flags & SN_FORCE_PRST)) {
- /* The REDISP option was specified. We will ignore
- * cookie and force to balance or use the dispatcher.
- */
+ /* The agent secondary check should only cause a server to be marked
+ * as down if check->status is HCHK_STATUS_L7STS, which indicates
+ * that the agent returned "fail", "stopped" or "down".
+ * The implication here is that failure to connect to the agent
+ * as a secondary check should not cause the server to be marked
+ * down. */
+ if ((check->state & CHK_ST_AGENT) && check->status != HCHK_STATUS_L7STS)
+ return;
- /* it's left to the dispatcher to choose a server */
- sess->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
+ if (check->health > 0)
+ return;
- pendconn_free(pc);
- task_wakeup(sess->task, TASK_WOKEN_RES);
- xferred++;
- }
- }
- return xferred;
+ /* We only report a reason for the check if we did not do so previously */
+ srv_set_stopped(s, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check_reason_string(check) : NULL);
}
-/* Check for pending connections at the backend, and assign some of them to
- * the server coming up. The server's weight is checked before being assigned
- * connections it may not be able to handle. The total number of transferred
- * connections is returned.
+/* Marks the check <check> as valid and tries to set its server up, provided
+ * it isn't in maintenance, it is not tracking a down server and other checks
+ * comply. The rule is simple : by default, a server is up, unless any of the
+ * following conditions is true :
+ * - health check failed (check->health < rise)
+ * - agent check failed (agent->health < rise)
+ * - the server tracks a down server (track && track->state == STOPPED)
+ * Note that if the server has a slowstart, it will switch to STARTING instead
+ * of RUNNING. Also, only the health checks support the nolb mode, so the
+ * agent's success may not take the server out of this mode.
*/
-static int check_for_pending(struct server *s)
+static void check_notify_success(struct check *check)
{
- int xferred;
-
- if (!s->eweight)
- return 0;
+ struct server *s = check->server;
- for (xferred = 0; !s->maxconn || xferred < srv_dynamic_maxconn(s); xferred++) {
- struct session *sess;
- struct pendconn *p;
+ if (s->admin & SRV_ADMF_MAINT)
+ return;
- p = pendconn_from_px(s->proxy);
- if (!p)
- break;
- p->sess->target = &s->obj_type;
- sess = p->sess;
- pendconn_free(p);
- task_wakeup(sess->task, TASK_WOKEN_RES);
- }
- return xferred;
-}
+ if (s->track && s->track->state == SRV_ST_STOPPED)
+ return;
-/* Shutdown all connections of a server. The caller must pass a termination
- * code in <why>, which must be one of SN_ERR_* indicating the reason for the
- * shutdown.
- */
-static void shutdown_sessions(struct server *srv, int why)
-{
- struct session *session, *session_bck;
+ if ((s->check.state & CHK_ST_ENABLED) && (s->check.health < s->check.rise))
+ return;
- list_for_each_entry_safe(session, session_bck, &srv->actconns, by_srv)
- if (session->srv_conn == srv)
- session_shutdown(session, why);
-}
+ if ((s->agent.state & CHK_ST_ENABLED) && (s->agent.health < s->agent.rise))
+ return;
-/* Shutdown all connections of all backup servers of a proxy. The caller must
- * pass a termination code in <why>, which must be one of SN_ERR_* indicating
- * the reason for the shutdown.
- */
-static void shutdown_backup_sessions(struct proxy *px, int why)
-{
- struct server *srv;
+ if ((check->state & CHK_ST_AGENT) && s->state == SRV_ST_STOPPING)
+ return;
- for (srv = px->srv; srv != NULL; srv = srv->next)
- if (srv->state & SRV_BACKUP)
- shutdown_sessions(srv, why);
+ srv_set_running(s, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check_reason_string(check) : NULL);
}
-/* Sets server <s> down, notifies by all available means, recounts the
- * remaining servers on the proxy and transfers queued sessions whenever
- * possible to other servers. It automatically recomputes the number of
- * servers, but not the map.
+/* Marks the check <check> as valid and tries to set its server into stopping mode
+ * if it was running or starting, and provided it isn't in maintenance and other
+ * checks comply. The conditions for the server to be marked in stopping mode are
+ * the same as for it to be turned up. Also, only the health checks support the
+ * nolb mode.
*/
-void set_server_down(struct check *check)
+static void check_notify_stopping(struct check *check)
{
struct server *s = check->server;
- struct server *srv;
- int xferred;
-
- if (s->state & SRV_MAINTAIN) {
- check->health = check->rise;
- }
-
- if ((s->state & SRV_RUNNING && check->health == check->rise) || s->track) {
- int srv_was_paused = s->state & SRV_GOINGDOWN;
- int prev_srv_count = s->proxy->srv_bck + s->proxy->srv_act;
-
- s->last_change = now.tv_sec;
- s->state &= ~(SRV_RUNNING | SRV_GOINGDOWN);
- if (s->proxy->lbprm.set_server_status_down)
- s->proxy->lbprm.set_server_status_down(s);
-
- if (s->onmarkeddown & HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS)
- shutdown_sessions(s, SN_ERR_DOWN);
-
- /* we might have sessions queued on this server and waiting for
- * a connection. Those which are redispatchable will be queued
- * to another server or to the proxy itself.
- */
- xferred = redistribute_pending(s);
-
- chunk_reset(&trash);
-
- if (s->state & SRV_MAINTAIN) {
- chunk_appendf(&trash,
- "%sServer %s/%s is DOWN for maintenance", s->state & SRV_BACKUP ? "Backup " : "",
- s->proxy->id, s->id);
- } else {
- chunk_appendf(&trash,
- "%sServer %s/%s is DOWN", s->state & SRV_BACKUP ? "Backup " : "",
- s->proxy->id, s->id);
-
- server_status_printf(&trash, s,
- ((!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check : 0),
- xferred);
- }
- Warning("%s.\n", trash.str);
-
- /* we don't send an alert if the server was previously paused */
- if (srv_was_paused)
- send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
- else
- send_log(s->proxy, LOG_ALERT, "%s.\n", trash.str);
-
- if (prev_srv_count && s->proxy->srv_bck == 0 && s->proxy->srv_act == 0)
- set_backend_down(s->proxy);
-
- s->counters.down_trans++;
-
- 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 */
-}
-
-void set_server_up(struct check *check) {
-
- struct server *s = check->server;
- struct server *srv;
- int xferred;
- unsigned int old_state = s->state;
-
- if (s->state & SRV_MAINTAIN) {
- check->health = check->rise;
- }
-
- if (s->track ||
- ((s->check.state & CHK_ST_ENABLED) && (s->check.health == s->check.rise) &&
- (s->agent.health >= s->agent.rise || !(s->agent.state & CHK_ST_ENABLED))) ||
- ((s->agent.state & CHK_ST_ENABLED) && (s->agent.health == s->agent.rise) &&
- (s->check.health >= s->check.rise || !(s->check.state & CHK_ST_ENABLED))) ||
- (!(s->agent.state & CHK_ST_ENABLED) && !(s->check.state & CHK_ST_ENABLED))) {
- if (s->proxy->srv_bck == 0 && s->proxy->srv_act == 0) {
- if (s->proxy->last_change < now.tv_sec) // ignore negative times
- s->proxy->down_time += now.tv_sec - s->proxy->last_change;
- s->proxy->last_change = now.tv_sec;
- }
-
- if (s->last_change < now.tv_sec) // ignore negative times
- s->down_time += now.tv_sec - s->last_change;
-
- s->last_change = now.tv_sec;
- s->state |= SRV_RUNNING;
- s->state &= ~SRV_MAINTAIN;
- s->check.state &= ~CHK_ST_PAUSED;
-
- if (s->slowstart > 0) {
- s->state |= SRV_WARMINGUP;
- task_schedule(s->warmup, tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20))));
- }
-
- server_recalc_eweight(s);
-
- /* If the server is set with "on-marked-up shutdown-backup-sessions",
- * and it's not a backup server and its effective weight is > 0,
- * then it can accept new connections, so we shut down all sessions
- * on all backup servers.
- */
- if ((s->onmarkedup & HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS) &&
- !(s->state & SRV_BACKUP) && s->eweight)
- shutdown_backup_sessions(s->proxy, SN_ERR_UP);
-
- /* check if we can handle some connections queued at the proxy. We
- * will take as many as we can handle.
- */
- xferred = check_for_pending(s);
-
- chunk_reset(&trash);
- if (old_state & SRV_MAINTAIN) {
- chunk_appendf(&trash,
- "%sServer %s/%s is UP (leaving maintenance)", s->state & SRV_BACKUP ? "Backup " : "",
- s->proxy->id, s->id);
- } else {
- chunk_appendf(&trash,
- "%sServer %s/%s is UP", s->state & SRV_BACKUP ? "Backup " : "",
- s->proxy->id, s->id);
-
- server_status_printf(&trash, s,
- ((!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check : NULL),
- xferred);
- }
-
- Warning("%s.\n", trash.str);
- send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
-
- 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)
- check->health = check->rise + check->fall - 1; /* OK now */
-
-}
-
-static void set_server_disabled(struct check *check) {
-
- struct server *s = check->server;
- struct server *srv;
- int xferred;
-
- s->state |= SRV_GOINGDOWN;
- if (s->proxy->lbprm.set_server_status_down)
- s->proxy->lbprm.set_server_status_down(s);
-
- /* we might have sessions queued on this server and waiting for
- * a connection. Those which are redispatchable will be queued
- * to another server or to the proxy itself.
- */
- xferred = redistribute_pending(s);
-
- chunk_reset(&trash);
-
- chunk_appendf(&trash,
- "Load-balancing on %sServer %s/%s is disabled",
- s->state & SRV_BACKUP ? "Backup " : "",
- s->proxy->id, s->id);
-
- server_status_printf(&trash, s,
- ((!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check : NULL),
- xferred);
-
- Warning("%s.\n", trash.str);
- send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
-
- if (!s->proxy->srv_bck && !s->proxy->srv_act)
- set_backend_down(s->proxy);
-
- for (srv = s->trackers; srv; srv = srv->tracknext)
- set_server_disabled(&srv->check);
-}
-
-static void set_server_enabled(struct check *check) {
-
- struct server *s = check->server;
- struct server *srv;
- int xferred;
-
- s->state &= ~SRV_GOINGDOWN;
- if (s->proxy->lbprm.set_server_status_up)
- s->proxy->lbprm.set_server_status_up(s);
-
- /* check if we can handle some connections queued at the proxy. We
- * will take as many as we can handle.
- */
- xferred = check_for_pending(s);
-
- chunk_reset(&trash);
-
- chunk_appendf(&trash,
- "Load-balancing on %sServer %s/%s is enabled again",
- s->state & SRV_BACKUP ? "Backup " : "",
- s->proxy->id, s->id);
-
- server_status_printf(&trash, s,
- ((!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check : NULL),
- xferred);
+ if (s->admin & SRV_ADMF_MAINT)
+ return;
- Warning("%s.\n", trash.str);
- send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
+ if (check->state & CHK_ST_AGENT)
+ return;
- for (srv = s->trackers; srv; srv = srv->tracknext)
- set_server_enabled(&srv->check);
-}
+ if (s->track && s->track->state == SRV_ST_STOPPED)
+ return;
-static void check_failed(struct check *check)
-{
- struct server *s = check->server;
+ if ((s->check.state & CHK_ST_ENABLED) && (s->check.health < s->check.rise))
+ return;
- /* The agent secondary check should only cause a server to be marked
- * as down if check->status is HCHK_STATUS_L7STS, which indicates
- * that the agent returned "fail", "stopped" or "down".
- * The implication here is that failure to connect to the agent
- * as a secondary check should not cause the server to be marked
- * down. */
- if ((check->state & CHK_ST_AGENT) && check->status != HCHK_STATUS_L7STS)
+ if ((s->agent.state & CHK_ST_ENABLED) && (s->agent.health < s->agent.rise))
return;
- if (check->health > check->rise) {
- check->health--; /* still good */
- s->counters.failed_checks++;
- }
- else
- set_server_down(check);
+ srv_set_stopping(s, (!s->track && !(s->proxy->options2 & PR_O2_LOGHCHKS)) ? check_reason_string(check) : NULL);
}
/* note: use health_adjust() only, which first checks that the observe mode is
@@ -703,16 +438,14 @@
case HANA_ONERR_FAILCHK:
/* simulate a failed health check */
set_server_check_status(&s->check, HCHK_STATUS_HANA, trash.str);
- check_failed(&s->check);
-
+ check_notify_failure(&s->check);
break;
case HANA_ONERR_MARKDWN:
/* mark server down */
s->check.health = s->check.rise;
set_server_check_status(&s->check, HCHK_STATUS_HANA, trash.str);
- set_server_down(&s->check);
-
+ check_notify_failure(&s->check);
break;
default:
@@ -748,13 +481,13 @@
if (!(s->check.state & CHK_ST_ENABLED))
sv_state = 6;
- else if (s->state & SRV_RUNNING) {
+ else if (s->state != SRV_ST_STOPPED) {
if (s->check.health == s->check.rise + s->check.fall - 1)
sv_state = 3; /* UP */
else
sv_state = 2; /* going down */
- if (s->state & SRV_GOINGDOWN)
+ if (s->state == SRV_ST_STOPPING)
sv_state += 2;
} else {
if (s->check.health)
@@ -765,8 +498,8 @@
hlen += snprintf(buffer + hlen, size - hlen,
srv_hlt_st[sv_state],
- (s->state & SRV_RUNNING) ? (s->check.health - s->check.rise + 1) : (s->check.health),
- (s->state & SRV_RUNNING) ? (s->check.fall) : (s->check.rise));
+ (s->state != SRV_ST_STOPPED) ? (s->check.health - s->check.rise + 1) : (s->check.health),
+ (s->state != SRV_ST_STOPPED) ? (s->check.fall) : (s->check.rise));
hlen += snprintf(buffer + hlen, size - hlen, "; name=%s/%s; node=%s; weight=%d/%d; scur=%d/%d; qcur=%d",
s->proxy->id, s->id,
@@ -776,7 +509,7 @@
s->cur_sess, s->proxy->beconn - s->proxy->nbpend,
s->nbpend);
- if ((s->state & SRV_WARMINGUP) &&
+ if ((s->state == SRV_ST_STARTING) &&
now.tv_sec < s->last_change + s->slowstart &&
now.tv_sec >= s->last_change) {
ratio = MAX(1, 100 * (now.tv_sec - s->last_change) / s->slowstart);
@@ -1087,7 +820,7 @@
desc = ltrim(check->bi->data + 12, ' ');
if ((s->proxy->options & PR_O_DISABLE404) &&
- (s->state & SRV_RUNNING) && (check->code == 404)) {
+ (s->state != SRV_ST_STOPPED) && (check->code == 404)) {
/* 404 may be accepted as "stopping" only if the server was up */
cut_crlf(desc);
set_server_check_status(check, HCHK_STATUS_L7OKCD, desc);
@@ -1147,13 +880,38 @@
break;
case PR_O2_LB_AGENT_CHK: {
- short status = HCHK_STATUS_L7RSP;
- const char *desc = "Unknown feedback string";
- const char *down_cmd = NULL;
- int disabled;
- char *p;
+ int status = HCHK_STATUS_CHECKED;
+ const char *hs = NULL; /* health status */
+ const char *as = NULL; /* admin status */
+ const char *ps = NULL; /* performance status */
+ const char *err = NULL; /* first error to report */
+ const char *wrn = NULL; /* first warning to report */
+ char *cmd, *p;
+
+ /* We're getting an agent check response. The agent could
+ * have been disabled in the mean time with a long check
+ * still pending. It is important that we ignore the whole
+ * response.
+ */
+ if (!(check->server->agent.state & CHK_ST_ENABLED))
+ break;
+
+ /* The agent supports strings made of a single line ended by the
+ * first CR ('\r') or LF ('\n'). This line is composed of words
+ * delimited by spaces (' '), tabs ('\t'), or commas (','). The
+ * line may optionally contained a description of a state change
+ * after a sharp ('#'), which is only considered if a health state
+ * is announced.
+ *
+ * Words may be composed of :
+ * - a numeric weight suffixed by the percent character ('%').
+ * - a health status among "up", "down", "stopped", and "fail".
+ * - an admin status among "ready", "drain", "maint".
+ *
+ * These words may appear in any order. If multiple words of the
+ * same category appear, the last one wins.
+ */
- /* get a complete line first */
p = check->bi->data;
while (*p && *p != '\n' && *p != '\r')
p++;
@@ -1166,58 +924,148 @@
set_server_check_status(check, check->status, "Ignoring incomplete line from agent");
break;
}
- *p = 0;
- /*
- * The agent may have been disabled after a check was
- * initialised. If so, ignore weight changes and drain
- * settings from the agent. Note that the setting is
- * always present in the state of the agent the server,
- * regardless of if the agent is being run as a primary or
- * secondary check. That is, regardless of if the check
- * parameter of this function is the agent or check field
- * of the server.
- */
- disabled = !(check->server->agent.state & CHK_ST_ENABLED);
+ *p = 0;
+ cmd = check->bi->data;
- if (strchr(check->bi->data, '%')) {
- if (disabled)
- break;
- desc = server_parse_weight_change_request(s, check->bi->data);
- if (!desc) {
- status = HCHK_STATUS_L7OKD;
- desc = check->bi->data;
+ while (*cmd) {
+ /* look for next word */
+ if (*cmd == ' ' || *cmd == '\t' || *cmd == ',') {
+ cmd++;
+ continue;
}
- } else if (!strcasecmp(check->bi->data, "drain")) {
- if (disabled)
+
+ if (*cmd == '#') {
+ /* this is the beginning of a health status description,
+ * skip the sharp and blanks.
+ */
+ cmd++;
+ while (*cmd == '\t' || *cmd == ' ')
+ cmd++;
break;
- desc = server_parse_weight_change_request(s, "0%");
- if (!desc) {
- desc = "drain";
- status = HCHK_STATUS_L7OKD;
}
- } else if (!strncasecmp(check->bi->data, "down", strlen("down"))) {
- down_cmd = "down";
- } else if (!strncasecmp(check->bi->data, "stopped", strlen("stopped"))) {
- down_cmd = "stopped";
- } else if (!strncasecmp(check->bi->data, "fail", strlen("fail"))) {
- down_cmd = "fail";
- }
- if (down_cmd) {
- const char *end = check->bi->data + strlen(down_cmd);
- /*
- * The command keyword must terminated the string or
- * be followed by a blank.
+ /* find the end of the word so that we have a null-terminated
+ * word between <cmd> and <p>.
*/
- if (end[0] == '\0' || end[0] == ' ' || end[0] == '\t') {
+ p = cmd + 1;
+ while (*p && *p != '\t' && *p != ' ' && *p != '\n' && *p != ',')
+ p++;
+ if (*p)
+ *p++ = 0;
+
+ /* first, health statuses */
+ if (strcasecmp(cmd, "up") == 0) {
+ check->health = check->rise + check->fall - 1;
+ status = HCHK_STATUS_L7OKD;
+ hs = cmd;
+ }
+ else if (strcasecmp(cmd, "down") == 0) {
+ check->health = 0;
status = HCHK_STATUS_L7STS;
- desc = check->bi->data;
+ hs = cmd;
+ }
+ else if (strcasecmp(cmd, "stopped") == 0) {
+ check->health = 0;
+ status = HCHK_STATUS_L7STS;
+ hs = cmd;
+ }
+ else if (strcasecmp(cmd, "fail") == 0) {
+ check->health = 0;
+ status = HCHK_STATUS_L7STS;
+ hs = cmd;
+ }
+ /* admin statuses */
+ else if (strcasecmp(cmd, "ready") == 0) {
+ as = cmd;
+ }
+ else if (strcasecmp(cmd, "drain") == 0) {
+ as = cmd;
}
+ else if (strcasecmp(cmd, "maint") == 0) {
+ as = cmd;
+ }
+ /* else try to parse a weight here and keep the last one */
+ else if (isdigit((unsigned char)*cmd) && strchr(cmd, '%') != NULL) {
+ ps = cmd;
+ }
+ else {
+ /* keep a copy of the first error */
+ if (!err)
+ err = cmd;
+ }
+ /* skip to next word */
+ cmd = p;
+ }
+ /* here, cmd points either to \0 or to the beginning of a
+ * description. Skip possible leading spaces.
+ */
+ while (*cmd == ' ' || *cmd == '\n')
+ cmd++;
+
+ /* First, update the admin status so that we avoid sending other
+ * possibly useless warnings and can also update the health if
+ * present after going back up.
+ */
+ if (as) {
+ if (strcasecmp(as, "drain") == 0)
+ srv_adm_set_drain(check->server);
+ else if (strcasecmp(as, "maint") == 0)
+ srv_adm_set_maint(check->server);
+ else
+ srv_adm_set_ready(check->server);
+ }
+
+ /* now change weights */
+ if (ps) {
+ const char *msg;
+
+ msg = server_parse_weight_change_request(s, ps);
+ if (!wrn || !*wrn)
+ wrn = msg;
}
- set_server_check_status(check, status, desc);
- set_server_drain_state(check->server);
+ /* and finally health status */
+ if (hs) {
+ /* We'll report some of the warnings and errors we have
+ * here. Down reports are critical, we leave them untouched.
+ * Lack of report, or report of 'UP' leaves the room for
+ * ERR first, then WARN.
+ */
+ const char *msg = cmd;
+ struct chunk *t;
+
+ if (!*msg || status == HCHK_STATUS_L7OKD) {
+ if (err && *err)
+ msg = err;
+ else if (wrn && *wrn)
+ msg = wrn;
+ }
+
+ t = get_trash_chunk();
+ chunk_printf(t, "via agent : %s%s%s%s",
+ hs, *msg ? " (" : "",
+ msg, *msg ? ")" : "");
+
+ set_server_check_status(check, status, t->str);
+ }
+ else if (err && *err) {
+ /* No status change but we'd like to report something odd.
+ * Just report the current state and copy the message.
+ */
+ chunk_printf(&trash, "agent reports an error : %s", err);
+ set_server_check_status(check, status/*check->status*/, trash.str);
+
+ }
+ else if (wrn && *wrn) {
+ /* No status change but we'd like to report something odd.
+ * Just report the current state and copy the message.
+ */
+ chunk_printf(&trash, "agent warns : %s", wrn);
+ set_server_check_status(check, status/*check->status*/, trash.str);
+ }
+ else
+ set_server_check_status(check, status, NULL);
break;
}
@@ -1484,18 +1332,20 @@
/* by default, plan on stopping the task */
t->expire = TICK_ETERNITY;
- if ((s->state & (SRV_RUNNING|SRV_WARMINGUP|SRV_MAINTAIN)) != (SRV_RUNNING|SRV_WARMINGUP))
+ if ((s->admin & SRV_ADMF_MAINT) ||
+ (s->state != SRV_ST_STARTING))
return t;
+ /* recalculate the weights and update the state */
server_recalc_eweight(s);
/* probably that we can refill this server with a bit more connections */
- check_for_pending(s);
+ pendconn_grab_from_px(s);
/* get back there in 1 second or 1/20th of the slowstart interval,
* whichever is greater, resulting in small 5% steps.
*/
- if (s->state & SRV_WARMINGUP)
+ if (s->state == SRV_ST_STARTING)
t->expire = tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20)));
return t;
}
@@ -1653,7 +1503,7 @@
/* here, we have seen a synchronous error, no fd was allocated */
check->state &= ~CHK_ST_INPROGRESS;
- check_failed(check);
+ check_notify_failure(check);
/* we allow up to min(inter, timeout.connect) for a connection
* to establish but only when timeout.check is set
@@ -1700,22 +1550,17 @@
conn_force_close(conn);
}
- if (check->result == CHK_RES_FAILED) /* a failure or timeout detected */
- check_failed(check);
- else { /* check was OK */
- /* we may have to add/remove this server from the LB group */
- if ((s->state & SRV_RUNNING) && (s->proxy->options & PR_O_DISABLE404)) {
- if ((s->state & SRV_GOINGDOWN) && (check->result != CHK_RES_CONDPASS))
- set_server_enabled(check);
- else if (!(s->state & SRV_GOINGDOWN) && (check->result == CHK_RES_CONDPASS))
- set_server_disabled(check);
- }
-
- if (!(s->state & SRV_MAINTAIN) &&
- check->health < check->rise + check->fall - 1) {
- check->health++; /* was bad, stays for a while */
- set_server_up(check);
- }
+ if (check->result == CHK_RES_FAILED) {
+ /* a failure or timeout detected */
+ check_notify_failure(check);
+ }
+ else if (check->result == CHK_RES_CONDPASS) {
+ /* check is OK but asks for stopping mode */
+ check_notify_stopping(check);
+ }
+ else if (check->result == CHK_RES_PASSED) {
+ /* a success was detected */
+ check_notify_success(check);
}
check->state &= ~CHK_ST_INPROGRESS;
@@ -1975,7 +1820,6 @@
static void tcpcheck_main(struct connection *conn)
{
char *contentptr;
- unsigned int contentlen;
struct list *head = NULL;
struct tcpcheck_rule *cur = NULL;
int done = 0, ret = 0;
@@ -2253,10 +2097,9 @@
}
contentptr = check->bi->data;
- contentlen = check->bi->i;
/* Check that response body is not empty... */
- if (*contentptr == '\0') {
+ if (!check->bi->i) {
if (!done)
continue;
@@ -2273,7 +2116,7 @@
tcpcheck_expect:
if (cur->string != NULL)
- ret = my_memmem(contentptr, contentlen, cur->string, cur->string_len) != NULL;
+ ret = my_memmem(contentptr, check->bi->i, cur->string, cur->string_len) != NULL;
else if (cur->expect_regex != NULL)
ret = regexec(cur->expect_regex, contentptr, MAX_MATCH, pmatch, 0) == 0;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/dumpstats.c
^
|
@@ -86,6 +86,39 @@
STAT_CLI_O_POOLS, /* dump memory pools */
};
+/* Actions available for the stats admin forms */
+enum {
+ ST_ADM_ACTION_NONE = 0,
+
+ /* enable/disable health checks */
+ ST_ADM_ACTION_DHLTH,
+ ST_ADM_ACTION_EHLTH,
+
+ /* force health check status */
+ ST_ADM_ACTION_HRUNN,
+ ST_ADM_ACTION_HNOLB,
+ ST_ADM_ACTION_HDOWN,
+
+ /* enable/disable agent checks */
+ ST_ADM_ACTION_DAGENT,
+ ST_ADM_ACTION_EAGENT,
+
+ /* force agent check status */
+ ST_ADM_ACTION_ARUNN,
+ ST_ADM_ACTION_ADOWN,
+
+ /* set admin state */
+ ST_ADM_ACTION_READY,
+ ST_ADM_ACTION_DRAIN,
+ ST_ADM_ACTION_MAINT,
+ ST_ADM_ACTION_SHUTDOWN,
+ /* these are the ancient actions, still available for compatibility */
+ ST_ADM_ACTION_DISABLE,
+ ST_ADM_ACTION_ENABLE,
+ ST_ADM_ACTION_STOP,
+ ST_ADM_ACTION_START,
+};
+
static int stats_dump_info_to_buffer(struct stream_interface *si);
static int stats_dump_pools_to_buffer(struct stream_interface *si);
static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct session *sess);
@@ -143,6 +176,7 @@
" show table [id]: report table usage stats or dump this table's contents\n"
" get weight : report a server's current weight\n"
" set weight : change a server's weight\n"
+ " set server : change a server's state or weight\n"
" set table [id] : update or create a table entry's data\n"
" set timeout : change a timeout setting\n"
" set maxconn : change a maxconn setting\n"
@@ -1355,18 +1389,85 @@
return 1;
warning = server_parse_weight_change_request(sv, args[3]);
- /*
- * The user-weight may now be zero and thus
- * the server considered to be draining.
- * Update the server's drain state as necessary.
- */
- set_server_drain_state(sv);
if (warning) {
appctx->ctx.cli.msg = warning;
appctx->st0 = STAT_CLI_PRINT;
}
return 1;
}
+ else if (strcmp(args[1], "server") == 0) {
+ struct server *sv;
+ const char *warning;
+
+ sv = expect_server_admin(s, si, args[2]);
+ if (!sv)
+ return 1;
+
+ if (strcmp(args[3], "weight") == 0) {
+ warning = server_parse_weight_change_request(sv, args[4]);
+ if (warning) {
+ appctx->ctx.cli.msg = warning;
+ appctx->st0 = STAT_CLI_PRINT;
+ }
+ }
+ else if (strcmp(args[3], "state") == 0) {
+ if (strcmp(args[4], "ready") == 0)
+ srv_adm_set_ready(sv);
+ else if (strcmp(args[4], "drain") == 0)
+ srv_adm_set_drain(sv);
+ else if (strcmp(args[4], "maint") == 0)
+ srv_adm_set_maint(sv);
+ else {
+ appctx->ctx.cli.msg = "'set server <srv> state' expects 'ready', 'drain' and 'maint'.\n";
+ appctx->st0 = STAT_CLI_PRINT;
+ }
+ }
+ else if (strcmp(args[3], "health") == 0) {
+ if (sv->track) {
+ appctx->ctx.cli.msg = "cannot change health on a tracking server.\n";
+ appctx->st0 = STAT_CLI_PRINT;
+ }
+ else if (strcmp(args[4], "up") == 0) {
+ sv->check.health = sv->check.rise + sv->check.fall - 1;
+ srv_set_running(sv, "changed from CLI");
+ }
+ else if (strcmp(args[4], "stopping") == 0) {
+ sv->check.health = sv->check.rise + sv->check.fall - 1;
+ srv_set_stopping(sv, "changed from CLI");
+ }
+ else if (strcmp(args[4], "down") == 0) {
+ sv->check.health = 0;
+ srv_set_stopped(sv, "changed from CLI");
+ }
+ else {
+ appctx->ctx.cli.msg = "'set server <srv> health' expects 'up', 'stopping', or 'down'.\n";
+ appctx->st0 = STAT_CLI_PRINT;
+ }
+ }
+ else if (strcmp(args[3], "agent") == 0) {
+ if (!(sv->agent.state & CHK_ST_ENABLED)) {
+ appctx->ctx.cli.msg = "agent checks are not enabled on this server.\n";
+ appctx->st0 = STAT_CLI_PRINT;
+ }
+ else if (strcmp(args[4], "up") == 0) {
+ sv->agent.health = sv->agent.rise + sv->agent.fall - 1;
+ srv_set_running(sv, "changed from CLI");
+ }
+ else if (strcmp(args[4], "down") == 0) {
+ sv->agent.health = 0;
+ srv_set_stopped(sv, "changed from CLI");
+ }
+ else {
+ appctx->ctx.cli.msg = "'set server <srv> agent' expects 'up' or 'down'.\n";
+ appctx->st0 = STAT_CLI_PRINT;
+ }
+ }
+ else {
+ appctx->ctx.cli.msg = "'set server <srv>' only supports 'agent', 'health', 'state' and 'weight'.\n";
+ appctx->st0 = STAT_CLI_PRINT;
+ }
+ return 1;
+ }
else if (strcmp(args[1], "timeout") == 0) {
if (strcmp(args[2], "cli") == 0) {
unsigned timeout;
@@ -1709,33 +1810,30 @@
sv->agent.state |= CHK_ST_ENABLED;
return 1;
}
- if (strcmp(args[1], "server") == 0) {
+ else if (strcmp(args[1], "health") == 0) {
struct server *sv;
sv = expect_server_admin(s, si, args[2]);
if (!sv)
return 1;
- if (sv->state & SRV_MAINTAIN) {
- /* The server is really in maintenance, we can change the server state */
- if (sv->track) {
- /* If this server tracks the status of another one,
- * we must restore the good status.
- */
- if (sv->track->state & SRV_RUNNING) {
- set_server_up(&sv->check);
- sv->check.health = sv->check.rise; /* up, but will fall down at first failure */
- } else {
- sv->state &= ~SRV_MAINTAIN;
- sv->check.state &= ~CHK_ST_PAUSED;
- set_server_down(&sv->check);
- }
- } else {
- set_server_up(&sv->check);
- sv->check.health = sv->check.rise; /* up, but will fall down at first failure */
- }
+ if (!(sv->check.state & CHK_ST_CONFIGURED)) {
+ appctx->ctx.cli.msg = "Health checks are not configured on this server, cannot enable.\n";
+ appctx->st0 = STAT_CLI_PRINT;
+ return 1;
}
+ sv->check.state |= CHK_ST_ENABLED;
+ return 1;
+ }
+ else if (strcmp(args[1], "server") == 0) {
+ struct server *sv;
+
+ sv = expect_server_admin(s, si, args[2]);
+ if (!sv)
+ return 1;
+
+ srv_adm_set_ready(sv);
return 1;
}
else if (strcmp(args[1], "frontend") == 0) {
@@ -1765,7 +1863,7 @@
return 1;
}
else { /* unknown "enable" parameter */
- appctx->ctx.cli.msg = "'enable' only supports 'frontend' and 'server'.\n";
+ appctx->ctx.cli.msg = "'enable' only supports 'agent', 'frontend', 'health', and 'server'.\n";
appctx->st0 = STAT_CLI_PRINT;
return 1;
}
@@ -1781,20 +1879,24 @@
sv->agent.state &= ~CHK_ST_ENABLED;
return 1;
}
- else if (strcmp(args[1], "server") == 0) {
+ else if (strcmp(args[1], "health") == 0) {
struct server *sv;
sv = expect_server_admin(s, si, args[2]);
if (!sv)
return 1;
- if (! (sv->state & SRV_MAINTAIN)) {
- /* Not already in maintenance, we can change the server state */
- sv->state |= SRV_MAINTAIN;
- sv->check.state |= CHK_ST_PAUSED;
- set_server_down(&sv->check);
- }
+ sv->check.state &= ~CHK_ST_ENABLED;
+ return 1;
+ }
+ else if (strcmp(args[1], "server") == 0) {
+ struct server *sv;
+ sv = expect_server_admin(s, si, args[2]);
+ if (!sv)
+ return 1;
+
+ srv_adm_set_maint(sv);
return 1;
}
else if (strcmp(args[1], "frontend") == 0) {
@@ -1824,7 +1926,7 @@
return 1;
}
else { /* unknown "disable" parameter */
- appctx->ctx.cli.msg = "'disable' only supports 'frontend' and 'server'.\n";
+ appctx->ctx.cli.msg = "'disable' only supports 'agent', 'frontend', 'health', and 'server'.\n";
appctx->st0 = STAT_CLI_PRINT;
return 1;
}
@@ -2318,6 +2420,17 @@
{
unsigned int up = (now.tv_sec - start_date.tv_sec);
+#ifdef USE_OPENSSL
+ int ssl_sess_rate = read_freq_ctr(&global.ssl_per_sec);
+ int ssl_key_rate = read_freq_ctr(&global.ssl_fe_keys_per_sec);
+ int ssl_reuse = 0;
+
+ if (ssl_key_rate < ssl_sess_rate) {
+ /* count the ssl reuse ratio and avoid overflows in both directions */
+ ssl_reuse = 100 - (100 * ssl_key_rate + (ssl_sess_rate - 1) / 2) / ssl_sess_rate;
+ }
+#endif
+
chunk_printf(&trash,
"Name: " PRODUCT_NAME "\n"
"Version: " HAPROXY_VERSION "\n"
@@ -2353,6 +2466,13 @@
"SslRate: %d\n"
"SslRateLimit: %d\n"
"MaxSslRate: %d\n"
+ "SslFrontendKeyRate: %d\n"
+ "SslFrontendMaxKeyRate: %d\n"
+ "SslFrontendSessionReuse_pct: %d\n"
+ "SslBackendKeyRate: %d\n"
+ "SslBackendMaxKeyRate: %d\n"
+ "SslCacheLookups: %u\n"
+ "SslCacheMisses: %u\n"
#endif
"CompressBpsIn: %u\n"
"CompressBpsOut: %u\n"
@@ -2383,7 +2503,11 @@
read_freq_ctr(&global.conn_per_sec), global.cps_lim, global.cps_max,
read_freq_ctr(&global.sess_per_sec), global.sps_lim, global.sps_max,
#ifdef USE_OPENSSL
- read_freq_ctr(&global.ssl_per_sec), global.ssl_lim, global.ssl_max,
+ ssl_sess_rate, global.ssl_lim, global.ssl_max,
+ ssl_key_rate, global.ssl_fe_keys_max,
+ ssl_reuse,
+ read_freq_ctr(&global.ssl_be_keys_per_sec), global.ssl_be_keys_max,
+ global.shctx_lookups, global.shctx_misses,
#endif
read_freq_ctr(&global.comp_bps_in), read_freq_ctr(&global.comp_bps_out),
global.comp_rate_lim,
@@ -2762,20 +2886,29 @@
* from stream interface <si>, stats flags <flags>, and server state <state>.
* The caller is responsible for clearing the trash if needed. Returns non-zero
* if it emits anything, zero otherwise. The <state> parameter can take the
- * following values : 0=DOWN, 1=going up, 2=going down, 3=UP, 4,5=NOLB,
- * 6,7=DRAIN, 8=unchecked.
+ * following values : 0=DOWN, 1=DOWN(agent) 2=going up, 3=going down, 4=UP, 5,6=NOLB,
+ * 7,8=DRAIN, 9=unchecked.
*/
static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, int flags, struct server *sv, int state)
{
struct appctx *appctx = __objt_appctx(si->end);
- struct server *ref = sv->track ? sv->track : sv;
+ struct server *via, *ref;
char str[INET6_ADDRSTRLEN];
struct chunk src;
int i;
+ /* we have "via" which is the tracked server as described in the configuration,
+ * and "ref" which is the checked server and the end of the chain.
+ */
+ via = sv->track ? sv->track : sv;
+ ref = via;
+ while (ref->track)
+ ref = ref->track;
+
if (appctx->ctx.stats.flags & STAT_FMT_HTML) {
- static char *srv_hlt_st[9] = {
+ static char *srv_hlt_st[10] = {
"DOWN",
+ "DOWN (agent)",
"DN %d/%d ↑",
"UP %d/%d ↓",
"UP",
@@ -2786,12 +2919,12 @@
"<i>no check</i>"
};
- if ((sv->state & SRV_MAINTAIN) || (ref->state & SRV_MAINTAIN))
+ if (sv->admin & SRV_ADMF_MAINT)
chunk_appendf(&trash, "<tr class=\"maintain\">");
else
chunk_appendf(&trash,
"<tr class=\"%s%d\">",
- (sv->state & SRV_BACKUP) ? "backup" : "active", state);
+ (sv->flags & SRV_F_BACKUP) ? "backup" : "active", state);
if ((px->cap & PR_CAP_BE) && px->srv && (appctx->ctx.stats.flags & STAT_ADMIN))
chunk_appendf(&trash,
@@ -2917,23 +3050,45 @@
/* status, lest check */
chunk_appendf(&trash, "<td class=ac>");
- if (sv->state & SRV_MAINTAIN) {
+ if (sv->admin & SRV_ADMF_MAINT) {
chunk_appendf(&trash, "%s ", human_time(now.tv_sec - sv->last_change, 1));
chunk_appendf(&trash, "MAINT");
}
- else if (ref != sv && ref->state & SRV_MAINTAIN) {
+ else if ((ref->agent.state & CHK_ST_ENABLED) && (ref->state == SRV_ST_STOPPED)) {
chunk_appendf(&trash, "%s ", human_time(now.tv_sec - ref->last_change, 1));
- chunk_appendf(&trash, "MAINT(via)");
+ chunk_appendf(&trash, srv_hlt_st[1]); /* DOWN (agent) */
}
else if (ref->check.state & CHK_ST_ENABLED) {
chunk_appendf(&trash, "%s ", human_time(now.tv_sec - ref->last_change, 1));
chunk_appendf(&trash,
srv_hlt_st[state],
- (ref->state & SRV_RUNNING) ? (ref->check.health - ref->check.rise + 1) : (ref->check.health),
- (ref->state & SRV_RUNNING) ? (ref->check.fall) : (ref->check.rise));
+ (ref->state != SRV_ST_STOPPED) ? (ref->check.health - ref->check.rise + 1) : (ref->check.health),
+ (ref->state != SRV_ST_STOPPED) ? (ref->check.fall) : (ref->check.rise));
}
- if (sv->check.state & CHK_ST_ENABLED) {
+ if ((sv->state == SRV_ST_STOPPED) &&
+ ((sv->agent.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED) && !(sv->agent.health)) {
+ chunk_appendf(&trash,
+ "</td><td class=ac><u> %s%s",
+ (sv->agent.state & CHK_ST_INPROGRESS) ? "* " : "",
+ get_check_status_info(sv->agent.status));
+
+ if (sv->agent.status >= HCHK_STATUS_L57DATA)
+ chunk_appendf(&trash, "/%d", sv->agent.code);
+
+ if (sv->agent.status >= HCHK_STATUS_CHECKED && sv->agent.duration >= 0)
+ chunk_appendf(&trash, " in %lums", sv->agent.duration);
+
+ chunk_appendf(&trash, "<div class=tips>%s",
+ get_check_status_description(sv->agent.status));
+ if (*sv->agent.desc) {
+ chunk_appendf(&trash, ": ");
+ chunk_initlen(&src, sv->agent.desc, 0, strlen(sv->agent.desc));
+ chunk_htmlencode(&trash, &src);
+ }
+ chunk_appendf(&trash, "</div></u>");
+ }
+ else if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED) {
chunk_appendf(&trash,
"</td><td class=ac><u> %s%s",
(sv->check.state & CHK_ST_INPROGRESS) ? "* " : "",
@@ -2964,8 +3119,8 @@
"<td class=ac>%s</td><td class=ac>%s</td>"
"",
(sv->eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv,
- (sv->state & SRV_BACKUP) ? "-" : "Y",
- (sv->state & SRV_BACKUP) ? "Y" : "-");
+ (sv->flags & SRV_F_BACKUP) ? "-" : "Y",
+ (sv->flags & SRV_F_BACKUP) ? "Y" : "-");
/* check failures: unique, fatal, down time */
if (sv->check.state & CHK_ST_ENABLED) {
@@ -2981,28 +3136,25 @@
ref->observe ? "/Health Analyses" : "",
ref->counters.down_trans, human_time(srv_downtime(sv), 1));
}
- else if (sv != ref) {
- if (sv->state & SRV_MAINTAIN)
- chunk_appendf(&trash,
- "<td class=ac colspan=3><a class=lfsb href=\"#%s/%s\"><a></td>",
- ref->proxy->id, ref->id);
- else
- chunk_appendf(&trash,
- "<td class=ac colspan=3><a class=lfsb href=\"#%s/%s\">via %s/%s<a></td>",
- ref->proxy->id, ref->id, ref->proxy->id, ref->id);
+ else if (!(sv->admin & SRV_ADMF_FMAINT) && sv != ref) {
+ /* tracking a server */
+ chunk_appendf(&trash,
+ "<td class=ac colspan=3><a class=lfsb href=\"#%s/%s\">via %s/%s</a></td>",
+ via->proxy->id, via->id, via->proxy->id, via->id);
}
else
chunk_appendf(&trash, "<td colspan=3></td>");
/* throttle */
- if (sv->state & SRV_WARMINGUP)
+ if (sv->state == SRV_ST_STARTING && !server_is_draining(sv))
chunk_appendf(&trash, "<td class=ac>%d %%</td></tr>\n", server_throttle_rate(sv));
else
chunk_appendf(&trash, "<td class=ac>-</td></tr>\n");
}
else { /* CSV mode */
- static char *srv_hlt_st[9] = {
+ static char *srv_hlt_st[10] = {
"DOWN,",
+ "DOWN (agent),",
"DOWN %d/%d,",
"UP %d/%d,",
"UP,",
@@ -3038,23 +3190,23 @@
sv->counters.retries, sv->counters.redispatches);
/* status */
- if (sv->state & SRV_MAINTAIN)
+ if (sv->admin & SRV_ADMF_IMAINT)
+ chunk_appendf(&trash, "MAINT (via %s/%s),", via->proxy->id, via->id);
+ else if (sv->admin & SRV_ADMF_MAINT)
chunk_appendf(&trash, "MAINT,");
- else if (ref != sv && ref->state & SRV_MAINTAIN)
- chunk_appendf(&trash, "MAINT(via),");
else
chunk_appendf(&trash,
srv_hlt_st[state],
- (ref->state & SRV_RUNNING) ? (ref->check.health - ref->check.rise + 1) : (ref->check.health),
- (ref->state & SRV_RUNNING) ? (ref->check.fall) : (ref->check.rise));
+ (ref->state != SRV_ST_STOPPED) ? (ref->check.health - ref->check.rise + 1) : (ref->check.health),
+ (ref->state != SRV_ST_STOPPED) ? (ref->check.fall) : (ref->check.rise));
chunk_appendf(&trash,
/* weight, active, backup */
"%d,%d,%d,"
"",
(sv->eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv,
- (sv->state & SRV_BACKUP) ? 0 : 1,
- (sv->state & SRV_BACKUP) ? 1 : 0);
+ (sv->flags & SRV_F_BACKUP) ? 0 : 1,
+ (sv->flags & SRV_F_BACKUP) ? 1 : 0);
/* check failures: unique, fatal; last change, total downtime */
if (sv->check.state & CHK_ST_ENABLED)
@@ -3073,7 +3225,7 @@
relative_pid, px->uuid, sv->puid);
/* throttle */
- if (sv->state & SRV_WARMINGUP)
+ if (sv->state == SRV_ST_STARTING && !server_is_draining(sv))
chunk_appendf(&trash, "%d", server_throttle_rate(sv));
/* sessions: lbtot */
@@ -3477,10 +3629,18 @@
"Choose the action to perform on the checked servers : "
"<select name=action>"
"<option value=\"\"></option>"
- "<option value=\"disable\">Disable</option>"
- "<option value=\"enable\">Enable</option>"
- "<option value=\"stop\">Soft Stop</option>"
- "<option value=\"start\">Soft Start</option>"
+ "<option value=\"ready\">Set state to READY</option>"
+ "<option value=\"drain\">Set state to DRAIN</option>"
+ "<option value=\"maint\">set state to MAINT</option>"
+ "<option value=\"dhlth\">Health: disable checks</option>"
+ "<option value=\"ehlth\">Health: enable checks</option>"
+ "<option value=\"hrunn\">Health: force UP</option>"
+ "<option value=\"hnolb\">Health: force NOLB</option>"
+ "<option value=\"hdown\">Health: force DOWN</option>"
+ "<option value=\"dagent\">Agent: disable checks</option>"
+ "<option value=\"eagent\">Agent: enable checks</option>"
+ "<option value=\"arunn\">Agent: force UP</option>"
+ "<option value=\"adown\">Agent: force DOWN</option>"
"<option value=\"shutdown\">Kill Sessions</option>"
"</select>"
"<input type=\"hidden\" name=\"b\" value=\"#%d\">"
@@ -3604,7 +3764,7 @@
case STAT_PX_ST_SV:
/* stats.sv has been initialized above */
for (; appctx->ctx.stats.sv != NULL; appctx->ctx.stats.sv = sv->next) {
- int sv_state; /* 0=DOWN, 1=going up, 2=going down, 3=UP, 4,5=NOLB, 6=unchecked */
+ int sv_state;
if (buffer_almost_full(rep->buf)) {
rep->flags |= CF_WAKE_WRITE;
@@ -3621,32 +3781,50 @@
continue;
}
- if (sv->track)
- svs = sv->track;
- else
- svs = sv;
+ svs = sv;
+ while (svs->track)
+ svs = svs->track;
+
+ if (sv->state == SRV_ST_RUNNING || sv->state == SRV_ST_STARTING) {
+ /* server is UP. The possibilities are :
+ * - UP, draining, going down => state = 7
+ * - UP, going down => state = 3
+ * - UP, draining => state = 8
+ * - UP, checked => state = 4
+ * - UP, not checked nor tracked => state = 9
+ */
- /* FIXME: produce some small strings for "UP/DOWN x/y &#xxxx;" */
- if (!(svs->check.state & CHK_ST_ENABLED))
- sv_state = 8;
- else if (svs->state & SRV_RUNNING) {
- if (svs->check.health == svs->check.rise + svs->check.fall - 1)
- sv_state = 3; /* UP */
+ if ((svs->check.state & CHK_ST_ENABLED) &&
+ (svs->check.health < svs->check.rise + svs->check.fall - 1))
+ sv_state = 3;
else
- sv_state = 2; /* going down */
+ sv_state = 4;
- if (svs->state & SRV_DRAIN)
+ if (server_is_draining(sv))
sv_state += 4;
- else if (svs->state & SRV_GOINGDOWN)
- sv_state += 2;
+
+ if (sv_state == 4 && !(svs->check.state & CHK_ST_ENABLED))
+ sv_state = 9; /* unchecked UP */
}
- else
- if (svs->check.health)
- sv_state = 1; /* going up */
+ else if (sv->state == SRV_ST_STOPPING) {
+ if ((!(sv->check.state & CHK_ST_ENABLED) && !sv->track) ||
+ (svs->check.health == svs->check.rise + svs->check.fall - 1))
+ sv_state = 6; /* NOLB */
else
+ sv_state = 5; /* NOLB going down */
+ }
+ else { /* stopped */
+ if ((svs->agent.state & CHK_ST_ENABLED) && !svs->agent.health)
+ sv_state = 1; /* DOWN (agent) */
+ else if ((svs->check.state & CHK_ST_ENABLED) && !svs->check.health)
sv_state = 0; /* DOWN */
+ else if ((svs->agent.state & CHK_ST_ENABLED) || (svs->check.state & CHK_ST_ENABLED))
+ sv_state = 2; /* going up */
+ else
+ sv_state = 0; /* DOWN, unchecked */
+ }
- if (((sv_state == 0) || (sv->state & SRV_MAINTAIN)) && (appctx->ctx.stats.flags & STAT_HIDE_DOWN)) {
+ if (((sv_state <= 1) || (sv->admin & SRV_ADMF_MAINT)) && (appctx->ctx.stats.flags & STAT_HIDE_DOWN)) {
/* do not report servers which are DOWN */
appctx->ctx.stats.sv = sv->next;
continue;
@@ -3746,23 +3924,25 @@
".socket {background: #d0d0d0;}\n"
".backend {background: #e8e8d0;}\n"
".active0 {background: #ff9090;}\n"
- ".active1 {background: #ffd020;}\n"
- ".active2 {background: #ffffa0;}\n"
- ".active3 {background: #c0ffc0;}\n"
- ".active4 {background: #ffffa0;}\n" /* NOLB state shows same as going down */
- ".active5 {background: #20a0ff;}\n" /* NOLB state shows different to be detected */
- ".active6 {background: #ffffa0;}\n" /* DRAIN going down = same as going down */
- ".active7 {background: #20a0FF;}\n" /* DRAIN must be detected (weight=0) */
- ".active8 {background: #e0e0e0;}\n"
+ ".active1 {background: #ff9090;}\n"
+ ".active2 {background: #ffd020;}\n"
+ ".active3 {background: #ffffa0;}\n"
+ ".active4 {background: #c0ffc0;}\n"
+ ".active5 {background: #ffffa0;}\n" /* NOLB state shows same as going down */
+ ".active6 {background: #20a0ff;}\n" /* NOLB state shows different to be detected */
+ ".active7 {background: #ffffa0;}\n" /* DRAIN going down = same as going down */
+ ".active8 {background: #20a0FF;}\n" /* DRAIN must be detected (weight=0) */
+ ".active9 {background: #e0e0e0;}\n"
".backup0 {background: #ff9090;}\n"
- ".backup1 {background: #ff80ff;}\n"
- ".backup2 {background: #c060ff;}\n"
- ".backup3 {background: #b0d0ff;}\n"
- ".backup4 {background: #c060ff;}\n" /* NOLB state shows same as going down */
- ".backup5 {background: #90b0e0;}\n" /* NOLB state shows same as going down */
- ".backup6 {background: #c060ff;}\n"
- ".backup7 {background: #cc9900;}\n"
- ".backup8 {background: #e0e0e0;}\n"
+ ".backup1 {background: #ff9090;}\n"
+ ".backup2 {background: #ff80ff;}\n"
+ ".backup3 {background: #c060ff;}\n"
+ ".backup4 {background: #b0d0ff;}\n"
+ ".backup5 {background: #c060ff;}\n" /* NOLB state shows same as going down */
+ ".backup6 {background: #90b0e0;}\n" /* NOLB state shows same as going down */
+ ".backup7 {background: #c060ff;}\n"
+ ".backup8 {background: #cc9900;}\n"
+ ".backup9 {background: #e0e0e0;}\n"
".maintain {background: #c07820;}\n"
".rls {letter-spacing: 0.2em; margin-right: 1px;}\n" /* right letter spacing (used for grouping digits) */
"\n"
@@ -3838,22 +4018,21 @@
"Running tasks: %d/%d; idle = %d %%<br>\n"
"</td><td align=\"center\" nowrap>\n"
"<table class=\"lgd\"><tr>\n"
- "<td class=\"active3\"> </td><td class=\"noborder\">active UP </td>"
- "<td class=\"backup3\"> </td><td class=\"noborder\">backup UP </td>"
+ "<td class=\"active4\"> </td><td class=\"noborder\">active UP </td>"
+ "<td class=\"backup4\"> </td><td class=\"noborder\">backup UP </td>"
"</tr><tr>\n"
- "<td class=\"active2\"></td><td class=\"noborder\">active UP, going down </td>"
- "<td class=\"backup2\"></td><td class=\"noborder\">backup UP, going down </td>"
+ "<td class=\"active3\"></td><td class=\"noborder\">active UP, going down </td>"
+ "<td class=\"backup3\"></td><td class=\"noborder\">backup UP, going down </td>"
"</tr><tr>\n"
- "<td class=\"active1\"></td><td class=\"noborder\">active DOWN, going up </td>"
- "<td class=\"backup1\"></td><td class=\"noborder\">backup DOWN, going up </td>"
+ "<td class=\"active2\"></td><td class=\"noborder\">active DOWN, going up </td>"
+ "<td class=\"backup2\"></td><td class=\"noborder\">backup DOWN, going up </td>"
"</tr><tr>\n"
"<td class=\"active0\"></td><td class=\"noborder\">active or backup DOWN </td>"
- "</tr><tr>\n"
- "<td class=\"active8\"></td><td class=\"noborder\">not checked </td>"
+ "<td class=\"active9\"></td><td class=\"noborder\">not checked </td>"
"</tr><tr>\n"
"<td class=\"maintain\"></td><td class=\"noborder\" colspan=\"3\">active or backup DOWN for maintenance (MAINT) </td>"
"</tr><tr>\n"
- "<td class=\"active7\"></td><td class=\"noborder\" colspan=\"3\">active or backup SOFT STOPPED for maintenance </td>"
+ "<td class=\"active8\"></td><td class=\"noborder\" colspan=\"3\">active or backup SOFT STOPPED for maintenance </td>"
"</tr></table>\n"
"Note: \"NOLB\"/\"DRAIN\" = UP with load-balancing disabled."
"</td>"
@@ -3958,7 +4137,7 @@
switch (appctx->ctx.stats.st_code) {
case STAT_STATUS_DONE:
chunk_appendf(&trash,
- "<p><div class=active3>"
+ "<p><div class=active4>"
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
"Action processed successfully."
"</div>\n", uri->uri_prefix,
@@ -3968,7 +4147,7 @@
break;
case STAT_STATUS_NONE:
chunk_appendf(&trash,
- "<p><div class=active2>"
+ "<p><div class=active3>"
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
"Nothing has changed."
"</div>\n", uri->uri_prefix,
@@ -3978,7 +4157,7 @@
break;
case STAT_STATUS_PART:
chunk_appendf(&trash,
- "<p><div class=active2>"
+ "<p><div class=active3>"
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
"Action partially processed.<br>"
"Some server names are probably unknown or ambiguous (duplicated names in the backend)."
@@ -4025,7 +4204,7 @@
break;
default:
chunk_appendf(&trash,
- "<p><div class=active8>"
+ "<p><div class=active9>"
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
"Unexpected result."
"</div>\n", uri->uri_prefix,
@@ -4223,7 +4402,47 @@
}
}
else if (!action && (strcmp(key, "action") == 0)) {
- if (strcmp(value, "disable") == 0) {
+ if (strcmp(value, "ready") == 0) {
+ action = ST_ADM_ACTION_READY;
+ }
+ else if (strcmp(value, "drain") == 0) {
+ action = ST_ADM_ACTION_DRAIN;
+ }
+ else if (strcmp(value, "maint") == 0) {
+ action = ST_ADM_ACTION_MAINT;
+ }
+ else if (strcmp(value, "shutdown") == 0) {
+ action = ST_ADM_ACTION_SHUTDOWN;
+ }
+ else if (strcmp(value, "dhlth") == 0) {
+ action = ST_ADM_ACTION_DHLTH;
+ }
+ else if (strcmp(value, "ehlth") == 0) {
+ action = ST_ADM_ACTION_EHLTH;
+ }
+ else if (strcmp(value, "hrunn") == 0) {
+ action = ST_ADM_ACTION_HRUNN;
+ }
+ else if (strcmp(value, "hnolb") == 0) {
+ action = ST_ADM_ACTION_HNOLB;
+ }
+ else if (strcmp(value, "hdown") == 0) {
+ action = ST_ADM_ACTION_HDOWN;
+ }
+ else if (strcmp(value, "dagent") == 0) {
+ action = ST_ADM_ACTION_DAGENT;
+ }
+ else if (strcmp(value, "eagent") == 0) {
+ action = ST_ADM_ACTION_EAGENT;
+ }
+ else if (strcmp(value, "arunn") == 0) {
+ action = ST_ADM_ACTION_ARUNN;
+ }
+ else if (strcmp(value, "adown") == 0) {
+ action = ST_ADM_ACTION_ADOWN;
+ }
+ /* else these are the old supported methods */
+ else if (strcmp(value, "disable") == 0) {
action = ST_ADM_ACTION_DISABLE;
}
else if (strcmp(value, "enable") == 0) {
@@ -4235,9 +4454,6 @@
else if (strcmp(value, "start") == 0) {
action = ST_ADM_ACTION_START;
}
- else if (strcmp(value, "shutdown") == 0) {
- action = ST_ADM_ACTION_SHUTDOWN;
- }
else {
appctx->ctx.stats.st_code = STAT_STATUS_ERRP;
goto out;
@@ -4258,44 +4474,113 @@
else if ((sv = findserver(px, value)) != NULL) {
switch (action) {
case ST_ADM_ACTION_DISABLE:
- if ((px->state != PR_STSTOPPED) && !(sv->state & SRV_MAINTAIN)) {
- /* Not already in maintenance, we can change the server state */
- sv->state |= SRV_MAINTAIN;
- sv->check.state |= CHK_ST_PAUSED;
- set_server_down(&sv->check);
+ if (!(sv->admin & SRV_ADMF_FMAINT)) {
altered_servers++;
total_servers++;
+ srv_set_admin_flag(sv, SRV_ADMF_FMAINT);
}
break;
case ST_ADM_ACTION_ENABLE:
- if ((px->state != PR_STSTOPPED) && (sv->state & SRV_MAINTAIN)) {
- /* Already in maintenance, we can change the server state.
- * If this server tracks the status of another one,
- * we must restore the good status.
- */
- if (!sv->track || (sv->track->state & SRV_RUNNING)) {
- set_server_up(&sv->check);
- sv->check.health = sv->check.rise; /* up, but will fall down at first failure */
- }
- else {
- sv->state &= ~SRV_MAINTAIN;
- sv->check.state &= ~CHK_ST_PAUSED;
- set_server_down(&sv->check);
- }
+ if (sv->admin & SRV_ADMF_FMAINT) {
altered_servers++;
total_servers++;
+ srv_clr_admin_flag(sv, SRV_ADMF_FMAINT);
}
break;
case ST_ADM_ACTION_STOP:
+ if (!(sv->admin & SRV_ADMF_FDRAIN)) {
+ srv_set_admin_flag(sv, SRV_ADMF_FDRAIN);
+ altered_servers++;
+ total_servers++;
+ }
+ break;
case ST_ADM_ACTION_START:
- if (action == ST_ADM_ACTION_START)
- sv->uweight = sv->iweight;
- else
- sv->uweight = 0;
-
- server_recalc_eweight(sv);
- set_server_drain_state(sv);
-
+ if (sv->admin & SRV_ADMF_FDRAIN) {
+ srv_clr_admin_flag(sv, SRV_ADMF_FDRAIN);
+ altered_servers++;
+ total_servers++;
+ }
+ break;
+ case ST_ADM_ACTION_DHLTH:
+ if (sv->check.state & CHK_ST_CONFIGURED) {
+ sv->check.state &= ~CHK_ST_ENABLED;
+ altered_servers++;
+ total_servers++;
+ }
+ break;
+ case ST_ADM_ACTION_EHLTH:
+ if (sv->check.state & CHK_ST_CONFIGURED) {
+ sv->check.state |= CHK_ST_ENABLED;
+ altered_servers++;
+ total_servers++;
+ }
+ break;
+ case ST_ADM_ACTION_HRUNN:
+ if (!(sv->track)) {
+ sv->check.health = sv->check.rise + sv->check.fall - 1;
+ srv_set_running(sv, "changed from Web interface");
+ altered_servers++;
+ total_servers++;
+ }
+ break;
+ case ST_ADM_ACTION_HNOLB:
+ if (!(sv->track)) {
+ sv->check.health = sv->check.rise + sv->check.fall - 1;
+ srv_set_stopping(sv, "changed from Web interface");
+ altered_servers++;
+ total_servers++;
+ }
+ break;
+ case ST_ADM_ACTION_HDOWN:
+ if (!(sv->track)) {
+ sv->check.health = 0;
+ srv_set_stopped(sv, "changed from Web interface");
+ altered_servers++;
+ total_servers++;
+ }
+ break;
+ case ST_ADM_ACTION_DAGENT:
+ if (sv->agent.state & CHK_ST_CONFIGURED) {
+ sv->agent.state &= ~CHK_ST_ENABLED;
+ altered_servers++;
+ total_servers++;
+ }
+ break;
+ case ST_ADM_ACTION_EAGENT:
+ if (sv->agent.state & CHK_ST_CONFIGURED) {
+ sv->agent.state |= CHK_ST_ENABLED;
+ altered_servers++;
+ total_servers++;
+ }
+ break;
+ case ST_ADM_ACTION_ARUNN:
+ if (sv->agent.state & CHK_ST_ENABLED) {
+ sv->agent.health = sv->agent.rise + sv->agent.fall - 1;
+ srv_set_running(sv, "changed from Web interface");
+ altered_servers++;
+ total_servers++;
+ }
+ break;
+ case ST_ADM_ACTION_ADOWN:
+ if (sv->agent.state & CHK_ST_ENABLED) {
+ sv->agent.health = 0;
+ srv_set_stopped(sv, "changed from Web interface");
+ altered_servers++;
+ total_servers++;
+ }
+ break;
+ case ST_ADM_ACTION_READY:
+ srv_adm_set_ready(sv);
+ altered_servers++;
+ total_servers++;
+ break;
+ case ST_ADM_ACTION_DRAIN:
+ srv_adm_set_drain(sv);
+ altered_servers++;
+ total_servers++;
+ break;
+ case ST_ADM_ACTION_MAINT:
+ srv_adm_set_maint(sv);
altered_servers++;
total_servers++;
break;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/ev_epoll.c
^
|
@@ -46,6 +46,19 @@
#endif
/*
+ * Immediately remove file descriptor from epoll set upon close.
+ * Since we forked, some fds share inodes with the other process, and epoll may
+ * send us events even though this process closed the fd (see man 7 epoll,
+ * "Questions and answers", Q 6).
+ */
+REGPRM1 static void __fd_clo(int fd)
+{
+ if (unlikely(fdtab[fd].cloned)) {
+ epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ev);
+ }
+}
+
+/*
* Linux epoll() poller
*/
REGPRM2 static void _do_poll(struct poller *p, int exp)
@@ -267,7 +280,7 @@
p->pref = 300;
p->private = NULL;
- p->clo = NULL;
+ p->clo = __fd_clo;
p->test = _do_test;
p->init = _do_init;
p->term = _do_term;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/fd.c
^
|
@@ -438,6 +438,13 @@
*/
int fork_poller()
{
+ int fd;
+ for (fd = 0; fd <= maxfd; fd++) {
+ if (fdtab[fd].owner) {
+ fdtab[fd].cloned = 1;
+ }
+ }
+
if (cur_poller.fork) {
if (cur_poller.fork(&cur_poller))
return 1;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/haproxy.c
^
|
@@ -449,7 +449,7 @@
chunk_printf(&trash,
"SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
p->id, s->id,
- (s->state & SRV_RUNNING) ? "UP" : "DOWN",
+ (s->state != SRV_ST_STOPPED) ? "UP" : "DOWN",
s->cur_sess, s->nbpend, s->counters.cum_sess);
Warning("%s\n", trash.str);
send_log(p, LOG_NOTICE, "%s\n", trash.str);
@@ -1610,6 +1610,8 @@
exit(0); /* parent must leave */
}
+ free(children);
+ children = NULL;
/* if we're NOT in QUIET mode, we should now close the 3 first FDs to ensure
* that we can detach from the TTY. We MUST NOT do it in other cases since
* it would have already be done, and 0-2 would have been affected to listening
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/lb_chash.c
^
|
@@ -98,18 +98,17 @@
{
struct proxy *p = srv->proxy;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
- if (srv_is_usable(srv->state, srv->eweight))
+ if (srv_is_usable(srv))
goto out_update_state;
- if (!srv_is_usable(srv->prev_state, srv->prev_eweight))
+ if (!srv_was_usable(srv))
/* server was already down */
goto out_update_backend;
- if (srv->state & SRV_BACKUP) {
+ if (srv->flags & SRV_F_BACKUP) {
p->lbprm.tot_wbck -= srv->prev_eweight;
p->srv_bck--;
@@ -121,8 +120,8 @@
do {
srv2 = srv2->next;
} while (srv2 &&
- !((srv2->state & SRV_BACKUP) &&
- srv_is_usable(srv2->state, srv2->eweight)));
+ !((srv2->flags & SRV_F_BACKUP) &&
+ srv_is_usable(srv2)));
p->lbprm.fbck = srv2;
}
} else {
@@ -136,8 +135,7 @@
/* check/update tot_used, tot_weight */
update_backend_weight(p);
out_update_state:
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function updates the server trees according to server <srv>'s new
@@ -151,18 +149,17 @@
{
struct proxy *p = srv->proxy;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
- if (!srv_is_usable(srv->state, srv->eweight))
+ if (!srv_is_usable(srv))
goto out_update_state;
- if (srv_is_usable(srv->prev_state, srv->prev_eweight))
+ if (srv_was_usable(srv))
/* server was already up */
goto out_update_backend;
- if (srv->state & SRV_BACKUP) {
+ if (srv->flags & SRV_F_BACKUP) {
p->lbprm.tot_wbck += srv->eweight;
p->srv_bck++;
@@ -194,8 +191,7 @@
/* check/update tot_used, tot_weight */
update_backend_weight(p);
out_update_state:
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function must be called after an update to server <srv>'s effective
@@ -206,8 +202,7 @@
int old_state, new_state;
struct proxy *p = srv->proxy;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
/* If changing the server's weight changes its state, we simply apply
@@ -218,12 +213,11 @@
* possibly a new tree for this server.
*/
- old_state = srv_is_usable(srv->prev_state, srv->prev_eweight);
- new_state = srv_is_usable(srv->state, srv->eweight);
+ old_state = srv_was_usable(srv);
+ new_state = srv_is_usable(srv);
if (!old_state && !new_state) {
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
return;
}
else if (!old_state && new_state) {
@@ -238,14 +232,13 @@
/* only adjust the server's presence in the tree */
chash_queue_dequeue_srv(srv);
- if (srv->state & SRV_BACKUP)
+ if (srv->flags & SRV_F_BACKUP)
p->lbprm.tot_wbck += srv->eweight - srv->prev_eweight;
else
p->lbprm.tot_wact += srv->eweight - srv->prev_eweight;
update_backend_weight(p);
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/*
@@ -383,8 +376,7 @@
p->lbprm.wdiv = BE_WEIGHT_SCALE;
for (srv = p->srv; srv; srv = srv->next) {
srv->eweight = (srv->uweight * p->lbprm.wdiv + p->lbprm.wmult - 1) / p->lbprm.wmult;
- srv->prev_eweight = srv->eweight;
- srv->prev_state = srv->state;
+ srv_lb_commit_status(srv);
}
recount_servers(p);
@@ -396,7 +388,7 @@
/* queue active and backup servers in two distinct groups */
for (srv = p->srv; srv; srv = srv->next) {
- srv->lb_tree = (srv->state & SRV_BACKUP) ? &p->lbprm.chash.bck : &p->lbprm.chash.act;
+ srv->lb_tree = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.chash.bck : &p->lbprm.chash.act;
srv->lb_nodes_tot = srv->uweight * BE_WEIGHT_SCALE;
srv->lb_nodes_now = 0;
srv->lb_nodes = (struct tree_occ *)calloc(srv->lb_nodes_tot, sizeof(struct tree_occ));
@@ -406,7 +398,7 @@
srv->lb_nodes[node].node.key = full_hash(srv->puid * SRV_EWGHT_RANGE + node);
}
- if (srv_is_usable(srv->state, srv->eweight))
+ if (srv_is_usable(srv))
chash_queue_dequeue_srv(srv);
}
}
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/lb_fas.c
^
|
@@ -77,18 +77,17 @@
{
struct proxy *p = srv->proxy;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
- if (srv_is_usable(srv->state, srv->eweight))
+ if (srv_is_usable(srv))
goto out_update_state;
- if (!srv_is_usable(srv->prev_state, srv->prev_eweight))
+ if (!srv_was_usable(srv))
/* server was already down */
goto out_update_backend;
- if (srv->state & SRV_BACKUP) {
+ if (srv->flags & SRV_F_BACKUP) {
p->lbprm.tot_wbck -= srv->prev_eweight;
p->srv_bck--;
@@ -100,8 +99,8 @@
do {
srv2 = srv2->next;
} while (srv2 &&
- !((srv2->state & SRV_BACKUP) &&
- srv_is_usable(srv2->state, srv2->eweight)));
+ !((srv2->flags & SRV_F_BACKUP) &&
+ srv_is_usable(srv2)));
p->lbprm.fbck = srv2;
}
} else {
@@ -116,8 +115,7 @@
/* check/update tot_used, tot_weight */
update_backend_weight(p);
out_update_state:
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function updates the server trees according to server <srv>'s new
@@ -131,18 +129,17 @@
{
struct proxy *p = srv->proxy;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
- if (!srv_is_usable(srv->state, srv->eweight))
+ if (!srv_is_usable(srv))
goto out_update_state;
- if (srv_is_usable(srv->prev_state, srv->prev_eweight))
+ if (srv_was_usable(srv))
/* server was already up */
goto out_update_backend;
- if (srv->state & SRV_BACKUP) {
+ if (srv->flags & SRV_F_BACKUP) {
srv->lb_tree = &p->lbprm.fas.bck;
p->lbprm.tot_wbck += srv->eweight;
p->srv_bck++;
@@ -176,8 +173,7 @@
/* check/update tot_used, tot_weight */
update_backend_weight(p);
out_update_state:
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function must be called after an update to server <srv>'s effective
@@ -188,8 +184,7 @@
int old_state, new_state;
struct proxy *p = srv->proxy;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
/* If changing the server's weight changes its state, we simply apply
@@ -200,12 +195,11 @@
* possibly a new tree for this server.
*/
- old_state = srv_is_usable(srv->prev_state, srv->prev_eweight);
- new_state = srv_is_usable(srv->state, srv->eweight);
+ old_state = srv_was_usable(srv);
+ new_state = srv_is_usable(srv);
if (!old_state && !new_state) {
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
return;
}
else if (!old_state && new_state) {
@@ -220,7 +214,7 @@
if (srv->lb_tree)
fas_dequeue_srv(srv);
- if (srv->state & SRV_BACKUP) {
+ if (srv->flags & SRV_F_BACKUP) {
p->lbprm.tot_wbck += srv->eweight - srv->prev_eweight;
srv->lb_tree = &p->lbprm.fas.bck;
} else {
@@ -231,8 +225,7 @@
fas_queue_srv(srv);
update_backend_weight(p);
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function is responsible for building the trees in case of fast
@@ -253,8 +246,7 @@
p->lbprm.wdiv = BE_WEIGHT_SCALE;
for (srv = p->srv; srv; srv = srv->next) {
srv->eweight = (srv->uweight * p->lbprm.wdiv + p->lbprm.wmult - 1) / p->lbprm.wmult;
- srv->prev_eweight = srv->eweight;
- srv->prev_state = srv->state;
+ srv_lb_commit_status(srv);
}
recount_servers(p);
@@ -265,9 +257,9 @@
/* queue active and backup servers in two distinct groups */
for (srv = p->srv; srv; srv = srv->next) {
- if (!srv_is_usable(srv->state, srv->eweight))
+ if (!srv_is_usable(srv))
continue;
- srv->lb_tree = (srv->state & SRV_BACKUP) ? &p->lbprm.fas.bck : &p->lbprm.fas.act;
+ srv->lb_tree = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.fas.bck : &p->lbprm.fas.act;
fas_queue_srv(srv);
}
}
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/lb_fwlc.c
^
|
@@ -69,18 +69,17 @@
{
struct proxy *p = srv->proxy;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
- if (srv_is_usable(srv->state, srv->eweight))
+ if (srv_is_usable(srv))
goto out_update_state;
- if (!srv_is_usable(srv->prev_state, srv->prev_eweight))
+ if (!srv_was_usable(srv))
/* server was already down */
goto out_update_backend;
- if (srv->state & SRV_BACKUP) {
+ if (srv->flags & SRV_F_BACKUP) {
p->lbprm.tot_wbck -= srv->prev_eweight;
p->srv_bck--;
@@ -92,8 +91,8 @@
do {
srv2 = srv2->next;
} while (srv2 &&
- !((srv2->state & SRV_BACKUP) &&
- srv_is_usable(srv2->state, srv2->eweight)));
+ !((srv2->flags & SRV_F_BACKUP) &&
+ srv_is_usable(srv2)));
p->lbprm.fbck = srv2;
}
} else {
@@ -108,8 +107,7 @@
/* check/update tot_used, tot_weight */
update_backend_weight(p);
out_update_state:
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function updates the server trees according to server <srv>'s new
@@ -123,18 +121,17 @@
{
struct proxy *p = srv->proxy;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
- if (!srv_is_usable(srv->state, srv->eweight))
+ if (!srv_is_usable(srv))
goto out_update_state;
- if (srv_is_usable(srv->prev_state, srv->prev_eweight))
+ if (srv_was_usable(srv))
/* server was already up */
goto out_update_backend;
- if (srv->state & SRV_BACKUP) {
+ if (srv->flags & SRV_F_BACKUP) {
srv->lb_tree = &p->lbprm.fwlc.bck;
p->lbprm.tot_wbck += srv->eweight;
p->srv_bck++;
@@ -168,8 +165,7 @@
/* check/update tot_used, tot_weight */
update_backend_weight(p);
out_update_state:
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function must be called after an update to server <srv>'s effective
@@ -180,8 +176,7 @@
int old_state, new_state;
struct proxy *p = srv->proxy;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
/* If changing the server's weight changes its state, we simply apply
@@ -192,12 +187,11 @@
* possibly a new tree for this server.
*/
- old_state = srv_is_usable(srv->prev_state, srv->prev_eweight);
- new_state = srv_is_usable(srv->state, srv->eweight);
+ old_state = srv_was_usable(srv);
+ new_state = srv_is_usable(srv);
if (!old_state && !new_state) {
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
return;
}
else if (!old_state && new_state) {
@@ -212,7 +206,7 @@
if (srv->lb_tree)
fwlc_dequeue_srv(srv);
- if (srv->state & SRV_BACKUP) {
+ if (srv->flags & SRV_F_BACKUP) {
p->lbprm.tot_wbck += srv->eweight - srv->prev_eweight;
srv->lb_tree = &p->lbprm.fwlc.bck;
} else {
@@ -223,8 +217,7 @@
fwlc_queue_srv(srv);
update_backend_weight(p);
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function is responsible for building the trees in case of fast
@@ -245,8 +238,7 @@
p->lbprm.wdiv = BE_WEIGHT_SCALE;
for (srv = p->srv; srv; srv = srv->next) {
srv->eweight = (srv->uweight * p->lbprm.wdiv + p->lbprm.wmult - 1) / p->lbprm.wmult;
- srv->prev_eweight = srv->eweight;
- srv->prev_state = srv->state;
+ srv_lb_commit_status(srv);
}
recount_servers(p);
@@ -257,9 +249,9 @@
/* queue active and backup servers in two distinct groups */
for (srv = p->srv; srv; srv = srv->next) {
- if (!srv_is_usable(srv->state, srv->eweight))
+ if (!srv_is_usable(srv))
continue;
- srv->lb_tree = (srv->state & SRV_BACKUP) ? &p->lbprm.fwlc.bck : &p->lbprm.fwlc.act;
+ srv->lb_tree = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.fwlc.bck : &p->lbprm.fwlc.act;
fwlc_queue_srv(srv);
}
}
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/lb_fwrr.c
^
|
@@ -39,21 +39,20 @@
struct proxy *p = srv->proxy;
struct fwrr_group *grp;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
- if (srv_is_usable(srv->state, srv->eweight))
+ if (srv_is_usable(srv))
goto out_update_state;
- if (!srv_is_usable(srv->prev_state, srv->prev_eweight))
+ if (!srv_was_usable(srv))
/* server was already down */
goto out_update_backend;
- grp = (srv->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
+ grp = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
grp->next_weight -= srv->prev_eweight;
- if (srv->state & SRV_BACKUP) {
+ if (srv->flags & SRV_F_BACKUP) {
p->lbprm.tot_wbck = p->lbprm.fwrr.bck.next_weight;
p->srv_bck--;
@@ -65,8 +64,8 @@
do {
srv2 = srv2->next;
} while (srv2 &&
- !((srv2->state & SRV_BACKUP) &&
- srv_is_usable(srv2->state, srv2->eweight)));
+ !((srv2->flags & SRV_F_BACKUP) &&
+ srv_is_usable(srv2)));
p->lbprm.fbck = srv2;
}
} else {
@@ -81,8 +80,7 @@
/* check/update tot_used, tot_weight */
update_backend_weight(p);
out_update_state:
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function updates the server trees according to server <srv>'s new
@@ -97,21 +95,20 @@
struct proxy *p = srv->proxy;
struct fwrr_group *grp;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
- if (!srv_is_usable(srv->state, srv->eweight))
+ if (!srv_is_usable(srv))
goto out_update_state;
- if (srv_is_usable(srv->prev_state, srv->prev_eweight))
+ if (srv_was_usable(srv))
/* server was already up */
goto out_update_backend;
- grp = (srv->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
+ grp = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
grp->next_weight += srv->eweight;
- if (srv->state & SRV_BACKUP) {
+ if (srv->flags & SRV_F_BACKUP) {
p->lbprm.tot_wbck = p->lbprm.fwrr.bck.next_weight;
p->srv_bck++;
@@ -145,8 +142,7 @@
/* check/update tot_used, tot_weight */
update_backend_weight(p);
out_update_state:
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function must be called after an update to server <srv>'s effective
@@ -158,8 +154,7 @@
struct proxy *p = srv->proxy;
struct fwrr_group *grp;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
/* If changing the server's weight changes its state, we simply apply
@@ -170,12 +165,11 @@
* possibly a new tree for this server.
*/
- old_state = srv_is_usable(srv->prev_state, srv->prev_eweight);
- new_state = srv_is_usable(srv->state, srv->eweight);
+ old_state = srv_was_usable(srv);
+ new_state = srv_is_usable(srv);
if (!old_state && !new_state) {
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
return;
}
else if (!old_state && new_state) {
@@ -187,7 +181,7 @@
return;
}
- grp = (srv->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
+ grp = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
grp->next_weight = grp->next_weight - srv->prev_eweight + srv->eweight;
p->lbprm.tot_wact = p->lbprm.fwrr.act.next_weight;
@@ -233,8 +227,7 @@
}
update_backend_weight(p);
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* Remove a server from a tree. It must have previously been dequeued. This
@@ -273,8 +266,7 @@
p->lbprm.wdiv = BE_WEIGHT_SCALE;
for (srv = p->srv; srv; srv = srv->next) {
srv->eweight = (srv->uweight * p->lbprm.wdiv + p->lbprm.wmult - 1) / p->lbprm.wmult;
- srv->prev_eweight = srv->eweight;
- srv->prev_state = srv->state;
+ srv_lb_commit_status(srv);
}
recount_servers(p);
@@ -298,9 +290,9 @@
/* queue active and backup servers in two distinct groups */
for (srv = p->srv; srv; srv = srv->next) {
- if (!srv_is_usable(srv->state, srv->eweight))
+ if (!srv_is_usable(srv))
continue;
- fwrr_queue_by_weight((srv->state & SRV_BACKUP) ?
+ fwrr_queue_by_weight((srv->flags & SRV_F_BACKUP) ?
p->lbprm.fwrr.bck.init :
p->lbprm.fwrr.act.init,
srv);
@@ -322,12 +314,12 @@
struct proxy *p = s->proxy;
struct fwrr_group *grp;
- grp = (s->state & SRV_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
+ grp = (s->flags & SRV_F_BACKUP) ? &p->lbprm.fwrr.bck : &p->lbprm.fwrr.act;
/* Delay everything which does not fit into the window and everything
* which does not fit into the theorical new window.
*/
- if (!srv_is_usable(s->state, s->eweight)) {
+ if (!srv_is_usable(s)) {
fwrr_remove_from_tree(s);
}
else if (s->eweight <= 0 ||
@@ -363,7 +355,7 @@
/* prepares a server when extracting it from the "next" tree */
static inline void fwrr_get_srv_next(struct server *s)
{
- struct fwrr_group *grp = (s->state & SRV_BACKUP) ?
+ struct fwrr_group *grp = (s->flags & SRV_F_BACKUP) ?
&s->proxy->lbprm.fwrr.bck :
&s->proxy->lbprm.fwrr.act;
@@ -373,7 +365,7 @@
/* prepares a server when it was marked down */
static inline void fwrr_get_srv_down(struct server *s)
{
- struct fwrr_group *grp = (s->state & SRV_BACKUP) ?
+ struct fwrr_group *grp = (s->flags & SRV_F_BACKUP) ?
&s->proxy->lbprm.fwrr.bck :
&s->proxy->lbprm.fwrr.act;
@@ -384,7 +376,7 @@
static void fwrr_get_srv(struct server *s)
{
struct proxy *p = s->proxy;
- struct fwrr_group *grp = (s->state & SRV_BACKUP) ?
+ struct fwrr_group *grp = (s->flags & SRV_F_BACKUP) ?
&p->lbprm.fwrr.bck :
&p->lbprm.fwrr.act;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/lb_map.c
^
|
@@ -28,11 +28,10 @@
{
struct proxy *p = srv->proxy;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
- if (srv_is_usable(srv->state, srv->eweight))
+ if (srv_is_usable(srv))
goto out_update_state;
/* FIXME: could be optimized since we know what changed */
@@ -40,8 +39,7 @@
update_backend_weight(p);
p->lbprm.map.state |= LB_MAP_RECALC;
out_update_state:
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function updates the map according to server <srv>'s new state */
@@ -49,11 +47,10 @@
{
struct proxy *p = srv->proxy;
- if (srv->state == srv->prev_state &&
- srv->eweight == srv->prev_eweight)
+ if (!srv_lb_status_changed(srv))
return;
- if (!srv_is_usable(srv->state, srv->eweight))
+ if (!srv_is_usable(srv))
goto out_update_state;
/* FIXME: could be optimized since we know what changed */
@@ -61,8 +58,7 @@
update_backend_weight(p);
p->lbprm.map.state |= LB_MAP_RECALC;
out_update_state:
- srv->prev_state = srv->state;
- srv->prev_eweight = srv->eweight;
+ srv_lb_commit_status(srv);
}
/* This function recomputes the server map for proxy px. It relies on
@@ -86,9 +82,9 @@
/* here we *know* that we have some servers */
if (px->srv_act)
- flag = SRV_RUNNING;
+ flag = 0;
else
- flag = SRV_RUNNING | SRV_BACKUP;
+ flag = SRV_F_BACKUP;
/* this algorithm gives priority to the first server, which means that
* it will respect the declaration order for equivalent weights, and
@@ -103,9 +99,8 @@
int max = 0;
best = NULL;
for (cur = px->srv; cur; cur = cur->next) {
- if (cur->eweight &&
- flag == (cur->state &
- (SRV_RUNNING | SRV_GOINGDOWN | SRV_BACKUP))) {
+ if ((cur->flags & SRV_F_BACKUP) == flag &&
+ srv_is_usable(cur)) {
int v;
/* If we are forced to return only one server, we don't want to
@@ -181,9 +176,9 @@
act = bck = 0;
for (srv = p->srv; srv; srv = srv->next) {
srv->eweight = (srv->uweight * p->lbprm.wdiv + p->lbprm.wmult - 1) / p->lbprm.wmult;
- srv->prev_eweight = srv->eweight;
- srv->prev_state = srv->state;
- if (srv->state & SRV_BACKUP)
+ srv_lb_commit_status(srv);
+
+ if (srv->flags & SRV_F_BACKUP)
bck += srv->eweight;
else
act += srv->eweight;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/pattern.c
^
|
@@ -1076,8 +1076,8 @@
/* compile regex */
if (!regex_comp(pat->ptr.str, patl->pat.ptr.reg, !(expr->mflags & PAT_MF_IGNORE_CASE), 0, err)) {
- free(patl);
free(patl->pat.ptr.reg);
+ free(patl);
return 0;
}
@@ -1458,14 +1458,14 @@
/* delete pattern from reference */
list_for_each_entry_safe(elt, safe, &ref->head, list) {
if (strcmp(key, elt->pattern) == 0) {
+ list_for_each_entry(expr, &ref->pat, list)
+ pattern_delete(expr, elt);
+
LIST_DEL(&elt->list);
free(elt->sample);
free(elt->pattern);
free(elt);
- list_for_each_entry(expr, &ref->pat, list)
- pattern_delete(expr, elt);
-
found = 1;
}
}
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/proto_http.c
^
|
@@ -6817,7 +6817,10 @@
break;
case ACT_REPLACE:
- trash.len = exp_replace(trash.str, cur_ptr, exp->replace, pmatch);
+ trash.len = exp_replace(trash.str, trash.size, cur_ptr, exp->replace, pmatch);
+ if (trash.len < 0)
+ return -1;
+
delta = buffer_replace2(req->buf, cur_ptr, cur_end, trash.str, trash.len);
/* FIXME: if the user adds a newline in the replacement, the
* index will not be recalculated for now, and the new line
@@ -6927,7 +6930,10 @@
case ACT_REPLACE:
*cur_end = term; /* restore the string terminator */
- trash.len = exp_replace(trash.str, cur_ptr, exp->replace, pmatch);
+ trash.len = exp_replace(trash.str, trash.size, cur_ptr, exp->replace, pmatch);
+ if (trash.len < 0)
+ return -1;
+
delta = buffer_replace2(req->buf, cur_ptr, cur_end, trash.str, trash.len);
/* FIXME: if the user adds a newline in the replacement, the
* index will not be recalculated for now, and the new line
@@ -7069,12 +7075,12 @@
while (srv) {
if (strcmp(srv->id, asession->serverid) == 0) {
- if ((srv->state & SRV_RUNNING) ||
+ if ((srv->state != SRV_ST_STOPPED) ||
(s->be->options & PR_O_PERSIST) ||
(s->flags & SN_FORCE_PRST)) {
/* we found the server and it's usable */
txn->flags &= ~TX_CK_MASK;
- txn->flags |= (srv->state & SRV_RUNNING) ? TX_CK_VALID : TX_CK_DOWN;
+ txn->flags |= (srv->state != SRV_ST_STOPPED) ? TX_CK_VALID : TX_CK_DOWN;
s->flags |= SN_DIRECT | SN_ASSIGNED;
s->target = &srv->obj_type;
@@ -7479,12 +7485,12 @@
while (srv) {
if (srv->cookie && (srv->cklen == delim - val_beg) &&
!memcmp(val_beg, srv->cookie, delim - val_beg)) {
- if ((srv->state & SRV_RUNNING) ||
+ if ((srv->state != SRV_ST_STOPPED) ||
(s->be->options & PR_O_PERSIST) ||
(s->flags & SN_FORCE_PRST)) {
/* we found the server and we can use it */
txn->flags &= ~TX_CK_MASK;
- txn->flags |= (srv->state & SRV_RUNNING) ? TX_CK_VALID : TX_CK_DOWN;
+ txn->flags |= (srv->state != SRV_ST_STOPPED) ? TX_CK_VALID : TX_CK_DOWN;
s->flags |= SN_DIRECT | SN_ASSIGNED;
s->target = &srv->obj_type;
break;
@@ -7676,7 +7682,10 @@
break;
case ACT_REPLACE:
- trash.len = exp_replace(trash.str, cur_ptr, exp->replace, pmatch);
+ trash.len = exp_replace(trash.str, trash.size, cur_ptr, exp->replace, pmatch);
+ if (trash.len < 0)
+ return -1;
+
delta = buffer_replace2(rtr->buf, cur_ptr, cur_end, trash.str, trash.len);
/* FIXME: if the user adds a newline in the replacement, the
* index will not be recalculated for now, and the new line
@@ -7766,7 +7775,10 @@
case ACT_REPLACE:
*cur_end = term; /* restore the string terminator */
- trash.len = exp_replace(trash.str, cur_ptr, exp->replace, pmatch);
+ trash.len = exp_replace(trash.str, trash.size, cur_ptr, exp->replace, pmatch);
+ if (trash.len < 0)
+ return -1;
+
delta = buffer_replace2(rtr->buf, cur_ptr, cur_end, trash.str, trash.len);
/* FIXME: if the user adds a newline in the replacement, the
* index will not be recalculated for now, and the new line
@@ -7847,7 +7859,8 @@
/* The filter did not match the response, it can be
* iterated through all headers.
*/
- apply_filter_to_resp_headers(s, rtr, exp);
+ if (unlikely(apply_filter_to_resp_headers(s, rtr, exp) < 0))
+ return -1;
}
}
return 0;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/proxy.c
^
|
@@ -233,6 +233,11 @@
}
}
+ if (*args[2] != 0) {
+ memprintf(err, "'timeout %s' : unexpected extra argument '%s' after value '%s'.", name, args[2], args[1]);
+ retval = -1;
+ }
+
*tv = MS_TO_TICKS(timeout);
return retval;
}
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/queue.c
^
|
@@ -50,7 +50,7 @@
else max = MAX(s->minconn,
s->proxy->beconn * s->maxconn / s->proxy->fullconn);
- if ((s->state & SRV_WARMINGUP) &&
+ if ((s->state == SRV_ST_STARTING) &&
now.tv_sec < s->last_change + s->slowstart &&
now.tv_sec >= s->last_change) {
unsigned int ratio;
@@ -109,7 +109,7 @@
ps = pendconn_from_srv(srv);
pp = pendconn_from_px(px);
/* we want to get the definitive pendconn in <ps> */
- if (!pp || !srv_is_usable(rsrv->state, rsrv->eweight)) {
+ if (!pp || !srv_is_usable(rsrv)) {
if (!ps)
return NULL;
} else {
@@ -167,6 +167,61 @@
return p;
}
+/* Redistribute pending connections when a server goes down. The number of
+ * connections redistributed is returned.
+ */
+int pendconn_redistribute(struct server *s)
+{
+ struct pendconn *pc, *pc_bck;
+ int xferred = 0;
+
+ list_for_each_entry_safe(pc, pc_bck, &s->pendconns, list) {
+ struct session *sess = pc->sess;
+
+ if ((sess->be->options & (PR_O_REDISP|PR_O_PERSIST)) == PR_O_REDISP &&
+ !(sess->flags & SN_FORCE_PRST)) {
+ /* The REDISP option was specified. We will ignore
+ * cookie and force to balance or use the dispatcher.
+ */
+
+ /* it's left to the dispatcher to choose a server */
+ sess->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
+
+ pendconn_free(pc);
+ task_wakeup(sess->task, TASK_WOKEN_RES);
+ xferred++;
+ }
+ }
+ return xferred;
+}
+
+/* Check for pending connections at the backend, and assign some of them to
+ * the server coming up. The server's weight is checked before being assigned
+ * connections it may not be able to handle. The total number of transferred
+ * connections is returned.
+ */
+int pendconn_grab_from_px(struct server *s)
+{
+ int xferred;
+
+ if (!srv_is_usable(s))
+ return 0;
+
+ for (xferred = 0; !s->maxconn || xferred < srv_dynamic_maxconn(s); xferred++) {
+ struct session *sess;
+ struct pendconn *p;
+
+ p = pendconn_from_px(s->proxy);
+ if (!p)
+ break;
+ p->sess->target = &s->obj_type;
+ sess = p->sess;
+ pendconn_free(p);
+ task_wakeup(sess->task, TASK_WOKEN_RES);
+ }
+ return xferred;
+}
+
/*
* Detaches pending connection <p>, decreases the pending count, and frees
* the pending connection. The connection might have been queued to a specific
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/regex.c
^
|
@@ -22,14 +22,17 @@
/* regex trash buffer used by various regex tests */
regmatch_t pmatch[MAX_MATCH]; /* rm_so, rm_eo for regular expressions */
-
-int exp_replace(char *dst, char *src, const char *str, const regmatch_t *matches)
+int exp_replace(char *dst, uint dst_size, char *src, const char *str, const regmatch_t *matches)
{
char *old_dst = dst;
+ char* dst_end = dst + dst_size;
while (*str) {
if (*str == '\\') {
str++;
+ if (!*str)
+ return -1;
+
if (isdigit((unsigned char)*str)) {
int len, num;
@@ -38,6 +41,10 @@
if (matches[num].rm_eo > -1 && matches[num].rm_so > -1) {
len = matches[num].rm_eo - matches[num].rm_so;
+
+ if (dst + len >= dst_end)
+ return -1;
+
memcpy(dst, src + matches[num].rm_so, len);
dst += len;
}
@@ -46,19 +53,39 @@
unsigned char hex1, hex2;
str++;
+ if (!*str)
+ return -1;
+
hex1 = toupper(*str++) - '0';
+
+ if (!*str)
+ return -1;
+
hex2 = toupper(*str++) - '0';
if (hex1 > 9) hex1 -= 'A' - '9' - 1;
if (hex2 > 9) hex2 -= 'A' - '9' - 1;
+
+ if (dst >= dst_end)
+ return -1;
+
*dst++ = (hex1<<4) + hex2;
} else {
+ if (dst >= dst_end)
+ return -1;
+
*dst++ = *str++;
}
} else {
+ if (dst >= dst_end)
+ return -1;
+
*dst++ = *str++;
}
}
+ if (dst >= dst_end)
+ return -1;
+
*dst = '\0';
return dst - old_dst;
}
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/server.c
^
|
@@ -22,8 +22,12 @@
#include <proto/port_range.h>
#include <proto/protocol.h>
+#include <proto/queue.h>
#include <proto/raw_sock.h>
#include <proto/server.h>
+#include <proto/session.h>
+#include <proto/task.h>
+
/* List head of all known server keywords */
static struct srv_kw_list srv_keywords = {
@@ -32,7 +36,7 @@
int srv_downtime(const struct server *s)
{
- if ((s->state & SRV_RUNNING) && s->last_change < now.tv_sec) // ignore negative time
+ if ((s->state != SRV_ST_STOPPED) && s->last_change < now.tv_sec) // ignore negative time
return s->down_time;
return now.tv_sec - s->last_change + s->down_time;
@@ -53,7 +57,7 @@
if ((check->state & CHK_ST_CONFIGURED) && (check->health == check->rise + check->fall - 1))
return check->inter;
- if (!(s->state & SRV_RUNNING) && check->health == 0)
+ if ((s->state == SRV_ST_STOPPED) && check->health == 0)
return (check->downinter)?(check->downinter):(check->inter);
return (check->fastinter)?(check->fastinter):(check->inter);
@@ -156,6 +160,539 @@
return 0;
}
+/* Shutdown all connections of a server. The caller must pass a termination
+ * code in <why>, which must be one of SN_ERR_* indicating the reason for the
+ * shutdown.
+ */
+void srv_shutdown_sessions(struct server *srv, int why)
+{
+ struct session *session, *session_bck;
+
+ list_for_each_entry_safe(session, session_bck, &srv->actconns, by_srv)
+ if (session->srv_conn == srv)
+ session_shutdown(session, why);
+}
+
+/* Shutdown all connections of all backup servers of a proxy. The caller must
+ * pass a termination code in <why>, which must be one of SN_ERR_* indicating
+ * the reason for the shutdown.
+ */
+void srv_shutdown_backup_sessions(struct proxy *px, int why)
+{
+ struct server *srv;
+
+ for (srv = px->srv; srv != NULL; srv = srv->next)
+ if (srv->flags & SRV_F_BACKUP)
+ srv_shutdown_sessions(srv, why);
+}
+
+/* Appends some information to a message string related to a server going UP or
+ * DOWN. If both <forced> and <reason> are null and the server tracks another
+ * one, a "via" information will be provided to know where the status came from.
+ * If <reason> is non-null, the entire string will be appended after a comma and
+ * a space (eg: to report some information from the check that changed the state).
+ * If <xferred> is non-negative, some information about requeued sessions are
+ * provided.
+ */
+void srv_append_status(struct chunk *msg, struct server *s, const char *reason, int xferred, int forced)
+{
+ if (reason)
+ chunk_appendf(msg, ", %s", reason);
+ else if (!forced && s->track)
+ chunk_appendf(msg, " via %s/%s", s->track->proxy->id, s->track->id);
+
+ if (xferred >= 0) {
+ if (s->state == SRV_ST_STOPPED)
+ chunk_appendf(msg, ". %d active and %d backup servers left.%s"
+ " %d sessions active, %d requeued, %d remaining in queue",
+ s->proxy->srv_act, s->proxy->srv_bck,
+ (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
+ s->cur_sess, xferred, s->nbpend);
+ else
+ chunk_appendf(msg, ". %d active and %d backup servers online.%s"
+ " %d sessions requeued, %d total in queue",
+ s->proxy->srv_act, s->proxy->srv_bck,
+ (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "",
+ xferred, s->nbpend);
+ }
+}
+
+/* Marks server <s> down, regardless of its checks' statuses, notifies by all
+ * available means, recounts the remaining servers on the proxy and transfers
+ * queued sessions whenever possible to other servers. It automatically
+ * recomputes the number of servers, but not the map. Maintenance servers are
+ * ignored. It reports <reason> if non-null as the reason for going down. Note
+ * that it makes use of the trash to build the log strings, so <reason> must
+ * not be placed there.
+ */
+void srv_set_stopped(struct server *s, const char *reason)
+{
+ struct server *srv;
+ int prev_srv_count = s->proxy->srv_bck + s->proxy->srv_act;
+ int srv_was_stopping = (s->state == SRV_ST_STOPPING);
+ int xferred;
+
+ if ((s->admin & SRV_ADMF_MAINT) || s->state == SRV_ST_STOPPED)
+ return;
+
+ s->last_change = now.tv_sec;
+ s->state = SRV_ST_STOPPED;
+ if (s->proxy->lbprm.set_server_status_down)
+ s->proxy->lbprm.set_server_status_down(s);
+
+ if (s->onmarkeddown & HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS)
+ srv_shutdown_sessions(s, SN_ERR_DOWN);
+
+ /* we might have sessions queued on this server and waiting for
+ * a connection. Those which are redispatchable will be queued
+ * to another server or to the proxy itself.
+ */
+ xferred = pendconn_redistribute(s);
+
+ chunk_printf(&trash,
+ "%sServer %s/%s is DOWN", s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+
+ srv_append_status(&trash, s, reason, xferred, 0);
+ Warning("%s.\n", trash.str);
+
+ /* we don't send an alert if the server was previously paused */
+ send_log(s->proxy, srv_was_stopping ? LOG_NOTICE : LOG_ALERT, "%s.\n", trash.str);
+
+ if (prev_srv_count && s->proxy->srv_bck == 0 && s->proxy->srv_act == 0)
+ set_backend_down(s->proxy);
+
+ s->counters.down_trans++;
+
+ for (srv = s->trackers; srv; srv = srv->tracknext)
+ srv_set_stopped(srv, NULL);
+}
+
+/* Marks server <s> up regardless of its checks' statuses and provided it isn't
+ * in maintenance. Notifies by all available means, recounts the remaining
+ * servers on the proxy and tries to grab requests from the proxy. It
+ * automatically recomputes the number of servers, but not the map. Maintenance
+ * servers are ignored. It reports <reason> if non-null as the reason for going
+ * up. Note that it makes use of the trash to build the log strings, so <reason>
+ * must not be placed there.
+ */
+void srv_set_running(struct server *s, const char *reason)
+{
+ struct server *srv;
+ int xferred;
+
+ if (s->admin & SRV_ADMF_MAINT)
+ return;
+
+ if (s->state == SRV_ST_STARTING || s->state == SRV_ST_RUNNING)
+ return;
+
+ if (s->proxy->srv_bck == 0 && s->proxy->srv_act == 0) {
+ if (s->proxy->last_change < now.tv_sec) // ignore negative times
+ s->proxy->down_time += now.tv_sec - s->proxy->last_change;
+ s->proxy->last_change = now.tv_sec;
+ }
+
+ if (s->state == SRV_ST_STOPPED && s->last_change < now.tv_sec) // ignore negative times
+ s->down_time += now.tv_sec - s->last_change;
+
+ s->last_change = now.tv_sec;
+
+ s->state = SRV_ST_STARTING;
+ if (s->slowstart > 0)
+ task_schedule(s->warmup, tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20))));
+ else
+ s->state = SRV_ST_RUNNING;
+
+ server_recalc_eweight(s);
+
+ /* If the server is set with "on-marked-up shutdown-backup-sessions",
+ * and it's not a backup server and its effective weight is > 0,
+ * then it can accept new connections, so we shut down all sessions
+ * on all backup servers.
+ */
+ if ((s->onmarkedup & HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS) &&
+ !(s->flags & SRV_F_BACKUP) && s->eweight)
+ srv_shutdown_backup_sessions(s->proxy, SN_ERR_UP);
+
+ /* check if we can handle some connections queued at the proxy. We
+ * will take as many as we can handle.
+ */
+ xferred = pendconn_grab_from_px(s);
+
+ chunk_printf(&trash,
+ "%sServer %s/%s is UP", s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+
+ srv_append_status(&trash, s, reason, xferred, 0);
+ Warning("%s.\n", trash.str);
+ send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
+
+ for (srv = s->trackers; srv; srv = srv->tracknext)
+ srv_set_running(srv, NULL);
+}
+
+/* Marks server <s> stopping regardless of its checks' statuses and provided it
+ * isn't in maintenance. Notifies by all available means, recounts the remaining
+ * servers on the proxy and tries to grab requests from the proxy. It
+ * automatically recomputes the number of servers, but not the map. Maintenance
+ * servers are ignored. It reports <reason> if non-null as the reason for going
+ * up. Note that it makes use of the trash to build the log strings, so <reason>
+ * must not be placed there.
+ */
+void srv_set_stopping(struct server *s, const char *reason)
+{
+ struct server *srv;
+ int xferred;
+
+ if (s->admin & SRV_ADMF_MAINT)
+ return;
+
+ if (s->state == SRV_ST_STOPPING)
+ return;
+
+ s->last_change = now.tv_sec;
+ s->state = SRV_ST_STOPPING;
+ if (s->proxy->lbprm.set_server_status_down)
+ s->proxy->lbprm.set_server_status_down(s);
+
+ /* we might have sessions queued on this server and waiting for
+ * a connection. Those which are redispatchable will be queued
+ * to another server or to the proxy itself.
+ */
+ xferred = pendconn_redistribute(s);
+
+ chunk_printf(&trash,
+ "%sServer %s/%s is stopping", s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+
+ srv_append_status(&trash, s, reason, xferred, 0);
+
+ Warning("%s.\n", trash.str);
+ send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
+
+ if (!s->proxy->srv_bck && !s->proxy->srv_act)
+ set_backend_down(s->proxy);
+
+ for (srv = s->trackers; srv; srv = srv->tracknext)
+ srv_set_stopping(srv, NULL);
+}
+
+/* Enables admin flag <mode> (among SRV_ADMF_*) on server <s>. This is used to
+ * enforce either maint mode or drain mode. It is not allowed to set more than
+ * one flag at once. The equivalent "inherited" flag is propagated to all
+ * tracking servers. Maintenance mode disables health checks (but not agent
+ * checks). When either the flag is already set or no flag is passed, nothing
+ * is done.
+ */
+void srv_set_admin_flag(struct server *s, enum srv_admin mode)
+{
+ struct check *check = &s->check;
+ struct server *srv;
+ int xferred;
+
+ if (!mode)
+ return;
+
+ /* stop going down as soon as we meet a server already in the same state */
+ if (s->admin & mode)
+ return;
+
+ s->admin |= mode;
+
+ /* stop going down if the equivalent flag was already present (forced or inherited) */
+ if (((mode & SRV_ADMF_MAINT) && (s->admin & ~mode & SRV_ADMF_MAINT)) ||
+ ((mode & SRV_ADMF_DRAIN) && (s->admin & ~mode & SRV_ADMF_DRAIN)))
+ return;
+
+ /* Maintenance must also disable health checks */
+ if (mode & SRV_ADMF_MAINT) {
+ if (s->check.state & CHK_ST_ENABLED) {
+ s->check.state |= CHK_ST_PAUSED;
+ check->health = 0;
+ }
+
+ if (s->state == SRV_ST_STOPPED) { /* server was already down */
+ chunk_printf(&trash,
+ "%sServer %s/%s was DOWN and now enters maintenance",
+ s->flags & SRV_F_BACKUP ? "Backup " : "", s->proxy->id, s->id);
+
+ srv_append_status(&trash, s, NULL, -1, (mode & SRV_ADMF_FMAINT));
+
+ Warning("%s.\n", trash.str);
+ send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
+ }
+ else { /* server was still running */
+ int srv_was_stopping = (s->state == SRV_ST_STOPPING) || (s->admin & SRV_ADMF_DRAIN);
+ int prev_srv_count = s->proxy->srv_bck + s->proxy->srv_act;
+
+ check->health = 0; /* failure */
+ s->last_change = now.tv_sec;
+ s->state = SRV_ST_STOPPED;
+ if (s->proxy->lbprm.set_server_status_down)
+ s->proxy->lbprm.set_server_status_down(s);
+
+ if (s->onmarkeddown & HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS)
+ srv_shutdown_sessions(s, SN_ERR_DOWN);
+
+ /* we might have sessions queued on this server and waiting for
+ * a connection. Those which are redispatchable will be queued
+ * to another server or to the proxy itself.
+ */
+ xferred = pendconn_redistribute(s);
+
+ chunk_printf(&trash,
+ "%sServer %s/%s is going DOWN for maintenance",
+ s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+
+ srv_append_status(&trash, s, NULL, xferred, (mode & SRV_ADMF_FMAINT));
+
+ Warning("%s.\n", trash.str);
+ send_log(s->proxy, srv_was_stopping ? LOG_NOTICE : LOG_ALERT, "%s.\n", trash.str);
+
+ if (prev_srv_count && s->proxy->srv_bck == 0 && s->proxy->srv_act == 0)
+ set_backend_down(s->proxy);
+
+ s->counters.down_trans++;
+ }
+ }
+
+ /* drain state is applied only if not yet in maint */
+ if ((mode & SRV_ADMF_DRAIN) && !(s->admin & SRV_ADMF_MAINT)) {
+ int prev_srv_count = s->proxy->srv_bck + s->proxy->srv_act;
+
+ s->last_change = now.tv_sec;
+ if (s->proxy->lbprm.set_server_status_down)
+ s->proxy->lbprm.set_server_status_down(s);
+
+ /* we might have sessions queued on this server and waiting for
+ * a connection. Those which are redispatchable will be queued
+ * to another server or to the proxy itself.
+ */
+ xferred = pendconn_redistribute(s);
+
+ chunk_printf(&trash, "%sServer %s/%s enters drain state",
+ s->flags & SRV_F_BACKUP ? "Backup " : "", s->proxy->id, s->id);
+
+ srv_append_status(&trash, s, NULL, xferred, (mode & SRV_ADMF_FDRAIN));
+
+ Warning("%s.\n", trash.str);
+ send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
+
+ if (prev_srv_count && s->proxy->srv_bck == 0 && s->proxy->srv_act == 0)
+ set_backend_down(s->proxy);
+ }
+
+ /* compute the inherited flag to propagate */
+ if (mode & SRV_ADMF_MAINT)
+ mode = SRV_ADMF_IMAINT;
+ else if (mode & SRV_ADMF_DRAIN)
+ mode = SRV_ADMF_IDRAIN;
+
+ for (srv = s->trackers; srv; srv = srv->tracknext)
+ srv_set_admin_flag(srv, mode);
+}
+
+/* Disables admin flag <mode> (among SRV_ADMF_*) on server <s>. This is used to
+ * stop enforcing either maint mode or drain mode. It is not allowed to set more
+ * than one flag at once. The equivalent "inherited" flag is propagated to all
+ * tracking servers. Leaving maintenance mode re-enables health checks. When
+ * either the flag is already cleared or no flag is passed, nothing is done.
+ */
+void srv_clr_admin_flag(struct server *s, enum srv_admin mode)
+{
+ struct check *check = &s->check;
+ struct server *srv;
+ int xferred = -1;
+
+ if (!mode)
+ return;
+
+ /* stop going down as soon as we see the flag is not there anymore */
+ if (!(s->admin & mode))
+ return;
+
+ s->admin &= ~mode;
+
+ if (s->admin & SRV_ADMF_MAINT) {
+ /* remaining in maintenance mode, let's inform precisely about the
+ * situation.
+ */
+ if (mode & SRV_ADMF_FMAINT) {
+ chunk_printf(&trash,
+ "%sServer %s/%s is leaving forced maintenance but remains in maintenance",
+ s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+
+ if (s->track) /* normally it's mandatory here */
+ chunk_appendf(&trash, " via %s/%s",
+ s->track->proxy->id, s->track->id);
+ Warning("%s.\n", trash.str);
+ send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
+ }
+ else if (mode & SRV_ADMF_IMAINT) {
+ chunk_printf(&trash,
+ "%sServer %s/%s remains in forced maintenance",
+ s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+ Warning("%s.\n", trash.str);
+ send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
+ }
+ /* don't report anything when leaving drain mode and remaining in maintenance */
+ }
+ else if (mode & SRV_ADMF_MAINT) {
+ /* OK here we're leaving maintenance, we have many things to check,
+ * because the server might possibly be coming back up depending on
+ * its state. In practice, leaving maintenance means that we should
+ * immediately turn to UP (more or less the slowstart) under the
+ * following conditions :
+ * - server is neither checked nor tracked
+ * - server tracks another server which is not checked
+ * - server tracks another server which is already up
+ * Which sums up as something simpler :
+ * "either the tracking server is up or the server's checks are disabled
+ * or up". Otherwise we only re-enable health checks. There's a special
+ * case associated to the stopping state which can be inherited. Note
+ * that the server might still be in drain mode, which is naturally dealt
+ * with by the lower level functions.
+ */
+
+ if (s->check.state & CHK_ST_ENABLED) {
+ s->check.state &= ~CHK_ST_PAUSED;
+ check->health = check->rise; /* start OK but check immediately */
+ }
+
+ if ((!s->track || s->track->state != SRV_ST_STOPPED) &&
+ (!(s->agent.state & CHK_ST_ENABLED) || (s->agent.health >= s->agent.rise)) &&
+ (!(s->check.state & CHK_ST_ENABLED) || (s->check.health >= s->check.rise))) {
+ if (s->proxy->srv_bck == 0 && s->proxy->srv_act == 0) {
+ if (s->proxy->last_change < now.tv_sec) // ignore negative times
+ s->proxy->down_time += now.tv_sec - s->proxy->last_change;
+ s->proxy->last_change = now.tv_sec;
+ }
+
+ if (s->last_change < now.tv_sec) // ignore negative times
+ s->down_time += now.tv_sec - s->last_change;
+ s->last_change = now.tv_sec;
+
+ if (s->track && s->track->state == SRV_ST_STOPPING)
+ s->state = SRV_ST_STOPPING;
+ else {
+ s->state = SRV_ST_STARTING;
+ if (s->slowstart > 0)
+ task_schedule(s->warmup, tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20))));
+ else
+ s->state = SRV_ST_RUNNING;
+ }
+
+ server_recalc_eweight(s);
+
+ /* If the server is set with "on-marked-up shutdown-backup-sessions",
+ * and it's not a backup server and its effective weight is > 0,
+ * then it can accept new connections, so we shut down all sessions
+ * on all backup servers.
+ */
+ if ((s->onmarkedup & HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS) &&
+ !(s->flags & SRV_F_BACKUP) && s->eweight)
+ srv_shutdown_backup_sessions(s->proxy, SN_ERR_UP);
+
+ /* check if we can handle some connections queued at the proxy. We
+ * will take as many as we can handle.
+ */
+ xferred = pendconn_grab_from_px(s);
+ }
+
+ if (mode & SRV_ADMF_FMAINT) {
+ chunk_printf(&trash,
+ "%sServer %s/%s is %s/%s (leaving forced maintenance)",
+ s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id,
+ (s->state == SRV_ST_STOPPED) ? "DOWN" : "UP",
+ (s->admin & SRV_ADMF_DRAIN) ? "DRAIN" : "READY");
+ }
+ else {
+ chunk_printf(&trash,
+ "%sServer %s/%s is %s/%s (leaving maintenance)",
+ s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id,
+ (s->state == SRV_ST_STOPPED) ? "DOWN" : "UP",
+ (s->admin & SRV_ADMF_DRAIN) ? "DRAIN" : "READY");
+ srv_append_status(&trash, s, NULL, xferred, 0);
+ }
+ Warning("%s.\n", trash.str);
+ send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
+ }
+ else if ((mode & SRV_ADMF_DRAIN) && (s->admin & SRV_ADMF_DRAIN)) {
+ /* remaining in drain mode after removing one of its flags */
+
+ if (mode & SRV_ADMF_FDRAIN) {
+ chunk_printf(&trash,
+ "%sServer %s/%s is leaving forced drain but remains in drain mode",
+ s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+
+ if (s->track) /* normally it's mandatory here */
+ chunk_appendf(&trash, " via %s/%s",
+ s->track->proxy->id, s->track->id);
+ }
+ else {
+ chunk_printf(&trash,
+ "%sServer %s/%s remains in forced drain mode",
+ s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id);
+ }
+ Warning("%s.\n", trash.str);
+ send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
+ }
+ else if (mode & SRV_ADMF_DRAIN) {
+ /* OK completely leaving drain mode */
+ if (s->proxy->srv_bck == 0 && s->proxy->srv_act == 0) {
+ if (s->proxy->last_change < now.tv_sec) // ignore negative times
+ s->proxy->down_time += now.tv_sec - s->proxy->last_change;
+ s->proxy->last_change = now.tv_sec;
+ }
+
+ if (s->last_change < now.tv_sec) // ignore negative times
+ s->down_time += now.tv_sec - s->last_change;
+ s->last_change = now.tv_sec;
+ server_recalc_eweight(s);
+
+ if (mode & SRV_ADMF_FDRAIN) {
+ chunk_printf(&trash,
+ "%sServer %s/%s is %s (leaving forced drain)",
+ s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id,
+ (s->state == SRV_ST_STOPPED) ? "DOWN" : "UP");
+ }
+ else {
+ chunk_printf(&trash,
+ "%sServer %s/%s is %s (leaving drain)",
+ s->flags & SRV_F_BACKUP ? "Backup " : "",
+ s->proxy->id, s->id,
+ (s->state == SRV_ST_STOPPED) ? "DOWN" : "UP");
+ if (s->track) /* normally it's mandatory here */
+ chunk_appendf(&trash, " via %s/%s",
+ s->track->proxy->id, s->track->id);
+ }
+ Warning("%s.\n", trash.str);
+ send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
+ }
+
+ /* stop going down if the equivalent flag is still present (forced or inherited) */
+ if (((mode & SRV_ADMF_MAINT) && (s->admin & SRV_ADMF_MAINT)) ||
+ ((mode & SRV_ADMF_DRAIN) && (s->admin & SRV_ADMF_DRAIN)))
+ return;
+
+ if (mode & SRV_ADMF_MAINT)
+ mode = SRV_ADMF_IMAINT;
+ else if (mode & SRV_ADMF_DRAIN)
+ mode = SRV_ADMF_IDRAIN;
+
+ for (srv = s->trackers; srv; srv = srv->tracknext)
+ srv_clr_admin_flag(srv, mode);
+}
+
/* Note: must not be declared <const> as its list will be overwritten.
* Please take care of keeping this list alphabetically sorted, doing so helps
* all code contributors.
@@ -185,13 +722,14 @@
if (now.tv_sec < sv->last_change || now.tv_sec >= sv->last_change + sv->slowstart) {
/* go to full throttle if the slowstart interval is reached */
- sv->state &= ~SRV_WARMINGUP;
+ if (sv->state == SRV_ST_STARTING)
+ sv->state = SRV_ST_RUNNING;
}
/* We must take care of not pushing the server to full throttle during slow starts.
* It must also start immediately, at least at the minimal step when leaving maintenance.
*/
- if ((sv->state & SRV_WARMINGUP) && (px->lbprm.algo & BE_LB_PROP_DYN))
+ if ((sv->state == SRV_ST_STARTING) && (px->lbprm.algo & BE_LB_PROP_DYN))
w = (px->lbprm.wdiv * (now.tv_sec - sv->last_change) + sv->slowstart) / sv->slowstart;
else
w = px->lbprm.wdiv;
@@ -201,7 +739,7 @@
/* now propagate the status change to any LB algorithms */
if (px->lbprm.update_server_eweight)
px->lbprm.update_server_eweight(sv);
- else if (sv->eweight) {
+ else if (srv_is_usable(sv)) {
if (px->lbprm.set_server_status_up)
px->lbprm.set_server_status_up(sv);
}
@@ -345,7 +883,9 @@
LIST_INIT(&newsrv->pendconns);
do_check = 0;
do_agent = 0;
- newsrv->state = SRV_RUNNING; /* early server setup */
+ newsrv->flags = 0;
+ newsrv->admin = 0;
+ newsrv->state = SRV_ST_RUNNING; /* early server setup */
newsrv->last_change = now.tv_sec;
newsrv->id = strdup(args[1]);
@@ -373,7 +913,7 @@
if (!port1 || !port2) {
/* no port specified, +offset, -offset */
- newsrv->state |= SRV_MAPPORTS;
+ newsrv->flags |= SRV_F_MAPPORTS;
}
else if (port1 != port2) {
/* port range */
@@ -605,11 +1145,11 @@
cur_arg += 2;
}
else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
- newsrv->state |= SRV_BACKUP;
+ newsrv->flags |= SRV_F_BACKUP;
cur_arg ++;
}
else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
- newsrv->state |= SRV_NON_STICK;
+ newsrv->flags |= SRV_F_NON_STICK;
cur_arg ++;
}
else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
@@ -679,8 +1219,8 @@
cur_arg += 1;
}
else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
- newsrv->state |= SRV_MAINTAIN;
- newsrv->state &= ~SRV_RUNNING;
+ newsrv->admin |= SRV_ADMF_FMAINT;
+ newsrv->state = SRV_ST_STOPPED;
newsrv->check.state |= CHK_ST_PAUSED;
newsrv->check.health = 0;
newsrv->agent.health = 0;
@@ -1026,9 +1566,6 @@
}
}
- /* Set initial drain state using now-configured weight */
- set_server_drain_state(newsrv);
-
if (do_check) {
int ret;
@@ -1141,12 +1678,12 @@
}
if (!defsrv) {
- if (newsrv->state & SRV_BACKUP)
+ if (newsrv->flags & SRV_F_BACKUP)
curproxy->srv_bck++;
else
curproxy->srv_act++;
- newsrv->prev_state = newsrv->state;
+ srv_lb_commit_status(newsrv);
}
}
return 0;
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/session.c
^
|
@@ -1375,7 +1375,7 @@
if (ret) {
struct server *srv = rule->srv.ptr;
- if ((srv->state & SRV_RUNNING) ||
+ if ((srv->state != SRV_ST_STOPPED) ||
(px->options & PR_O_PERSIST) ||
(s->flags & SN_FORCE_PRST)) {
s->flags |= SN_DIRECT | SN_ASSIGNED;
@@ -1460,7 +1460,7 @@
struct server *srv;
srv = container_of(node, struct server, conf.id);
- if ((srv->state & SRV_RUNNING) ||
+ if ((srv->state != SRV_ST_STOPPED) ||
(px->options & PR_O_PERSIST) ||
(s->flags & SN_FORCE_PRST)) {
s->flags |= SN_DIRECT | SN_ASSIGNED;
@@ -1565,7 +1565,7 @@
struct stksess *ts;
void *ptr;
- if (objt_server(s->target) && objt_server(s->target)->state & SRV_NON_STICK) {
+ if (objt_server(s->target) && objt_server(s->target)->flags & SRV_F_NON_STICK) {
stksess_free(s->store[i].table, s->store[i].ts);
s->store[i].ts = NULL;
continue;
@@ -1619,6 +1619,7 @@
unsigned int rq_prod_last, rq_cons_last;
unsigned int rp_cons_last, rp_prod_last;
unsigned int req_ana_back;
+ unsigned int rq_oneshot, rp_oneshot;
//DPRINTF(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
// s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s->rep->flags);
@@ -1626,9 +1627,13 @@
/* this data may be no longer valid, clear it */
memset(&s->txn.auth, 0, sizeof(s->txn.auth));
- /* This flag must explicitly be set every time */
- s->req->flags &= ~(CF_READ_NOEXP|CF_WAKE_WRITE);
- s->rep->flags &= ~(CF_READ_NOEXP|CF_WAKE_WRITE);
+ /* These flags must explicitly be set every time by the analysers who
+ * need them, but we won't always call them (eg: during a connection
+ * retry). So we need to keep them and only clear them if we're sure
+ * to call the analysers.
+ */
+ rq_oneshot = s->req->flags & (CF_READ_NOEXP | CF_WAKE_WRITE);
+ rp_oneshot = s->rep->flags & (CF_READ_NOEXP | CF_WAKE_WRITE);
/* Keep a copy of req/rep flags so that we can detect shutdowns */
rqf_last = s->req->flags & ~CF_MASK_ANALYSER;
@@ -1809,6 +1814,8 @@
s->si[1].state != rq_cons_last) {
unsigned int flags = s->req->flags;
+ s->req->flags &= ~rq_oneshot;
+ rq_oneshot = 0;
if (s->req->prod->state >= SI_ST_EST) {
int max_loops = global.tune.maxpollevents;
unsigned int ana_list;
@@ -1962,11 +1969,13 @@
/* Analyse response */
if (((s->rep->flags & ~rpf_last) & CF_MASK_ANALYSER) ||
- (s->rep->flags ^ rpf_last) & CF_MASK_STATIC ||
- s->si[0].state != rp_cons_last ||
- s->si[1].state != rp_prod_last) {
+ ((s->rep->flags ^ rpf_last) & CF_MASK_STATIC) ||
+ s->si[0].state != rp_cons_last ||
+ s->si[1].state != rp_prod_last) {
unsigned int flags = s->rep->flags;
+ s->rep->flags &= ~rp_oneshot;
+ rp_oneshot = 0;
if ((s->rep->flags & CF_MASK_ANALYSER) &&
(s->rep->analysers & AN_REQ_WAIT_HTTP)) {
/* Due to HTTP pipelining, the HTTP request analyser might be waiting
@@ -2160,6 +2169,9 @@
channel_auto_close(s->req);
buffer_flush(s->req->buf);
+ s->req->flags &= ~rq_oneshot;
+ rq_oneshot = 0;
+
/* We'll let data flow between the producer (if still connected)
* to the consumer (which might possibly not be connected yet).
*/
@@ -2315,6 +2327,9 @@
channel_auto_close(s->rep);
buffer_flush(s->rep->buf);
+ s->rep->flags &= ~rp_oneshot;
+ rp_oneshot = 0;
+
/* We'll let data flow between the producer (if still connected)
* to the consumer.
*/
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/shctx.c
^
|
@@ -18,16 +18,14 @@
#else
#ifdef USE_SYSCALL_FUTEX
#include <unistd.h>
-#ifndef u32
-#define u32 unsigned int
-#endif
#include <linux/futex.h>
#include <sys/syscall.h>
#endif
#endif
#endif
#include <arpa/inet.h>
-#include "ebmbtree.h"
+#include <ebmbtree.h>
+#include <types/global.h>
#include "proto/shctx.h"
struct shsess_packet_hdr {
@@ -440,6 +438,8 @@
int data_len;
SSL_SESSION *sess;
+ global.shctx_lookups++;
+
/* allow the session to be freed automatically by openssl */
*do_copy = 0;
@@ -458,6 +458,7 @@
if (!shsess) {
/* no session found: unlock cache and exit */
shared_context_unlock();
+ global.shctx_misses++;
return NULL;
}
|
[-]
[+]
|
Changed |
_service:download_url:haproxy-1.5-dev26.tar.gz/src/ssl_sock.c
^
|
@@ -728,7 +728,7 @@
{
int cfgerr = 0;
int verify = SSL_VERIFY_NONE;
- int ssloptions =
+ long ssloptions =
SSL_OP_ALL | /* all known workarounds for bugs */
SSL_OP_NO_SSLv2 |
SSL_OP_NO_COMPRESSION |
@@ -736,7 +736,7 @@
SSL_OP_SINGLE_ECDH_USE |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
SSL_OP_CIPHER_SERVER_PREFERENCE;
- int sslmode =
+ long sslmode =
SSL_MODE_ENABLE_PARTIAL_WRITE |
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
SSL_MODE_RELEASE_BUFFERS;
@@ -995,11 +995,11 @@
int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
{
int cfgerr = 0;
- int options =
+ long options =
SSL_OP_ALL | /* all known workarounds for bugs */
SSL_OP_NO_SSLv2 |
SSL_OP_NO_COMPRESSION;
- int mode =
+ long mode =
SSL_MODE_ENABLE_PARTIAL_WRITE |
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
SSL_MODE_RELEASE_BUFFERS;
@@ -1447,14 +1447,23 @@
reneg_ok:
/* Handshake succeeded */
- if (objt_server(conn->target)) {
- if (!SSL_session_reused(conn->xprt_ctx)) {
+ if (!SSL_session_reused(conn->xprt_ctx)) {
+ if (objt_server(conn->target)) {
+ update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
+ if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
+ global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
+
/* check if session was reused, if not store current session on server for reuse */
if (objt_server(conn->target)->ssl_ctx.reused_sess)
SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
objt_server(conn->target)->ssl_ctx.reused_sess = SSL_get1_session(conn->xprt_ctx);
}
+ else {
+ update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
+ if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
+ global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
+ }
}
/* The connection is now established at both layers, it's time to leave */
|