On 23.09.2020 22:50, Jiri Denemark wrote: > On Mon, Sep 21, 2020 at 10:51:16 +0300, Nikolay Shirokovskiy wrote: >> Currently virDomainMigrate3 reports "this function is not supported by the >> connection driver: virDomainMigrate3" if connection to destination for example >> is broken. This is a bit misleading. >> >> This is a result of we treat errors as unsupported feature in >> VIR_DRV_SUPPORTS_FEATURE macro. So let's handle errors instead. In order to >> keep logic clean as before there are new helper functions >> virDrvSupportsFeature/virDrvNSupportsFeature. They allow to keep if/else if >> structure of feature tests. >> >> I guess all the other occurences of VIR_DRV_SUPPORTS_FEATURE need to be >> replaced with one these new helper functions so that we detect error early and >> not have issues similar to virDomainMigrate3. I'm going to fix the other >> places if this RFC is approved. > > To be honest, I think this is quite ugly. > >> >> --- >> src/datatypes.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++ >> src/datatypes.h | 7 +++++ >> src/libvirt-domain.c | 76 +++++++++++++++++++++++++++++++--------------------- >> 3 files changed, 123 insertions(+), 30 deletions(-) >> >> diff --git a/src/datatypes.c b/src/datatypes.c >> index 1db38c5..3fb71f4 100644 >> --- a/src/datatypes.c >> +++ b/src/datatypes.c >> @@ -1257,3 +1257,73 @@ virAdmClientDispose(void *obj) >> >> virObjectUnref(clt->srv); >> } >> + >> + >> +/* >> + * Tests if feature is supported by connection. If testing failed >> + * due to error then function returns true as well and set @err flag >> + * to true. Thus positive result should be checked for an error. >> + * If @err is already set to true then no checking is done and >> + * the function returns true immediately so that previous error >> + * is not overwritten. >> + * >> + * Returns: >> + * true feature is supported or testing hit error >> + * false feature is not supported >> + */ >> +bool >> +virDrvSupportsFeature(virConnectPtr conn, >> + virDrvFeature feature, >> + bool *err) >> +{ >> + int rc; >> + >> + if (*err) >> + return true; >> + >> + if (!conn->driver->connectSupportsFeature) >> + return false; >> + >> + if ((rc = conn->driver->connectSupportsFeature(conn, feature)) < 0) { >> + *err = true; >> + return true; >> + } >> + >> + return rc > 0 ? true : false; >> +} > > I would just make virDrvSupportsFeature a tiny wrapper around > conn->driver->connectSupportsFeature checking > conn->driver->connectSupportsFeature != NULL and that's it. It could > break the if/elseif flow, but with much cleaner semantics and reduced > black magic. > Ok, thanx. I'll send next version. Nikolay