diff --git a/include/proto/server.h b/include/proto/server.h index a1fa6c2f9..408427b2b 100644 --- a/include/proto/server.h +++ b/include/proto/server.h @@ -46,6 +46,18 @@ static void inline srv_inc_sess_ctr(struct server *s) #endif /* _PROTO_SERVER_H */ +/* + * Registers the server keyword list as a list of valid keywords for next + * parsing sessions. + */ +void srv_register_keywords(struct srv_kw_list *kwl); + +/* Return a pointer to the server keyword , or NULL if not found. */ +struct srv_kw *srv_find_kw(const char *kw); + +/* Dumps all registered "server" keywords to the string pointer. */ +void srv_dump_kws(char **out); + /* * Local variables: * c-indent-level: 8 diff --git a/include/types/server.h b/include/types/server.h index 2a22e72e5..3e83d64fc 100644 --- a/include/types/server.h +++ b/include/types/server.h @@ -203,6 +203,31 @@ struct server { } conf; /* config information */ }; +/* Descriptor for a "server" keyword. The ->parse() function returns 0 in case of + * success, or a combination of ERR_* flags if an error is encountered. The + * function pointer can be NULL if not implemented. The function also has an + * access to the current "server" config line. The ->skip value tells the parser + * how many words have to be skipped after the keyword. If the function needs to + * parse more keywords, it needs to update cur_arg. + */ +struct srv_kw { + const char *kw; + int (*parse)(char **args, int *cur_arg, struct proxy *px, struct server *srv, char **err); + int skip; /* nb min of args to skip, for use when kw is not handled */ + int default_ok; /* non-zero if kw is supported in default-server section */ +}; + +/* + * A keyword list. It is a NULL-terminated array of keywords. It embeds a + * struct list in order to be linked to other lists, allowing it to easily + * be declared where it is needed, and linked without duplicating data nor + * allocating memory. It is also possible to indicate a scope for the keywords. + */ +struct srv_kw_list { + const char *scope; + struct list list; + struct srv_kw kw[VAR_ARRAY]; +}; #endif /* _TYPES_SERVER_H */ diff --git a/src/server.c b/src/server.c index 0016c8028..ae46af5d2 100644 --- a/src/server.c +++ b/src/server.c @@ -1,7 +1,7 @@ /* * Server management functions. * - * Copyright 2000-2006 Willy Tarreau + * Copyright 2000-2012 Willy Tarreau * Copyright 2007-2008 Krzysztof Piotr Oledzki * * This program is free software; you can redistribute it and/or @@ -16,16 +16,21 @@ #include -int srv_downtime(struct server *s) { +/* List head of all known server keywords */ +static struct srv_kw_list srv_keywords = { + .list = LIST_HEAD_INIT(srv_keywords.list) +}; +int srv_downtime(struct server *s) +{ if ((s->state & SRV_RUNNING) && s->last_change < now.tv_sec) // ignore negative time return s->down_time; return now.tv_sec - s->last_change + s->down_time; } -int srv_getinter(struct server *s) { - +int srv_getinter(struct server *s) +{ if ((s->state & SRV_CHECKED) && (s->health == s->rise + s->fall - 1)) return s->inter; @@ -35,6 +40,71 @@ int srv_getinter(struct server *s) { return (s->fastinter)?(s->fastinter):(s->inter); } +/* + * Registers the server keyword list as a list of valid keywords for next + * parsing sessions. + */ +void srv_register_keywords(struct srv_kw_list *kwl) +{ + LIST_ADDQ(&srv_keywords.list, &kwl->list); +} + +/* Return a pointer to the server keyword , or NULL if not found. If the + * keyword is found with a NULL ->parse() function, then an attempt is made to + * find one with a valid ->parse() function. This way it is possible to declare + * platform-dependant, known keywords as NULL, then only declare them as valid + * if some options are met. Note that if the requested keyword contains an + * opening parenthesis, everything from this point is ignored. + */ +struct srv_kw *srv_find_kw(const char *kw) +{ + int index; + const char *kwend; + struct srv_kw_list *kwl; + struct srv_kw *ret = NULL; + + kwend = strchr(kw, '('); + if (!kwend) + kwend = kw + strlen(kw); + + list_for_each_entry(kwl, &srv_keywords.list, list) { + for (index = 0; kwl->kw[index].kw != NULL; index++) { + if ((strncmp(kwl->kw[index].kw, kw, kwend - kw) == 0) && + kwl->kw[index].kw[kwend-kw] == 0) { + if (kwl->kw[index].parse) + return &kwl->kw[index]; /* found it !*/ + else + ret = &kwl->kw[index]; /* may be OK */ + } + } + } + return ret; +} + +/* Dumps all registered "server" keywords to the string pointer. The + * unsupported keywords are only dumped if their supported form was not + * found. + */ +void srv_dump_kws(char **out) +{ + struct srv_kw_list *kwl; + int index; + + *out = NULL; + list_for_each_entry(kwl, &srv_keywords.list, list) { + for (index = 0; kwl->kw[index].kw != NULL; index++) { + if (kwl->kw[index].parse || + srv_find_kw(kwl->kw[index].kw) == &kwl->kw[index]) { + memprintf(out, "%s[%4s] %s%s%s%s\n", *out ? *out : "", + kwl->scope, + kwl->kw[index].kw, + kwl->kw[index].skip ? " " : "", + kwl->kw[index].default_ok ? " [dflt_ok]" : "", + kwl->kw[index].parse ? "" : " (not supported)"); + } + } + } +} /* * Local variables: