qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2015 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
2016-02-08 19:08:51 +01:00
|
|
|
#include "qemu/osdep.h"
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
|
include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef. Since then, we've moved to include qemu/osdep.h
everywhere. Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h. That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h. Include qapi/error.h in .c files that need it and don't
get it now. Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly. Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h. Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third. Unfortunately, the number depending on
qapi-types.h shrinks only a little. More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-03-14 09:01:28 +01:00
|
|
|
#include "qapi/error.h"
|
2021-03-12 18:35:45 +01:00
|
|
|
#include "qapi/qobject-input-visitor.h"
|
|
|
|
#include "qapi/qmp/qdict.h"
|
|
|
|
#include "qapi/qmp/qobject.h"
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
#include "qom/object.h"
|
|
|
|
#include "qemu/module.h"
|
2017-06-04 01:13:31 +02:00
|
|
|
#include "qemu/option.h"
|
2022-04-20 15:26:06 +02:00
|
|
|
#include "qemu/keyval.h"
|
2017-06-04 01:13:31 +02:00
|
|
|
#include "qemu/config-file.h"
|
|
|
|
#include "qom/object_interfaces.h"
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
|
|
|
|
|
|
|
|
#define TYPE_DUMMY "qemu-dummy"
|
|
|
|
|
|
|
|
typedef struct DummyObject DummyObject;
|
|
|
|
typedef struct DummyObjectClass DummyObjectClass;
|
|
|
|
|
2020-08-31 23:07:33 +02:00
|
|
|
DECLARE_INSTANCE_CHECKER(DummyObject, DUMMY_OBJECT,
|
|
|
|
TYPE_DUMMY)
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:08 +02:00
|
|
|
typedef enum DummyAnimal DummyAnimal;
|
|
|
|
|
|
|
|
enum DummyAnimal {
|
|
|
|
DUMMY_FROG,
|
|
|
|
DUMMY_ALLIGATOR,
|
|
|
|
DUMMY_PLATYPUS,
|
|
|
|
|
|
|
|
DUMMY_LAST,
|
|
|
|
};
|
|
|
|
|
2017-08-24 10:46:10 +02:00
|
|
|
const QEnumLookup dummy_animal_map = {
|
|
|
|
.array = (const char *const[]) {
|
|
|
|
[DUMMY_FROG] = "frog",
|
|
|
|
[DUMMY_ALLIGATOR] = "alligator",
|
|
|
|
[DUMMY_PLATYPUS] = "platypus",
|
|
|
|
},
|
|
|
|
.size = DUMMY_LAST
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:08 +02:00
|
|
|
};
|
|
|
|
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
struct DummyObject {
|
|
|
|
Object parent_obj;
|
|
|
|
|
|
|
|
bool bv;
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:08 +02:00
|
|
|
DummyAnimal av;
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
char *sv;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DummyObjectClass {
|
|
|
|
ObjectClass parent_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void dummy_set_bv(Object *obj,
|
|
|
|
bool value,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
DummyObject *dobj = DUMMY_OBJECT(obj);
|
|
|
|
|
|
|
|
dobj->bv = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool dummy_get_bv(Object *obj,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
DummyObject *dobj = DUMMY_OBJECT(obj);
|
|
|
|
|
|
|
|
return dobj->bv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:08 +02:00
|
|
|
static void dummy_set_av(Object *obj,
|
|
|
|
int value,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
DummyObject *dobj = DUMMY_OBJECT(obj);
|
|
|
|
|
|
|
|
dobj->av = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dummy_get_av(Object *obj,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
DummyObject *dobj = DUMMY_OBJECT(obj);
|
|
|
|
|
|
|
|
return dobj->av;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
static void dummy_set_sv(Object *obj,
|
|
|
|
const char *value,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
DummyObject *dobj = DUMMY_OBJECT(obj);
|
|
|
|
|
|
|
|
g_free(dobj->sv);
|
|
|
|
dobj->sv = g_strdup(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *dummy_get_sv(Object *obj,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
DummyObject *dobj = DUMMY_OBJECT(obj);
|
|
|
|
|
|
|
|
return g_strdup(dobj->sv);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void dummy_init(Object *obj)
|
|
|
|
{
|
|
|
|
object_property_add_bool(obj, "bv",
|
|
|
|
dummy_get_bv,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
dummy_set_bv);
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
}
|
|
|
|
|
2015-10-13 14:37:46 +02:00
|
|
|
|
|
|
|
static void dummy_class_init(ObjectClass *cls, void *data)
|
|
|
|
{
|
|
|
|
object_class_property_add_str(cls, "sv",
|
|
|
|
dummy_get_sv,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
dummy_set_sv);
|
2015-10-13 14:37:46 +02:00
|
|
|
object_class_property_add_enum(cls, "av",
|
|
|
|
"DummyAnimal",
|
2017-08-24 10:46:10 +02:00
|
|
|
&dummy_animal_map,
|
2015-10-13 14:37:46 +02:00
|
|
|
dummy_get_av,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
dummy_set_av);
|
2015-10-13 14:37:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
static void dummy_finalize(Object *obj)
|
|
|
|
{
|
|
|
|
DummyObject *dobj = DUMMY_OBJECT(obj);
|
|
|
|
|
|
|
|
g_free(dobj->sv);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const TypeInfo dummy_info = {
|
|
|
|
.name = TYPE_DUMMY,
|
|
|
|
.parent = TYPE_OBJECT,
|
|
|
|
.instance_size = sizeof(DummyObject),
|
|
|
|
.instance_init = dummy_init,
|
|
|
|
.instance_finalize = dummy_finalize,
|
|
|
|
.class_size = sizeof(DummyObjectClass),
|
2015-10-13 14:37:46 +02:00
|
|
|
.class_init = dummy_class_init,
|
2017-06-04 01:13:31 +02:00
|
|
|
.interfaces = (InterfaceInfo[]) {
|
|
|
|
{ TYPE_USER_CREATABLE },
|
|
|
|
{ }
|
|
|
|
}
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
};
|
|
|
|
|
2015-11-16 16:37:34 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The following 3 object classes are used to
|
|
|
|
* simulate the kind of relationships seen in
|
|
|
|
* qdev, which result in complex object
|
|
|
|
* property destruction ordering.
|
|
|
|
*
|
|
|
|
* DummyDev has a 'bus' child to a DummyBus
|
|
|
|
* DummyBus has a 'backend' child to a DummyBackend
|
|
|
|
* DummyDev has a 'backend' link to DummyBackend
|
|
|
|
*
|
|
|
|
* When DummyDev is finalized, it unparents the
|
|
|
|
* DummyBackend, which unparents the DummyDev
|
|
|
|
* which deletes the 'backend' link from DummyDev
|
|
|
|
* to DummyBackend. This illustrates that the
|
|
|
|
* object_property_del_all() method needs to
|
|
|
|
* cope with the list of properties being changed
|
|
|
|
* while it iterates over them.
|
|
|
|
*/
|
|
|
|
typedef struct DummyDev DummyDev;
|
|
|
|
typedef struct DummyDevClass DummyDevClass;
|
|
|
|
typedef struct DummyBus DummyBus;
|
|
|
|
typedef struct DummyBusClass DummyBusClass;
|
|
|
|
typedef struct DummyBackend DummyBackend;
|
|
|
|
typedef struct DummyBackendClass DummyBackendClass;
|
|
|
|
|
|
|
|
#define TYPE_DUMMY_DEV "qemu-dummy-dev"
|
|
|
|
#define TYPE_DUMMY_BUS "qemu-dummy-bus"
|
|
|
|
#define TYPE_DUMMY_BACKEND "qemu-dummy-backend"
|
|
|
|
|
2020-08-31 23:07:33 +02:00
|
|
|
DECLARE_INSTANCE_CHECKER(DummyDev, DUMMY_DEV,
|
|
|
|
TYPE_DUMMY_DEV)
|
|
|
|
DECLARE_INSTANCE_CHECKER(DummyBus, DUMMY_BUS,
|
|
|
|
TYPE_DUMMY_BUS)
|
|
|
|
DECLARE_INSTANCE_CHECKER(DummyBackend, DUMMY_BACKEND,
|
|
|
|
TYPE_DUMMY_BACKEND)
|
2015-11-16 16:37:34 +01:00
|
|
|
|
|
|
|
struct DummyDev {
|
|
|
|
Object parent_obj;
|
|
|
|
|
|
|
|
DummyBus *bus;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DummyDevClass {
|
|
|
|
ObjectClass parent_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DummyBus {
|
|
|
|
Object parent_obj;
|
|
|
|
|
|
|
|
DummyBackend *backend;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DummyBusClass {
|
|
|
|
ObjectClass parent_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DummyBackend {
|
|
|
|
Object parent_obj;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DummyBackendClass {
|
|
|
|
ObjectClass parent_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-07-07 21:49:41 +02:00
|
|
|
static void dummy_dev_finalize(Object *obj)
|
|
|
|
{
|
|
|
|
DummyDev *dev = DUMMY_DEV(obj);
|
|
|
|
|
|
|
|
object_unref(OBJECT(dev->bus));
|
|
|
|
}
|
|
|
|
|
2015-11-16 16:37:34 +01:00
|
|
|
static void dummy_dev_init(Object *obj)
|
|
|
|
{
|
|
|
|
DummyDev *dev = DUMMY_DEV(obj);
|
|
|
|
DummyBus *bus = DUMMY_BUS(object_new(TYPE_DUMMY_BUS));
|
|
|
|
DummyBackend *backend = DUMMY_BACKEND(object_new(TYPE_DUMMY_BACKEND));
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
object_property_add_child(obj, "bus", OBJECT(bus));
|
2015-11-16 16:37:34 +01:00
|
|
|
dev->bus = bus;
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
object_property_add_child(OBJECT(bus), "backend", OBJECT(backend));
|
2015-11-16 16:37:34 +01:00
|
|
|
bus->backend = backend;
|
|
|
|
|
|
|
|
object_property_add_link(obj, "backend", TYPE_DUMMY_BACKEND,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
(Object **)&bus->backend, NULL, 0);
|
2015-11-16 16:37:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void dummy_dev_unparent(Object *obj)
|
|
|
|
{
|
|
|
|
DummyDev *dev = DUMMY_DEV(obj);
|
|
|
|
object_unparent(OBJECT(dev->bus));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dummy_dev_class_init(ObjectClass *klass, void *opaque)
|
|
|
|
{
|
|
|
|
klass->unparent = dummy_dev_unparent;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-07 21:49:41 +02:00
|
|
|
static void dummy_bus_finalize(Object *obj)
|
|
|
|
{
|
|
|
|
DummyBus *bus = DUMMY_BUS(obj);
|
|
|
|
|
|
|
|
object_unref(OBJECT(bus->backend));
|
|
|
|
}
|
|
|
|
|
2015-11-16 16:37:34 +01:00
|
|
|
static void dummy_bus_init(Object *obj)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dummy_bus_unparent(Object *obj)
|
|
|
|
{
|
|
|
|
DummyBus *bus = DUMMY_BUS(obj);
|
2020-05-05 17:29:26 +02:00
|
|
|
object_property_del(obj->parent, "backend");
|
2015-11-16 16:37:34 +01:00
|
|
|
object_unparent(OBJECT(bus->backend));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dummy_bus_class_init(ObjectClass *klass, void *opaque)
|
|
|
|
{
|
|
|
|
klass->unparent = dummy_bus_unparent;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dummy_backend_init(Object *obj)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const TypeInfo dummy_dev_info = {
|
|
|
|
.name = TYPE_DUMMY_DEV,
|
|
|
|
.parent = TYPE_OBJECT,
|
|
|
|
.instance_size = sizeof(DummyDev),
|
|
|
|
.instance_init = dummy_dev_init,
|
2016-07-07 21:49:41 +02:00
|
|
|
.instance_finalize = dummy_dev_finalize,
|
2015-11-16 16:37:34 +01:00
|
|
|
.class_size = sizeof(DummyDevClass),
|
|
|
|
.class_init = dummy_dev_class_init,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const TypeInfo dummy_bus_info = {
|
|
|
|
.name = TYPE_DUMMY_BUS,
|
|
|
|
.parent = TYPE_OBJECT,
|
|
|
|
.instance_size = sizeof(DummyBus),
|
|
|
|
.instance_init = dummy_bus_init,
|
2016-07-07 21:49:41 +02:00
|
|
|
.instance_finalize = dummy_bus_finalize,
|
2015-11-16 16:37:34 +01:00
|
|
|
.class_size = sizeof(DummyBusClass),
|
|
|
|
.class_init = dummy_bus_class_init,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const TypeInfo dummy_backend_info = {
|
|
|
|
.name = TYPE_DUMMY_BACKEND,
|
|
|
|
.parent = TYPE_OBJECT,
|
|
|
|
.instance_size = sizeof(DummyBackend),
|
|
|
|
.instance_init = dummy_backend_init,
|
|
|
|
.class_size = sizeof(DummyBackendClass),
|
|
|
|
};
|
|
|
|
|
2017-06-04 01:13:31 +02:00
|
|
|
static QemuOptsList qemu_object_opts = {
|
|
|
|
.name = "object",
|
|
|
|
.implied_opt_name = "qom-type",
|
|
|
|
.head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
|
|
|
|
.desc = {
|
|
|
|
{ }
|
|
|
|
},
|
|
|
|
};
|
2015-11-16 16:37:34 +01:00
|
|
|
|
|
|
|
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
static void test_dummy_createv(void)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
Object *parent = object_get_objects_root();
|
|
|
|
DummyObject *dobj = DUMMY_OBJECT(
|
|
|
|
object_new_with_props(TYPE_DUMMY,
|
|
|
|
parent,
|
|
|
|
"dummy0",
|
|
|
|
&err,
|
|
|
|
"bv", "yes",
|
|
|
|
"sv", "Hiss hiss hiss",
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:08 +02:00
|
|
|
"av", "platypus",
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
NULL));
|
|
|
|
|
|
|
|
g_assert(err == NULL);
|
|
|
|
g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss");
|
|
|
|
g_assert(dobj->bv == true);
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:08 +02:00
|
|
|
g_assert(dobj->av == DUMMY_PLATYPUS);
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
|
|
|
|
g_assert(object_resolve_path_component(parent, "dummy0")
|
|
|
|
== OBJECT(dobj));
|
|
|
|
|
|
|
|
object_unparent(OBJECT(dobj));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Object *new_helper(Error **errp,
|
|
|
|
Object *parent,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
va_list vargs;
|
|
|
|
Object *obj;
|
|
|
|
|
|
|
|
va_start(vargs, parent);
|
|
|
|
obj = object_new_with_propv(TYPE_DUMMY,
|
|
|
|
parent,
|
|
|
|
"dummy0",
|
|
|
|
errp,
|
|
|
|
vargs);
|
|
|
|
va_end(vargs);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_dummy_createlist(void)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
Object *parent = object_get_objects_root();
|
|
|
|
DummyObject *dobj = DUMMY_OBJECT(
|
|
|
|
new_helper(&err,
|
|
|
|
parent,
|
|
|
|
"bv", "yes",
|
|
|
|
"sv", "Hiss hiss hiss",
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:08 +02:00
|
|
|
"av", "platypus",
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
NULL));
|
|
|
|
|
|
|
|
g_assert(err == NULL);
|
|
|
|
g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss");
|
|
|
|
g_assert(dobj->bv == true);
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:08 +02:00
|
|
|
g_assert(dobj->av == DUMMY_PLATYPUS);
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
|
|
|
|
g_assert(object_resolve_path_component(parent, "dummy0")
|
|
|
|
== OBJECT(dobj));
|
|
|
|
|
|
|
|
object_unparent(OBJECT(dobj));
|
|
|
|
}
|
|
|
|
|
2021-03-12 18:35:45 +01:00
|
|
|
static bool test_create_obj(QDict *qdict, Error **errp)
|
|
|
|
{
|
|
|
|
Visitor *v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
|
|
|
|
Object *obj = user_creatable_add_type(TYPE_DUMMY, "dev0", qdict, v, errp);
|
|
|
|
|
|
|
|
visit_free(v);
|
|
|
|
object_unref(obj);
|
|
|
|
return !!obj;
|
|
|
|
}
|
|
|
|
|
2017-06-04 01:13:31 +02:00
|
|
|
static void test_dummy_createcmdl(void)
|
|
|
|
{
|
2021-03-12 18:35:45 +01:00
|
|
|
QDict *qdict;
|
2017-06-04 01:13:31 +02:00
|
|
|
DummyObject *dobj;
|
|
|
|
Error *err = NULL;
|
2021-03-12 18:35:45 +01:00
|
|
|
bool created, help;
|
|
|
|
const char *params = "bv=yes,sv=Hiss hiss hiss,av=platypus";
|
2017-06-04 01:13:31 +02:00
|
|
|
|
2021-03-12 18:35:45 +01:00
|
|
|
/* Needed for user_creatable_del. */
|
2017-06-04 01:13:31 +02:00
|
|
|
qemu_add_opts(&qemu_object_opts);
|
2021-03-12 18:35:45 +01:00
|
|
|
|
|
|
|
qdict = keyval_parse(params, "qom-type", &help, &err);
|
2017-06-04 01:13:31 +02:00
|
|
|
g_assert(err == NULL);
|
2021-03-12 18:35:45 +01:00
|
|
|
g_assert(qdict);
|
|
|
|
g_assert(!help);
|
2017-06-04 01:13:31 +02:00
|
|
|
|
2021-03-12 18:35:45 +01:00
|
|
|
created = test_create_obj(qdict, &err);
|
|
|
|
g_assert(created);
|
2017-06-04 01:13:31 +02:00
|
|
|
g_assert(err == NULL);
|
2021-03-12 18:35:45 +01:00
|
|
|
qobject_unref(qdict);
|
|
|
|
|
|
|
|
dobj = DUMMY_OBJECT(object_resolve_path_component(object_get_objects_root(),
|
|
|
|
"dev0"));
|
2017-06-04 01:13:31 +02:00
|
|
|
g_assert(dobj);
|
|
|
|
g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss");
|
|
|
|
g_assert(dobj->bv == true);
|
|
|
|
g_assert(dobj->av == DUMMY_PLATYPUS);
|
|
|
|
|
2021-03-12 18:35:45 +01:00
|
|
|
qdict = keyval_parse(params, "qom-type", &help, &err);
|
|
|
|
created = test_create_obj(qdict, &err);
|
|
|
|
g_assert(!created);
|
|
|
|
g_assert(err);
|
|
|
|
g_assert(object_resolve_path_component(object_get_objects_root(), "dev0")
|
|
|
|
== OBJECT(dobj));
|
|
|
|
qobject_unref(qdict);
|
|
|
|
error_free(err);
|
|
|
|
err = NULL;
|
|
|
|
|
|
|
|
qdict = keyval_parse(params, "qom-type", &help, &err);
|
2020-06-30 11:03:29 +02:00
|
|
|
user_creatable_del("dev0", &error_abort);
|
2021-03-12 18:35:45 +01:00
|
|
|
g_assert(object_resolve_path_component(object_get_objects_root(), "dev0")
|
|
|
|
== NULL);
|
2017-06-04 01:13:31 +02:00
|
|
|
|
2021-03-12 18:35:45 +01:00
|
|
|
created = test_create_obj(qdict, &err);
|
|
|
|
g_assert(created);
|
|
|
|
g_assert(err == NULL);
|
|
|
|
qobject_unref(qdict);
|
|
|
|
|
|
|
|
dobj = DUMMY_OBJECT(object_resolve_path_component(object_get_objects_root(),
|
|
|
|
"dev0"));
|
|
|
|
g_assert(dobj);
|
|
|
|
g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss");
|
|
|
|
g_assert(dobj->bv == true);
|
|
|
|
g_assert(dobj->av == DUMMY_PLATYPUS);
|
|
|
|
g_assert(object_resolve_path_component(object_get_objects_root(), "dev0")
|
|
|
|
== OBJECT(dobj));
|
|
|
|
|
|
|
|
object_unparent(OBJECT(dobj));
|
2017-06-04 01:13:31 +02:00
|
|
|
}
|
|
|
|
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:08 +02:00
|
|
|
static void test_dummy_badenum(void)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
Object *parent = object_get_objects_root();
|
|
|
|
Object *dobj =
|
|
|
|
object_new_with_props(TYPE_DUMMY,
|
|
|
|
parent,
|
|
|
|
"dummy0",
|
|
|
|
&err,
|
|
|
|
"bv", "yes",
|
|
|
|
"sv", "Hiss hiss hiss",
|
|
|
|
"av", "yeti",
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
g_assert(dobj == NULL);
|
|
|
|
g_assert(err != NULL);
|
|
|
|
g_assert_cmpstr(error_get_pretty(err), ==,
|
2021-10-20 20:02:31 +02:00
|
|
|
"Parameter 'av' does not accept value 'yeti'");
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:08 +02:00
|
|
|
|
|
|
|
g_assert(object_resolve_path_component(parent, "dummy0")
|
|
|
|
== NULL);
|
|
|
|
|
|
|
|
error_free(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-27 17:07:56 +02:00
|
|
|
static void test_dummy_getenum(void)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
int val;
|
|
|
|
Object *parent = object_get_objects_root();
|
|
|
|
DummyObject *dobj = DUMMY_OBJECT(
|
|
|
|
object_new_with_props(TYPE_DUMMY,
|
|
|
|
parent,
|
|
|
|
"dummy0",
|
|
|
|
&err,
|
|
|
|
"av", "platypus",
|
|
|
|
NULL));
|
|
|
|
|
|
|
|
g_assert(err == NULL);
|
|
|
|
g_assert(dobj->av == DUMMY_PLATYPUS);
|
|
|
|
|
|
|
|
val = object_property_get_enum(OBJECT(dobj),
|
|
|
|
"av",
|
|
|
|
"DummyAnimal",
|
2020-06-30 11:03:29 +02:00
|
|
|
&error_abort);
|
2015-05-27 17:07:56 +02:00
|
|
|
g_assert(val == DUMMY_PLATYPUS);
|
|
|
|
|
|
|
|
/* A bad enum type name */
|
|
|
|
val = object_property_get_enum(OBJECT(dobj),
|
|
|
|
"av",
|
|
|
|
"BadAnimal",
|
|
|
|
&err);
|
2020-09-17 14:55:39 +02:00
|
|
|
g_assert(val == -1);
|
2020-06-30 11:03:30 +02:00
|
|
|
error_free_or_abort(&err);
|
2015-05-27 17:07:56 +02:00
|
|
|
|
|
|
|
/* A non-enum property name */
|
|
|
|
val = object_property_get_enum(OBJECT(dobj),
|
|
|
|
"iv",
|
|
|
|
"DummyAnimal",
|
|
|
|
&err);
|
2020-09-17 14:55:39 +02:00
|
|
|
g_assert(val == -1);
|
2020-06-30 11:03:30 +02:00
|
|
|
error_free_or_abort(&err);
|
2015-10-13 14:37:40 +02:00
|
|
|
|
|
|
|
object_unparent(OBJECT(dobj));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-05 17:29:16 +02:00
|
|
|
static void test_dummy_prop_iterator(ObjectPropertyIterator *iter,
|
|
|
|
const char *expected[], int n)
|
2015-10-13 14:37:40 +02:00
|
|
|
{
|
|
|
|
ObjectProperty *prop;
|
2020-05-05 17:29:16 +02:00
|
|
|
int i;
|
2015-10-13 14:37:40 +02:00
|
|
|
|
2018-09-06 16:13:34 +02:00
|
|
|
while ((prop = object_property_iter_next(iter))) {
|
2020-05-05 17:29:16 +02:00
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
if (!g_strcmp0(prop->name, expected[i])) {
|
|
|
|
break;
|
|
|
|
}
|
2015-10-13 14:37:40 +02:00
|
|
|
}
|
2020-05-05 17:29:16 +02:00
|
|
|
g_assert(i < n);
|
|
|
|
expected[i] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
g_assert(!expected[i]);
|
2015-10-13 14:37:40 +02:00
|
|
|
}
|
2018-09-06 16:13:34 +02:00
|
|
|
}
|
2015-10-13 14:37:40 +02:00
|
|
|
|
2018-09-06 16:13:34 +02:00
|
|
|
static void test_dummy_iterator(void)
|
|
|
|
{
|
2020-05-05 17:29:16 +02:00
|
|
|
const char *expected[] = {
|
|
|
|
"type", /* inherited from TYPE_OBJECT */
|
|
|
|
"sv", "av", /* class properties */
|
|
|
|
"bv"}; /* instance property */
|
2018-09-06 16:13:34 +02:00
|
|
|
Object *parent = object_get_objects_root();
|
|
|
|
DummyObject *dobj = DUMMY_OBJECT(
|
|
|
|
object_new_with_props(TYPE_DUMMY,
|
|
|
|
parent,
|
|
|
|
"dummy0",
|
|
|
|
&error_abort,
|
|
|
|
"bv", "yes",
|
|
|
|
"sv", "Hiss hiss hiss",
|
|
|
|
"av", "platypus",
|
|
|
|
NULL));
|
|
|
|
ObjectPropertyIterator iter;
|
|
|
|
|
|
|
|
object_property_iter_init(&iter, OBJECT(dobj));
|
2020-05-05 17:29:16 +02:00
|
|
|
test_dummy_prop_iterator(&iter, expected, ARRAY_SIZE(expected));
|
2015-10-13 14:37:40 +02:00
|
|
|
object_unparent(OBJECT(dobj));
|
2015-05-27 17:07:56 +02:00
|
|
|
}
|
|
|
|
|
2018-09-06 16:14:01 +02:00
|
|
|
static void test_dummy_class_iterator(void)
|
|
|
|
{
|
2020-05-05 17:29:16 +02:00
|
|
|
const char *expected[] = { "type", "av", "sv" };
|
2018-09-06 16:14:01 +02:00
|
|
|
ObjectPropertyIterator iter;
|
|
|
|
ObjectClass *klass = object_class_by_name(TYPE_DUMMY);
|
|
|
|
|
|
|
|
object_class_property_iter_init(&iter, klass);
|
2020-05-05 17:29:16 +02:00
|
|
|
test_dummy_prop_iterator(&iter, expected, ARRAY_SIZE(expected));
|
2018-09-06 16:14:01 +02:00
|
|
|
}
|
2015-05-27 17:07:56 +02:00
|
|
|
|
2015-11-16 16:37:34 +01:00
|
|
|
static void test_dummy_delchild(void)
|
|
|
|
{
|
|
|
|
Object *parent = object_get_objects_root();
|
|
|
|
DummyDev *dev = DUMMY_DEV(
|
|
|
|
object_new_with_props(TYPE_DUMMY_DEV,
|
|
|
|
parent,
|
|
|
|
"dev0",
|
|
|
|
&error_abort,
|
|
|
|
NULL));
|
|
|
|
|
|
|
|
object_unparent(OBJECT(dev));
|
|
|
|
}
|
|
|
|
|
2017-07-07 23:30:51 +02:00
|
|
|
static void test_qom_partial_path(void)
|
|
|
|
{
|
|
|
|
Object *root = object_get_objects_root();
|
|
|
|
Object *cont1 = container_get(root, "/cont1");
|
|
|
|
Object *obj1 = object_new(TYPE_DUMMY);
|
|
|
|
Object *obj2a = object_new(TYPE_DUMMY);
|
|
|
|
Object *obj2b = object_new(TYPE_DUMMY);
|
|
|
|
bool ambiguous;
|
|
|
|
|
|
|
|
/* Objects created:
|
|
|
|
* /cont1
|
|
|
|
* /cont1/obj1
|
|
|
|
* /cont1/obj2 (obj2a)
|
|
|
|
* /obj2 (obj2b)
|
|
|
|
*/
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
object_property_add_child(cont1, "obj1", obj1);
|
2017-07-07 23:30:51 +02:00
|
|
|
object_unref(obj1);
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
object_property_add_child(cont1, "obj2", obj2a);
|
2017-07-07 23:30:51 +02:00
|
|
|
object_unref(obj2a);
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 17:29:22 +02:00
|
|
|
object_property_add_child(root, "obj2", obj2b);
|
2017-07-07 23:30:51 +02:00
|
|
|
object_unref(obj2b);
|
|
|
|
|
|
|
|
ambiguous = false;
|
|
|
|
g_assert(!object_resolve_path_type("", TYPE_DUMMY, &ambiguous));
|
|
|
|
g_assert(ambiguous);
|
2017-07-07 23:30:52 +02:00
|
|
|
g_assert(!object_resolve_path_type("", TYPE_DUMMY, NULL));
|
2017-07-07 23:30:51 +02:00
|
|
|
|
|
|
|
ambiguous = false;
|
|
|
|
g_assert(!object_resolve_path("obj2", &ambiguous));
|
|
|
|
g_assert(ambiguous);
|
2017-07-07 23:30:52 +02:00
|
|
|
g_assert(!object_resolve_path("obj2", NULL));
|
2017-07-07 23:30:51 +02:00
|
|
|
|
|
|
|
ambiguous = false;
|
|
|
|
g_assert(object_resolve_path("obj1", &ambiguous) == obj1);
|
|
|
|
g_assert(!ambiguous);
|
2017-07-07 23:30:52 +02:00
|
|
|
g_assert(object_resolve_path("obj1", NULL) == obj1);
|
2017-07-07 23:30:51 +02:00
|
|
|
|
|
|
|
object_unparent(obj2b);
|
|
|
|
object_unparent(cont1);
|
|
|
|
}
|
|
|
|
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
g_test_init(&argc, &argv, NULL);
|
|
|
|
|
|
|
|
module_call_init(MODULE_INIT_QOM);
|
|
|
|
type_register_static(&dummy_info);
|
2015-11-16 16:37:34 +01:00
|
|
|
type_register_static(&dummy_dev_info);
|
|
|
|
type_register_static(&dummy_bus_info);
|
|
|
|
type_register_static(&dummy_backend_info);
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
|
|
|
|
g_test_add_func("/qom/proplist/createlist", test_dummy_createlist);
|
|
|
|
g_test_add_func("/qom/proplist/createv", test_dummy_createv);
|
2017-06-04 01:13:31 +02:00
|
|
|
g_test_add_func("/qom/proplist/createcmdline", test_dummy_createcmdl);
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:08 +02:00
|
|
|
g_test_add_func("/qom/proplist/badenum", test_dummy_badenum);
|
2015-05-27 17:07:56 +02:00
|
|
|
g_test_add_func("/qom/proplist/getenum", test_dummy_getenum);
|
2015-10-13 14:37:40 +02:00
|
|
|
g_test_add_func("/qom/proplist/iterator", test_dummy_iterator);
|
2018-09-06 16:14:01 +02:00
|
|
|
g_test_add_func("/qom/proplist/class_iterator", test_dummy_class_iterator);
|
2015-11-16 16:37:34 +01:00
|
|
|
g_test_add_func("/qom/proplist/delchild", test_dummy_delchild);
|
2017-07-07 23:30:51 +02:00
|
|
|
g_test_add_func("/qom/resolve/partial", test_qom_partial_path);
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 18:14:06 +02:00
|
|
|
|
|
|
|
return g_test_run();
|
|
|
|
}
|