[libvirt] [PATCH v4 00/17] virObject adjustments for common object

Peter Krempa pkrempa at redhat.com
Tue Aug 22 15:34:53 UTC 2017


On Mon, Aug 21, 2017 at 11:27:17 -0400, John Ferlan wrote:
> On 08/21/2017 09:06 AM, Peter Krempa wrote:
> > On Fri, Aug 18, 2017 at 17:50:24 -0400, John Ferlan wrote:

[...]

> Oddly it's OK for virhash code to generically call something a "key" and
> have a default search mechanism that uses a void * STREQ comparison, but
> yet when applied to virobject code used to combine the needs for the

virHash code also stores anything you give it and returns it back. In
your approach the code is not generic enough to take a virObject or a
void *.

> various driver/vir*obj modules to create, add, search, list, remove, and
> delete for a what amounts to be common code between each of them using
> hash table(s) to manage "uuid" or "name" based objects, then it's not OK.

No, not entirely. As I've said, if you are going to add a "hash table on
steroids", it's fine if you call it anonymously.

What is not okay, that you are going to use the new object type and make
all (domain, storage, ...) objects inherit from it. I strongly dislike
this. Object members need to be clearly named, otherwise it will end up
only in confusion.

You certainly can add some internal data structure, which can be an
object, to hold the data which allow this to work. But making domain
objects inherit from it is wrong.

> Ironically my first/initial pass at this took the path of a single
> src/conf/virpoolobj.c module, but it was suggested to use virobject
> instead to abstract things. When that's done - it's back to well I don't
> like that approach because it's too generic, so you should use a common
> module in order to make all those abstractions along with quite a bit
> more specific code in order to handle (known) differences between how
> each of the driver/vir*obj's needs to reference things.

Your first implementation was neither generic nor specific. It contained
generic parts (anonymized name and UUID) and then specific parts, where
you'd have to pass in VM/storage/nw objects. It couldn't really be used
for anything else.

And this is mostly the same. You have a hybrid, where you need the
stored objects to inherit from the object you've created, and then
introduce fields which make it specific for this only use case "active".

With this you are basically attempting to move an implementation detail
of the approach to map multiple keys to a virObject of some type to the
object properties themselves, which feels wrong. Especially since the
properties you are trying to extract can't be named uniformly for all
possible objects inheriting from such object.

> FWIW: Initial posting... Patch 2 is where the virobject enhancement was
> suggested.
> 
> https://www.redhat.com/archives/libvir-list/2017-February/msg00519.html
> 
> > 
> > This makes such helpers hard to use and hard to remember which
> > fields serves which purpose in the given use case. This also then
> > triggers custom wrappers for every single usage area where you put names
> > to those fields.
> > 
> 
> How is it hard to use/remember?  I would think it's much harder to use
> and remember 8 different ways to do things as opposed to one, but maybe
> I'm the only one looking to simplify/unify.

If 'key1' is a name of the VM but 'uuid' for a secret, then it's
confusing and hard to remember. Confusing is worse than having different
implementation. If you are going to argue that 'key1' should ever be
interpreted in the context of the lookup functions, then you made it an
implementation detail of the lookup functions thus not requiring
everything to inherit from it.

> If you really look at the code - you'll see for the most part it's a
> wrapper around various virhash functions with specific needs for
> driver/vir*obj that includes the refcnt, locking, and smaller subset of
> driver/vir*obj specific code to "manage" the details of/for a vir*DefPtr.

Yes. That's what I object to. If

> 
> It works for nodedev, secret, network, and interface already as seen in
> later patches in the series.
> 
> And again, usage of "key1/key2" vs. "uuid/name" is because:
> 
> Nodedev uses "name" as it's key
> Secret uses "uuid" as it's key
> Network uses "uuid" and (with these patches) "name" as keys
> Interface uses "name" as it's key
> Nwfilter uses "name" as it's key
> Storage Pool uses "uuid" and "name" as keys
> Storage Volume uses "name" as it's key
> Domains use "uuid" and "name" as keys.

Yes they are different. And that's my point. If you are going to make an
object, which will agregate those properties, you need to be able to
name them. If you can't, don't try


> So, is that really that hard to remember? Do you really have a need to

Yes. Also duplicated. You still have the name in vm->def or pool->def.
It bugs me that we store the name in 'def' rather the object itself, but
I don't feel like trying to change it. (I tried and gave up few years
ago.)

> remember? Why do you feel it's so important that the object knows it's
> managing a table of UUIDs or a table of names? The driver/vir*obj

No that's fine. As long as you don't force us to inherit from it. If you
inherit from it, the names need to be meaningful. If you treat the
object as an impl. Detail then they don't.

> implementation essentially wants at least 1 way to store things and
> possibly 2 so that lookup by a second key is quicker (lookup-by-keyid
> vs. search all for specific name). Yes, they are one or the other
> currently. In the long run, it's just a name.
> 
> The driver/vir*obj.c code can choose which to use and manages it's own
> mapping. One need only look at the argument in the create/new to know
> which is which. But, it doesn't matter once you get to the Find/Search
> code as if there are two tables an object has to be in both tables. So,
> when using a Lookup function on some string both tables can be searched
> in order to perform lookup. When it comes to the ForEach or Search type
> functions, only one table needs to be searched in order to run through
> all the elements. So rather than need to make the (generic) object code
> need to check if one table or the other exists, just make at least one
> table required and define that to be the first table. It's just a design
> decision.
> 
> >> I think that's the whole purpose of it. After some soul searching I feel
> > 
> > Could you elaborate please on the purpose and final goal of this. I
> > was't able to piece together what you are trying to achieve. If you want
> > to unify the code that sections of libvirt use to hold lists of objects
> > I don't think you need a custom sub-type for them.
> > 
> 
> As if I haven't already elaborated the purpose and final goal. It's been
> stated multiple times and I think it's very obvious.
> 
> The goal is to make things generic enough to be used by various
> driver/vir*obj modules in order to abstract away or combine alike code.
> If that's truly not desired that's fine. I think it's far better to have
> less cut/copy-n-paste code, but not everyone has that same viewpoint.
> 
> Rather than take a myopic viewpoint of a domain or storage or network -
> once you consider that each of those subsystems essentially does the
> same thing - creates an object, stores that object, allows searches on
> that object, and eventually deletes that object.  The details of the
> object is still handle-able by specific code, but there's much with that
> object that can and should be generically handled.
> 
> The "reason" I went down this rabbit hole was some patches posted by
> Virtuozzo which essentially copied *a lot* from the storage driver in
> order to make another storage driver specific for their needs. I felt
> rather than cut-copy-n-paste that we should be able to "combine" a lot
> of code. As I dug into the code I found a mish-mash of object management
> throughout the drivers. Mostly forward linked lists, but each set of
> code just different enough to make things "difficult" as it relates to
> being able to support/maintain code over time. So rather than have
> multiple ways to do things, take a common approach so that when you're
> looking through code you don't have to know the differences between 8
> piles of code that all accomplished the same goal, but each in its own
> unique way.

Fair enough. So you want a better way to collect objects in lists.
That's a very worthwile goal.

[... trimmed the rest, since most points would repeat ... ]

> > 
> > The wrapper object you are adding here doesn't seem to add any value,
> 
> That's your opinion.

Well, you techincally asked for it by sending it for review. It would be
more worhtwhile to refute it rather than dismiss it.

I might have not responded to everything, but this message was rather
long. Feel free to reiterate points which you feel I've missed.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20170822/6cfe7bd3/attachment-0001.sig>


More information about the libvir-list mailing list