MINOR: vars: make vars_get_by_* support an optional default value

In preparation for support default values when fetching variables, we
need to update the internal API to pass an extra argument to functions
vars_get_by_{name,desc} to provide an optional default value. This
patch does this and always passes NULL in this argument. var_to_smp()
was extended to fall back to this value when available.
This commit is contained in:
Willy Tarreau 2021-09-03 11:52:38 +02:00
parent be7e00d134
commit e352b9dac7
4 changed files with 40 additions and 23 deletions

View File

@ -34,11 +34,11 @@ void var_accounting_diff(struct vars *vars, struct session *sess, struct stream
unsigned int var_clear(struct var *var);
void vars_prune(struct vars *vars, struct session *sess, struct stream *strm);
void vars_prune_per_sess(struct vars *vars);
int vars_get_by_name(const char *name, size_t len, struct sample *smp);
int vars_get_by_name(const char *name, size_t len, struct sample *smp, const struct buffer *def);
int vars_set_by_name_ifexist(const char *name, size_t len, struct sample *smp);
int vars_set_by_name(const char *name, size_t len, struct sample *smp);
int vars_unset_by_name_ifexist(const char *name, size_t len, struct sample *smp);
int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp);
int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp, const struct buffer *def);
int vars_check_arg(struct arg *arg, char **err);
#endif

View File

