mirror of
https://github.com/qemu/qemu.git
synced 2024-12-03 16:53:53 +08:00
QMP and QObject patches
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWMyUCAAoJEDhwtADrkYZTNAMQAKW+cQaH1GdWb0cX38fJ3ngM HYeHiYa4g7DXJGTUtobfq19v688JTZRF9DzZVj0iU8qY/UDxDtOzH10eX02C/oZn 1ra8otYNtTHCz2xGnSP+AFcn+5VjhucBH+SwWTb889NriQASnxbOiCKkBrsxxRhK 0ReCUOi7FqG8Yq5PKTIZHcU4u5LYZQm07/4WNM0Rv8HnflRF/I6CswG60ZWsy4lM x4WFnB/K6aB8Tg0TmSQgz5jFNfJyO+IVvplaqW3Lz/cUmOam7hx6eB5xxH84MrY9 Ng6taT7v+V6mKvq1wof57D0EFa2Ple4HqKvEYza6ShwkoTN57joJAr6MCKbILMXp /GYDMHo+IJvf1T2NkeM6nMDYMFsWMYBxxJN6ygukRdb/H5ACDxl9juZpHx3QP4KR V6+JpJ+BBtfWCTGzYD8Yn0Qs2O2Th43KvPAZ7j/RlcU/MNzv6fyRCc+7fwNdG9fo Xoz4c2S6Io7GJtLMDZiVG7Xz27TacprZx4CucBE2ccxJGsKIWrWRYrtqTQTh0Vtk br9QHK/Dqh02VJ42TCo16EDkDd594Q4QdhxvAgblmH0MH6lWDpuMJwbIfZKfkJxl KJ1c6DvYGdgixWhBWavVMwGSvzDr7udU1uz2FEfQmGKneiQIxfjTnHYl0CyQb/q0 Y4lGGbmdtQ+1iBogq3Y/ =0NNZ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-monitor-2015-10-30' into staging QMP and QObject patches # gpg: Signature made Fri 30 Oct 2015 08:06:26 GMT using RSA key ID EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" * remotes/armbru/tags/pull-monitor-2015-10-30: docs: Document QMP event rate limiting monitor: Throttle event VSERPORT_CHANGE separately by "id" monitor: Turn monitor_qapi_event_state[] into a hash table glib: add compatibility interface for g_hash_table_add() monitor: Split MonitorQAPIEventConf off MonitorQAPIEventState monitor: Switch from timer_new() to timer_new_ns() monitor: Simplify event throttling monitor: Reduce casting of QAPI event QDict qstring: Make conversion from QObject * accept null qlist: Make conversion from QObject * accept null qfloat qint: Make conversion from QObject * accept null qdict: Make conversion from QObject * accept null qbool: Make conversion from QObject * accept null qobject: Drop QObject_HEAD Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
fdf927621a
@ -28,6 +28,8 @@ Example:
|
||||
"data": { "actual": 944766976 },
|
||||
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
||||
|
||||
Note: this event is rate-limited.
|
||||
|
||||
BLOCK_IMAGE_CORRUPTED
|
||||
---------------------
|
||||
|
||||
@ -296,6 +298,8 @@ Example:
|
||||
"data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 },
|
||||
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
|
||||
Note: this event is rate-limited.
|
||||
|
||||
QUORUM_REPORT_BAD
|
||||
-----------------
|
||||
|
||||
@ -318,6 +322,8 @@ Example:
|
||||
"data": { "node-name": "1.raw", "sector-num": 345435, "sectors-count": 5 },
|
||||
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||
|
||||
Note: this event is rate-limited.
|
||||
|
||||
RESET
|
||||
-----
|
||||
|
||||
@ -358,6 +364,8 @@ Example:
|
||||
"data": { "offset": 78 },
|
||||
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
||||
|
||||
Note: this event is rate-limited.
|
||||
|
||||
SHUTDOWN
|
||||
--------
|
||||
|
||||
@ -632,6 +640,8 @@ Example:
|
||||
"data": { "id": "channel0", "open": true },
|
||||
"timestamp": { "seconds": 1401385907, "microseconds": 422329 } }
|
||||
|
||||
Note: this event is rate-limited separately for each "id".
|
||||
|
||||
WAKEUP
|
||||
------
|
||||
|
||||
@ -662,3 +672,5 @@ Example:
|
||||
|
||||
Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
|
||||
followed respectively by the RESET, SHUTDOWN, or STOP events.
|
||||
|
||||
Note: this event is rate-limited.
|
||||
|
@ -175,6 +175,11 @@ The format of asynchronous events is:
|
||||
For a listing of supported asynchronous events, please, refer to the
|
||||
qmp-events.txt file.
|
||||
|
||||
Some events are rate-limited to at most one per second. If additional
|
||||
"similar" events arrive within one second, all but the last one are
|
||||
dropped, and the last one is delayed. "Similar" normally means same
|
||||
event type. See qmp-events.txt for details.
|
||||
|
||||
2.5 QGA Synchronization
|
||||
-----------------------
|
||||
|
||||
|
@ -165,6 +165,14 @@ static inline GThread *g_thread_new(const char *name,
|
||||
#define CompatGCond GCond
|
||||
#endif /* glib 2.31 */
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 32, 0)
|
||||
/* Beware, function returns gboolean since 2.39.2, see GLib commit 9101915 */
|
||||
static inline void g_hash_table_add(GHashTable *hash_table, gpointer key)
|
||||
{
|
||||
g_hash_table_replace(hash_table, key, key);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef g_assert_true
|
||||
#define g_assert_true(expr) \
|
||||
do { \
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QBool {
|
||||
QObject_HEAD;
|
||||
QObject base;
|
||||
bool value;
|
||||
} QBool;
|
||||
|
||||
|
@ -28,7 +28,7 @@ typedef struct QDictEntry {
|
||||
} QDictEntry;
|
||||
|
||||
typedef struct QDict {
|
||||
QObject_HEAD;
|
||||
QObject base;
|
||||
size_t size;
|
||||
QLIST_HEAD(,QDictEntry) table[QDICT_BUCKET_MAX];
|
||||
} QDict;
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QFloat {
|
||||
QObject_HEAD;
|
||||
QObject base;
|
||||
double value;
|
||||
} QFloat;
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QInt {
|
||||
QObject_HEAD;
|
||||
QObject base;
|
||||
int64_t value;
|
||||
} QInt;
|
||||
|
||||
|
@ -22,7 +22,7 @@ typedef struct QListEntry {
|
||||
} QListEntry;
|
||||
|
||||
typedef struct QList {
|
||||
QObject_HEAD;
|
||||
QObject base;
|
||||
QTAILQ_HEAD(,QListEntry) head;
|
||||
} QList;
|
||||
|
||||
|
@ -59,10 +59,6 @@ typedef struct QObject {
|
||||
size_t refcnt;
|
||||
} QObject;
|
||||
|
||||
/* Objects definitions must include this */
|
||||
#define QObject_HEAD \
|
||||
QObject base
|
||||
|
||||
/* Get the 'base' part of an object */
|
||||
#define QOBJECT(obj) (&(obj)->base)
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QString {
|
||||
QObject_HEAD;
|
||||
QObject base;
|
||||
char *string;
|
||||
size_t length;
|
||||
size_t capacity;
|
||||
|
192
monitor.c
192
monitor.c
@ -181,13 +181,16 @@ typedef struct {
|
||||
* instance.
|
||||
*/
|
||||
typedef struct MonitorQAPIEventState {
|
||||
QAPIEvent event; /* Event being tracked */
|
||||
int64_t rate; /* Minimum time (in ns) between two events */
|
||||
int64_t last; /* QEMU_CLOCK_REALTIME value at last emission */
|
||||
QAPIEvent event; /* Throttling state for this event type and... */
|
||||
QDict *data; /* ... data, see qapi_event_throttle_equal() */
|
||||
QEMUTimer *timer; /* Timer for handling delayed events */
|
||||
QObject *data; /* Event pending delayed dispatch */
|
||||
QDict *qdict; /* Delayed event (if any) */
|
||||
} MonitorQAPIEventState;
|
||||
|
||||
typedef struct {
|
||||
int64_t rate; /* Minimum time (in ns) between two events */
|
||||
} MonitorQAPIEventConf;
|
||||
|
||||
struct Monitor {
|
||||
CharDriverState *chr;
|
||||
int reset_seen;
|
||||
@ -438,132 +441,161 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data,
|
||||
}
|
||||
|
||||
|
||||
static MonitorQAPIEventState monitor_qapi_event_state[QAPI_EVENT_MAX];
|
||||
static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT_MAX] = {
|
||||
/* Limit guest-triggerable events to 1 per second */
|
||||
[QAPI_EVENT_RTC_CHANGE] = { 1000 * SCALE_MS },
|
||||
[QAPI_EVENT_WATCHDOG] = { 1000 * SCALE_MS },
|
||||
[QAPI_EVENT_BALLOON_CHANGE] = { 1000 * SCALE_MS },
|
||||
[QAPI_EVENT_QUORUM_REPORT_BAD] = { 1000 * SCALE_MS },
|
||||
[QAPI_EVENT_QUORUM_FAILURE] = { 1000 * SCALE_MS },
|
||||
[QAPI_EVENT_VSERPORT_CHANGE] = { 1000 * SCALE_MS },
|
||||
};
|
||||
|
||||
GHashTable *monitor_qapi_event_state;
|
||||
|
||||
/*
|
||||
* Emits the event to every monitor instance, @event is only used for trace
|
||||
* Called with monitor_lock held.
|
||||
*/
|
||||
static void monitor_qapi_event_emit(QAPIEvent event, QObject *data)
|
||||
static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict)
|
||||
{
|
||||
Monitor *mon;
|
||||
|
||||
trace_monitor_protocol_event_emit(event, data);
|
||||
trace_monitor_protocol_event_emit(event, qdict);
|
||||
QLIST_FOREACH(mon, &mon_list, entry) {
|
||||
if (monitor_is_qmp(mon) && mon->qmp.in_command_mode) {
|
||||
monitor_json_emitter(mon, data);
|
||||
monitor_json_emitter(mon, QOBJECT(qdict));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void monitor_qapi_event_handler(void *opaque);
|
||||
|
||||
/*
|
||||
* Queue a new event for emission to Monitor instances,
|
||||
* applying any rate limiting if required.
|
||||
*/
|
||||
static void
|
||||
monitor_qapi_event_queue(QAPIEvent event, QDict *data, Error **errp)
|
||||
monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
|
||||
{
|
||||
MonitorQAPIEventConf *evconf;
|
||||
MonitorQAPIEventState *evstate;
|
||||
|
||||
assert(event < QAPI_EVENT_MAX);
|
||||
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
||||
evconf = &monitor_qapi_event_conf[event];
|
||||
trace_monitor_protocol_event_queue(event, qdict, evconf->rate);
|
||||
|
||||
evstate = &(monitor_qapi_event_state[event]);
|
||||
trace_monitor_protocol_event_queue(event,
|
||||
data,
|
||||
evstate->rate,
|
||||
evstate->last,
|
||||
now);
|
||||
|
||||
/* Rate limit of 0 indicates no throttling */
|
||||
qemu_mutex_lock(&monitor_lock);
|
||||
if (!evstate->rate) {
|
||||
monitor_qapi_event_emit(event, QOBJECT(data));
|
||||
evstate->last = now;
|
||||
|
||||
if (!evconf->rate) {
|
||||
/* Unthrottled event */
|
||||
monitor_qapi_event_emit(event, qdict);
|
||||
} else {
|
||||
int64_t delta = now - evstate->last;
|
||||
if (evstate->data ||
|
||||
delta < evstate->rate) {
|
||||
/* If there's an existing event pending, replace
|
||||
* it with the new event, otherwise schedule a
|
||||
* timer for delayed emission
|
||||
QDict *data = qobject_to_qdict(qdict_get(qdict, "data"));
|
||||
MonitorQAPIEventState key = { .event = event, .data = data };
|
||||
|
||||
evstate = g_hash_table_lookup(monitor_qapi_event_state, &key);
|
||||
assert(!evstate || timer_pending(evstate->timer));
|
||||
|
||||
if (evstate) {
|
||||
/*
|
||||
* Timer is pending for (at least) evconf->rate ns after
|
||||
* last send. Store event for sending when timer fires,
|
||||
* replacing a prior stored event if any.
|
||||
*/
|
||||
if (evstate->data) {
|
||||
qobject_decref(evstate->data);
|
||||
} else {
|
||||
int64_t then = evstate->last + evstate->rate;
|
||||
timer_mod_ns(evstate->timer, then);
|
||||
}
|
||||
evstate->data = QOBJECT(data);
|
||||
qobject_incref(evstate->data);
|
||||
QDECREF(evstate->qdict);
|
||||
evstate->qdict = qdict;
|
||||
QINCREF(evstate->qdict);
|
||||
} else {
|
||||
monitor_qapi_event_emit(event, QOBJECT(data));
|
||||
evstate->last = now;
|
||||
/*
|
||||
* Last send was (at least) evconf->rate ns ago.
|
||||
* Send immediately, and arm the timer to call
|
||||
* monitor_qapi_event_handler() in evconf->rate ns. Any
|
||||
* events arriving before then will be delayed until then.
|
||||
*/
|
||||
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
||||
|
||||
monitor_qapi_event_emit(event, qdict);
|
||||
|
||||
evstate = g_new(MonitorQAPIEventState, 1);
|
||||
evstate->event = event;
|
||||
evstate->data = data;
|
||||
QINCREF(evstate->data);
|
||||
evstate->qdict = NULL;
|
||||
evstate->timer = timer_new_ns(QEMU_CLOCK_REALTIME,
|
||||
monitor_qapi_event_handler,
|
||||
evstate);
|
||||
g_hash_table_add(monitor_qapi_event_state, evstate);
|
||||
timer_mod_ns(evstate->timer, now + evconf->rate);
|
||||
}
|
||||
}
|
||||
|
||||
qemu_mutex_unlock(&monitor_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* The callback invoked by QemuTimer when a delayed
|
||||
* event is ready to be emitted
|
||||
* This function runs evconf->rate ns after sending a throttled
|
||||
* event.
|
||||
* If another event has since been stored, send it.
|
||||
*/
|
||||
static void monitor_qapi_event_handler(void *opaque)
|
||||
{
|
||||
MonitorQAPIEventState *evstate = opaque;
|
||||
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
||||
MonitorQAPIEventConf *evconf = &monitor_qapi_event_conf[evstate->event];
|
||||
|
||||
trace_monitor_protocol_event_handler(evstate->event,
|
||||
evstate->data,
|
||||
evstate->last,
|
||||
now);
|
||||
trace_monitor_protocol_event_handler(evstate->event, evstate->qdict);
|
||||
qemu_mutex_lock(&monitor_lock);
|
||||
if (evstate->data) {
|
||||
monitor_qapi_event_emit(evstate->event, evstate->data);
|
||||
qobject_decref(evstate->data);
|
||||
evstate->data = NULL;
|
||||
|
||||
if (evstate->qdict) {
|
||||
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
||||
|
||||
monitor_qapi_event_emit(evstate->event, evstate->qdict);
|
||||
QDECREF(evstate->qdict);
|
||||
evstate->qdict = NULL;
|
||||
timer_mod_ns(evstate->timer, now + evconf->rate);
|
||||
} else {
|
||||
g_hash_table_remove(monitor_qapi_event_state, evstate);
|
||||
QDECREF(evstate->data);
|
||||
timer_free(evstate->timer);
|
||||
g_free(evstate);
|
||||
}
|
||||
evstate->last = now;
|
||||
|
||||
qemu_mutex_unlock(&monitor_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* @event: the event ID to be limited
|
||||
* @rate: the rate limit in milliseconds
|
||||
*
|
||||
* Sets a rate limit on a particular event, so no
|
||||
* more than 1 event will be emitted within @rate
|
||||
* milliseconds
|
||||
*/
|
||||
static void
|
||||
monitor_qapi_event_throttle(QAPIEvent event, int64_t rate)
|
||||
static unsigned int qapi_event_throttle_hash(const void *key)
|
||||
{
|
||||
MonitorQAPIEventState *evstate;
|
||||
assert(event < QAPI_EVENT_MAX);
|
||||
const MonitorQAPIEventState *evstate = key;
|
||||
unsigned int hash = evstate->event * 255;
|
||||
|
||||
evstate = &(monitor_qapi_event_state[event]);
|
||||
if (evstate->event == QAPI_EVENT_VSERPORT_CHANGE) {
|
||||
hash += g_str_hash(qdict_get_str(evstate->data, "id"));
|
||||
}
|
||||
|
||||
trace_monitor_protocol_event_throttle(event, rate);
|
||||
evstate->event = event;
|
||||
assert(rate * SCALE_MS <= INT64_MAX);
|
||||
evstate->rate = rate * SCALE_MS;
|
||||
evstate->last = 0;
|
||||
evstate->data = NULL;
|
||||
evstate->timer = timer_new(QEMU_CLOCK_REALTIME,
|
||||
SCALE_MS,
|
||||
monitor_qapi_event_handler,
|
||||
evstate);
|
||||
return hash;
|
||||
}
|
||||
|
||||
static gboolean qapi_event_throttle_equal(const void *a, const void *b)
|
||||
{
|
||||
const MonitorQAPIEventState *eva = a;
|
||||
const MonitorQAPIEventState *evb = b;
|
||||
|
||||
if (eva->event != evb->event) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (eva->event == QAPI_EVENT_VSERPORT_CHANGE) {
|
||||
return !strcmp(qdict_get_str(eva->data, "id"),
|
||||
qdict_get_str(evb->data, "id"));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void monitor_qapi_event_init(void)
|
||||
{
|
||||
/* Limit guest-triggerable events to 1 per second */
|
||||
monitor_qapi_event_throttle(QAPI_EVENT_RTC_CHANGE, 1000);
|
||||
monitor_qapi_event_throttle(QAPI_EVENT_WATCHDOG, 1000);
|
||||
monitor_qapi_event_throttle(QAPI_EVENT_BALLOON_CHANGE, 1000);
|
||||
monitor_qapi_event_throttle(QAPI_EVENT_QUORUM_REPORT_BAD, 1000);
|
||||
monitor_qapi_event_throttle(QAPI_EVENT_QUORUM_FAILURE, 1000);
|
||||
monitor_qapi_event_throttle(QAPI_EVENT_VSERPORT_CHANGE, 1000);
|
||||
|
||||
monitor_qapi_event_state = g_hash_table_new(qapi_event_throttle_hash,
|
||||
qapi_event_throttle_equal);
|
||||
qmp_event_set_func_emit(monitor_qapi_event_queue);
|
||||
}
|
||||
|
||||
|
@ -225,45 +225,45 @@ static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true);
|
||||
QInt *qint = qobject_to_qint(qmp_input_get_object(qiv, name, true));
|
||||
|
||||
if (!qobj || qobject_type(qobj) != QTYPE_QINT) {
|
||||
if (!qint) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
||||
"integer");
|
||||
return;
|
||||
}
|
||||
|
||||
*obj = qint_get_int(qobject_to_qint(qobj));
|
||||
*obj = qint_get_int(qint);
|
||||
}
|
||||
|
||||
static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true);
|
||||
QBool *qbool = qobject_to_qbool(qmp_input_get_object(qiv, name, true));
|
||||
|
||||
if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) {
|
||||
if (!qbool) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
||||
"boolean");
|
||||
return;
|
||||
}
|
||||
|
||||
*obj = qbool_get_bool(qobject_to_qbool(qobj));
|
||||
*obj = qbool_get_bool(qbool);
|
||||
}
|
||||
|
||||
static void qmp_input_type_str(Visitor *v, char **obj, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true);
|
||||
QString *qstr = qobject_to_qstring(qmp_input_get_object(qiv, name, true));
|
||||
|
||||
if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) {
|
||||
if (!qstr) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
||||
"string");
|
||||
return;
|
||||
}
|
||||
|
||||
*obj = g_strdup(qstring_get_str(qobject_to_qstring(qobj)));
|
||||
*obj = g_strdup(qstring_get_str(qstr));
|
||||
}
|
||||
|
||||
static void qmp_input_type_number(Visitor *v, double *obj, const char *name,
|
||||
@ -271,19 +271,23 @@ static void qmp_input_type_number(Visitor *v, double *obj, const char *name,
|
||||
{
|
||||
QmpInputVisitor *qiv = to_qiv(v);
|
||||
QObject *qobj = qmp_input_get_object(qiv, name, true);
|
||||
QInt *qint;
|
||||
QFloat *qfloat;
|
||||
|
||||
if (!qobj || (qobject_type(qobj) != QTYPE_QFLOAT &&
|
||||
qobject_type(qobj) != QTYPE_QINT)) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
||||
"number");
|
||||
qint = qobject_to_qint(qobj);
|
||||
if (qint) {
|
||||
*obj = qint_get_int(qobject_to_qint(qobj));
|
||||
return;
|
||||
}
|
||||
|
||||
if (qobject_type(qobj) == QTYPE_QINT) {
|
||||
*obj = qint_get_int(qobject_to_qint(qobj));
|
||||
} else {
|
||||
qfloat = qobject_to_qfloat(qobj);
|
||||
if (qfloat) {
|
||||
*obj = qfloat_get_double(qobject_to_qfloat(qobj));
|
||||
return;
|
||||
}
|
||||
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
||||
"number");
|
||||
}
|
||||
|
||||
static void qmp_input_type_any(Visitor *v, QObject **obj, const char *name,
|
||||
|
11
qga/main.c
11
qga/main.c
@ -573,7 +573,6 @@ static void process_command(GAState *s, QDict *req)
|
||||
static void process_event(JSONMessageParser *parser, QList *tokens)
|
||||
{
|
||||
GAState *s = container_of(parser, GAState, parser);
|
||||
QObject *obj;
|
||||
QDict *qdict;
|
||||
Error *err = NULL;
|
||||
int ret;
|
||||
@ -581,9 +580,9 @@ static void process_event(JSONMessageParser *parser, QList *tokens)
|
||||
g_assert(s && parser);
|
||||
|
||||
g_debug("process_event: called");
|
||||
obj = json_parser_parse_err(tokens, NULL, &err);
|
||||
if (err || !obj || qobject_type(obj) != QTYPE_QDICT) {
|
||||
qobject_decref(obj);
|
||||
qdict = qobject_to_qdict(json_parser_parse_err(tokens, NULL, &err));
|
||||
if (err || !qdict) {
|
||||
QDECREF(qdict);
|
||||
qdict = qdict_new();
|
||||
if (!err) {
|
||||
g_warning("failed to parse event: unknown error");
|
||||
@ -593,12 +592,8 @@ static void process_event(JSONMessageParser *parser, QList *tokens)
|
||||
}
|
||||
qdict_put_obj(qdict, "error", qmp_build_error_object(err));
|
||||
error_free(err);
|
||||
} else {
|
||||
qdict = qobject_to_qdict(obj);
|
||||
}
|
||||
|
||||
g_assert(qdict);
|
||||
|
||||
/* handle host->guest commands */
|
||||
if (qdict_haskey(qdict, "execute")) {
|
||||
process_command(s, qdict);
|
||||
|
@ -51,9 +51,9 @@ bool qbool_get_bool(const QBool *qb)
|
||||
*/
|
||||
QBool *qobject_to_qbool(const QObject *obj)
|
||||
{
|
||||
if (qobject_type(obj) != QTYPE_QBOOL)
|
||||
if (!obj || qobject_type(obj) != QTYPE_QBOOL) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
return container_of(obj, QBool, base);
|
||||
}
|
||||
|
||||
|
@ -46,9 +46,9 @@ QDict *qdict_new(void)
|
||||
*/
|
||||
QDict *qobject_to_qdict(const QObject *obj)
|
||||
{
|
||||
if (qobject_type(obj) != QTYPE_QDICT)
|
||||
if (!obj || qobject_type(obj) != QTYPE_QDICT) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
return container_of(obj, QDict, base);
|
||||
}
|
||||
|
||||
@ -229,8 +229,7 @@ double qdict_get_double(const QDict *qdict, const char *key)
|
||||
*/
|
||||
int64_t qdict_get_int(const QDict *qdict, const char *key)
|
||||
{
|
||||
QObject *obj = qdict_get_obj(qdict, key, QTYPE_QINT);
|
||||
return qint_get_int(qobject_to_qint(obj));
|
||||
return qint_get_int(qobject_to_qint(qdict_get(qdict, key)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,8 +242,7 @@ int64_t qdict_get_int(const QDict *qdict, const char *key)
|
||||
*/
|
||||
bool qdict_get_bool(const QDict *qdict, const char *key)
|
||||
{
|
||||
QObject *obj = qdict_get_obj(qdict, key, QTYPE_QBOOL);
|
||||
return qbool_get_bool(qobject_to_qbool(obj));
|
||||
return qbool_get_bool(qobject_to_qbool(qdict_get(qdict, key)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -270,7 +268,7 @@ QList *qdict_get_qlist(const QDict *qdict, const char *key)
|
||||
*/
|
||||
QDict *qdict_get_qdict(const QDict *qdict, const char *key)
|
||||
{
|
||||
return qobject_to_qdict(qdict_get_obj(qdict, key, QTYPE_QDICT));
|
||||
return qobject_to_qdict(qdict_get(qdict, key));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -284,8 +282,7 @@ QDict *qdict_get_qdict(const QDict *qdict, const char *key)
|
||||
*/
|
||||
const char *qdict_get_str(const QDict *qdict, const char *key)
|
||||
{
|
||||
QObject *obj = qdict_get_obj(qdict, key, QTYPE_QSTRING);
|
||||
return qstring_get_str(qobject_to_qstring(obj));
|
||||
return qstring_get_str(qobject_to_qstring(qdict_get(qdict, key)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -298,13 +295,9 @@ const char *qdict_get_str(const QDict *qdict, const char *key)
|
||||
int64_t qdict_get_try_int(const QDict *qdict, const char *key,
|
||||
int64_t def_value)
|
||||
{
|
||||
QObject *obj;
|
||||
QInt *qint = qobject_to_qint(qdict_get(qdict, key));
|
||||
|
||||
obj = qdict_get(qdict, key);
|
||||
if (!obj || qobject_type(obj) != QTYPE_QINT)
|
||||
return def_value;
|
||||
|
||||
return qint_get_int(qobject_to_qint(obj));
|
||||
return qint ? qint_get_int(qint) : def_value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -316,13 +309,9 @@ int64_t qdict_get_try_int(const QDict *qdict, const char *key,
|
||||
*/
|
||||
bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value)
|
||||
{
|
||||
QObject *obj;
|
||||
QBool *qbool = qobject_to_qbool(qdict_get(qdict, key));
|
||||
|
||||
obj = qdict_get(qdict, key);
|
||||
if (!obj || qobject_type(obj) != QTYPE_QBOOL)
|
||||
return def_value;
|
||||
|
||||
return qbool_get_bool(qobject_to_qbool(obj));
|
||||
return qbool ? qbool_get_bool(qbool) : def_value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -335,13 +324,9 @@ bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value)
|
||||
*/
|
||||
const char *qdict_get_try_str(const QDict *qdict, const char *key)
|
||||
{
|
||||
QObject *obj;
|
||||
QString *qstr = qobject_to_qstring(qdict_get(qdict, key));
|
||||
|
||||
obj = qdict_get(qdict, key);
|
||||
if (!obj || qobject_type(obj) != QTYPE_QSTRING)
|
||||
return NULL;
|
||||
|
||||
return qstring_get_str(qobject_to_qstring(obj));
|
||||
return qstr ? qstring_get_str(qstr) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,9 +51,9 @@ double qfloat_get_double(const QFloat *qf)
|
||||
*/
|
||||
QFloat *qobject_to_qfloat(const QObject *obj)
|
||||
{
|
||||
if (qobject_type(obj) != QTYPE_QFLOAT)
|
||||
if (!obj || qobject_type(obj) != QTYPE_QFLOAT) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
return container_of(obj, QFloat, base);
|
||||
}
|
||||
|
||||
|
@ -50,9 +50,9 @@ int64_t qint_get_int(const QInt *qi)
|
||||
*/
|
||||
QInt *qobject_to_qint(const QObject *obj)
|
||||
{
|
||||
if (qobject_type(obj) != QTYPE_QINT)
|
||||
if (!obj || qobject_type(obj) != QTYPE_QINT) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
return container_of(obj, QInt, base);
|
||||
}
|
||||
|
||||
|
@ -142,10 +142,9 @@ size_t qlist_size(const QList *qlist)
|
||||
*/
|
||||
QList *qobject_to_qlist(const QObject *obj)
|
||||
{
|
||||
if (qobject_type(obj) != QTYPE_QLIST) {
|
||||
if (!obj || qobject_type(obj) != QTYPE_QLIST) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return container_of(obj, QList, base);
|
||||
}
|
||||
|
||||
|
@ -117,9 +117,9 @@ void qstring_append_chr(QString *qstring, int c)
|
||||
*/
|
||||
QString *qobject_to_qstring(const QObject *obj)
|
||||
{
|
||||
if (qobject_type(obj) != QTYPE_QSTRING)
|
||||
if (!obj || qobject_type(obj) != QTYPE_QSTRING) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
return container_of(obj, QString, base);
|
||||
}
|
||||
|
||||
|
@ -1031,9 +1031,9 @@ esp_pci_sbac_write(uint32_t reg, uint32_t val) "sbac: 0x%8.8x -> 0x%8.8x"
|
||||
# monitor.c
|
||||
handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\""
|
||||
monitor_protocol_emitter(void *mon) "mon %p"
|
||||
monitor_protocol_event_handler(uint32_t event, void *data, uint64_t last, uint64_t now) "event=%d data=%p last=%" PRId64 " now=%" PRId64
|
||||
monitor_protocol_event_handler(uint32_t event, void *qdict) "event=%d data=%p"
|
||||
monitor_protocol_event_emit(uint32_t event, void *data) "event=%d data=%p"
|
||||
monitor_protocol_event_queue(uint32_t event, void *data, uint64_t rate, uint64_t last, uint64_t now) "event=%d data=%p rate=%" PRId64 " last=%" PRId64 " now=%" PRId64
|
||||
monitor_protocol_event_queue(uint32_t event, void *qdict, uint64_t rate) "event=%d data=%p rate=%" PRId64
|
||||
monitor_protocol_event_throttle(uint32_t event, uint64_t rate) "event=%d rate=%" PRId64
|
||||
|
||||
# hw/net/opencores_eth.c
|
||||
|
Loading…
Reference in New Issue
Block a user