qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 2/3] monitor: throttle QAPI_EVENT_VSERPORT_CHANG


From: Marc-André Lureau
Subject: Re: [Qemu-devel] [PATCH 2/3] monitor: throttle QAPI_EVENT_VSERPORT_CHANGE by "id"
Date: Thu, 17 Sep 2015 16:06:40 +0200

Hi

On Wed, Sep 16, 2015 at 6:40 PM, Markus Armbruster <address@hidden> wrote:
> address@hidden writes:
>
>> From: Marc-André Lureau <address@hidden>
>>
>> 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 <address@hidden>
>> Reviewed-by: Eric Blake <address@hidden>
>> ---
>>  monitor.c | 104 
>> ++++++++++++++++++++++++++++++++++++++++++++++----------------
>>  1 file changed, 78 insertions(+), 26 deletions(-)
>>
>> diff --git a/monitor.c b/monitor.c
>> index 0a6a16a..7f5c80f 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)
>
> Function name gets even longer, yet I miss a function comment as much as
> before :)

It's longer simply because the struct name is longer.
The function "update" MonitorQAPIEventPending.

>
> Since this is the common part of monitor_qapi_event_delay() and
> monitor_qapi_event_id_delay(), what about calling it
> monitor_qapi_event_do_delay()?
>

That's confusing, not only it doesn't follow the struct prefix, but
it's also very close to monitor_qapi_event_delay() (the simple
throttle/delay handler)

>>  {
>>      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));
>> -    }
>
> No change, just diff being insufficiently smart.
>
>> +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);
>>  }
>
> Why not simply
>
>     return monitor_qapi_event_pending_update(evstate, evstate->data, data);

ok

>
>>
>>  /*
>> @@ -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");
>
> Why is this called s?
>
> Here are less confusing names:
>
> * The parameter should not be called data, because it's the complete QMP
>   event object, and *not* its data member.  Either match
>   QMPEventFuncEmit and call it qdict, or call it event.
>

It was called "data" before, I think because "event" is for QAPIEvent
in general, and the "data" of QDict is the actual event data.

So I guess qdict is a better name, although it's also very generic to me.

> * The variable s *is* the data member, and should therefore be called data.

ok

>
>> +    const char *id = qdict_get_str(s, "id");
>
> This assumes s has a member "id" of type QString.  Therefore, the
> function can only be used for events where that is always the case.
> Unobvious requirements like that should be spelled out in a function
> comment.

It spelled in the function name, but I added a comment on top.

>> +    MonitorQAPIEventPending *p = g_hash_table_lookup(ht, id);
>> +    QAPIEvent event = evstate - monitor_qapi_event_state;
>
> Another unobvious requirement: evstate must point into
> monitor_qapi_event_state.

It's an element in the array. I'll add a comment and an assert.

>
>> +
>> +    if (!p) {
>> +        p = monitor_qapi_event_pending_new(event);
>> +        g_hash_table_insert(ht, g_strdup(id), p);
>
> Note for later: both key and value are dynamically allocated.

value has a destroy handler being called when removing the value

The key should also be destroyed, let's fix that leak. thanks

>
>> +    }
>> +
>> +    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);
>
> Ignorant question: who owns p->data?
>

MonitorQAPIEventPending, but the event is freed when emitted. Let's
add a cleanup here too.

>> +}
>> +
>>  /*
>>   * @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]);
>
> Superfluous parenthesis.
>

was there before, copy-pasta. removing

>> +
>> +    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);
>
> Both key and value are dynamically allocated.  But you define only the
> value's free callback.  Why?

At first I thought the key would remain in the hashtable, it's a leftover. Fixed

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



-- 
Marc-André Lureau



reply via email to

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