From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52033) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zcbk3-0007cj-TK for qemu-devel@nongnu.org; Thu, 17 Sep 2015 12:09:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Zcbk2-00050H-Qc for qemu-devel@nongnu.org; Thu, 17 Sep 2015 12:08:59 -0400 Received: from mail-qg0-x236.google.com ([2607:f8b0:400d:c04::236]:35704) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zcbk2-000502-Le for qemu-devel@nongnu.org; Thu, 17 Sep 2015 12:08:58 -0400 Received: by qgt47 with SMTP id 47so16596532qgt.2 for ; Thu, 17 Sep 2015 09:08:58 -0700 (PDT) Sender: =?UTF-8?B?TWFyYy1BbmRyw6kgTHVyZWF1?= From: marcandre.lureau@redhat.com Date: Thu, 17 Sep 2015 18:08:46 +0200 Message-Id: <1442506130-15219-2-git-send-email-marcandre.lureau@redhat.com> 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 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subject: [Qemu-devel] [PATCH v2 1/5] monitor: split MonitorQAPIEventState List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: armbru@redhat.com, amit.shah@redhat.com, =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , lersek@redhat.com From: Marc-André Lureau Create a separate structure MonitorQAPIEventPending for holding the data related to pending event. The next commits are going to reuse this structure for different throttling implementations. Signed-off-by: Marc-André Lureau --- monitor.c | 85 +++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 35 deletions(-) diff --git a/monitor.c b/monitor.c index 1f43263..2d2e030 100644 --- a/monitor.c +++ b/monitor.c @@ -174,18 +174,24 @@ typedef struct { bool in_command_mode; /* are we in command mode? */ } MonitorQMP; +typedef struct { + QAPIEvent event; /* Event being tracked */ + int64_t last; /* QEMU_CLOCK_REALTIME value at last emission */ + QEMUTimer *timer; /* Timer for handling delayed events */ + QObject *data; /* Event pending delayed dispatch */ +} MonitorQAPIEventPending; + +typedef struct MonitorQAPIEventState MonitorQAPIEventState; + /* * To prevent flooding clients, events can be throttled. The * throttling is calculated globally, rather than per-Monitor * instance. */ -typedef struct MonitorQAPIEventState { - QAPIEvent event; /* Event being tracked */ +struct MonitorQAPIEventState { int64_t rate; /* Minimum time (in ns) between two events */ - int64_t last; /* QEMU_CLOCK_REALTIME value at last emission */ - QEMUTimer *timer; /* Timer for handling delayed events */ - QObject *data; /* Event pending delayed dispatch */ -} MonitorQAPIEventState; + void *delay_data; /* data for the throttle handler */ +}; struct Monitor { CharDriverState *chr; @@ -464,40 +470,41 @@ static void monitor_qapi_event_queue(QAPIEvent event, QDict *data, Error **errp) { MonitorQAPIEventState *evstate; + MonitorQAPIEventPending *p; assert(event < QAPI_EVENT_MAX); int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - evstate = &(monitor_qapi_event_state[event]); + evstate = &monitor_qapi_event_state[event]; + p = evstate->delay_data; trace_monitor_protocol_event_queue(event, data, evstate->rate, - evstate->last, + 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)); - evstate->last = now; } else { - int64_t delta = now - evstate->last; - if (evstate->data || + 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->data) { - qobject_decref(evstate->data); + if (evstate->delay_data) { + qobject_decref(evstate->delay_data); } else { - int64_t then = evstate->last + evstate->rate; - timer_mod_ns(evstate->timer, then); + int64_t then = p->last + evstate->rate; + timer_mod_ns(p->timer, then); } - evstate->data = QOBJECT(data); - qobject_incref(evstate->data); + evstate->delay_data = QOBJECT(data); + qobject_incref(evstate->delay_data); } else { monitor_qapi_event_emit(event, QOBJECT(data)); - evstate->last = now; + p->last = now; } } qemu_mutex_unlock(&monitor_lock); @@ -509,23 +516,37 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *data, Error **errp) */ static void monitor_qapi_event_handler(void *opaque) { - MonitorQAPIEventState *evstate = opaque; + MonitorQAPIEventPending *p = opaque; int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - trace_monitor_protocol_event_handler(evstate->event, - evstate->data, - evstate->last, + trace_monitor_protocol_event_handler(p->event, + p->data, + p->last, now); qemu_mutex_lock(&monitor_lock); - if (evstate->data) { - monitor_qapi_event_emit(evstate->event, evstate->data); - qobject_decref(evstate->data); - evstate->data = NULL; + if (p->data) { + monitor_qapi_event_emit(p->event, p->data); + qobject_decref(p->data); + p->data = NULL; } - evstate->last = now; + p->last = now; qemu_mutex_unlock(&monitor_lock); } +static MonitorQAPIEventPending * +monitor_qapi_event_pending_new(QAPIEvent event) +{ + MonitorQAPIEventPending *p; + + p = g_new0(MonitorQAPIEventPending, 1); + p->event = event; + p->timer = timer_new(QEMU_CLOCK_REALTIME, + SCALE_MS, + monitor_qapi_event_handler, + p); + return p; +} + /* * @event: the event ID to be limited * @rate: the rate limit in milliseconds @@ -540,18 +561,12 @@ monitor_qapi_event_throttle(QAPIEvent event, int64_t rate) MonitorQAPIEventState *evstate; assert(event < QAPI_EVENT_MAX); - evstate = &(monitor_qapi_event_state[event]); + evstate = &monitor_qapi_event_state[event]; trace_monitor_protocol_event_throttle(event, rate); - evstate->event = event; assert(rate * SCALE_MS <= INT64_MAX); evstate->rate = rate * SCALE_MS; - evstate->last = 0; - evstate->data = NULL; - evstate->timer = timer_new(QEMU_CLOCK_REALTIME, - SCALE_MS, - monitor_qapi_event_handler, - evstate); + evstate->delay_data = monitor_qapi_event_pending_new(event); } static void monitor_qapi_event_init(void) -- 2.4.3