[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object
From: |
Paolo Bonzini |
Subject: |
Re: [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command |
Date: |
Tue, 17 Dec 2013 13:24:47 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130923 Thunderbird/17.0.9 |
Il 17/12/2013 12:54, Peter Crosthwaite ha scritto:
>> + visit_start_struct(opts_get_visitor(ov), &dummy, NULL, NULL, 0, &err);
>> + if (error_is_set(&err)) {
>> + goto out_clean;
>> + }
>
> So I have been thinking about repeated if(error_is_set(&err)) { goto
> foo; } and how to reduce its verbosity in situations like this. Can it
> be solved with a simple semantic:
>
> "Error ** accepting APIs will perform no action if the Error **
> argument is already set."
I think this is a case where verbosity <<< ease of use.
In this case, the caller code is particularly simple, but what if I
needed to dereference the return value of the first called function, to
get the argument to the second? You would still need an "if".
Paolo
> In this case we would patch visit_foo to just return if
> error_is_set(errp). Then we can delete these three LOC...
>
>> +
>> + qdict_del(pdict, "qom-type");
>> + visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err);
>> + if (error_is_set(&err)) {
>> + goto out_clean;
>> + }
>> +
>
> and these
>
>> + qdict_del(pdict, "id");
>> + visit_type_str(opts_get_visitor(ov), &id, "id", &err);
>> + if (error_is_set(&err)) {
>> + goto out_clean;
>> + }
>
> and these
>
>> +
>> + object_add(type, id, pdict, opts_get_visitor(ov), &err);
>> + if (error_is_set(&err)) {
>> + goto out_clean;
>> + }
>
> And leave just the last one which will catch and report the
> first-occured error as desired.
>
> Out of scope of the series of course.
>
> Regards,
> Peter
>
>> + visit_end_struct(opts_get_visitor(ov), &err);
>> + if (error_is_set(&err)) {
>> + qmp_object_del(id, NULL);
>> + }
>> +
>> +out_clean:
>> + opts_visitor_cleanup(ov);
>> +
>> + QDECREF(pdict);
>> + qemu_opts_del(opts);
>> + g_free(id);
>> + g_free(type);
>> + g_free(dummy);
>> +
>> +out:
>> + hmp_handle_error(mon, &err);
>> +}
>> +
>> void hmp_getfd(Monitor *mon, const QDict *qdict)
>> {
>> const char *fdname = qdict_get_str(qdict, "fdname");
>> diff --git a/hmp.h b/hmp.h
>> index 54cf71f..521449b 100644
>> --- a/hmp.h
>> +++ b/hmp.h
>> @@ -89,5 +89,6 @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
>> void hmp_chardev_add(Monitor *mon, const QDict *qdict);
>> void hmp_chardev_remove(Monitor *mon, const QDict *qdict);
>> void hmp_qemu_io(Monitor *mon, const QDict *qdict);
>> +void hmp_object_add(Monitor *mon, const QDict *qdict);
>>
>> #endif
>> diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
>> index 10fa0e3..22d8b8f 100644
>> --- a/include/monitor/monitor.h
>> +++ b/include/monitor/monitor.h
>> @@ -93,6 +93,9 @@ int monitor_read_password(Monitor *mon, ReadLineFunc
>> *readline_func,
>> int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret);
>>
>> int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret);
>> +int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret);
>> +void object_add(const char *type, const char *id, const QDict *qdict,
>> + Visitor *v, Error **errp);
>>
>> AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id,
>> bool has_opaque, const char *opaque,
>> diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
>> index 48a2a2e..29da211 100644
>> --- a/include/qapi/visitor.h
>> +++ b/include/qapi/visitor.h
>> @@ -13,6 +13,7 @@
>> #ifndef QAPI_VISITOR_CORE_H
>> #define QAPI_VISITOR_CORE_H
>>
>> +#include "qemu/typedefs.h"
>> #include "qapi/qmp/qobject.h"
>> #include "qapi/error.h"
>> #include <stdlib.h>
>> @@ -26,8 +27,6 @@ typedef struct GenericList
>> struct GenericList *next;
>> } GenericList;
>>
>> -typedef struct Visitor Visitor;
>> -
>> void visit_start_handle(Visitor *v, void **obj, const char *kind,
>> const char *name, Error **errp);
>> void visit_end_handle(Visitor *v, Error **errp);
>> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
>> index a4c1b84..4524496 100644
>> --- a/include/qemu/typedefs.h
>> +++ b/include/qemu/typedefs.h
>> @@ -10,6 +10,8 @@ typedef struct QEMUBH QEMUBH;
>>
>> typedef struct AioContext AioContext;
>>
>> +typedef struct Visitor Visitor;
>> +
>> struct Monitor;
>> typedef struct Monitor Monitor;
>> typedef struct MigrationParams MigrationParams;
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index 83fa485..111463b 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -2759,6 +2759,26 @@
>> { 'command': 'netdev_del', 'data': {'id': 'str'} }
>>
>> ##
>> +# @object-add:
>> +#
>> +# Create a QOM object.
>> +#
>> +# @qom-type: the class name for the object to be created
>> +#
>> +# @id: the name of the new object
>> +#
>> +# @props: #optional a dictionary of properties to be passed to the backend
>> +#
>> +# Returns: Nothing on success
>> +# Error if @qom-type is not a valid class name
>> +#
>> +# Since: 2.0
>> +##
>> +{ 'command': 'object-add',
>> + 'data': {'qom-type': 'str', 'id': 'str', '*props': 'dict'},
>> + 'gen': 'no' }
>> +
>> +##
>> # @NetdevNoneOptions
>> #
>> # Use it alone to have zero network devices.
>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>> index fba15cd..d09ea53 100644
>> --- a/qmp-commands.hx
>> +++ b/qmp-commands.hx
>> @@ -879,6 +879,33 @@ Example:
>> EQMP
>>
>> {
>> + .name = "object-add",
>> + .args_type = "qom-type:s,id:s,props:q?",
>> + .mhandler.cmd_new = qmp_object_add,
>> + },
>> +
>> +SQMP
>> +object-add
>> +----------
>> +
>> +Create QOM object.
>> +
>> +Arguments:
>> +
>> +- "qom-type": the object's QOM type, i.e. the class name (json-string)
>> +- "id": the object's ID, must be unique (json-string)
>> +- "props": a dictionary of object property values (optional, json-dict)
>> +
>> +Example:
>> +
>> +-> { "execute": "object-add", "arguments": { "qom-type": "rng-random",
>> "id": "rng1",
>> + "props": { "filename": "/dev/hwrng" } } }
>> +<- { "return": {} }
>> +
>> +EQMP
>> +
>> +
>> + {
>> .name = "block_resize",
>> .args_type = "device:B,size:o",
>> .mhandler.cmd_new = qmp_marshal_input_block_resize,
>> diff --git a/qmp.c b/qmp.c
>> index 4c149b3..255c55f 100644
>> --- a/qmp.c
>> +++ b/qmp.c
>> @@ -24,6 +24,8 @@
>> #include "hw/qdev.h"
>> #include "sysemu/blockdev.h"
>> #include "qom/qom-qobject.h"
>> +#include "qapi/qmp/qobject.h"
>> +#include "qapi/qmp-input-visitor.h"
>> #include "hw/boards.h"
>>
>> NameInfo *qmp_query_name(Error **errp)
>> @@ -529,3 +531,63 @@ void qmp_add_client(const char *protocol, const char
>> *fdname,
>> error_setg(errp, "protocol '%s' is invalid", protocol);
>> close(fd);
>> }
>> +
>> +void object_add(const char *type, const char *id, const QDict *qdict,
>> + Visitor *v, Error **errp)
>> +{
>> + Object *obj;
>> + const QDictEntry *e;
>> + Error *local_err = NULL;
>> +
>> + if (!object_class_by_name(type)) {
>> + error_setg(errp, "invalid class name");
>> + return;
>> + }
>> +
>> + obj = object_new(type);
>> + if (qdict) {
>> + for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
>> + object_property_set(obj, v, e->key, &local_err);
>> + if (error_is_set(&local_err)) {
>> + error_propagate(errp, local_err);
>> + object_unref(obj);
>> + return;
>> + }
>> + }
>> + }
>> +
>> + object_property_add_child(container_get(object_get_root(), "/objects"),
>> + id, obj, errp);
>> + object_unref(obj);
>> +}
>> +
>> +int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret)
>> +{
>> + const char *type = qdict_get_str(qdict, "qom-type");
>> + const char *id = qdict_get_str(qdict, "id");
>> + QObject *props = qdict_get(qdict, "props");
>> + const QDict *pdict = NULL;
>> + Error *local_err = NULL;
>> + QmpInputVisitor *qiv;
>> +
>> + if (props) {
>> + pdict = qobject_to_qdict(props);
>> + if (!pdict) {
>> + error_set(&local_err, QERR_INVALID_PARAMETER_TYPE, "props",
>> "dict");
>> + goto out;
>> + }
>> + }
>> +
>> + qiv = qmp_input_visitor_new(props);
>> + object_add(type, id, pdict, qmp_input_get_visitor(qiv), &local_err);
>> + qmp_input_visitor_cleanup(qiv);
>> +
>> +out:
>> + if (local_err) {
>> + qerror_report_err(local_err);
>> + error_free(local_err);
>> + return -1;
>> + }
>> +
>> + return 0;
>> +}
>> --
>> 1.8.4.2
>>
>>
>>
[Qemu-devel] [PATCH v2 5/5] monitor: add object-del (QMP) and object_del (HMP) command, Paolo Bonzini, 2013/12/17
[Qemu-devel] [PATCH v2 2/5] qom: fix leak for objects created with -object, Paolo Bonzini, 2013/12/17
Re: [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del, Igor Mammedov, 2013/12/18
Re: [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del, Luiz Capitulino, 2013/12/18