mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
docs: Document our event loop
I was asked the other day what's event loop and how libvirt uses it. Well, I haven't found any good sources on the Internet so I thought of writing the documentation on my own. Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
8c40ede4a4
commit
cc874efb5b
@ -14,6 +14,7 @@
|
||||
<li>Introduction to basic rules and guidelines for
|
||||
<a href="hacking.html">hacking</a> on libvirt code</li>
|
||||
<li>Guide to adding <a href="api_extension.html">public APIs</a></li>
|
||||
<li>Insight into libvirt <a href="internals/eventloop.html">event loop and worker pool</a></li>
|
||||
<li>Approach for <a href="internals/command.html">spawning commands</a>
|
||||
from libvirt driver code</li>
|
||||
<li>The libvirt <a href="internals/rpc.html">RPC infrastructure</a></li>
|
||||
|
106
docs/internals/eventloop.html.in
Normal file
106
docs/internals/eventloop.html.in
Normal file
@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<body>
|
||||
<h1>Libvirt's event loop</h1>
|
||||
|
||||
<ul id="toc"></ul>
|
||||
|
||||
<p>
|
||||
This page describes the event loop approach used in
|
||||
libvirt. Both server and client.
|
||||
</p>
|
||||
|
||||
<h2><a name="event_loop">Event driven programming</a></h2>
|
||||
|
||||
<p>Traditionally, a program simply ran once, then terminated.
|
||||
This type of program was very common in the early days of
|
||||
computing, and lacked any form of user interactivity. This is
|
||||
still used frequently, particularly in small one purpose
|
||||
programs.</p>
|
||||
|
||||
<p>However, that approach is not suitable for all the types
|
||||
of applications. For instance graphical applications spend
|
||||
most of their run time waiting for an input from user. Only
|
||||
after it happened (in our example a button was clicked, a key
|
||||
pressed, etc.) an event is generated to which they respond
|
||||
by executing desired function. If generalized, this is how
|
||||
many long running programs (daemons) work. Even those who are
|
||||
not waiting for direct user input and have no graphical
|
||||
interface. Such as Libvirt.</p>
|
||||
|
||||
<img alt="event loop" src="http://libvirt.org/git/?p=libvirt-media.git;a=blob_plain;f=png/event_loop_simple.png;hb=HEAD"/>
|
||||
|
||||
<p>In Libvirt this approach is used in combination with
|
||||
<code>poll(2)</code> as all the communication with its
|
||||
clients (and domains it manages too) happens through sockets.
|
||||
Therefore whenever new client connects, it is given exclusive
|
||||
file descriptor which is then watched for incoming events,
|
||||
e.g. messages. </p>
|
||||
|
||||
<h2><a name="api">The event loop API</a></h2>
|
||||
|
||||
<p>To work with event loop from our code we have plenty of
|
||||
APIs.</p>
|
||||
|
||||
<ul>
|
||||
<li><code>virEventAddHandle</code>: Registers a
|
||||
callback for monitoring file handle events.</li>
|
||||
<li><code>virEventUpdateHandle</code>: Change set of events
|
||||
monitored file handle is being watched for.</li>
|
||||
<li><code>virEventRemoveHandle</code>: Unregisters
|
||||
previously registered file handle so that it is no
|
||||
longer monitored for any events.</li>
|
||||
<li><code>virEventAddTimeout</code>: Registers a
|
||||
callback for timer event.</li>
|
||||
<li><code>virEventUpdateTimeout</code>: Changes frequency
|
||||
for a timer.</li>
|
||||
<li><code>virEventRemoveTimeout</code>: Unregisters
|
||||
a timer.</li>
|
||||
</ul>
|
||||
|
||||
<p>For more information on these APIs continue reading <a
|
||||
href="../html/libvirt-libvirt-event.html">here</a>.</p>
|
||||
|
||||
<h2><a name="worker_pool">Worker pool</a></h2>
|
||||
|
||||
<p>Looking back at the image above we can see one big
|
||||
limitation. While processing a message event loop is blocked
|
||||
and for an outside observer unresponsive. This is not
|
||||
acceptable for Libvirt. Therefore we have came up with the
|
||||
following solution.</p>
|
||||
|
||||
<img alt="event loop" src="http://libvirt.org/git/?p=libvirt-media.git;a=blob_plain;f=png/event_loop_worker.png;hb=HEAD"/>
|
||||
|
||||
<p>The event loop does only necessary minimum and hand over
|
||||
message processing to another thread. In fact, there can be
|
||||
as many processing threads as configured increasing
|
||||
processing power.</p>
|
||||
|
||||
<p>To break this high level description into smaller pieces,
|
||||
here is what happens when user calls an API:</p>
|
||||
<ol>
|
||||
<li>User (or management application) calls a Libvirt API.
|
||||
Depending on the connection URI, this may or may not
|
||||
involve server. Well, for the sake of our
|
||||
demonstration we assume the former.</li>
|
||||
<li>Remote driver encodes the API among it's arguments
|
||||
into an <a href="rpc.html">RPC message</a> and sends
|
||||
it to the server.</li>
|
||||
<li>Here, server is waiting in <code>poll(2)</code> for
|
||||
an event, like incoming message.</li>
|
||||
<li>As soon as the first bytes of message are received,
|
||||
even loop wakes up and server starts reading the
|
||||
whole message.</li>
|
||||
<li>Once fully read, the event loop notifies threads
|
||||
known as worker threads from which one picks the incoming
|
||||
message, decodes and process it.</li>
|
||||
<li>As soon as API execution is finished, a reply is sent
|
||||
to the client.</li>
|
||||
</ol>
|
||||
|
||||
<p>In case that there's no free worker to process an incoming
|
||||
message in step 5, message is placed at the end of a message
|
||||
queue and is processed in next iteration.</p>
|
||||
</body>
|
||||
</html>
|
@ -396,6 +396,10 @@
|
||||
<a href="api_extension.html">API extensions</a>
|
||||
<span>Adding new public libvirt APIs</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="internals/eventloop.html">Event loop and worker pool</a>
|
||||
<span>Libvirt's event loop and worker pool mode</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="internals/command.html">Spawning commands</a>
|
||||
<span>Spawning commands from libvirt driver code</span>
|
||||
|
Loading…
Reference in New Issue
Block a user