All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: aliguori@linux.vnet.ibm.com, mdroth@linux.vnet.ibm.com
Subject: [Qemu-devel] [RFC 2/8] qapi: add QemuFileOutputVisitor
Date: Mon, 19 Sep 2011 09:41:43 -0500	[thread overview]
Message-ID: <1316443309-23843-3-git-send-email-mdroth@linux.vnet.ibm.com> (raw)
In-Reply-To: <1316443309-23843-1-git-send-email-mdroth@linux.vnet.ibm.com>

Visitor interface to write values to a QEMUFile.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 Makefile.objs                   |   16 +-
 qapi/qemu-file-output-visitor.c |  353 +++++++++++++++++++++++++++++++++++++++
 qapi/qemu-file-output-visitor.h |   26 +++
 3 files changed, 388 insertions(+), 7 deletions(-)
 create mode 100644 qapi/qemu-file-output-visitor.c
 create mode 100644 qapi/qemu-file-output-visitor.h

diff --git a/Makefile.objs b/Makefile.objs
index 62020d7..48fe0c4 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -20,6 +20,13 @@ coroutine-obj-$(CONFIG_POSIX) += coroutine-gthread.o
 endif
 coroutine-obj-$(CONFIG_WIN32) += coroutine-win32.o
 
+######################################################################
+# qapi
+
+qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o
+qapi-nested-y += qmp-registry.o qmp-dispatch.o
+qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
+
 #######################################################################
 # block-obj-y is code used by both qemu system emulation and qemu-img
 
@@ -73,6 +80,8 @@ fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
 # CPUs and machines.
 
 common-obj-y = $(block-obj-y) blockdev.o
+common-obj-y += $(qapi-obj-y)
+common-obj-y += qapi/qemu-file-output-visitor.o
 common-obj-y += $(net-obj-y)
 common-obj-y += $(qobject-obj-y)
 common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
@@ -399,13 +408,6 @@ $(trace-obj-y): $(GENERATED_HEADERS)
 libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o card_7816.o
 
 ######################################################################
-# qapi
-
-qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o
-qapi-nested-y += qmp-registry.o qmp-dispatch.o
-qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
-
-######################################################################
 # guest agent
 
 qga-nested-y = guest-agent-commands.o guest-agent-command-state.o
