diff mbox

[08/11] QMP: Asynchronous messages enable/disable support

Message ID 1264108180-3666-9-git-send-email-lcapitulino@redhat.com
State New
Headers show

Commit Message

Luiz Capitulino Jan. 21, 2010, 9:09 p.m. UTC
This commit disables asynchronous messages by default and
introduces two new QMP commands: async_msg_enable and
async_msg_disable.

Each QMP Monitor has its own set of asynchronous messages,
so for example, if QEMU is run with two QMP Monitors async
messages setup in one of them doesn't affect the other.

To implement this design a bitmap is introduced to the
Monitor struct, each async message is represented by one bit.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 monitor.c       |   49 ++++++++++++++++++++++++++++++++++++++++++++++++-
 qemu-monitor.hx |   30 ++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 1 deletions(-)

Comments

Anthony Liguori Jan. 22, 2010, 6:05 p.m. UTC | #1
On 01/21/2010 03:09 PM, Luiz Capitulino wrote:
> This commit disables asynchronous messages by default and
> introduces two new QMP commands: async_msg_enable and
> async_msg_disable.
>
> Each QMP Monitor has its own set of asynchronous messages,
> so for example, if QEMU is run with two QMP Monitors async
> messages setup in one of them doesn't affect the other.
>
> To implement this design a bitmap is introduced to the
> Monitor struct, each async message is represented by one bit.
>
> Signed-off-by: Luiz Capitulino<lcapitulino@redhat.com>
>    

Ah, I see I was a little confused.

I'd suggest making async message masking an independent mechanism.  
Capabilities should strictly deal with protocol changes, not feature 
details.

For instance, protocol timestamps are something would reasonable 
considered a capability.  Extended data types would be a capability.

Another way to look at it, is that if you're writing a client library, 
the capability negotiation should be entirely invisible to the end API user.

Regards,

Anthony Liguori
Luiz Capitulino Jan. 22, 2010, 8:09 p.m. UTC | #2
On Fri, 22 Jan 2010 12:05:19 -0600
Anthony Liguori <anthony@codemonkey.ws> wrote:

> On 01/21/2010 03:09 PM, Luiz Capitulino wrote:
> > This commit disables asynchronous messages by default and
> > introduces two new QMP commands: async_msg_enable and
> > async_msg_disable.
> >
> > Each QMP Monitor has its own set of asynchronous messages,
> > so for example, if QEMU is run with two QMP Monitors async
> > messages setup in one of them doesn't affect the other.
> >
> > To implement this design a bitmap is introduced to the
> > Monitor struct, each async message is represented by one bit.
> >
> > Signed-off-by: Luiz Capitulino<lcapitulino@redhat.com>
> >    
> 
> Ah, I see I was a little confused.
> 
> I'd suggest making async message masking an independent mechanism.  
> Capabilities should strictly deal with protocol changes, not feature 
> details.

 To summarize (after a IRC talk): async messages are considered a
capability and should be enabled during the negotiation phase but
the masking of particular messages are not and can be done at
any time after the negotiation phase.

 I'm ok with that, Markus?
Anthony Liguori Jan. 22, 2010, 11:14 p.m. UTC | #3
On 01/22/2010 02:09 PM, Luiz Capitulino wrote:
> On Fri, 22 Jan 2010 12:05:19 -0600
> Anthony Liguori<anthony@codemonkey.ws>  wrote:
>
>    
>> On 01/21/2010 03:09 PM, Luiz Capitulino wrote:
>>      
>>> This commit disables asynchronous messages by default and
>>> introduces two new QMP commands: async_msg_enable and
>>> async_msg_disable.
>>>
>>> Each QMP Monitor has its own set of asynchronous messages,
>>> so for example, if QEMU is run with two QMP Monitors async
>>> messages setup in one of them doesn't affect the other.
>>>
>>> To implement this design a bitmap is introduced to the
>>> Monitor struct, each async message is represented by one bit.
>>>
>>> Signed-off-by: Luiz Capitulino<lcapitulino@redhat.com>
>>>
>>>        
>> Ah, I see I was a little confused.
>>
>> I'd suggest making async message masking an independent mechanism.
>> Capabilities should strictly deal with protocol changes, not feature
>> details.
>>      
>   To summarize (after a IRC talk): async messages are considered a
> capability and should be enabled during the negotiation phase but
> the masking of particular messages are not and can be done at
> any time after the negotiation phase.
>    

