[libvirt] [PATCH v4 6/9] util: virTypedParams{Filter, GetAllStrings}

Michal Privoznik mprivozn at redhat.com
Tue Jun 16 15:44:11 UTC 2015


On 16.06.2015 00:42, Pavel Boldin wrote:
> Add multikey API:
> 
>  * virTypedParamsFilter that filters all the parameters with specified name.
>  * virTypedParamsGetAllStrings that returns a list with all the values for
>    specified name and string type.
> 
> Signed-off-by: Pavel Boldin <pboldin at mirantis.com>
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
>  include/libvirt/libvirt-host.h |   5 ++
>  src/libvirt_public.syms        |   5 ++
>  src/util/virtypedparam.c       | 102 +++++++++++++++++++++++++++++++++++++++++
>  src/util/virtypedparam.h       |   9 ++++
>  tests/Makefile.am              |   2 +-
>  tests/virtypedparamtest.c      | 100 ++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 222 insertions(+), 1 deletion(-)
> 
> diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
> index 070550b..8222cfb 100644
> --- a/include/libvirt/libvirt-host.h
> +++ b/include/libvirt/libvirt-host.h
> @@ -284,6 +284,11 @@ virTypedParamsGetString (virTypedParameterPtr params,
>                           const char *name,
>                           const char **value);
>  int
> +virTypedParamsGetAllStrings(virTypedParameterPtr params,
> +                         int nparams,
> +                         const char *name,
> +                         const char ***values);
> +int
>  virTypedParamsAddInt    (virTypedParameterPtr *params,
>                           int *nparams,
>                           int *maxparams,
> diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
> index 716dd2f..0a1feea 100644
> --- a/src/libvirt_public.syms
> +++ b/src/libvirt_public.syms
> @@ -715,4 +715,9 @@ LIBVIRT_1.2.16 {
>          virDomainSetUserPassword;
>  } LIBVIRT_1.2.15;
>  
> +LIBVIRT_1.3.0 {
> +    global:
> +        virTypedParamsGetAllStrings;
> +} LIBVIRT_1.2.16;
> +

I don't think this symbol needs to be exported.


>  # .... define new API here using predicted next version number ....
> diff --git a/src/util/virtypedparam.c b/src/util/virtypedparam.c
> index 6f608d6..a12006c 100644
> --- a/src/util/virtypedparam.c
> +++ b/src/util/virtypedparam.c
> @@ -482,6 +482,51 @@ virTypedParamsGet(virTypedParameterPtr params,
>  }
>  
>  
> +/**
> + * virTypedParamsFilter:
> + * @params: array of typed parameters
> + * @nparams: number of parameters in the @params array
> + * @name: name of the parameter to find
> + * @ret: pointer to the returned array
> + *
> + * Filters @params retaining only the parameters named @name in the
> + * resulting array @ret. Caller should free the @ret array but not
> + * the items since they are pointing to the @params elements.
> + *
> + * Returns amount of elements in @ret on success, -1 on error.
> + */
> +int
> +virTypedParamsFilter(virTypedParameterPtr params,
> +                     int nparams,
> +                     const char *name,
> +                     virTypedParameterPtr **ret)
> +{
> +    size_t i, alloc = 0, n = 0;
> +
> +    virCheckNonNullArgGoto(params, error);
> +    virCheckNonNullArgGoto(name, error);
> +    virCheckNonNullArgGoto(ret, error);
> +
> +    *ret = NULL;
> +
> +    for (i = 0; i < nparams; i++) {
> +        if (STREQ(params[i].field, name)) {
> +            if (VIR_RESIZE_N(*ret, alloc, n, 1) < 0)
> +                goto error;
> +
> +            (*ret)[n] = &params[i];
> +
> +            n++;
> +        }
> +    }
> +
> +    return n;
> +
> + error:
> +    return -1;
> +}
> +
> +
>  #define VIR_TYPED_PARAM_CHECK_TYPE(check_type)                              \
>      do { if (param->type != check_type) {                                   \
>          virReportError(VIR_ERR_INVALID_ARG,                                 \
> @@ -750,6 +795,63 @@ virTypedParamsGetString(virTypedParameterPtr params,
>  
>  
>  /**
> + * virTypedParamsGetAllStrings:
> + * @params: array of typed parameters
> + * @nparams: number of parameters in the @params array
> + * @name: name of the parameter to find
> + * @values: array of returned values
> + *
> + * Finds all parameters with desired @name within @params and
> + * store their values into @values. The @values array is self
> + * allocated and its length is stored into @picked. When no
> + * longer needed, caller should free the returned array, but not
> + * the items since they are taken from @params array.
> + *
> + * Returns amount of strings in @values array on success,
> + * -1 otherwise.
> + */
> +int
> +virTypedParamsGetAllStrings(virTypedParameterPtr params,
> +                            int nparams,
> +                            const char *name,
> +                            const char ***values)
> +{
> +    size_t i, n;
> +    int nfiltered;
> +    virTypedParameterPtr *filtered = NULL;
> +
> +    virResetLastError();
> +
> +    virCheckNonNullArgGoto(values, error);
> +    *values = NULL;
> +
> +    nfiltered = virTypedParamsFilter(params, nparams, name, &filtered);
> +
> +    if (nfiltered < 0)
> +        goto error;
> +
> +    if (nfiltered &&
> +        VIR_ALLOC_N(*values, nfiltered) < 0)
> +        goto error;
> +
> +    for (n = 0, i = 0; i < nfiltered; i++) {
> +        if (filtered[i]->type == VIR_TYPED_PARAM_STRING)
> +            (*values)[n++] = filtered[i]->value.s;
> +    }
> +
> +    VIR_FREE(filtered);
> +    return n;
> +
> + error:
> +    if (values)
> +        VIR_FREE(*values);
> +    VIR_FREE(filtered);
> +    virDispatchError(NULL);
> +    return -1;
> +}
> +
> +
> +/**
>   * virTypedParamsAddInt:
>   * @params: pointer to the array of typed parameters
>   * @nparams: number of parameters in the @params array
> diff --git a/src/util/virtypedparam.h b/src/util/virtypedparam.h
> index 9f2d08c..ac7f3a1 100644
> --- a/src/util/virtypedparam.h
> +++ b/src/util/virtypedparam.h
> @@ -45,6 +45,15 @@ bool virTypedParamsCheck(virTypedParameterPtr params,
>                           const char **names,
>                           int nnames);
>  
> +int
> +virTypedParamsFilter    (virTypedParameterPtr params,
> +                         int nparams,
> +                         const char *name,
> +                         virTypedParameterPtr **ret)
> +    ATTRIBUTE_RETURN_CHECK  ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3)
> +    ATTRIBUTE_NONNULL(4);
> +
> +

Since this is an internal API, it must go into src/libvirt_private.syms too.

>  int virTypedParameterAssign(virTypedParameterPtr param, const char *name,
>                              int type, /* TYPE arg */ ...)
>      ATTRIBUTE_RETURN_CHECK;
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index 9efb441..2d02208 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -1228,7 +1228,7 @@ objecteventtest_LDADD = $(LDADDS)
>  
>  virtypedparamtest_SOURCES = \
>  	virtypedparamtest.c testutils.h testutils.c
> -virtypedparamtest_LDADD = $(LDADDS)
> +virtypedparamtest_LDADD = $(LDADDS) ../src/libvirt_util.la $(GNULIB_LIBS)

Once the virTypedParamsFilter symbol is exposed (internally), you will
not need this.

>  
>  
>  if WITH_LINUX
> diff --git a/tests/virtypedparamtest.c b/tests/virtypedparamtest.c
> index 95e22a7..698255a 100644
> --- a/tests/virtypedparamtest.c
> +++ b/tests/virtypedparamtest.c
> @@ -81,6 +81,100 @@ testTypedParamsValidate(const void *opaque)
>      .nparams = PARAMS_SIZE(__VA_ARGS__),
>  
>  static int
> +testTypedParamsFilter(const void *opaque ATTRIBUTE_UNUSED)
> +{
> +    size_t i, nfiltered;
> +    int rv = -1;
> +    virTypedParameter params[] = {
> +        { .field = "bar", .type = VIR_TYPED_PARAM_UINT },
> +        { .field = "foo", .type = VIR_TYPED_PARAM_INT },
> +        { .field = "bar", .type = VIR_TYPED_PARAM_UINT },
> +        { .field = "foo", .type = VIR_TYPED_PARAM_INT },
> +        { .field = "foobar", .type = VIR_TYPED_PARAM_STRING },
> +        { .field = "foo", .type = VIR_TYPED_PARAM_INT }
> +    };
> +    virTypedParameterPtr *filtered = NULL;
> +
> +
> +    nfiltered = virTypedParamsFilter(params, ARRAY_CARDINALITY(params),
> +                                     "foo", &filtered);
> +    if (nfiltered != 3)
> +        goto cleanup;
> +
> +    for (i = 0; i < nfiltered; i++) {
> +        if (filtered[i] != &params[1 + i * 2])
> +            goto cleanup;
> +    }
> +    VIR_FREE(filtered);
> +    filtered = NULL;
> +
> +    nfiltered = virTypedParamsFilter(params, ARRAY_CARDINALITY(params),
> +                                     "bar", &filtered);
> +
> +    if (nfiltered != 2)
> +        goto cleanup;
> +
> +    for (i = 0; i < nfiltered; i++) {
> +        if (filtered[i] != &params[i * 2])
> +            goto cleanup;
> +    }
> +
> +    rv = 0;
> + cleanup:
> +    VIR_FREE(filtered);
> +    return rv;
> +}
> +
> +static int
> +testTypedParamsGetAllStrings(const void *opaque ATTRIBUTE_UNUSED)
> +{
> +    int i, picked;

A loop iterator needs to be size_t. 'syntax-check' would have warn you
about this.

> +    int rv = -1;
> +    char l = '1';
> +    const char **strings = NULL;
> +
> +    virTypedParameter params[] = {
> +        { .field = "bar", .type = VIR_TYPED_PARAM_STRING,
> +          .value = { .s = (char*)"bar1"} },
> +        { .field = "foo", .type = VIR_TYPED_PARAM_INT },
> +        { .field = "bar", .type = VIR_TYPED_PARAM_STRING,
> +          .value = { .s = (char*)"bar2"} },
> +        { .field = "foo", .type = VIR_TYPED_PARAM_INT },
> +        { .field = "foobar", .type = VIR_TYPED_PARAM_STRING },
> +        { .field = "bar", .type = VIR_TYPED_PARAM_STRING,
> +          .value = { .s = NULL } },
> +        { .field = "foo", .type = VIR_TYPED_PARAM_INT },
> +        { .field = "bar", .type = VIR_TYPED_PARAM_STRING,
> +          .value = { .s = (char*)"bar3"} }
> +    };
> +
> +    picked = virTypedParamsGetAllStrings(params,
> +                                         ARRAY_CARDINALITY(params),
> +                                         "bar",
> +                                         &strings);
> +
> +    if (picked < 0)
> +        goto cleanup;
> +
> +    for (i = 0; i < picked; i++) {
> +        if (i == 2) {
> +            if (strings[i] != NULL)
> +                goto cleanup;
> +            continue;
> +        }
> +        if (!STREQLEN(strings[i], "bar", 3))
> +            goto cleanup;
> +        if (strings[i][3] != l++)
> +            goto cleanup;
> +    }
> +
> +    rv = 0;
> + cleanup:
> +    VIR_FREE(strings);
> +    return rv;
> +}
> +
> +static int
>  testTypedParamsValidator(void)
>  {
>      size_t i;
> @@ -159,6 +253,12 @@ mymain(void)
>      if (testTypedParamsValidator() < 0)
>          rv = -1;
>  
> +    if (virtTestRun("Filtering", testTypedParamsFilter, NULL) < 0)
> +        rv = -1;
> +
> +    if (virtTestRun("Get All Strings", testTypedParamsGetAllStrings, NULL) < 0)
> +        rv = -1;
> +
>      if (rv < 0)
>          return EXIT_FAILURE;
>      return EXIT_SUCCESS;
> 

Michal




More information about the libvir-list mailing list