Re: [PATCH v3 22/30] qom: Factor out user_creatable_process_cmdline()

2021-03-15 Thread Kevin Wolf
Am 13.03.2021 um 09:41 hat Markus Armbruster geschrieben:
> Observation, not objection:
> 
> 1. QMP core parses JSON text into QObject, passes to generated
>marshaller.
> 
> 2. Marshaller converts QObject to ObjectOptions with the QObject input
>visitor, passes to qmp_object_add().
> 
> 3. qmp_object_add() wraps around user_creatable_add_qapi().
> 
> 4. user_creatable_add_qapi() converts right back to QObject with the
>QObject output visitor.  It splits the result into qom_type, id and
>the rest, and passes all three to user_creatable_add_type().
> 
> 5. user_creatable_add_type() performs a virtual visit with the QObject
>input visitor.  The outermost object it visits itself, its children
>it visits by calling object_property_set().
> 
> I sure hope we wouldn't write it this way from scratch :)
> 
> I think your patch is a reasonable step towards a QOM that is at peace
> with QAPI.  But there's plenty of work left.

Yes, obviously the conversion back to QObject is not great. There are
two reasons why we currently need it:

1. user_creatable_add_type() wants to iterate over all properties
   without knowing which properties exist. This should be fixed by not
   visiting the top level in user_creatable_add_type(), but moving this
   part to object-specific code (in the final state probably code
   generated from the QAPI schema).

2. We have ObjectOptions, but need to pass a visitor. We don't have a
   general purpose visitor that visits both sides. The clone visitor
   seems somewhat similar to what we need, but I seem to remember it was
   more restricted to its particular use case.

Kevin



Re: [PATCH v3 22/30] qom: Factor out user_creatable_process_cmdline()

2021-03-13 Thread Paolo Bonzini

On 13/03/21 09:41, Markus Armbruster wrote:

Observation, not objection:

1. QMP core parses JSON text into QObject, passes to generated
marshaller.

2. Marshaller converts QObject to ObjectOptions with the QObject input
visitor, passes to qmp_object_add().

3. qmp_object_add() wraps around user_creatable_add_qapi().

4. user_creatable_add_qapi() converts right back to QObject with the
QObject output visitor.  It splits the result into qom_type, id and
the rest, and passes all three to user_creatable_add_type().

5. user_creatable_add_type() performs a virtual visit with the QObject
input visitor.  The outermost object it visits itself, its children
it visits by calling object_property_set().

I sure hope we wouldn't write it this way from scratch:)


All problems in computer science ca be solved by adding another level of 
indirection, except those that can be solved by adding two more levels 
of indirection.



I think your patch is a reasonable step towards a QOM that is at peace
with QAPI.  But there's plenty of work left.


Absolutely, see https://wiki.qemu.org/Features/QOM-QAPI_integration for 
some brainstorming about it.


Paolo



Re: [PATCH v3 22/30] qom: Factor out user_creatable_process_cmdline()

2021-03-13 Thread Markus Armbruster
Kevin Wolf  writes:

