From patchwork Thu Sep 17 16:08:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 518926 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 2EC5C141739 for ; Fri, 18 Sep 2015 02:12:21 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=Hi61C29h; dkim-atps=neutral Received: from localhost ([::1]:59715 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZcbnH-0003zx-Di for incoming@patchwork.ozlabs.org; Thu, 17 Sep 2015 12:12:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52113) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZcbkE-0007vS-UI for qemu-devel@nongnu.org; Thu, 17 Sep 2015 12:09:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZcbkD-00053u-OR for qemu-devel@nongnu.org; Thu, 17 Sep 2015 12:09:10 -0400 Received: from mail-qg0-x22e.google.com ([2607:f8b0:400d:c04::22e]:35727) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZcbkD-00053m-Gv for qemu-devel@nongnu.org; Thu, 17 Sep 2015 12:09:09 -0400 Received: by qgt47 with SMTP id 47so16601141qgt.2 for ; Thu, 17 Sep 2015 09:09:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=orZaT2ugD9vkCZnir1LjrlcZDw55GPdAh2u34pVtTTU=; b=Hi61C29hcBlIvfJCpwngrekKsf8vpegmO5kvYFLiLSISPvVq+cQe44Lp6u0cE4pcXO dfi+yNf7/Bjndkc97oFq2uLsMLR8Wvxkm8fYLZ3fzNJPCjyQqYqg6WEnxoawe/S9VbmK lsc0q2WQLNgtzUT2PWVvL0nQvlIXtumJPj4ms7xkIzlbLwZm0bOxytBFYzD++TdvzEI5 oaQIhzUIBH63bFMTGRPixSqe6z1b90Vh8E6VYvVZjpyVW81wvQVAOILQljERIyEpVRHh byhONNNPcGwYkDO1qCSJs0zo78Ao5JQBQfy7f5XQIFfwnRvvy1rSBfwKT4PFhcugZow0 0QpQ== X-Received: by 10.140.217.70 with SMTP id n67mr54155854qhb.96.1442506149066; Thu, 17 Sep 2015 09:09:09 -0700 (PDT) Received: from localhost (bne75-h02-31-39-163-232.dsl.sta.abo.bbox.fr. [31.39.163.232]) by smtp.gmail.com with ESMTPSA id c7sm1570360qgc.2.2015.09.17.09.09.07 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Sep 2015 09:09:08 -0700 (PDT) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Date: Thu, 17 Sep 2015 18:08:49 +0200 Message-Id: <1442506130-15219-5-git-send-email-marcandre.lureau@redhat.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1442506130-15219-1-git-send-email-marcandre.lureau@redhat.com> References: <1442506130-15219-1-git-send-email-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:400d:c04::22e Cc: armbru@redhat.com, amit.shah@redhat.com, =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , lersek@redhat.com Subject: [Qemu-devel] [PATCH v2 4/5] monitor: throttle QAPI_EVENT_VSERPORT_CHANGE by "id" X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 Reviewed-by: Eric Blake Reviewed-by: Daniel P. Berrange --- monitor.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 23 deletions(-) diff --git a/monitor.c b/monitor.c index 2f8af5b..90f06ce 100644 --- a/monitor.c +++ b/monitor.c @@ -472,10 +472,10 @@ static void monitor_qapi_event_emit(QAPIEvent event, QObject *data) * Return 'false' if the event is not delayed and can be emitted now. */ static bool -monitor_qapi_event_delay(MonitorQAPIEventState *evstate, QDict *qdict) +monitor_qapi_event_pending_update(MonitorQAPIEventState *evstate, + MonitorQAPIEventPending *p, QDict *qdict) { int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - MonitorQAPIEventPending *p = evstate->delay_data; int64_t delta = now - p->last; trace_monitor_protocol_event_delay(p->event, @@ -510,27 +510,11 @@ monitor_qapi_event_delay(MonitorQAPIEventState *evstate, QDict *qdict) 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 *qdict, Error **errp) +static bool +monitor_qapi_event_delay(MonitorQAPIEventState *evstate, QDict *qdict) { - MonitorQAPIEventState *evstate; - assert(event < QAPI_EVENT_MAX); - - evstate = &monitor_qapi_event_state[event]; - trace_monitor_protocol_event_queue(event, qdict); - - qemu_mutex_lock(&monitor_lock); - - if (!evstate->delay || - !evstate->delay(evstate, qdict)) { - monitor_qapi_event_emit(event, QOBJECT(qdict)); - } - - qemu_mutex_unlock(&monitor_lock); + return monitor_qapi_event_pending_update(evstate, + evstate->delay_data, qdict); } /* @@ -571,6 +555,62 @@ monitor_qapi_event_pending_new(QAPIEvent event) } /* + * A delay handler that will filter events by the "id" event field. + * evstate must be an element of the monitor_qapi_event_state array. + * + * Return 'false' if the event is not delayed and can be emitted now. + */ +static bool +monitor_qapi_event_id_delay(MonitorQAPIEventState *evstate, QDict *qdict) +{ + GHashTable *ht = evstate->delay_data; + QDict *data = qdict_get_qdict(qdict, "data"); + const char *id = qdict_get_str(data, "id"); + MonitorQAPIEventPending *p = g_hash_table_lookup(ht, id); + QAPIEvent event = evstate - monitor_qapi_event_state; + assert(event >= 0 || event < QAPI_EVENT_MAX); + + 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, qdict); +} + +/* + * Queue a new event for emission to Monitor instances, + * applying any rate limiting if required. + */ +static void +monitor_qapi_event_queue(QAPIEvent event, QDict *qdict, Error **errp) +{ + MonitorQAPIEventState *evstate; + assert(event < QAPI_EVENT_MAX); + + evstate = &(monitor_qapi_event_state[event]); + trace_monitor_protocol_event_queue(event, qdict); + + qemu_mutex_lock(&monitor_lock); + + if (!evstate->delay || + !evstate->delay(evstate, qdict)) { + monitor_qapi_event_emit(event, QOBJECT(qdict)); + } + + qemu_mutex_unlock(&monitor_lock); +} + +static void +monitor_qapi_event_pending_free(MonitorQAPIEventPending *p) +{ + qobject_decref(p->qdict); + timer_del(p->timer); + timer_free(p->timer); + g_free(p); +} + +/* * @event: the event ID to be limited * @rate: the rate limit in milliseconds * @@ -594,6 +634,24 @@ monitor_qapi_event_throttle(QAPIEvent event, int64_t rate) evstate->delay_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->delay_data = + g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + (GDestroyNotify)monitor_qapi_event_pending_free); +} + static void monitor_qapi_event_init(void) { /* Limit guest-triggerable events to 1 per second */ @@ -602,7 +660,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); }