qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 1/3] monitor: split MonitorQAPIEventState


From: Marc-André Lureau
Subject: Re: [Qemu-devel] [PATCH 1/3] monitor: split MonitorQAPIEventState
Date: Thu, 17 Sep 2015 15:17:00 +0200

Hi

On Wed, Sep 16, 2015 at 3:57 PM, Markus Armbruster <address@hidden> wrote:
> address@hidden writes:
>
>> From: Marc-André Lureau <address@hidden>
>>
>> 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 <address@hidden>
>> ---
>>  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?

I prefer to keep the 'QAPIEvent' together like the rest of the types.
I don't mind changing it though if you think it's a bad idea

>
>> +
>> +typedef struct MonitorQAPIEventState MonitorQAPIEventState;
>> +
>> +typedef bool (*MonitorQAPIEventDelay) (MonitorQAPIEventState *evstate,
>> +                                       QDict *data);
>
> Style nit: we don't normally have space before an argument list.
>

fixed

>>  /*
>>   * 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 :)

ok

>
> 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 *?

to allow other kind of throttling implementation and their own data,
I'll rename it and add a comment.

>
>> +};
>>
>>  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.
>

ok

> Could use a function comment, because the return value isn't obvious.
>

ok

> Also: too many things are named "data" for my taste.

It's the same QDict *data, ie the actual event qdict. How would you rename it?

I will rename the "delay data".

>>  /*
>>   * 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?

ok

>
>>
>> -    /* 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?

if no delay

>
>>          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."

ok

>> 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
>



-- 
Marc-André Lureau



reply via email to

[Prev in Thread] Current Thread [Next in Thread]