Sys::Virt::Event integration w/ AnyEvent
Marc Lehmann
schmorp at schmorp.de
Sat Mar 15 09:28:11 CET 2014
On Fri, Mar 14, 2014 at 05:40:24PM -0600, Scott Wiersdorf <scott at betterservers.com> wrote:
> I’ve looked carefully at all of the included AnyEvent::Impl::* libraries, per the "SUPPLYING YOUR OWN EVENT MODEL INTERFACE" documentation in AnyEvent.pm and just don’t see how the two overlap. Sys::Virt::Event supplies a run_default() method that runs a single iteration of its loop. I’ve been able to hack something like this:
To write an interface to it that is standalone, you should write a module
that looks like this:
package My::AnyEvent::VirtEvent::Interface;
push @AnyEvent:::REGISTRY, [Sys::Virt::Event => My::AnyEvent::VirtEvent::Interface::];
use Sys::Virt::Event;
sub timer {
my (undef, %arg) = @_;
my $virtwatch = Sys::Virt::Event::add_timeout ($magic, $arg{cb});
bless \$virtwatch, My::AnyEvent::VirtEvent::Interface::timer::
}
sub My::AnyEvent::VirtEvent::Interface::timer::DESTROY {
Sys::Virt::Event::remove_timeout ${ $_[0] };
}
sub io {
...
}
sub _poll {
Sys::Virt::Event::run_default;
}
I.e. provide implementations for the AnyEvent timer and io
methods. Sys::Virt doesn't seem to support any other watchers or an event
time, so you can/must rely on AnyEvent's emulation of those.
Things you would need to watch out for are:
a) there can be multiple watchers on the same fd, and they can be removed
in any order. you would need to find out if Sys::Virt supports that and,
if not, emulate it (and inefficient but simple workaround is dup'ing the
fd for each watcher with AnyEvent::_dupfh, if the implementaton becomes
part of the AnyEvent module).
b) AnyEvent supports file descriptors and file handles: the docs for
Sys::Virt call it fd, but name it "filehandle", so you need to find out
which one they really expect, and make sure both are supported.
c) the timers in AnyEvent have an initial timeout and an optional repeat
timeout, Sys::VirtEvent only seems to support repeat events, so you need
to update_timeout a new timer for subsequent iterations and be able
to destroy the timer before AnyEvent destroys it (for this, you would
normally need to have some illegal $watch id, such as undef).
> while (! $quit) {
> EV::run EV::RUN_ONCE; ## find my events
> $ev->run_default(); ## find libvirt events
> }
> where $ev is an instance of Sys::Virt::Event, but this feels terrible and wrong to me.
Unless you tell EV about the Sys::Virt events (or the latter uses the
former internally, which is unlikely), then this won't work very well, as
both modules will block indefinitely until they can hndle an avent, so the
events of the other won't be handled for potentially very long times.
> #!/usr/bin/env perl
Offtopic and not your code, but this is a terribly bad way to start perl
programs, as it just randomly picks the first perl in your path, which is
a) unnecessary (perl is basically always in /usr/bin/perl, unlike python)
and b) unnecessary if you use perls install (which will patch in the
correct path) and c) wrong if the code was installed for one perl, but now
is attempted to run with another.
> Under the hood, libvirt connects to a unix domain socket, speaks the right protocol to subscribe to the EVENT_ID_LIFECYCLE event, then registers my callback which fires when the event occurs (I think it uses epoll on the fd). I’d prefer to let EV run the loop (via EV::run), rather than run two loops so I can catch all my events.
A completely different option to providing an AnyEvent interface would be to
treat Sys::Virt as soem AnyEvent customer, and register its file descriptor
with e.g. EV, and then call run_default. However, you need to make sure that
run_default does return instantly, e.g. by having a frequency 0 or so timer.
That requires that you get the internal fd.
However, it leaves every user of Sys::Virt::Event broken, as you will only
see I/O events on the internal fd, and will not see any timeouts or other
fd events, so the only way to do it "right" is by providing an AnyEvent
implementation for it, which also rules out usage of EV.
> Has anyone successfully integrated Sys::Virt::Event with AnyEvent (or EV—I’m not even sure how to ask this correctly)?
I can understand that the task is a bit overwhelming, so here is my
offer: I am quite short on time, but if you can manage (with my help if
you need) to make an initial implementation of AnyEvent::Impl::SysVirt and
tell me how to test it (presumably, I can just compile the module and use
it standalone?), then I will gladly include it in AnyEvent proper and take
care of any subtle details and bugs in the future.
(An example of a subtle detail would be: "is Sys::Virt or Sys::Virt::Event
the event model", i.e. should AnyEvent use its virtevent module when
Sys::Virt is loaded or when Sys::Virt::Event is loaded).
--
The choice of a Deliantra, the free code+content MORPG
-----==- _GNU_ http://www.deliantra.net
----==-- _ generation
---==---(_)__ __ ____ __ Marc Lehmann
--==---/ / _ \/ // /\ \/ / schmorp at schmorp.de
-=====/_/_//_/\_,_/ /_/\_\
More information about the anyevent
mailing list