@ -4382,7 +4382,7 @@ __LJMP static int hlua_applet_tcp_get_var(lua_State *L)
s = luactx->htxn.s;
smp_set_owner(&smp, s->be, s->sess, s, 0);
if (!vars_get_by_name(name, len, &smp)) {
if (!vars_get_by_name(name, len, &smp, NULL)) {
lua_pushnil(L);
return 1;
}
@ -4869,7 +4869,7 @@ __LJMP static int hlua_applet_http_get_var(lua_State *L)
s = luactx->htxn.s;
smp_set_owner(&smp, s->be, s->sess, s, 0);
if (!vars_get_by_name(name, len, &smp)) {
if (!vars_get_by_name(name, len, &smp, NULL)) {
lua_pushnil(L);
return 1;
}
@ -6966,7 +6966,7 @@ __LJMP static int hlua_get_var(lua_State *L)
name = MAY_LJMP(luaL_checklstring(L, 2, &len));
smp_set_owner(&smp, htxn->p, htxn->s->sess, htxn->s, htxn->dir & SMP_OPT_DIR);
if (!vars_get_by_name(name, len, &smp)) {
if (!vars_get_by_name(name, len, &smp, NULL)) {
lua_pushnil(L);
return 1;
}

View File

@ -1747,7 +1747,7 @@ static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *
smp->flags = SMP_F_CONST;
return 1;
case ARGT_VAR:
if (!vars_get_by_desc(&arg->data.var, smp))
if (!vars_get_by_desc(&arg->data.var, smp, NULL))
return 0;
if (!sample_casts[smp->data.type][SMP_T_STR])
return 0;
@ -2990,7 +2990,7 @@ static inline int sample_conv_var2smp(const struct arg *arg, struct sample *smp)
smp->data.u.sint = arg->data.sint;
return 1;
case ARGT_VAR:
if (!vars_get_by_desc(&arg->data.var, smp))
if (!vars_get_by_desc(&arg->data.var, smp, NULL))
return 0;
if (!sample_casts[smp->data.type][SMP_T_SINT])
return 0;
@ -3317,7 +3317,7 @@ static int sample_conv_concat(const struct arg *arg_p, struct sample *smp, void
* into a string.
*/
smp_set_owner(&tmp, smp->px, smp->sess, smp->strm, smp->opt);
if (arg_p[1].type == ARGT_VAR && vars_get_by_desc(&arg_p[1].data.var, &tmp) &&
if (arg_p[1].type == ARGT_VAR && vars_get_by_desc(&arg_p[1].data.var, &tmp, NULL) &&
(sample_casts[tmp.data.type][SMP_T_STR] == c_none ||
sample_casts[tmp.data.type][SMP_T_STR](&tmp))) {
@ -3377,7 +3377,7 @@ static int sample_conv_strcmp(const struct arg *arg_p, struct sample *smp, void
smp_set_owner(&tmp, smp->px, smp->sess, smp->strm, smp->opt);
if (arg_p[0].type != ARGT_VAR)
return 0;
if (!vars_get_by_desc(&arg_p[0].data.var, &tmp))
if (!vars_get_by_desc(&arg_p[0].data.var, &tmp, NULL))
return 0;
if (!sample_casts[tmp.data.type][SMP_T_STR](&tmp))
return 0;
@ -3415,7 +3415,7 @@ static int sample_conv_secure_memcmp(const struct arg *arg_p, struct sample *smp
smp_set_owner(&tmp, smp->px, smp->sess, smp->strm, smp->opt);
if (arg_p[0].type != ARGT_VAR)
return 0;
if (!vars_get_by_desc(&arg_p[0].data.var, &tmp))
if (!vars_get_by_desc(&arg_p[0].data.var, &tmp, NULL))
return 0;
if (!sample_casts[tmp.data.type][SMP_T_BIN](&tmp))
return 0;

View File

@ -340,7 +340,7 @@ static int smp_fetch_var(const struct arg *args, struct sample *smp, const char
{
const struct var_desc *var_desc = &args[0].data.var;
return vars_get_by_desc(var_desc, smp);
return vars_get_by_desc(var_desc, smp, NULL);
}
/* This function search in the <head> a variable with the same
@ -574,10 +574,11 @@ int vars_unset_by_name_ifexist(const char *name, size_t len, struct sample *smp)
* release the variables lock ASAP (so a pre-allocated chunk is obtained
* via get_trash_shunk()). The variables' lock is used for reads.
*
* The function returns 0 if the variable was not found, otherwise 1
* with the sample filled.
* The function returns 0 if the variable was not found and no default
* value was provided in <def>, otherwise 1 with the sample filled.
* Default values are always returned as strings.
*/
static int var_to_smp(struct vars *vars, const char *name, struct sample *smp)
static int var_to_smp(struct vars *vars, const char *name, struct sample *smp, const struct buffer *def)
{
struct var *var;
@ -585,12 +586,19 @@ static int var_to_smp(struct vars *vars, const char *name, struct sample *smp)
HA_RWLOCK_RDLOCK(VARS_LOCK, &vars->rwlock);
var = var_get(vars, name);
if (!var) {
HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
return 0;
if (!def) {
HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
return 0;
}
/* not found but we have a default value */
smp->data.type = SMP_T_STR;
smp->data.u.str = *def;
}
else
smp->data = var->data;
/* Copy sample. */
smp->data = var->data;
smp_dup(smp);
HA_RWLOCK_RDUNLOCK(VARS_LOCK, &vars->rwlock);
@ -603,9 +611,13 @@ static int var_to_smp(struct vars *vars, const char *name, struct sample *smp)
* and it therefore uses a pre-allocated trash chunk as returned by
* get_trash_chunk().
*
* If the variable is not valid in this scope, 0 is always returned.
* If the variable is valid but not found, either the default value
* <def> is returned if not NULL, or zero is returned.
*
* Returns 1 if the sample is filled, otherwise it returns 0.
*/
int vars_get_by_name(const char *name, size_t len, struct sample *smp)
int vars_get_by_name(const char *name, size_t len, struct sample *smp, const struct buffer *def)
{
struct vars *vars;
enum vars_scope scope;
@ -620,7 +632,8 @@ int vars_get_by_name(const char *name, size_t len, struct sample *smp)
if (!vars || vars->scope != scope)
return 0;
return var_to_smp(vars, name, smp);
return var_to_smp(vars, name, smp, def);
}
/* This function fills a sample with the content of the variable described
@ -630,9 +643,13 @@ int vars_get_by_name(const char *name, size_t len, struct sample *smp)
* and it therefore uses a pre-allocated trash chunk as returned by
* get_trash_chunk().
*
* If the variable is not valid in this scope, 0 is always returned.
* If the variable is valid but not found, either the default value
* <def> is returned if not NULL, or zero is returned.
*
* Returns 1 if the sample is filled, otherwise it returns 0.
*/
int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp)
int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp, const struct buffer *def)
{
struct vars *vars;
@ -643,7 +660,7 @@ int vars_get_by_desc(const struct var_desc *var_desc, struct sample *smp)
if (!vars || vars->scope != var_desc->scope)
return 0;
return var_to_smp(vars, var_desc->name, smp);
return var_to_smp(vars, var_desc->name, smp, def);
}
/* Always returns ACT_RET_CONT even if an error occurs. */
@ -739,7 +756,7 @@ static void release_store_rule(struct act_rule *rule)
/* This two function checks the variable name and replace the
* configuration string name by the global string name. its
* the same string, but the global pointer can be easy to
* compare.
* compare. They return non-zero on success, zero on failure.
*
* The first function checks a sample-fetch and the second
* checks a converter.
@ -989,7 +1006,7 @@ static int vars_parse_cli_get_var(char **args, char *payload, struct appctx *app
if (!vars || vars->scope != SCOPE_PROC)
return 0;
if (!vars_get_by_name(args[2], strlen(args[2]), &smp))
if (!vars_get_by_name(args[2], strlen(args[2]), &smp, NULL))
return cli_err(appctx, "Variable not found.\n");
/* the sample returned by vars_get_by_name() is allocated into a trash