summaryrefslogtreecommitdiffstats
path: root/src/proto.c
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2010-08-28 10:33:24 +0100
committerRichard Jones <rjones@redhat.com>2010-08-31 19:27:34 +0100
commite776a46ffcbede6d9b030dbc8f6ab32500b325ec (patch)
tree0ccab8e3751abf91b83f987c76b18e4f1cf00ed5 /src/proto.c
parenta8a44cecbadfd21c7f0483f8c1cdb355d08960a4 (diff)
downloadlibguestfs-e776a46ffcbede6d9b030dbc8f6ab32500b325ec.tar.gz
libguestfs-e776a46ffcbede6d9b030dbc8f6ab32500b325ec.tar.xz
libguestfs-e776a46ffcbede6d9b030dbc8f6ab32500b325ec.zip
Implement progress messages in the daemon and library.
This implements progress notification messages in the daemon, and adds a callback in the library to handle them. No calls are changed so far, so in fact no progress messages can be generated by this commit. For more details, see: https://www.redhat.com/archives/libguestfs/2010-July/msg00003.html https://www.redhat.com/archives/libguestfs/2010-July/msg00024.html
Diffstat (limited to 'src/proto.c')
-rw-r--r--src/proto.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/src/proto.c b/src/proto.c
index ad173c6b..5d924e86 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -373,7 +373,15 @@ guestfs___send_to_daemon (guestfs_h *g, const void *v_buf, size_t n)
*
* It also checks for EOF (qemu died) and passes that up through the
* child_cleanup function above.
+ *
+ * Progress notifications are handled transparently by this function.
+ * If the callback exists, it is called. The caller of this function
+ * will not see GUESTFS_PROGRESS_FLAG.
*/
+
+/* Size of guestfs_progress message on the wire. */
+#define PROGRESS_MESSAGE_SIZE 24
+
int
guestfs___recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
{
@@ -400,7 +408,13 @@ guestfs___recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
*/
ssize_t nr = -4;
- while (nr < (ssize_t) *size_rtn) {
+ for (;;) {
+ ssize_t message_size =
+ *size_rtn != GUESTFS_PROGRESS_FLAG ?
+ *size_rtn : PROGRESS_MESSAGE_SIZE;
+ if (nr >= message_size)
+ break;
+
rset2 = rset;
int r = select (max_fd+1, &rset2, NULL, NULL, NULL);
if (r == -1) {
@@ -450,6 +464,11 @@ guestfs___recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
xdr_uint32_t (&xdr, size_rtn);
xdr_destroy (&xdr);
+ /* *size_rtn changed, recalculate message_size */
+ message_size =
+ *size_rtn != GUESTFS_PROGRESS_FLAG ?
+ *size_rtn : PROGRESS_MESSAGE_SIZE;
+
if (*size_rtn == GUESTFS_LAUNCH_FLAG) {
if (g->state != LAUNCHING)
error (g, _("received magic signature from guestfsd, but in state %d"),
@@ -463,6 +482,8 @@ guestfs___recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
}
else if (*size_rtn == GUESTFS_CANCEL_FLAG)
return 0;
+ else if (*size_rtn == GUESTFS_PROGRESS_FLAG)
+ /*FALLTHROUGH*/;
/* If this happens, it's pretty bad and we've probably lost
* synchronization.
*/
@@ -473,11 +494,11 @@ guestfs___recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
}
/* Allocate the complete buffer, size now known. */
- *buf_rtn = safe_malloc (g, *size_rtn);
+ *buf_rtn = safe_malloc (g, message_size);
/*FALLTHROUGH*/
}
- size_t sizetoread = *size_rtn - nr;
+ size_t sizetoread = message_size - nr;
if (sizetoread > BUFSIZ) sizetoread = BUFSIZ;
r = read (g->sock, (char *) (*buf_rtn) + nr, sizetoread);
@@ -524,6 +545,26 @@ guestfs___recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
}
#endif
+ if (*size_rtn == GUESTFS_PROGRESS_FLAG) {
+ if (g->state == BUSY && g->progress_cb) {
+ guestfs_progress message;
+ XDR xdr;
+ xdrmem_create (&xdr, *buf_rtn, PROGRESS_MESSAGE_SIZE, XDR_DECODE);
+ xdr_guestfs_progress (&xdr, &message);
+ xdr_destroy (&xdr);
+
+ g->progress_cb (g, g->progress_cb_data,
+ message.proc, message.serial,
+ message.position, message.total);
+ }
+
+ free (*buf_rtn);
+ *buf_rtn = NULL;
+
+ /* Process next message. */
+ return guestfs___recv_from_daemon (g, size_rtn, buf_rtn);
+ }
+
return 0;
}