diff --git a/docs/qmp-events.txt b/docs/qmp-events.txt index d92cc4833b131b7b168ca77cd2876c5812ed60a8..d2f1ce497e481f31de4a81d44e2d8ab78e8b0e13 100644 --- a/docs/qmp-events.txt +++ b/docs/qmp-events.txt @@ -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. diff --git a/docs/qmp-spec.txt b/docs/qmp-spec.txt index 4c28cd943804f7762d7a5b82985ae48be2d6f619..4fb10a5d6b718829cee7889bb53675dbc051ea1d 100644 --- a/docs/qmp-spec.txt +++ b/docs/qmp-spec.txt @@ -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 ----------------------- diff --git a/include/glib-compat.h b/include/glib-compat.h index fb25f437b48316fdb5bc4bee42e5230c6c2a5342..03d8b1267518bae59e83de77ae1f602906a2deb2 100644 --- a/include/glib-compat.h +++ b/include/glib-compat.h @@ -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 { \ diff --git a/include/qapi/qmp/qbool.h b/include/qapi/qmp/qbool.h index 4aa6be3b3378a77c6f18703f8e7e0cbda6731039..d9256e4268778d06505f076c6a48ad8213d2fb44 100644 --- a/include/qapi/qmp/qbool.h +++ b/include/qapi/qmp/qbool.h @@ -18,7 +18,7 @@ #include "qapi/qmp/qobject.h" typedef struct QBool { - QObject_HEAD; + QObject base; bool value; } QBool; diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h index a37f4c1567b12c54150304a565cb975fcbf5e9df..787c658967ce3a42256d4741adaf4f55b48a9e0c 100644 --- a/include/qapi/qmp/qdict.h +++ b/include/qapi/qmp/qdict.h @@ -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; diff --git a/include/qapi/qmp/qfloat.h b/include/qapi/qmp/qfloat.h index a8658443dc206518a4748fe64f5c6757bc876485..46745e50d146ae86011a88b55571605c389085ad 100644 --- a/include/qapi/qmp/qfloat.h +++ b/include/qapi/qmp/qfloat.h @@ -18,7 +18,7 @@ #include "qapi/qmp/qobject.h" typedef struct QFloat { - QObject_HEAD; + QObject base; double value; } QFloat; diff --git a/include/qapi/qmp/qint.h b/include/qapi/qmp/qint.h index 48a41b0f2aed45bfc90e3d6838e204728bc2ee58..339a9abb8fbe860b28b6fda83806bf20c899d720 100644 --- a/include/qapi/qmp/qint.h +++ b/include/qapi/qmp/qint.h @@ -17,7 +17,7 @@ #include "qapi/qmp/qobject.h" typedef struct QInt { - QObject_HEAD; + QObject base; int64_t value; } QInt; diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h index 6cc4831df3edbdcbdae6614ad5c5ddb275923c4a..b1bf7852c5e4917465f34d85eecafa02fae5d2d3 100644 --- a/include/qapi/qmp/qlist.h +++ b/include/qapi/qmp/qlist.h @@ -22,7 +22,7 @@ typedef struct QListEntry { } QListEntry; typedef struct QList { - QObject_HEAD; + QObject base; QTAILQ_HEAD(,QListEntry) head; } QList; diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index 260d2ed3cc9dc9c91b3070aceb2b199e7abd6f57..c856f553b7efb8873431cc03350cb63d16bda0d4 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -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) diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h index 1bc3666107ca766814aa11e1b6838da30b920a59..34675a7fc03827780b18ba3265b2e63f6cd6ed98 100644 --- a/include/qapi/qmp/qstring.h +++ b/include/qapi/qmp/qstring.h @@ -17,7 +17,7 @@ #include "qapi/qmp/qobject.h" typedef struct QString { - QObject_HEAD; + QObject base; char *string; size_t length; size_t capacity; diff --git a/monitor.c b/monitor.c index 301a143ffaaa7a56d79e26f2cbdd6780347d9dc2..6cd747f4f96cc77d785f65f93c21be37d7d93890 100644 --- a/monitor.c +++ b/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); - evstate = &(monitor_qapi_event_state[event]); - trace_monitor_protocol_event_queue(event, - data, - evstate->rate, - evstate->last, - now); + assert(event < QAPI_EVENT_MAX); + evconf = &monitor_qapi_event_conf[event]; + trace_monitor_protocol_event_queue(event, qdict, evconf->rate); - /* 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; + + if (evstate->event == QAPI_EVENT_VSERPORT_CHANGE) { + hash += g_str_hash(qdict_get_str(evstate->data, "id")); + } + + return hash; +} + +static gboolean qapi_event_throttle_equal(const void *a, const void *b) +{ + const MonitorQAPIEventState *eva = a; + const MonitorQAPIEventState *evb = b; - evstate = &(monitor_qapi_event_state[event]); + 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")); + } - 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 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); } diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index 5dd9ed5ce5ac6a13ab21fd15daccd57a8495272d..eb6e110300a02bd4c9397a231161af5e5a5317a2 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -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, diff --git a/qga/main.c b/qga/main.c index 068169fcbc0b4f258fa39cad0226f3705ab20eac..d2a0ffc807f1ddf7de9f5d44f7c1697a8fed5a52 100644 --- a/qga/main.c +++ b/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); diff --git a/qobject/qbool.c b/qobject/qbool.c index 5ff69f0b2dabe1e02933c3e967dfe8177800428f..bc6535fa49a5ab2af39732d44c8a22fe751a7036 100644 --- a/qobject/qbool.c +++ b/qobject/qbool.c @@ -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); } diff --git a/qobject/qdict.c b/qobject/qdict.c index 67b1a58abfd14ec69e5cae285e1596c5421cbeb3..2d67bf157951ad50d303736ab85532c772691a12 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -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; - - obj = qdict_get(qdict, key); - if (!obj || qobject_type(obj) != QTYPE_QSTRING) - return NULL; + QString *qstr = qobject_to_qstring(qdict_get(qdict, key)); - return qstring_get_str(qobject_to_qstring(obj)); + return qstr ? qstring_get_str(qstr) : NULL; } /** diff --git a/qobject/qfloat.c b/qobject/qfloat.c index 7de0992dba7f1302cea3a0f366ba26d01e4ee2d9..c86516327f97b1d9a5bd50077d0138da23d9d212 100644 --- a/qobject/qfloat.c +++ b/qobject/qfloat.c @@ -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); } diff --git a/qobject/qint.c b/qobject/qint.c index 86b9b04f0b6214a88c223e6a3420ed7085016231..999688e9ce56ff042538120d326e16e8a5359f35 100644 --- a/qobject/qint.c +++ b/qobject/qint.c @@ -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); } diff --git a/qobject/qlist.c b/qobject/qlist.c index 1ced0de58e21467327aeb94223e4ee67bd114d1e..298003aaf761280e3e523f22cd59606d34f786ff 100644 --- a/qobject/qlist.c +++ b/qobject/qlist.c @@ -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); } diff --git a/qobject/qstring.c b/qobject/qstring.c index 607b7a142c697f5382b3418c3730980e2b8da2f0..cb72dfbfc8ca0bb0fcdf99f6b4572f8fdf135568 100644 --- a/qobject/qstring.c +++ b/qobject/qstring.c @@ -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); } diff --git a/trace-events b/trace-events index bdfe79f359704caf8e66fa609e470d489864b6c6..72136b984607b51f092225b74f103c69816436d4 100644 --- a/trace-events +++ b/trace-events @@ -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