qemu-devel
[Top][All Lists]
Advanced

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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]