On Mon, 21 May 2012 17:59:51 +0100 "Daniel P. Berrange" <berra...@redhat.com> wrote:
> From: "Daniel P. Berrange" <berra...@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 <berra...@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 > ------------- >