Just to further clarify, the mental model I have of capabilities is that 
they are things that affect the protocol itself.  Additional features 
(new command options, new commands, new async messages) are things that 
are enabled/discovered in a different way.

Async messages themselves are a capability since it changes the 
protocol.  Timestamps would be another capability and a new data type 
(like an uint64 type) would be a new capability.

>   I'm ok with that, Markus?
>    

Regards,

Anthony Liguori
Avi Kivity Jan. 24, 2010, 10:34 a.m. UTC | #4
On 01/22/2010 08:05 PM, Anthony Liguori wrote:
> On 01/21/2010 03:09 PM, Luiz Capitulino wrote:
>> This commit disables asynchronous messages by default and
>> introduces two new QMP commands: async_msg_enable and
>> async_msg_disable.
>>
>> Each QMP Monitor has its own set of asynchronous messages,
>> so for example, if QEMU is run with two QMP Monitors async
>> messages setup in one of them doesn't affect the other.
>>
>> To implement this design a bitmap is introduced to the
>> Monitor struct, each async message is represented by one bit.
>>
>> Signed-off-by: Luiz Capitulino<lcapitulino@redhat.com>
>
> Ah, I see I was a little confused.
>
> I'd suggest making async message masking an independent mechanism.  
> Capabilities should strictly deal with protocol changes, not feature 
> details.
>
> For instance, protocol timestamps are something would reasonable 
> considered a capability.  Extended data types would be a capability.
>
> Another way to look at it, is that if you're writing a client library, 
> the capability negotiation should be entirely invisible to the end API 
> user.
>

I agree with that, but we can look at async messages as a baseline 
protocol capability (thus no negotiation required), and the new command 
only enabled individual messages.
Avi Kivity Jan. 24, 2010, 10:36 a.m. UTC | #5
On 01/21/2010 11:09 PM, Luiz Capitulino wrote:
> This commit disables asynchronous messages by default and
> introduces two new QMP commands: async_msg_enable and
> async_msg_disable.
>
> Each QMP Monitor has its own set of asynchronous messages,
> so for example, if QEMU is run with two QMP Monitors async
> messages setup in one of them doesn't affect the other.
>
> To implement this design a bitmap is introduced to the
> Monitor struct, each async message is represented by one bit.
>
>    

A bitmap is an overkill here, an array of booleans should suffice.

>
> +#define EVENTS_BITMAP_SIZE (QEVENT_MAX / 8)
>    

Doesn't that underflow if QEVENT_MAX is not a multiple of 8?
Jamie Lokier Jan. 24, 2010, 11:07 a.m. UTC | #6
Avi Kivity wrote:
> On 01/22/2010 08:05 PM, Anthony Liguori wrote:
> >On 01/21/2010 03:09 PM, Luiz Capitulino wrote:
> >>This commit disables asynchronous messages by default and
> >>introduces two new QMP commands: async_msg_enable and
> >>async_msg_disable.
> >>
> >>Each QMP Monitor has its own set of asynchronous messages,
> >>so for example, if QEMU is run with two QMP Monitors async
> >>messages setup in one of them doesn't affect the other.
> >>
> >>To implement this design a bitmap is introduced to the
> >>Monitor struct, each async message is represented by one bit.
> >>
> >>Signed-off-by: Luiz Capitulino<lcapitulino@redhat.com>
> >
> >Ah, I see I was a little confused.
> >
> >I'd suggest making async message masking an independent mechanism.  
> >Capabilities should strictly deal with protocol changes, not feature 
> >details.
> >
> >For instance, protocol timestamps are something would reasonable 
> >considered a capability.  Extended data types would be a capability.
> >
> >Another way to look at it, is that if you're writing a client library, 
> >the capability negotiation should be entirely invisible to the end API 
> >user.
> 
> I agree with that, but we can look at async messages as a baseline 
> protocol capability (thus no negotiation required), and the new command 
> only enabled individual messages.

