From: Paolo Bonzini <pbonzini@redhat.com>
To: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Cc: Igor Mammedov <imammedo@redhat.com>,
"qemu-devel@nongnu.org Developers" <qemu-devel@nongnu.org>,
Stefan Hajnoczi <stefanha@redhat.com>,
lcapitulino@redhat.com
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 [thread overview]
Message-ID: <52B0428F.7020101@redhat.com> (raw)
In-Reply-To: <CAEgOgz6jBJDMjDc3xY03Kd89RJOqoZvrXa1oPtuMaN3ebA3Ypg@mail.gmail.com>
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
>>
>>
>>
next prev parent reply other threads:[~2013-12-17 12:25 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-17 11:25 [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Paolo Bonzini
2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 1/5] rng: initialize file descriptor to -1 Paolo Bonzini
2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 2/5] qom: fix leak for objects created with -object Paolo Bonzini
2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 3/5] qom: catch errors in object_property_add_child Paolo Bonzini
2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command Paolo Bonzini
2013-12-17 11:54 ` Peter Crosthwaite
2013-12-17 12:24 ` Paolo Bonzini [this message]
2013-12-17 12:38 ` Peter Crosthwaite
2013-12-17 13:07 ` Markus Armbruster
2013-12-17 21:56 ` Peter Crosthwaite
2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 5/5] monitor: add object-del (QMP) and object_del " Paolo Bonzini
2013-12-18 13:00 ` [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Igor Mammedov
2013-12-18 16:36 ` Luiz Capitulino
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52B0428F.7020101@redhat.com \
--to=pbonzini@redhat.com \
--cc=imammedo@redhat.com \
--cc=lcapitulino@redhat.com \
--cc=peter.crosthwaite@xilinx.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.