* [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema
@ 2014-01-02 23:10 Wenchao Xia
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 1/5] os-posix: include sys/time.h Wenchao Xia
` (5 more replies)
0 siblings, 6 replies; 27+ messages in thread
From: Wenchao Xia @ 2014-01-02 23:10 UTC (permalink / raw)
To: qemu-devel; +Cc: Wenchao Xia, mreitz, armbru, lcapitulino
This series add support for tag/keyword 'event' in qapi-schema.
A new file was created to store some helper functions in patch 2, patch 4 is
the test case, patch 5 is a convert example.
The implemention is done by generate API and a batch of parameters for each
event define, it doesn't generate a struture and visit function in the
background for every event, so it doesn't support nested structure in the
define to avoid trouble. A callback layer is added to control the behavior.
More detail can be found in patch 3's message and incode comments.
Since it is also touching qapi script, it is on top of series:
http://lists.nongnu.org/archive/html/qemu-devel/2013-12/msg03840.html
v2:
Address Luiz's comments:
patch 3: rename *err to *local_err, do not initialize *qmp = NULL, create
a new function qmp_build_evet_dict().
Other change:
reorgnized script in patch 3, it have a clear three steps, see patch 3's
incode comments.
Luiz, I have following change a bit different with your comments, please
have a review:
docs/writing-qmp-commands.txt is still missing, I will add that patch
when this approach get positive feedback.
Patch 3:
API name is qapi_event_send_***(), instead of qapi_send_event_***(), to
keep unified api prefix.
when qapi_event_function.emit == NULL, still return instead of core dump
or error. Before this series, the event function does invalid work silently,
my patch change it to skip invalid work silently. If core dump code is there,
then it still have a silently invalid work as before, since caller will set a
emtpy emit function.
Some code is still kepted in generated file, see incode comments for those
code.
Wenchao Xia (5):
1 os-posix: include sys/time.h
2 qapi: add event helper functions
3 qapi script: add event support by qapi-event.py
4 test: add test cases for qapi event
5 qapi event: convert RTC_CHANGE
Makefile | 9 +-
Makefile.objs | 2 +-
include/qapi/qmp-event.h | 22 ++
include/sysemu/os-posix.h | 2 +
monitor.c | 14 +
qapi-schema.json | 3 +
qapi/Makefile.objs | 1 +
qapi/qmp-event.c | 56 ++++
scripts/qapi-event.py | 432 +++++++++++++++++++++++++++++++
tests/Makefile | 14 +-
tests/qapi-schema/qapi-schema-test.json | 12 +
tests/qapi-schema/qapi-schema-test.out | 10 +-
tests/test-qmp-event.c | 254 ++++++++++++++++++
vl.c | 7 +-
14 files changed, 824 insertions(+), 14 deletions(-)
create mode 100644 include/qapi/qmp-event.h
create mode 100644 qapi/qmp-event.c
create mode 100644 scripts/qapi-event.py
create mode 100644 tests/test-qmp-event.c
^ permalink raw reply [flat|nested] 27+ messages in thread
* [Qemu-devel] [RFC PATCH V2 1/5] os-posix: include sys/time.h
2014-01-02 23:10 [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema Wenchao Xia
@ 2014-01-02 23:10 ` Wenchao Xia
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 2/5] qapi: add event helper functions Wenchao Xia
` (4 subsequent siblings)
5 siblings, 0 replies; 27+ messages in thread
From: Wenchao Xia @ 2014-01-02 23:10 UTC (permalink / raw)
To: qemu-devel; +Cc: Wenchao Xia, mreitz, armbru, lcapitulino
Since gettimeofday() is used in this header file as a macro define,
include the function's define header file, to avoid compile warning
when other file include os-posix.h.
Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
include/sysemu/os-posix.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h
index 25d0b2a..f131521 100644
--- a/include/sysemu/os-posix.h
+++ b/include/sysemu/os-posix.h
@@ -26,6 +26,8 @@
#ifndef QEMU_OS_POSIX_H
#define QEMU_OS_POSIX_H
+#include <sys/time.h>
+
void os_set_line_buffering(void);
void os_set_proc_name(const char *s);
void os_setup_signal_handling(void);
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [RFC PATCH V2 2/5] qapi: add event helper functions
2014-01-02 23:10 [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema Wenchao Xia
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 1/5] os-posix: include sys/time.h Wenchao Xia
@ 2014-01-02 23:10 ` Wenchao Xia
2014-01-06 22:23 ` Luiz Capitulino
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py Wenchao Xia
` (3 subsequent siblings)
5 siblings, 1 reply; 27+ messages in thread
From: Wenchao Xia @ 2014-01-02 23:10 UTC (permalink / raw)
To: qemu-devel; +Cc: Wenchao Xia, mreitz, armbru, lcapitulino
This file hold some functions that do not need to be generated.
Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
include/qapi/qmp-event.h | 22 ++++++++++++++++++
qapi/Makefile.objs | 1 +
qapi/qmp-event.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+), 0 deletions(-)
create mode 100644 include/qapi/qmp-event.h
create mode 100644 qapi/qmp-event.c
diff --git a/include/qapi/qmp-event.h b/include/qapi/qmp-event.h
new file mode 100644
index 0000000..2baf093
--- /dev/null
+++ b/include/qapi/qmp-event.h
@@ -0,0 +1,22 @@
+/*
+ * QMP Event related
+ *
+ * Copyright IBM, Corp. 2014
+ *
+ * Authors:
+ * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPLv2+ or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QMP_EVENT_H
+#define QMP_EVENT_H
+
+#include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
+
+QDict *qmp_event_build_dict(const char *event_name);
+
+#endif
diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
index 1f9c973..d14b769 100644
--- a/qapi/Makefile.objs
+++ b/qapi/Makefile.objs
@@ -3,3 +3,4 @@ util-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
util-obj-y += string-input-visitor.o string-output-visitor.o
util-obj-y += opts-visitor.o
+util-obj-y += qmp-event.o
diff --git a/qapi/qmp-event.c b/qapi/qmp-event.c
new file mode 100644
index 0000000..dc81ec2
--- /dev/null
+++ b/qapi/qmp-event.c
@@ -0,0 +1,56 @@
+/*
+ * QMP Event related
+ *
+ * Copyright IBM, Corp. 2014
+ *
+ * Authors:
+ * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPLv2+ or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include <inttypes.h>
+
+#include "qemu-common.h"
+#include "qapi/qmp-event.h"
+#include "qapi/qmp/qstring.h"
+#include "qapi/qmp/qjson.h"
+
+#ifdef _WIN32
+#include "sysemu/os-win32.h"
+#endif
+
+#ifdef CONFIG_POSIX
+#include "sysemu/os-posix.h"
+#endif
+
+static void timestamp_put(QDict *qdict)
+{
+ int err;
+ QObject *obj;
+ qemu_timeval tv;
+
+ err = qemu_gettimeofday(&tv);
+ if (err < 0) {
+ return;
+ }
+
+ obj = qobject_from_jsonf("{ 'seconds': %" PRId64 ", "
+ "'microseconds': %" PRId64 " }",
+ (int64_t) tv.tv_sec, (int64_t) tv.tv_usec);
+ qdict_put_obj(qdict, "timestamp", obj);
+}
+
+/*
+ * Build a QDict, then fill event name and time stamp, caller should free the
+ * QDict after usage.
+ */
+QDict *qmp_event_build_dict(const char *event_name)
+{
+ QDict *dict = qdict_new();
+ qdict_put(dict, "event", qstring_from_str(event_name));
+ timestamp_put(dict);
+ return dict;
+}
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-01-02 23:10 [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema Wenchao Xia
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 1/5] os-posix: include sys/time.h Wenchao Xia
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 2/5] qapi: add event helper functions Wenchao Xia
@ 2014-01-02 23:10 ` Wenchao Xia
2014-01-06 23:10 ` Luiz Capitulino
2014-03-06 18:49 ` Eric Blake
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 4/5] test: add test cases for qapi event Wenchao Xia
` (2 subsequent siblings)
5 siblings, 2 replies; 27+ messages in thread
From: Wenchao Xia @ 2014-01-02 23:10 UTC (permalink / raw)
To: qemu-devel; +Cc: Wenchao Xia, mreitz, armbru, lcapitulino
qapi-event.py will parse the schema and generate qapi-event.c, then
the API in qapi-event.c can be used to handle event in qemu code.
All API have prefix "qapi_event", all types have prefix "QAPIEvent".
Examples can be found in following patches.
The script mainly include three parts: generate API for each event
define, generate an enum type for all defined event, generate behavior
control functions.
Since in some case the real emit behavior may change, for example,
qemu-img would not send a event, a callback layer is added to
control the behavior. As a result, the stubs at compile time
can be saved, the binding of block layer code and monitor code
will become looser.
Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
Makefile | 9 +-
Makefile.objs | 2 +-
scripts/qapi-event.py | 432 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 439 insertions(+), 4 deletions(-)
create mode 100644 scripts/qapi-event.py
diff --git a/Makefile b/Makefile
index bdff4e4..fa59765 100644
--- a/Makefile
+++ b/Makefile
@@ -45,8 +45,8 @@ endif
endif
GENERATED_HEADERS = config-host.h qemu-options.def
-GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
-GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
+GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
+GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
GENERATED_HEADERS += trace/generated-events.h
GENERATED_SOURCES += trace/generated-events.c
@@ -185,7 +185,7 @@ Makefile: $(version-obj-y) $(version-lobj-y)
# Build libraries
libqemustub.a: $(stub-obj-y)
-libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o
+libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o qapi-event.o
######################################################################
@@ -226,6 +226,9 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
qapi-visit.c qapi-visit.h :\
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." -b < $<, " GEN $@")
+qapi-event.c qapi-event.h :\
+$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py $(gen-out-type) -o "." -b < $<, " GEN $@")
qmp-commands.h qmp-marshal.c :\
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@")
diff --git a/Makefile.objs b/Makefile.objs
index 2b6c1fe..33f5950 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -12,7 +12,7 @@ block-obj-y += main-loop.o iohandler.o qemu-timer.o
block-obj-$(CONFIG_POSIX) += aio-posix.o
block-obj-$(CONFIG_WIN32) += aio-win32.o
block-obj-y += block/
-block-obj-y += qapi-types.o qapi-visit.o
+block-obj-y += qapi-types.o qapi-visit.o qapi-event.o
block-obj-y += qemu-io-cmds.o
block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
new file mode 100644
index 0000000..7526366
--- /dev/null
+++ b/scripts/qapi-event.py
@@ -0,0 +1,432 @@
+#
+# QAPI event generator
+#
+# Copyright IBM, Corp. 2014
+#
+# Authors:
+# Wenchao Xia <xiawenc@linux.vnet.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPLv2+ or later.
+# See the COPYING.LIB file in the top-level directory.
+
+from ordereddict import OrderedDict
+from qapi import *
+import sys
+import os
+import getopt
+import errno
+
+def _generate_event_api_name(event_name, params):
+ api_name = "void qapi_event_send_%s(" % c_fun(event_name).lower();
+ l = len(api_name)
+
+ if params:
+ for argname, argentry, optional, structured in parse_args(params):
+ if structured:
+ sys.stderr.write("Nested structure define in event is not "
+ "supported now, event '%s', argname '%s'\n" %
+ (event_name, argname))
+ sys.exit(1)
+ continue
+
+ if optional:
+ api_name += "bool has_%s,\n" % c_var(argname)
+ api_name += "".ljust(l)
+
+ if argentry == "str":
+ api_name += "const "
+ api_name += "%s %s,\n" % (c_type(argentry), c_var(argname))
+ api_name += "".ljust(l)
+
+ api_name += "Error **errp)"
+ return api_name;
+
+
+# Following are the core functions that transate user input into a qdict going
+# to be emitted in the wire.
+
+def generate_event_declaration(api_name):
+ return mcgen('''
+
+%(api_name)s;
+''',
+ api_name = api_name)
+
+def generate_event_implement(api_name, event_name, params):
+ # step 1: declare and variables
+ ret = mcgen("""
+
+%(api_name)s
+{
+ QDict *qmp;
+ Error *local_err = NULL;
+ QAPIEventFuncEmit emit;
+""",
+ api_name = api_name)
+
+ if params:
+ ret += mcgen("""
+ QmpOutputVisitor *qov;
+ Visitor *v;
+ QObject *obj;
+
+""")
+
+ # step 2: check emit function, create a dict
+ ret += mcgen("""
+ emit = qapi_event_get_func_emit();
+ if (!emit) {
+ return;
+ }
+
+ qmp = qmp_event_build_dict("%(event_name)s");
+
+""",
+ event_name = event_name)
+
+ # step 3: visit the params if params != None
+ if params:
+ ret += mcgen("""
+ qov = qmp_output_visitor_new();
+ g_assert(qov);
+
+ v = qmp_output_get_visitor(qov);
+ g_assert(v);
+
+ /* Fake visit, as if all member are under a structure */
+ visit_start_struct(v, NULL, "", "%(event_name)s", 0, &local_err);
+ if (error_is_set(&local_err)) {
+ goto clean;
+ }
+
+""",
+ event_name = event_name)
+
+ for argname, argentry, optional, structured in parse_args(params):
+ if structured:
+ sys.stderr.write("Nested structure define in event is not "
+ "supported now, event '%s', argname '%s'\n" %
+ (event_name, argname))
+ sys.exit(1)
+
+ if optional:
+ ret += mcgen("""
+ if (has_%(var)s) {
+""",
+ var = c_var(argname))
+ push_indent()
+
+ if argentry == "str":
+ var_type = "(char **)"
+ else:
+ var_type = ""
+
+ ret += mcgen("""
+ visit_type_%(type)s(v, %(var_type)s&%(var)s, "%(name)s", &local_err);
+ if (error_is_set(&local_err)) {
+ goto clean;
+ }
+""",
+ var_type = var_type,
+ var = c_var(argname),
+ type = type_name(argentry),
+ name = argname)
+
+ if optional:
+ pop_indent()
+ ret += mcgen("""
+ }
+""")
+
+ ret += mcgen("""
+
+ visit_end_struct(v, &local_err);
+ if (error_is_set(&local_err)) {
+ goto clean;
+ }
+
+ obj = qmp_output_get_qobject(qov);
+ g_assert(obj != NULL);
+
+ qdict_put_obj(qmp, "data", obj);
+""")
+
+ # step 4: call qmp event api
+ ret += mcgen("""
+ emit(%(event_enum_value)s, qmp, &local_err);
+
+""",
+ event_enum_value = event_enum_value)
+
+ # step 5: clean up
+ if params:
+ ret += mcgen("""
+ clean:
+ qmp_output_visitor_cleanup(qov);
+""")
+ ret += mcgen("""
+ error_propagate(errp, local_err);
+ QDECREF(qmp);
+}
+""")
+
+ return ret
+
+
+# Following are the functions that generate an enum type for all defined
+# events, similar with qapi-types.py. Here we already have enum name and
+# values which is generated before and recorded in event_enum_*. It also
+# walk around the issue that "import qapi-types" can't work.
+
+def generate_event_enum_decl(event_enum_name, event_enum_values):
+ lookup_decl = mcgen('''
+
+extern const char *%(event_enum_name)s_lookup[];
+''',
+ event_enum_name = event_enum_name)
+
+ enum_decl = mcgen('''
+typedef enum %(event_enum_name)s
+{
+''',
+ event_enum_name = event_enum_name)
+
+ # append automatically generated _MAX value
+ enum_max_value = generate_enum_full_value_string(event_enum_name, "MAX")
+ enum_values = event_enum_values + [ enum_max_value ]
+
+ i = 0
+ for value in enum_values:
+ enum_decl += mcgen('''
+ %(value)s = %(i)d,
+''',
+ value = value,
+ i = i)
+ i += 1
+
+ enum_decl += mcgen('''
+} %(event_enum_name)s;
+''',
+ event_enum_name = event_enum_name)
+
+ return lookup_decl + enum_decl
+
+def generate_event_enum_lookup(event_enum_name, event_enum_strings):
+ ret = mcgen('''
+
+const char *%(event_enum_name)s_lookup[] = {
+''',
+ event_enum_name = event_enum_name)
+
+ i = 0
+ for string in event_enum_strings:
+ ret += mcgen('''
+ "%(string)s",
+''',
+ string = string)
+
+ ret += mcgen('''
+ NULL,
+};
+''')
+ return ret
+
+
+# Following are the functions that generate event behavior control functions.
+# Those functions are put here in the qapi-event.c, since it need to include
+# qapi-event.h for the event enum type declaration, put them in other file
+# requiring other file include qapi-event.h, causing a cross including. For
+# example: if we have qmp-event.c and qmp-event.h, then qmp-event.c
+# ->qmp-event.h->qapi-event.h, qapi-event.c->qmp-event.h. Another problem
+# follow: test-qapi-event.c will meet event enum double declaration since it
+# include both test-qapi-event.h and qmp-event.h. One solution is putting event
+# enum declaration in a separate header file, but then qmp-event.h need to
+# include test-qapi-event.h or qapi-event.h on compile time condition. So the
+# easist way is, just generate them here.
+
+def generate_event_behavior_control_decl(event_enum_name):
+ ret = mcgen('''
+
+typedef void (*QAPIEventFuncEmit)(%(event_enum_name)s ev,
+ QDict *dict,
+ Error **errp);
+
+void qapi_event_set_func_emit(QAPIEventFuncEmit emit);
+
+QAPIEventFuncEmit qapi_event_get_func_emit(void);
+''',
+ event_enum_name = event_enum_name)
+ return ret;
+
+def generate_event_behavior_control_implement():
+ ret = mcgen('''
+
+typedef struct QAPIEventFunctions {
+ QAPIEventFuncEmit emit;
+} QAPIEventFunctions;
+
+QAPIEventFunctions qapi_event_functions;
+
+void qapi_event_set_func_emit(QAPIEventFuncEmit emit)
+{
+ qapi_event_functions.emit = emit;
+}
+
+QAPIEventFuncEmit qapi_event_get_func_emit(void)
+{
+ return qapi_event_functions.emit;
+}
+''')
+ return ret
+
+
+# Start the real job
+
+try:
+ opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
+ ["source", "header", "builtins", "prefix=",
+ "output-dir="])
+except getopt.GetoptError, err:
+ print str(err)
+ sys.exit(1)
+
+output_dir = ""
+prefix = ""
+c_file = 'qapi-event.c'
+h_file = 'qapi-event.h'
+
+do_c = False
+do_h = False
+do_builtins = False
+
+for o, a in opts:
+ if o in ("-p", "--prefix"):
+ prefix = a
+ elif o in ("-o", "--output-dir"):
+ output_dir = a + "/"
+ elif o in ("-c", "--source"):
+ do_c = True
+ elif o in ("-h", "--header"):
+ do_h = True
+ elif o in ("-b", "--builtins"):
+ do_builtins = True
+
+if not do_c and not do_h:
+ do_c = True
+ do_h = True
+
+c_file = output_dir + prefix + c_file
+h_file = output_dir + prefix + h_file
+
+try:
+ os.makedirs(output_dir)
+except os.error, e:
+ if e.errno != errno.EEXIST:
+ raise
+
+def maybe_open(really, name, opt):
+ if really:
+ return open(name, opt)
+ else:
+ import StringIO
+ return StringIO.StringIO()
+
+fdef = maybe_open(do_c, c_file, 'w')
+fdecl = maybe_open(do_h, h_file, 'w')
+
+fdef.write(mcgen('''
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+/*
+ * schema-defined QAPI event functions
+ *
+ * Copyright IBM, Corp. 2014
+ *
+ * Authors:
+ * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPLv2+ or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "%(header)s"
+#include "%(prefix)sqapi-visit.h"
+#include "qapi/qmp-output-visitor.h"
+#include "qapi/qmp-event.h"
+
+''',
+ prefix=prefix, header=basename(h_file)))
+
+fdecl.write(mcgen('''
+/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+/*
+ * schema-defined QAPI event function
+ *
+ * Copyright IBM, Corp. 2014
+ *
+ * Authors:
+ * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPLv2+ or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef %(guard)s
+#define %(guard)s
+
+#include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
+#include "%(prefix)sqapi-types.h"
+
+''',
+ prefix=prefix, guard=guardname(h_file)))
+
+exprs = parse_schema(sys.stdin)
+
+event_enum_name = "QAPIEvent"
+event_enum_values = []
+event_enum_strings = []
+
+for expr in exprs:
+ if expr.has_key('event'):
+ event_name = expr['event']
+ params = expr.get('data')
+ if params and len(params) == 0:
+ params = None
+
+ api_name = _generate_event_api_name(event_name, params)
+ ret = generate_event_declaration(api_name)
+ fdecl.write(ret)
+
+ # We need an enum value per event
+ event_enum_value = generate_enum_full_value_string(event_enum_name,
+ event_name)
+ ret = generate_event_implement(api_name, event_name, params)
+ fdef.write(ret)
+
+ # Record it, and generate enum later
+ event_enum_values.append(event_enum_value)
+ event_enum_strings.append(event_name)
+
+ret = generate_event_enum_decl(event_enum_name, event_enum_values)
+fdecl.write(ret)
+ret = generate_event_enum_lookup(event_enum_name, event_enum_strings)
+fdef.write(ret)
+ret = generate_event_behavior_control_decl(event_enum_name)
+fdecl.write(ret)
+ret = generate_event_behavior_control_implement()
+fdef.write(ret)
+
+fdecl.write('''
+#endif
+''')
+
+fdecl.flush()
+fdecl.close()
+
+fdef.flush()
+fdef.close()
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [RFC PATCH V2 4/5] test: add test cases for qapi event
2014-01-02 23:10 [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema Wenchao Xia
` (2 preceding siblings ...)
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py Wenchao Xia
@ 2014-01-02 23:10 ` Wenchao Xia
2014-03-06 20:05 ` Eric Blake
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 5/5] qapi event: convert RTC_CHANGE Wenchao Xia
2014-01-06 23:18 ` [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema Luiz Capitulino
5 siblings, 1 reply; 27+ messages in thread
From: Wenchao Xia @ 2014-01-02 23:10 UTC (permalink / raw)
To: qemu-devel; +Cc: Wenchao Xia, mreitz, armbru, lcapitulino
These cases will verify whether the expected qdict is built.
Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
tests/Makefile | 14 ++-
tests/qapi-schema/qapi-schema-test.json | 12 ++
tests/qapi-schema/qapi-schema-test.out | 10 +-
tests/test-qmp-event.c | 254 +++++++++++++++++++++++++++++++
4 files changed, 285 insertions(+), 5 deletions(-)
create mode 100644 tests/test-qmp-event.c
diff --git a/tests/Makefile b/tests/Makefile
index 8d25878..e83ff71 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -23,6 +23,8 @@ check-unit-y += tests/test-string-input-visitor$(EXESUF)
gcov-files-test-string-input-visitor-y = qapi/string-input-visitor.c
check-unit-y += tests/test-string-output-visitor$(EXESUF)
gcov-files-test-string-output-visitor-y = qapi/string-output-visitor.c
+check-unit-y += tests/test-qmp-event$(EXESUF)
+gcov-files-test-qmp-event-y += qapi/qmp-event.c
check-unit-y += tests/test-opts-visitor$(EXESUF)
gcov-files-test-opts-visitor-y = qapi/opts-visitor.c
check-unit-y += tests/test-coroutine$(EXESUF)
@@ -123,7 +125,8 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
trailing-comma-list.json trailing-comma-object.json \
unclosed-list.json unclosed-object.json unclosed-string.json)
-GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
+GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h \
+ tests/test-qapi-event.h tests/test-qmp-commands.h
test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
tests/check-qlist.o tests/check-qfloat.o tests/check-qjson.o \
@@ -132,9 +135,10 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
tests/test-qmp-commands.o tests/test-visitor-serialization.o \
tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
- tests/test-opts-visitor.o
+ tests/test-opts-visitor.o tests/test-qmp-event.o
-test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o
+test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
+ tests/test-qapi-event.o
$(test-obj-y): QEMU_INCLUDES += -Itests
QEMU_CFLAGS += -I$(SRC_PATH)/tests
@@ -170,12 +174,16 @@ $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-typ
tests/test-qapi-visit.c tests/test-qapi-visit.h :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
+tests/test-qapi-event.c tests/test-qapi-event.h :\
+$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-event.py
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
+tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 0bc58ac..547cc88 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -88,3 +88,15 @@
'*u16' : [ 'uint16' ],
'*i64x': 'int' ,
'*u64x': 'uint64' } }
+
+# testing event
+{ 'type': 'EventStructOne',
+ 'data': { 'struct1': 'UserDefOne', 'string': 'str', '*enum2': 'EnumOne' } }
+
+{ 'event': 'EVENT_A' }
+{ 'event': 'EVENT_B',
+ 'data': { } }
+{ 'event': 'EVENT_C',
+ 'data': { '*a': 'int', '*b': 'UserDefOne', 'c': 'str' } }
+{ 'event': 'EVENT_D',
+ 'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 80edf10..b2204af 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -15,7 +15,12 @@
OrderedDict([('command', 'user_def_cmd'), ('data', OrderedDict())]),
OrderedDict([('command', 'user_def_cmd1'), ('data', OrderedDict([('ud1a', 'UserDefOne')]))]),
OrderedDict([('command', 'user_def_cmd2'), ('data', OrderedDict([('ud1a', 'UserDefOne'), ('ud1b', 'UserDefOne')])), ('returns', 'UserDefTwo')]),
- OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])]
+ OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]),
+ OrderedDict([('type', 'EventStructOne'), ('data', OrderedDict([('struct1', 'UserDefOne'), ('string', 'str'), ('*enum2', 'EnumOne')]))]),
+ OrderedDict([('event', 'EVENT_A')]),
+ OrderedDict([('event', 'EVENT_B'), ('data', OrderedDict())]),
+ OrderedDict([('event', 'EVENT_C'), ('data', OrderedDict([('*a', 'int'), ('*b', 'UserDefOne'), ('c', 'str')]))]),
+ OrderedDict([('event', 'EVENT_D'), ('data', OrderedDict([('a', 'EventStructOne'), ('b', 'str'), ('*c', 'str'), ('*enum3', 'EnumOne')]))])]
[{'enum_name': 'EnumOne', 'enum_values': ['value1', 'value2', 'value3']},
{'enum_name': 'UserDefUnionKind', 'enum_values': None},
{'enum_name': 'UserDefBaseUnionKind', 'enum_values': None},
@@ -29,4 +34,5 @@
OrderedDict([('type', 'UserDefBase0'), ('data', OrderedDict([('base-string0', 'str'), ('base-enum0', 'EnumOne')]))]),
OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
- OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])]
+ OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]),
+ OrderedDict([('type', 'EventStructOne'), ('data', OrderedDict([('struct1', 'UserDefOne'), ('string', 'str'), ('*enum2', 'EnumOne')]))])]
diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
new file mode 100644
index 0000000..d8fbef9
--- /dev/null
+++ b/tests/test-qmp-event.c
@@ -0,0 +1,254 @@
+/*
+ * qapi event unit-tests.
+ *
+ * Copyright IBM, Corp. 2014
+ *
+ * Authors:
+ * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPLv2+ or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qemu-common.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "test-qapi-event.h"
+#include "qapi/qmp/types.h"
+#include "qapi/qmp/qobject.h"
+
+typedef struct TestEventData {
+ QDict *expect;
+} TestEventData;
+
+typedef struct QDictCmpData {
+ QDict *expect;
+ bool result;
+} QDictCmpData;
+
+TestEventData *test_event_data;
+static GStaticMutex test_event_lock = G_STATIC_MUTEX_INIT;
+
+/* Only compares bool, int, string */
+static
+void qdict_cmp_do_simple(const char *key, QObject *obj1, void *opaque)
+
+{
+ QObject *obj2;
+ QDictCmpData d_new, *d = opaque;
+
+ if (!d->result) {
+ return;
+ }
+
+ obj2 = qdict_get(d->expect, key);
+ if (!obj2) {
+ d->result = false;
+ return;
+ }
+
+ if (qobject_type(obj1) != qobject_type(obj2)) {
+ d->result = false;
+ return;
+ }
+
+ switch (qobject_type(obj1)) {
+ case QTYPE_QBOOL:
+ d->result = (qbool_get_int(qobject_to_qbool(obj1)) ==
+ qbool_get_int(qobject_to_qbool(obj2)));
+ return;
+ case QTYPE_QINT:
+ d->result = (qint_get_int(qobject_to_qint(obj1)) ==
+ qint_get_int(qobject_to_qint(obj2)));
+ return;
+ case QTYPE_QSTRING:
+ if (!g_strcmp0(qstring_get_str(qobject_to_qstring(obj1)),
+ qstring_get_str(qobject_to_qstring(obj2)))) {
+ d->result = true;
+ } else {
+ d->result = false;
+ }
+ return;
+ case QTYPE_QDICT:
+ d_new.expect = qobject_to_qdict(obj2);
+ d_new.result = true;
+ qdict_iter(qobject_to_qdict(obj1), qdict_cmp_do_simple, &d_new);
+ d->result = d_new.result;
+ return;
+ default:
+ abort();
+ }
+}
+
+static bool qdict_cmp_simple(QDict *a, QDict *b)
+{
+ QDictCmpData d;
+
+ d.expect = b;
+ d.result = true;
+ qdict_iter(a, qdict_cmp_do_simple, &d);
+ return d.result;
+}
+
+/* This function is hooked as final emit funtion, which can verify the
+ correctness. */
+static void event_test_emit(QAPIEvent ev, QDict *d, Error **errp)
+{
+ QObject *obj;
+ QDict *t;
+
+ /* Verify that we have timestamp, then remove it to compare other field */
+ obj = qdict_get(d, "timestamp");
+ g_assert(obj);
+ t = qobject_to_qdict(obj);
+ g_assert(t);
+ obj = qdict_get(t, "seconds");
+ g_assert(obj && qobject_type(obj) == QTYPE_QINT);
+ obj = qdict_get(t, "microseconds");
+ g_assert(obj && qobject_type(obj) == QTYPE_QINT);
+
+ qdict_del(d, "timestamp");
+
+ g_assert(qdict_cmp_simple(d, test_event_data->expect));
+
+}
+
+static void event_prepare(TestEventData *data,
+ const void *unused)
+{
+ /* Global variable test_event_data was used to pass the expectation, so
+ test cases can't be executed at same time. */
+ g_static_mutex_lock(&test_event_lock);
+
+ data->expect = qdict_new();
+ test_event_data = data;
+}
+
+static void event_teardown(TestEventData *data,
+ const void *unused)
+{
+ QDECREF(data->expect);
+ test_event_data = NULL;
+
+ g_static_mutex_unlock(&test_event_lock);
+}
+
+static void event_test_add(const char *testpath,
+ void (*test_func)(TestEventData *data,
+ const void *user_data))
+{
+ g_test_add(testpath, TestEventData, NULL, event_prepare, test_func,
+ event_teardown);
+}
+
+
+/* Test cases */
+
+static void test_event_a(TestEventData *data,
+ const void *unused)
+{
+ QDict *d;
+ d = data->expect;
+ qdict_put(d, "event", qstring_from_str("EVENT_A"));
+ qapi_event_send_event_a(NULL);
+}
+
+static void test_event_b(TestEventData *data,
+ const void *unused)
+{
+ QDict *d;
+ d = data->expect;
+ qdict_put(d, "event", qstring_from_str("EVENT_B"));
+ qapi_event_send_event_b(NULL);
+}
+
+static void test_event_c(TestEventData *data,
+ const void *unused)
+{
+ QDict *d, *d_data, *d_b;
+
+ UserDefOne b;
+ b.integer = 2;
+ b.string = g_strdup("test1");
+ b.has_enum1 = false;
+
+ d_b = qdict_new();
+ qdict_put(d_b, "integer", qint_from_int(2));
+ qdict_put(d_b, "string", qstring_from_str("test1"));
+
+ d_data = qdict_new();
+ qdict_put(d_data, "a", qint_from_int(1));
+ qdict_put(d_data, "b", d_b);
+ qdict_put(d_data, "c", qstring_from_str("test2"));
+
+ d = data->expect;
+ qdict_put(d, "event", qstring_from_str("EVENT_C"));
+ qdict_put(d, "data", d_data);
+
+ qapi_event_send_event_c(true, 1, true, &b, "test2", NULL);
+
+ g_free(b.string);
+}
+
+/* Complex type */
+static void test_event_d(TestEventData *data,
+ const void *unused)
+{
+ UserDefOne struct1;
+ EventStructOne a;
+ QDict *d, *d_data, *d_a, *d_struct1;
+
+ struct1.integer = 2;
+ struct1.string = g_strdup("test1");
+ struct1.has_enum1 = true;
+ struct1.enum1 = ENUM_ONE_VALUE1;
+
+ a.struct1 = &struct1;
+ a.string = g_strdup("test2");
+ a.has_enum2 = true;
+ a.enum2 = ENUM_ONE_VALUE2;
+
+ d_struct1 = qdict_new();
+ qdict_put(d_struct1, "integer", qint_from_int(2));
+ qdict_put(d_struct1, "string", qstring_from_str("test1"));
+ qdict_put(d_struct1, "enum1", qstring_from_str("value1"));
+
+ d_a = qdict_new();
+ qdict_put(d_a, "struct1", d_struct1);
+ qdict_put(d_a, "string", qstring_from_str("test2"));
+ qdict_put(d_a, "enum2", qstring_from_str("value2"));
+
+ d_data = qdict_new();
+ qdict_put(d_data, "a", d_a);
+ qdict_put(d_data, "b", qstring_from_str("test3"));
+ qdict_put(d_data, "enum3", qstring_from_str("value3"));
+
+ d = data->expect;
+ qdict_put(d, "event", qstring_from_str("EVENT_D"));
+ qdict_put(d, "data", d_data);
+
+ qapi_event_send_event_d(&a, "test3", false, NULL, true, ENUM_ONE_VALUE3,
+ NULL);
+
+ g_free(struct1.string);
+ g_free(a.string);
+}
+
+int main(int argc, char **argv)
+{
+ qapi_event_set_func_emit(event_test_emit);
+
+ g_test_init(&argc, &argv, NULL);
+
+ event_test_add("/event/event_a", test_event_a);
+ event_test_add("/event/event_b", test_event_b);
+ event_test_add("/event/event_c", test_event_c);
+ event_test_add("/event/event_d", test_event_d);
+ g_test_run();
+
+ return 0;
+}
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [Qemu-devel] [RFC PATCH V2 5/5] qapi event: convert RTC_CHANGE
2014-01-02 23:10 [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema Wenchao Xia
` (3 preceding siblings ...)
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 4/5] test: add test cases for qapi event Wenchao Xia
@ 2014-01-02 23:10 ` Wenchao Xia
2014-03-06 20:24 ` Eric Blake
2014-01-06 23:18 ` [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema Luiz Capitulino
5 siblings, 1 reply; 27+ messages in thread
From: Wenchao Xia @ 2014-01-02 23:10 UTC (permalink / raw)
To: qemu-devel; +Cc: Wenchao Xia, mreitz, armbru, lcapitulino
This is just an example of how to use qapi event API, and it
bypassed the event throttle queue. A complete convert should
be first define all events in qapi-schema.json, use qapi
event types in monitor functions, then change calller one
by one.
Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
---
monitor.c | 14 ++++++++++++++
qapi-schema.json | 3 +++
vl.c | 7 ++-----
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/monitor.c b/monitor.c
index 845f608..8dca027 100644
--- a/monitor.c
+++ b/monitor.c
@@ -74,6 +74,8 @@
#endif
#include "hw/lm32/lm32_pic.h"
+#include "qapi-event.h"
+
//#define DEBUG
//#define DEBUG_COMPLETION
@@ -628,6 +630,16 @@ monitor_protocol_event_throttle(MonitorEvent event,
evstate->data = NULL;
}
+static void monitor_event_emit(QAPIEvent ev, QDict *d, Error **errp)
+{
+ Monitor *mon;
+
+ QLIST_FOREACH(mon, &mon_list, entry) {
+ if (monitor_ctrl_mode(mon) && qmp_cmd_mode(mon)) {
+ monitor_json_emitter(mon, QOBJECT(d));
+ }
+ }
+}
/* Global, one-time initializer to configure the rate limiting
* and initialize state */
@@ -637,6 +649,8 @@ static void monitor_protocol_event_init(void)
monitor_protocol_event_throttle(QEVENT_RTC_CHANGE, 1000);
monitor_protocol_event_throttle(QEVENT_BALLOON_CHANGE, 1000);
monitor_protocol_event_throttle(QEVENT_WATCHDOG, 1000);
+
+ qapi_event_set_func_emit(monitor_event_emit);
}
/**
diff --git a/qapi-schema.json b/qapi-schema.json
index 9b51dcc..60ddf44 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -4247,3 +4247,6 @@
# Since: 1.7
##
{ 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
+
+{ 'event': 'RTC_CHANGE',
+ 'data': { 'offset' : 'int' } }
diff --git a/vl.c b/vl.c
index 7511e70..7726116 100644
--- a/vl.c
+++ b/vl.c
@@ -170,6 +170,7 @@ int main(int argc, char **argv)
#include "ui/qemu-spice.h"
#include "qapi/string-input-visitor.h"
+#include "qapi-event.h"
//#define DEBUG_NET
//#define DEBUG_SLIRP
@@ -743,11 +744,7 @@ int qemu_timedate_diff(struct tm *tm)
void rtc_change_mon_event(struct tm *tm)
{
- QObject *data;
-
- data = qobject_from_jsonf("{ 'offset': %d }", qemu_timedate_diff(tm));
- monitor_protocol_event(QEVENT_RTC_CHANGE, data);
- qobject_decref(data);
+ qapi_event_send_rtc_change(qemu_timedate_diff(tm), NULL);
}
static void configure_rtc_date_offset(const char *startdate, int legacy)
--
1.7.1
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 2/5] qapi: add event helper functions
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 2/5] qapi: add event helper functions Wenchao Xia
@ 2014-01-06 22:23 ` Luiz Capitulino
2014-01-07 2:28 ` Wenchao Xia
2014-03-06 18:26 ` Eric Blake
0 siblings, 2 replies; 27+ messages in thread
From: Luiz Capitulino @ 2014-01-06 22:23 UTC (permalink / raw)
To: Wenchao Xia; +Cc: mreitz, qemu-devel, armbru
On Fri, 3 Jan 2014 07:10:31 +0800
Wenchao Xia <xiawenc@linux.vnet.ibm.com> wrote:
> This file hold some functions that do not need to be generated.
>
> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> ---
> include/qapi/qmp-event.h | 22 ++++++++++++++++++
> qapi/Makefile.objs | 1 +
> qapi/qmp-event.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 79 insertions(+), 0 deletions(-)
> create mode 100644 include/qapi/qmp-event.h
> create mode 100644 qapi/qmp-event.c
>
> diff --git a/include/qapi/qmp-event.h b/include/qapi/qmp-event.h
> new file mode 100644
> index 0000000..2baf093
> --- /dev/null
> +++ b/include/qapi/qmp-event.h
> @@ -0,0 +1,22 @@
> +/*
> + * QMP Event related
> + *
> + * Copyright IBM, Corp. 2014
> + *
> + * Authors:
> + * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> + *
> + * This work is licensed under the terms of the GNU GPLv2+ or later.
> + * See the COPYING.LIB file in the top-level directory.
> + *
> + */
> +
> +#ifndef QMP_EVENT_H
> +#define QMP_EVENT_H
> +
> +#include "qapi/error.h"
> +#include "qapi/qmp/qdict.h"
> +
> +QDict *qmp_event_build_dict(const char *event_name);
> +
> +#endif
> diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
> index 1f9c973..d14b769 100644
> --- a/qapi/Makefile.objs
> +++ b/qapi/Makefile.objs
> @@ -3,3 +3,4 @@ util-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
> util-obj-y += string-input-visitor.o string-output-visitor.o
>
> util-obj-y += opts-visitor.o
> +util-obj-y += qmp-event.o
> diff --git a/qapi/qmp-event.c b/qapi/qmp-event.c
> new file mode 100644
> index 0000000..dc81ec2
> --- /dev/null
> +++ b/qapi/qmp-event.c
> @@ -0,0 +1,56 @@
> +/*
> + * QMP Event related
> + *
> + * Copyright IBM, Corp. 2014
> + *
> + * Authors:
> + * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> + *
> + * This work is licensed under the terms of the GNU GPLv2+ or later.
> + * See the COPYING.LIB file in the top-level directory.
> + *
> + */
> +
> +#include <inttypes.h>
> +
> +#include "qemu-common.h"
> +#include "qapi/qmp-event.h"
> +#include "qapi/qmp/qstring.h"
> +#include "qapi/qmp/qjson.h"
> +
> +#ifdef _WIN32
> +#include "sysemu/os-win32.h"
> +#endif
> +
> +#ifdef CONFIG_POSIX
> +#include "sysemu/os-posix.h"
> +#endif
> +
> +static void timestamp_put(QDict *qdict)
> +{
> + int err;
> + QObject *obj;
> + qemu_timeval tv;
> +
> + err = qemu_gettimeofday(&tv);
> + if (err < 0) {
> + return;
> + }
Hmm, I see this has always existed (and I guess I did it myself), but it's
not quite right. Sending an event w/o time info wouldn't be complaint to
the protocol spec. It's a good idea to fix this now. We have three options:
1. abort()
2. Skip sending the event altogether
3. Add a bogus time value (say seconds=0 and microseconds=0)
I don't know what's best, but I guess I'd do item 3. Although I wonder
if zero is any better then no info at all (it's certainly complaint, but
not a valid info). Maybe skip the event then?
> +
> + obj = qobject_from_jsonf("{ 'seconds': %" PRId64 ", "
> + "'microseconds': %" PRId64 " }",
> + (int64_t) tv.tv_sec, (int64_t) tv.tv_usec);
> + qdict_put_obj(qdict, "timestamp", obj);
> +}
> +
> +/*
> + * Build a QDict, then fill event name and time stamp, caller should free the
> + * QDict after usage.
> + */
> +QDict *qmp_event_build_dict(const char *event_name)
> +{
> + QDict *dict = qdict_new();
> + qdict_put(dict, "event", qstring_from_str(event_name));
> + timestamp_put(dict);
> + return dict;
> +}
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py Wenchao Xia
@ 2014-01-06 23:10 ` Luiz Capitulino
2014-01-06 23:17 ` Luiz Capitulino
2014-01-07 2:53 ` Wenchao Xia
2014-03-06 18:49 ` Eric Blake
1 sibling, 2 replies; 27+ messages in thread
From: Luiz Capitulino @ 2014-01-06 23:10 UTC (permalink / raw)
To: Wenchao Xia; +Cc: mreitz, qemu-devel, armbru
On Fri, 3 Jan 2014 07:10:32 +0800
Wenchao Xia <xiawenc@linux.vnet.ibm.com> wrote:
> qapi-event.py will parse the schema and generate qapi-event.c, then
> the API in qapi-event.c can be used to handle event in qemu code.
> All API have prefix "qapi_event", all types have prefix "QAPIEvent".
> Examples can be found in following patches.
>
> The script mainly include three parts: generate API for each event
> define, generate an enum type for all defined event, generate behavior
> control functions.
>
> Since in some case the real emit behavior may change, for example,
> qemu-img would not send a event, a callback layer is added to
> control the behavior. As a result, the stubs at compile time
> can be saved, the binding of block layer code and monitor code
> will become looser.
>
> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> ---
> Makefile | 9 +-
> Makefile.objs | 2 +-
> scripts/qapi-event.py | 432 +++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 439 insertions(+), 4 deletions(-)
> create mode 100644 scripts/qapi-event.py
>
> diff --git a/Makefile b/Makefile
> index bdff4e4..fa59765 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -45,8 +45,8 @@ endif
> endif
>
> GENERATED_HEADERS = config-host.h qemu-options.def
> -GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
> -GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
> +GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
> +GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
>
> GENERATED_HEADERS += trace/generated-events.h
> GENERATED_SOURCES += trace/generated-events.c
> @@ -185,7 +185,7 @@ Makefile: $(version-obj-y) $(version-lobj-y)
> # Build libraries
>
> libqemustub.a: $(stub-obj-y)
> -libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o
> +libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o qapi-event.o
>
> ######################################################################
>
> @@ -226,6 +226,9 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
> qapi-visit.c qapi-visit.h :\
> $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
> $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." -b < $<, " GEN $@")
> +qapi-event.c qapi-event.h :\
> +$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
> + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py $(gen-out-type) -o "." -b < $<, " GEN $@")
> qmp-commands.h qmp-marshal.c :\
> $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
> $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@")
> diff --git a/Makefile.objs b/Makefile.objs
> index 2b6c1fe..33f5950 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -12,7 +12,7 @@ block-obj-y += main-loop.o iohandler.o qemu-timer.o
> block-obj-$(CONFIG_POSIX) += aio-posix.o
> block-obj-$(CONFIG_WIN32) += aio-win32.o
> block-obj-y += block/
> -block-obj-y += qapi-types.o qapi-visit.o
> +block-obj-y += qapi-types.o qapi-visit.o qapi-event.o
> block-obj-y += qemu-io-cmds.o
>
> block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
> diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
> new file mode 100644
> index 0000000..7526366
> --- /dev/null
> +++ b/scripts/qapi-event.py
> @@ -0,0 +1,432 @@
> +#
> +# QAPI event generator
> +#
> +# Copyright IBM, Corp. 2014
> +#
> +# Authors:
> +# Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> +#
> +# This work is licensed under the terms of the GNU GPLv2+ or later.
> +# See the COPYING.LIB file in the top-level directory.
> +
> +from ordereddict import OrderedDict
> +from qapi import *
> +import sys
> +import os
> +import getopt
> +import errno
> +
> +def _generate_event_api_name(event_name, params):
Why the underline? And, what you generate is a function declaration...
> + api_name = "void qapi_event_send_%s(" % c_fun(event_name).lower();
> + l = len(api_name)
> +
> + if params:
> + for argname, argentry, optional, structured in parse_args(params):
> + if structured:
> + sys.stderr.write("Nested structure define in event is not "
> + "supported now, event '%s', argname '%s'\n" %
> + (event_name, argname))
> + sys.exit(1)
> + continue
> +
> + if optional:
> + api_name += "bool has_%s,\n" % c_var(argname)
> + api_name += "".ljust(l)
> +
> + if argentry == "str":
> + api_name += "const "
> + api_name += "%s %s,\n" % (c_type(argentry), c_var(argname))
> + api_name += "".ljust(l)
> +
> + api_name += "Error **errp)"
> + return api_name;
> +
> +
> +# Following are the core functions that transate user input into a qdict going
s/transate/translate
Although the comment doesn't make much sense to me.
> +# to be emitted in the wire.
> +
> +def generate_event_declaration(api_name):
> + return mcgen('''
> +
> +%(api_name)s;
> +''',
> + api_name = api_name)
> +
> +def generate_event_implement(api_name, event_name, params):
I wonder if it would be clearer to to generate the declaration here.
> + # step 1: declare and variables
> + ret = mcgen("""
> +
> +%(api_name)s
> +{
> + QDict *qmp;
> + Error *local_err = NULL;
> + QAPIEventFuncEmit emit;
> +""",
> + api_name = api_name)
> +
> + if params:
> + ret += mcgen("""
> + QmpOutputVisitor *qov;
> + Visitor *v;
> + QObject *obj;
> +
> +""")
> +
> + # step 2: check emit function, create a dict
> + ret += mcgen("""
> + emit = qapi_event_get_func_emit();
> + if (!emit) {
> + return;
> + }
> +
> + qmp = qmp_event_build_dict("%(event_name)s");
> +
> +""",
> + event_name = event_name)
> +
> + # step 3: visit the params if params != None
> + if params:
> + ret += mcgen("""
> + qov = qmp_output_visitor_new();
> + g_assert(qov);
> +
> + v = qmp_output_get_visitor(qov);
> + g_assert(v);
> +
> + /* Fake visit, as if all member are under a structure */
> + visit_start_struct(v, NULL, "", "%(event_name)s", 0, &local_err);
> + if (error_is_set(&local_err)) {
> + goto clean;
> + }
> +
> +""",
> + event_name = event_name)
> +
> + for argname, argentry, optional, structured in parse_args(params):
> + if structured:
> + sys.stderr.write("Nested structure define in event is not "
> + "supported now, event '%s', argname '%s'\n" %
> + (event_name, argname))
> + sys.exit(1)
> +
> + if optional:
> + ret += mcgen("""
> + if (has_%(var)s) {
> +""",
> + var = c_var(argname))
> + push_indent()
> +
> + if argentry == "str":
> + var_type = "(char **)"
> + else:
> + var_type = ""
> +
> + ret += mcgen("""
> + visit_type_%(type)s(v, %(var_type)s&%(var)s, "%(name)s", &local_err);
> + if (error_is_set(&local_err)) {
> + goto clean;
> + }
> +""",
> + var_type = var_type,
> + var = c_var(argname),
> + type = type_name(argentry),
> + name = argname)
> +
> + if optional:
> + pop_indent()
> + ret += mcgen("""
> + }
> +""")
> +
> + ret += mcgen("""
> +
> + visit_end_struct(v, &local_err);
> + if (error_is_set(&local_err)) {
> + goto clean;
> + }
> +
> + obj = qmp_output_get_qobject(qov);
> + g_assert(obj != NULL);
> +
> + qdict_put_obj(qmp, "data", obj);
> +""")
> +
> + # step 4: call qmp event api
> + ret += mcgen("""
> + emit(%(event_enum_value)s, qmp, &local_err);
> +
> +""",
> + event_enum_value = event_enum_value)
> +
> + # step 5: clean up
> + if params:
> + ret += mcgen("""
> + clean:
> + qmp_output_visitor_cleanup(qov);
> +""")
> + ret += mcgen("""
> + error_propagate(errp, local_err);
> + QDECREF(qmp);
> +}
> +""")
> +
> + return ret
> +
> +
> +# Following are the functions that generate an enum type for all defined
> +# events, similar with qapi-types.py. Here we already have enum name and
> +# values which is generated before and recorded in event_enum_*. It also
> +# walk around the issue that "import qapi-types" can't work.
> +
> +def generate_event_enum_decl(event_enum_name, event_enum_values):
> + lookup_decl = mcgen('''
> +
> +extern const char *%(event_enum_name)s_lookup[];
> +''',
> + event_enum_name = event_enum_name)
> +
> + enum_decl = mcgen('''
> +typedef enum %(event_enum_name)s
> +{
> +''',
> + event_enum_name = event_enum_name)
> +
> + # append automatically generated _MAX value
> + enum_max_value = generate_enum_full_value_string(event_enum_name, "MAX")
> + enum_values = event_enum_values + [ enum_max_value ]
> +
> + i = 0
> + for value in enum_values:
> + enum_decl += mcgen('''
> + %(value)s = %(i)d,
> +''',
> + value = value,
> + i = i)
> + i += 1
> +
> + enum_decl += mcgen('''
> +} %(event_enum_name)s;
> +''',
> + event_enum_name = event_enum_name)
> +
> + return lookup_decl + enum_decl
> +
> +def generate_event_enum_lookup(event_enum_name, event_enum_strings):
> + ret = mcgen('''
> +
> +const char *%(event_enum_name)s_lookup[] = {
> +''',
> + event_enum_name = event_enum_name)
> +
> + i = 0
> + for string in event_enum_strings:
> + ret += mcgen('''
> + "%(string)s",
> +''',
> + string = string)
> +
> + ret += mcgen('''
> + NULL,
> +};
> +''')
> + return ret
> +
> +
> +# Following are the functions that generate event behavior control functions.
> +# Those functions are put here in the qapi-event.c, since it need to include
> +# qapi-event.h for the event enum type declaration, put them in other file
> +# requiring other file include qapi-event.h, causing a cross including. For
> +# example: if we have qmp-event.c and qmp-event.h, then qmp-event.c
> +# ->qmp-event.h->qapi-event.h, qapi-event.c->qmp-event.h. Another problem
> +# follow: test-qapi-event.c will meet event enum double declaration since it
> +# include both test-qapi-event.h and qmp-event.h. One solution is putting event
> +# enum declaration in a separate header file, but then qmp-event.h need to
> +# include test-qapi-event.h or qapi-event.h on compile time condition. So the
> +# easist way is, just generate them here.
> +
> +def generate_event_behavior_control_decl(event_enum_name):
> + ret = mcgen('''
> +
> +typedef void (*QAPIEventFuncEmit)(%(event_enum_name)s ev,
> + QDict *dict,
> + Error **errp);
> +
> +void qapi_event_set_func_emit(QAPIEventFuncEmit emit);
> +
> +QAPIEventFuncEmit qapi_event_get_func_emit(void);
> +''',
> + event_enum_name = event_enum_name)
> + return ret;
> +
> +def generate_event_behavior_control_implement():
> + ret = mcgen('''
> +
> +typedef struct QAPIEventFunctions {
> + QAPIEventFuncEmit emit;
> +} QAPIEventFunctions;
> +
> +QAPIEventFunctions qapi_event_functions;
> +
> +void qapi_event_set_func_emit(QAPIEventFuncEmit emit)
> +{
> + qapi_event_functions.emit = emit;
> +}
> +
> +QAPIEventFuncEmit qapi_event_get_func_emit(void)
> +{
> + return qapi_event_functions.emit;
> +}
> +''')
> + return ret
> +
> +
> +# Start the real job
> +
> +try:
> + opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
> + ["source", "header", "builtins", "prefix=",
> + "output-dir="])
> +except getopt.GetoptError, err:
> + print str(err)
> + sys.exit(1)
> +
> +output_dir = ""
> +prefix = ""
> +c_file = 'qapi-event.c'
> +h_file = 'qapi-event.h'
> +
> +do_c = False
> +do_h = False
> +do_builtins = False
> +
> +for o, a in opts:
> + if o in ("-p", "--prefix"):
> + prefix = a
> + elif o in ("-o", "--output-dir"):
> + output_dir = a + "/"
> + elif o in ("-c", "--source"):
> + do_c = True
> + elif o in ("-h", "--header"):
> + do_h = True
> + elif o in ("-b", "--builtins"):
> + do_builtins = True
> +
> +if not do_c and not do_h:
> + do_c = True
> + do_h = True
> +
> +c_file = output_dir + prefix + c_file
> +h_file = output_dir + prefix + h_file
> +
> +try:
> + os.makedirs(output_dir)
> +except os.error, e:
> + if e.errno != errno.EEXIST:
> + raise
> +
> +def maybe_open(really, name, opt):
> + if really:
> + return open(name, opt)
> + else:
> + import StringIO
> + return StringIO.StringIO()
> +
> +fdef = maybe_open(do_c, c_file, 'w')
> +fdecl = maybe_open(do_h, h_file, 'w')
> +
> +fdef.write(mcgen('''
> +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
> +
> +/*
> + * schema-defined QAPI event functions
> + *
> + * Copyright IBM, Corp. 2014
> + *
> + * Authors:
> + * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> + *
> + * This work is licensed under the terms of the GNU GPLv2+ or later.
> + * See the COPYING.LIB file in the top-level directory.
> + *
> + */
> +
> +#include "qemu-common.h"
> +#include "%(header)s"
> +#include "%(prefix)sqapi-visit.h"
> +#include "qapi/qmp-output-visitor.h"
> +#include "qapi/qmp-event.h"
> +
> +''',
> + prefix=prefix, header=basename(h_file)))
> +
> +fdecl.write(mcgen('''
> +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
> +
> +/*
> + * schema-defined QAPI event function
> + *
> + * Copyright IBM, Corp. 2014
> + *
> + * Authors:
> + * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> + *
> + * This work is licensed under the terms of the GNU GPLv2+ or later.
> + * See the COPYING.LIB file in the top-level directory.
> + *
> + */
> +
> +#ifndef %(guard)s
> +#define %(guard)s
> +
> +#include "qapi/error.h"
> +#include "qapi/qmp/qdict.h"
> +#include "%(prefix)sqapi-types.h"
> +
> +''',
> + prefix=prefix, guard=guardname(h_file)))
> +
> +exprs = parse_schema(sys.stdin)
> +
> +event_enum_name = "QAPIEvent"
> +event_enum_values = []
> +event_enum_strings = []
> +
> +for expr in exprs:
> + if expr.has_key('event'):
> + event_name = expr['event']
> + params = expr.get('data')
> + if params and len(params) == 0:
> + params = None
> +
> + api_name = _generate_event_api_name(event_name, params)
> + ret = generate_event_declaration(api_name)
> + fdecl.write(ret)
> +
> + # We need an enum value per event
> + event_enum_value = generate_enum_full_value_string(event_enum_name,
> + event_name)
> + ret = generate_event_implement(api_name, event_name, params)
> + fdef.write(ret)
> +
> + # Record it, and generate enum later
> + event_enum_values.append(event_enum_value)
> + event_enum_strings.append(event_name)
> +
> +ret = generate_event_enum_decl(event_enum_name, event_enum_values)
> +fdecl.write(ret)
> +ret = generate_event_enum_lookup(event_enum_name, event_enum_strings)
> +fdef.write(ret)
> +ret = generate_event_behavior_control_decl(event_enum_name)
> +fdecl.write(ret)
> +ret = generate_event_behavior_control_implement()
> +fdef.write(ret)
> +
> +fdecl.write('''
> +#endif
> +''')
> +
> +fdecl.flush()
> +fdecl.close()
> +
> +fdef.flush()
> +fdef.close()
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-01-06 23:10 ` Luiz Capitulino
@ 2014-01-06 23:17 ` Luiz Capitulino
2014-01-07 3:24 ` Wenchao Xia
2014-01-07 2:53 ` Wenchao Xia
1 sibling, 1 reply; 27+ messages in thread
From: Luiz Capitulino @ 2014-01-06 23:17 UTC (permalink / raw)
To: Luiz Capitulino; +Cc: armbru, mreitz, Wenchao Xia, qemu-devel
[Pressed enter too soon, forgot two things]
On Mon, 6 Jan 2014 18:10:04 -0500
Luiz Capitulino <lcapitulino@redhat.com> wrote:
> On Fri, 3 Jan 2014 07:10:32 +0800
> Wenchao Xia <xiawenc@linux.vnet.ibm.com> wrote:
>
> > qapi-event.py will parse the schema and generate qapi-event.c, then
> > the API in qapi-event.c can be used to handle event in qemu code.
> > All API have prefix "qapi_event", all types have prefix "QAPIEvent".
> > Examples can be found in following patches.
> >
> > The script mainly include three parts: generate API for each event
> > define, generate an enum type for all defined event, generate behavior
> > control functions.
> >
> > Since in some case the real emit behavior may change, for example,
> > qemu-img would not send a event, a callback layer is added to
> > control the behavior. As a result, the stubs at compile time
> > can be saved, the binding of block layer code and monitor code
> > will become looser.
> >
> > Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> > ---
> > Makefile | 9 +-
> > Makefile.objs | 2 +-
> > scripts/qapi-event.py | 432 +++++++++++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 439 insertions(+), 4 deletions(-)
> > create mode 100644 scripts/qapi-event.py
> >
> > diff --git a/Makefile b/Makefile
> > index bdff4e4..fa59765 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -45,8 +45,8 @@ endif
> > endif
> >
> > GENERATED_HEADERS = config-host.h qemu-options.def
> > -GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
> > -GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
> > +GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
> > +GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
> >
> > GENERATED_HEADERS += trace/generated-events.h
> > GENERATED_SOURCES += trace/generated-events.c
> > @@ -185,7 +185,7 @@ Makefile: $(version-obj-y) $(version-lobj-y)
> > # Build libraries
> >
> > libqemustub.a: $(stub-obj-y)
> > -libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o
> > +libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o qapi-event.o
> >
> > ######################################################################
> >
> > @@ -226,6 +226,9 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
> > qapi-visit.c qapi-visit.h :\
> > $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
> > $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." -b < $<, " GEN $@")
> > +qapi-event.c qapi-event.h :\
> > +$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
> > + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py $(gen-out-type) -o "." -b < $<, " GEN $@")
> > qmp-commands.h qmp-marshal.c :\
> > $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
> > $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@")
> > diff --git a/Makefile.objs b/Makefile.objs
> > index 2b6c1fe..33f5950 100644
> > --- a/Makefile.objs
> > +++ b/Makefile.objs
> > @@ -12,7 +12,7 @@ block-obj-y += main-loop.o iohandler.o qemu-timer.o
> > block-obj-$(CONFIG_POSIX) += aio-posix.o
> > block-obj-$(CONFIG_WIN32) += aio-win32.o
> > block-obj-y += block/
> > -block-obj-y += qapi-types.o qapi-visit.o
> > +block-obj-y += qapi-types.o qapi-visit.o qapi-event.o
> > block-obj-y += qemu-io-cmds.o
> >
> > block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
> > diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
> > new file mode 100644
> > index 0000000..7526366
> > --- /dev/null
> > +++ b/scripts/qapi-event.py
> > @@ -0,0 +1,432 @@
> > +#
> > +# QAPI event generator
> > +#
> > +# Copyright IBM, Corp. 2014
> > +#
> > +# Authors:
> > +# Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> > +#
> > +# This work is licensed under the terms of the GNU GPLv2+ or later.
> > +# See the COPYING.LIB file in the top-level directory.
> > +
> > +from ordereddict import OrderedDict
> > +from qapi import *
> > +import sys
> > +import os
> > +import getopt
> > +import errno
> > +
> > +def _generate_event_api_name(event_name, params):
>
> Why the underline? And, what you generate is a function declaration...
>
> > + api_name = "void qapi_event_send_%s(" % c_fun(event_name).lower();
> > + l = len(api_name)
> > +
> > + if params:
> > + for argname, argentry, optional, structured in parse_args(params):
> > + if structured:
> > + sys.stderr.write("Nested structure define in event is not "
> > + "supported now, event '%s', argname '%s'\n" %
> > + (event_name, argname))
> > + sys.exit(1)
> > + continue
> > +
> > + if optional:
> > + api_name += "bool has_%s,\n" % c_var(argname)
> > + api_name += "".ljust(l)
> > +
> > + if argentry == "str":
> > + api_name += "const "
> > + api_name += "%s %s,\n" % (c_type(argentry), c_var(argname))
> > + api_name += "".ljust(l)
> > +
> > + api_name += "Error **errp)"
> > + return api_name;
> > +
> > +
> > +# Following are the core functions that transate user input into a qdict going
>
> s/transate/translate
>
> Although the comment doesn't make much sense to me.
>
> > +# to be emitted in the wire.
> > +
> > +def generate_event_declaration(api_name):
> > + return mcgen('''
> > +
> > +%(api_name)s;
> > +''',
> > + api_name = api_name)
> > +
> > +def generate_event_implement(api_name, event_name, params):
>
> I wonder if it would be clearer to to generate the declaration here.
>
> > + # step 1: declare and variables
> > + ret = mcgen("""
> > +
> > +%(api_name)s
> > +{
> > + QDict *qmp;
> > + Error *local_err = NULL;
> > + QAPIEventFuncEmit emit;
> > +""",
> > + api_name = api_name)
> > +
> > + if params:
> > + ret += mcgen("""
> > + QmpOutputVisitor *qov;
> > + Visitor *v;
> > + QObject *obj;
> > +
> > +""")
> > +
> > + # step 2: check emit function, create a dict
> > + ret += mcgen("""
> > + emit = qapi_event_get_func_emit();
> > + if (!emit) {
> > + return;
> > + }
> > +
> > + qmp = qmp_event_build_dict("%(event_name)s");
> > +
> > +""",
> > + event_name = event_name)
> > +
> > + # step 3: visit the params if params != None
> > + if params:
> > + ret += mcgen("""
> > + qov = qmp_output_visitor_new();
> > + g_assert(qov);
> > +
> > + v = qmp_output_get_visitor(qov);
> > + g_assert(v);
> > +
> > + /* Fake visit, as if all member are under a structure */
> > + visit_start_struct(v, NULL, "", "%(event_name)s", 0, &local_err);
> > + if (error_is_set(&local_err)) {
> > + goto clean;
> > + }
> > +
> > +""",
> > + event_name = event_name)
> > +
> > + for argname, argentry, optional, structured in parse_args(params):
> > + if structured:
> > + sys.stderr.write("Nested structure define in event is not "
> > + "supported now, event '%s', argname '%s'\n" %
> > + (event_name, argname))
> > + sys.exit(1)
> > +
> > + if optional:
> > + ret += mcgen("""
> > + if (has_%(var)s) {
> > +""",
> > + var = c_var(argname))
> > + push_indent()
> > +
> > + if argentry == "str":
> > + var_type = "(char **)"
> > + else:
> > + var_type = ""
> > +
> > + ret += mcgen("""
> > + visit_type_%(type)s(v, %(var_type)s&%(var)s, "%(name)s", &local_err);
> > + if (error_is_set(&local_err)) {
> > + goto clean;
> > + }
> > +""",
> > + var_type = var_type,
> > + var = c_var(argname),
> > + type = type_name(argentry),
> > + name = argname)
> > +
> > + if optional:
> > + pop_indent()
> > + ret += mcgen("""
> > + }
> > +""")
> > +
> > + ret += mcgen("""
> > +
> > + visit_end_struct(v, &local_err);
> > + if (error_is_set(&local_err)) {
> > + goto clean;
> > + }
> > +
> > + obj = qmp_output_get_qobject(qov);
> > + g_assert(obj != NULL);
> > +
> > + qdict_put_obj(qmp, "data", obj);
> > +""")
> > +
> > + # step 4: call qmp event api
> > + ret += mcgen("""
> > + emit(%(event_enum_value)s, qmp, &local_err);
> > +
> > +""",
> > + event_enum_value = event_enum_value)
> > +
> > + # step 5: clean up
> > + if params:
> > + ret += mcgen("""
> > + clean:
> > + qmp_output_visitor_cleanup(qov);
> > +""")
> > + ret += mcgen("""
> > + error_propagate(errp, local_err);
> > + QDECREF(qmp);
> > +}
> > +""")
> > +
> > + return ret
> > +
> > +
> > +# Following are the functions that generate an enum type for all defined
> > +# events, similar with qapi-types.py. Here we already have enum name and
> > +# values which is generated before and recorded in event_enum_*. It also
> > +# walk around the issue that "import qapi-types" can't work.
> > +
> > +def generate_event_enum_decl(event_enum_name, event_enum_values):
> > + lookup_decl = mcgen('''
> > +
> > +extern const char *%(event_enum_name)s_lookup[];
> > +''',
> > + event_enum_name = event_enum_name)
> > +
> > + enum_decl = mcgen('''
> > +typedef enum %(event_enum_name)s
> > +{
> > +''',
> > + event_enum_name = event_enum_name)
> > +
> > + # append automatically generated _MAX value
> > + enum_max_value = generate_enum_full_value_string(event_enum_name, "MAX")
> > + enum_values = event_enum_values + [ enum_max_value ]
> > +
> > + i = 0
> > + for value in enum_values:
> > + enum_decl += mcgen('''
> > + %(value)s = %(i)d,
> > +''',
> > + value = value,
> > + i = i)
> > + i += 1
> > +
> > + enum_decl += mcgen('''
> > +} %(event_enum_name)s;
> > +''',
> > + event_enum_name = event_enum_name)
> > +
> > + return lookup_decl + enum_decl
> > +
> > +def generate_event_enum_lookup(event_enum_name, event_enum_strings):
> > + ret = mcgen('''
> > +
> > +const char *%(event_enum_name)s_lookup[] = {
> > +''',
> > + event_enum_name = event_enum_name)
> > +
> > + i = 0
> > + for string in event_enum_strings:
> > + ret += mcgen('''
> > + "%(string)s",
> > +''',
> > + string = string)
> > +
> > + ret += mcgen('''
> > + NULL,
> > +};
> > +''')
> > + return ret
> > +
> > +
> > +# Following are the functions that generate event behavior control functions.
> > +# Those functions are put here in the qapi-event.c, since it need to include
> > +# qapi-event.h for the event enum type declaration, put them in other file
> > +# requiring other file include qapi-event.h, causing a cross including. For
> > +# example: if we have qmp-event.c and qmp-event.h, then qmp-event.c
> > +# ->qmp-event.h->qapi-event.h, qapi-event.c->qmp-event.h. Another problem
> > +# follow: test-qapi-event.c will meet event enum double declaration since it
> > +# include both test-qapi-event.h and qmp-event.h. One solution is putting event
> > +# enum declaration in a separate header file, but then qmp-event.h need to
> > +# include test-qapi-event.h or qapi-event.h on compile time condition. So the
> > +# easist way is, just generate them here.
> > +
> > +def generate_event_behavior_control_decl(event_enum_name):
> > + ret = mcgen('''
> > +
> > +typedef void (*QAPIEventFuncEmit)(%(event_enum_name)s ev,
> > + QDict *dict,
> > + Error **errp);
Why does the emit function need 'ev'? Doesn't 'dict' contain all the
info it needs? Also, it's better to rename it to 'event' or 'qmp_event'.
> > +
> > +void qapi_event_set_func_emit(QAPIEventFuncEmit emit);
> > +
> > +QAPIEventFuncEmit qapi_event_get_func_emit(void);
> > +''',
> > + event_enum_name = event_enum_name)
> > + return ret;
> > +
> > +def generate_event_behavior_control_implement():
> > + ret = mcgen('''
> > +
> > +typedef struct QAPIEventFunctions {
> > + QAPIEventFuncEmit emit;
> > +} QAPIEventFunctions;
> > +
> > +QAPIEventFunctions qapi_event_functions;
> > +
> > +void qapi_event_set_func_emit(QAPIEventFuncEmit emit)
> > +{
> > + qapi_event_functions.emit = emit;
> > +}
If this function and the typedefs don't change, I think they shouldn't
be generated.
> > +
> > +QAPIEventFuncEmit qapi_event_get_func_emit(void)
> > +{
> > + return qapi_event_functions.emit;
> > +}
> > +''')
> > + return ret
> > +
> > +
> > +# Start the real job
> > +
> > +try:
> > + opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
> > + ["source", "header", "builtins", "prefix=",
> > + "output-dir="])
> > +except getopt.GetoptError, err:
> > + print str(err)
> > + sys.exit(1)
> > +
> > +output_dir = ""
> > +prefix = ""
> > +c_file = 'qapi-event.c'
> > +h_file = 'qapi-event.h'
> > +
> > +do_c = False
> > +do_h = False
> > +do_builtins = False
> > +
> > +for o, a in opts:
> > + if o in ("-p", "--prefix"):
> > + prefix = a
> > + elif o in ("-o", "--output-dir"):
> > + output_dir = a + "/"
> > + elif o in ("-c", "--source"):
> > + do_c = True
> > + elif o in ("-h", "--header"):
> > + do_h = True
> > + elif o in ("-b", "--builtins"):
> > + do_builtins = True
> > +
> > +if not do_c and not do_h:
> > + do_c = True
> > + do_h = True
> > +
> > +c_file = output_dir + prefix + c_file
> > +h_file = output_dir + prefix + h_file
> > +
> > +try:
> > + os.makedirs(output_dir)
> > +except os.error, e:
> > + if e.errno != errno.EEXIST:
> > + raise
> > +
> > +def maybe_open(really, name, opt):
> > + if really:
> > + return open(name, opt)
> > + else:
> > + import StringIO
> > + return StringIO.StringIO()
> > +
> > +fdef = maybe_open(do_c, c_file, 'w')
> > +fdecl = maybe_open(do_h, h_file, 'w')
> > +
> > +fdef.write(mcgen('''
> > +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
> > +
> > +/*
> > + * schema-defined QAPI event functions
> > + *
> > + * Copyright IBM, Corp. 2014
> > + *
> > + * Authors:
> > + * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> > + *
> > + * This work is licensed under the terms of the GNU GPLv2+ or later.
> > + * See the COPYING.LIB file in the top-level directory.
> > + *
> > + */
> > +
> > +#include "qemu-common.h"
> > +#include "%(header)s"
> > +#include "%(prefix)sqapi-visit.h"
> > +#include "qapi/qmp-output-visitor.h"
> > +#include "qapi/qmp-event.h"
> > +
> > +''',
> > + prefix=prefix, header=basename(h_file)))
> > +
> > +fdecl.write(mcgen('''
> > +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
> > +
> > +/*
> > + * schema-defined QAPI event function
> > + *
> > + * Copyright IBM, Corp. 2014
> > + *
> > + * Authors:
> > + * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> > + *
> > + * This work is licensed under the terms of the GNU GPLv2+ or later.
> > + * See the COPYING.LIB file in the top-level directory.
> > + *
> > + */
> > +
> > +#ifndef %(guard)s
> > +#define %(guard)s
> > +
> > +#include "qapi/error.h"
> > +#include "qapi/qmp/qdict.h"
> > +#include "%(prefix)sqapi-types.h"
> > +
> > +''',
> > + prefix=prefix, guard=guardname(h_file)))
> > +
> > +exprs = parse_schema(sys.stdin)
> > +
> > +event_enum_name = "QAPIEvent"
> > +event_enum_values = []
> > +event_enum_strings = []
> > +
> > +for expr in exprs:
> > + if expr.has_key('event'):
> > + event_name = expr['event']
> > + params = expr.get('data')
> > + if params and len(params) == 0:
> > + params = None
> > +
> > + api_name = _generate_event_api_name(event_name, params)
> > + ret = generate_event_declaration(api_name)
> > + fdecl.write(ret)
> > +
> > + # We need an enum value per event
> > + event_enum_value = generate_enum_full_value_string(event_enum_name,
> > + event_name)
> > + ret = generate_event_implement(api_name, event_name, params)
> > + fdef.write(ret)
> > +
> > + # Record it, and generate enum later
> > + event_enum_values.append(event_enum_value)
> > + event_enum_strings.append(event_name)
> > +
> > +ret = generate_event_enum_decl(event_enum_name, event_enum_values)
> > +fdecl.write(ret)
> > +ret = generate_event_enum_lookup(event_enum_name, event_enum_strings)
> > +fdef.write(ret)
> > +ret = generate_event_behavior_control_decl(event_enum_name)
> > +fdecl.write(ret)
> > +ret = generate_event_behavior_control_implement()
> > +fdef.write(ret)
> > +
> > +fdecl.write('''
> > +#endif
> > +''')
> > +
> > +fdecl.flush()
> > +fdecl.close()
> > +
> > +fdef.flush()
> > +fdef.close()
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema
2014-01-02 23:10 [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema Wenchao Xia
` (4 preceding siblings ...)
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 5/5] qapi event: convert RTC_CHANGE Wenchao Xia
@ 2014-01-06 23:18 ` Luiz Capitulino
2014-03-06 18:14 ` Eric Blake
5 siblings, 1 reply; 27+ messages in thread
From: Luiz Capitulino @ 2014-01-06 23:18 UTC (permalink / raw)
To: Wenchao Xia; +Cc: mdroth, mreitz, qemu-devel, armbru
On Fri, 3 Jan 2014 07:10:29 +0800
Wenchao Xia <xiawenc@linux.vnet.ibm.com> wrote:
> This series add support for tag/keyword 'event' in qapi-schema.
> A new file was created to store some helper functions in patch 2, patch 4 is
> the test case, patch 5 is a convert example.
>
> The implemention is done by generate API and a batch of parameters for each
> event define, it doesn't generate a struture and visit function in the
> background for every event, so it doesn't support nested structure in the
> define to avoid trouble. A callback layer is added to control the behavior.
> More detail can be found in patch 3's message and incode comments.
The general approach seems good to me. Would be nice to get another
reviewer though, maybe Eric and/or Michael.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 2/5] qapi: add event helper functions
2014-01-06 22:23 ` Luiz Capitulino
@ 2014-01-07 2:28 ` Wenchao Xia
2014-03-06 18:26 ` Eric Blake
1 sibling, 0 replies; 27+ messages in thread
From: Wenchao Xia @ 2014-01-07 2:28 UTC (permalink / raw)
To: Luiz Capitulino; +Cc: mreitz, qemu-devel, armbru
于 2014/1/7 6:23, Luiz Capitulino 写道:
> On Fri, 3 Jan 2014 07:10:31 +0800
> Wenchao Xia <xiawenc@linux.vnet.ibm.com> wrote:
>
>> This file hold some functions that do not need to be generated.
>>
>> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
>> ---
>> include/qapi/qmp-event.h | 22 ++++++++++++++++++
>> qapi/Makefile.objs | 1 +
>> qapi/qmp-event.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 79 insertions(+), 0 deletions(-)
>> create mode 100644 include/qapi/qmp-event.h
>> create mode 100644 qapi/qmp-event.c
>>
>> diff --git a/include/qapi/qmp-event.h b/include/qapi/qmp-event.h
>> new file mode 100644
>> index 0000000..2baf093
>> --- /dev/null
>> +++ b/include/qapi/qmp-event.h
>> @@ -0,0 +1,22 @@
>> +/*
>> + * QMP Event related
>> + *
>> + * Copyright IBM, Corp. 2014
>> + *
>> + * Authors:
>> + * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
>> + *
>> + * This work is licensed under the terms of the GNU GPLv2+ or later.
>> + * See the COPYING.LIB file in the top-level directory.
>> + *
>> + */
>> +
>> +#ifndef QMP_EVENT_H
>> +#define QMP_EVENT_H
>> +
>> +#include "qapi/error.h"
>> +#include "qapi/qmp/qdict.h"
>> +
>> +QDict *qmp_event_build_dict(const char *event_name);
>> +
>> +#endif
>> diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
>> index 1f9c973..d14b769 100644
>> --- a/qapi/Makefile.objs
>> +++ b/qapi/Makefile.objs
>> @@ -3,3 +3,4 @@ util-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
>> util-obj-y += string-input-visitor.o string-output-visitor.o
>>
>> util-obj-y += opts-visitor.o
>> +util-obj-y += qmp-event.o
>> diff --git a/qapi/qmp-event.c b/qapi/qmp-event.c
>> new file mode 100644
>> index 0000000..dc81ec2
>> --- /dev/null
>> +++ b/qapi/qmp-event.c
>> @@ -0,0 +1,56 @@
>> +/*
>> + * QMP Event related
>> + *
>> + * Copyright IBM, Corp. 2014
>> + *
>> + * Authors:
>> + * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
>> + *
>> + * This work is licensed under the terms of the GNU GPLv2+ or later.
>> + * See the COPYING.LIB file in the top-level directory.
>> + *
>> + */
>> +
>> +#include <inttypes.h>
>> +
>> +#include "qemu-common.h"
>> +#include "qapi/qmp-event.h"
>> +#include "qapi/qmp/qstring.h"
>> +#include "qapi/qmp/qjson.h"
>> +
>> +#ifdef _WIN32
>> +#include "sysemu/os-win32.h"
>> +#endif
>> +
>> +#ifdef CONFIG_POSIX
>> +#include "sysemu/os-posix.h"
>> +#endif
>> +
>> +static void timestamp_put(QDict *qdict)
>> +{
>> + int err;
>> + QObject *obj;
>> + qemu_timeval tv;
>> +
>> + err = qemu_gettimeofday(&tv);
>> + if (err < 0) {
>> + return;
>> + }
>
> Hmm, I see this has always existed (and I guess I did it myself), but it's
> not quite right. Sending an event w/o time info wouldn't be complaint to
> the protocol spec. It's a good idea to fix this now. We have three options:
>
> 1. abort()
>
> 2. Skip sending the event altogether
>
> 3. Add a bogus time value (say seconds=0 and microseconds=0)
>
> I don't know what's best, but I guess I'd do item 3. Although I wonder
> if zero is any better then no info at all (it's certainly complaint, but
> not a valid info). Maybe skip the event then?
>
I think user want a way, to know error happens. If it is
skepted, then we should report it in stderr or a special message in
monitor. In my opinion, sending an event would be the easist way.
We can set time to zero and doc "timestamp == 0 means failure in
getting host time", and this avoid impacting existing user who always
seeking key "timestamp".
>
>> +
>> + obj = qobject_from_jsonf("{ 'seconds': %" PRId64 ", "
>> + "'microseconds': %" PRId64 " }",
>> + (int64_t) tv.tv_sec, (int64_t) tv.tv_usec);
>> + qdict_put_obj(qdict, "timestamp", obj);
>> +}
>> +
>> +/*
>> + * Build a QDict, then fill event name and time stamp, caller should free the
>> + * QDict after usage.
>> + */
>> +QDict *qmp_event_build_dict(const char *event_name)
>> +{
>> + QDict *dict = qdict_new();
>> + qdict_put(dict, "event", qstring_from_str(event_name));
>> + timestamp_put(dict);
>> + return dict;
>> +}
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-01-06 23:10 ` Luiz Capitulino
2014-01-06 23:17 ` Luiz Capitulino
@ 2014-01-07 2:53 ` Wenchao Xia
1 sibling, 0 replies; 27+ messages in thread
From: Wenchao Xia @ 2014-01-07 2:53 UTC (permalink / raw)
To: Luiz Capitulino; +Cc: mreitz, qemu-devel, armbru
>> diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
>> new file mode 100644
>> index 0000000..7526366
>> --- /dev/null
>> +++ b/scripts/qapi-event.py
>> @@ -0,0 +1,432 @@
>> +#
>> +# QAPI event generator
>> +#
>> +# Copyright IBM, Corp. 2014
>> +#
>> +# Authors:
>> +# Wenchao Xia <xiawenc@linux.vnet.ibm.com>
>> +#
>> +# This work is licensed under the terms of the GNU GPLv2+ or later.
>> +# See the COPYING.LIB file in the top-level directory.
>> +
>> +from ordereddict import OrderedDict
>> +from qapi import *
>> +import sys
>> +import os
>> +import getopt
>> +import errno
>> +
>> +def _generate_event_api_name(event_name, params):
>
> Why the underline? And, what you generate is a function declaration...
>
I want to tip it is not a public API. It is generating API name,
missing ";" for declaration, implement may want it without ";". :)
>> + api_name = "void qapi_event_send_%s(" % c_fun(event_name).lower();
>> + l = len(api_name)
>> +
>> + if params:
>> + for argname, argentry, optional, structured in parse_args(params):
>> + if structured:
>> + sys.stderr.write("Nested structure define in event is not "
>> + "supported now, event '%s', argname '%s'\n" %
>> + (event_name, argname))
>> + sys.exit(1)
>> + continue
>> +
>> + if optional:
>> + api_name += "bool has_%s,\n" % c_var(argname)
>> + api_name += "".ljust(l)
>> +
>> + if argentry == "str":
>> + api_name += "const "
>> + api_name += "%s %s,\n" % (c_type(argentry), c_var(argname))
>> + api_name += "".ljust(l)
>> +
>> + api_name += "Error **errp)"
>> + return api_name;
>> +
>> +
>> +# Following are the core functions that transate user input into a qdict going
>
> s/transate/translate
>
> Although the comment doesn't make much sense to me.
>
OK, let me improve.
>> +# to be emitted in the wire.
>> +
>> +def generate_event_declaration(api_name):
>> + return mcgen('''
>> +
>> +%(api_name)s;
>> +''',
>> + api_name = api_name)
>> +
>> +def generate_event_implement(api_name, event_name, params):
>
> I wonder if it would be clearer to to generate the declaration here.
>
I think so, but a little slower at compile time. I use api_name to
avoid call _generate_event_api_name() twice. I am not sure which
way is better.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-01-06 23:17 ` Luiz Capitulino
@ 2014-01-07 3:24 ` Wenchao Xia
2014-02-14 3:26 ` Wenchao Xia
0 siblings, 1 reply; 27+ messages in thread
From: Wenchao Xia @ 2014-01-07 3:24 UTC (permalink / raw)
To: Luiz Capitulino; +Cc: mreitz, qemu-devel, armbru
>>> +
>>> +
>>> +# Following are the functions that generate event behavior control functions.
>>> +# Those functions are put here in the qapi-event.c, since it need to include
>>> +# qapi-event.h for the event enum type declaration, put them in other file
>>> +# requiring other file include qapi-event.h, causing a cross including. For
>>> +# example: if we have qmp-event.c and qmp-event.h, then qmp-event.c
>>> +# ->qmp-event.h->qapi-event.h, qapi-event.c->qmp-event.h. Another problem
>>> +# follow: test-qapi-event.c will meet event enum double declaration since it
>>> +# include both test-qapi-event.h and qmp-event.h. One solution is putting event
>>> +# enum declaration in a separate header file, but then qmp-event.h need to
>>> +# include test-qapi-event.h or qapi-event.h on compile time condition. So the
>>> +# easist way is, just generate them here.
>>> +
>>> +def generate_event_behavior_control_decl(event_enum_name):
>>> + ret = mcgen('''
>>> +
>>> +typedef void (*QAPIEventFuncEmit)(%(event_enum_name)s ev,
>>> + QDict *dict,
>>> + Error **errp);
>
> Why does the emit function need 'ev'? Doesn't 'dict' contain all the
> info it needs? Also, it's better to rename it to 'event' or 'qmp_event'.
>
ev is for rate limit. I didn't move rate limit logic from callback to
internal, mainly because it is a generated function, which seems
too complex. And the genrated function was not moved into a separte
file mainly because the enum and including issue, see the comments
in script above.
The problem is enum is changing, so the new file include it need
to recompile, for example, test schema and qapi-schema.json may
force recompile twice, I am not sure if it is good to do
some tricks in build system.
>>> +
>>> +void qapi_event_set_func_emit(QAPIEventFuncEmit emit);
>>> +
>>> +QAPIEventFuncEmit qapi_event_get_func_emit(void);
>>> +''',
>>> + event_enum_name = event_enum_name)
>>> + return ret;
>>> +
>>> +def generate_event_behavior_control_implement():
>>> + ret = mcgen('''
>>> +
>>> +typedef struct QAPIEventFunctions {
>>> + QAPIEventFuncEmit emit;
>>> +} QAPIEventFunctions;
>>> +
>>> +QAPIEventFunctions qapi_event_functions;
>>> +
>>> +void qapi_event_set_func_emit(QAPIEventFuncEmit emit)
>>> +{
>>> + qapi_event_functions.emit = emit;
>>> +}
>
> If this function and the typedefs don't change, I think they shouldn't
> be generated.
>
>>> +
>>> +QAPIEventFuncEmit qapi_event_get_func_emit(void)
>>> +{
>>> + return qapi_event_functions.emit;
>>> +}
>>> +''')
>>> + return ret
>>> +
>>> +
>>> +# Start the real job
>>> +
>>> +try:
>>> + opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
>>> + ["source", "header", "builtins", "prefix=",
>>> + "output-dir="])
>>> +except getopt.GetoptError, err:
>>> + print str(err)
>>> + sys.exit(1)
>>> +
>>> +output_dir = ""
>>> +prefix = ""
>>> +c_file = 'qapi-event.c'
>>> +h_file = 'qapi-event.h'
>>> +
>>> +do_c = False
>>> +do_h = False
>>> +do_builtins = False
>>> +
>>> +for o, a in opts:
>>> + if o in ("-p", "--prefix"):
>>> + prefix = a
>>> + elif o in ("-o", "--output-dir"):
>>> + output_dir = a + "/"
>>> + elif o in ("-c", "--source"):
>>> + do_c = True
>>> + elif o in ("-h", "--header"):
>>> + do_h = True
>>> + elif o in ("-b", "--builtins"):
>>> + do_builtins = True
>>> +
>>> +if not do_c and not do_h:
>>> + do_c = True
>>> + do_h = True
>>> +
>>> +c_file = output_dir + prefix + c_file
>>> +h_file = output_dir + prefix + h_file
>>> +
>>> +try:
>>> + os.makedirs(output_dir)
>>> +except os.error, e:
>>> + if e.errno != errno.EEXIST:
>>> + raise
>>> +
>>> +def maybe_open(really, name, opt):
>>> + if really:
>>> + return open(name, opt)
>>> + else:
>>> + import StringIO
>>> + return StringIO.StringIO()
>>> +
>>> +fdef = maybe_open(do_c, c_file, 'w')
>>> +fdecl = maybe_open(do_h, h_file, 'w')
>>> +
>>> +fdef.write(mcgen('''
>>> +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
>>> +
>>> +/*
>>> + * schema-defined QAPI event functions
>>> + *
>>> + * Copyright IBM, Corp. 2014
>>> + *
>>> + * Authors:
>>> + * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
>>> + *
>>> + * This work is licensed under the terms of the GNU GPLv2+ or later.
>>> + * See the COPYING.LIB file in the top-level directory.
>>> + *
>>> + */
>>> +
>>> +#include "qemu-common.h"
>>> +#include "%(header)s"
>>> +#include "%(prefix)sqapi-visit.h"
>>> +#include "qapi/qmp-output-visitor.h"
>>> +#include "qapi/qmp-event.h"
>>> +
>>> +''',
>>> + prefix=prefix, header=basename(h_file)))
>>> +
>>> +fdecl.write(mcgen('''
>>> +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
>>> +
>>> +/*
>>> + * schema-defined QAPI event function
>>> + *
>>> + * Copyright IBM, Corp. 2014
>>> + *
>>> + * Authors:
>>> + * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
>>> + *
>>> + * This work is licensed under the terms of the GNU GPLv2+ or later.
>>> + * See the COPYING.LIB file in the top-level directory.
>>> + *
>>> + */
>>> +
>>> +#ifndef %(guard)s
>>> +#define %(guard)s
>>> +
>>> +#include "qapi/error.h"
>>> +#include "qapi/qmp/qdict.h"
>>> +#include "%(prefix)sqapi-types.h"
>>> +
>>> +''',
>>> + prefix=prefix, guard=guardname(h_file)))
>>> +
>>> +exprs = parse_schema(sys.stdin)
>>> +
>>> +event_enum_name = "QAPIEvent"
>>> +event_enum_values = []
>>> +event_enum_strings = []
>>> +
>>> +for expr in exprs:
>>> + if expr.has_key('event'):
>>> + event_name = expr['event']
>>> + params = expr.get('data')
>>> + if params and len(params) == 0:
>>> + params = None
>>> +
>>> + api_name = _generate_event_api_name(event_name, params)
>>> + ret = generate_event_declaration(api_name)
>>> + fdecl.write(ret)
>>> +
>>> + # We need an enum value per event
>>> + event_enum_value = generate_enum_full_value_string(event_enum_name,
>>> + event_name)
>>> + ret = generate_event_implement(api_name, event_name, params)
>>> + fdef.write(ret)
>>> +
>>> + # Record it, and generate enum later
>>> + event_enum_values.append(event_enum_value)
>>> + event_enum_strings.append(event_name)
>>> +
>>> +ret = generate_event_enum_decl(event_enum_name, event_enum_values)
>>> +fdecl.write(ret)
>>> +ret = generate_event_enum_lookup(event_enum_name, event_enum_strings)
>>> +fdef.write(ret)
>>> +ret = generate_event_behavior_control_decl(event_enum_name)
>>> +fdecl.write(ret)
>>> +ret = generate_event_behavior_control_implement()
>>> +fdef.write(ret)
>>> +
>>> +fdecl.write('''
>>> +#endif
>>> +''')
>>> +
>>> +fdecl.flush()
>>> +fdecl.close()
>>> +
>>> +fdef.flush()
>>> +fdef.close()
>>
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-01-07 3:24 ` Wenchao Xia
@ 2014-02-14 3:26 ` Wenchao Xia
0 siblings, 0 replies; 27+ messages in thread
From: Wenchao Xia @ 2014-02-14 3:26 UTC (permalink / raw)
To: Luiz Capitulino; +Cc: armbru, qemu-devel, mreitz
于 2014/1/7 11:24, Wenchao Xia 写道:
>>>> +
>>>> +
>>>> +# Following are the functions that generate event behavior control
>>>> functions.
>>>> +# Those functions are put here in the qapi-event.c, since it need
>>>> to include
>>>> +# qapi-event.h for the event enum type declaration, put them in
>>>> other file
>>>> +# requiring other file include qapi-event.h, causing a cross
>>>> including. For
>>>> +# example: if we have qmp-event.c and qmp-event.h, then qmp-event.c
>>>> +# ->qmp-event.h->qapi-event.h, qapi-event.c->qmp-event.h. Another
>>>> problem
>>>> +# follow: test-qapi-event.c will meet event enum double declaration
>>>> since it
>>>> +# include both test-qapi-event.h and qmp-event.h. One solution is
>>>> putting event
>>>> +# enum declaration in a separate header file, but then qmp-event.h
>>>> need to
>>>> +# include test-qapi-event.h or qapi-event.h on compile time
>>>> condition. So the
>>>> +# easist way is, just generate them here.
>>>> +
>>>> +def generate_event_behavior_control_decl(event_enum_name):
>>>> + ret = mcgen('''
>>>> +
>>>> +typedef void (*QAPIEventFuncEmit)(%(event_enum_name)s ev,
>>>> + QDict *dict,
>>>> + Error **errp);
>>
>> Why does the emit function need 'ev'? Doesn't 'dict' contain all the
>> info it needs? Also, it's better to rename it to 'event' or 'qmp_event'.
>>
>
> ev is for rate limit. I didn't move rate limit logic from callback to
> internal, mainly because it is a generated function, which seems
> too complex. And the genrated function was not moved into a separte
> file mainly because the enum and including issue, see the comments
> in script above.
> The problem is enum is changing, so the new file include it need
> to recompile, for example, test schema and qapi-schema.json may
> force recompile twice, I am not sure if it is good to do
> some tricks in build system.
>
I am going to respin this series after sync with upstream.
"ev" will be removed, and will try use a runtime call to solve
issue above.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema
2014-01-06 23:18 ` [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema Luiz Capitulino
@ 2014-03-06 18:14 ` Eric Blake
2014-03-06 19:58 ` Luiz Capitulino
0 siblings, 1 reply; 27+ messages in thread
From: Eric Blake @ 2014-03-06 18:14 UTC (permalink / raw)
To: Luiz Capitulino, Wenchao Xia; +Cc: mdroth, mreitz, qemu-devel, armbru
[-- Attachment #1: Type: text/plain, Size: 1096 bytes --]
On 01/06/2014 04:18 PM, Luiz Capitulino wrote:
> On Fri, 3 Jan 2014 07:10:29 +0800
> Wenchao Xia <xiawenc@linux.vnet.ibm.com> wrote:
>
>> This series add support for tag/keyword 'event' in qapi-schema.
>> A new file was created to store some helper functions in patch 2, patch 4 is
>> the test case, patch 5 is a convert example.
>>
>> The implemention is done by generate API and a batch of parameters for each
>> event define, it doesn't generate a struture and visit function in the
>> background for every event, so it doesn't support nested structure in the
>> define to avoid trouble. A callback layer is added to control the behavior.
>> More detail can be found in patch 3's message and incode comments.
>
> The general approach seems good to me. Would be nice to get another
> reviewer though, maybe Eric and/or Michael.
Just now looking at this thread. Is this still something that we want
in 2.0, or at this point are we late enough to delay to 2.1?
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 2/5] qapi: add event helper functions
2014-01-06 22:23 ` Luiz Capitulino
2014-01-07 2:28 ` Wenchao Xia
@ 2014-03-06 18:26 ` Eric Blake
1 sibling, 0 replies; 27+ messages in thread
From: Eric Blake @ 2014-03-06 18:26 UTC (permalink / raw)
To: Luiz Capitulino, Wenchao Xia; +Cc: mreitz, qemu-devel, armbru
[-- Attachment #1: Type: text/plain, Size: 1746 bytes --]
On 01/06/2014 03:23 PM, Luiz Capitulino wrote:
> On Fri, 3 Jan 2014 07:10:31 +0800
> Wenchao Xia <xiawenc@linux.vnet.ibm.com> wrote:
>
>> This file hold some functions that do not need to be generated.
>>
>> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
>> ---
>> +static void timestamp_put(QDict *qdict)
>> +{
>> + int err;
>> + QObject *obj;
>> + qemu_timeval tv;
>> +
>> + err = qemu_gettimeofday(&tv);
>> + if (err < 0) {
>> + return;
>> + }
>
> Hmm, I see this has always existed (and I guess I did it myself), but it's
> not quite right. Sending an event w/o time info wouldn't be complaint to
> the protocol spec. It's a good idea to fix this now. We have three options:
>
> 1. abort()
>
> 2. Skip sending the event altogether
>
> 3. Add a bogus time value (say seconds=0 and microseconds=0)
>
> I don't know what's best, but I guess I'd do item 3. Although I wonder
> if zero is any better then no info at all (it's certainly complaint, but
> not a valid info). Maybe skip the event then?
I have a patch pending[1] for libvirt (missed libvirt 1.2.2, but will be
in 1.2.3) that exposes raw qemu events through libvirt-qemu.so
(basically, as a debugging aid, similar to libvirt's 'virsh
qemu-monitor-command', it will add 'virsh qemu-monitor-event'). In my
implementation, I documented that seconds=-1 implies a missing timestamp
(at which point microseconds is ignored, but can be set to 0). So I'm
in favor of option 3, but with -1 rather than 0 for seconds.
[1]https://www.redhat.com/archives/libvir-list/2014-February/msg00000.html
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py Wenchao Xia
2014-01-06 23:10 ` Luiz Capitulino
@ 2014-03-06 18:49 ` Eric Blake
2014-03-19 2:38 ` Wenchao Xia
1 sibling, 1 reply; 27+ messages in thread
From: Eric Blake @ 2014-03-06 18:49 UTC (permalink / raw)
To: Wenchao Xia, qemu-devel; +Cc: mreitz, armbru, lcapitulino
[-- Attachment #1: Type: text/plain, Size: 2927 bytes --]
On 01/02/2014 04:10 PM, Wenchao Xia wrote:
> qapi-event.py will parse the schema and generate qapi-event.c, then
> the API in qapi-event.c can be used to handle event in qemu code.
> All API have prefix "qapi_event", all types have prefix "QAPIEvent".
> Examples can be found in following patches.
>
> The script mainly include three parts: generate API for each event
> define, generate an enum type for all defined event, generate behavior
s/event/events/
> control functions.
>
> Since in some case the real emit behavior may change, for example,
> qemu-img would not send a event, a callback layer is added to
> control the behavior. As a result, the stubs at compile time
> can be saved, the binding of block layer code and monitor code
> will become looser.
>
> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> ---
> Makefile | 9 +-
> Makefile.objs | 2 +-
> scripts/qapi-event.py | 432 +++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 439 insertions(+), 4 deletions(-)
> create mode 100644 scripts/qapi-event.py
In addition to Luiz' comments, you are missing documentation. At a
minimum, docs/qapi-code-gen.txt should be updated.
> +try:
> + opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
> + ["source", "header", "builtins", "prefix=",
> + "output-dir="])
> +except getopt.GetoptError, err:
> + print str(err)
> + sys.exit(1)
> +
> +output_dir = ""
> +prefix = ""
> +c_file = 'qapi-event.c'
> +h_file = 'qapi-event.h'
> +
> +do_c = False
> +do_h = False
> +do_builtins = False
> +
> +for o, a in opts:
> + if o in ("-p", "--prefix"):
> + prefix = a
> + elif o in ("-o", "--output-dir"):
> + output_dir = a + "/"
> + elif o in ("-c", "--source"):
> + do_c = True
> + elif o in ("-h", "--header"):
> + do_h = True
> + elif o in ("-b", "--builtins"):
> + do_builtins = True
You may need to rebase this on top of other patches that refactor the
qapi generators to track the input file, for improved error messages.
> +fdef.write(mcgen('''
> +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
> +
> +/*
> + * schema-defined QAPI event functions
> + *
> + * Copyright IBM, Corp. 2014
> + *
> + * Authors:
> + * Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> + *
> + * This work is licensed under the terms of the GNU GPLv2+ or later.
> + * See the COPYING.LIB file in the top-level directory.
Fix this. If these are really GPL files, then they should refer to
COPYING. If you meant LGPL for the generated files, say so (but that's
possibly at odds with other parts of your patch that put the generator
under GPL).
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema
2014-03-06 18:14 ` Eric Blake
@ 2014-03-06 19:58 ` Luiz Capitulino
2014-03-07 1:13 ` Wenchao Xia
0 siblings, 1 reply; 27+ messages in thread
From: Luiz Capitulino @ 2014-03-06 19:58 UTC (permalink / raw)
To: Eric Blake; +Cc: mdroth, armbru, mreitz, Wenchao Xia, qemu-devel
On Thu, 06 Mar 2014 11:14:01 -0700
Eric Blake <eblake@redhat.com> wrote:
> On 01/06/2014 04:18 PM, Luiz Capitulino wrote:
> > On Fri, 3 Jan 2014 07:10:29 +0800
> > Wenchao Xia <xiawenc@linux.vnet.ibm.com> wrote:
> >
> >> This series add support for tag/keyword 'event' in qapi-schema.
> >> A new file was created to store some helper functions in patch 2, patch 4 is
> >> the test case, patch 5 is a convert example.
> >>
> >> The implemention is done by generate API and a batch of parameters for each
> >> event define, it doesn't generate a struture and visit function in the
> >> background for every event, so it doesn't support nested structure in the
> >> define to avoid trouble. A callback layer is added to control the behavior.
> >> More detail can be found in patch 3's message and incode comments.
> >
> > The general approach seems good to me. Would be nice to get another
> > reviewer though, maybe Eric and/or Michael.
>
> Just now looking at this thread. Is this still something that we want
> in 2.0, or at this point are we late enough to delay to 2.1?
We could get this in if we get it posted and fully reviewed before hard freeze
(which is on March 12). But I'd suggest postponing to 2.1.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 4/5] test: add test cases for qapi event
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 4/5] test: add test cases for qapi event Wenchao Xia
@ 2014-03-06 20:05 ` Eric Blake
0 siblings, 0 replies; 27+ messages in thread
From: Eric Blake @ 2014-03-06 20:05 UTC (permalink / raw)
To: Wenchao Xia, qemu-devel; +Cc: mreitz, armbru, lcapitulino
[-- Attachment #1: Type: text/plain, Size: 1516 bytes --]
On 01/02/2014 04:10 PM, Wenchao Xia wrote:
> These cases will verify whether the expected qdict is built.
>
> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> ---
> tests/Makefile | 14 ++-
> tests/qapi-schema/qapi-schema-test.json | 12 ++
> tests/qapi-schema/qapi-schema-test.out | 10 +-
> tests/test-qmp-event.c | 254 +++++++++++++++++++++++++++++++
> 4 files changed, 285 insertions(+), 5 deletions(-)
> create mode 100644 tests/test-qmp-event.c
>
> +
> +/* This function is hooked as final emit funtion, which can verify the
> + correctness. */
> +static void event_test_emit(QAPIEvent ev, QDict *d, Error **errp)
s/funtion/function/
> +{
> + QObject *obj;
> + QDict *t;
> +
> + /* Verify that we have timestamp, then remove it to compare other field */
> + obj = qdict_get(d, "timestamp");
> + g_assert(obj);
> + t = qobject_to_qdict(obj);
> + g_assert(t);
> + obj = qdict_get(t, "seconds");
> + g_assert(obj && qobject_type(obj) == QTYPE_QINT);
> + obj = qdict_get(t, "microseconds");
> + g_assert(obj && qobject_type(obj) == QTYPE_QINT);
> +
> + qdict_del(d, "timestamp");
Should you also check that no other fields besides seconds and
microseconds were in the timestamp dictionary?
With the typo fixed,
Reviewed-by: Eric Blake <eblake@redhat.com>
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 5/5] qapi event: convert RTC_CHANGE
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 5/5] qapi event: convert RTC_CHANGE Wenchao Xia
@ 2014-03-06 20:24 ` Eric Blake
0 siblings, 0 replies; 27+ messages in thread
From: Eric Blake @ 2014-03-06 20:24 UTC (permalink / raw)
To: Wenchao Xia, qemu-devel; +Cc: mreitz, armbru, lcapitulino
[-- Attachment #1: Type: text/plain, Size: 996 bytes --]
On 01/02/2014 04:10 PM, Wenchao Xia wrote:
> This is just an example of how to use qapi event API, and it
> bypassed the event throttle queue. A complete convert should
> be first define all events in qapi-schema.json, use qapi
> event types in monitor functions, then change calller one
s/calller/caller/
> by one.
>
> Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com>
> ---
> monitor.c | 14 ++++++++++++++
> qapi-schema.json | 3 +++
> vl.c | 7 ++-----
> 3 files changed, 19 insertions(+), 5 deletions(-)
>
> +++ b/qapi-schema.json
> @@ -4247,3 +4247,6 @@
> # Since: 1.7
> ##
> { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
> +
> +{ 'event': 'RTC_CHANGE',
You'll need to add documentation before each 'event' (hint - crib the
existing documentation we already have in qmp-events.txt)
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema
2014-03-06 19:58 ` Luiz Capitulino
@ 2014-03-07 1:13 ` Wenchao Xia
0 siblings, 0 replies; 27+ messages in thread
From: Wenchao Xia @ 2014-03-07 1:13 UTC (permalink / raw)
To: Luiz Capitulino; +Cc: mdroth, armbru, qemu-devel, mreitz, Wenchao Xia
于 2014/3/7 3:58, Luiz Capitulino 写道:
> On Thu, 06 Mar 2014 11:14:01 -0700
> Eric Blake<eblake@redhat.com> wrote:
>
>> On 01/06/2014 04:18 PM, Luiz Capitulino wrote:
>>> On Fri, 3 Jan 2014 07:10:29 +0800
>>> Wenchao Xia<xiawenc@linux.vnet.ibm.com> wrote:
>>>
>>>> This series add support for tag/keyword 'event' in qapi-schema.
>>>> A new file was created to store some helper functions in patch 2, patch 4 is
>>>> the test case, patch 5 is a convert example.
>>>>
>>>> The implemention is done by generate API and a batch of parameters for each
>>>> event define, it doesn't generate a struture and visit function in the
>>>> background for every event, so it doesn't support nested structure in the
>>>> define to avoid trouble. A callback layer is added to control the behavior.
>>>> More detail can be found in patch 3's message and incode comments.
>>> The general approach seems good to me. Would be nice to get another
>>> reviewer though, maybe Eric and/or Michael.
>> Just now looking at this thread. Is this still something that we want
>> in 2.0, or at this point are we late enough to delay to 2.1?
> We could get this in if we get it posted and fully reviewed before hard freeze
> (which is on March 12). But I'd suggest postponing to 2.1.
>
There is still something not solved perfectly, I'll update later,guess
it can't catch up
with 2.0.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-03-06 18:49 ` Eric Blake
@ 2014-03-19 2:38 ` Wenchao Xia
2014-03-20 22:29 ` Eric Blake
0 siblings, 1 reply; 27+ messages in thread
From: Wenchao Xia @ 2014-03-19 2:38 UTC (permalink / raw)
To: Eric Blake; +Cc: armbru, lcapitulino, qemu-devel, mreitz
于 2014/3/7 2:49, Eric Blake 写道:
> On 01/02/2014 04:10 PM, Wenchao Xia wrote:
>> qapi-event.py will parse the schema and generate qapi-event.c, then
>> the API in qapi-event.c can be used to handle event in qemu code.
>> All API have prefix "qapi_event", all types have prefix "QAPIEvent".
>> Examples can be found in following patches.
>>
>> The script mainly include three parts: generate API for each event
>> define, generate an enum type for all defined event, generate behavior
> s/event/events/
>
>> control functions.
>>
>> Since in some case the real emit behavior may change, for example,
>> qemu-img would not send a event, a callback layer is added to
>> control the behavior. As a result, the stubs at compile time
>> can be saved, the binding of block layer code and monitor code
>> will become looser.
>>
>> Signed-off-by: Wenchao Xia<xiawenc@linux.vnet.ibm.com>
>> ---
>> Makefile | 9 +-
>> Makefile.objs | 2 +-
>> scripts/qapi-event.py | 432 +++++++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 439 insertions(+), 4 deletions(-)
>> create mode 100644 scripts/qapi-event.py
> In addition to Luiz' comments, you are missing documentation. At a
> minimum, docs/qapi-code-gen.txt should be updated.
>
>
>> +try:
>> + opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
>> + ["source", "header", "builtins", "prefix=",
>> + "output-dir="])
>> +except getopt.GetoptError, err:
>> + print str(err)
>> + sys.exit(1)
>> +
>> +output_dir = ""
>> +prefix = ""
>> +c_file = 'qapi-event.c'
>> +h_file = 'qapi-event.h'
>> +
>> +do_c = False
>> +do_h = False
>> +do_builtins = False
>> +
>> +for o, a in opts:
>> + if o in ("-p", "--prefix"):
>> + prefix = a
>> + elif o in ("-o", "--output-dir"):
>> + output_dir = a + "/"
>> + elif o in ("-c", "--source"):
>> + do_c = True
>> + elif o in ("-h", "--header"):
>> + do_h = True
>> + elif o in ("-b", "--builtins"):
>> + do_builtins = True
> You may need to rebase this on top of other patches that refactor the
> qapi generators to track the input file, for improved error messages.
It seems qapi-visit.py and qapi-types.py remains the same as above in
upstream, which kind of change are your referring to?
>> +fdef.write(mcgen('''
>> +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
>> +
>> +/*
>> + * schema-defined QAPI event functions
>> + *
>> + * Copyright IBM, Corp. 2014
>> + *
>> + * Authors:
>> + * Wenchao Xia<xiawenc@linux.vnet.ibm.com>
>> + *
>> + * This work is licensed under the terms of the GNU GPLv2+ or later.
>> + * See the COPYING.LIB file in the top-level directory.
> Fix this. If these are really GPL files, then they should refer to
> COPYING. If you meant LGPL for the generated files, say so (but that's
> possibly at odds with other parts of your patch that put the generator
> under GPL).
>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-03-19 2:38 ` Wenchao Xia
@ 2014-03-20 22:29 ` Eric Blake
2014-03-24 0:55 ` Wenchao Xia
0 siblings, 1 reply; 27+ messages in thread
From: Eric Blake @ 2014-03-20 22:29 UTC (permalink / raw)
To: Wenchao Xia; +Cc: armbru, lcapitulino, qemu-devel, mreitz
[-- Attachment #1: Type: text/plain, Size: 1307 bytes --]
On 03/18/2014 08:38 PM, Wenchao Xia wrote:
> 于 2014/3/7 2:49, Eric Blake 写道:
>> On 01/02/2014 04:10 PM, Wenchao Xia wrote:
>>> qapi-event.py will parse the schema and generate qapi-event.c, then
>>> the API in qapi-event.c can be used to handle event in qemu code.
>>> All API have prefix "qapi_event", all types have prefix "QAPIEvent".
>>> Examples can be found in following patches.
>>>
>>> +for o, a in opts:
>>> + if o in ("-p", "--prefix"):
>>> + prefix = a
>>> + elif o in ("-o", "--output-dir"):
>>> + output_dir = a + "/"
>>> + elif o in ("-c", "--source"):
>>> + do_c = True
>>> + elif o in ("-h", "--header"):
>>> + do_h = True
>>> + elif o in ("-b", "--builtins"):
>>> + do_builtins = True
>> You may need to rebase this on top of other patches that refactor the
>> qapi generators to track the input file, for improved error messages.
> It seems qapi-visit.py and qapi-types.py remains the same as above in
> upstream, which kind of change are your referring to?
Lluís' patch to use an explicit input file via a new -i option:
https://lists.gnu.org/archive/html/qemu-devel/2014-02/msg05220.html
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-03-20 22:29 ` Eric Blake
@ 2014-03-24 0:55 ` Wenchao Xia
2014-03-26 12:42 ` Markus Armbruster
0 siblings, 1 reply; 27+ messages in thread
From: Wenchao Xia @ 2014-03-24 0:55 UTC (permalink / raw)
To: Eric Blake; +Cc: armbru, lcapitulino, qemu-devel, mreitz
于 2014/3/21 6:29, Eric Blake 写道:
> On 03/18/2014 08:38 PM, Wenchao Xia wrote:
>> 于 2014/3/7 2:49, Eric Blake 写道:
>>> On 01/02/2014 04:10 PM, Wenchao Xia wrote:
>>>> qapi-event.py will parse the schema and generate qapi-event.c, then
>>>> the API in qapi-event.c can be used to handle event in qemu code.
>>>> All API have prefix "qapi_event", all types have prefix "QAPIEvent".
>>>> Examples can be found in following patches.
>>>>
>>>> +for o, a in opts:
>>>> + if o in ("-p", "--prefix"):
>>>> + prefix = a
>>>> + elif o in ("-o", "--output-dir"):
>>>> + output_dir = a + "/"
>>>> + elif o in ("-c", "--source"):
>>>> + do_c = True
>>>> + elif o in ("-h", "--header"):
>>>> + do_h = True
>>>> + elif o in ("-b", "--builtins"):
>>>> + do_builtins = True
>>> You may need to rebase this on top of other patches that refactor the
>>> qapi generators to track the input file, for improved error messages.
>> It seems qapi-visit.py and qapi-types.py remains the same as above in
>> upstream, which kind of change are your referring to?
> Lluís' patch to use an explicit input file via a new -i option:
> https://lists.gnu.org/archive/html/qemu-devel/2014-02/msg05220.html
>
I see, will adjust it.
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-03-24 0:55 ` Wenchao Xia
@ 2014-03-26 12:42 ` Markus Armbruster
2014-03-26 13:13 ` Benoît Canet
0 siblings, 1 reply; 27+ messages in thread
From: Markus Armbruster @ 2014-03-26 12:42 UTC (permalink / raw)
To: Wenchao Xia; +Cc: Benoît Canet, mreitz, qemu-devel, lcapitulino
Wenchao Xia <wenchaoqemu@gmail.com> writes:
> 于 2014/3/21 6:29, Eric Blake 写道:
>> On 03/18/2014 08:38 PM, Wenchao Xia wrote:
>>> 于 2014/3/7 2:49, Eric Blake 写道:
>>>> On 01/02/2014 04:10 PM, Wenchao Xia wrote:
>>>>> qapi-event.py will parse the schema and generate qapi-event.c, then
>>>>> the API in qapi-event.c can be used to handle event in qemu code.
>>>>> All API have prefix "qapi_event", all types have prefix "QAPIEvent".
>>>>> Examples can be found in following patches.
>>>>>
>>>>> +for o, a in opts:
>>>>> + if o in ("-p", "--prefix"):
>>>>> + prefix = a
>>>>> + elif o in ("-o", "--output-dir"):
>>>>> + output_dir = a + "/"
>>>>> + elif o in ("-c", "--source"):
>>>>> + do_c = True
>>>>> + elif o in ("-h", "--header"):
>>>>> + do_h = True
>>>>> + elif o in ("-b", "--builtins"):
>>>>> + do_builtins = True
>>>> You may need to rebase this on top of other patches that refactor the
>>>> qapi generators to track the input file, for improved error messages.
>>> It seems qapi-visit.py and qapi-types.py remains the same as above in
>>> upstream, which kind of change are your referring to?
>> Lluís' patch to use an explicit input file via a new -i option:
>> https://lists.gnu.org/archive/html/qemu-devel/2014-02/msg05220.html
>>
> I see, will adjust it.
Part of "[PATCH v4 0/3] qapi: Allow modularization of QAPI schema
files". There's also Benoît's "[PATCH 0/2] Create and include directive
for QAPI JSON files"[*]. Benoît, care to explain how the two are
related?
Wenchao, please note "you *may* need to rebase". First patch in wins :)
[*] https://lists.nongnu.org/archive/html/qemu-devel/2014-03/msg04412.html
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-03-26 12:42 ` Markus Armbruster
@ 2014-03-26 13:13 ` Benoît Canet
2014-03-27 7:52 ` Wenchao Xia
0 siblings, 1 reply; 27+ messages in thread
From: Benoît Canet @ 2014-03-26 13:13 UTC (permalink / raw)
To: Markus Armbruster
Cc: Benoît Canet, Wenchao Xia, qemu-devel, mreitz, lcapitulino
The Wednesday 26 Mar 2014 à 13:42:38 (+0100), Markus Armbruster wrote :
> Wenchao Xia <wenchaoqemu@gmail.com> writes:
>
> > 于 2014/3/21 6:29, Eric Blake 写道:
> >> On 03/18/2014 08:38 PM, Wenchao Xia wrote:
> >>> 于 2014/3/7 2:49, Eric Blake 写道:
> >>>> On 01/02/2014 04:10 PM, Wenchao Xia wrote:
> >>>>> qapi-event.py will parse the schema and generate qapi-event.c, then
> >>>>> the API in qapi-event.c can be used to handle event in qemu code.
> >>>>> All API have prefix "qapi_event", all types have prefix "QAPIEvent".
> >>>>> Examples can be found in following patches.
> >>>>>
> >>>>> +for o, a in opts:
> >>>>> + if o in ("-p", "--prefix"):
> >>>>> + prefix = a
> >>>>> + elif o in ("-o", "--output-dir"):
> >>>>> + output_dir = a + "/"
> >>>>> + elif o in ("-c", "--source"):
> >>>>> + do_c = True
> >>>>> + elif o in ("-h", "--header"):
> >>>>> + do_h = True
> >>>>> + elif o in ("-b", "--builtins"):
> >>>>> + do_builtins = True
> >>>> You may need to rebase this on top of other patches that refactor the
> >>>> qapi generators to track the input file, for improved error messages.
> >>> It seems qapi-visit.py and qapi-types.py remains the same as above in
> >>> upstream, which kind of change are your referring to?
> >> Lluís' patch to use an explicit input file via a new -i option:
> >> https://lists.gnu.org/archive/html/qemu-devel/2014-02/msg05220.html
> >>
> > I see, will adjust it.
>
> Part of "[PATCH v4 0/3] qapi: Allow modularization of QAPI schema
> files". There's also Benoît's "[PATCH 0/2] Create and include directive
> for QAPI JSON files"[*]. Benoît, care to explain how the two are
> related?
I don't see the relation excepted that my patch changes the various qapi-generators
to accept their input files as argv[1].
The purpose of my patch is to implement a directive to modularise the pseudo JSON
files we use. Lluis told me that he would not have the time to work on his series
until the end of the month so I picked up the ball.
Best regards
Benoît
>
> Wenchao, please note "you *may* need to rebase". First patch in wins :)
>
> [*] https://lists.nongnu.org/archive/html/qemu-devel/2014-03/msg04412.html
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py
2014-03-26 13:13 ` Benoît Canet
@ 2014-03-27 7:52 ` Wenchao Xia
0 siblings, 0 replies; 27+ messages in thread
From: Wenchao Xia @ 2014-03-27 7:52 UTC (permalink / raw)
To: Benoît Canet, Markus Armbruster; +Cc: mreitz, qemu-devel, lcapitulino
>>>>>> You may need to rebase this on top of other patches that refactor the
>>>>>> qapi generators to track the input file, for improved error messages.
>>>>> It seems qapi-visit.py and qapi-types.py remains the same as above in
>>>>> upstream, which kind of change are your referring to?
>>>> Lluís' patch to use an explicit input file via a new -i option:
>>>> https://lists.gnu.org/archive/html/qemu-devel/2014-02/msg05220.html
>>>>
>>> I see, will adjust it.
>>
>> Part of "[PATCH v4 0/3] qapi: Allow modularization of QAPI schema
>> files". There's also Benoît's "[PATCH 0/2] Create and include directive
>> for QAPI JSON files"[*]. Benoît, care to explain how the two are
>> related?
>
> I don't see the relation excepted that my patch changes the various qapi-generators
> to accept their input files as argv[1].
>
> The purpose of my patch is to implement a directive to modularise the pseudo JSON
> files we use. Lluis told me that he would not have the time to work on his series
> until the end of the month so I picked up the ball.
>
> Best regards
>
> Benoît
>
Thanks for the explain, I'll rebase on top once your series merged
into Luiz's tree.
>>
>> Wenchao, please note "you *may* need to rebase". First patch in wins :)
>>
>> [*] https://lists.nongnu.org/archive/html/qemu-devel/2014-03/msg04412.html
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2014-03-27 7:52 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-02 23:10 [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema Wenchao Xia
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 1/5] os-posix: include sys/time.h Wenchao Xia
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 2/5] qapi: add event helper functions Wenchao Xia
2014-01-06 22:23 ` Luiz Capitulino
2014-01-07 2:28 ` Wenchao Xia
2014-03-06 18:26 ` Eric Blake
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 3/5] qapi script: add event support by qapi-event.py Wenchao Xia
2014-01-06 23:10 ` Luiz Capitulino
2014-01-06 23:17 ` Luiz Capitulino
2014-01-07 3:24 ` Wenchao Xia
2014-02-14 3:26 ` Wenchao Xia
2014-01-07 2:53 ` Wenchao Xia
2014-03-06 18:49 ` Eric Blake
2014-03-19 2:38 ` Wenchao Xia
2014-03-20 22:29 ` Eric Blake
2014-03-24 0:55 ` Wenchao Xia
2014-03-26 12:42 ` Markus Armbruster
2014-03-26 13:13 ` Benoît Canet
2014-03-27 7:52 ` Wenchao Xia
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 4/5] test: add test cases for qapi event Wenchao Xia
2014-03-06 20:05 ` Eric Blake
2014-01-02 23:10 ` [Qemu-devel] [RFC PATCH V2 5/5] qapi event: convert RTC_CHANGE Wenchao Xia
2014-03-06 20:24 ` Eric Blake
2014-01-06 23:18 ` [Qemu-devel] [RFC PATCH V2 0/5] add direct support of event in qapi schema Luiz Capitulino
2014-03-06 18:14 ` Eric Blake
2014-03-06 19:58 ` Luiz Capitulino
2014-03-07 1:13 ` Wenchao Xia
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).