@@ -35,6 +35,12 @@ struct QmpClient {
};
typedef void (QmpCommandFunc)(QDict *, QObject **, Error **);
+typedef void (QmpCommandFuncAsync)(QDict *, QmpReturn *);
+
+typedef enum QmpCommandType {
+ QCT_NORMAL,
+ QCT_ASYNC,
+} QmpCommandType;
typedef enum QmpCommandOptions
{
@@ -44,8 +50,12 @@ typedef enum QmpCommandOptions
typedef struct QmpCommand
{
+ QmpCommandType type;
const char *name;
- QmpCommandFunc *fn;
+ union {
+ QmpCommandFunc *fn;
+ QmpCommandFuncAsync *fn_async;
+ };
QmpCommandOptions options;
QTAILQ_ENTRY(QmpCommand) node;
bool enabled;
@@ -53,6 +63,8 @@ typedef struct QmpCommand
void qmp_register_command(const char *name, QmpCommandFunc *fn,
QmpCommandOptions options);
+void qmp_register_async_command(const char *name, QmpCommandFuncAsync *fn,
+ QmpCommandOptions options);
void qmp_unregister_command(const char *name);
QmpCommand *qmp_find_command(const char *name);
void qmp_client_init(QmpClient *client, QmpDispatchReturn *return_cb);
@@ -95,13 +95,20 @@ static QObject *do_qmp_dispatch(QObject *request, QmpReturn *qret, Error **errp)
QINCREF(args);
}
- cmd->fn(args, &ret, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- } else if (cmd->options & QCO_NO_SUCCESS_RESP) {
- g_assert(!ret);
- } else if (!ret) {
- ret = QOBJECT(qdict_new());
+ switch (cmd->type) {
+ case QCT_NORMAL:
+ cmd->fn(args, &ret, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ } else if (cmd->options & QCO_NO_SUCCESS_RESP) {
+ g_assert(!ret);
+ } else if (!ret) {
+ ret = QOBJECT(qdict_new());
+ }
+ break;
+ case QCT_ASYNC:
+ cmd->fn_async(args, qret);
+ break;
}
QDECREF(args);
@@ -18,16 +18,35 @@
static QTAILQ_HEAD(QmpCommandList, QmpCommand) qmp_commands =
QTAILQ_HEAD_INITIALIZER(qmp_commands);
-void qmp_register_command(const char *name, QmpCommandFunc *fn,
- QmpCommandOptions options)
+static QmpCommand *qmp_command_new(const char *name,
+ QmpCommandOptions options)
{
QmpCommand *cmd = g_malloc0(sizeof(*cmd));
cmd->name = name;
- cmd->fn = fn;
cmd->enabled = true;
cmd->options = options;
QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
+
+ return cmd;
+}
+
+void qmp_register_command(const char *name, QmpCommandFunc *fn,
+ QmpCommandOptions options)
+{
+ QmpCommand *cmd = qmp_command_new(name, options);
+
+ cmd->type = QCT_NORMAL;
+ cmd->fn = fn;
+}
+
+void qmp_register_async_command(const char *name, QmpCommandFuncAsync *fn,
+ QmpCommandOptions options)
+{
+ QmpCommand *cmd = qmp_command_new(name, options);
+
+ cmd->type = QCT_ASYNC;
+ cmd->fn_async = fn;
}
void qmp_unregister_command(const char *name)
Qemu used to have command types, but it was removed in 42a502a7a60632234f0dd5028924926a7eac6c94. Add it back, and add a new type of command, QmpCommandFuncAsync: they can return later thanks to QmpReturn. This commit introduces the new types and register functions. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- include/qapi/qmp/dispatch.h | 14 +++++++++++++- qapi/qmp-dispatch.c | 21 ++++++++++++++------- qapi/qmp-registry.c | 25 ++++++++++++++++++++++--- 3 files changed, 49 insertions(+), 11 deletions(-)