mirror of
https://github.com/qemu/qemu.git
synced 2024-12-11 20:53:51 +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 },
|
"data": { "actual": 944766976 },
|
||||||
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
||||||
|
|
||||||
|
Note: this event is rate-limited.
|
||||||
|
|
||||||
BLOCK_IMAGE_CORRUPTED
|
BLOCK_IMAGE_CORRUPTED
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
@ -296,6 +298,8 @@ Example:
|
|||||||
"data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 },
|
"data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 },
|
||||||
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||||
|
|
||||||
|
Note: this event is rate-limited.
|
||||||
|
|
||||||
QUORUM_REPORT_BAD
|
QUORUM_REPORT_BAD
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@ -318,6 +322,8 @@ Example:
|
|||||||
"data": { "node-name": "1.raw", "sector-num": 345435, "sectors-count": 5 },
|
"data": { "node-name": "1.raw", "sector-num": 345435, "sectors-count": 5 },
|
||||||
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
|
||||||
|
|
||||||
|
Note: this event is rate-limited.
|
||||||
|
|
||||||
RESET
|
RESET
|
||||||
-----
|
-----
|
||||||
|
|
||||||
@ -358,6 +364,8 @@ Example:
|
|||||||
"data": { "offset": 78 },
|
"data": { "offset": 78 },
|
||||||
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
|
||||||
|
|
||||||
|
Note: this event is rate-limited.
|
||||||
|
|
||||||
SHUTDOWN
|
SHUTDOWN
|
||||||
--------
|
--------
|
||||||
|
|
||||||
@ -632,6 +640,8 @@ Example:
|
|||||||
"data": { "id": "channel0", "open": true },
|
"data": { "id": "channel0", "open": true },
|
||||||
"timestamp": { "seconds": 1401385907, "microseconds": 422329 } }
|
"timestamp": { "seconds": 1401385907, "microseconds": 422329 } }
|
||||||
|
|
||||||
|
Note: this event is rate-limited separately for each "id".
|
||||||
|
|
||||||
WAKEUP
|
WAKEUP
|
||||||
------
|
------
|
||||||
|
|
||||||
@ -662,3 +672,5 @@ Example:
|
|||||||
|
|
||||||
Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
|
Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
|
||||||
followed respectively by the RESET, SHUTDOWN, or STOP events.
|
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
|
For a listing of supported asynchronous events, please, refer to the
|
||||||
qmp-events.txt file.
|
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
|
2.5 QGA Synchronization
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
@ -165,6 +165,14 @@ static inline GThread *g_thread_new(const char *name,
|
|||||||
#define CompatGCond GCond
|
#define CompatGCond GCond
|
||||||
#endif /* glib 2.31 */
|
#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
|
#ifndef g_assert_true
|
||||||
#define g_assert_true(expr) \
|
#define g_assert_true(expr) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "qapi/qmp/qobject.h"
|
#include "qapi/qmp/qobject.h"
|
||||||
|
|
||||||
typedef struct QBool {
|
typedef struct QBool {
|
||||||
QObject_HEAD;
|
QObject base;
|
||||||
bool value;
|
bool value;
|
||||||
} QBool;
|
} QBool;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ typedef struct QDictEntry {
|
|||||||
} QDictEntry;
|
} QDictEntry;
|
||||||
|
|
||||||
typedef struct QDict {
|
typedef struct QDict {
|
||||||
QObject_HEAD;
|
QObject base;
|
||||||
size_t size;
|
size_t size;
|
||||||
QLIST_HEAD(,QDictEntry) table[QDICT_BUCKET_MAX];
|
QLIST_HEAD(,QDictEntry) table[QDICT_BUCKET_MAX];
|
||||||
} QDict;
|
} QDict;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "qapi/qmp/qobject.h"
|
#include "qapi/qmp/qobject.h"
|
||||||
|
|
||||||
typedef struct QFloat {
|
typedef struct QFloat {
|
||||||
QObject_HEAD;
|
QObject base;
|
||||||
double value;
|
double value;
|
||||||
} QFloat;
|
} QFloat;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include "qapi/qmp/qobject.h"
|
#include "qapi/qmp/qobject.h"
|
||||||
|
|
||||||
typedef struct QInt {
|
typedef struct QInt {
|
||||||
QObject_HEAD;
|
QObject base;
|
||||||
int64_t value;
|
int64_t value;
|
||||||
} QInt;
|
} QInt;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ typedef struct QListEntry {
|
|||||||
} QListEntry;
|
} QListEntry;
|
||||||
|
|
||||||
typedef struct QList {
|
typedef struct QList {
|
||||||
QObject_HEAD;
|
QObject base;
|
||||||
QTAILQ_HEAD(,QListEntry) head;
|
QTAILQ_HEAD(,QListEntry) head;
|
||||||
} QList;
|
} QList;
|
||||||
|
|
||||||
|
@ -59,10 +59,6 @@ typedef struct QObject {
|
|||||||
size_t refcnt;
|
size_t refcnt;
|
||||||
} QObject;
|
} QObject;
|
||||||
|
|
||||||
/* Objects definitions must include this */
|
|
||||||
#define QObject_HEAD \
|
|
||||||
QObject base
|
|
||||||
|
|
||||||
/* Get the 'base' part of an object */
|
/* Get the 'base' part of an object */
|
||||||
#define QOBJECT(obj) (&(obj)->base)
|
#define QOBJECT(obj) (&(obj)->base)
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include "qapi/qmp/qobject.h"
|
#include "qapi/qmp/qobject.h"
|
||||||
|
|
||||||
typedef struct QString {
|
typedef struct QString {
|
||||||
QObject_HEAD;
|
QObject base;
|
||||||
char *string;
|
char *string;
|
||||||
size_t length;
|
size_t length;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
|
192
monitor.c
192
monitor.c
@ -181,13 +181,16 @@ typedef struct {
|
|||||||
* instance.
|
* instance.
|
||||||
*/
|
*/
|
||||||
typedef struct MonitorQAPIEventState {
|
typedef struct MonitorQAPIEventState {
|
||||||
QAPIEvent event; /* Event being tracked */
|
QAPIEvent event; /* Throttling state for this event type and... */
|
||||||
int64_t rate; /* Minimum time (in ns) between two events */
|
QDict *data; /* ... data, see qapi_event_throttle_equal() */
|
||||||
int64_t last; /* QEMU_CLOCK_REALTIME value at last emission */
|
|
||||||
QEMUTimer *timer; /* Timer for handling delayed events */
|
QEMUTimer *timer; /* Timer for handling delayed events */
|
||||||
QObject *data; /* Event pending delayed dispatch */
|
QDict *qdict; /* Delayed event (if any) */
|
||||||
} MonitorQAPIEventState;
|
} MonitorQAPIEventState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int64_t rate; /* Minimum time (in ns) between two events */
|
||||||
|
} MonitorQAPIEventConf;
|
||||||
|
|
||||||
struct Monitor {
|
struct Monitor {
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
int reset_seen;
|
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
|
* Emits the event to every monitor instance, @event is only used for trace
|
||||||
* Called with monitor_lock held.
|
* 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;
|
Monitor *mon;
|
||||||
|
|
||||||
trace_monitor_protocol_event_emit(event, data);
|
trace_monitor_protocol_event_emit(event, qdict);
|
||||||
QLIST_FOREACH(mon, &mon_list, entry) {
|
QLIST_FOREACH(mon, &mon_list, entry) {
|
||||||
if (monitor_is_qmp(mon) && mon->qmp.in_command_mode) {
|
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,
|
* Queue a new event for emission to Monitor instances,
|
||||||
* applying any rate limiting if required.
|
* applying any rate limiting if required.
|
||||||
*/
|
*/
|
||||||
static void
|
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;
|
MonitorQAPIEventState *evstate;
|
||||||
|
|
||||||
assert(event < QAPI_EVENT_MAX);
|
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);
|
qemu_mutex_lock(&monitor_lock);
|
||||||
if (!evstate->rate) {
|
|
||||||
monitor_qapi_event_emit(event, QOBJECT(data));
|
if (!evconf->rate) {
|
||||||
evstate->last = now;
|
/* Unthrottled event */
|
||||||
|
monitor_qapi_event_emit(event, qdict);
|
||||||
} else {
|
} else {
|
||||||
int64_t delta = now - evstate->last;
|
QDict *data = qobject_to_qdict(qdict_get(qdict, "data"));
|
||||||
if (evstate->data ||
|
MonitorQAPIEventState key = { .event = event, .data = data };
|
||||||
delta < evstate->rate) {
|
|
||||||
/* If there's an existing event pending, replace
|
evstate = g_hash_table_lookup(monitor_qapi_event_state, &key);
|
||||||
* it with the new event, otherwise schedule a
|
assert(!evstate || timer_pending(evstate->timer));
|
||||||
* timer for delayed emission
|
|
||||||
|
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) {
|
QDECREF(evstate->qdict);
|
||||||
qobject_decref(evstate->data);
|
evstate->qdict = qdict;
|
||||||
} else {
|
QINCREF(evstate->qdict);
|
||||||
int64_t then = evstate->last + evstate->rate;
|
|
||||||
timer_mod_ns(evstate->timer, then);
|
|
||||||
}
|
|
||||||
evstate->data = QOBJECT(data);
|
|
||||||
qobject_incref(evstate->data);
|
|
||||||
} else {
|
} 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);
|
qemu_mutex_unlock(&monitor_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The callback invoked by QemuTimer when a delayed
|
* This function runs evconf->rate ns after sending a throttled
|
||||||
* event is ready to be emitted
|
* event.
|
||||||
|
* If another event has since been stored, send it.
|
||||||
*/
|
*/
|
||||||
static void monitor_qapi_event_handler(void *opaque)
|
static void monitor_qapi_event_handler(void *opaque)
|
||||||
{
|
{
|
||||||
MonitorQAPIEventState *evstate = 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,
|
trace_monitor_protocol_event_handler(evstate->event, evstate->qdict);
|
||||||
evstate->data,
|
|
||||||
evstate->last,
|
|
||||||
now);
|
|
||||||
qemu_mutex_lock(&monitor_lock);
|
qemu_mutex_lock(&monitor_lock);
|
||||||
if (evstate->data) {
|
|
||||||
monitor_qapi_event_emit(evstate->event, evstate->data);
|
if (evstate->qdict) {
|
||||||
qobject_decref(evstate->data);
|
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
||||||
evstate->data = NULL;
|
|
||||||
|
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);
|
qemu_mutex_unlock(&monitor_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static unsigned int qapi_event_throttle_hash(const void *key)
|
||||||
* @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)
|
|
||||||
{
|
{
|
||||||
MonitorQAPIEventState *evstate;
|
const MonitorQAPIEventState *evstate = key;
|
||||||
assert(event < QAPI_EVENT_MAX);
|
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);
|
return hash;
|
||||||
evstate->event = event;
|
}
|
||||||
assert(rate * SCALE_MS <= INT64_MAX);
|
|
||||||
evstate->rate = rate * SCALE_MS;
|
static gboolean qapi_event_throttle_equal(const void *a, const void *b)
|
||||||
evstate->last = 0;
|
{
|
||||||
evstate->data = NULL;
|
const MonitorQAPIEventState *eva = a;
|
||||||
evstate->timer = timer_new(QEMU_CLOCK_REALTIME,
|
const MonitorQAPIEventState *evb = b;
|
||||||
SCALE_MS,
|
|
||||||
monitor_qapi_event_handler,
|
if (eva->event != evb->event) {
|
||||||
evstate);
|
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)
|
static void monitor_qapi_event_init(void)
|
||||||
{
|
{
|
||||||
/* Limit guest-triggerable events to 1 per second */
|
monitor_qapi_event_state = g_hash_table_new(qapi_event_throttle_hash,
|
||||||
monitor_qapi_event_throttle(QAPI_EVENT_RTC_CHANGE, 1000);
|
qapi_event_throttle_equal);
|
||||||
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);
|
|
||||||
|
|
||||||
qmp_event_set_func_emit(monitor_qapi_event_queue);
|
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)
|
Error **errp)
|
||||||
{
|
{
|
||||||
QmpInputVisitor *qiv = to_qiv(v);
|
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",
|
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
||||||
"integer");
|
"integer");
|
||||||
return;
|
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,
|
static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
QmpInputVisitor *qiv = to_qiv(v);
|
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",
|
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
||||||
"boolean");
|
"boolean");
|
||||||
return;
|
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,
|
static void qmp_input_type_str(Visitor *v, char **obj, const char *name,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
QmpInputVisitor *qiv = to_qiv(v);
|
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",
|
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
||||||
"string");
|
"string");
|
||||||
return;
|
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,
|
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);
|
QmpInputVisitor *qiv = to_qiv(v);
|
||||||
QObject *qobj = qmp_input_get_object(qiv, name, true);
|
QObject *qobj = qmp_input_get_object(qiv, name, true);
|
||||||
|
QInt *qint;
|
||||||
|
QFloat *qfloat;
|
||||||
|
|
||||||
if (!qobj || (qobject_type(qobj) != QTYPE_QFLOAT &&
|
qint = qobject_to_qint(qobj);
|
||||||
qobject_type(qobj) != QTYPE_QINT)) {
|
if (qint) {
|
||||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
*obj = qint_get_int(qobject_to_qint(qobj));
|
||||||
"number");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qobject_type(qobj) == QTYPE_QINT) {
|
qfloat = qobject_to_qfloat(qobj);
|
||||||
*obj = qint_get_int(qobject_to_qint(qobj));
|
if (qfloat) {
|
||||||
} else {
|
|
||||||
*obj = qfloat_get_double(qobject_to_qfloat(qobj));
|
*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,
|
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)
|
static void process_event(JSONMessageParser *parser, QList *tokens)
|
||||||
{
|
{
|
||||||
GAState *s = container_of(parser, GAState, parser);
|
GAState *s = container_of(parser, GAState, parser);
|
||||||
QObject *obj;
|
|
||||||
QDict *qdict;
|
QDict *qdict;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
@ -581,9 +580,9 @@ static void process_event(JSONMessageParser *parser, QList *tokens)
|
|||||||
g_assert(s && parser);
|
g_assert(s && parser);
|
||||||
|
|
||||||
g_debug("process_event: called");
|
g_debug("process_event: called");
|
||||||
obj = json_parser_parse_err(tokens, NULL, &err);
|
qdict = qobject_to_qdict(json_parser_parse_err(tokens, NULL, &err));
|
||||||
if (err || !obj || qobject_type(obj) != QTYPE_QDICT) {
|
if (err || !qdict) {
|
||||||
qobject_decref(obj);
|
QDECREF(qdict);
|
||||||
qdict = qdict_new();
|
qdict = qdict_new();
|
||||||
if (!err) {
|
if (!err) {
|
||||||
g_warning("failed to parse event: unknown error");
|
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));
|
qdict_put_obj(qdict, "error", qmp_build_error_object(err));
|
||||||
error_free(err);
|
error_free(err);
|
||||||
} else {
|
|
||||||
qdict = qobject_to_qdict(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert(qdict);
|
|
||||||
|
|
||||||
/* handle host->guest commands */
|
/* handle host->guest commands */
|
||||||
if (qdict_haskey(qdict, "execute")) {
|
if (qdict_haskey(qdict, "execute")) {
|
||||||
process_command(s, qdict);
|
process_command(s, qdict);
|
||||||
|
@ -51,9 +51,9 @@ bool qbool_get_bool(const QBool *qb)
|
|||||||
*/
|
*/
|
||||||
QBool *qobject_to_qbool(const QObject *obj)
|
QBool *qobject_to_qbool(const QObject *obj)
|
||||||
{
|
{
|
||||||
if (qobject_type(obj) != QTYPE_QBOOL)
|
if (!obj || qobject_type(obj) != QTYPE_QBOOL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
return container_of(obj, QBool, base);
|
return container_of(obj, QBool, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,9 +46,9 @@ QDict *qdict_new(void)
|
|||||||
*/
|
*/
|
||||||
QDict *qobject_to_qdict(const QObject *obj)
|
QDict *qobject_to_qdict(const QObject *obj)
|
||||||
{
|
{
|
||||||
if (qobject_type(obj) != QTYPE_QDICT)
|
if (!obj || qobject_type(obj) != QTYPE_QDICT) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
return container_of(obj, QDict, base);
|
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)
|
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(qdict_get(qdict, key)));
|
||||||
return qint_get_int(qobject_to_qint(obj));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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)
|
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(qdict_get(qdict, key)));
|
||||||
return qbool_get_bool(qobject_to_qbool(obj));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -270,7 +268,7 @@ QList *qdict_get_qlist(const QDict *qdict, const char *key)
|
|||||||
*/
|
*/
|
||||||
QDict *qdict_get_qdict(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)
|
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(qdict_get(qdict, key)));
|
||||||
return qstring_get_str(qobject_to_qstring(obj));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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 qdict_get_try_int(const QDict *qdict, const char *key,
|
||||||
int64_t def_value)
|
int64_t def_value)
|
||||||
{
|
{
|
||||||
QObject *obj;
|
QInt *qint = qobject_to_qint(qdict_get(qdict, key));
|
||||||
|
|
||||||
obj = qdict_get(qdict, key);
|
return qint ? qint_get_int(qint) : def_value;
|
||||||
if (!obj || qobject_type(obj) != QTYPE_QINT)
|
|
||||||
return def_value;
|
|
||||||
|
|
||||||
return qint_get_int(qobject_to_qint(obj));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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)
|
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);
|
return qbool ? qbool_get_bool(qbool) : def_value;
|
||||||
if (!obj || qobject_type(obj) != QTYPE_QBOOL)
|
|
||||||
return def_value;
|
|
||||||
|
|
||||||
return qbool_get_bool(qobject_to_qbool(obj));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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)
|
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);
|
return qstr ? qstring_get_str(qstr) : NULL;
|
||||||
if (!obj || qobject_type(obj) != QTYPE_QSTRING)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return qstring_get_str(qobject_to_qstring(obj));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,9 +51,9 @@ double qfloat_get_double(const QFloat *qf)
|
|||||||
*/
|
*/
|
||||||
QFloat *qobject_to_qfloat(const QObject *obj)
|
QFloat *qobject_to_qfloat(const QObject *obj)
|
||||||
{
|
{
|
||||||
if (qobject_type(obj) != QTYPE_QFLOAT)
|
if (!obj || qobject_type(obj) != QTYPE_QFLOAT) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
return container_of(obj, QFloat, base);
|
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)
|
QInt *qobject_to_qint(const QObject *obj)
|
||||||
{
|
{
|
||||||
if (qobject_type(obj) != QTYPE_QINT)
|
if (!obj || qobject_type(obj) != QTYPE_QINT) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
return container_of(obj, QInt, base);
|
return container_of(obj, QInt, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,10 +142,9 @@ size_t qlist_size(const QList *qlist)
|
|||||||
*/
|
*/
|
||||||
QList *qobject_to_qlist(const QObject *obj)
|
QList *qobject_to_qlist(const QObject *obj)
|
||||||
{
|
{
|
||||||
if (qobject_type(obj) != QTYPE_QLIST) {
|
if (!obj || qobject_type(obj) != QTYPE_QLIST) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return container_of(obj, QList, base);
|
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)
|
QString *qobject_to_qstring(const QObject *obj)
|
||||||
{
|
{
|
||||||
if (qobject_type(obj) != QTYPE_QSTRING)
|
if (!obj || qobject_type(obj) != QTYPE_QSTRING) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
return container_of(obj, QString, base);
|
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
|
# monitor.c
|
||||||
handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\""
|
handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\""
|
||||||
monitor_protocol_emitter(void *mon) "mon %p"
|
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_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
|
monitor_protocol_event_throttle(uint32_t event, uint64_t rate) "event=%d rate=%" PRId64
|
||||||
|
|
||||||
# hw/net/opencores_eth.c
|
# hw/net/opencores_eth.c
|
||||||
|
Loading…
Reference in New Issue
Block a user