[Spice-devel] [PATCH 2/3 v3] replay: allows to specify a filter for record output
Jonathon Jongsma
jjongsma at redhat.com
Thu May 26 15:03:28 UTC 2016
Thanks
Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
On Thu, 2016-05-26 at 10:20 +0100, Frediano Ziglio wrote:
> This allows compression using external programs or any type
> of filters.
>
> To use it set SPICE_WORKER_RECORD_FILTER environment to the
> filter command you want to use. The command is executed with
> g_spawn_async_with_pipes (which uses execve) so is not a shell
> command although the command is parsed using g_shell_parse_argv
> which split arguments as shell does.
>
> One easy way to use it is to just use a compressor like gzip with
>
> export SPICE_WORKER_RECORD_FILENAME=/tmp/qemu_record.gz
> export SPICE_WORKER_RECORD_FILTER=gzip
> qemu ...
>
> The filter will receive the recording on standard input and is
> supposed to write in output filename (which is the standard output).
> You can use additional arguments in SPICE_WORKER_RECORD_FILTER to
> specify for instance compression level.
>
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> ---
> server/red-record-qxl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 45 insertions(+)
>
> Changes from v2:
> - clarify comment removed unneeded and confusing notes;
> - rename out_setup to child_output_setup;
> - add some comments.
>
> diff --git a/server/red-record-qxl.c b/server/red-record-qxl.c
> index 5337699..c6cd963 100644
> --- a/server/red-record-qxl.c
> +++ b/server/red-record-qxl.c
> @@ -21,6 +21,8 @@
>
> #include <stdbool.h>
> #include <inttypes.h>
> +#include <fcntl.h>
> +#include <glib.h>
> #include "red-worker.h"
> #include "red-common.h"
> #include "memslot.h"
> @@ -834,10 +836,26 @@ void red_record_qxl_command(RedRecord *record,
> RedMemSlotInfo *slots,
> }
> }
>
> +/**
> + * Redirects child output to the file specified
> + */
> +static void child_output_setup(gpointer user_data)
> +{
> + int fd = GPOINTER_TO_INT(user_data);
> +
> + while (dup2(fd, STDOUT_FILENO) < 0 && errno == EINTR)
> + continue;
> + close(fd);
> +
> + // make sure file is not closed calling exec()
> + fcntl(STDOUT_FILENO, F_SETFD, 0);
> +}
> +
> RedRecord *red_record_new(const char *filename)
> {
> static const char header[] = "SPICE_REPLAY 1\n";
>
> + const char *filter;
> FILE *f;
> RedRecord *record;
>
> @@ -846,6 +864,33 @@ RedRecord *red_record_new(const char *filename)
> spice_error("failed to open recording file %s\n", filename);
> }
>
> + filter = getenv("SPICE_WORKER_RECORD_FILTER");
> + if (filter) {
> + gint argc;
> + gchar **argv = NULL;
> + GError *error = NULL;
> + GPid child_pid;
> + gboolean ret;
> + gint fd_in;
> +
> + ret = g_shell_parse_argv(filter, &argc, &argv, &error);
> +
> + if (ret)
> + ret = g_spawn_async_with_pipes(NULL, argv, NULL,
> G_SPAWN_SEARCH_PATH,
> + child_output_setup,
> GINT_TO_POINTER(fileno(f)), &child_pid,
> + &fd_in, NULL, NULL, &error);
> +
> + g_strfreev(argv);
> + if (!ret) {
> + g_error_free(error);
> + fclose(f);
> + spice_error("failed to setup filter for replay");
> + }
> + while (dup2(fd_in, fileno(f)) < 0 && errno == EINTR)
> + continue;
> + close(fd_in);
> + }
> +
> if (fwrite(header, sizeof(header)-1, 1, f) != 1) {
> spice_error("failed to write replay header");
> }
More information about the Spice-devel
mailing list