From 888617dc3bdd750698fb6c2288bf8f8c53a95544 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 20 Jun 2010 09:11:39 +0200 Subject: [PATCH] [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. --- include/proto/stick_table.h | 19 +++++++++++++------ include/types/stick_table.h | 13 +++++++++++++ src/cfgparse.c | 26 +++++++++++++++++++++----- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/include/proto/stick_table.h b/include/proto/stick_table.h index 38ec9ae8f..7381737c0 100644 --- a/include/proto/stick_table.h +++ b/include/proto/stick_table.h @@ -23,6 +23,7 @@ #ifndef _PROTO_STICK_TABLE_H #define _PROTO_STICK_TABLE_H +#include #include #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 . Return non-0 if OK, or 0 if already - * allocated (or impossible type). +/* reserve some space for data type , and associate argument at if + * not NULL. Returns PE_NONE (0) if OK or an error code among : + * - PE_ENUM_OOR if does not exist + * - PE_EXIST if 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 in sticky session of table , or diff --git a/include/types/stick_table.h b/include/types/stick_table.h index 4cd18d3f7..caca0bea0 100644 --- a/include/types/stick_table.h +++ b/include/types/stick_table.h @@ -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]; diff --git a/src/cfgparse.c b/src/cfgparse.c index 69ab56606..3fa6c7eb1 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -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); } }