diff --git a/src/vars.c b/src/vars.c
index 2a17dbcf6..8a54c20d8 100644
--- a/src/vars.c
+++ b/src/vars.c
@@ -347,14 +347,24 @@ static int smp_fetch_var(const struct arg *args, struct sample *smp, const char
return vars_get_by_desc(var_desc, smp, def);
}
-/* This function search in the
a variable with the same
- * pointer value that the . If the variable doesn't exists,
- * create it. The function stores a copy of smp> if the variable.
- * It returns 0 if fails, else returns 1.
+/* This function tries to create variable in scope and store
+ * sample as its value. The stream and session are extracted from ,
+ * and the stream may be NULL when scope is SCOPE_SESS. In case there wouldn't
+ * be enough memory to store the sample while the variable was already created,
+ * it would be changed to a bool (which is memory-less).
+ * It returns 0 on failure, non-zero on success.
*/
-static int sample_store(struct vars *vars, const char *name, struct sample *smp)
+static int var_set(const char *name, enum vars_scope scope, struct sample *smp)
{
+ struct vars *vars;
struct var *var;
+ int ret = 0;
+
+ vars = get_vars(smp->sess, smp->strm, scope);
+ if (!vars || vars->scope != scope)
+ return 0;
+
+ HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
/* Look for existing variable name. */
var = var_get(vars, name);
@@ -373,15 +383,14 @@ static int sample_store(struct vars *vars, const char *name, struct sample *smp)
-var->data.u.meth.str.data);
}
} else {
-
/* Check memory available. */
if (!var_accounting_add(vars, smp->sess, smp->strm, sizeof(struct var)))
- return 0;
+ goto unlock;
/* Create new entry. */
var = pool_alloc(var_pool);
if (!var)
- return 0;
+ goto unlock;
LIST_APPEND(&vars->head, &var->l);
var->name = name;
}
@@ -405,14 +414,15 @@ static int sample_store(struct vars *vars, const char *name, struct sample *smp)
case SMP_T_BIN:
if (!var_accounting_add(vars, smp->sess, smp->strm, smp->data.u.str.data)) {
var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
- return 0;
+ goto unlock;
}
+
var->data.u.str.area = malloc(smp->data.u.str.data);
if (!var->data.u.str.area) {
var_accounting_diff(vars, smp->sess, smp->strm,
-smp->data.u.str.data);
var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
- return 0;
+ goto unlock;
}
var->data.u.str.data = smp->data.u.str.data;
memcpy(var->data.u.str.area, smp->data.u.str.area,
@@ -425,14 +435,15 @@ static int sample_store(struct vars *vars, const char *name, struct sample *smp)
if (!var_accounting_add(vars, smp->sess, smp->strm, smp->data.u.meth.str.data)) {
var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
- return 0;
+ goto unlock;
}
+
var->data.u.meth.str.area = malloc(smp->data.u.meth.str.data);
if (!var->data.u.meth.str.area) {
var_accounting_diff(vars, smp->sess, smp->strm,
-smp->data.u.meth.str.data);
var->data.type = SMP_T_BOOL; /* This type doesn't use additional memory. */
- return 0;
+ goto unlock;
}
var->data.u.meth.str.data = smp->data.u.meth.str.data;
var->data.u.meth.str.size = smp->data.u.meth.str.data;
@@ -440,21 +451,10 @@ static int sample_store(struct vars *vars, const char *name, struct sample *smp)
var->data.u.meth.str.data);
break;
}
- return 1;
-}
-/* Returns 0 if fails, else returns 1. Note that stream may be null for SCOPE_SESS. */
-static inline int sample_store_stream(const char *name, enum vars_scope scope, struct sample *smp)
-{
- struct vars *vars;
- int ret;
-
- vars = get_vars(smp->sess, smp->strm, scope);
- if (!vars || vars->scope != scope)
- return 0;
-
- HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
- ret = sample_store(vars, name, smp);
+ /* OK, now done */
+ ret = 1;
+ unlock:
HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
return ret;
}
@@ -487,7 +487,7 @@ static int var_unset(const char *name, enum vars_scope scope, struct sample *smp
/* Returns 0 if fails, else returns 1. */
static int smp_conv_store(const struct arg *args, struct sample *smp, void *private)
{
- return sample_store_stream(args[0].data.var.name, args[0].data.var.scope, smp);
+ return var_set(args[0].data.var.name, args[0].data.var.scope, smp);
}
/* Returns 0 if fails, else returns 1. */
@@ -541,7 +541,7 @@ int vars_set_by_name_ifexist(const char *name, size_t len, struct sample *smp)
if (!name)
return 0;
- return sample_store_stream(name, scope, smp);
+ return var_set(name, scope, smp);
}
@@ -557,7 +557,7 @@ int vars_set_by_name(const char *name, size_t len, struct sample *smp)
if (!name)
return 0;
- return sample_store_stream(name, scope, smp);
+ return var_set(name, scope, smp);
}
/* This function unset a variable if it was already defined.
@@ -717,7 +717,7 @@ static enum act_return action_store(struct act_rule *rule, struct proxy *px,
smp_set_owner(&smp, px, sess, s, 0);
smp.data.type = SMP_T_STR;
smp.data.u.str = *fmtstr;
- sample_store_stream(rule->arg.vars.name, rule->arg.vars.scope, &smp);
+ var_set(rule->arg.vars.name, rule->arg.vars.scope, &smp);
}
else {
/* an expression is used */
@@ -727,7 +727,7 @@ static enum act_return action_store(struct act_rule *rule, struct proxy *px,
}
/* Store the sample, and ignore errors. */
- sample_store_stream(rule->arg.vars.name, rule->arg.vars.scope, &smp);
+ var_set(rule->arg.vars.name, rule->arg.vars.scope, &smp);
free_trash_chunk(fmtstr);
return ACT_RET_CONT;
}