mirror of https://gitee.com/openkylin/qemu.git
monitor: Throttle event VSERPORT_CHANGE separately by "id"
VSERPORT_CHANGE is emitted when the guest opens or closes a virtio-serial port. The event's member "id" identifies the port. When several events arrive quickly, throttling drops all but the last of them. Because of that, a QMP client must assume that *any* port may have changed state when it receives a VSERPORT_CHANGE event and throttling may have happened. Make the event more useful by throttling it for each port separately. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <1444921716-9511-7-git-send-email-armbru@redhat.com>
This commit is contained in:
parent
a24712af54
commit
7de0be6573
27
monitor.c
27
monitor.c
|
@ -181,7 +181,8 @@ typedef struct {
|
||||||
* instance.
|
* instance.
|
||||||
*/
|
*/
|
||||||
typedef struct MonitorQAPIEventState {
|
typedef struct MonitorQAPIEventState {
|
||||||
QAPIEvent event; /* Event being tracked */
|
QAPIEvent event; /* Throttling state for this event type and... */
|
||||||
|
QDict *data; /* ... data, see qapi_event_throttle_equal() */
|
||||||
QEMUTimer *timer; /* Timer for handling delayed events */
|
QEMUTimer *timer; /* Timer for handling delayed events */
|
||||||
QDict *qdict; /* Delayed event (if any) */
|
QDict *qdict; /* Delayed event (if any) */
|
||||||
} MonitorQAPIEventState;
|
} MonitorQAPIEventState;
|
||||||
|
@ -490,7 +491,8 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
|
||||||
/* Unthrottled event */
|
/* Unthrottled event */
|
||||||
monitor_qapi_event_emit(event, qdict);
|
monitor_qapi_event_emit(event, qdict);
|
||||||
} else {
|
} else {
|
||||||
MonitorQAPIEventState key = { .event = event };
|
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);
|
evstate = g_hash_table_lookup(monitor_qapi_event_state, &key);
|
||||||
assert(!evstate || timer_pending(evstate->timer));
|
assert(!evstate || timer_pending(evstate->timer));
|
||||||
|
@ -517,6 +519,8 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp)
|
||||||
|
|
||||||
evstate = g_new(MonitorQAPIEventState, 1);
|
evstate = g_new(MonitorQAPIEventState, 1);
|
||||||
evstate->event = event;
|
evstate->event = event;
|
||||||
|
evstate->data = data;
|
||||||
|
QINCREF(evstate->data);
|
||||||
evstate->qdict = NULL;
|
evstate->qdict = NULL;
|
||||||
evstate->timer = timer_new_ns(QEMU_CLOCK_REALTIME,
|
evstate->timer = timer_new_ns(QEMU_CLOCK_REALTIME,
|
||||||
monitor_qapi_event_handler,
|
monitor_qapi_event_handler,
|
||||||
|
@ -551,6 +555,7 @@ static void monitor_qapi_event_handler(void *opaque)
|
||||||
timer_mod_ns(evstate->timer, now + evconf->rate);
|
timer_mod_ns(evstate->timer, now + evconf->rate);
|
||||||
} else {
|
} else {
|
||||||
g_hash_table_remove(monitor_qapi_event_state, evstate);
|
g_hash_table_remove(monitor_qapi_event_state, evstate);
|
||||||
|
QDECREF(evstate->data);
|
||||||
timer_free(evstate->timer);
|
timer_free(evstate->timer);
|
||||||
g_free(evstate);
|
g_free(evstate);
|
||||||
}
|
}
|
||||||
|
@ -561,8 +566,13 @@ static void monitor_qapi_event_handler(void *opaque)
|
||||||
static unsigned int qapi_event_throttle_hash(const void *key)
|
static unsigned int qapi_event_throttle_hash(const void *key)
|
||||||
{
|
{
|
||||||
const MonitorQAPIEventState *evstate = key;
|
const MonitorQAPIEventState *evstate = key;
|
||||||
|
unsigned int hash = evstate->event * 255;
|
||||||
|
|
||||||
return 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)
|
static gboolean qapi_event_throttle_equal(const void *a, const void *b)
|
||||||
|
@ -570,7 +580,16 @@ static gboolean qapi_event_throttle_equal(const void *a, const void *b)
|
||||||
const MonitorQAPIEventState *eva = a;
|
const MonitorQAPIEventState *eva = a;
|
||||||
const MonitorQAPIEventState *evb = b;
|
const MonitorQAPIEventState *evb = b;
|
||||||
|
|
||||||
return eva->event == evb->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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void monitor_qapi_event_init(void)
|
static void monitor_qapi_event_init(void)
|
||||||
|
|
Loading…
Reference in New Issue