[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 23/31] libxl_qmp_ev: Handle messages from QEMU



This will handle messages received, and call callbacks registered via
libxl__ev_qmp_register().

This also print error messages from QMP on behalf of the callback.

Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>

---
Should we let callbacks print error messages themself? They already have
the error class, which is often GenericError, a human readable
error message.
---
 tools/libxl/libxl_qmp.c | 100 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 100 insertions(+)

diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 0e7ec54b9f..db07c1822a 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1420,6 +1420,101 @@ static int ev_qmp_queue_command(libxl__gc *gc,
     return 0;
 }
 
+/*
+ * Handle messages received from QMP server
+ */
+
+static void ev_qmp_handle_return(libxl__egc *egc,
+                                 libxl__ev_qmp_state *qmp,
+                                 const libxl__json_object *resp,
+                                 libxl__qmp_message_type type)
+{
+    EGC_GC;
+    const libxl__json_object *o;
+    int id;
+    libxl__ev_qmp *ev;
+    const libxl__json_object *ret;
+    libxl__qmp_error_class error_class = 0;
+
+    o = libxl__json_map_get("id", resp, JSON_INTEGER);
+    if (!o) {
+        const char *error_desc;
+
+        /* unexpected message, attempt to find an error description */
+        o = libxl__json_map_get("error", resp, JSON_MAP);
+        o = libxl__json_map_get("desc", o, JSON_STRING);
+        error_desc = libxl__json_object_get_string(o);
+        if (error_desc)
+            LOGD(ERROR, qmp->domid, "%s", error_desc);
+        else
+            LOGD(ERROR, qmp->domid, "Received unexpected message: %s",
+                 libxl__json_object_to_json(gc, resp));
+        return;
+    }
+
+    id = libxl__json_object_get_integer(o);
+    LIBXL_TAILQ_FOREACH(ev, &qmp->qmp_events, entry) {
+        if (ev->id == id)
+            break;
+    }
+    if (!ev)
+        /* callback not found */
+        return;
+
+    switch (type) {
+    case LIBXL__QMP_MESSAGE_TYPE_RETURN: {
+        ret = libxl__json_map_get("return", resp, JSON_ANY);
+        break;
+    }
+    case LIBXL__QMP_MESSAGE_TYPE_ERROR: {
+        const char *s;
+        const libxl__json_object *err;
+
+        error_class = LIBXL__QMP_ERROR_CLASS_UNKNOWN;
+        err = libxl__json_map_get("error", resp, JSON_MAP);
+        o = libxl__json_map_get("class", err, JSON_STRING);
+        s = libxl__json_object_get_string(o);
+        if (s)
+            libxl__qmp_error_class_from_string(s, &error_class);
+
+        o = libxl__json_map_get("desc", err, JSON_STRING);
+        s = libxl__json_object_get_string(o);
+        if (s)
+            LOGD(ERROR, qmp->domid, "%s", s);
+
+        ret = NULL;
+        break;
+    }
+    default:
+        abort();
+    }
+    ev->id = -1;
+    ev->callback(egc, ev, ret, error_class);
+}
+
+static void ev_qmp_handle_message(libxl__egc *egc,
+                                  libxl__ev_qmp_state *qmp,
+                                  const libxl__json_object *resp)
+{
+    EGC_GC;
+    libxl__qmp_message_type type = qmp_response_type(resp);
+
+    switch (type) {
+    case LIBXL__QMP_MESSAGE_TYPE_QMP:
+        /* greeting message */
+        return;
+    case LIBXL__QMP_MESSAGE_TYPE_RETURN:
+    case LIBXL__QMP_MESSAGE_TYPE_ERROR:
+        ev_qmp_handle_return(egc, qmp, resp, type);
+        return;
+    case LIBXL__QMP_MESSAGE_TYPE_EVENT:
+        /* Event are ignored */
+        return;
+    case LIBXL__QMP_MESSAGE_TYPE_INVALID:
+        return;
+    }
+}
+
 static int ev_qmp_callback_readable(libxl__egc *egc, libxl__ev_qmp_state *qmp,
                                     int fd)
 {
@@ -1557,6 +1652,8 @@ static int ev_qmp_callback_readable(libxl__egc *egc, 
libxl__ev_qmp_state *qmp,
 
         LOG_QMP("JSON object received: %s", libxl__json_object_to_json(gc, o));
 
+        ev_qmp_handle_message(egc, qmp, o);
+
         /* check if there is another message received at the same time */
         if (buf) {
             end = strstr(buf->buf + buf->consumed, "\r\n");
@@ -1762,6 +1859,9 @@ void libxl__ev_qmp_stop(libxl__gc *gc, 
libxl__ev_qmp_state *qmp)
 
     LOGD(DEBUG, qmp->domid, "Stopping QMP handler");
 
+    /* There should be no more events requested */
+    assert(LIBXL_TAILQ_EMPTY(&qmp->qmp_events));
+
     LIBXL_TAILQ_FOREACH_SAFE(buf, &qmp->bufs, entry, tbuf)
         free(buf);
     LIBXL_TAILQ_INIT(&qmp->bufs);
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.