I'd like to be able to connect and be sure not to receive any async
messages, from simple scripts with simple output parsing.

If async messages can only be received as a result of commands which
trigger individual messages, that will be achieved.

But it would be a nice little bonus if disabling async messages caused
all slow commands to be synchronous - that is, the async result
message becomes the command's synchronous result.

-- Jamie
Anthony Liguori Jan. 24, 2010, 2:04 p.m. UTC | #7
On 01/24/2010 04:34 AM, Avi Kivity wrote:
> On 01/22/2010 08:05 PM, Anthony Liguori wrote:
>> On 01/21/2010 03:09 PM, Luiz Capitulino wrote:
>>> This commit disables asynchronous messages by default and
>>> introduces two new QMP commands: async_msg_enable and
>>> async_msg_disable.
>>>
>>> Each QMP Monitor has its own set of asynchronous messages,
>>> so for example, if QEMU is run with two QMP Monitors async
>>> messages setup in one of them doesn't affect the other.
>>>
>>> To implement this design a bitmap is introduced to the
>>> Monitor struct, each async message is represented by one bit.
>>>
>>> Signed-off-by: Luiz Capitulino<lcapitulino@redhat.com>
>>
>> Ah, I see I was a little confused.
>>
>> I'd suggest making async message masking an independent mechanism.  
>> Capabilities should strictly deal with protocol changes, not feature 
>> details.
>>
>> For instance, protocol timestamps are something would reasonable 
>> considered a capability.  Extended data types would be a capability.
>>
>> Another way to look at it, is that if you're writing a client 
>> library, the capability negotiation should be entirely invisible to 
>> the end API user.
>>
>
> I agree with that, but we can look at async messages as a baseline 
> protocol capability (thus no negotiation required), and the new 
> command only enabled individual messages.

To be honest, I don't think there's really a need to mask individual 
messages.  A client can always ignore messages it doesn't care about.  
There is no side effect of receiving a message so there is no functional 
implication of receiving messages you don't care about.

The only time it would matter is if we had a really high volume of 
messages.  I'd suggest waiting until a message is introduced that could 
potentially have a high rate and then implement a mechanism to mask it.  
For now, it just adds unnecessary complexity.

Regards,

Anthony Liguori
Avi Kivity Jan. 24, 2010, 2:17 p.m. UTC | #8
On 01/24/2010 04:04 PM, Anthony Liguori wrote:
>> I agree with that, but we can look at async messages as a baseline 
>> protocol capability (thus no negotiation required), and the new 
>> command only enabled individual messages.
>
>
> To be honest, I don't think there's really a need to mask individual 
> messages.  A client can always ignore messages it doesn't care about.  
> There is no side effect of receiving a message so there is no 
> functional implication of receiving messages you don't care about.
>
> The only time it would matter is if we had a really high volume of 
> messages.  I'd suggest waiting until a message is introduced that 
> could potentially have a high rate and then implement a mechanism to 
> mask it.  For now, it just adds unnecessary complexity.

Fair enough.  But then, why can't all clients do that?  Dropping an 
async notification is maybe one line of code.
Anthony Liguori Jan. 24, 2010, 2:19 p.m. UTC | #9
On 01/24/2010 08:17 AM, Avi Kivity wrote:
> On 01/24/2010 04:04 PM, Anthony Liguori wrote:
>>> I agree with that, but we can look at async messages as a baseline 
>>> protocol capability (thus no negotiation required), and the new 
>>> command only enabled individual messages.
>>
>>
>> To be honest, I don't think there's really a need to mask individual 
>> messages.  A client can always ignore messages it doesn't care 
>> about.  There is no side effect of receiving a message so there is no 
>> functional implication of receiving messages you don't care about.
>>
>> The only time it would matter is if we had a really high volume of 
>> messages.  I'd suggest waiting until a message is introduced that 
>> could potentially have a high rate and then implement a mechanism to 
>> mask it.  For now, it just adds unnecessary complexity.
>
> Fair enough.  But then, why can't all clients do that?  Dropping an 
> async notification is maybe one line of code.

I agree.  The only argument I can imagine for masking is if we had a 
really, really high volume event that caused bandwidth issues.  I don't 
think that's an appropriate use of async messages though so I don't 
think this will ever happen.