> The implementation for --object can be shared between
> qemu-storage-daemon and other binaries, so move it into a function in
> qom/object_interfaces.c that is accessible from everywhere.
>
> This also requires moving the implementation of qmp_object_add() into a
> new user_creatable_add_qapi(), because qom/qom-qmp-cmds.c is not linked
> for tools.
>
> user_creatable_print_help_from_qdict() can become static now.
>
> Signed-off-by: Kevin Wolf 
> Acked-by: Peter Krempa 
> Reviewed-by: Eric Blake 
> ---
>  include/qom/object_interfaces.h  | 41 +++
>  qom/object_interfaces.c  | 50 +++-
>  qom/qom-qmp-cmds.c   | 20 +--
>  storage-daemon/qemu-storage-daemon.c | 24 ++---
>  4 files changed, 80 insertions(+), 55 deletions(-)
>
> diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
> index 5299603f50..1e6c51b541 100644
> --- a/include/qom/object_interfaces.h
> +++ b/include/qom/object_interfaces.h
> @@ -2,6 +2,7 @@
>  #define OBJECT_INTERFACES_H
>  
>  #include "qom/object.h"
> +#include "qapi/qapi-types-qom.h"
>  #include "qapi/visitor.h"
>  
>  #define TYPE_USER_CREATABLE "user-creatable"
> @@ -86,6 +87,18 @@ Object *user_creatable_add_type(const char *type, const 
> char *id,
>  const QDict *qdict,
>  Visitor *v, Error **errp);
>  
> +/**
> + * user_creatable_add_qapi:
> + * @options: the object definition
> + * @errp: if an error occurs, a pointer to an area to store the error
> + *
> + * Create an instance of the user creatable object according to the
> + * options passed in @opts as described in the QAPI schema documentation.
> + *
> + * Returns: the newly created object or NULL on error
> + */
> +void user_creatable_add_qapi(ObjectOptions *options, Error **errp);
> +
>  /**
>   * user_creatable_add_opts:
>   * @opts: the object definition
> @@ -131,6 +144,21 @@ typedef bool (*user_creatable_add_opts_predicate)(const 
> char *type);
>  int user_creatable_add_opts_foreach(void *opaque,
>  QemuOpts *opts, Error **errp);
>  
> +/**
> + * user_creatable_process_cmdline:
> + * @optarg: the object definition string as passed on the command line
> + *
> + * Create an instance of the user creatable object by parsing optarg
> + * with a keyval parser and implicit key 'qom-type', converting the
> + * result to ObjectOptions and calling into qmp_object_add().
> + *
> + * If a help option is given, print help instead and exit.
> + *
> + * This function is only meant to be called during command line parsing.
> + * It exits the process on failure or after printing help.
> + */
> +void user_creatable_process_cmdline(const char *optarg);
> +
>  /**
>   * user_creatable_print_help:
>   * @type: the QOM type to be added
> @@ -145,19 +173,6 @@ int user_creatable_add_opts_foreach(void *opaque,
>   */
>  bool user_creatable_print_help(const char *type, QemuOpts *opts);
>  
> -/**
> - * user_creatable_print_help_from_qdict:
> - * @args: options to create
> - *
> - * Prints help considering the other options given in @args (if "qom-type" is
> - * given and valid, print properties for the type, otherwise print valid 
> types)
> - *
> - * In contrast to user_creatable_print_help(), this function can't return 
> that
> - * no help was requested. It should only be called if we know that help is
> - * requested and it will always print some help.
> - */
> -void user_creatable_print_help_from_qdict(QDict *args);
> -
>  /**
>   * user_creatable_del:
>   * @id: the unique ID for the object
> diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
> index 02c3934329..2eaf9971f5 100644
> --- a/qom/object_interfaces.c
> +++ b/qom/object_interfaces.c
> @@ -2,10 +2,13 @@
>  
>  #include "qemu/cutils.h"
>  #include "qapi/error.h"
> +#include "qapi/qapi-commands-qom.h"
> +#include "qapi/qapi-visit-qom.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qapi/qmp/qjson.h"
>  #include "qapi/qobject-input-visitor.h"
> +#include "qapi/qobject-output-visitor.h"
>  #include "qom/object_interfaces.h"
>  #include "qemu/help_option.h"
>  #include "qemu/id.h"
> @@ -113,6 +116,29 @@ out:
>  return obj;
>  }
>  
> +void user_creatable_add_qapi(ObjectOptions *options, Error **errp)
> +{
> +Visitor *v;
> +QObject *qobj;
> +QDict *props;
> +Object *obj;
> +
> +v = qobject_output_visitor_new();
> +visit_type_ObjectOptions(v, NULL, , _abort);
> +visit_complete(v, );
> +visit_free(v);
> +
> +props = qobject_to(QDict, qobj);
> +qdict_del(props, "qom-type");
> +qdict_del(props, "id");
> +
> +v = qobject_input_visitor_new(QOBJECT(props));
> +obj = user_creatable_add_type(ObjectType_str(options->qom_type),
> +  options->id, props, v, errp);
> +object_unref(obj);
> +visit_free(v);
> +}
> +

Observation, 

[PATCH v3 22/30] qom: Factor out user_creatable_process_cmdline()

2021-03-08 Thread Kevin Wolf
The implementation for --object can be shared between
qemu-storage-daemon and other binaries, so move it into a function in
qom/object_interfaces.c that is accessible from everywhere.

This also requires moving the implementation of qmp_object_add() into a
new user_creatable_add_qapi(), because qom/qom-qmp-cmds.c is not linked
for tools.

user_creatable_print_help_from_qdict() can become static now.

Signed-off-by: Kevin Wolf 
Acked-by: Peter Krempa 
Reviewed-by: Eric Blake 
---
 include/qom/object_interfaces.h  | 41 +++
 qom/object_interfaces.c  | 50 +++-
 qom/qom-qmp-cmds.c   | 20 +--
 storage-daemon/qemu-storage-daemon.c | 24 ++---
 4 files changed, 80 insertions(+), 55 deletions(-)

diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
index 5299603f50..1e6c51b541 100644
--- a/include/qom/object_interfaces.h
+++ b/include/qom/object_interfaces.h
@@ -2,6 +2,7 @@
 #define OBJECT_INTERFACES_H
 
 #include "qom/object.h"
+#include "qapi/qapi-types-qom.h"
 #include "qapi/visitor.h"
 
 #define TYPE_USER_CREATABLE "user-creatable"
@@ -86,6 +87,18 @@ Object *user_creatable_add_type(const char *type, const char 
*id,
 const QDict *qdict,
 Visitor *v, Error **errp);
 
+/**
+ * user_creatable_add_qapi:
+ * @options: the object definition
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Create an instance of the user creatable object according to the
+ * options passed in @opts as described in the QAPI schema documentation.
+ *
+ * Returns: the newly created object or NULL on error
+ */
+void user_creatable_add_qapi(ObjectOptions *options, Error **errp);
+
 /**
  * user_creatable_add_opts:
  * @opts: the object definition
@@ -131,6 +144,21 @@ typedef bool (*user_creatable_add_opts_predicate)(const 
char *type);
 int user_creatable_add_opts_foreach(void *opaque,
 QemuOpts *opts, Error **errp);
 
+/**
+ * user_creatable_process_cmdline:
+ * @optarg: the object definition string as passed on the command line
+ *
+ * Create an instance of the user creatable object by parsing optarg
+ * with a keyval parser and implicit key 'qom-type', converting the
+ * result to ObjectOptions and calling into qmp_object_add().
+ *
+ * If a help option is given, print help instead and exit.
+ *
+ * This function is only meant to be called during command line parsing.
+ * It exits the process on failure or after printing help.
+ */
+void user_creatable_process_cmdline(const char *optarg);
+
 /**
  * user_creatable_print_help:
  * @type: the QOM type to be added
@@ -145,19 +173,6 @@ int user_creatable_add_opts_foreach(void *opaque,
  */
 bool user_creatable_print_help(const char *type, QemuOpts *opts);
 
