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 >> >> >>