Regards,

Anthony Liguori
Anthony Liguori Jan. 24, 2010, 3:35 p.m. UTC | #10
On 01/24/2010 05:07 AM, Jamie Lokier wrote:
> Avi Kivity wrote:
>    
>> On 01/22/2010 08:05 PM, Anthony Liguori wrote:
>>      
>>> On 01/21/2010 03:09 PM, Luiz Capitulino wrote:
>>>        
>>>> This commit disables asynchronous messages by default and
>>>> introduces two new QMP commands: async_msg_enable and
>>>> async_msg_disable.
>>>>
>>>> Each QMP Monitor has its own set of asynchronous messages,
>>>> so for example, if QEMU is run with two QMP Monitors async
>>>> messages setup in one of them doesn't affect the other.
>>>>
>>>> To implement this design a bitmap is introduced to the
>>>> Monitor struct, each async message is represented by one bit.
>>>>
>>>> Signed-off-by: Luiz Capitulino<lcapitulino@redhat.com>
>>>>          
>>> Ah, I see I was a little confused.
>>>
>>> I'd suggest making async message masking an independent mechanism.
>>> Capabilities should strictly deal with protocol changes, not feature
>>> details.
>>>
>>> For instance, protocol timestamps are something would reasonable
>>> considered a capability.  Extended data types would be a capability.
>>>
>>> Another way to look at it, is that if you're writing a client library,
>>> the capability negotiation should be entirely invisible to the end API
>>> user.
>>>        
>> I agree with that, but we can look at async messages as a baseline
>> protocol capability (thus no negotiation required), and the new command
>> only enabled individual messages.
>>      
> I'd like to be able to connect and be sure not to receive any async
> messages, from simple scripts with simple output parsing.
>    

You can't have simple output parsing with QMP.  You need a full JSON 
stack.  The simplest script would be a python script that uses the 
builtin json support.  Having async messages means that you'll have to 
loop on recv in order make sure that the response is a command response 
vs. an async message.  It's just a few lines more of code so I have a 
hard time believing it's really a problem.

But what you probably want is a python QMP library and that would mean 
you wouldn't need the few more lines of code.

> If async messages can only be received as a result of commands which
> trigger individual messages, that will be achieved.
>
> But it would be a nice little bonus if disabling async messages caused
> all slow commands to be synchronous - that is, the async result
> message becomes the command's synchronous result.
>    

I know what you're getting at but I think it's the wrong target for 
QMP.  The goal is not to allow simple, hacky clients, but to provide a 
robust management API.  It should not be difficult to use, but parsing 
it in a shell with awk is not a requirement in my mind :-)

Regards,

Anthony Liguori
Jamie Lokier Jan. 24, 2010, 6:35 p.m. UTC | #11
Anthony Liguori wrote:
> >I'd like to be able to connect and be sure not to receive any async
> >messages, from simple scripts with simple output parsing.
> 
> You can't have simple output parsing with QMP.  You need a full JSON 
> stack.  The simplest script would be a python script that uses the 
> builtin json support.  Having async messages means that you'll have to 
> loop on recv in order make sure that the response is a command response 
> vs. an async message.  It's just a few lines more of code so I have a 
> hard time believing it's really a problem.
> 
> But what you probably want is a python QMP library and that would mean 
> you wouldn't need the few more lines of code.

You're right.  To be honest, parsing JSON can be done in a single Perl
regexp; a "full JSON stack" isn't much.

On that note, it'd be good if the end of a QMP message is framed with
something that can't appear inside the JSON value, without having to
parse the JSON incrementally on each partial read().  There are plenty
of short character sequences to choose from that can't appear.  Some
JSON parsers expect a whole well-formed expression or throw a parse
error - it's what people do over HTTP after all.  So you wait until
you think you've read a whole one, then pass it to the JSON parser.

> >If async messages can only be received as a result of commands which
> >trigger individual messages, that will be achieved.
> >
> >But it would be a nice little bonus if disabling async messages caused
> >all slow commands to be synchronous - that is, the async result
> >message becomes the command's synchronous result.
> 
> I know what you're getting at but I think it's the wrong target for 
> QMP.  The goal is not to allow simple, hacky clients, but to provide a 
> robust management API.  It should not be difficult to use, but parsing 
> it in a shell with awk is not a requirement in my mind :-)

