From: Marc-André Lureau <marcandre.lur...@redhat.com> Move the delay handling in a seperate function that can be changed for different throttling implementations, as will be done in following commits.
Signed-off-by: Marc-André Lureau <marcandre.lur...@redhat.com> --- monitor.c | 85 +++++++++++++++++++++++++++++++++++++++--------------------- trace-events | 3 ++- 2 files changed, 57 insertions(+), 31 deletions(-) diff --git a/monitor.c b/monitor.c index 2d2e030..e78ecc2 100644 --- a/monitor.c +++ b/monitor.c @@ -183,6 +183,8 @@ typedef struct { typedef struct MonitorQAPIEventState MonitorQAPIEventState; +typedef bool (*MonitorQAPIEventDelay)(MonitorQAPIEventState *evstate, + QDict *data); /* * To prevent flooding clients, events can be throttled. The * throttling is calculated globally, rather than per-Monitor @@ -190,6 +192,7 @@ typedef struct MonitorQAPIEventState MonitorQAPIEventState; */ struct MonitorQAPIEventState { int64_t rate; /* Minimum time (in ns) between two events */ + MonitorQAPIEventDelay delay; void *delay_data; /* data for the throttle handler */ }; @@ -463,50 +466,70 @@ static void monitor_qapi_event_emit(QAPIEvent event, QObject *data) } /* - * Queue a new event for emission to Monitor instances, - * applying any rate limiting if required. + * A simple delay handler, that will delay all events according to the + * evstate->rate limit. + * + * Return 'false' if the event is not delayed and can be emitted now. */ -static void -monitor_qapi_event_queue(QAPIEvent event, QDict *data, Error **errp) +static bool +monitor_qapi_event_delay(MonitorQAPIEventState *evstate, QDict *data) { - MonitorQAPIEventState *evstate; - MonitorQAPIEventPending *p; - assert(event < QAPI_EVENT_MAX); int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); + MonitorQAPIEventPending *p = evstate->delay_data; + int64_t delta = now - p->last; - evstate = &monitor_qapi_event_state[event]; - p = evstate->delay_data; - trace_monitor_protocol_event_queue(event, + trace_monitor_protocol_event_delay(p->event, data, evstate->rate, p->last, now); /* Rate limit of 0 indicates no throttling */ - qemu_mutex_lock(&monitor_lock); if (!evstate->rate) { - monitor_qapi_event_emit(event, QOBJECT(data)); - } else { - int64_t delta = now - p->last; - if (evstate->delay_data || - delta < evstate->rate) { - /* If there's an existing event pending, replace - * it with the new event, otherwise schedule a - * timer for delayed emission - */ - if (evstate->delay_data) { - qobject_decref(evstate->delay_data); - } else { - int64_t then = p->last + evstate->rate; - timer_mod_ns(p->timer, then); - } - evstate->delay_data = QOBJECT(data); - qobject_incref(evstate->delay_data); + p->last = now; + return false; + } + + if (p->data || delta < evstate->rate) { + /* If there's an existing event pending, replace + * it with the new event, otherwise schedule a + * timer for delayed emission + */ + if (p->data) { + qobject_decref(p->data); } else { - monitor_qapi_event_emit(event, QOBJECT(data)); - p->last = now; + int64_t then = p->last + evstate->rate; + timer_mod_ns(p->timer, then); } + p->data = QOBJECT(data); + qobject_incref(p->data); + return true; } + + p->last = now; + return false; +} + +/* + * 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) +{ + MonitorQAPIEventState *evstate; + assert(event < QAPI_EVENT_MAX); + + evstate = &monitor_qapi_event_state[event]; + trace_monitor_protocol_event_queue(event, data); + + qemu_mutex_lock(&monitor_lock); + + if (!evstate->delay || + !evstate->delay(evstate, data)) { + monitor_qapi_event_emit(event, QOBJECT(data)); + } + qemu_mutex_unlock(&monitor_lock); } @@ -566,6 +589,8 @@ monitor_qapi_event_throttle(QAPIEvent event, int64_t rate) trace_monitor_protocol_event_throttle(event, rate); assert(rate * SCALE_MS <= INT64_MAX); evstate->rate = rate * SCALE_MS; + + evstate->delay = monitor_qapi_event_delay; evstate->delay_data = monitor_qapi_event_pending_new(event); } diff --git a/trace-events b/trace-events index 88a2f14..20eb8bf 100644 --- a/trace-events +++ b/trace-events @@ -1035,7 +1035,8 @@ 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_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_delay(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 *data) "event=%d data=%p" monitor_protocol_event_throttle(uint32_t event, uint64_t rate) "event=%d rate=%" PRId64 # hw/net/opencores_eth.c -- 2.4.3