Copying Andreas into the qom: related patch in this series On Mon, Jan 11, 2016 at 03:00:45PM +0000, Daniel P. Berrange wrote: > The QMP monitor code has two helper methods object_add > and qmp_object_del that are called from several places > in the code (QMP, HMP and main emulator startup). > > The HMP and main emulator startup code also share > further logic that extracts the qom-type & id > values from a qdict. > > We soon need to use this logic from qemu-img, qemu-io > and qemu-nbd too, but don't want those to depend on > the monitor, nor do we want to duplicate the code. > > To avoid this, move some code out of qmp.c and hmp.c > adding 3 new methods to qom/object_interfaces.c > > - user_creatable_add - takes a QDict holding a full > object definition & instantiates it > - user_creatable_add_type - takes an ID, type name, > and QDict holding object properties & instantiates > it > - user_creatable_del - takes an ID and deletes the > corresponding object > > The existing code is updated to use these new methods. > > Signed-off-by: Daniel P. Berrange <berra...@redhat.com> > --- > hmp.c | 52 ++++----------- > include/monitor/monitor.h | 3 - > include/qom/object_interfaces.h | 48 ++++++++++++++ > qmp.c | 76 ++-------------------- > qom/object_interfaces.c | 139 > ++++++++++++++++++++++++++++++++++++++++ > vl.c | 48 ++++---------- > 6 files changed, 216 insertions(+), 150 deletions(-) > > diff --git a/hmp.c b/hmp.c > index c2b2c16..6a9c51d 100644 > --- a/hmp.c > +++ b/hmp.c > @@ -29,6 +29,7 @@ > #include "qapi/string-output-visitor.h" > #include "qapi/util.h" > #include "qapi-visit.h" > +#include "qom/object_interfaces.h" > #include "ui/console.h" > #include "block/qapi.h" > #include "qemu-io.h" > @@ -1663,58 +1664,27 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict) > void hmp_object_add(Monitor *mon, const QDict *qdict) > { > Error *err = NULL; > - Error *err_end = NULL; > QemuOpts *opts; > - char *type = NULL; > - char *id = NULL; > - void *dummy = NULL; > OptsVisitor *ov; > - QDict *pdict; > + Object *obj = NULL; > > opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err); > if (err) { > - goto out; > + hmp_handle_error(mon, &err); > + return; > } > > ov = opts_visitor_new(opts); > - pdict = qdict_clone_shallow(qdict); > - > - visit_start_struct(opts_get_visitor(ov), &dummy, NULL, NULL, 0, &err); > - if (err) { > - goto out_clean; > - } > - > - qdict_del(pdict, "qom-type"); > - visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err); > - if (err) { > - goto out_end; > - } > + obj = user_creatable_add(qdict, opts_get_visitor(ov), &err); > + opts_visitor_cleanup(ov); > + qemu_opts_del(opts); > > - qdict_del(pdict, "id"); > - visit_type_str(opts_get_visitor(ov), &id, "id", &err); > if (err) { > - goto out_end; > + hmp_handle_error(mon, &err); > } > - > - object_add(type, id, pdict, opts_get_visitor(ov), &err); > - > -out_end: > - visit_end_struct(opts_get_visitor(ov), &err_end); > - if (!err && err_end) { > - qmp_object_del(id, NULL); > + if (obj) { > + object_unref(obj); > } > - error_propagate(&err, err_end); > -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) > @@ -1944,7 +1914,7 @@ void hmp_object_del(Monitor *mon, const QDict *qdict) > const char *id = qdict_get_str(qdict, "id"); > Error *err = NULL; > > - qmp_object_del(id, &err); > + user_creatable_del(id, &err); > hmp_handle_error(mon, &err); > } > > diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h > index 91b95ae..aa0f373 100644 > --- a/include/monitor/monitor.h > +++ b/include/monitor/monitor.h > @@ -43,9 +43,6 @@ void monitor_read_command(Monitor *mon, int show_prompt); > int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, > void *opaque); > > -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, > Error **errp); > diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h > index 283ae0d..7bbaf2f 100644 > --- a/include/qom/object_interfaces.h > +++ b/include/qom/object_interfaces.h > @@ -2,6 +2,8 @@ > #define OBJECT_INTERFACES_H > > #include "qom/object.h" > +#include "qapi/qmp/qdict.h" > +#include "qapi/visitor.h" > > #define TYPE_USER_CREATABLE "user-creatable" > > @@ -72,4 +74,50 @@ void user_creatable_complete(Object *obj, Error **errp); > * from implements USER_CREATABLE interface. > */ > bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp); > + > +/** > + * user_creatable_add: > + * @qdict: the object definition > + * @v: the visitor > + * @errp: if an error occurs, a pointer to an area to store the error > + * > + * Create an instance of the user creatable object whose type, > + * is defined in @qdict by the 'qom-type' field, placing it > + * in the object composition tree with name provided by the > + * 'id' field. The remaining fields in @qdict are used to > + * initialize the object properties. > + * > + * Returns: the newly created object or NULL on error > + */ > +Object *user_creatable_add(const QDict *qdict, > + Visitor *v, Error **errp); > + > +/** > + * user_creatable_add_type: > + * @type: the object type name > + * @id: the unique ID for the object > + * @qdict: the object properties > + * @v: the visitor > + * @errp: if an error occurs, a pointer to an area to store the error > + * > + * Create an instance of the user creatable object @type, placing > + * it in the object composition tree with name @id, initializing > + * it with properties from @qdict > + * > + * Returns: the newly created object or NULL on error > + */ > +Object *user_creatable_add_type(const char *type, const char *id, > + const QDict *qdict, > + Visitor *v, Error **errp); > + > +/** > + * user_creatable_del: > + * @id: the unique ID for the object > + * @errp: if an error occurs, a pointer to an area to store the error > + * > + * Delete an instance of the user creatable object identified > + * by @id. > + */ > +void user_creatable_del(const char *id, Error **errp); > + > #endif > diff --git a/qmp.c b/qmp.c > index 0a1fa19..15fee9b 100644 > --- a/qmp.c > +++ b/qmp.c > @@ -622,65 +622,13 @@ void qmp_add_client(const char *protocol, const char > *fdname, > close(fd); > } > > -void object_add(const char *type, const char *id, const QDict *qdict, > - Visitor *v, Error **errp) > -{ > - Object *obj; > - ObjectClass *klass; > - const QDictEntry *e; > - Error *local_err = NULL; > - > - klass = object_class_by_name(type); > - if (!klass) { > - error_setg(errp, "invalid object type: %s", type); > - return; > - } > - > - if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) { > - error_setg(errp, "object type '%s' isn't supported by object-add", > - type); > - return; > - } > - > - if (object_class_is_abstract(klass)) { > - error_setg(errp, "object type '%s' is abstract", type); > - 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 (local_err) { > - goto out; > - } > - } > - } > - > - object_property_add_child(object_get_objects_root(), > - id, obj, &local_err); > - if (local_err) { > - goto out; > - } > - > - user_creatable_complete(obj, &local_err); > - if (local_err) { > - object_property_del(object_get_objects_root(), > - id, &error_abort); > - goto out; > - } > -out: > - if (local_err) { > - error_propagate(errp, local_err); > - } > - object_unref(obj); > -} > > void qmp_object_add(const char *type, const char *id, > bool has_props, QObject *props, Error **errp) > { > const QDict *pdict = NULL; > QmpInputVisitor *qiv; > + Object *obj; > > if (props) { > pdict = qobject_to_qdict(props); > @@ -691,27 +639,17 @@ void qmp_object_add(const char *type, const char *id, > } > > qiv = qmp_input_visitor_new(props); > - object_add(type, id, pdict, qmp_input_get_visitor(qiv), errp); > + obj = user_creatable_add_type(type, id, pdict, > + qmp_input_get_visitor(qiv), errp); > qmp_input_visitor_cleanup(qiv); > + if (obj) { > + object_unref(obj); > + } > } > > void qmp_object_del(const char *id, Error **errp) > { > - Object *container; > - Object *obj; > - > - container = object_get_objects_root(); > - obj = object_resolve_path_component(container, id); > - if (!obj) { > - error_setg(errp, "object id not found"); > - return; > - } > - > - if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) { > - error_setg(errp, "%s is in use, can not be deleted", id); > - return; > - } > - object_unparent(obj); > + user_creatable_del(id, errp); > } > > MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp) > diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c > index a66cd60..9c15db3 100644 > --- a/qom/object_interfaces.c > +++ b/qom/object_interfaces.c > @@ -30,6 +30,145 @@ bool user_creatable_can_be_deleted(UserCreatable *uc, > Error **errp) > } > } > > + > +Object *user_creatable_add(const QDict *qdict, > + Visitor *v, Error **errp) > +{ > + char *type = NULL; > + char *id = NULL; > + Object *obj = NULL; > + Error *local_err = NULL, *end_err = NULL; > + QDict *pdict; > + > + pdict = qdict_clone_shallow(qdict); > + > + visit_start_struct(v, NULL, NULL, NULL, 0, &local_err); > + if (local_err) { > + goto out; > + } > + > + qdict_del(pdict, "qom-type"); > + visit_type_str(v, &type, "qom-type", &local_err); > + if (local_err) { > + goto out_visit; > + } > + > + qdict_del(pdict, "id"); > + visit_type_str(v, &id, "id", &local_err); > + if (local_err) { > + goto out_visit; > + } > + > + obj = user_creatable_add_type(type, id, pdict, v, &local_err); > + if (local_err) { > + goto out_visit; > + } > + > + out_visit: > + visit_end_struct(v, &end_err); > + if (end_err) { > + if (!local_err) { > + error_propagate(&local_err, end_err); > + } else { > + error_free(end_err); > + } > + if (obj) { > + user_creatable_del(id, NULL); > + } > + goto out; > + } > + > +out: > + QDECREF(pdict); > + g_free(id); > + g_free(type); > + if (local_err) { > + error_propagate(errp, local_err); > + if (obj) { > + object_unref(obj); > + } > + return NULL; > + } > + return obj; > +} > + > + > +Object *user_creatable_add_type(const char *type, const char *id, > + const QDict *qdict, > + Visitor *v, Error **errp) > +{ > + Object *obj; > + ObjectClass *klass; > + const QDictEntry *e; > + Error *local_err = NULL; > + > + klass = object_class_by_name(type); > + if (!klass) { > + error_setg(errp, "invalid object type: %s", type); > + return NULL; > + } > + > + if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) { > + error_setg(errp, "object type '%s' isn't supported by object-add", > + type); > + return NULL; > + } > + > + if (object_class_is_abstract(klass)) { > + error_setg(errp, "object type '%s' is abstract", type); > + return NULL; > + } > + > + 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 (local_err) { > + goto out; > + } > + } > + } > + > + object_property_add_child(object_get_objects_root(), > + id, obj, &local_err); > + if (local_err) { > + goto out; > + } > + > + user_creatable_complete(obj, &local_err); > + if (local_err) { > + object_property_del(object_get_objects_root(), > + id, &error_abort); > + goto out; > + } > +out: > + if (local_err) { > + error_propagate(errp, local_err); > + object_unref(obj); > + return NULL; > + } > + return obj; > +} > + > +void user_creatable_del(const char *id, Error **errp) > +{ > + Object *container; > + Object *obj; > + > + container = object_get_objects_root(); > + obj = object_resolve_path_component(container, id); > + if (!obj) { > + error_setg(errp, "object id not found"); > + return; > + } > + > + if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) { > + error_setg(errp, "%s is in use, can not be deleted", id); > + return; > + } > + object_unparent(obj); > +} > + > static void register_types(void) > { > static const TypeInfo uc_interface_info = { > diff --git a/vl.c b/vl.c > index 5aaea77..0287f48 100644 > --- a/vl.c > +++ b/vl.c > @@ -2828,52 +2828,26 @@ static bool object_create_delayed(const char *type) > static int object_create(void *opaque, QemuOpts *opts, Error **errp) > { > Error *err = NULL; > - char *type = NULL; > - char *id = NULL; > - void *dummy = NULL; > OptsVisitor *ov; > QDict *pdict; > bool (*type_predicate)(const char *) = opaque; > + Object *obj = NULL; > + const char *type; > > - ov = opts_visitor_new(opts); > - pdict = qemu_opts_to_qdict(opts, NULL); > - > - visit_start_struct(opts_get_visitor(ov), &dummy, NULL, NULL, 0, &err); > - if (err) { > - goto out; > - } > - > - qdict_del(pdict, "qom-type"); > - visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err); > - if (err) { > - goto out; > - } > - if (!type_predicate(type)) { > - goto out; > - } > - > - qdict_del(pdict, "id"); > - visit_type_str(opts_get_visitor(ov), &id, "id", &err); > - if (err) { > - goto out; > + type = qemu_opt_get(opts, "qom-type"); > + if (type && !type_predicate(type)) { > + return 0; > } > > - object_add(type, id, pdict, opts_get_visitor(ov), &err); > - if (err) { > - goto out; > - } > - visit_end_struct(opts_get_visitor(ov), &err); > - if (err) { > - qmp_object_del(id, NULL); > - } > + ov = opts_visitor_new(opts); > + pdict = qemu_opts_to_qdict(opts, NULL); > > -out: > + obj = user_creatable_add(pdict, opts_get_visitor(ov), &err); > opts_visitor_cleanup(ov); > - > QDECREF(pdict); > - g_free(id); > - g_free(type); > - g_free(dummy); > + if (obj) { > + object_unref(obj); > + } > if (err) { > error_report_err(err); > return -1; > -- > 2.5.0 >
Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|