I agree - not a requirement.  Just seemed nice if that turned out to
be a natural thing to do anyway.

-- Jamie
Luiz Capitulino Jan. 25, 2010, 11:49 a.m. UTC | #12
On Sun, 24 Jan 2010 18:35:14 +0000
Jamie Lokier <jamie@shareable.org> wrote:

> Anthony Liguori wrote:
> > >I'd like to be able to connect and be sure not to receive any async
> > >messages, from simple scripts with simple output parsing.
> > 
> > You can't have simple output parsing with QMP.  You need a full JSON 
> > stack.  The simplest script would be a python script that uses the 
> > builtin json support.  Having async messages means that you'll have to 
> > loop on recv in order make sure that the response is a command response 
> > vs. an async message.  It's just a few lines more of code so I have a 
> > hard time believing it's really a problem.
> > 
> > But what you probably want is a python QMP library and that would mean 
> > you wouldn't need the few more lines of code.
> 
> You're right.  To be honest, parsing JSON can be done in a single Perl
> regexp; a "full JSON stack" isn't much.
> 
> On that note, it'd be good if the end of a QMP message is framed with
> something that can't appear inside the JSON value, without having to
> parse the JSON incrementally on each partial read().  There are plenty
> of short character sequences to choose from that can't appear.  Some
> JSON parsers expect a whole well-formed expression or throw a parse
> error - it's what people do over HTTP after all.  So you wait until
> you think you've read a whole one, then pass it to the JSON parser.

 The Monitor sends a CRLF sequence at the end of each line and I have
maintained that behaivor for QMP, but it's hard to _guarantee_ that this
sequence won't appear inside a json-string.

 In practice it doesn't, afaik.
Luiz Capitulino Jan. 25, 2010, 12:02 p.m. UTC | #13
On Sun, 24 Jan 2010 08:19:53 -0600
Anthony Liguori <anthony@codemonkey.ws> wrote:

> On 01/24/2010 08:17 AM, Avi Kivity wrote:
> > On 01/24/2010 04:04 PM, Anthony Liguori wrote:
> >>> I agree with that, but we can look at async messages as a baseline 
> >>> protocol capability (thus no negotiation required), and the new 
> >>> command only enabled individual messages.
> >>
> >>
> >> To be honest, I don't think there's really a need to mask individual 
> >> messages.  A client can always ignore messages it doesn't care 
> >> about.  There is no side effect of receiving a message so there is no 
> >> functional implication of receiving messages you don't care about.
> >>
> >> The only time it would matter is if we had a really high volume of 
> >> messages.  I'd suggest waiting until a message is introduced that 
> >> could potentially have a high rate and then implement a mechanism to 
> >> mask it.  For now, it just adds unnecessary complexity.
> >
> > Fair enough.  But then, why can't all clients do that?  Dropping an 
> > async notification is maybe one line of code.
> 
> I agree.  The only argument I can imagine for masking is if we had a 
> really, really high volume event that caused bandwidth issues.  I don't 
> think that's an appropriate use of async messages though so I don't 
> think this will ever happen.

 The only real client writer we have thought it would be a good
idea to disable them by default.

 If we don't this now and add a masking command later, then clients
that don't want certain messages will have to deal with them between
the window of qmp_swicth_mode and masking.

 I don't have strong opinions here though.
Luiz Capitulino Jan. 25, 2010, 1:14 p.m. UTC | #14
On Sun, 24 Jan 2010 12:36:39 +0200
Avi Kivity <avi@redhat.com> wrote:

> On 01/21/2010 11:09 PM, Luiz Capitulino wrote:
> > This commit disables asynchronous messages by default and
> > introduces two new QMP commands: async_msg_enable and
> > async_msg_disable.
> >
> > Each QMP Monitor has its own set of asynchronous messages,
> > so for example, if QEMU is run with two QMP Monitors async
> > messages setup in one of them doesn't affect the other.
> >
> > To implement this design a bitmap is introduced to the
> > Monitor struct, each async message is represented by one bit.
> >
> >    
> 
> A bitmap is an overkill here, an array of booleans should suffice.

 Ok.

> > +#define EVENTS_BITMAP_SIZE (QEVENT_MAX / 8)
> >    
> 
> Doesn't that underflow if QEVENT_MAX is not a multiple of 8?

 Yes.
Markus Armbruster Jan. 25, 2010, 2:15 p.m. UTC | #15
Luiz Capitulino <lcapitulino@redhat.com> writes:

> On Sun, 24 Jan 2010 18:35:14 +0000
> Jamie Lokier <jamie@shareable.org> wrote:
>
>> Anthony Liguori wrote:
>> > >I'd like to be able to connect and be sure not to receive any async
>> > >messages, from simple scripts with simple output parsing.
>> > 
>> > You can't have simple output parsing with QMP.  You need a full JSON 
>> > stack.  The simplest script would be a python script that uses the 
>> > builtin json support.  Having async messages means that you'll have to 
>> > loop on recv in order make sure that the response is a command response 
>> > vs. an async message.  It's just a few lines more of code so I have a 
>> > hard time believing it's really a problem.
>> > 
>> > But what you probably want is a python QMP library and that would mean 
>> > you wouldn't need the few more lines of code.
>> 
>> You're right.  To be honest, parsing JSON can be done in a single Perl
>> regexp; a "full JSON stack" isn't much.
>> 
>> On that note, it'd be good if the end of a QMP message is framed with
>> something that can't appear inside the JSON value, without having to
>> parse the JSON incrementally on each partial read().  There are plenty
>> of short character sequences to choose from that can't appear.  Some
>> JSON parsers expect a whole well-formed expression or throw a parse
>> error - it's what people do over HTTP after all.  So you wait until
>> you think you've read a whole one, then pass it to the JSON parser.
>
>  The Monitor sends a CRLF sequence at the end of each line and I have
> maintained that behaivor for QMP, but it's hard to _guarantee_ that this
> sequence won't appear inside a json-string.

JSON requires control characters in strings to be escaped.  RFC 4627
section 2.5:

   A string begins and ends with quotation marks.  All Unicode
   characters may be placed within the quotation marks except for the
   characters that must be escaped: quotation mark, reverse solidus, and
   the control characters (U+0000 through U+001F).

>  In practice it doesn't, afaik.

If it doesn't, then it's not proper JSON, is it?
Luiz Capitulino Jan. 25, 2010, 2:22 p.m. UTC | #16
On Mon, 25 Jan 2010 15:15:59 +0100
Markus Armbruster <armbru@redhat.com> wrote:

> Luiz Capitulino <lcapitulino@redhat.com> writes:
> 
> > On Sun, 24 Jan 2010 18:35:14 +0000
> > Jamie Lokier <jamie@shareable.org> wrote:
> >
> >> Anthony Liguori wrote:
> >> > >I'd like to be able to connect and be sure not to receive any async
> >> > >messages, from simple scripts with simple output parsing.
> >> > 
> >> > You can't have simple output parsing with QMP.  You need a full JSON 
> >> > stack.  The simplest script would be a python script that uses the 
> >> > builtin json support.  Having async messages means that you'll have to 
> >> > loop on recv in order make sure that the response is a command response 
> >> > vs. an async message.  It's just a few lines more of code so I have a 
> >> > hard time believing it's really a problem.
> >> > 
> >> > But what you probably want is a python QMP library and that would mean 
> >> > you wouldn't need the few more lines of code.
> >> 
> >> You're right.  To be honest, parsing JSON can be done in a single Perl
> >> regexp; a "full JSON stack" isn't much.
> >> 
> >> On that note, it'd be good if the end of a QMP message is framed with
> >> something that can't appear inside the JSON value, without having to
> >> parse the JSON incrementally on each partial read().  There are plenty
> >> of short character sequences to choose from that can't appear.  Some
> >> JSON parsers expect a whole well-formed expression or throw a parse
> >> error - it's what people do over HTTP after all.  So you wait until
> >> you think you've read a whole one, then pass it to the JSON parser.
> >
> >  The Monitor sends a CRLF sequence at the end of each line and I have
> > maintained that behaivor for QMP, but it's hard to _guarantee_ that this
> > sequence won't appear inside a json-string.
> 
> JSON requires control characters in strings to be escaped.  RFC 4627
> section 2.5:

 Excellent.

