[Spice-devel] [PATCH 2/2 v2] replay: allows to specify a filter for record output

Jonathon Jongsma jjongsma at redhat.com
Wed May 25 22:08:53 UTC 2016


On Wed, 2016-05-25 at 16:35 +0100, Frediano Ziglio wrote:
> This allows compressions using external programs or any type

compressions -> compression

> 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).
> Nothing forbid to close and delete the file and do something else
> use additional argument in SPICE_WORKER_RECORD_FILTER to specify
> for instance compression level. 

I don't quite understand this last sentence.

> Note however that even if you don't
> use the output file is always opened

what does this mean "the output file is always opened"?

>  and SPICE_WORKER_RECORD_FILENAME
> have to be defined to enable recording.
> 
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> ---
>  server/red-record-qxl.c | 40 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
> 
> Changes from v1:
> - rebased.
> 
> diff --git a/server/red-record-qxl.c b/server/red-record-qxl.c
> index a4e0cc0..778ee1e 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,21 @@ void red_record_qxl_command(RedRecord *record,
> RedMemSlotInfo *slots,
>      }
>  }
>  
> +static void out_setup(gpointer user_data)

How about child_output_setup()? It would help me understand the context a little
better. Also, a couple comments in this function would probably help me in the
future since I don't use these functions very often.

> +{
> +    int fd = GPOINTER_TO_INT(user_data);
> +
> +    while (dup2(fd, 1) < 0 && errno == EINTR)

What about using STDOUT_FILENO here instead of a bare constant? 

> +        continue;
> +    close(fd);
> +    fcntl(1, F_SETFD, 0);

and here too? 

> +}
> +
>  RedRecord *red_record_new(const char *filename)
>  {
>      static const char header[] = "SPICE_REPLAY 1\n";
>  
> +    const char *filter;
>      FILE *f;
>      RedRecord *record;
>  
> @@ -847,6 +860,33 @@ RedRecord *red_record_new(const char *filename)
>          return NULL;
>      }
>  
> +    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,
> +                               out_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");
>      }


Reviewed-by: Jonathon Jongsma <jjongsma at redhat.com>



More information about the Spice-devel mailing list