[MEDIUM] stick-tables: add support for arguments to data_types

Some data types will require arguments (eg: period for a rate counter).
This patch adds support for such arguments between parenthesis in the
"store" directive of the stick-table statement. Right now only integers
are supported.
This commit is contained in:
Willy Tarreau 2010-06-20 09:11:39 +02:00
parent b084e9ccb9
commit 888617dc3b
3 changed files with 47 additions and 11 deletions

View File

@ -23,6 +23,7 @@
#ifndef _PROTO_STICK_TABLE_H
#define _PROTO_STICK_TABLE_H
#include <common/errors.h>
#include <types/stick_table.h>
#define stktable_data_size(type) (sizeof(((union stktable_data*)0)->type))
@ -48,21 +49,27 @@ int stktable_compatible_pattern(struct pattern_expr *expr, unsigned long table_t
int stktable_get_data_type(char *name);
struct proxy *find_stktable(const char *name);
/* reserve some space for data type <type>. Return non-0 if OK, or 0 if already
* allocated (or impossible type).
/* reserve some space for data type <type>, and associate argument at <sa> if
* not NULL. Returns PE_NONE (0) if OK or an error code among :
* - PE_ENUM_OOR if <type> does not exist
* - PE_EXIST if <type> is already registered
*/
static inline int stktable_alloc_data_type(struct stktable *t, int type)
static inline int stktable_alloc_data_type(struct stktable *t, int type, const char *sa)
{
if (type >= STKTABLE_DATA_TYPES)
return 0;
return PE_ENUM_OOR;
if (t->data_ofs[type])
/* already allocated */
return 0;
return PE_EXIST;
t->data_size += stktable_data_types[type].data_length;
t->data_ofs[type] = -t->data_size;
return 1;
/* right now only int type is supported, but we may later support type-
* specific arg type.
*/
t->data_arg[type].i = sa ? atoi(sa) : 0;
return PE_NONE;
}
/* return pointer for data type <type> in sticky session <ts> of table <t>, or

View File

@ -50,6 +50,13 @@ enum {
STKTABLE_DATA_TYPES /* Number of data types, must always be last */
};
/* The types of optional arguments to stored data */
enum {
ARG_T_NONE = 0, /* data type takes no argument (default) */
ARG_T_INT, /* signed integer */
ARG_T_DELAY, /* a delay which supports time units */
};
/* stick_table extra data. This is mainly used for casting or size computation */
union stktable_data {
int server_id;
@ -64,6 +71,7 @@ union stktable_data {
struct stktable_data_type {
const char *name; /* name of the data type */
int data_length; /* length of this type, or 0 if variable (eg: string) */
int arg_type; /* type of optional argument, ARG_T_* */
};
/* stick table key type flags */
@ -104,6 +112,11 @@ struct stktable {
int expire; /* time to live for sticky sessions (milliseconds) */
int data_size; /* the size of the data that is prepended *before* stksess */
int data_ofs[STKTABLE_DATA_TYPES]; /* negative offsets of present data types, or 0 if absent */
union {
int i;
unsigned int u;
void *p;
} data_arg[STKTABLE_DATA_TYPES]; /* optional argument of each data type */
};
struct stktable_data_type stktable_data_types[STKTABLE_DATA_TYPES];

View File

@ -2276,15 +2276,31 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
}
else if (strcmp(args[myidx], "store") == 0) {
int type;
char *cw, *nw;
char *cw, *nw, *sa;
myidx++;
nw = args[myidx];
while (*nw) {
/* the "store" keyword supports a comma-separated list */
cw = nw;
while (*nw && *nw != ',')
sa = NULL; /* store arg */
while (*nw && *nw != ',') {
if (*nw == '(') {
*nw = 0;
sa = ++nw;
while (*nw != ')') {
if (!*nw) {
Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
file, linenum, args[0], cw);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
nw++;
}
*nw = '\0';
}
nw++;
}
if (*nw)
*nw++ = '\0';
type = stktable_get_data_type(cw);
@ -2294,7 +2310,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if (!stktable_alloc_data_type(&curproxy->table, type)) {
if (stktable_alloc_data_type(&curproxy->table, type, sa)) {
Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
file, linenum, args[0], cw);
err_code |= ERR_WARN;
@ -4910,7 +4926,7 @@ int check_config_validity()
else {
free((void *)mrule->table.name);
mrule->table.t = &(target->table);
stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID);
stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
}
}
@ -4943,7 +4959,7 @@ int check_config_validity()
else {
free((void *)mrule->table.name);
mrule->table.t = &(target->table);
stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID);
stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
}
}