Patchwork [v1,17/23] qapi: add QMP dispatch functions

login
register
mail settings
Submitter Michael Roth
Date May 18, 2011, 12:52 a.m.
Message ID <1305679930-4215-18-git-send-email-mdroth@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/96108/
State New
Headers show

Comments

Michael Roth - May 18, 2011, 12:52 a.m.
Given an object recieved via QMP, this code uses the dispatch table
provided by qmp_registry.c to call the corresponding marshalling/dispatch
function and format return values/errors for delivery to the QMP.
Currently only synchronous QMP functions are supported, but this will
also be used for async QMP functions and QMP guest proxy dispatch as
well.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 qapi/qmp-dispatch.c |  104 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 104 insertions(+), 0 deletions(-)
 create mode 100644 qapi/qmp-dispatch.c
Stefan Hajnoczi - May 18, 2011, 8:58 a.m.
On Wed, May 18, 2011 at 1:52 AM, Michael Roth <mdroth@linux.vnet.ibm.com> wrote:
> Given an object recieved via QMP, this code uses the dispatch table
> provided by qmp_registry.c to call the corresponding marshalling/dispatch
> function and format return values/errors for delivery to the QMP.
> Currently only synchronous QMP functions are supported, but this will
> also be used for async QMP functions and QMP guest proxy dispatch as
> well.
>
> Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
> ---
>  qapi/qmp-dispatch.c |  104 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 104 insertions(+), 0 deletions(-)
>  create mode 100644 qapi/qmp-dispatch.c
>
> diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
> new file mode 100644
> index 0000000..733decf
> --- /dev/null
> +++ b/qapi/qmp-dispatch.c
> @@ -0,0 +1,104 @@
> +#include <glib.h>
> +#include "qemu-objects.h"
> +#include "qapi/qmp-core.h"
> +#include "json-parser.h"
> +
> +static QObject *qmp_dispatch_err(QmpState *state, QObject *request, Error **errp)
> +{
> +    const char *command;
> +    QDict *args, *dict;
> +    //QObject *request;
> +    QmpCommand *cmd;
> +    QObject *ret = NULL;
> +    //Error *err = NULL;

Please remove commented out lines, it makes the code noisy.

> +    case QCT_ASYNC: {
> +        QmpCommandState *s = qemu_mallocz(sizeof(*s));
> +        // FIXME save async commands and do something
> +        // smart if disconnect occurs before completion
> +        s->state = state;
> +        s->tag = NULL;
> +        if (qdict_haskey(dict, "tag")) {
> +            s->tag = qdict_get(dict, "tag");
> +            qobject_incref(s->tag);
> +        }
> +        cmd->afn(args, errp, s);

async_fn() would be a clear name.

> +        ret = NULL;

It is already NULL.

> +    }
> +        break;
> +    case QCT_PROXY: {
> +        QmpCommandState *s = qemu_mallocz(sizeof(*s));
> +        // FIXME save async commands and do something
> +        // smart if disconnect occurs before completion
> +        s->state = state;
> +        s->tag = NULL;
> +        if (qdict_haskey(dict, "tag")) {
> +            s->tag = qdict_get(dict, "tag");
> +            qobject_incref(s->tag);
> +        }
> +        cmd->pfn(args, errp, s);
> +        ret = NULL;

Same comments as for async.

Stefan

Patch

diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
new file mode 100644
index 0000000..733decf
--- /dev/null
+++ b/qapi/qmp-dispatch.c
@@ -0,0 +1,104 @@ 
+#include <glib.h>
+#include "qemu-objects.h"
+#include "qapi/qmp-core.h"
+#include "json-parser.h"
+
+static QObject *qmp_dispatch_err(QmpState *state, QObject *request, Error **errp)
+{
+    const char *command;
+    QDict *args, *dict;
+    //QObject *request;
+    QmpCommand *cmd;
+    QObject *ret = NULL;
+    //Error *err = NULL;
+
+    if (qobject_type(request) != QTYPE_QDICT) {
+        error_set(errp, QERR_JSON_PARSE_ERROR, "request is not a dictionary");
+        goto out;
+    }
+
+    dict = qobject_to_qdict(request);
+    if (!qdict_haskey(dict, "execute")) {
+        error_set(errp, QERR_JSON_PARSE_ERROR, "no execute key");
+        goto out;
+    }
+
+    command = qdict_get_str(dict, "execute");
+    cmd = qmp_find_command(command);
+    if (cmd == NULL) {
+        error_set(errp, QERR_COMMAND_NOT_FOUND, command);
+        goto out;
+    }
+
+    if (!qdict_haskey(dict, "arguments")) {
+        args = qdict_new();
+    } else {
+        args = qdict_get_qdict(dict, "arguments");
+        QINCREF(args);
+    }
+
+    switch (cmd->type) {
+    case QCT_NORMAL:
+        cmd->fn(state, args, &ret, errp);
+        if (ret == NULL) {
+            ret = QOBJECT(qdict_new());
+        }
+        break;
+    case QCT_ASYNC: {
+        QmpCommandState *s = qemu_mallocz(sizeof(*s));
+        // FIXME save async commands and do something
+        // smart if disconnect occurs before completion
+        s->state = state;
+        s->tag = NULL;
+        if (qdict_haskey(dict, "tag")) {
+            s->tag = qdict_get(dict, "tag");
+            qobject_incref(s->tag);
+        }
+        cmd->afn(args, errp, s);
+        ret = NULL;
+    }
+        break;
+    case QCT_PROXY: {
+        QmpCommandState *s = qemu_mallocz(sizeof(*s));
+        // FIXME save async commands and do something
+        // smart if disconnect occurs before completion
+        s->state = state;
+        s->tag = NULL;
+        if (qdict_haskey(dict, "tag")) {
+            s->tag = qdict_get(dict, "tag");
+            qobject_incref(s->tag);
+        }
+        cmd->pfn(args, errp, s);
+        ret = NULL;
+    }
+        break;
+    }
+
+    QDECREF(args);
+
+out:
+
+    return ret;
+}
+
+QObject *qmp_dispatch(QmpState *state, QObject *request)
+{
+    Error *err = NULL;
+    QObject *ret;
+    QDict *rsp;
+
+    ret = qmp_dispatch_err(state, request, &err);
+
+    rsp = qdict_new();
+    if (err) {
+        qdict_put_obj(rsp, "error", error_get_qobject(err));
+        error_free(err);
+    } else if (ret) {
+        qdict_put_obj(rsp, "return", ret);
+    } else {
+        QDECREF(rsp);
+        return NULL;
+    }
+
+    return QOBJECT(rsp);
+}