From ebcd4844e82a4198ea5d98fe491a46267da1d1ec Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 19 Jun 2015 11:59:02 +0200 Subject: [PATCH] MEDIUM: vars: move the session variables to the session, not the stream It's important that the session-wide variables are in the session and not in the stream. --- include/proto/vars.h | 1 + include/types/session.h | 2 ++ src/session.c | 3 +++ src/stream.c | 6 ++--- src/vars.c | 49 ++++++++++++++++++++++++++++++++--------- 5 files changed, 46 insertions(+), 15 deletions(-) diff --git a/include/proto/vars.h b/include/proto/vars.h index e1092c75a..4c8582565 100644 --- a/include/proto/vars.h +++ b/include/proto/vars.h @@ -5,6 +5,7 @@ void vars_init(struct vars *vars, enum vars_scope scope); void vars_prune(struct vars *vars, struct stream *strm); +void vars_prune_per_sess(struct vars *vars); int vars_get_by_name(const char *name, size_t len, struct stream *strm, struct sample *smp); void vars_set_by_name(const char *name, size_t len, struct stream *strm, struct sample *smp); int vars_check_arg(struct arg *arg, char **err); diff --git a/include/types/session.h b/include/types/session.h index d02e57fef..62c3a95fe 100644 --- a/include/types/session.h +++ b/include/types/session.h @@ -35,6 +35,7 @@ #include #include #include +#include struct session { struct proxy *fe; /* the proxy this session depends on for the client side */ @@ -43,6 +44,7 @@ struct session { struct timeval accept_date; /* date of the session's accept() in user date */ struct timeval tv_accept; /* date of the session's accept() in internal date (monotonic) */ struct stkctr stkctr[MAX_SESS_STKCTR]; /* stick counters for tcp-connection */ + struct vars vars; /* list of variables for the session scope. */ }; #endif /* _TYPES_SESSION_H */ diff --git a/src/session.c b/src/session.c index 7189fbeeb..44fccbf1d 100644 --- a/src/session.c +++ b/src/session.c @@ -27,6 +27,7 @@ #include #include #include +#include struct pool_head *pool2_session; @@ -59,6 +60,7 @@ struct session *session_new(struct proxy *fe, struct listener *li, enum obj_type sess->accept_date = date; /* user-visible date for logging */ sess->tv_accept = now; /* corrected date for internal use */ memset(sess->stkctr, 0, sizeof(sess->stkctr)); + vars_init(&sess->vars, SCOPE_SESS); } return sess; } @@ -66,6 +68,7 @@ struct session *session_new(struct proxy *fe, struct listener *li, enum obj_type void session_free(struct session *sess) { session_store_counters(sess); + vars_prune_per_sess(&sess->vars); pool_free2(pool2_session, sess); } diff --git a/src/stream.c b/src/stream.c index 0a38f2e99..10038268d 100644 --- a/src/stream.c +++ b/src/stream.c @@ -137,10 +137,9 @@ struct stream *stream_new(struct session *sess, struct task *t, enum obj_type *o s->req_cap = NULL; s->res_cap = NULL; - /* Initialise alle the variable context even if will not use. - * This permits to prune these context without errors. + /* Initialise all the variables contexts even if not used. + * This permits to prune these contexts without errors. */ - vars_init(&s->vars_sess, SCOPE_SESS); vars_init(&s->vars_txn, SCOPE_TXN); vars_init(&s->vars_reqres, SCOPE_REQ); @@ -302,7 +301,6 @@ static void stream_free(struct stream *s) } /* Cleanup all variable contexts. */ - vars_prune(&s->vars_sess, s); vars_prune(&s->vars_txn, s); vars_prune(&s->vars_reqres, s); diff --git a/src/vars.c b/src/vars.c index 9662abe31..fa521f35e 100644 --- a/src/vars.c +++ b/src/vars.c @@ -10,6 +10,7 @@ #include #include #include +#include /* This contains a pool of struct vars */ static struct pool_head *var_pool = NULL; @@ -93,7 +94,33 @@ void vars_prune(struct vars *vars, struct stream *strm) pool_free2(var_pool, var); size += sizeof(struct var); } - var_accounting_diff(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, -size); + var_accounting_diff(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, -size); +} + +/* This function frees all the memory used by all the session variables in the + * list starting at . + */ +void vars_prune_per_sess(struct vars *vars) +{ + struct var *var, *tmp; + unsigned int size = 0; + + list_for_each_entry_safe(var, tmp, &vars->head, l) { + if (var->data.type == SMP_T_STR || + var->data.type == SMP_T_BIN) { + free(var->data.data.str.str); + size += var->data.data.str.len; + } + else if (var->data.type == SMP_T_METH) { + free(var->data.data.meth.str.str); + size += var->data.data.meth.str.len; + } + LIST_DEL(&var->l); + pool_free2(var_pool, var); + size += sizeof(struct var); + } + vars->size -= size; + var_global_size -= size; } /* This function init a list of variabes. */ @@ -207,7 +234,7 @@ static int smp_fetch_var(const struct arg *args, struct sample *smp, const char /* Check the availibity of the variable. */ switch (var_desc->scope) { - case SCOPE_SESS: vars = &smp->strm->vars_sess; break; + case SCOPE_SESS: vars = &smp->strm->sess->vars; break; case SCOPE_TXN: vars = &smp->strm->vars_txn; break; case SCOPE_REQ: case SCOPE_RES: @@ -245,16 +272,16 @@ static int sample_store(struct vars *vars, const char *name, struct stream *strm if (var->data.type == SMP_T_STR || var->data.type == SMP_T_BIN) { free(var->data.data.str.str); - var_accounting_diff(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, -var->data.data.str.len); + var_accounting_diff(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, -var->data.data.str.len); } else if (var->data.type == SMP_T_METH) { free(var->data.data.meth.str.str); - var_accounting_diff(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, -var->data.data.meth.str.len); + var_accounting_diff(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, -var->data.data.meth.str.len); } } else { /* Check memory avalaible. */ - if (!var_accounting_add(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, sizeof(struct var))) + if (!var_accounting_add(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, sizeof(struct var))) return 0; /* Create new entry. */ @@ -283,13 +310,13 @@ static int sample_store(struct vars *vars, const char *name, struct stream *strm break; case SMP_T_STR: case SMP_T_BIN: - if (!var_accounting_add(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, smp->data.str.len)) { + if (!var_accounting_add(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, smp->data.str.len)) { var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */ return 0; } var->data.data.str.str = malloc(smp->data.str.len); if (!var->data.data.str.str) { - var_accounting_diff(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, -smp->data.str.len); + var_accounting_diff(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, -smp->data.str.len); var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */ return 0; } @@ -297,13 +324,13 @@ static int sample_store(struct vars *vars, const char *name, struct stream *strm memcpy(var->data.data.str.str, smp->data.str.str, var->data.data.str.len); break; case SMP_T_METH: - if (!var_accounting_add(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, smp->data.meth.str.len)) { + if (!var_accounting_add(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, smp->data.meth.str.len)) { var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */ return 0; } var->data.data.meth.str.str = malloc(smp->data.meth.str.len); if (!var->data.data.meth.str.str) { - var_accounting_diff(vars, &strm->vars_sess, &strm->vars_txn, &strm->vars_reqres, -smp->data.meth.str.len); + var_accounting_diff(vars, &strm->sess->vars, &strm->vars_txn, &strm->vars_reqres, -smp->data.meth.str.len); var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */ return 0; } @@ -323,7 +350,7 @@ static inline int sample_store_stream(const char *name, enum vars_scope scope, struct vars *vars; switch (scope) { - case SCOPE_SESS: vars = &strm->vars_sess; break; + case SCOPE_SESS: vars = &strm->sess->vars; break; case SCOPE_TXN: vars = &strm->vars_txn; break; case SCOPE_REQ: case SCOPE_RES: @@ -399,7 +426,7 @@ int vars_get_by_name(const char *name, size_t len, struct stream *strm, struct s /* Select "vars" pool according with the scope. */ switch (scope) { - case SCOPE_SESS: vars = &strm->vars_sess; break; + case SCOPE_SESS: vars = &strm->sess->vars; break; case SCOPE_TXN: vars = &strm->vars_txn; break; case SCOPE_REQ: case SCOPE_RES: