All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
Cc: Kevin Wolf <kwolf@redhat.com>,
	Luiz Capitulino <lcapitulino@redhat.com>,
	qemu-devel <qemu-devel@nongnu.org>,
	Markus Armbruster <armbru@redhat.com>
Subject: Re: [Qemu-devel] [RFC] qapi: events in QMP
Date: Sun, 13 Feb 2011 12:15:06 -0600	[thread overview]
Message-ID: <4D581FAA.5020808@codemonkey.ws> (raw)
In-Reply-To: <4D581E04.1020901@codemonkey.ws>

On 02/13/2011 12:08 PM, Anthony Liguori wrote:
> Hi,
>
> In my QAPI branch[1], I've now got almost every existing QMP command 
> converted with (hopefully) all of the hard problems solved.  There is 
> only one remaining thing to attack before posting for inclusion and 
> that's events.  Here's my current thinking about what to do.
>
> Events in QMP Today
>
> QMP events are asynchronous messages.  They are not tied explicitly to 
> any type of context, do not have a well defined format, and are have 
> no mechanism to mask or filter events.  As of right now, we have 
> somewhere around a dozen events.
>
> Goals of QAPI
>
> 1) Make all interfaces consumable in C such that we can use the 
> interfaces in QEMU
>
> 2) Make all interfaces exposed through a library using code generation 
> from static introspection
>
> 3) Make all interfaces well specified in a formal schema
>
> Proposal for events in QAPI
>
> For QAPI, I'd like to model events on the notion of signals and 
> slots[2].  A client would explicitly connect to a signal through a QMP 
> interface which would result in a slot being added that then generates 
> an event.  Internally in QEMU, we could also connect slots to the same 
> signals.  Since we don't have an object API in QMP, we'd use a pair of 
> connect/disconnect functions that had enough information to identify 
> the signal.
>
> Example:
>
> We would define QEVENT_BLOCK_IO_EVENT as:
>
> # qmp-schema.json
> { 'BlockIOEvent': {'device': 'str', 'action': 'str', 'operation': 
> 'str'} }
>
> The 'Event' suffix is used to determine that the type is an event and 
> not a structure.  This would generate the following structures for QEMU:
>
> typedef void (BlockIOEventFunc)(const char *device, const char 
> *action, const char *operation, void *opaque);

One thing I'm on the fence about, is making the slot callback take a 
BlockIOEvent *event as the first argument.  If we did this, the signals 
would be compatible with GObject signals.

It's hard to map that to a libqmp though so I'm not sure.

Regards,

Anthony Liguori

