MINOR: server: add minimal infrastructure to parse keywords

Just like with the "bind" lines, we'll switch the "server" line
parsing to keyword registration. The code is essentially the same
as for bind keywords, with minor changes such as support for the
default-server keywords and support for variable argument count.
This commit is contained in:
Willy Tarreau 2012-10-10 08:27:36 +02:00
parent 7fca87fd9d
commit 21faa91be6
3 changed files with 111 additions and 4 deletions

View File

@ -46,6 +46,18 @@ static void inline srv_inc_sess_ctr(struct server *s)
#endif /* _PROTO_SERVER_H */
/*
* Registers the server keyword list <kwl> 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 <kw>, or NULL if not found. */
struct srv_kw *srv_find_kw(const char *kw);
/* Dumps all registered "server" keywords to the <out> string pointer. */
void srv_dump_kws(char **out);
/*
* Local variables:
* c-indent-level: 8

View File

@ -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 */

View File

@ -1,7 +1,7 @@
/*
* Server management functions.
*
* Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
* Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
* Copyright 2007-2008 Krzysztof Piotr Oledzki <ole@ans.pl>
*
* This program is free software; you can redistribute it and/or
@ -16,16 +16,21 @@
#include <proto/server.h>
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 <kwl> 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 <kw>, 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 <out> 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 ? " <arg>" : "",
kwl->kw[index].default_ok ? " [dflt_ok]" : "",
kwl->kw[index].parse ? "" : " (not supported)");
}
}
}
}
/*
* Local variables: