MINOR: checks/vars: Add a check scope for variables

Add a dedicated vars scope for checks. This scope is considered as part of the
session scope for accounting purposes.

The scope can be addressed by a valid session, even embryonic. The stream is not
necessary.

The scope is initialized after the check session is created. All variables are
then pruned before the session is destroyed.
This commit is contained in:
Gaetan Rivet 2020-02-21 18:13:44 +01:00 committed by Christopher Faulet
parent 05d692dc09
commit 13a5043a9e
5 changed files with 46 additions and 3 deletions

View File

@ -26,6 +26,8 @@
#include <common/config.h>
#include <types/mailers.h>
#include <types/action.h>
const char *get_check_status_description(short check_status);
const char *get_check_status_info(short check_status);
void __health_adjust(struct server *s, short status);

View File

@ -159,6 +159,7 @@ enum {
struct check {
struct session *sess; /* Health check session. */
struct vars vars; /* Health check dynamic variables. */
struct xprt_ops *xprt; /* transport layer operations for health checks */
struct conn_stream *cs; /* conn_stream state for health checks */
struct buffer bi, bo; /* input and output buffers to send/recv check */

View File

@ -12,6 +12,7 @@ enum vars_scope {
SCOPE_REQ,
SCOPE_RES,
SCOPE_PROC,
SCOPE_CHECK,
};
struct vars {

View File

@ -58,6 +58,7 @@
#include <proto/signal.h>
#include <proto/stream_interface.h>
#include <proto/task.h>
#include <proto/vars.h>
#include <proto/log.h>
#include <proto/dns.h>
#include <proto/proto_udp.h>
@ -3224,12 +3225,13 @@ static int tcpcheck_main(struct check *check)
}
else {
/* First evaluation, create a session */
check->sess = session_new(&checks_fe, NULL, NULL);
check->sess = session_new(&checks_fe, NULL, (check->server ? &check->server->obj_type : NULL));
if (!check->sess) {
chunk_printf(&trash, "TCPCHK error allocating check session");
set_server_check_status(check, HCHK_STATUS_SOCKERR, trash.area);
goto out_end_tcpcheck;
}
vars_init(&check->vars, SCOPE_CHECK);
rule = LIST_NEXT(check->tcpcheck_rules, typeof(rule), list);
}
@ -3339,12 +3341,12 @@ static int tcpcheck_main(struct check *check)
/* cleanup before leaving */
check->current_step = NULL;
if (check->sess != NULL) {
vars_prune(&check->vars, check->sess, NULL);
session_free(check->sess);
check->sess = NULL;
}
out:
return retcode;
}
static const char *init_check(struct check *check, int type)

View File

@ -14,6 +14,7 @@
#include <proto/stream.h>
#include <proto/tcp_rules.h>
#include <proto/vars.h>
#include <proto/checks.h>
/* This contains a pool of struct vars */
DECLARE_STATIC_POOL(var_pool, "vars", sizeof(struct var));
@ -33,6 +34,7 @@ static unsigned int var_proc_limit = 0;
static unsigned int var_sess_limit = 0;
static unsigned int var_txn_limit = 0;
static unsigned int var_reqres_limit = 0;
static unsigned int var_check_limit = 0;
__decl_rwlock(var_names_rwlock);
@ -46,6 +48,11 @@ static inline struct vars *get_vars(struct session *sess, struct stream *strm, e
return &global.vars;
case SCOPE_SESS:
return &sess->vars;
case SCOPE_CHECK: {
struct server *srv = objt_server(sess->origin);
return srv ? &srv->check.vars : NULL;
}
case SCOPE_TXN:
return strm ? &strm->vars_txn : NULL;
case SCOPE_REQ:
@ -69,7 +76,15 @@ static void var_accounting_diff(struct vars *vars, struct session *sess, struct
case SCOPE_TXN:
if (strm)
_HA_ATOMIC_ADD(&strm->vars_txn.size, size);
goto scope_sess;
case SCOPE_CHECK: {
struct server *srv = objt_server(sess->origin);
if (srv != NULL)
_HA_ATOMIC_ADD(&srv->check.vars.size, size);
}
/* fall through */
scope_sess:
case SCOPE_SESS:
_HA_ATOMIC_ADD(&sess->vars.size, size);
/* fall through */
@ -97,7 +112,16 @@ static int var_accounting_add(struct vars *vars, struct session *sess, struct st
case SCOPE_TXN:
if (var_txn_limit && strm && strm->vars_txn.size + size > var_txn_limit)
return 0;
goto scope_sess;
case SCOPE_CHECK: {
struct server *srv = objt_server(sess->origin);
if (var_check_limit && srv &&
srv->check.vars.size + size > var_check_limit)
return 0;
}
/* fall through */
scope_sess:
case SCOPE_SESS:
if (var_sess_limit && sess->vars.size + size > var_sess_limit)
return 0;
@ -226,9 +250,14 @@ static char *register_name(const char *name, int len, enum vars_scope *scope,
len -= 4;
*scope = SCOPE_RES;
}
else if (len > 6 && strncmp(name, "check.", 6) == 0) {
name += 6;
len -= 6;
*scope = SCOPE_CHECK;
}
else {
memprintf(err, "invalid variable name '%s'. A variable name must be start by its scope. "
"The scope can be 'proc', 'sess', 'txn', 'req' or 'res'", name);
"The scope can be 'proc', 'sess', 'txn', 'req', 'res' or 'check'", name);
return res;
}
@ -827,6 +856,13 @@ static int vars_max_size_reqres(char **args, int section_type, struct proxy *cur
return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_reqres_limit);
}
static int vars_max_size_check(char **args, int section_type, struct proxy *curpx,
struct proxy *defpx, const char *file, int line,
char **err)
{
return vars_max_size(args, section_type, curpx, defpx, file, line, err, &var_check_limit);
}
static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
{ "var", smp_fetch_var, ARG1(1,STR), smp_check_var, SMP_T_STR, SMP_USE_L4CLI },
@ -897,6 +933,7 @@ static struct cfg_kw_list cfg_kws = {{ },{
{ CFG_GLOBAL, "tune.vars.sess-max-size", vars_max_size_sess },
{ CFG_GLOBAL, "tune.vars.txn-max-size", vars_max_size_txn },
{ CFG_GLOBAL, "tune.vars.reqres-max-size", vars_max_size_reqres },
{ CFG_GLOBAL, "tune.vars.check-max-size", vars_max_size_check },
{ /* END */ }
}};