From: Markus Armbruster <armbru@redhat.com>
To: marcandre.lureau@redhat.com
Cc: amit.shah@redhat.com, lersek@redhat.com, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 1/3] monitor: split MonitorQAPIEventState
Date: Wed, 16 Sep 2015 15:57:51 +0200 [thread overview]
Message-ID: <87bnd2qxeo.fsf@blackfin.pond.sub.org> (raw)
In-Reply-To: <1441192183-4812-2-git-send-email-marcandre.lureau@redhat.com> (marcandre lureau's message of "Wed, 2 Sep 2015 13:09:41 +0200")
marcandre.lureau@redhat.com writes:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Create a separate pending event structure MonitorQAPIEventPending.
> Use a MonitorQAPIEventDelay callback to handle the delaying. This
> allows other implementations of throttling.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> monitor.c | 124 +++++++++++++++++++++++++++++++++++++----------------------
> trace-events | 2 +-
> 2 files changed, 79 insertions(+), 47 deletions(-)
>
> diff --git a/monitor.c b/monitor.c
> index fc32f12..0a6a16a 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -170,18 +170,27 @@ 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;
"MonitorQAPIEventPending" sounds like the name of a predicate "is an
event pending?" MonitorQAPIPendingEvent?
> +
> +typedef struct MonitorQAPIEventState MonitorQAPIEventState;
> +
> +typedef bool (*MonitorQAPIEventDelay) (MonitorQAPIEventState *evstate,
> + QDict *data);
Style nit: we don't normally have space before an argument list.
> /*
> * 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;
> + MonitorQAPIEventDelay delay;
Since your commit message is so sparse, I have to actually think to
figure out how this patch works. To think, I have to write. And when I
write, I can just as well send it out, so you can correct my thinking.
If you want less verbose reviews from me, try writing more verbose
commit messages :)
Obvious: event, last, timer and data move into MonitorQAPIEventDelay.
Not obvious (yet): how to reach them. Read on and see, I guess.
> + void *data;
What does data point to?
Why does it have to be void *?
> +};
>
> struct Monitor {
> CharDriverState *chr;
> @@ -452,6 +461,39 @@ static void monitor_qapi_event_emit(QAPIEvent event, QObject *data)
> }
> }
>
> +static bool
> +monitor_qapi_event_delay(MonitorQAPIEventState *evstate, 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 */
> + if (!evstate->rate) {
> + 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 {
> + 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;
> +}
> +
Okay, this is the part of monitor_qapi_event_queue() protected by the
lock, less the monitor_qapi_event_emit(), with the move of last, time
and data from evstate to p squashed in, and the computation of delta
moved up some. Would be easier to review if you did the transformations
in separate patches.
Could use a function comment, because the return value isn't obvious.
Also: too many things are named "data" for my taste.
> /*
> * Queue a new event for emission to Monitor instances,
> * applying any rate limiting if required.
> @@ -467,35 +509,15 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *data, Error **errp)
> trace_monitor_protocol_event_queue(event,
> data,
> evstate->rate,
> - evstate->last,
> now);
Should monitor_qapi_event_delay() trace evstate->last to compensate?
>
> - /* Rate limit of 0 indicates no throttling */
> qemu_mutex_lock(&monitor_lock);
> - if (!evstate->rate) {
> +
> + if (!evstate->delay ||
> + !evstate->delay(evstate, data)) {
Sure evstate->delay can be null?
> monitor_qapi_event_emit(event, QOBJECT(data));
> - evstate->last = now;
> - } else {
> - int64_t delta = now - evstate->last;
> - if (evstate->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);
> - } else {
> - int64_t then = evstate->last + evstate->rate;
> - timer_mod_ns(evstate->timer, then);
> - }
> - evstate->data = QOBJECT(data);
> - qobject_incref(evstate->data);
> - } else {
> - monitor_qapi_event_emit(event, QOBJECT(data));
> - evstate->last = now;
> - }
> }
> +
> qemu_mutex_unlock(&monitor_lock);
> }
>
> @@ -505,23 +527,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
> @@ -539,15 +575,11 @@ monitor_qapi_event_throttle(QAPIEvent event, int64_t rate)
> 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 = monitor_qapi_event_delay;
> + evstate->data = monitor_qapi_event_pending_new(event);
> }
>
> static void monitor_qapi_event_init(void)
All right, the moved members end up in evstate->data, and we now
indirect the interesting part of monitor_qapi_event_queue() through
evstate->delay.
Why this is useful isn't obvious, yet. The only clue I have is the
commit message's "This allows other implementations of throttling." I'd
add something like "The next few commits will add one."
> diff --git a/trace-events b/trace-events
> index 8f9614a..b1ea596 100644
> --- a/trace-events
> +++ b/trace-events
> @@ -1028,7 +1028,7 @@ 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_queue(uint32_t event, void *data, uint64_t rate, uint64_t now) "event=%d data=%p rate=%" PRId64 " now=%" PRId64
> monitor_protocol_event_throttle(uint32_t event, uint64_t rate) "event=%d rate=%" PRId64
>
> # hw/net/opencores_eth.c
next prev parent reply other threads:[~2015-09-16 13:58 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-02 11:09 [Qemu-devel] [PATCH 0/3] monitor: throttle VSERPORT_CHANGED by "id" marcandre.lureau
2015-09-02 11:09 ` [Qemu-devel] [PATCH 1/3] monitor: split MonitorQAPIEventState marcandre.lureau
2015-09-10 8:34 ` Daniel P. Berrange
2015-09-16 13:57 ` Markus Armbruster [this message]
2015-09-17 13:17 ` Marc-André Lureau
2015-09-02 11:09 ` [Qemu-devel] [PATCH 2/3] monitor: throttle QAPI_EVENT_VSERPORT_CHANGE by "id" marcandre.lureau
2015-09-10 8:35 ` Daniel P. Berrange
2015-09-16 16:40 ` Markus Armbruster
2015-09-17 11:28 ` Marc-André Lureau
2015-09-17 14:06 ` Marc-André Lureau
2015-09-02 11:09 ` [Qemu-devel] [PATCH 3/3] monitor: remove old entries from event hash table marcandre.lureau
2015-09-10 8:35 ` Daniel P. Berrange
2015-09-16 16:50 ` Markus Armbruster
2015-09-17 14:43 ` Marc-André Lureau
2015-09-08 10:18 ` [Qemu-devel] [PATCH 0/3] monitor: throttle VSERPORT_CHANGED by "id" Marc-André Lureau
2015-09-10 4:22 ` Amit Shah
2015-09-10 6:46 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87bnd2qxeo.fsf@blackfin.pond.sub.org \
--to=armbru@redhat.com \
--cc=amit.shah@redhat.com \
--cc=lersek@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.