>
> typedef struct BlockIOEvent {
>     /* contents are private */
> } BlockIOEvent;
>
> /* Connect a slot to a BlockIOEvent signal and return a handle to the 
> connection */
> int block_io_event_connect(BlockIOEvent *event, BlockIOEventFunc *cb, 
> void *opaque);
>
> /* Signal any connect slots of a BlockIOEvent */
> void block_io_event_signal(BlockIOEvent *event, const char *device, 
> const char *action, const char *operation);
>
> /* Disconnect a slot from a signal based on a connection handle */
> void block_io_event_disconnect(BlockIOEvent *event, int handle);
>
> In the case of BlockIOEvent, this is a global signal that is not tied 
> to any specific object so there would be a global BlockIOEvent object 
> within QEMU.
>
> From a QMP perspective, we would have the following function in the 
> schema:
>
> [ 'block-io-event', {}, {}, 'BlockIOEvent' ]
>
> A function definition that returns an Event is a signal accessor.  
> Within QEMU, we implement a signal accessor like so:
>
> BlockIOEvent *qmp_block_io_event(Error **errp)
> {
>      return &global_block_io_event;
> }
>
> For QMP and libqmp, signal accessors are handled specially.  A signal 
> accessor is expanded into two QMP functions:
>
> [ 'block-io-event-connect', {}, {}, 'str' ]
> [ 'block-io-event-disconnect', {'tag' : 'str'}, {}, 'none' ]
>
> Connect returns a handle to the connection as an opaque string.  
> Disconnect takes that handle.  Both functions will also take any 
> arguments that the signal accessor takes and under the cover uses the 
> signal accessor to access the object.
>
> In libqmp, the following interfaces will be generated:
>
> int libqmp_block_io_event_connect(QmpSession *sess, BlockIOEventFunc 
> *cb, void *opaque, Error **errp);
> void libqmp_block_io_event_disconnect(QmpSession *sess, int handle, 
> Error **errp);
>
> Again, if the signal accessor takes additional arguments, they will be 
> passed here.
>
> All existing events will be converted to signals with signal accessors 
> that take no arguments.  However, BlockIOEvent is a good example of a 
> signal that we'll add a new version of that takes a 'const char 
> *device' as an argument for the signal accessor.  This will let 
> clients register for block io events on specific block devices.
>
> Backwards Compatibility
>
> Right now, QMP events to not have any type of context information 
> which means that there's no way to communicate the connection handle.  
> We'll solve this by adding a new 'tag' field to events that are 
> registered through one of the connect interfaces.  Since this is only 
> present on events registered through this new interface, backwards 
> compatibility is preserved.
>
> Upon initial connection, we'll treat all existing signals as having a 
> 'default signal connection'.  We'll introduce a new QMP command that 
> can be executed while in capabilities mode to disconnect default 
> signal connections.  The effect is that new clients can use the 
> explicit register/unregister interface while old clients will continue 
> to see the old style events.
>
> We'll deprecate the 'default signal connections' and make sure to 
> never add a new one post 0.15.  Old clients will need to be updated to 
> explicitly register for events.
>
> Another Example
>
> Here's an example of BlockDeviceEvent, the successor to BlockIOEvent.  
> It makes use of signal accessor arguments and QAPI enumeration support:
>
> # qmp-schema.json
> { 'BlockDeviceAction': [ 'report', 'stop', 'none' ] }
> { 'BlockDeviceOperation': [ 'read', 'write' ] }
> { 'BlockDeviceActionReason': [ 'nospc', 'io', 'other' ] }
> { 'BlockDeviceEvent': { 'action': 'BlockDeviceAction', 'operation': 
> 'BlockDeviceOperation', 'reason': 'BlockDeviceActionReason' } }
>
> [ 'block-device-event', { 'device': 'str' }, {}, 'BlockDeviceEvent' ]
>
> # qemu/block.c (Signal Accessor)
> BlockDeviceEvent *qmp_block_device_event(const char *str, Error **errp)'
>
> # qemu/qmp-types.h (Generated QMP interfaces)
> typedef enum BlockDeviceAction {
>     BDA_REPORT = 0,
>     BDA_STOP,
>     BDA_NONE,
> } BlockDeviceAction;
>
> typedef enum BlockDeviceOperation {
>     BDO_READ = 0,
>     BDO_WRITE,
> } BlockDeviceOperation;
>
> typedef enum BlockDeviceActionReason {
>    BDAR_NOSPC = 0,
>    BDAR_IO,
>    BDAR_OTHER,
> } BlockDeviceActionReason;
>
> typedef struct BlockDeviceEvent {
>     /* private */
> } BlockDeviceEvent;
>
> typedef void (BlockDeviceEventFunc)(BlockDeviceAction action, 
> BlockDeviceOperation operator, BlockDeviceActionReason reason);
>
> int block_device_event_connect(BlockDeviceEvent *event, 
> BlockDeviceEventFunc *cb, void *opaque);
> void block_device_event_disconnect(BlockDeviceEvent *event, int handle);
>
> # qemu/libqmp.h (Generated libqmp interfaces)
>
> int libqmp_block_device_event_connect(QmpSession *sess, const char 
> *device, BlockDeviceEventFunc *cb, void *opaque);
>
> void libqmp_block_device_event_disconnect(QmpSession *sess, const char 
> *device, int handle);
>
> Regards,
>
> Anthony Liguori
>
> [1] http://repo.or.cz/w/qemu/aliguori.git/shortlog/refs/heads/glib
>
> [2] http://en.wikipedia.org/wiki/Signals_and_slots
>
>

  reply	other threads:[~2011-02-13 18:15 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-13 18:08 [Qemu-devel] [RFC] qapi: events in QMP Anthony Liguori
2011-02-13 18:15 ` Anthony Liguori [this message]
2011-02-14  9:50 ` [Qemu-devel] " Kevin Wolf
2011-02-14 12:03   ` Anthony Liguori
2011-02-14 12:32     ` Kevin Wolf
2011-02-14 12:45       ` Luiz Capitulino
2011-02-14 14:39         ` Anthony Liguori
2011-02-14 18:34           ` Luiz Capitulino
2011-02-14 19:34             ` Anthony Liguori
2011-02-14 19:58               ` Luiz Capitulino
2011-02-14 20:01                 ` Luiz Capitulino
2011-02-14 20:15                 ` Anthony Liguori
2011-02-15 13:35                   ` Luiz Capitulino
2011-02-15 14:54                 ` Markus Armbruster
2011-02-15  9:20               ` Kevin Wolf
2011-02-15 13:38                 ` Luiz Capitulino
2011-02-16  0:59                   ` Anthony Liguori
2011-02-16  8:50                     ` Kevin Wolf
2011-02-16 13:43                       ` Anthony Liguori
2011-02-16 14:15                         ` Kevin Wolf
2011-02-16 14:32                           ` Anthony Liguori
2011-02-16 14:32                           ` Anthony Liguori
2011-02-14 21:14       ` Anthony Liguori
2011-02-14 13:28 ` Luiz Capitulino
2011-02-14 13:33   ` Daniel P. Berrange
2011-02-14 14:24     ` Anthony Liguori
2011-02-14 14:32   ` Anthony Liguori
2011-02-15 14:07 ` What's QAPI? (was: [Qemu-devel] [RFC] qapi: events in QMP) Markus Armbruster
2011-02-15 14:13   ` [Qemu-devel] Re: What's QAPI? Anthony Liguori
2011-02-15 16:15   ` Anthony Liguori

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=4D581FAA.5020808@codemonkey.ws \
    --to=anthony@codemonkey.ws \
    --cc=armbru@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=lcapitulino@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.