> >  In practice it doesn't, afaik.
> 
> If it doesn't, then it's not proper JSON, is it?

 My 'doesn\'t' meant: no JSON string we currently generate has CR or
LF in them, as far as I can remember. But even if it happens it's
not a problem, as you clarified.
Markus Armbruster Jan. 25, 2010, 2:29 p.m. UTC | #17
Luiz Capitulino <lcapitulino@redhat.com> writes:

> On Fri, 22 Jan 2010 12:05:19 -0600
> Anthony Liguori <anthony@codemonkey.ws> wrote:
>
>> On 01/21/2010 03:09 PM, Luiz Capitulino wrote:
>> > This commit disables asynchronous messages by default and
>> > introduces two new QMP commands: async_msg_enable and
>> > async_msg_disable.
>> >
>> > Each QMP Monitor has its own set of asynchronous messages,
>> > so for example, if QEMU is run with two QMP Monitors async
>> > messages setup in one of them doesn't affect the other.
>> >
>> > To implement this design a bitmap is introduced to the
>> > Monitor struct, each async message is represented by one bit.
>> >
>> > Signed-off-by: Luiz Capitulino<lcapitulino@redhat.com>
>> >    
>> 
>> Ah, I see I was a little confused.
>> 
>> I'd suggest making async message masking an independent mechanism.  
>> Capabilities should strictly deal with protocol changes, not feature 
>> details.
>
>  To summarize (after a IRC talk): async messages are considered a
> capability and should be enabled during the negotiation phase but
> the masking of particular messages are not and can be done at
> any time after the negotiation phase.
>
>  I'm ok with that, Markus?

I agree with Anthony that async message masking doesn't really affect
the protocol proper.  We could pretend it does so we can let protocol
capability negotiation (which we need anyway) cover it.  But I'm
certainly fine with keeping it separate.

Whether we call it protocol or not, the question whether we should
permit changing the masks at any time is valid, I think.  Permitting it
adds a bit of conceptual complexity, as a command disabling reporting of
an event can race with the event.  But that's just giving clients some
more rope.  I'm fine with that.
Avi Kivity Jan. 25, 2010, 2:33 p.m. UTC | #18
On 01/25/2010 04:29 PM, Markus Armbruster wrote:
>
> I agree with Anthony that async message masking doesn't really affect
> the protocol proper.  We could pretend it does so we can let protocol
> capability negotiation (which we need anyway) cover it.  But I'm
> certainly fine with keeping it separate.
>
> Whether we call it protocol or not, the question whether we should
> permit changing the masks at any time is valid, I think.  Permitting it
> adds a bit of conceptual complexity, as a command disabling reporting of
> an event can race with the event.  But that's just giving clients some
> more rope.  I'm fine with that.
>    

