Define the qom-tree-get QAPI command, which fetches an entire tree of properties and values with a single QAPI call. This is much faster than using qom-list plus qom-get for every node and property of the tree. See qom.json for details.
Signed-off-by: Steve Sistare <steven.sist...@oracle.com> --- qapi/qom.json | 56 ++++++++++++++++++++++++++++++++++++++++++ qom/qom-qmp-cmds.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/qapi/qom.json b/qapi/qom.json index 28ce24c..94662ad 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -46,6 +46,38 @@ '*default-value': 'any' } } ## +# @ObjectPropertyValue: +# +# @name: the name of the property +# +# @type: the type of the property, as described in @ObjectPropertyInfo +# +# @value: the value of the property. Omitted if cannot be read. +# +# Since 10.1 +## +{ 'struct': 'ObjectPropertyValue', + 'data': { 'name': 'str', + 'type': 'str', + '*value': 'any' } } + +## +# @ObjectNode: +# +# @name: the name of the node +# +# @children: child nodes +# +# @properties: properties of the node +# +# Since 10.1 +## +{ 'struct': 'ObjectNode', + 'data': { 'name': 'str', + 'children': [ 'ObjectNode' ], + 'properties': [ 'ObjectPropertyValue' ] }} + +## # @qom-list: # # This command will list any properties of a object given a path in @@ -126,6 +158,30 @@ 'allow-preconfig': true } ## +# @qom-tree-get: +# +# This command returns a tree of objects and their properties, +# rooted at the specified path. +# +# @path: The absolute or partial path within the object model, as +# described in @qom-get +# +# Errors: +# - If path is not valid or is ambiguous, returns an error. +# - If a property cannot be read, the value field is omitted in +# the corresponding @ObjectPropertyValue. +# +# Returns: A tree of @ObjectNode. Each node contains its name, list +# of properties, and list of child nodes. +# +# Since 10.1 +## +{ 'command': 'qom-tree-get', + 'data': { 'path': 'str' }, + 'returns': 'ObjectNode', + 'allow-preconfig': true } + +## # @qom-set: # # This command will set a property from a object model path. diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c index 293755f..b876681 100644 --- a/qom/qom-qmp-cmds.c +++ b/qom/qom-qmp-cmds.c @@ -69,6 +69,78 @@ ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp) return props; } +static void qom_list_add_property_value(Object *obj, ObjectProperty *prop, + ObjectPropertyValueList **props) +{ + ObjectPropertyValue *item = g_new0(ObjectPropertyValue, 1); + Error *err = NULL; + + QAPI_LIST_PREPEND(*props, item); + + item->name = g_strdup(prop->name); + item->type = g_strdup(prop->type); + item->value = object_property_get_qobject(obj, prop->name, &err); + + if (!item->value) { + /* + * For bulk get, the error message is dropped, but the value field + * is omitted so the caller knows this property could not be read. + */ + error_free(err); + } +} + +static ObjectNode *qom_tree_get(const char *path, Error **errp) +{ + Object *obj; + ObjectProperty *prop; + ObjectNode *result, *child; + ObjectPropertyIterator iter; + + obj = qom_resolve_path(path, errp); + if (obj == NULL) { + return NULL; + } + + result = g_new0(ObjectNode, 1); + + object_property_iter_init(&iter, obj); + while ((prop = object_property_iter_next(&iter))) { + if (strstart(prop->type, "child<", NULL)) { + g_autofree char *child_path = g_strdup_printf("%s/%s", + path, prop->name); + child = qom_tree_get(child_path, errp); + if (!child) { + qapi_free_ObjectNode(result); + return NULL; + } + child->name = g_strdup(prop->name); + QAPI_LIST_PREPEND(result->children, child); + } else { + qom_list_add_property_value(obj, prop, &result->properties); + } + } + + return result; +} + +ObjectNode *qmp_qom_tree_get(const char *path, Error **errp) +{ + ObjectNode *result = qom_tree_get(path, errp); + + if (result) { + /* Strip the path prefix if any */ + const char *basename = strrchr(path, '/'); + + if (!basename || !basename[1]) { + result->name = g_strdup(path); + } else { + result->name = g_strdup(basename + 1); + } + } + return result; +} + void qmp_qom_set(const char *path, const char *property, QObject *value, Error **errp) { -- 1.8.3.1