[libvirt] [PATCH 22/49] list: Add helpers to list network objects

Laine Stump laine at laine.org
Tue Jul 24 17:22:01 UTC 2012


On 07/24/2012 01:09 AM, Osier Yang wrote:
> On 2012年07月24日 04:53, Laine Stump wrote:
>> On 07/20/2012 10:25 AM, Osier Yang wrote:
>>> src/conf/virobjectlist.c: Add virNetworkMatch to filter the networks;
>>> and virNetworkList to iterate over all the networks with the filter.
>>>
>>> src/conf/virobjectlist.h: Declare virNetworkList and define the macros
>>> for filters.
>
> Thanks for the reviewing, Laine.
>
>>
>> Before anything else - as I've said in a couple of earlier responses to
>> this series (and I won't say it for the other iterations - you can just
>> assume the same comment for all :-) - I don't think that driver-specific
>> functions (virNetworkMatch, virNetworkList) should be in a common source
>> file. If these functions have something in common, factor out that
>> common part and put *that* in a common file. If a function is specific
>> enough that it needs the name of the driver in the name, then it
>> shouldn't be in a common file.
>
> I see what you concern, and agree with you driver specific stuffs
> should be separated into each driver.
>
> But for these list stuffs, I insist that keeping those function in
> a common file is better. They are of specific drivers indeed, but
> in common from function point of view.


"function point of view" how? Because they all build a list of pointers
to objects? That argument doesn't hold - should all functions in libvirt
that build a list of pointers to objects be put into the same source
file? To be hyperbolic about it - should we put all functions that
acquire and release a lock in the same file?

Organizing the code in the manner you propose leads to a source tree
where adding a new API requires touching an incredibly long list of
files, and makes it difficult to split out pieces for use elsewhere.

(I know that's already the case for several other pieces of libvirt, but
why make the list longer? Each separate subsystem should be as
self-contained as possible.)

If you're concerned about maintenance of multiple functions that are all
mostly a copy-paste of each other, rather than grouping all those
functions together in one file, refactor it so that they all call a
common function with appropriate args (which may require some
callbacks). If the resulting utility function is more difficult to
understand than the current straightforward functions, then it's not
worth the bother.


>
> Or you prefer to have separate files like virDomainList.[ch],
> virStorageList.[ch], ..etc?


No, I think that's overkill.


> Or folder the functions into
> conf/domain_conf.[ch], conf/storage_conf.[ch], etc?

