@@ -21,18 +21,23 @@
typedef struct QmpReturn QmpReturn;
typedef void (QmpCommandFunc)(QDict *, QObject **, Error **);
+typedef void (QmpCommandAsyncFunc)(QDict *, QmpReturn *);
typedef enum QmpCommandOptions
{
QCO_NO_OPTIONS = 0x0,
QCO_NO_SUCCESS_RESP = (1U << 0),
QCO_ALLOW_OOB = (1U << 1),
+ QCO_ASYNC = (1U << 2),
} 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,8 @@ 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);
void qmp_unregister_command(QmpCommandList *cmds, const char *name);
QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name);
@@ -195,7 +195,9 @@ void qmp_dispatch(QmpSession *session, QDict *req)
QINCREF(args);
}
- {
+ if (cmd->options & QCO_ASYNC) {
+ cmd->async_fn(args, qmp_return_new(session, req));
+ } else {
QObject *ret = NULL;
cmd->fn(args, &ret, &err);
if (err || cmd->options & QCO_NO_SUCCESS_RESP) {
@@ -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;
}
void qmp_unregister_command(QmpCommandList *cmds, const char *name)
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(). Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- include/qapi/qmp/dispatch.h | 9 ++++++++- qapi/qmp-dispatch.c | 4 +++- qapi/qmp-registry.c | 27 ++++++++++++++++++++++++--- 3 files changed, 35 insertions(+), 5 deletions(-)