[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