Where is the source data structure defined? If the data structure that
is used to list of domains/networks/storage pools|volumes is defined in
conf/*_conf.h, then the function that operates on that data structure to
produce the output list should be defined in conf/*_conf.c. If the data
structure is defined in ${driver}.h, then the function that operates on
it should be defined in ${driver}.c. (I think for all examples in this
current patchset, the answer is *_conf.c)


> IMO either
> is not better than keeping them in common place. :-)
>
>>
>> I'll review the rest, ignoring that for the moment.
>>
>>>
>>> src/libvirt_private.syms: Export virNetworkList.
>>> ---
>>>   src/conf/virobjectlist.c |   90
>>> ++++++++++++++++++++++++++++++++++++++++++++++
>>>   src/conf/virobjectlist.h |   23 ++++++++++++
>>>   src/libvirt_private.syms |    1 +
>>>   3 files changed, 114 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/src/conf/virobjectlist.c b/src/conf/virobjectlist.c
>>> index fb5f974..83b0d9c 100644
>>> --- a/src/conf/virobjectlist.c
>>> +++ b/src/conf/virobjectlist.c
>>> @@ -191,6 +191,37 @@ virStoragePoolMatch (virStoragePoolObjPtr poolobj,
>>>
>>>       return true;
>>>   }
>>> +
>>> +static bool
>>> +virNetworkMatch (virNetworkObjPtr netobj,
>>> +                 unsigned int flags)
>>> +{
>>> +    /* filter by active state */
>>> +    if (MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE)&&
>>> +        !((MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)&&
>>> +           virNetworkObjIsActive(netobj)) ||
>>> +          (MATCH(VIR_CONNECT_LIST_NETWORKS_INACTIVE)&&
>>> +           !virNetworkObjIsActive(netobj))))
>>> +        return false;
>>> +
>>> +    /* filter by persistence */
>>> +    if (MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_PERSISTENT)&&
>>> +        !((MATCH(VIR_CONNECT_LIST_NETWORKS_PERSISTENT)&&
>>> +           netobj->persistent) ||
>>> +          (MATCH(VIR_CONNECT_LIST_NETWORKS_TRANSIENT)&&
>>> +           !netobj->persistent)))
>>> +        return false;
>>> +
>>> +    /* filter by autostart option */
>>> +    if (MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_AUTOSTART)&&
>>> +        !((MATCH(VIR_CONNECT_LIST_NETWORKS_AUTOSTART)&&
>>> +           netobj->autostart) ||
>>> +          (MATCH(VIR_CONNECT_LIST_NETWORKS_NO_AUTOSTART)&&
>>> +           !netobj->autostart)))
>>> +        return false;
>>> +
>>> +    return true;
>>> +}
>>>   #undef MATCH
>>>
>>>   int
>>> @@ -340,3 +371,62 @@ cleanup:
>>>       VIR_FREE(tmp_pools);
>>>       return ret;
>>>   }
>>> +
>>> +int
>>> +virNetworkList(virConnectPtr conn,
>>> +               virNetworkObjList netobjs,
>>
>> Minor point - to be consistent with naming in existing network driver
>> code, why not call it "networks" rather than "netobjs"?
>
> I intended to keep consistent with other funcs in virobjectlist.c.
> If finally we prefer to have driver specific funcs separately,
> I will update it to "networks".
>
>>
>>> +               virNetworkPtr **nets,
>>> +               unsigned int flags)
>>> +{
>>> +    virNetworkPtr *tmp_nets = NULL;
>>> +    virNetworkPtr net = NULL;
>>> +    int nnets = 0;
>>> +    int ret = -1;
>>> +    int i;
>>> +
>>> +    if (nets) {
>>> +        if (VIR_ALLOC_N(tmp_nets, netobjs.count + 1)<  0) {
>>> +            virReportOOMError();
>>> +            goto cleanup;
>>> +        }
>>> +    }
>>> +
>>> +    for (i = 0; i<  netobjs.count; i++) {
>>> +        virNetworkObjPtr netobj = netobjs.objs[i];
>>> +        virNetworkObjLock(netobj);
>>> +        if (virNetworkMatch(netobj, flags)) {
>>> +            if (nets) {
>>> +                if (!(net = virGetNetwork(conn,
>>> +                                          netobj->def->name,
>>> +                                          netobj->def->uuid))) {
>>> +                    virNetworkObjUnlock(netobj);
>>> +                    goto cleanup;
>>> +                }
>>> +                tmp_nets[nnets++] = net;
>>> +            } else {
>>> +                nnets++;
>>
>> I don't think you want this else clause. the index on netobjs (i) is
>> incremented by the for(), and you only want the index on the output list
>> to be incremented when you actually add something to it.
>
> One design of the list APIs is to only return the object number. So
> the index is always needed. But this could be optimized as:
>
> if (nets) {
>     if (!(net = virGetNetwork(conn,
>                               netobj->def->name,
>                               netobj->def->uuid))) {
>         virNetworkObjUnlock(netobj);
>         goto cleanup;
>     }
>     tmp_nets[nnets] = net;
> }
> nnets++;

Never mind - I read through the code too quickly, and somehow mistakenly
saw the else clause at the level of the Match, rather than one step
further in (my brain had seen it as nnets being incremented even in the
case of no match).

I do prefer your modified version above, though.


>>
>>> +            }
>>> +        }
>>> +        virNetworkObjUnlock(netobj);
>>> +    }
>>> +
>>> +    if (tmp_nets) {
>>> +        /* trim the array to the final size */
>>> +        ignore_value(VIR_REALLOC_N(tmp_nets, nnets + 1));
>>> +        *nets = tmp_nets;
>>> +        tmp_nets = NULL;
>>> +    }
>>> +
>>> +    ret = nnets;
>>> +
>>> +cleanup:
>>> +    if (tmp_nets) {
>>> +        for (i = 0; i<  netobjs.count; i++) {
>>
>> You only want to do this nnets times, not netobjs.count. Since it's
>> NULL-initialized, there's no harm, but it may foster a misunderstanding
>> of the code in the future).
>
> Agreed.
>
> Regards,
> Osier
>




More information about the libvir-list mailing list