-/**
- * user_creatable_print_help_from_qdict:
- * @args: options to create
- *
- * Prints help considering the other options given in @args (if "qom-type" is
- * given and valid, print properties for the type, otherwise print valid types)
- *
- * In contrast to user_creatable_print_help(), this function can't return that
- * no help was requested. It should only be called if we know that help is
- * requested and it will always print some help.
- */
-void user_creatable_print_help_from_qdict(QDict *args);
-
 /**
  * user_creatable_del:
  * @id: the unique ID for the object
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index 02c3934329..2eaf9971f5 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -2,10 +2,13 @@
 
 #include "qemu/cutils.h"
 #include "qapi/error.h"
+#include "qapi/qapi-commands-qom.h"
+#include "qapi/qapi-visit-qom.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/qmp/qjson.h"
 #include "qapi/qobject-input-visitor.h"
+#include "qapi/qobject-output-visitor.h"
 #include "qom/object_interfaces.h"
 #include "qemu/help_option.h"
 #include "qemu/id.h"
@@ -113,6 +116,29 @@ out:
 return obj;
 }
 
+void user_creatable_add_qapi(ObjectOptions *options, Error **errp)
+{
+Visitor *v;
+QObject *qobj;
+QDict *props;
+Object *obj;
+
+v = qobject_output_visitor_new();
+visit_type_ObjectOptions(v, NULL, , _abort);
+visit_complete(v, );
+visit_free(v);
+
+props = qobject_to(QDict, qobj);
+qdict_del(props, "qom-type");
+qdict_del(props, "id");
+
+v = qobject_input_visitor_new(QOBJECT(props));
+obj = user_creatable_add_type(ObjectType_str(options->qom_type),
+  options->id, props, v, errp);
+object_unref(obj);
+visit_free(v);
+}
+
 Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
 {
 Visitor *v;
@@ -256,7 +282,7 @@ bool user_creatable_print_help(const char *type, QemuOpts 
*opts)
 return false;
 }
 
-void user_creatable_print_help_from_qdict(QDict *args)
+static void user_creatable_print_help_from_qdict(QDict *args)
 {