From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54868) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZPbyX-0007z5-GP for qemu-devel@nongnu.org; Wed, 12 Aug 2015 15:46:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZPbyW-0002Ur-4T for qemu-devel@nongnu.org; Wed, 12 Aug 2015 15:46:13 -0400 Received: from mail-qg0-x22b.google.com ([2607:f8b0:400d:c04::22b]:35106) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZPbyV-0002Uf-VF for qemu-devel@nongnu.org; Wed, 12 Aug 2015 15:46:12 -0400 Received: by qgj62 with SMTP id 62so17925840qgj.2 for ; Wed, 12 Aug 2015 12:46:11 -0700 (PDT) Sender: =?UTF-8?B?TWFyYy1BbmRyw6kgTHVyZWF1?= From: marcandre.lureau@redhat.com Date: Wed, 12 Aug 2015 21:46:02 +0200 Message-Id: <1439408763-12785-3-git-send-email-marcandre.lureau@redhat.com> In-Reply-To: <1439408763-12785-1-git-send-email-marcandre.lureau@redhat.com> References: <1439408763-12785-1-git-send-email-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subject: [Qemu-devel] [RFC 2/3] monitor: throttle QAPI_EVENT_VSERPORT_CHANGE by "id" List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: lersek@redhat.com, =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= From: Marc-André Lureau Use a hash table to lookup the pending event corresponding to the "id" field. The hash table may grow without limit here, the following patch will add some cleaning. Signed-off-by: Marc-André Lureau --- monitor.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 26 deletions(-) diff --git a/monitor.c b/monitor.c index 9c51ffa..7334ffb 100644 --- a/monitor.c +++ b/monitor.c @@ -462,10 +462,10 @@ static void monitor_qapi_event_emit(QAPIEvent event, QObject *data) } static bool -monitor_qapi_event_delay(MonitorQAPIEventState *evstate, QDict *data) +monitor_qapi_event_pending_update(MonitorQAPIEventState *evstate, + MonitorQAPIEventPending *p, QDict *data) { int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - MonitorQAPIEventPending *p = evstate->data; int64_t delta = now - p->last; /* Rate limit of 0 indicates no throttling */ @@ -494,31 +494,13 @@ monitor_qapi_event_delay(MonitorQAPIEventState *evstate, QDict *data) 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); - 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, - now); - qemu_mutex_lock(&monitor_lock); - - if (!evstate->delay || - !evstate->delay(evstate, data)) { - monitor_qapi_event_emit(event, QOBJECT(data)); - } +static bool +monitor_qapi_event_delay(MonitorQAPIEventState *evstate, QDict *data) +{ + MonitorQAPIEventPending *p = evstate->data; - qemu_mutex_unlock(&monitor_lock); + return monitor_qapi_event_pending_update(evstate, p, data); } /* @@ -558,6 +540,58 @@ monitor_qapi_event_pending_new(QAPIEvent event) return p; } +static bool +monitor_qapi_event_id_delay(MonitorQAPIEventState *evstate, QDict *data) +{ + GHashTable *ht = evstate->data; + QDict *s = qdict_get_qdict(data, "data"); + const char *id = qdict_get_str(s, "id"); + MonitorQAPIEventPending *p = g_hash_table_lookup(ht, id); + QAPIEvent event = evstate - monitor_qapi_event_state; + + if (!p) { + p = monitor_qapi_event_pending_new(event); + g_hash_table_insert(ht, g_strdup(id), p); + } + + return monitor_qapi_event_pending_update(evstate, p, data); +} + +/* + * 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); + 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, + now); + + qemu_mutex_lock(&monitor_lock); + + if (!evstate->delay || + !evstate->delay(evstate, data)) { + monitor_qapi_event_emit(event, QOBJECT(data)); + } + + qemu_mutex_unlock(&monitor_lock); +} + +static void +monitor_qapi_event_pending_free(MonitorQAPIEventPending *p) +{ + timer_del(p->timer); + timer_free(p->timer); + g_free(p); +} + /* * @event: the event ID to be limited * @rate: the rate limit in milliseconds @@ -582,6 +616,24 @@ monitor_qapi_event_throttle(QAPIEvent event, int64_t rate) evstate->data = monitor_qapi_event_pending_new(event); } +static void +monitor_qapi_event_id_throttle(QAPIEvent event, int64_t rate) +{ + MonitorQAPIEventState *evstate; + assert(event < QAPI_EVENT_MAX); + + evstate = &(monitor_qapi_event_state[event]); + + trace_monitor_protocol_event_throttle(event, rate); + assert(rate * SCALE_MS <= INT64_MAX); + evstate->rate = rate * SCALE_MS; + + evstate->delay = monitor_qapi_event_id_delay; + evstate->data = + g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + (GDestroyNotify)monitor_qapi_event_pending_free); +} + static void monitor_qapi_event_init(void) { /* Limit guest-triggerable events to 1 per second */ @@ -590,7 +642,7 @@ static void monitor_qapi_event_init(void) 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_id_throttle(QAPI_EVENT_VSERPORT_CHANGE, 1000); qmp_event_set_func_emit(monitor_qapi_event_queue); } -- 2.4.3