diff --git a/qapi/qemu-file-output-visitor.c b/qapi/qemu-file-output-visitor.c
new file mode 100644
index 0000000..c44b76c
--- /dev/null
+++ b/qapi/qemu-file-output-visitor.c
@@ -0,0 +1,353 @@
+/*
+ * QEMUFile Output Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Michael Roth   <mdroth@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu-file-output-visitor.h"
+#include "qemu-queue.h"
+#include "qemu-common.h"
+#include "qemu-objects.h"
+#include "hw/hw.h"
+#include "qerror.h"
+
+typedef struct {
+    size_t elem_count;
+    size_t elem_size;
+    size_t pos;
+} ArrayInfo;
+
+typedef struct StackEntry
+{
+    enum {
+        QFOV_ARRAY,
+        QFOV_LIST,
+        QFOV_STRUCT,
+    } type;
+    ArrayInfo array_info;
+    bool is_list_head;
+    QTAILQ_ENTRY(StackEntry) node;
+} StackEntry;
+
+struct QemuFileOutputVisitor
+{
+    Visitor visitor;
+    QTAILQ_HEAD(, StackEntry) stack;
+    QEMUFile *file;
+};
+
+static QemuFileOutputVisitor *to_ov(Visitor *v)
+{
+    return container_of(v, QemuFileOutputVisitor, visitor);
+}
+
+static void qemu_file_output_push(QemuFileOutputVisitor *ov, StackEntry *e)
+{
+    QTAILQ_INSERT_HEAD(&ov->stack, e, node);
+}
+
+static void qemu_file_output_push_array(QemuFileOutputVisitor *ov, ArrayInfo ai)
+{
+    StackEntry *e = g_malloc0(sizeof(*e));
+    e->type = QFOV_ARRAY;
+    e->array_info = ai;
+    qemu_file_output_push(ov, e);
+}
+
+static void qemu_file_output_push_list(QemuFileOutputVisitor *ov)
+{
+    StackEntry *e = g_malloc0(sizeof(*e));
+    e->type = QFOV_LIST;
+    e->is_list_head = true;
+    qemu_file_output_push(ov, e);
+}
+
+static void qemu_file_output_push_struct(QemuFileOutputVisitor *ov)
+{
+    StackEntry *e = g_malloc0(sizeof(*e));
+    e->type = QFOV_STRUCT;
+    qemu_file_output_push(ov, e);
+}
+
+static StackEntry *qemu_file_output_pop(QemuFileOutputVisitor *ov)
+{
+    StackEntry *e = QTAILQ_FIRST(&ov->stack);
+    QTAILQ_REMOVE(&ov->stack, e, node);
+    return e;
+}
+
+static bool qemu_file_output_is_array(QemuFileOutputVisitor *ov)
+{
+    StackEntry *e = QTAILQ_FIRST(&ov->stack);
+    return e && e->type == QFOV_ARRAY;
+}
+
+static bool qemu_file_output_is_list(QemuFileOutputVisitor *ov)
+{
+    StackEntry *e = QTAILQ_FIRST(&ov->stack);
+    return e && e->type == QFOV_LIST;
+}
+
+static void qemu_file_output_start_struct(Visitor *v, void **obj,
+                                          const char *kind, const char *name,
+                                          size_t unused, Error **errp)
+{
+    QemuFileOutputVisitor *ov = to_ov(v);
+
+    if (!obj || *obj == NULL) {
+        error_set(errp, QERR_INVALID_PARAMETER, "obj");
+    }
+    qemu_file_output_push_struct(ov);
+}
+
+static void qemu_file_output_end_struct(Visitor *v, Error **errp)
+{
+    QemuFileOutputVisitor *ov = to_ov(v);
+    StackEntry *e = qemu_file_output_pop(ov);
+
+    if (!e || e->type != QFOV_STRUCT) {
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
+    }
+    g_free(e);
+}
+
+static void qemu_file_output_start_list(Visitor *v, const char *name,
+                                        Error **errp)
+{
+    QemuFileOutputVisitor *ov = to_ov(v);
+    qemu_file_output_push_list(ov);
+}
+
+static GenericList *qemu_file_output_next_list(Visitor *v, GenericList **list,
+                                           Error **errp)
+{
+    QemuFileOutputVisitor *ov = to_ov(v);
+    GenericList *entry = *list;
+    StackEntry *e = QTAILQ_FIRST(&ov->stack);
+
+    if (!entry || !qemu_file_output_is_list(ov)) {
+        error_set(errp, QERR_UNDEFINED_ERROR);
+    }
+
+    /* The way the list iterator is currently used unfortunately clobbers
+     * **list by subseqently assigning our return value to the same container.
+     * This can cause an infinite loop, but we can get around this by tracking
+     * a bit of state to note when we should pass back the next entry rather
+     * than the current one.
+     */
+    if (e->is_list_head) {
+        e->is_list_head = false;
+        return entry;
+    }
+
+    *list = entry->next;
+    return entry->next;
+}
+
+static void qemu_file_output_end_list(Visitor *v, Error **errp)
+{
+    QemuFileOutputVisitor *ov = to_ov(v);
+    StackEntry *e = qemu_file_output_pop(ov);
+    if (!e || e->type != QFOV_LIST) {
+        error_set(errp, QERR_UNDEFINED_ERROR);
+    }
+    g_free(e);
+}
+
+static void qemu_file_output_start_array(Visitor *v, void **obj,
+                                         const char *name,
+                                         size_t elem_count,
+                                         size_t elem_size, Error **errp)
+{
+    QemuFileOutputVisitor *ov = to_ov(v);
+    ArrayInfo ai = {
+        .elem_count = elem_count,
+        .elem_size = elem_size,
+        .pos = 0
+    };
+    qemu_file_output_push_array(ov, ai);
+}
+
+static void qemu_file_output_next_array(Visitor *v, Error **errp)
+{
+    QemuFileOutputVisitor *ov = to_ov(v);
+    StackEntry *e = QTAILQ_FIRST(&ov->stack);
+    if (!qemu_file_output_is_array(ov) ||
+        e->array_info.pos >= e->array_info.elem_count) {
+        error_set(errp, QERR_UNDEFINED_ERROR);
+    }
+
+    e->array_info.pos++;
+}
+
+static void qemu_file_output_end_array(Visitor *v, Error **errp)
+{
+    QemuFileOutputVisitor *ov = to_ov(v);
+    StackEntry *e = qemu_file_output_pop(ov);
+    if (!e || e->type != QFOV_ARRAY) {
+        error_set(errp, QERR_UNDEFINED_ERROR);
+        return;
+    }
+    g_free(e);
+}
+
+static void qemu_file_output_type_str(Visitor *v, char **obj, const char *name,
+                                      Error **errp)
+{
+    if (obj) {
+        g_free(*obj);
+    }
+}
+
+static void qemu_file_output_type_uint8_t(Visitor *v, uint8_t *obj,
+                                          const char *name,
+                                          Error **errp)
+{
+    QemuFileOutputVisitor *ov = container_of(v, QemuFileOutputVisitor, visitor);
+    qemu_put_byte(ov->file, *obj);
+}
+
+static void qemu_file_output_type_uint16_t(Visitor *v, uint16_t *obj,
+                                           const char *name, Error **errp)
+{
+    QemuFileOutputVisitor *ov = container_of(v, QemuFileOutputVisitor, visitor);
+    qemu_put_byte(ov->file, *obj >> 8);
+    qemu_put_byte(ov->file, *obj);
+}
+
+static void qemu_file_output_type_uint32_t(Visitor *v, uint32_t *obj,
+                                           const char *name, Error **errp)
+{
+    QemuFileOutputVisitor *ov = container_of(v, QemuFileOutputVisitor, visitor);
+    qemu_put_byte(ov->file, *obj >> 24);
+    qemu_put_byte(ov->file, *obj >> 16);
+    qemu_put_byte(ov->file, *obj >> 8);
+    qemu_put_byte(ov->file, *obj);
+}
+
+static void qemu_file_output_type_uint64_t(Visitor *v, uint64_t *obj,
+                                           const char *name, Error **errp)
+{
+    QemuFileOutputVisitor *ov = container_of(v, QemuFileOutputVisitor, visitor);
+    qemu_put_byte(ov->file, *obj >> 56);
+    qemu_put_byte(ov->file, *obj >> 48);
+    qemu_put_byte(ov->file, *obj >> 40);
+    qemu_put_byte(ov->file, *obj >> 32);
+    qemu_put_byte(ov->file, *obj >> 24);
+    qemu_put_byte(ov->file, *obj >> 16);
+    qemu_put_byte(ov->file, *obj >> 8);
+    qemu_put_byte(ov->file, *obj);
+}
+
+static void qemu_file_output_type_int8_t(Visitor *v, int8_t *obj,
+                                         const char *name, Error **errp)
+{
+    QemuFileOutputVisitor *ov = container_of(v, QemuFileOutputVisitor, visitor);
+    qemu_put_sbyte(ov->file, *obj);
+}
+
+static void qemu_file_output_type_int16_t(Visitor *v, int16_t *obj,
+                                          const char *name, Error **errp)
+{
+    QemuFileOutputVisitor *ov = container_of(v, QemuFileOutputVisitor, visitor);
+    qemu_put_sbyte(ov->file, *obj >> 8);
+    qemu_put_sbyte(ov->file, *obj);
+}
+
+static void qemu_file_output_type_int32_t(Visitor *v, int32_t *obj,
+                                          const char *name, Error **errp)
+{
+    QemuFileOutputVisitor *ov = container_of(v, QemuFileOutputVisitor, visitor);
+    qemu_put_sbyte(ov->file, *obj >> 24);
+    qemu_put_sbyte(ov->file, *obj >> 16);
+    qemu_put_sbyte(ov->file, *obj >> 8);
+    qemu_put_sbyte(ov->file, *obj);
+}
+
+static void qemu_file_output_type_int64_t(Visitor *v, int64_t *obj,
+                                          const char *name, Error **errp)
+{
+    QemuFileOutputVisitor *ov = container_of(v, QemuFileOutputVisitor, visitor);
+    qemu_put_sbyte(ov->file, *obj >> 56);
+    qemu_put_sbyte(ov->file, *obj >> 48);
+    qemu_put_sbyte(ov->file, *obj >> 40);
+    qemu_put_sbyte(ov->file, *obj >> 32);
+    qemu_put_sbyte(ov->file, *obj >> 24);
+    qemu_put_sbyte(ov->file, *obj >> 16);
+    qemu_put_sbyte(ov->file, *obj >> 8);
+    qemu_put_sbyte(ov->file, *obj);
+}
+
+static void qemu_file_output_type_bool(Visitor *v, bool *obj, const char *name,
+                                   Error **errp)
+{
+    uint8_t val = *obj;
+    qemu_file_output_type_uint8_t(v, &val, name, errp);
+}
+
+static void qemu_file_output_type_number(Visitor *v, double *obj,
+                                         const char *name, Error **errp)
+{
+    uint64_t *val = (uint64_t *)obj;
+    qemu_file_output_type_uint64_t(v, val, name, errp);
+}
+
+static void qemu_file_output_type_enum(Visitor *v, int *obj,
+                                       const char *strings[],
+                                       const char *kind, const char *name,
+                                       Error **errp)
+{
+}
+
+Visitor *qemu_file_output_get_visitor(QemuFileOutputVisitor *v)
+{
+    return &v->visitor;
+}
+
+void qemu_file_output_visitor_cleanup(QemuFileOutputVisitor *ov)
+{
+    g_free(ov);
+}
+
+QemuFileOutputVisitor *qemu_file_output_visitor_new(QEMUFile *f)
+{
+    QemuFileOutputVisitor *v;
+
+    v = g_malloc0(sizeof(*v));
+
+    v->file = f;
+
+    v->visitor.start_struct = qemu_file_output_start_struct;
+    v->visitor.end_struct = qemu_file_output_end_struct;
+    v->visitor.start_list = qemu_file_output_start_list;
+    v->visitor.next_list = qemu_file_output_next_list;
+    v->visitor.end_list = qemu_file_output_end_list;
+    v->visitor.start_array = qemu_file_output_start_array;
+    v->visitor.next_array = qemu_file_output_next_array;
+    v->visitor.end_array = qemu_file_output_end_array;
+    v->visitor.type_enum = qemu_file_output_type_enum;
+    v->visitor.type_int = qemu_file_output_type_int64_t;
+    v->visitor.type_uint8_t = qemu_file_output_type_uint8_t;
+    v->visitor.type_uint16_t = qemu_file_output_type_uint16_t;
+    v->visitor.type_uint32_t = qemu_file_output_type_uint32_t;
+    v->visitor.type_uint64_t = qemu_file_output_type_uint64_t;
+    v->visitor.type_int8_t = qemu_file_output_type_int8_t;
+    v->visitor.type_int16_t = qemu_file_output_type_int16_t;
+    v->visitor.type_int32_t = qemu_file_output_type_int32_t;
+    v->visitor.type_int64_t = qemu_file_output_type_int64_t;
+    v->visitor.type_bool = qemu_file_output_type_bool;
+    v->visitor.type_str = qemu_file_output_type_str;
+    v->visitor.type_number = qemu_file_output_type_number;
+
+    QTAILQ_INIT(&v->stack);
+
+    return v;
+}
diff --git a/qapi/qemu-file-output-visitor.h b/qapi/qemu-file-output-visitor.h
new file mode 100644
index 0000000..e446f08
--- /dev/null
+++ b/qapi/qemu-file-output-visitor.h
@@ -0,0 +1,26 @@
+/*
+ * QEMUFile Visitor
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Michael Roth   <mdroth@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_FILE_OUTPUT_VISITOR_H
+#define QEMU_FILE_OUTPUT_VISITOR_H
+
+#include "qapi-visit-core.h"
+
+typedef struct QemuFileOutputVisitor QemuFileOutputVisitor;
+
+QemuFileOutputVisitor *qemu_file_output_visitor_new(QEMUFile *f);
+void qemu_file_output_visitor_cleanup(QemuFileOutputVisitor *d);
+
+Visitor *qemu_file_output_get_visitor(QemuFileOutputVisitor *v);
+
+#endif
-- 
1.7.0.4

  parent reply	other threads:[~2011-09-19 14:42 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-09-19 14:41 [Qemu-devel] [RFC] New Migration Protocol using Visitor Interface Michael Roth
2011-09-19 14:41 ` [Qemu-devel] [RFC 1/8] qapi: add Visitor interfaces for uint*_t and int*_t Michael Roth
2011-09-19 14:41 ` Michael Roth [this message]
2011-09-19 14:41 ` [Qemu-devel] [RFC 3/8] qapi: add QemuFileInputVisitor Michael Roth
2011-10-24 23:59   ` Chris Krumme
2011-09-19 14:41 ` [Qemu-devel] [RFC 4/8] savevm: move QEMUFile interfaces into qemu-file.c Michael Roth
2011-09-24  7:23   ` Blue Swirl
2011-09-19 14:41 ` [Qemu-devel] [RFC 5/8] qapi: test cases for QEMUFile input/output visitors Michael Roth
2011-09-19 14:41 ` [Qemu-devel] [RFC 6/8] savevm: add QEMUFile->visitor lookup routines Michael Roth
2011-09-19 14:41 ` [Qemu-devel] [RFC 7/8] cutil: add strocat(), to concat a string to an offset in another Michael Roth
2011-09-20 10:43   ` Paolo Bonzini
2011-09-19 14:41 ` [Qemu-devel] [RFC 8/8] slirp: convert save/load function to visitor interface Michael Roth
2011-09-30 13:39   ` Anthony Liguori
2011-09-30 14:08     ` Michael Roth
2011-10-02 20:21 ` [Qemu-devel] [RFC] New Migration Protocol using Visitor Interface Stefan Berger
2011-10-02 21:08   ` Michael S. Tsirkin
2011-10-03 12:55     ` Anthony Liguori
2011-10-03 13:10       ` Stefan Berger
2011-10-03 13:18         ` Anthony Liguori
2011-10-03 13:30           ` Michael S. Tsirkin
2011-10-03 13:48             ` Anthony Liguori
2011-10-03 14:18               ` Michael S. Tsirkin
2011-10-03 14:56                 ` Anthony Liguori
2011-10-03 15:42                   ` Michael S. Tsirkin
2011-10-03 13:38       ` Michael S. Tsirkin
2011-10-03 13:51         ` Anthony Liguori
2011-10-03 14:41           ` Michael S. Tsirkin
2011-10-03 15:00             ` Anthony Liguori
2011-10-03 15:45               ` Michael S. Tsirkin
2011-10-03 16:05                 ` Anthony Liguori
2011-10-03 16:24                   ` Daniel P. Berrange
2011-10-03 16:51                   ` Michael S. Tsirkin
2011-10-05 11:28               ` Michael S. Tsirkin
2011-10-05 12:46                 ` Anthony Liguori
2011-10-03  6:46 ` Michael S. Tsirkin
2011-10-03 12:51   ` Anthony Liguori
2011-10-03 13:24     ` Michael S. Tsirkin
2011-10-03 13:43       ` Anthony Liguori
2011-10-03 14:11         ` Michael S. Tsirkin
2011-10-03 14:42           ` Anthony Liguori
2011-10-03 15:29             ` Michael S. Tsirkin
2011-10-03 15:44               ` Anthony Liguori
2011-10-03 15:58                 ` Michael S. Tsirkin
2011-10-03 16:02                   ` Anthony Liguori
2011-10-03 14:15         ` Michael S. Tsirkin
2011-10-03 14:55           ` Anthony Liguori
2011-10-03 15:41             ` Michael S. Tsirkin
2011-10-05  2:05         ` Stefan Berger
2011-10-05 12:54           ` Anthony Liguori
2011-10-05 19:06             ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1316443309-23843-3-git-send-email-mdroth@linux.vnet.ibm.com \
    --to=mdroth@linux.vnet.ibm.com \
    --cc=aliguori@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.