[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 10/14] vmstate: use new JSON output visitor
From: |
Eric Blake |
Subject: |
[Qemu-devel] [PATCH v2 10/14] vmstate: use new JSON output visitor |
Date: |
Mon, 21 Dec 2015 17:31:04 -0700 |
Rather than using a QJSON object and converting the QString result
to a char *, we can use the new JSON output visitor and get directly
to a char *.
The conversions are a bit tricky in place (in places, we have to
copy an integer to an int64_t temporary to get the right pointer for
visit_type_int(); and for several strings, we have to copy to a
temporary variable so we can take an address (&char[] is not the
same as &char*) and cast away const), but overall still fairly
mechanical.
Suggested-by: Paolo Bonzini <address@hidden>
Signed-off-by: Eric Blake <address@hidden>
---
v2: new patch
This is part of alternative 2, along with patch 11. See also patch 8
for alternative 1.
---
include/migration/vmstate.h | 4 +--
migration/savevm.c | 66 ++++++++++++++++++++++++++++-----------------
migration/vmstate.c | 63 ++++++++++++++++++++++++++-----------------
tests/Makefile | 2 +-
4 files changed, 84 insertions(+), 51 deletions(-)
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 7267e38..101742e 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -29,7 +29,7 @@
#ifndef CONFIG_USER_ONLY
#include <migration/qemu-file.h>
#endif
-#include <qjson.h>
+#include "qapi/json-output-visitor.h"
typedef void SaveStateHandler(QEMUFile *f, void *opaque);
typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
@@ -814,7 +814,7 @@ void loadvm_free_handlers(MigrationIncomingState *mis);
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, int version_id);
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, QJSON *vmdesc);
+ void *opaque, Visitor *vmdesc);
bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque);
diff --git a/migration/savevm.c b/migration/savevm.c
index 0ad1b93..a739b8b 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -646,27 +646,32 @@ static int vmstate_load(QEMUFile *f, SaveStateEntry *se,
int version_id)
return vmstate_load_state(f, se->vmsd, se->opaque, version_id);
}
-static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se, QJSON
*vmdesc)
+static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se,
+ Visitor *vmdesc)
{
int64_t old_offset, size;
+ const char *tmp;
old_offset = qemu_ftell_fast(f);
se->ops->save_state(f, se->opaque);
size = qemu_ftell_fast(f) - old_offset;
if (vmdesc) {
- json_prop_int(vmdesc, "size", size);
- json_start_array(vmdesc, "fields");
- json_start_object(vmdesc, NULL);
- json_prop_str(vmdesc, "name", "data");
- json_prop_int(vmdesc, "size", size);
- json_prop_str(vmdesc, "type", "buffer");
- json_end_object(vmdesc);
- json_end_array(vmdesc);
+ visit_type_int(vmdesc, "size", &size, &error_abort);
+ visit_start_list(vmdesc, "fields", NULL, 0, &error_abort);
+ visit_start_struct(vmdesc, NULL, NULL, 0, &error_abort);
+ tmp = "data";
+ visit_type_str(vmdesc, "name", (char **)&tmp, &error_abort);
+ visit_type_int(vmdesc, "size", &size, &error_abort);
+ tmp = "buffer";
+ visit_type_str(vmdesc, "type", (char **)&tmp, &error_abort);
+ visit_check_struct(vmdesc, &error_abort);
+ visit_end_struct(vmdesc);
+ visit_end_list(vmdesc);
}
}
-static void vmstate_save(QEMUFile *f, SaveStateEntry *se, QJSON *vmdesc)
+static void vmstate_save(QEMUFile *f, SaveStateEntry *se, Visitor *vmdesc)
{
trace_vmstate_save(se->idstr, se->vmsd ? se->vmsd->name : "(old)");
if (!se->vmsd) {
@@ -886,7 +891,7 @@ void qemu_savevm_state_header(QEMUFile *f)
if (!savevm_state.skip_configuration) {
qemu_put_byte(f, QEMU_VM_CONFIGURATION);
- vmstate_save_state(f, &vmstate_configuration, &savevm_state, 0);
+ vmstate_save_state(f, &vmstate_configuration, &savevm_state, NULL);
}
}
@@ -1028,11 +1033,15 @@ void qemu_savevm_state_complete_postcopy(QEMUFile *f)
void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only)
{
- QJSON *vmdesc;
+ JsonOutputVisitor *vmdesc_jov;
+ Visitor *vmdesc;
+ char *vmdesc_str;
int vmdesc_len;
SaveStateEntry *se;
int ret;
bool in_postcopy = migration_in_postcopy(migrate_get_current());
+ int64_t tmp_i;
+ char *tmp_s;
trace_savevm_state_complete_precopy();
@@ -1068,9 +1077,12 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f,
bool iterable_only)
return;
}
- vmdesc = qjson_new();
- json_prop_int(vmdesc, "page_size", TARGET_PAGE_SIZE);
- json_start_array(vmdesc, "devices");
+ vmdesc_jov = json_output_visitor_new();
+ vmdesc = json_output_get_visitor(vmdesc_jov);
+ visit_start_struct(vmdesc, NULL, NULL, 0, &error_abort);
+ tmp_i = TARGET_PAGE_SIZE;
+ visit_type_int(vmdesc, "page_size", &tmp_i, &error_abort);
+ visit_start_list(vmdesc, "devices", NULL, 0, &error_abort);
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if ((!se->ops || !se->ops->save_state) && !se->vmsd) {
@@ -1083,15 +1095,18 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f,
bool iterable_only)
trace_savevm_section_start(se->idstr, se->section_id);
- json_start_object(vmdesc, NULL);
- json_prop_str(vmdesc, "name", se->idstr);
- json_prop_int(vmdesc, "instance_id", se->instance_id);
+ visit_start_struct(vmdesc, NULL, NULL, 0, &error_abort);
+ tmp_s = se->idstr;
+ visit_type_str(vmdesc, "name", &tmp_s, &error_abort);
+ tmp_i = se->instance_id;
+ visit_type_int(vmdesc, "instance_id", &tmp_i, &error_abort);
save_section_header(f, se, QEMU_VM_SECTION_FULL);
vmstate_save(f, se, vmdesc);
- json_end_object(vmdesc);
+ visit_check_struct(vmdesc, &error_abort);
+ visit_end_struct(vmdesc);
trace_savevm_section_end(se->idstr, se->section_id, 0);
save_section_footer(f, se);
}
@@ -1101,16 +1116,19 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f,
bool iterable_only)
qemu_put_byte(f, QEMU_VM_EOF);
}
- json_end_array(vmdesc);
- qjson_finish(vmdesc);
- vmdesc_len = strlen(qjson_get_str(vmdesc));
+ visit_end_list(vmdesc);
+ visit_check_struct(vmdesc, &error_abort);
+ visit_end_struct(vmdesc);
+ vmdesc_str = json_output_get_string(vmdesc_jov);
+ vmdesc_len = strlen(vmdesc_str);
if (should_send_vmdesc()) {
qemu_put_byte(f, QEMU_VM_VMDESCRIPTION);
qemu_put_be32(f, vmdesc_len);
- qemu_put_buffer(f, (uint8_t *)qjson_get_str(vmdesc), vmdesc_len);
+ qemu_put_buffer(f, (uint8_t *)vmdesc_str, vmdesc_len);
}
- object_unref(OBJECT(vmdesc));
+ g_free(vmdesc_str);
+ json_output_visitor_cleanup(vmdesc_jov);
qemu_fflush(f);
}
diff --git a/migration/vmstate.c b/migration/vmstate.c
index e8ccf22..9491171 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -5,10 +5,9 @@
#include "qemu/bitops.h"
#include "qemu/error-report.h"
#include "trace.h"
-#include "qjson.h"
static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription
*vmsd,
- void *opaque, QJSON *vmdesc);
+ void *opaque, Visitor *vmdesc);
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque);
@@ -221,12 +220,15 @@ static bool vmsd_can_compress(VMStateField *field)
return true;
}
-static void vmsd_desc_field_start(const VMStateDescription *vmsd, QJSON
*vmdesc,
+static void vmsd_desc_field_start(const VMStateDescription *vmsd,
+ Visitor *vmdesc,
VMStateField *field, int i, int max)
{
char *name, *old_name;
bool is_array = max > 1;
bool can_compress = vmsd_can_compress(field);
+ int64_t tmp;
+ const char *type;
if (!vmdesc) {
return;
@@ -242,38 +244,47 @@ static void vmsd_desc_field_start(const
VMStateDescription *vmsd, QJSON *vmdesc,
g_free(old_name);
}
- json_start_object(vmdesc, NULL);
- json_prop_str(vmdesc, "name", name);
+ visit_start_struct(vmdesc, NULL, NULL, 0, &error_abort);
+ visit_type_str(vmdesc, "name", &name, &error_abort);
if (is_array) {
if (can_compress) {
- json_prop_int(vmdesc, "array_len", max);
+ tmp = max;
+ visit_type_int(vmdesc, "array_len", &tmp, &error_abort);
} else {
- json_prop_int(vmdesc, "index", i);
+ tmp = i;
+ visit_type_int(vmdesc, "index", &tmp, &error_abort);
}
}
- json_prop_str(vmdesc, "type", vmfield_get_type_name(field));
+ type = vmfield_get_type_name(field);
+ visit_type_str(vmdesc, "type", (char **)&type, &error_abort);
if (field->flags & VMS_STRUCT) {
- json_start_object(vmdesc, "struct");
+ visit_start_struct(vmdesc, "struct", NULL, 0, &error_abort);
}
g_free(name);
}
-static void vmsd_desc_field_end(const VMStateDescription *vmsd, QJSON *vmdesc,
+static void vmsd_desc_field_end(const VMStateDescription *vmsd,
+ Visitor *vmdesc,
VMStateField *field, size_t size, int i)
{
+ int64_t tmp;
+
if (!vmdesc) {
return;
}
if (field->flags & VMS_STRUCT) {
/* We printed a struct in between, close its child object */
- json_end_object(vmdesc);
+ visit_check_struct(vmdesc, &error_abort);
+ visit_end_struct(vmdesc);
}
- json_prop_int(vmdesc, "size", size);
- json_end_object(vmdesc);
+ tmp = size;
+ visit_type_int(vmdesc, "size", &tmp, &error_abort);
+ visit_check_struct(vmdesc, &error_abort);
+ visit_end_struct(vmdesc);
}
@@ -288,7 +299,7 @@ bool vmstate_save_needed(const VMStateDescription *vmsd,
void *opaque)
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, QJSON *vmdesc)
+ void *opaque, Visitor *vmdesc)
{
VMStateField *field = vmsd->fields;
@@ -297,9 +308,11 @@ void vmstate_save_state(QEMUFile *f, const
VMStateDescription *vmsd,
}
if (vmdesc) {
- json_prop_str(vmdesc, "vmsd_name", vmsd->name);
- json_prop_int(vmdesc, "version", vmsd->version_id);
- json_start_array(vmdesc, "fields");
+ const char *tmp_s = vmsd->name;
+ int64_t tmp_i = vmsd->version_id;
+ visit_type_str(vmdesc, "vmsd_name", (char **)&tmp_s, &error_abort);
+ visit_type_int(vmdesc, "version", &tmp_i, &error_abort);
+ visit_start_list(vmdesc, "fields", NULL, 0, &error_abort);
}
while (field->name) {
@@ -309,7 +322,7 @@ void vmstate_save_state(QEMUFile *f, const
VMStateDescription *vmsd,
int i, n_elems = vmstate_n_elems(opaque, field);
int size = vmstate_size(opaque, field);
int64_t old_offset, written_bytes;
- QJSON *vmdesc_loop = vmdesc;
+ Visitor *vmdesc_loop = vmdesc;
for (i = 0; i < n_elems; i++) {
void *addr = base_addr + size * i;
@@ -345,7 +358,7 @@ void vmstate_save_state(QEMUFile *f, const
VMStateDescription *vmsd,
}
if (vmdesc) {
- json_end_array(vmdesc);
+ visit_end_list(vmdesc);
}
vmstate_subsection_save(f, vmsd, opaque, vmdesc);
@@ -415,7 +428,7 @@ static int vmstate_subsection_load(QEMUFile *f, const
VMStateDescription *vmsd,
}
static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription
*vmsd,
- void *opaque, QJSON *vmdesc)
+ void *opaque, Visitor *vmdesc)
{
const VMStateDescription **sub = vmsd->subsections;
bool subsection_found = false;
@@ -428,11 +441,12 @@ static void vmstate_subsection_save(QEMUFile *f, const
VMStateDescription *vmsd,
if (vmdesc) {
/* Only create subsection array when we have any */
if (!subsection_found) {
- json_start_array(vmdesc, "subsections");
+ visit_start_list(vmdesc, "subsections", NULL, 0,
+ &error_abort);
subsection_found = true;
}
- json_start_object(vmdesc, NULL);
+ visit_start_struct(vmdesc, NULL, NULL, 0, &error_abort);
}
qemu_put_byte(f, QEMU_VM_SUBSECTION);
@@ -443,14 +457,15 @@ static void vmstate_subsection_save(QEMUFile *f, const
VMStateDescription *vmsd,
vmstate_save_state(f, vmsd, opaque, vmdesc);
if (vmdesc) {
- json_end_object(vmdesc);
+ visit_check_struct(vmdesc, &error_abort);
+ visit_end_struct(vmdesc);
}
}
sub++;
}
if (vmdesc && subsection_found) {
- json_end_array(vmdesc);
+ visit_end_list(vmdesc);
}
}
diff --git a/tests/Makefile b/tests/Makefile
index 19a9ee0..e363720 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -424,7 +424,7 @@ tests/test-qdev-global-props$(EXESUF):
tests/test-qdev-global-props.o \
$(test-qapi-obj-y)
tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
migration/vmstate.o migration/qemu-file.o migration/qemu-file-buf.o \
- migration/qemu-file-unix.o qjson.o \
+ migration/qemu-file-unix.o qapi/json-output-visitor.o \
$(test-qom-obj-y)
tests/test-timed-average$(EXESUF): tests/test-timed-average.o qemu-timer.o \
$(test-util-obj-y)
--
2.4.3
- Re: [Qemu-devel] [PATCH v2 02/14] qapi: Improve use of qmp/types.h, (continued)
- [Qemu-devel] [PATCH v2 05/14] qapi: Use qstring_append_chr() where appropriate, Eric Blake, 2015/12/21
- [Qemu-devel] [PATCH v2 04/14] qapi: Factor out JSON number formatting, Eric Blake, 2015/12/21
- [Qemu-devel] [PATCH v2 06/14] qapi: Add qstring_append_format(), Eric Blake, 2015/12/21
- [Qemu-devel] [PATCH v2 03/14] qapi: Factor out JSON string escaping, Eric Blake, 2015/12/21
- [Qemu-devel] [PATCH v2 08/14] qjson: Simplify by using json-output-visitor, Eric Blake, 2015/12/21
- [Qemu-devel] [PATCH v2 10/14] vmstate: use new JSON output visitor,
Eric Blake <=
- [Qemu-devel] [PATCH v2 07/14] qapi: add json output visitor, Eric Blake, 2015/12/21
- [Qemu-devel] [PATCH v2 11/14] qjson: Remove unused file, Eric Blake, 2015/12/21
- [Qemu-devel] [PATCH v2 12/14] qapi: Add qobject_to_json_pretty_prefix(), Eric Blake, 2015/12/21
- [Qemu-devel] [PATCH v2 01/14] qapi: Rename (one) qjson.h to qobject-json.h, Eric Blake, 2015/12/21
- [Qemu-devel] [PATCH v2 14/14] qemu-img: Use new JSON output formatter, Eric Blake, 2015/12/21
- [Qemu-devel] [PATCH v2 09/14] Revert "qjson: Simplify by using json-output-visitor", Eric Blake, 2015/12/21
- [Qemu-devel] [PATCH v2 13/14] qapi: Support pretty printing in JSON output visitor, Eric Blake, 2015/12/21
- Re: [Qemu-devel] [PATCH v2 00/14] Add qapi-to-JSON output visitor, Eric Blake, 2015/12/23