Message ID | 1337619593-25823-2-git-send-email-berrange@redhat.com |
---|---|
State | New |
Headers | show |
On Mon, 21 May 2012 17:59:51 +0100 "Daniel P. Berrange" <berrange@redhat.com> wrote: > From: "Daniel P. Berrange" <berrange@redhat.com> > > Sometimes it is neccessary for an application to determine > whether a particular QMP event is available, so they can > decide whether to use compatibility code instead. This > introduces a new 'query-events' command to QMP to do just > that > > { "execute": "query-events" } > {"return": [{"name": "WAKEUP"}, > {"name": "SUSPEND"}, > {"name": "DEVICE_TRAY_MOVED"}, > {"name": "BLOCK_JOB_CANCELLED"}, > {"name": "BLOCK_JOB_COMPLETED"}, > ...snip... > {"name": "SHUTDOWN"}]} > > * monitor.c: Turn MonitorEvent -> string conversion > into a lookup from a static table of constant strings. > Add impl of qmp_query_events monitor command handler > * qapi-schema.json, qmp-commands.hx: Define contract of > query-events command > > Signed-off-by: Daniel P. Berrange <berrange@redhat.com> Looks good to me. As this independent of the other patches I've applied it to the qmp-next branch, so you don't need to include this if you respin. > --- > monitor.c | 107 +++++++++++++++++++++++------------------------------- > monitor.h | 4 ++ > qapi-schema.json | 22 +++++++++++ > qmp-commands.hx | 37 +++++++++++++++++++ > 4 files changed, 108 insertions(+), 62 deletions(-) > > diff --git a/monitor.c b/monitor.c > index 12a6fe2..a3bc2c7 100644 > --- a/monitor.c > +++ b/monitor.c > @@ -422,6 +422,30 @@ static void timestamp_put(QDict *qdict) > qdict_put_obj(qdict, "timestamp", obj); > } > > + > +static const char *monitor_event_names[] = { > + [QEVENT_SHUTDOWN] = "SHUTDOWN", > + [QEVENT_RESET] = "RESET", > + [QEVENT_POWERDOWN] = "POWERDOWN", > + [QEVENT_STOP] = "STOP", > + [QEVENT_RESUME] = "RESUME", > + [QEVENT_VNC_CONNECTED] = "VNC_CONNECTED", > + [QEVENT_VNC_INITIALIZED] = "VNC_INITIALIZED", > + [QEVENT_VNC_DISCONNECTED] = "VNC_DISCONNECTED", > + [QEVENT_BLOCK_IO_ERROR] = "BLOCK_IO_ERROR", > + [QEVENT_RTC_CHANGE] = "RTC_CHANGE", > + [QEVENT_WATCHDOG] = "WATCHDOG", > + [QEVENT_SPICE_CONNECTED] = "SPICE_CONNECTED", > + [QEVENT_SPICE_INITIALIZED] = "SPICE_INITIALIZED", > + [QEVENT_SPICE_DISCONNECTED] = "SPICE_DISCONNECTED", > + [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED", > + [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED", > + [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED", > + [QEVENT_SUSPEND] = "SUSPEND", > + [QEVENT_WAKEUP] = "WAKEUP", > +}; > +QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX) > + > /** > * monitor_protocol_event(): Generate a Monitor event > * > @@ -435,68 +459,8 @@ void monitor_protocol_event(MonitorEvent event, QObject *data) > > assert(event < QEVENT_MAX); > > - switch (event) { > - case QEVENT_SHUTDOWN: > - event_name = "SHUTDOWN"; > - break; > - case QEVENT_RESET: > - event_name = "RESET"; > - break; > - case QEVENT_POWERDOWN: > - event_name = "POWERDOWN"; > - break; > - case QEVENT_STOP: > - event_name = "STOP"; > - break; > - case QEVENT_RESUME: > - event_name = "RESUME"; > - break; > - case QEVENT_VNC_CONNECTED: > - event_name = "VNC_CONNECTED"; > - break; > - case QEVENT_VNC_INITIALIZED: > - event_name = "VNC_INITIALIZED"; > - break; > - case QEVENT_VNC_DISCONNECTED: > - event_name = "VNC_DISCONNECTED"; > - break; > - case QEVENT_BLOCK_IO_ERROR: > - event_name = "BLOCK_IO_ERROR"; > - break; > - case QEVENT_RTC_CHANGE: > - event_name = "RTC_CHANGE"; > - break; > - case QEVENT_WATCHDOG: > - event_name = "WATCHDOG"; > - break; > - case QEVENT_SPICE_CONNECTED: > - event_name = "SPICE_CONNECTED"; > - break; > - case QEVENT_SPICE_INITIALIZED: > - event_name = "SPICE_INITIALIZED"; > - break; > - case QEVENT_SPICE_DISCONNECTED: > - event_name = "SPICE_DISCONNECTED"; > - break; > - case QEVENT_BLOCK_JOB_COMPLETED: > - event_name = "BLOCK_JOB_COMPLETED"; > - break; > - case QEVENT_BLOCK_JOB_CANCELLED: > - event_name = "BLOCK_JOB_CANCELLED"; > - break; > - case QEVENT_DEVICE_TRAY_MOVED: > - event_name = "DEVICE_TRAY_MOVED"; > - break; > - case QEVENT_SUSPEND: > - event_name = "SUSPEND"; > - break; > - case QEVENT_WAKEUP: > - event_name = "WAKEUP"; > - break; > - default: > - abort(); > - break; > - } > + event_name = monitor_event_names[event]; > + assert(event_name != NULL); > > qmp = qdict_new(); > timestamp_put(qmp); > @@ -738,6 +702,25 @@ CommandInfoList *qmp_query_commands(Error **errp) > return cmd_list; > } > > +EventInfoList *qmp_query_events(Error **errp) > +{ > + EventInfoList *info, *ev_list = NULL; > + MonitorEvent e; > + > + for (e = 0 ; e < QEVENT_MAX ; e++) { > + const char *event_name = monitor_event_names[e]; > + assert(event_name != NULL); > + info = g_malloc0(sizeof(*info)); > + info->value = g_malloc0(sizeof(*info->value)); > + info->value->name = g_strdup(event_name); > + > + info->next = ev_list; > + ev_list = info; > + } > + > + return ev_list; > +} > + > /* set the current CPU defined by the user */ > int monitor_set_cpu(int cpu_index) > { > diff --git a/monitor.h b/monitor.h > index 0d49800..cd1d878 100644 > --- a/monitor.h > +++ b/monitor.h > @@ -41,6 +41,10 @@ typedef enum MonitorEvent { > QEVENT_DEVICE_TRAY_MOVED, > QEVENT_SUSPEND, > QEVENT_WAKEUP, > + > + /* Add to 'monitor_event_names' array in monitor.c when > + * defining new events here */ > + > QEVENT_MAX, > } MonitorEvent; > > diff --git a/qapi-schema.json b/qapi-schema.json > index 2ca7195..94aa0ae 100644 > --- a/qapi-schema.json > +++ b/qapi-schema.json > @@ -228,6 +228,28 @@ > { 'command': 'query-commands', 'returns': ['CommandInfo'] } > > ## > +# @EventInfo: > +# > +# Information about a QMP event > +# > +# @name: The event name > +# > +# Since: 1.2.0 > +## > +{ 'type': 'EventInfo', 'data': {'name': 'str'} } > + > +## > +# @query-events: > +# > +# Return a list of supported QMP events by this server > +# > +# Returns: A list of @EventInfo for all supported events > +# > +# Since: 1.2.0 > +## > +{ 'command': 'query-events', 'returns': ['EventInfo'] } > + > +## > # @MigrationStats > # > # Detailed migration status. > diff --git a/qmp-commands.hx b/qmp-commands.hx > index db980fa..9c15d3c 100644 > --- a/qmp-commands.hx > +++ b/qmp-commands.hx > @@ -1179,6 +1179,43 @@ EQMP > }, > > SQMP > +query-events > +-------------- > + > +List QMP available events. > + > +Each event is represented by a json-object, the returned value is a json-array > +of all events. > + > +Each json-object contains: > + > +- "name": event's name (json-string) > + > +Example: > + > +-> { "execute": "query-events" } > +<- { > + "return":[ > + { > + "name":"SHUTDOWN" > + }, > + { > + "name":"RESET" > + } > + ] > + } > + > +Note: This example has been shortened as the real response is too long. > + > +EQMP > + > + { > + .name = "query-events", > + .args_type = "", > + .mhandler.cmd_new = qmp_marshal_input_query_events, > + }, > + > +SQMP > query-chardev > ------------- >
diff --git a/monitor.c b/monitor.c index 12a6fe2..a3bc2c7 100644 --- a/monitor.c +++ b/monitor.c @@ -422,6 +422,30 @@ static void timestamp_put(QDict *qdict) qdict_put_obj(qdict, "timestamp", obj); } + +static const char *monitor_event_names[] = { + [QEVENT_SHUTDOWN] = "SHUTDOWN", + [QEVENT_RESET] = "RESET", + [QEVENT_POWERDOWN] = "POWERDOWN", + [QEVENT_STOP] = "STOP", + [QEVENT_RESUME] = "RESUME", + [QEVENT_VNC_CONNECTED] = "VNC_CONNECTED", + [QEVENT_VNC_INITIALIZED] = "VNC_INITIALIZED", + [QEVENT_VNC_DISCONNECTED] = "VNC_DISCONNECTED", + [QEVENT_BLOCK_IO_ERROR] = "BLOCK_IO_ERROR", + [QEVENT_RTC_CHANGE] = "RTC_CHANGE", + [QEVENT_WATCHDOG] = "WATCHDOG", + [QEVENT_SPICE_CONNECTED] = "SPICE_CONNECTED", + [QEVENT_SPICE_INITIALIZED] = "SPICE_INITIALIZED", + [QEVENT_SPICE_DISCONNECTED] = "SPICE_DISCONNECTED", + [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED", + [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED", + [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED", + [QEVENT_SUSPEND] = "SUSPEND", + [QEVENT_WAKEUP] = "WAKEUP", +}; +QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX) + /** * monitor_protocol_event(): Generate a Monitor event * @@ -435,68 +459,8 @@ void monitor_protocol_event(MonitorEvent event, QObject *data) assert(event < QEVENT_MAX); - switch (event) { - case QEVENT_SHUTDOWN: - event_name = "SHUTDOWN"; - break; - case QEVENT_RESET: - event_name = "RESET"; - break; - case QEVENT_POWERDOWN: - event_name = "POWERDOWN"; - break; - case QEVENT_STOP: - event_name = "STOP"; - break; - case QEVENT_RESUME: - event_name = "RESUME"; - break; - case QEVENT_VNC_CONNECTED: - event_name = "VNC_CONNECTED"; - break; - case QEVENT_VNC_INITIALIZED: - event_name = "VNC_INITIALIZED"; - break; - case QEVENT_VNC_DISCONNECTED: - event_name = "VNC_DISCONNECTED"; - break; - case QEVENT_BLOCK_IO_ERROR: - event_name = "BLOCK_IO_ERROR"; - break; - case QEVENT_RTC_CHANGE: - event_name = "RTC_CHANGE"; - break; - case QEVENT_WATCHDOG: - event_name = "WATCHDOG"; - break; - case QEVENT_SPICE_CONNECTED: - event_name = "SPICE_CONNECTED"; - break; - case QEVENT_SPICE_INITIALIZED: - event_name = "SPICE_INITIALIZED"; - break; - case QEVENT_SPICE_DISCONNECTED: - event_name = "SPICE_DISCONNECTED"; - break; - case QEVENT_BLOCK_JOB_COMPLETED: - event_name = "BLOCK_JOB_COMPLETED"; - break; - case QEVENT_BLOCK_JOB_CANCELLED: - event_name = "BLOCK_JOB_CANCELLED"; - break; - case QEVENT_DEVICE_TRAY_MOVED: - event_name = "DEVICE_TRAY_MOVED"; - break; - case QEVENT_SUSPEND: - event_name = "SUSPEND"; - break; - case QEVENT_WAKEUP: - event_name = "WAKEUP"; - break; - default: - abort(); - break; - } + event_name = monitor_event_names[event]; + assert(event_name != NULL); qmp = qdict_new(); timestamp_put(qmp); @@ -738,6 +702,25 @@ CommandInfoList *qmp_query_commands(Error **errp) return cmd_list; } +EventInfoList *qmp_query_events(Error **errp) +{ + EventInfoList *info, *ev_list = NULL; + MonitorEvent e; + + for (e = 0 ; e < QEVENT_MAX ; e++) { + const char *event_name = monitor_event_names[e]; + assert(event_name != NULL); + info = g_malloc0(sizeof(*info)); + info->value = g_malloc0(sizeof(*info->value)); + info->value->name = g_strdup(event_name); + + info->next = ev_list; + ev_list = info; + } + + return ev_list; +} + /* set the current CPU defined by the user */ int monitor_set_cpu(int cpu_index) { diff --git a/monitor.h b/monitor.h index 0d49800..cd1d878 100644 --- a/monitor.h +++ b/monitor.h @@ -41,6 +41,10 @@ typedef enum MonitorEvent { QEVENT_DEVICE_TRAY_MOVED, QEVENT_SUSPEND, QEVENT_WAKEUP, + + /* Add to 'monitor_event_names' array in monitor.c when + * defining new events here */ + QEVENT_MAX, } MonitorEvent; diff --git a/qapi-schema.json b/qapi-schema.json index 2ca7195..94aa0ae 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -228,6 +228,28 @@ { 'command': 'query-commands', 'returns': ['CommandInfo'] } ## +# @EventInfo: +# +# Information about a QMP event +# +# @name: The event name +# +# Since: 1.2.0 +## +{ 'type': 'EventInfo', 'data': {'name': 'str'} } + +## +# @query-events: +# +# Return a list of supported QMP events by this server +# +# Returns: A list of @EventInfo for all supported events +# +# Since: 1.2.0 +## +{ 'command': 'query-events', 'returns': ['EventInfo'] } + +## # @MigrationStats # # Detailed migration status. diff --git a/qmp-commands.hx b/qmp-commands.hx index db980fa..9c15d3c 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1179,6 +1179,43 @@ EQMP }, SQMP +query-events +-------------- + +List QMP available events. + +Each event is represented by a json-object, the returned value is a json-array +of all events. + +Each json-object contains: + +- "name": event's name (json-string) + +Example: + +-> { "execute": "query-events" } +<- { + "return":[ + { + "name":"SHUTDOWN" + }, + { + "name":"RESET" + } + ] + } + +Note: This example has been shortened as the real response is too long. + +EQMP + + { + .name = "query-events", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_events, + }, + +SQMP query-chardev -------------