X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=guestfs.pod;h=db8887e8d043fee67869b34e0955b6cf6107808c;hp=6c0160006e0e4d644095826c07f96b191572a133;hb=13465753d3ed056609ec1e3137750a05d0497a66;hpb=ec89b939882564b0f7a481298e06111b7578d60d diff --git a/guestfs.pod b/guestfs.pod index 6c01600..db8887e 100644 --- a/guestfs.pod +++ b/guestfs.pod @@ -86,9 +86,8 @@ C is the opaque type representing a connection handle. Create a handle by calling C. Call C to free the handle and release all resources used. -Handles and operations on handles are not thread safe. However you -can use a separate handle for each thread (but not on the same disk -image). +For information on using multiple handles and threads, see the section +MULTIPLE HANDLES AND MULTIPLE THREADS below. =head2 guestfs_create @@ -312,34 +311,21 @@ this function with C set to C. =head2 NON-BLOCKING ACTIONS -XXX NOT IMPLEMENTED YET XXX +XXX This section was documented in previous versions but never +implemented in a way which matched the documentation. For now I have +removed the documentation, pending a working implementation. See also +C in the source. -C is the most interesting callback to -play with, since it allows you to perform actions without blocking. -For example: +=head2 guestfs_set_send_callback - do_it () - { - start_call (); - guestfs_main_loop_run (); /* --> blocks, then calls my_cb */ - } + typedef void (*guestfs_send_cb) (guestfs_h *g, void *opaque); + void guestfs_set_send_callback (guestfs_h *handle, + guestfs_send_cb cb, + void *opaque); - start_call () - { - guestfs_set_reply_callback (handle, my_cb, data); - guestfs_nb_[action] (handle, [other parameters ...]); - /* returns immediately */ - } - - my_cb (guestfs_h *handle, void *data, XDR *xdr) - { - retval = guestfs_nb_[action]_r (handle, xdr); - /* ... */ - } - -There are C and C functions -corresponding to every C action in the high-level API. +The callback function C will be called whenever a message +which is queued for sending, has been sent. =head2 guestfs_set_reply_callback @@ -400,9 +386,10 @@ non-blocking wait for the child process to finish booting up. =head2 EVENT MAIN LOOP -To use the low-level event API, you have to provide an event "main -loop". You can write your own, but if you don't want to write one, -two are provided for you: +To use the low-level event API and/or to use handles from multiple +threads, you have to provide an event "main loop". You can write your +own, but if you don't want to write one, two types are provided for +you: =over 4 @@ -410,8 +397,8 @@ two are provided for you: A simple main loop that is implemented using L. -This is the default main loop unless you call C -or C. +This is the default main loop for new guestfs handles, unless you +call C after a handle is created. =item libguestfs-glib @@ -421,73 +408,220 @@ without hanging during long or slow operations. =back -=head2 guestfs_set_main_loop +=head2 MULTIPLE HANDLES AND MULTIPLE THREADS + +The support for multiple handles and multiple threads is modelled +after glib (although doesn't require glib, if you use the select-based +main loop). + +L - void guestfs_set_main_loop (guestfs_main_loop *); +You will need to create one main loop for each thread that wants to +use libguestfs. Each guestfs handle should be confined to one thread. +If you try to pass guestfs handles between threads, you will get +undefined results. -This call sets the current main loop to the list of callbacks -contained in the C structure. +If you only want to use guestfs handles from one thread in your +program, but your program has other threads doing other things, then +you don't need to do anything special. -Only one main loop implementation can be used by libguestfs, so -calling this replaces the previous one. (So this is something that -has to be done by the main program, but only the main program "knows" -that it is a GTK+ program or whatever). +=head2 SINGLE THREAD CASE -You should call this early in the main program, certainly before -calling C. +In the single thread case, there is a single select-based main loop +created for you. All guestfs handles will use this main loop to +execute high level API actions. -=head2 guestfs_glib_set_main_loop +=head2 MULTIPLE THREADS CASE - void guestfs_glib_set_main_loop (GMainLoop *); +In the multiple threads case, you will need to create a main loop for +each thread that wants to use libguestfs. + +To create main loops for other threads, use +C or C. + +Then you will need to attach each handle to the thread-specific main +loop by calling: + + handle = guestfs_create (); + guestfs_set_main_loop (handle, main_loop_of_current_thread); + +=head2 guestfs_set_main_loop -This helper calls C with the correct callbacks -for integrating with the GLib main loop. + void guestfs_set_main_loop (guestfs_h *handle, + guestfs_main_loop *main_loop); -The libguestfs-glib main loop is contained in a separate library, so -that libguestfs doesn't depend on the whole of GLib: +Sets the main loop used by high level API actions for this handle. By +default, the select-based main loop is used (see +C). - #include - #include +You only need to use this in multi-threaded programs, where multiple +threads want to use libguestfs. Create a main loop for each thread, +then call this function. - main () - { - GMainLoop *loop = - g_main_loop_new (g_main_context_default (), 1); - ... - guestfs_glib_set_main_loop (loop); - ... - g_main_loop_run (loop); - } +You cannot pass guestfs handles between threads. -To use this main loop you must link with C<-lguestfs-glib>. (See also -the GLib and GTK+ documentation). +=head2 guestfs_get_main_loop -=head2 guestfs_main_loop_run + guestfs_main_loop *guestfs_get_main_loop (guestfs_h *handle); - void guestfs_main_loop_run (void); +Return the main loop used by C. -This calls the main loop. +=head2 guestfs_get_default_main_loop -For some types of main loop you may want or prefer to call another -function, eg. C, or the main loop may already be -invoked by another part of your program. In those cases, ignore this -call. + guestfs_main_loop *guestfs_get_default_main_loop (void); -=head2 guestfs_main_loop_quit +Return the default select-based main loop. - void guestfs_main_loop_quit (void); +=head2 guestfs_create_main_loop -This instructs the main loop to quit. In other words, -C will return. + guestfs_main_loop *guestfs_create_main_loop (void); -For some types of main loop you may want or prefer to call another -function, eg. C. In those cases, ignore this call. +This creates a select-based main loop. You should create one main +loop for each additional thread that needs to use libguestfs. + +=head2 guestfs_free_main_loop + + void guestfs_free_main_loop (guestfs_main_loop *); + +Free the select-based main loop which was previously allocated with +C. =head2 WRITING A CUSTOM MAIN LOOP This isn't documented. Please see the libguestfs-select and libguestfs-glib implementations. +=head1 INTERNALS + +=head2 COMMUNICATION PROTOCOL + +Don't rely on using this protocol directly. This section documents +how it currently works, but it may change at any time. + +The protocol used to talk between the library and the daemon running +inside the qemu virtual machine is a simple RPC mechanism built on top +of XDR (RFC 1014, RFC 1832, RFC 4506). + +The detailed format of structures is in C +(note: this file is automatically generated). + +There are two broad cases, ordinary functions that don't have any +C and C parameters, which are handled with very +simple request/reply messages. Then there are functions that have any +C or C parameters, which use the same request and +reply messages, but they may also be followed by files sent using a +chunked encoding. + +=head3 ORDINARY FUNCTIONS (NO FILEIN/FILEOUT PARAMS) + +For ordinary functions, the request message is: + + total length (header + arguments, + but not including the length word itself) + struct guestfs_message_header + struct guestfs__args + +The total length field allows the daemon to allocate a fixed size +buffer into which it slurps the rest of the message. As a result, the +total length is limited to C bytes (currently +4MB), which means the effective size of any request is limited to +somewhere under this size. + +Note also that many functions don't take any arguments, in which case +the C_args> is completely omitted. + +The header contains the procedure number (C) which is +how the receiver knows what type of args structure to expect, or none +at all. + +The reply message for ordinary functions is: + + total length (header + ret, + but not including the length word itself) + struct guestfs_message_header + struct guestfs__ret + +As above the C_ret> structure may be completely omitted +for functions that return no formal return values. + +As above the total length of the reply is limited to +C. + +In the case of an error, a flag is set in the header, and the reply +message is slightly changed: + + total length (header + error, + but not including the length word itself) + struct guestfs_message_header + struct guestfs_message_error + +The C structure contains the error message as a +string. + +=head3 FUNCTIONS THAT HAVE FILEIN PARAMETERS + +A C parameter indicates that we transfer a file I the +guest. The normal request message is sent (see above). However this +is followed by a sequence of file chunks. + + total length (header + arguments, + but not including the length word itself, + and not including the chunks) + struct guestfs_message_header + struct guestfs__args + sequence of chunks for FileIn param #0 + sequence of chunks for FileIn param #1 etc. + +The sequence of chunks is a sequence of C. A +flag is set in the final chunk to indicate either successful +completion or early cancellation. + +At time of writing there are no functions that have more than one +FileIn parameter. However this is (theoretically) supported, by +sending the chunks for each FileIn parameter one after another (from +left to right). + +Both the library (sender) I the daemon (receiver) may cancel the +transfer. The library does this by sending a chunk with a special +flag set to indicate cancellation. When the daemon sees this, it +cancels the whole RPC, does I send any reply, and goes back to +reading the next request. + +The daemon may also cancel. It does this by writing a special word +C to the socket. The library listens for this +during the transfer, and if it gets it, it will cancel the transfer +(it sends a cancel chunk). The special word is chosen so that even if +cancellation happens right at the end of the transfer (after the +library has finished writing and has started listening for the reply), +the "spurious" cancel flag will not be confused with the reply +message. + +This protocol allows the transfer of arbitrary sized files (no 32 bit +limit), and also files where the size is not known in advance +(eg. from pipes or sockets). However the chunks are rather small +(C), so that neither the library nor the +daemon need to keep much in memory. + +=head3 FUNCTIONS THAT HAVE FILEOUT PARAMETERS + +The protocol for FileOut parameters is exactly the same as for FileIn +parameters, but with the roles of daemon and library reversed. + + total length (header + ret, + but not including the length word itself, + and not including the chunks) + struct guestfs_message_header + struct guestfs__ret + sequence of chunks for FileOut param #0 + sequence of chunks for FileOut param #1 etc. + +=head3 INITIAL MESSAGE + +Because the underlying channel (QEmu -net channel) doesn't have any +sort of connection control, when the daemon launches it sends an +initial word (C) which indicates that the guest +and daemon is alive. This is what C waits for. + =head1 ENVIRONMENT VARIABLES =over 4