mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-20 13:21:29 +02:00
MEDIUM: sink: implement sink_find_early()
sink_find_early() is a convenient function that can be used instead of sink_find() during parsing time in order to try to find a matching sink even if the sink is not defined yet. Indeed, if the sink is not defined, sink_find_early() will try to create it and mark it as forward-declared. It will also save informations from the caller to better identify it in case of errors. If the sink happens to be found in the config, it will transition from forward-declared type to its final type. Else, it means that the sink was not found in the config, in this case, during postresolve, we raise an error to indicate that the sink was not found in the configuration. It should help solve postresolving issue with rings, because for now only log targets implement proper ring postresolving.. but rings may be used at different places in the code, such as debug() converter or in "traces" section.
This commit is contained in:
parent
ba7c03c18e
commit
1bdf6e884a
@ -31,9 +31,10 @@
|
||||
* - ring buffer, readable from CLI
|
||||
*/
|
||||
enum sink_type {
|
||||
SINK_TYPE_NEW, // not yet initialized
|
||||
SINK_TYPE_FD, // events sent to a file descriptor
|
||||
SINK_TYPE_BUFFER, // events sent to a ring buffer
|
||||
SINK_TYPE_FORWARD_DECLARED, // was searched using sink_find_early(), is expected to exist by some component
|
||||
SINK_TYPE_NEW, // not yet initialized
|
||||
SINK_TYPE_FD, // events sent to a file descriptor
|
||||
SINK_TYPE_BUFFER, // events sent to a ring buffer
|
||||
};
|
||||
|
||||
struct sink_forward_target {
|
||||
@ -50,7 +51,11 @@ struct sink_forward_target {
|
||||
struct sink {
|
||||
struct list sink_list; // position in the sink list
|
||||
char *name; // sink name
|
||||
char *desc; // sink description
|
||||
char *desc; /* sink description:
|
||||
* when forward-declared, holds info about where the
|
||||
* sink was first forward declared, else holds actual
|
||||
* sink description
|
||||
*/
|
||||
char *store; // backing-store file when buffer
|
||||
enum log_fmt fmt; // format expected by the sink
|
||||
enum sink_type type; // type of storage
|
||||
|
@ -31,6 +31,7 @@ extern struct list sink_list;
|
||||
extern struct proxy *sink_proxies_list;
|
||||
|
||||
struct sink *sink_find(const char *name);
|
||||
struct sink *sink_find_early(const char *name, const char *from, const char *file, int line);
|
||||
struct sink *sink_new_fd(const char *name, const char *desc, enum log_fmt, int fd);
|
||||
ssize_t __sink_write(struct sink *sink, struct log_header hdr, size_t maxlen,
|
||||
const struct ist msg[], size_t nmsg);
|
||||
|
92
src/sink.c
92
src/sink.c
@ -46,7 +46,7 @@ struct proxy *sink_proxies_list;
|
||||
|
||||
struct sink *cfg_sink;
|
||||
|
||||
struct sink *sink_find(const char *name)
|
||||
static struct sink *_sink_find(const char *name)
|
||||
{
|
||||
struct sink *sink;
|
||||
|
||||
@ -56,6 +56,63 @@ struct sink *sink_find(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* returns sink if it really exists */
|
||||
struct sink *sink_find(const char *name)
|
||||
{
|
||||
struct sink *sink;
|
||||
|
||||
sink = _sink_find(name);
|
||||
if (sink && sink->type != SINK_TYPE_FORWARD_DECLARED)
|
||||
return sink;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Similar to sink_find(), but intended to be used during config parsing:
|
||||
* tries to resolve sink name, if it fails, creates the sink and marks
|
||||
* it as forward-declared and hope that it will be defined later.
|
||||
*
|
||||
* The caller has to identify itself using <from>, <file> and <line> in
|
||||
* order to report precise error messages in the event that the sink is
|
||||
* never defined later (only the first misuse will be considered).
|
||||
*
|
||||
* It returns the sink on success and NULL on failure (memory error)
|
||||
*/
|
||||
struct sink *sink_find_early(const char *name, const char *from, const char *file, int line)
|
||||
{
|
||||
struct sink *sink;
|
||||
|
||||
/* not expected to be used during runtime */
|
||||
BUG_ON(!(global.mode & MODE_STARTING));
|
||||
|
||||
sink = _sink_find(name);
|
||||
if (sink)
|
||||
return sink;
|
||||
|
||||
/* not found, try to forward-declare it */
|
||||
sink = calloc(1, sizeof(*sink));
|
||||
if (!sink)
|
||||
return NULL;
|
||||
|
||||
sink->name = strdup(name);
|
||||
if (!sink->name)
|
||||
goto err;
|
||||
|
||||
memprintf(&sink->desc, "parsing [%s:%d] : %s", file, line, from);
|
||||
if (!sink->desc)
|
||||
goto err;
|
||||
|
||||
sink->type = SINK_TYPE_FORWARD_DECLARED;
|
||||
LIST_APPEND(&sink_list, &sink->sink_list);
|
||||
|
||||
return sink;
|
||||
|
||||
err:
|
||||
ha_free(&sink->name);
|
||||
ha_free(&sink->desc);
|
||||
ha_free(&sink);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* creates a new sink and adds it to the list, it's still generic and not fully
|
||||
* initialized. Returns NULL on allocation failure. If another one already
|
||||
* exists with the same name, it will be returned. The caller can detect it as
|
||||
@ -64,12 +121,19 @@ struct sink *sink_find(const char *name)
|
||||
static struct sink *__sink_new(const char *name, const char *desc, int fmt)
|
||||
{
|
||||
struct sink *sink;
|
||||
uint8_t _new = 0;
|
||||
|
||||
sink = sink_find(name);
|
||||
if (sink)
|
||||
sink = _sink_find(name);
|
||||
if (sink) {
|
||||
if (sink->type == SINK_TYPE_FORWARD_DECLARED) {
|
||||
ha_free(&sink->desc); // free previous desc
|
||||
goto forward_declared;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
sink = calloc(1, sizeof(*sink));
|
||||
_new = 1;
|
||||
if (!sink)
|
||||
goto end;
|
||||
|
||||
@ -77,6 +141,7 @@ static struct sink *__sink_new(const char *name, const char *desc, int fmt)
|
||||
if (!sink->name)
|
||||
goto err;
|
||||
|
||||
forward_declared:
|
||||
sink->desc = strdup(desc);
|
||||
if (!sink->desc)
|
||||
goto err;
|
||||
@ -87,7 +152,8 @@ static struct sink *__sink_new(const char *name, const char *desc, int fmt)
|
||||
/* address will be filled by the caller if needed */
|
||||
sink->ctx.fd = -1;
|
||||
sink->ctx.dropped = 0;
|
||||
LIST_APPEND(&sink_list, &sink->sink_list);
|
||||
if (_new)
|
||||
LIST_APPEND(&sink_list, &sink->sink_list);
|
||||
end:
|
||||
return sink;
|
||||
|
||||
@ -1329,6 +1395,23 @@ static void sink_init()
|
||||
sink_new_buf("buf0", "in-memory ring buffer", LOG_FORMAT_TIMED, 1048576);
|
||||
}
|
||||
|
||||
static int sink_postcheck()
|
||||
{
|
||||
struct sink *sink;
|
||||
|
||||
list_for_each_entry(sink, &sink_list, sink_list) {
|
||||
if (sink->type == SINK_TYPE_FORWARD_DECLARED) {
|
||||
/* sink wasn't upgraded to actual sink despite being
|
||||
* forward-declared: it is an error (the sink doesn't
|
||||
* really exist)
|
||||
*/
|
||||
ha_alert("%s: sink '%s' doesn't exist.\n", sink->desc, sink->name);
|
||||
return ERR_ALERT | ERR_FATAL;
|
||||
}
|
||||
}
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
static void sink_deinit()
|
||||
{
|
||||
struct sink *sink, *sb;
|
||||
@ -1338,6 +1421,7 @@ static void sink_deinit()
|
||||
}
|
||||
|
||||
INITCALL0(STG_REGISTER, sink_init);
|
||||
REGISTER_POST_CHECK(sink_postcheck);
|
||||
REGISTER_POST_DEINIT(sink_deinit);
|
||||
|
||||
static struct cli_kw_list cli_kws = {{ },{
|
||||
|
Loading…
x
Reference in New Issue
Block a user