From: Marc-André Lureau <[email protected]> Do not let the hash table grow without limit, schedule a cleanup for outdated event.
Signed-off-by: Marc-André Lureau <[email protected]> --- monitor.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/monitor.c b/monitor.c index 90f06ce..a81341f 100644 --- a/monitor.c +++ b/monitor.c @@ -541,7 +541,7 @@ static void monitor_qapi_event_handler(void *opaque) } static MonitorQAPIEventPending * -monitor_qapi_event_pending_new(QAPIEvent event) +monitor_qapi_event_pending_new(QAPIEvent event, QEMUTimerCB *handler) { MonitorQAPIEventPending *p; @@ -549,11 +549,52 @@ monitor_qapi_event_pending_new(QAPIEvent event) p->event = event; p->timer = timer_new(QEMU_CLOCK_REALTIME, SCALE_MS, - monitor_qapi_event_handler, + handler, p); return p; } +static void monitor_qapi_event_id_remove(MonitorQAPIEventPending *p) +{ + MonitorQAPIEventState *s = &monitor_qapi_event_state[p->event]; + GHashTable *ht = s->delay_data; + GHashTableIter iter; + gpointer value; + + g_hash_table_iter_init(&iter, ht); + while (g_hash_table_iter_next(&iter, NULL, &value)) { + if (value == p) { + g_hash_table_iter_remove(&iter); + return; + } + } +} + +/* + * do not let the hash table grow, if no later pending event + * scheduled, remove the old entry after rate timeout. + */ +static void monitor_qapi_event_id_schedule_remove(MonitorQAPIEventPending *p) +{ + MonitorQAPIEventState *s = &monitor_qapi_event_state[p->event]; + int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); + int64_t then = now + s->rate; + + timer_mod_ns(p->timer, then); +} + +static void monitor_qapi_event_id_handler(void *opaque) +{ + MonitorQAPIEventPending *p = opaque; + + if (p->qdict) { + monitor_qapi_event_handler(p); + monitor_qapi_event_id_schedule_remove(p); + } else { + monitor_qapi_event_id_remove(p); + } +} + /* * A delay handler that will filter events by the "id" event field. * evstate must be an element of the monitor_qapi_event_state array. @@ -571,11 +612,17 @@ monitor_qapi_event_id_delay(MonitorQAPIEventState *evstate, QDict *qdict) assert(event >= 0 || event < QAPI_EVENT_MAX); if (!p) { - p = monitor_qapi_event_pending_new(event); + p = monitor_qapi_event_pending_new(event, + monitor_qapi_event_id_handler); g_hash_table_insert(ht, g_strdup(id), p); } - return monitor_qapi_event_pending_update(evstate, p, qdict); + if (monitor_qapi_event_pending_update(evstate, p, qdict)) { + return true; + } else { + monitor_qapi_event_id_schedule_remove(p); + return false; + } } /* @@ -631,7 +678,8 @@ monitor_qapi_event_throttle(QAPIEvent event, int64_t rate) evstate->rate = rate * SCALE_MS; evstate->delay = monitor_qapi_event_delay; - evstate->delay_data = monitor_qapi_event_pending_new(event); + evstate->delay_data = + monitor_qapi_event_pending_new(event, monitor_qapi_event_handler); } static void -- 2.4.3
