[libvirt] [PATCH v2 11/20] virlog: Introduce virLogParseOutputs

John Ferlan jferlan at redhat.com
Wed Sep 21 18:38:50 UTC 2016



On 08/18/2016 07:47 AM, Erik Skultety wrote:
> Another abstraction added on the top of parsing a single logging output. This
> method takes and parses the whole set of outputs, adding each single output
> that has already been parsed into a caller-provided array. If the user-supplied
> string contained duplicate outputs, only the last occurrence is taken into
> account (all the others are removed from the list), so we silently avoid
> duplicate logs and leaking journald fds.
> 
> Signed-off-by: Erik Skultety <eskultet at redhat.com>
> ---
>  src/libvirt_private.syms |  1 +
>  src/util/virlog.c        | 79 ++++++++++++++++++++++++++++++++++++++++++++++++
>  src/util/virlog.h        |  1 +
>  3 files changed, 81 insertions(+)
> 
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 1dfd7c8..b12ca92 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1869,6 +1869,7 @@ virLogParseAndDefineOutputs;
>  virLogParseDefaultPriority;
>  virLogParseFilter;
>  virLogParseOutput;
> +virLogParseOutputs;
>  virLogPriorityFromSyslog;
>  virLogProbablyLogMessage;
>  virLogReset;
> diff --git a/src/util/virlog.c b/src/util/virlog.c
> index 43b3d75..89e58cd 100644
> --- a/src/util/virlog.c
> +++ b/src/util/virlog.c
> @@ -1966,3 +1966,82 @@ virLogParseFilter(const char *filter)
>      virStringFreeList(tokens);
>      return ret;
>  }
> +
> +/**
> + * virLogParseOutputs:
> + * @src: string defining a (set of) output(s)
> + * @outputs: user-supplied list where parsed outputs from @src shall be stored
> + *
> + * The format for an output can be:
> + *    x:stderr
> + *       output goes to stderr
> + *    x:syslog:name
> + *       use syslog for the output and use the given name as the ident
> + *    x:file:file_path
> + *       output to a file, with the given filepath
> + * In all case the x prefix is the minimal level, acting as a filter
> + *    1: DEBUG
> + *    2: INFO
> + *    3: WARNING
> + *    4: ERROR
> + *
> + * Multiple outputs can be defined within @src string, they just need to be
> + * separated by spaces.
> + *
> + * If running in setuid mode, then only the 'stderr' output will
> + * be allowed
> + *

Much of this text would be moved to patch 9. This function doesn't do
any of those format checks.

> + * Returns the number of outputs parsed or -1 in case of error.
> + */
> +int
> +virLogParseOutputs(const char *src, virLogOutputPtr **outputs)
> +{
> +    int ret = -1;
> +    int at = -1;
> +    size_t noutputs = 0;
> +    size_t i;
> +    char **strings = NULL;
> +    virLogOutputPtr output = NULL;
> +    virLogOutputPtr *list = NULL;
> +
> +    if (!src)
> +        return -1;

Again ATTRIBUTE_NONNULL(1) in the prototype

> +
> +    VIR_DEBUG("outputs=%s", src);
> +
> +    if (!(strings = virStringSplit(src, " ", 0)))

You could use the Count version and then...

> +        goto cleanup;
> +
> +    for (i = 0; strings[i]; i++) {

...rather than strings[i], it's < count

> +        /* virStringSplit may return empty strings */
> +        if (STREQ(strings[i], ""))
> +            continue;
> +
> +        if (!(output = virLogParseOutput(strings[i])))
> +            goto cleanup;
> +
> +        /* let's check if a duplicate output does not already exist in which
> +         * case we replace it with its last occurrence
> +         */
> +        if ((at = virLogFindOutput(list, noutputs, output->dest,
> +                                   output->name)) >= 0) {
> +            virLogOutputFree(list[at]);
> +            VIR_DELETE_ELEMENT(list, at, noutputs);
> +        }
> +
> +        if (VIR_APPEND_ELEMENT(list, noutputs, output) < 0) {
> +            virLogOutputFree(output);

In this case, the old one is also gone... So we've effectively removed
it. Is that intentional?  or should the DELETE of 'at' occur after this
successfully adds a new one?

IOW:
   at = virLogFindOutput()
   if (VIR_APPEND_ELEMENT() < 0)
...
   }
   if (at >= 0) {
       virLogOutputFree(list[at]);
       VIR_DELETE_ELEMENT();
   }

> +            goto cleanup;
> +        }
> +
> +        virLogOutputFree(output);

Is this right? I don't think it's necessary unless you change to using
the _COPY append macro


> +    }
> +
> +    ret = noutputs;
> +    *outputs = list;

If you then set "list = NULL"...

> + cleanup:
> +    if (ret < 0)

... the (ret < 0) is not necessary

> +        virLogOutputListFree(list, noutputs);
> +    virStringFreeList(strings);
> +    return ret;
> +}
> diff --git a/src/util/virlog.h b/src/util/virlog.h
> index e7f6b85..ed60c00 100644
> --- a/src/util/virlog.h
> +++ b/src/util/virlog.h
> @@ -247,5 +247,6 @@ virLogOutputPtr virLogNewOutputToSyslog(virLogPriority priority,
>  virLogOutputPtr virLogNewOutputToJournald(int priority);
>  virLogOutputPtr virLogParseOutput(const char *src);
>  virLogFilterPtr virLogParseFilter(const char *src);
> +int virLogParseOutputs(const char *src, virLogOutputPtr **outputs);

s/;/ATTRIBUTE_NONNULL(1);

Conditional ACK - guess I'm curious how the duplication and error path
issue falls out...

John
>  
>  #endif
> 




More information about the libvir-list mailing list