Without disagreeing with the rest (which means I'm just nit-picking), 
there's no race.  Once the command that disables an event report returns 
to the caller, the event can no longer be reported.
Luiz Capitulino Jan. 25, 2010, 3:11 p.m. UTC | #19
On Mon, 25 Jan 2010 16:33:02 +0200
Avi Kivity <avi@redhat.com> wrote:

> On 01/25/2010 04:29 PM, Markus Armbruster wrote:
> >
> > I agree with Anthony that async message masking doesn't really affect
> > the protocol proper.  We could pretend it does so we can let protocol
> > capability negotiation (which we need anyway) cover it.  But I'm
> > certainly fine with keeping it separate.
> >
> > Whether we call it protocol or not, the question whether we should
> > permit changing the masks at any time is valid, I think.  Permitting it
> > adds a bit of conceptual complexity, as a command disabling reporting of
> > an event can race with the event.  But that's just giving clients some
> > more rope.  I'm fine with that.
> >    
> 
> Without disagreeing with the rest (which means I'm just nit-picking), 
> there's no race.  Once the command that disables an event report returns 
> to the caller, the event can no longer be reported.

 I wouldn't call it a race, but if you don't want an event you'll have
to deal with it between mode change and masking.

 Not a big deal, only confirms that clients are required to know how to
ignore events, even if masking is available (which I'm not going to
introduce).
diff mbox

Patch

diff --git a/monitor.c b/monitor.c
index 61c0273..321bc3a 100644
--- a/monitor.c
+++ b/monitor.c
@@ -108,11 +108,14 @@  typedef enum QMPMode {
     QMODE_HANDSHAKE,
 } QMPMode;
 
+#define EVENTS_BITMAP_SIZE (QEVENT_MAX / 8)
+
 typedef struct MonitorControl {
     QObject *id;
     QMPMode mode;
     int print_enabled;
     JSONMessageParser parser;
+    uint8_t events_bitmap[EVENTS_BITMAP_SIZE];
 } MonitorControl;
 
 struct Monitor {
@@ -318,6 +321,23 @@  static void monitor_protocol_emitter(Monitor *mon, QObject *data)
     QDECREF(qmp);
 }
 
+static void qevent_set(const Monitor *mon, int64_t event)
+{
+    assert(event >= 0 && event < QEVENT_MAX);
+    mon->mc->events_bitmap[event / 8] |= (1 << (event % 8));
+}
+
+static void qevent_unset(const Monitor *mon, int64_t event)
+{
+    assert(event >= 0 && event < QEVENT_MAX);
+    mon->mc->events_bitmap[event / 8] &= ~(1 << (event % 8));
+}
+
+static int qevent_enabled(const Monitor *mon, int64_t event)
+{
+    return (mon->mc->events_bitmap[event / 8] & (1 << (event % 8)));
+}
+
 static void timestamp_put(QDict *qdict)
 {
     int err;
@@ -389,7 +409,8 @@  void monitor_protocol_event(MonitorEvent event, QObject *data)
     }
 
     QLIST_FOREACH(mon, &mon_list, entry) {
-        if (monitor_ctrl_mode(mon)) {
+        if (monitor_ctrl_mode(mon) &&
+            qevent_enabled(mon, event)) {
             monitor_json_emitter(mon, QOBJECT(qmp));
         }
     }
@@ -465,6 +486,32 @@  static void do_commit(Monitor *mon, const QDict *qdict)
     }
 }
 
+static void qevent_set_value(Monitor *mon, const QDict *qdict, int value)
+{
+    int i;
+    const char *name = qdict_get_str(qdict, "name");
+
+    for (i = 0; monitor_events_names[i].name != NULL; i++) {
+        if (!strcmp(monitor_events_names[i].name, name)) {
+            return (value ? qevent_set(mon, i) : qevent_unset(mon, i));
+        }
+    }
+
+    qemu_error_new(QERR_ASYNC_MSG_NOT_FOUND, name);
+}
+
+static void do_async_msg_enable(Monitor *mon, const QDict *qdict,
+                                QObject **ret_data)
+{
+    qevent_set_value(mon, qdict, 1);
+}
+
+static void do_async_msg_disable(Monitor *mon, const QDict *qdict,
+                                 QObject **ret_data)
+{
+    qevent_set_value(mon, qdict, 0);
+}
+
 static void do_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     const mon_cmd_t *cmd;
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index eebea09..0f3dfde 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -1077,6 +1077,36 @@  STEXI
 Switch QMP to @var{mode}
 ETEXI
 
+    {
+        .name       = "async_msg_enable",
+        .args_type  = "name:s",
+        .params     = "async_msg_enable name",
+        .help       = "enable an asynchronous message",
+        .flags      = HANDLER_HANDSHAKE_ONLY,
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_async_msg_enable,
+    },
+
+STEXI
+@item async_msg_enable @var{name}
+Enable the asynchronous message @var{name}
+ETEXI
+
+    {
+        .name       = "async_msg_disable",
+        .args_type  = "name:s",
+        .params     = "async_msg_disable name",
+        .help       = "disable an asynchronous message",
+        .flags      = HANDLER_HANDSHAKE_ONLY,
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_async_msg_disable,
+    },
+
+STEXI
+@item async_msg_disable @var{name}
+Disable the asynchronous message @var{name}
+ETEXI
+
 STEXI
 @end table
 ETEXI