mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-18 09:24:31 +00:00
MINOR: vars: Parse optional conditions passed to the set-var converter
This patch adds the parsing of the optional condition parameters that can be passed to the set-var converter. Those conditions will not be taken into account yet in the var_set function so conditions passed as parameters will not have any effect. This is true for any condition apart from the "ifexists" one that is also used to replace the VF_UPDATEONLY flag that was used to prevent proc scope variable creation from a LUA module.
This commit is contained in:
parent
25fccd52ac
commit
51899d251c
@ -26,9 +26,17 @@
|
||||
#include <haproxy/thread-t.h>
|
||||
|
||||
/* flags used when setting/clearing variables */
|
||||
#define VF_UPDATEONLY 0x00000001 // SCOPE_PROC variables are only updated
|
||||
#define VF_CREATEONLY 0x00000002 // do nothing if the variable already exists
|
||||
#define VF_PERMANENT 0x00000004 // variables known to the config parser
|
||||
#define VF_CREATEONLY 0x00000001 // do nothing if the variable already exists
|
||||
#define VF_PERMANENT 0x00000002 // variables known to the config parser
|
||||
|
||||
#define VF_COND_IFEXISTS 0x00000004 // only set variable if it already exists
|
||||
#define VF_COND_IFNOTEXISTS 0x00000008 // only set variable if it did not exist yet
|
||||
#define VF_COND_IFEMPTY 0x00000010 // only set variable if sample is empty
|
||||
#define VF_COND_IFNOTEMPTY 0x00000020 // only set variable if sample is not empty
|
||||
#define VF_COND_IFSET 0x00000040 // only set variable if its type is not SMP_TYPE_ANY
|
||||
#define VF_COND_IFNOTSET 0x00000080 // only set variable if its type is ANY
|
||||
#define VF_COND_IFGT 0x00000100 // only set variable if its value is greater than the sample's
|
||||
#define VF_COND_IFLT 0x00000200 // ony set variable if its value is less than the sample's
|
||||
|
||||
enum vars_scope {
|
||||
SCOPE_SESS = 0,
|
||||
|
81
src/vars.c
81
src/vars.c
@ -36,6 +36,26 @@ static unsigned int var_reqres_limit = 0;
|
||||
static unsigned int var_check_limit = 0;
|
||||
static uint64_t var_name_hash_seed = 0;
|
||||
|
||||
/* Structure and array matching set-var conditions to their respective flag
|
||||
* value.
|
||||
*/
|
||||
struct var_set_condition {
|
||||
const char *cond_str;
|
||||
uint flag;
|
||||
};
|
||||
|
||||
static struct var_set_condition conditions_array[] = {
|
||||
{ "ifexists", VF_COND_IFEXISTS },
|
||||
{ "ifnotexists", VF_COND_IFNOTEXISTS },
|
||||
{ "ifempty", VF_COND_IFEMPTY },
|
||||
{ "ifnotempty", VF_COND_IFNOTEMPTY },
|
||||
{ "ifset", VF_COND_IFSET },
|
||||
{ "ifnotset", VF_COND_IFNOTSET },
|
||||
{ "ifgt", VF_COND_IFGT },
|
||||
{ "iflt", VF_COND_IFLT },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/* returns the struct vars pointer for a session, stream and scope, or NULL if
|
||||
* it does not exist.
|
||||
*/
|
||||
@ -329,10 +349,18 @@ static inline void var_clear_buffer(struct sample *smp, struct vars *vars, struc
|
||||
* a bool (which is memory-less).
|
||||
*
|
||||
* Flags is a bitfield that may contain one of the following flags:
|
||||
* - VF_UPDATEONLY: the variable may only be updated but not created.
|
||||
* - VF_CREATEONLY: do nothing if the variable already exists (success).
|
||||
* - VF_PERMANENT: this flag will be passed to the variable upon creation
|
||||
*
|
||||
* - VF_COND_IFEXISTS: only set variable if it already exists
|
||||
* - VF_COND_IFNOTEXISTS: only set variable if it did not exist yet
|
||||
* - VF_COND_IFEMPTY: only set variable if sample is empty
|
||||
* - VF_COND_IFNOTEMPTY: only set variable if sample is not empty
|
||||
* - VF_COND_IFSET: only set variable if its type is not SMP_TYPE_ANY
|
||||
* - VF_COND_IFNOTSET: only set variable if its type is ANY
|
||||
* - VF_COND_IFGT: only set variable if its value is greater than the sample's
|
||||
* - VF_COND_IFLT: ony set variable if its value is less than the sample's
|
||||
*
|
||||
* It returns 0 on failure, non-zero on success.
|
||||
*/
|
||||
static int var_set(uint64_t name_hash, enum vars_scope scope, struct sample *smp, uint flags)
|
||||
@ -357,7 +385,7 @@ static int var_set(uint64_t name_hash, enum vars_scope scope, struct sample *smp
|
||||
goto unlock;
|
||||
}
|
||||
} else {
|
||||
if (flags & VF_UPDATEONLY)
|
||||
if (flags & VF_COND_IFEXISTS)
|
||||
goto unlock;
|
||||
|
||||
/* Check memory available. */
|
||||
@ -469,10 +497,44 @@ static int var_unset(uint64_t name_hash, enum vars_scope scope, struct sample *s
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a string set-var condition into its numerical value.
|
||||
* The corresponding bit is set in the <cond_bitmap> parameter if the
|
||||
* <cond> is known.
|
||||
* Returns 1 in case of success.
|
||||
*/
|
||||
static int vars_parse_cond_param(const struct buffer *cond, uint *cond_bitmap, char **err)
|
||||
{
|
||||
struct var_set_condition *cond_elt = &conditions_array[0];
|
||||
|
||||
/* The conditions array is NULL terminated. */
|
||||
while (cond_elt->cond_str) {
|
||||
if (chunk_strcmp(cond, cond_elt->cond_str) == 0) {
|
||||
*cond_bitmap |= cond_elt->flag;
|
||||
break;
|
||||
}
|
||||
++cond_elt;
|
||||
}
|
||||
|
||||
if (cond_elt->cond_str == NULL && err)
|
||||
memprintf(err, "unknown condition \"%.*s\"", (int)cond->data, cond->area);
|
||||
|
||||
return cond_elt->cond_str != NULL;
|
||||
}
|
||||
|
||||
/* Returns 0 if fails, else returns 1. */
|
||||
static int smp_conv_store(const struct arg *args, struct sample *smp, void *private)
|
||||
{
|
||||
return var_set(args[0].data.var.name_hash, args[0].data.var.scope, smp, 0);
|
||||
uint conditions = 0;
|
||||
int cond_idx = 1;
|
||||
|
||||
while (args[cond_idx].type == ARGT_STR) {
|
||||
if (vars_parse_cond_param(&args[cond_idx++].data.str, &conditions, NULL) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return var_set(args[0].data.var.name_hash, args[0].data.var.scope, smp, conditions);
|
||||
}
|
||||
|
||||
/* Returns 0 if fails, else returns 1. */
|
||||
@ -529,7 +591,7 @@ int vars_set_by_name_ifexist(const char *name, size_t len, struct sample *smp)
|
||||
return 0;
|
||||
|
||||
/* Variable creation is allowed for all scopes apart from the PROC one. */
|
||||
return var_set(hash, scope, smp, (scope == SCOPE_PROC) ? VF_UPDATEONLY : 0);
|
||||
return var_set(hash, scope, smp, (scope == SCOPE_PROC) ? VF_COND_IFEXISTS : 0);
|
||||
}
|
||||
|
||||
|
||||
@ -765,7 +827,14 @@ static int smp_check_var(struct arg *args, char **err)
|
||||
static int conv_check_var(struct arg *args, struct sample_conv *conv,
|
||||
const char *file, int line, char **err_msg)
|
||||
{
|
||||
return vars_check_arg(&args[0], err_msg);
|
||||
int cond_idx = 1;
|
||||
uint conditions = 0;
|
||||
int retval = vars_check_arg(&args[0], err_msg);
|
||||
|
||||
while (retval && args[cond_idx].type == ARGT_STR)
|
||||
retval = vars_parse_cond_param(&args[cond_idx++].data.str, &conditions, err_msg);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* This function is a common parser for using variables. It understands
|
||||
@ -1219,7 +1288,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
|
||||
INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
|
||||
|
||||
static struct sample_conv_kw_list sample_conv_kws = {ILH, {
|
||||
{ "set-var", smp_conv_store, ARG1(1,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
|
||||
{ "set-var", smp_conv_store, ARG5(1,STR,STR,STR,STR,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
|
||||
{ "unset-var", smp_conv_clear, ARG1(1,STR), conv_check_var, SMP_T_ANY, SMP_T_ANY },
|
||||
{ /* END */ },
|
||||
}};
|
||||
|
Loading…
Reference in New Issue
Block a user