[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v4 12/20] qmp: introduce asynchronous command type
From: |
Marc-André Lureau |
Subject: |
[Qemu-devel] [PATCH v4 12/20] qmp: introduce asynchronous command type |
Date: |
Tue, 9 Apr 2019 18:10:01 +0200 |
Add a new type of command, QmpCommandFuncAsync: those commands can
return later thanks to QmpReturn. This commit introduces the new type
and register function and teach qmp_dipatch() to call it without
qmp_return(). The async_fn callback will be responsible for calling
qmp_return(), either synchronously or asynchronously.
Signed-off-by: Marc-André Lureau <address@hidden>
---
include/qapi/qmp/dispatch.h | 10 +++++++++-
qapi/qmp-dispatch.c | 27 ++++++++++++++++-----------
qapi/qmp-registry.c | 27 ++++++++++++++++++++++++---
3 files changed, 49 insertions(+), 15 deletions(-)
diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index 92d6fd1afb..6aef0abc70 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -21,6 +21,7 @@
typedef struct QmpReturn QmpReturn;
typedef void (QmpCommandFunc)(QDict *, QObject **, Error **);
+typedef void (QmpCommandAsyncFunc)(QDict *, QmpReturn *);
typedef enum QmpCommandOptions
{
@@ -28,12 +29,16 @@ typedef enum QmpCommandOptions
QCO_NO_SUCCESS_RESP = (1U << 0),
QCO_ALLOW_OOB = (1U << 1),
QCO_ALLOW_PRECONFIG = (1U << 2),
+ QCO_ASYNC = (1U << 3),
} QmpCommandOptions;
typedef struct QmpCommand
{
const char *name;
- QmpCommandFunc *fn;
+ union {
+ QmpCommandFunc *fn;
+ QmpCommandAsyncFunc *async_fn;
+ };
QmpCommandOptions options;
QTAILQ_ENTRY(QmpCommand) node;
bool enabled;
@@ -88,6 +93,9 @@ void qmp_return_error(QmpReturn *qret, Error *err);
void qmp_register_command(QmpCommandList *cmds, const char *name,
QmpCommandFunc *fn, QmpCommandOptions options);
+void qmp_register_async_command(QmpCommandList *cmds, const char *name,
+ QmpCommandAsyncFunc *fn,
+ QmpCommandOptions options);
const QmpCommand *qmp_find_command(const QmpCommandList *cmds,
const char *name);
void qmp_session_init(QmpSession *session,
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 546a6c9f7b..1f493af67a 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -171,7 +171,7 @@ static QDict *qmp_dispatch_check_obj(const QObject
*request, bool allow_oob,
return dict;
}
-static QObject *do_qmp_dispatch(const QmpCommandList *cmds, QObject *request,
+static QObject *do_qmp_dispatch(QmpSession *session, QObject *request,
bool allow_oob, Error **errp)
{
Error *local_err = NULL;
@@ -193,7 +193,7 @@ static QObject *do_qmp_dispatch(const QmpCommandList *cmds,
QObject *request,
command = qdict_get_str(dict, "exec-oob");
oob = true;
}
- cmd = qmp_find_command(cmds, command);
+ cmd = qmp_find_command(session->cmds, command);
if (cmd == NULL) {
error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
"The command %s has not been found", command);
@@ -224,14 +224,19 @@ static QObject *do_qmp_dispatch(const QmpCommandList
*cmds, QObject *request,
qobject_ref(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) {
- /* TODO turn into assertion */
- ret = QOBJECT(qdict_new());
+
+ if (cmd->options & QCO_ASYNC) {
+ cmd->async_fn(args, qmp_return_new(session, request));
+ } else {
+ 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) {
+ /* TODO turn into assertion */
+ ret = QOBJECT(qdict_new());
+ }
}
qobject_unref(args);
@@ -304,7 +309,7 @@ void qmp_dispatch(QmpSession *session, QObject *request,
bool allow_oob)
Error *err = NULL;
QObject *ret;
- ret = do_qmp_dispatch(session->cmds, request, allow_oob, &err);
+ ret = do_qmp_dispatch(session, request, allow_oob, &err);
if (err) {
qmp_return_error(qmp_return_new(session, request), err);
} else if (ret) {
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
index d0f9a1d3e3..0f3d521ce5 100644
--- a/qapi/qmp-registry.c
+++ b/qapi/qmp-registry.c
@@ -15,16 +15,37 @@
#include "qemu/osdep.h"
#include "qapi/qmp/dispatch.h"
-void qmp_register_command(QmpCommandList *cmds, const char *name,
- QmpCommandFunc *fn, QmpCommandOptions options)
+
+static QmpCommand *qmp_command_new(QmpCommandList *cmds, 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(cmds, cmd, node);
+
+ return cmd;
+}
+
+
+void qmp_register_command(QmpCommandList *cmds, const char *name,
+ QmpCommandFunc *fn, QmpCommandOptions options)
+{
+ QmpCommand *cmd = qmp_command_new(cmds, name, options);
+
+ assert(!(options & QCO_ASYNC));
+ cmd->fn = fn;
+}
+
+void qmp_register_async_command(QmpCommandList *cmds, const char *name,
+ QmpCommandAsyncFunc *fn, QmpCommandOptions options)
+{
+ QmpCommand *cmd = qmp_command_new(cmds, name, options);
+
+ assert(options & QCO_ASYNC);
+ cmd->async_fn = fn;
}
const QmpCommand *qmp_find_command(const QmpCommandList *cmds, const char
*name)
--
2.21.0.196.g041f5ea1cf
- [Qemu-devel] [PATCH v4 01/20] qmp: constify QmpCommand and list, (continued)
- [Qemu-devel] [PATCH v4 01/20] qmp: constify QmpCommand and list, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 02/20] json-lexer: make it safe to call destroy multiple times, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 03/20] qmp: add QmpSession, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 04/20] QmpSession: add a return callback, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 05/20] QmpSession: add json parser and use it in qga, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 06/20] monitor: use qmp session to parse json feed, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 07/20] qga: simplify dispatch_return_cb, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 08/20] QmpSession: introduce QmpReturn, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 09/20] qmp: simplify qmp_return_error(), Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 11/20] QmpSession: return orderly, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 12/20] qmp: introduce asynchronous command type,
Marc-André Lureau <=
- [Qemu-devel] [PATCH v4 13/20] scripts: learn 'async' qapi commands, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 14/20] qmp: add qmp_return_is_cancelled(), Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 15/20] monitor: add qmp_return_get_monitor(), Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 16/20] console: add graphic_hw_update_done(), Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 10/20] QmpSession: keep a queue of pending commands, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 17/20] console: make screendump asynchronous, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 18/20] monitor: start making qmp_human_monitor_command() asynchronous, Marc-André Lureau, 2019/04/09
- [Qemu-devel] [PATCH v4 19/20] monitor: teach HMP about asynchronous commands, Marc-André Lureau, 2019/04/09