[ltt-dev] [UST PATCH] Rename libustd to libustconsumer and ustd to ust-consumerd

Nils Carlson nils.carlson at ericsson.com
Wed Jan 5 09:13:00 EST 2011


If nobody protests quickly I will pull this patch so I can go on to work 
on more fun things... :-)

Mathieu, any comments?

/Nils

Nils Carlson wrote:
> This is a fargoing but necessary renaming of some ust components.
> The point of the renaming is to allow for a new daemon, ustd, which
> will be able to keep track of tracing sessions and connect applications
> with consumers. Also, the current names were non-sensical.
>
> This patch is a step on the way towards creating a session daemon
> that can connect trace producers and consumers in a nice way.
>
> Signed-off-by: Nils Carlson <nils.carlson at ericsson.com>
> ---
>  Makefile.am                     |    2 +-
>  README                          |   10 +-
>  TODO                            |    2 +-
>  configure.ac                    |    4 +-
>  doc/Makefile.am                 |    2 +-
>  doc/info/ust.texi               |   10 +-
>  doc/man/Makefile.am             |    4 +-
>  doc/man/ust-consumerd.1         |   51 +++
>  doc/man/ust-consumerd.1.md      |   44 ++
>  doc/man/ustctl.1                |    4 +-
>  doc/man/ustctl.1.md             |    4 +-
>  doc/man/ustd.1                  |   51 ---
>  doc/man/ustd.1.md               |   44 --
>  doc/man/usttrace.1              |    2 +-
>  doc/man/usttrace.1.md           |    2 +-
>  include/Makefile.am             |    2 +-
>  include/ust/ustconsumer.h       |  287 +++++++++++++
>  include/ust/ustd.h              |  287 -------------
>  libust/tracectl.c               |   14 +-
>  libustcmd/ustcmd.c              |    2 +-
>  libustconsumer/Makefile.am      |   16 +
>  libustconsumer/libustconsumer.c |  891 +++++++++++++++++++++++++++++++++++++++
>  libustconsumer/lowlevel.c       |  143 +++++++
>  libustconsumer/lowlevel.h       |   35 ++
>  libustd/Makefile.am             |   17 -
>  libustd/libustd.c               |  891 ---------------------------------------
>  libustd/lowlevel.c              |  143 -------
>  libustd/lowlevel.h              |   35 --
>  tests/manual_mode_tracing.sh    |   10 +-
>  tests/runtests                  |    2 +-
>  tests/valgrind_ust-consumerd.sh |   54 +++
>  tests/valgrind_ustd.sh          |   54 ---
>  ust-consumerd/Makefile.am       |   14 +
>  ust-consumerd/README            |    3 +
>  ust-consumerd/ust-consumerd.c   |  505 ++++++++++++++++++++++
>  ustd/Makefile.am                |   14 -
>  ustd/README                     |    3 -
>  ustd/ustd.c                     |  505 ----------------------
>  usttrace                        |   46 +-
>  39 files changed, 2106 insertions(+), 2103 deletions(-)
>  create mode 100644 doc/man/ust-consumerd.1
>  create mode 100644 doc/man/ust-consumerd.1.md
>  delete mode 100644 doc/man/ustd.1
>  delete mode 100644 doc/man/ustd.1.md
>  create mode 100644 include/ust/ustconsumer.h
>  delete mode 100644 include/ust/ustd.h
>  create mode 100644 libustconsumer/Makefile.am
>  create mode 100644 libustconsumer/libustconsumer.c
>  create mode 100644 libustconsumer/lowlevel.c
>  create mode 100644 libustconsumer/lowlevel.h
>  delete mode 100644 libustd/Makefile.am
>  delete mode 100644 libustd/libustd.c
>  delete mode 100644 libustd/lowlevel.c
>  delete mode 100644 libustd/lowlevel.h
>  create mode 100755 tests/valgrind_ust-consumerd.sh
>  delete mode 100755 tests/valgrind_ustd.sh
>  create mode 100644 ust-consumerd/Makefile.am
>  create mode 100644 ust-consumerd/README
>  create mode 100644 ust-consumerd/ust-consumerd.c
>  delete mode 100644 ustd/Makefile.am
>  delete mode 100644 ustd/README
>  delete mode 100644 ustd/ustd.c
>
> diff --git a/Makefile.am b/Makefile.am
> index 5132d59..249bf02 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -5,7 +5,7 @@ ACLOCAL_AMFLAGS = -I config
>  # libust and '.' (that contains the linker script). However, '.'
>  # must be installed after libust so it can overwrite libust.so with
>  # the linker script.
> -SUBDIRS = snprintf libustcomm libustcmd libust . tests libustinstr-malloc libustd ustd ustctl libustfork include doc
> +SUBDIRS = snprintf libustcomm libustcmd libust . tests libustinstr-malloc libustconsumer ust-consumerd ustctl libustfork include doc
>
>  EXTRA_DIST = libust.ldscript.in libust-initializer.c libust-initializer.h
>  dist_bin_SCRIPTS = usttrace
> diff --git a/README b/README
> index 8eaf618..a381c95 100644
> --- a/README
> +++ b/README
> @@ -61,7 +61,7 @@ PACKAGE CONTENTS:
>    - include
>      The public header files that will be installed on the system.
>
> -  - ustd
> +  - ust-consumerd
>      The daemon that collects trace data and writes it to the disk.
>
>    - doc
> @@ -83,8 +83,12 @@ PACKAGE CONTENTS:
>      A library to control tracing in other processes. Used by ustctl.
>
>    - libustcomm
> -    A static library shared between libust, ustd and libustcmd, that provides
> -    functions that allow these components to communicate together.
> +    A static library shared between libust, ust-consumerd and libustcmd, that
> +    provides functions that allow these components to communicate together.
> +
> +  - libustconsumer
> +    A library to create ust consumers by registering callbacks, used by
> +    ust-consumerd.
>
>    - snprintf
>      An asynchronous signal-safe version of snprintf.
> diff --git a/TODO b/TODO
> index 46d5b64..0d07589 100644
> --- a/TODO
> +++ b/TODO
> @@ -19,7 +19,7 @@
>  - save_registers: save them only when the marker is active (complicated because we need to know their value at the address that is put in struct marker)
>  - make streaming work, including periodical flush
>  - make a system (signal-based?) that allow the listener thread to not be started initially
> -- ustd should work as a pool of threads
> +- ust-consumerd should work as a pool of threads
>  - support more than one marker with the same channel and name on the same line?
>  - make a mode where the listener thread can poll buffers to check if they are ready to be collected
>    This is to guarantee there will never be a system call in the tracing path. Currently there is a system
> diff --git a/configure.ac b/configure.ac
> index 189ab12..b6cf946 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -129,8 +129,8 @@ AC_CONFIG_FILES([
>         tests/ustcmd_function_tests/Makefile
>         libustinstr-malloc/Makefile
>         libustfork/Makefile
> -       libustd/Makefile
> -       ustd/Makefile
> +       libustconsumer/Makefile
> +       ust-consumerd/Makefile
>         ustctl/Makefile
>         libustcomm/Makefile
>         libustcmd/Makefile
> diff --git a/doc/Makefile.am b/doc/Makefile.am
> index 37a55ac..463203c 100644
> --- a/doc/Makefile.am
> +++ b/doc/Makefile.am
> @@ -1 +1 @@
> -SUBDIRS = man info
> \ No newline at end of file
> +SUBDIRS = man info
> diff --git a/doc/info/ust.texi b/doc/info/ust.texi
> index e0565f3..a0ccdf1 100644
> --- a/doc/info/ust.texi
> +++ b/doc/info/ust.texi
> @@ -92,7 +92,7 @@ Components licensed as GPL v2:
>  @itemize @bullet
>  @item ustctl
>  @item libustcmd
> - at item ustd
> + at item ust-consumerd
>  @end itemize
>
>  @node Supported platforms
> @@ -112,7 +112,7 @@ The following packages are required:
>  @item
>  ust
>
> -This contains the tracing library, the ustd daemon, trace control tools
> +This contains the tracing library, the ust-consumerd daemon, trace control tools
>  and other helper tools.
>
>  Repository: @url{http://git.dorsal.polymtl.ca}
> @@ -385,11 +385,11 @@ First the daemon must be started.
>  # Make sure the directory for the communication sockets exists.
>  $ mkdir /tmp/ustsocks
>
> -# Make sure the directory where ustd will write the trace exists.
> +# Make sure the directory where ust-consumerd will write the trace exists.
>  $ mkdir /tmp/trace
>
>  # Start the daemon
> -$ ustd
> +$ ust-consumerd
>
>  # We assume the program we want to trace is already running and that
>  # it has pid 1234.
> @@ -543,7 +543,7 @@ the application (or library) being linked to libust.
>  Libust is initialized by a constructor, which by definition runs before the
>  @code{main()} function of the application starts. This constructor creates a
>  thread called the @emph{listener thread}.  The listener thread initializes a
> -named socket and waits for connections for ustd or ustctl.
> +named socket and waits for connections for ust-consumerd or ustctl.
>
>  Libust-specific code may:
>  @itemize @bullet
> diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
> index 7e18b8e..5adbba4 100644
> --- a/doc/man/Makefile.am
> +++ b/doc/man/Makefile.am
> @@ -1,2 +1,2 @@
> -EXTRA_DIST = ustctl.1 ustd.1 usttrace.1
> -man_MANS = ustctl.1 ustd.1 usttrace.1
> +EXTRA_DIST = ustctl.1 ust-consumerd.1 usttrace.1
> +man_MANS = ustctl.1 ust-consumerd.1 usttrace.1
> diff --git a/doc/man/ust-consumerd.1 b/doc/man/ust-consumerd.1
> new file mode 100644
> index 0000000..c6ce6a4
> --- /dev/null
> +++ b/doc/man/ust-consumerd.1
> @@ -0,0 +1,51 @@
> +.\" generated with Ronn/v0.5
> +.\" http://github.com/rtomayko/ronn/
> +.
> +.TH "UST-CONSUMERD" "1" "May 2010" "" ""
> +.
> +.SH "NAME"
> +\fBust-consumerd\fR \-\- a daemon that collects trace data and writes it to the disk
> +.
> +.SH "SYNOPSIS"
> +\fBust-consumerd\fR [\fIoptions\fR]
> +.
> +.SH "DESCRIPTION"
> +\fBust-consumerd\fR is a program that collects trace data and writes it to the disk.
> +.
> +.SH "OPTIONS"
> +These programs follow the usual GNU command line syntax, with long options
> +starting with two dashes(`\-'). A summary of options is included below.
> +.
> +.TP
> +\fB\-h\fR, \fB\-\-help\fR
> +Show summary of options.
> +.
> +.TP
> +\fB\-o\fR \fIDIR\fR
> +Specify the directory where to output the traces.
> +.
> +.TP
> +\fB\-s\fR \fIPATH\fR
> +Specify the path to use for the daemon socket.
> +.
> +.TP
> +\fB\-d\fR
> +Start as a daemon.
> +.
> +.TP
> +\fB\-p\fR, \fB\-\-pidfile\fR=\fIFILE\fR
> +Write the PID in this file (when using \-d).
> +.
> +.TP
> +\fB\-V\fR, \fB\-\-version\fR
> +Show version of program.
> +.
> +.SH "SEE ALSO"
> +ustctl(1), usttrace(1)
> +.
> +.SH "AUTHOR"
> +\fBust-consumerd\fR was written by Pierre\-Marc Fournier.
> +.
> +.P
> +This manual page was written by Jon Bernard <jbernard at debian.org>, for
> +the Debian project (and may be used by others).
> diff --git a/doc/man/ust-consumerd.1.md b/doc/man/ust-consumerd.1.md
> new file mode 100644
> index 0000000..1b93f47
> --- /dev/null
> +++ b/doc/man/ust-consumerd.1.md
> @@ -0,0 +1,44 @@
> +ust-consumerd(1) -- a daemon that collects trace data and writes it to the disk
> +======================================================================
> +
> +## SYNOPSIS
> +
> +`ust-consumerd` [<options>]
> +
> +## DESCRIPTION
> +
> +`ust-consumerd` is a program that collects trace data and writes it to the disk.
> +
> +## OPTIONS
> +
> +These programs follow the usual GNU command line syntax, with long options
> +starting with two dashes(`-'). A summary of options is included below.
> +
> +  * `-h`, `--help`:
> +    Show summary of options.
> +
> +  * `-o` <DIR>:
> +    Specify the directory where to output the traces.
> +
> +  * `-s` <PATH>:
> +    Specify the path to use for the daemon socket.
> +
> +  * `-d`:
> +    Start as a daemon.
> +
> +  * `-p`, `--pidfile`=<FILE>:
> +    Write the PID in this file (when using -d).
> +
> +  * `-V`, `--version`:
> +    Show version of program.
> +
> +## SEE ALSO
> +
> +ustctl(1), usttrace(1)
> +
> +## AUTHOR
> +
> +`ust-consumerd` was written by Pierre-Marc Fournier.
> +
> +This manual page was written by Jon Bernard <jbernard at debian.org>, for
> +the Debian project (and may be used by others).
> diff --git a/doc/man/ustctl.1 b/doc/man/ustctl.1
> index 4f171c6..b0f97d9 100644
> --- a/doc/man/ustctl.1
> +++ b/doc/man/ustctl.1
> @@ -114,7 +114,7 @@ have flushed to the disk the full contents of the buffer yet.
>  .P
>  Finally, when \fB\-\-destroy\-trace\fR is used, the trace buffers are unallocated.
>  However, the memory may not be effectively freed until the daemon finishes to
> -collect them. When the trace is being collected by \fBustd\fR, this command
> +collect them. When the trace is being collected by \fBust-consumerd\fR, this command
>  guarantees its full contents is flushed to the disk.
>  .
>  .SH "STRUCTURE OF A TRACE"
> @@ -139,7 +139,7 @@ for a given channel may be chosen with \fB\-\-set\-subbuf\-size\fR while the sub
>  count is set with \fB\-\-set\-subbuf\-num\fR.
>  .
>  .SH "SEE ALSO"
> -usttrace(1), ustd(1)
> +usttrace(1), ust-consumerd(1)
>  .
>  .SH "AUTHOR"
>  \fBustctl\fR was written by Pierre\-Marc Fournier.
> diff --git a/doc/man/ustctl.1.md b/doc/man/ustctl.1.md
> index 208e1dd..c8ad1f1 100644
> --- a/doc/man/ustctl.1.md
> +++ b/doc/man/ustctl.1.md
> @@ -92,7 +92,7 @@ have flushed to the disk the full contents of the buffer yet.
>
>  Finally, when `--destroy-trace` is used, the trace buffers are unallocated.
>  However, the memory may not be effectively freed until the daemon finishes to
> -collect them. When the trace is being collected by `ustd`, this command
> +collect them. When the trace is being collected by `ust-consumerd`, this command
>  guarantees its full contents is flushed to the disk.
>
>  ## STRUCTURE OF A TRACE
> @@ -118,7 +118,7 @@ count is set with `--set-subbuf-num`.
>
>  ## SEE ALSO
>
> -usttrace(1), ustd(1)
> +usttrace(1), ust-consumerd(1)
>
>  ## AUTHOR
>
> diff --git a/doc/man/ustd.1 b/doc/man/ustd.1
> deleted file mode 100644
> index f423978..0000000
> --- a/doc/man/ustd.1
> +++ /dev/null
> @@ -1,51 +0,0 @@
> -.\" generated with Ronn/v0.5
> -.\" http://github.com/rtomayko/ronn/
> -.
> -.TH "USTD" "1" "May 2010" "" ""
> -.
> -.SH "NAME"
> -\fBustd\fR \-\- a daemon that collects trace data and writes it to the disk
> -.
> -.SH "SYNOPSIS"
> -\fBustd\fR [\fIoptions\fR]
> -.
> -.SH "DESCRIPTION"
> -\fBustd\fR is a program that collects trace data and writes it to the disk.
> -.
> -.SH "OPTIONS"
> -These programs follow the usual GNU command line syntax, with long options
> -starting with two dashes(`\-'). A summary of options is included below.
> -.
> -.TP
> -\fB\-h\fR, \fB\-\-help\fR
> -Show summary of options.
> -.
> -.TP
> -\fB\-o\fR \fIDIR\fR
> -Specify the directory where to output the traces.
> -.
> -.TP
> -\fB\-s\fR \fIPATH\fR
> -Specify the path to use for the daemon socket.
> -.
> -.TP
> -\fB\-d\fR
> -Start as a daemon.
> -.
> -.TP
> -\fB\-p\fR, \fB\-\-pidfile\fR=\fIFILE\fR
> -Write the PID in this file (when using \-d).
> -.
> -.TP
> -\fB\-V\fR, \fB\-\-version\fR
> -Show version of program.
> -.
> -.SH "SEE ALSO"
> -ustctl(1), usttrace(1)
> -.
> -.SH "AUTHOR"
> -\fBustd\fR was written by Pierre\-Marc Fournier.
> -.
> -.P
> -This manual page was written by Jon Bernard <jbernard at debian.org>, for
> -the Debian project (and may be used by others).
> diff --git a/doc/man/ustd.1.md b/doc/man/ustd.1.md
> deleted file mode 100644
> index 296d1c4..0000000
> --- a/doc/man/ustd.1.md
> +++ /dev/null
> @@ -1,44 +0,0 @@
> -ustd(1) -- a daemon that collects trace data and writes it to the disk
> -======================================================================
> -
> -## SYNOPSIS
> -
> -`ustd` [<options>]
> -
> -## DESCRIPTION
> -
> -`ustd` is a program that collects trace data and writes it to the disk.
> -
> -## OPTIONS
> -
> -These programs follow the usual GNU command line syntax, with long options
> -starting with two dashes(`-'). A summary of options is included below.
> -
> -  * `-h`, `--help`:
> -    Show summary of options.
> -
> -  * `-o` <DIR>:
> -    Specify the directory where to output the traces.
> -
> -  * `-s` <PATH>:
> -    Specify the path to use for the daemon socket.
> -
> -  * `-d`:
> -    Start as a daemon.
> -
> -  * `-p`, `--pidfile`=<FILE>:
> -    Write the PID in this file (when using -d).
> -
> -  * `-V`, `--version`:
> -    Show version of program.
> -
> -## SEE ALSO
> -
> -ustctl(1), usttrace(1)
> -
> -## AUTHOR
> -
> -`ustd` was written by Pierre-Marc Fournier.
> -
> -This manual page was written by Jon Bernard <jbernard at debian.org>, for
> -the Debian project (and may be used by others).
> diff --git a/doc/man/usttrace.1 b/doc/man/usttrace.1
> index e789e45..a56cfc4 100644
> --- a/doc/man/usttrace.1
> +++ b/doc/man/usttrace.1
> @@ -91,7 +91,7 @@ Specify the number of subbuffers.
>  Print the location of the last trace saved in the usttrace output directory.
>  .
>  .SH "SEE ALSO"
> -ustctl(1), ustd(1)
> +ustctl(1), ust-consumerd(1)
>  .
>  .SH "AUTHOR"
>  \fBusttrace\fR was written by Pierre\-Marc Fournier.
> diff --git a/doc/man/usttrace.1.md b/doc/man/usttrace.1.md
> index 34acb36..75cff9a 100644
> --- a/doc/man/usttrace.1.md
> +++ b/doc/man/usttrace.1.md
> @@ -64,7 +64,7 @@ starting with two dashes(`-'). A summary of options is included below.
>
>  ## SEE ALSO
>
> -ustctl(1), ustd(1)
> +ustctl(1), ust-consumerd(1)
>
>
>  ## AUTHOR
> diff --git a/include/Makefile.am b/include/Makefile.am
> index 0ace775..400e8b1 100644
> --- a/include/Makefile.am
> +++ b/include/Makefile.am
> @@ -18,6 +18,6 @@ nobase_include_HEADERS = \
>         ust/kcompat/types.h \
>         ust/kcompat/stringify.h \
>         ust/ustcmd.h \
> -       ust/ustd.h
> +       ust/ustconsumer.h
>
>  noinst_HEADERS = share.h usterr.h ust_snprintf.h
> diff --git a/include/ust/ustconsumer.h b/include/ust/ustconsumer.h
> new file mode 100644
> index 0000000..e07b75e
> --- /dev/null
> +++ b/include/ust/ustconsumer.h
> @@ -0,0 +1,287 @@
> +/*
> + * libustconsumer header file
> + *
> + * Copyright 2005-2010 -
> + *              Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
> + * Copyright 2010-
> + *              Oumarou Dicko <oumarou.dicko at polymtl.ca>
> + *              Michael Sills-Lavoie <michael.sills-lavoie at polymtl.ca>
> + *              Alexis Halle <alexis.halle at polymtl.ca>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef _USTCONSUMER_H
> +#define _USTCONSUMER_H
> +
> +#include <pthread.h>
> +#include <dirent.h>
> +#include <ust/kcompat/kcompat.h>
> +#include <urcu/list.h>
> +
> +#define USTCONSUMER_DEFAULT_TRACE_PATH "/tmp/usttrace"
> +
> +struct ustcomm_sock;
> +
> +struct buffer_info {
> +       char *name;
> +       char *trace;
> +       char *channel;
> +       int channel_cpu;
> +
> +       pid_t pid;
> +       int app_sock;
> +       /* The pipe file descriptor */
> +       int pipe_fd;
> +
> +       int shmid;
> +       int bufstruct_shmid;
> +
> +       /* the buffer memory */
> +       void *mem;
> +       /* buffer size */
> +       int memlen;
> +       /* number of subbuffers in buffer */
> +       int n_subbufs;
> +       /* size of each subbuffer */
> +       int subbuf_size;
> +
> +       /* the buffer information struct */
> +       void *bufstruct_mem;
> +
> +       long consumed_old;
> +
> +       s64 pidunique;
> +
> +       void *user_data;
> +};
> +
> +struct ustconsumer_callbacks;
> +
> +/**
> + * struct ustconsumer_instance - Contains the data associated with a trace instance.
> + * The lib user can read but MUST NOT change any attributes but callbacks.
> + * @callbacks: Contains the necessary callbacks for a tracing session.
> + */
> +struct ustconsumer_instance {
> +       struct ustconsumer_callbacks *callbacks;
> +       int quit_program;
> +       int is_init;
> +       struct cds_list_head connections;
> +       int epoll_fd;
> +       struct ustcomm_sock *listen_sock;
> +       char *sock_path;
> +       pthread_mutex_t mutex;
> +       int active_buffers;
> +};
> +
> +/**
> +* struct ustconsumer_callbacks - Contains the necessary callbacks for a tracing
> +* session. The user can set the unnecessary functions to NULL if he does not
> +* need them.
> +*/
> +struct ustconsumer_callbacks {
> +       /**
> +        * on_open_buffer - Is called after a buffer is attached to process memory
> +        *
> +        * @data: pointer to the callbacks structure that has been passed to the
> +        *        library.
> +        * @buf: structure that contains the data associated with the buffer
> +        *
> +        * Returns 0 if the callback succeeds else not 0.
> +        *
> +        * It has to be thread safe, because it is called by many threads.
> +        */
> +       int (*on_open_buffer)(struct ustconsumer_callbacks *data,
> +                               struct buffer_info *buf);
> +
> +       /**
> +        * on_close_buffer - Is called after a buffer is detached from process memory
> +        *
> +        * @data: pointer to the callbacks structure that has been passed to the
> +        *        library.
> +        * @buf: structure that contains the data associated with the buffer
> +        *
> +        * Returns 0 if the callback succeeds else not 0.
> +        *
> +        * It has to be thread safe, because it is called by many threads.
> +        */
> +       int (*on_close_buffer)(struct ustconsumer_callbacks *data,
> +                               struct buffer_info *buf);
> +
> +       /**
> +        * on_read_subbuffer - Is called after a subbuffer is a reserved.
> +        *
> +        * @data: pointer to the callbacks structure that has been passed to the
> +        *        library.
> +        * @buf: structure that contains the data associated with the buffer
> +        *
> +        * Returns 0 if the callback succeeds else not 0.
> +        *
> +        * It has to be thread safe, because it is called by many threads.
> +        */
> +       int (*on_read_subbuffer)(struct ustconsumer_callbacks *data,
> +                               struct buffer_info *buf);
> +
> +       /**
> +        * on_read_partial_subbuffer - Is called when an incomplete subbuffer
> +        *                             is being salvaged from an app crash
> +        *
> +        * @data: pointer to the callbacks structure that has been passed to the
> +        *        library.
> +        * @buf: structure that contains the data associated with the buffer
> +        * @subbuf_index: index of the subbuffer to read in the buffer
> +        * @valid_length: number of bytes considered safe to read
> +        *
> +        * Returns 0 if the callback succeeds else not 0.
> +        *
> +        * It has to be thread safe, because it is called by many threads.
> +        */
> +       int (*on_read_partial_subbuffer)(struct ustconsumer_callbacks *data,
> +                                       struct buffer_info *buf,
> +                                       long subbuf_index,
> +                                       unsigned long valid_length);
> +
> +       /**
> +        * on_put_error - Is called when a put error has occured and the last
> +        *                subbuffer read is no longer safe to keep
> +        *
> +        * @data: pointer to the callbacks structure that has been passed to the
> +        *        library.
> +        * @buf: structure that contains the data associated with the buffer
> +        *
> +        * Returns 0 if the callback succeeds else not 0.
> +        *
> +        * It has to be thread safe, because it is called by many threads.
> +        */
> +       int (*on_put_error)(struct ustconsumer_callbacks *data,
> +                               struct buffer_info *buf);
> +
> +       /**
> +        * on_new_thread - Is called when a new thread is created
> +        *
> +        * @data: pointer to the callbacks structure that has been passed to the
> +        *        library.
> +        *
> +        * Returns 0 if the callback succeeds else not 0.
> +        *
> +        * It has to be thread safe, because it is called by many threads.
> +        */
> +       int (*on_new_thread)(struct ustconsumer_callbacks *data);
> +
> +       /**
> +        * on_close_thread - Is called just before a thread is destroyed
> +        *
> +        * @data: pointer to the callbacks structure that has been passed to the
> +        *        library.
> +        *
> +        * Returns 0 if the callback succeeds else not 0.
> +        *
> +        * It has to be thread safe, because it is called by many threads.
> +        */
> +       int (*on_close_thread)(struct ustconsumer_callbacks *data);
> +
> +       /**
> +        * on_trace_end - Is called at the very end of the tracing session. At
> +        * this time, everything has been closed and the threads have
> +        * been destroyed.
> +        *
> +        * @instance: pointer to the instance structure that has been passed to
> +        *            the library.
> +        *
> +        * Returns 0 if the callback succeeds else not 0.
> +        *
> +        * After this callback is called, no other callback will be called
> +        * again and the tracing instance will be deleted automatically by
> +        * libustconsumer. After this call, the user must not use the libustconsumer instance.
> +        */
> +       int (*on_trace_end)(struct ustconsumer_instance *instance);
> +
> +       /**
> +        * The library's data.
> +        */
> +       void *user_data;
> +};
> +
> +/**
> + * ustconsumer_new_instance - Is called to create a new tracing session.
> + *
> + * @callbacks:    Pointer to a callbacks structure that contain the user
> + *                callbacks and data.
> + * @sock_path:    Path to the socket used for communication with the traced app
> + *
> + * Returns the instance if the function succeeds else NULL.
> + */
> +struct ustconsumer_instance *
> +ustconsumer_new_instance(
> +       struct ustconsumer_callbacks *callbacks, char *sock_path);
> +
> +/**
> + * ustconsumer_delete_instance - Is called to free a ustconsumer_instance struct
> + *
> + * @instance: The tracing session instance that needs to be freed.
> + *
> + * This function should only be called if the instance has not been started,
> + * as it will automatically be called at the end of ustconsumer_start_instance.
> + */
> +void ustconsumer_delete_instance(struct ustconsumer_instance *instance);
> +
> +/**
> + * ustconsumer_init_instance - Is called to initiliaze a new tracing session
> + *
> + * @instance: The tracing session instance that needs to be started.
> + *
> + * Returns 0 if the function succeeds.
> + *
> + * This function must be called between ustconsumer_new_instance and
> + * ustconsumer_start_instance. It sets up the communication between the library
> + * and the tracing application.
> + */
> +int ustconsumer_init_instance(struct ustconsumer_instance *instance);
> +
> +/**
> + * ustconsumer_start_instance - Is called to start a new tracing session.
> + *
> + * @instance: The tracing session instance that needs to be started.
> + *
> + * Returns 0 if the function succeeds.
> + *
> + * This is a blocking function. The caller will be blocked on it until the
> + * tracing session is stopped by the user using ustconsumer_stop_instance or until
> + * the traced application terminates
> + */
> +int ustconsumer_start_instance(struct ustconsumer_instance *instance);
> +
> +/**
> + * ustconsumer_stop_instance - Is called to stop a tracing session.
> + *
> + * @instance: The tracing session instance that needs to be stoped.
> + * @send_msg: If true, a message will be sent to the listening thread through
> + *            the daemon socket to force it to return from the poll syscall
> + *            and realize that it must close. This is not necessary if the
> + *            instance is being stopped as part of an interrupt handler, as
> + *            the interrupt itself will cause poll to return.
> + *
> + * Returns 0 if the function succeeds.
> + *
> + * This function returns immediately, it only tells libustconsumer to stop the
> + * instance. The on_trace_end callback will be called when the tracing session
> + * will really be stopped. The instance is deleted automatically by libustconsumer
> + * after on_trace_end is called.
> + */
> +int ustconsumer_stop_instance(struct ustconsumer_instance *instance, int send_msg);
> +
> +#endif /* _USTCONSUMER_H */
> +
> diff --git a/include/ust/ustd.h b/include/ust/ustd.h
> deleted file mode 100644
> index 6336e69..0000000
> --- a/include/ust/ustd.h
> +++ /dev/null
> @@ -1,287 +0,0 @@
> -/*
> - * libustd header file
> - *
> - * Copyright 2005-2010 -
> - *              Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
> - * Copyright 2010-
> - *              Oumarou Dicko <oumarou.dicko at polymtl.ca>
> - *              Michael Sills-Lavoie <michael.sills-lavoie at polymtl.ca>
> - *              Alexis Halle <alexis.halle at polymtl.ca>
> - *
> - * This library is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU Lesser General Public
> - * License as published by the Free Software Foundation; either
> - * version 2.1 of the License, or (at your option) any later version.
> - *
> - * This library is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public
> - * License along with this library; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> - */
> -
> -#ifndef USTD_H
> -#define USTD_H
> -
> -#include <pthread.h>
> -#include <dirent.h>
> -#include <ust/kcompat/kcompat.h>
> -#include <urcu/list.h>
> -
> -#define USTD_DEFAULT_TRACE_PATH "/tmp/usttrace"
> -
> -struct ustcomm_sock;
> -
> -struct buffer_info {
> -       char *name;
> -       char *trace;
> -       char *channel;
> -       int channel_cpu;
> -
> -       pid_t pid;
> -       int app_sock;
> -       /* The pipe file descriptor */
> -       int pipe_fd;
> -
> -       int shmid;
> -       int bufstruct_shmid;
> -
> -       /* the buffer memory */
> -       void *mem;
> -       /* buffer size */
> -       int memlen;
> -       /* number of subbuffers in buffer */
> -       int n_subbufs;
> -       /* size of each subbuffer */
> -       int subbuf_size;
> -
> -       /* the buffer information struct */
> -       void *bufstruct_mem;
> -
> -       long consumed_old;
> -
> -       s64 pidunique;
> -
> -       void *user_data;
> -};
> -
> -struct libustd_callbacks;
> -
> -/**
> - * struct libustd_instance - Contains the data associated with a trace instance.
> - * The lib user can read but MUST NOT change any attributes but callbacks.
> - * @callbacks: Contains the necessary callbacks for a tracing session.
> - */
> -struct libustd_instance {
> -       struct libustd_callbacks *callbacks;
> -       int quit_program;
> -       int is_init;
> -       struct cds_list_head connections;
> -       int epoll_fd;
> -       struct ustcomm_sock *listen_sock;
> -       char *sock_path;
> -       pthread_mutex_t mutex;
> -       int active_buffers;
> -};
> -
> -/**
> -* struct libustd_callbacks - Contains the necessary callbacks for a tracing
> -* session. The user can set the unnecessary functions to NULL if he does not
> -* need them.
> -*/
> -struct libustd_callbacks {
> -       /**
> -        * on_open_buffer - Is called after a buffer is attached to process memory
> -        *
> -        * @data: pointer to the callbacks structure that has been passed to the
> -        *        library.
> -        * @buf: structure that contains the data associated with the buffer
> -        *
> -        * Returns 0 if the callback succeeds else not 0.
> -        *
> -        * It has to be thread safe, because it is called by many threads.
> -        */
> -       int (*on_open_buffer)(struct libustd_callbacks *data,
> -                               struct buffer_info *buf);
> -
> -       /**
> -        * on_close_buffer - Is called after a buffer is detached from process memory
> -        *
> -        * @data: pointer to the callbacks structure that has been passed to the
> -        *        library.
> -        * @buf: structure that contains the data associated with the buffer
> -        *
> -        * Returns 0 if the callback succeeds else not 0.
> -        *
> -        * It has to be thread safe, because it is called by many threads.
> -        */
> -       int (*on_close_buffer)(struct libustd_callbacks *data,
> -                               struct buffer_info *buf);
> -
> -       /**
> -        * on_read_subbuffer - Is called after a subbuffer is a reserved.
> -        *
> -        * @data: pointer to the callbacks structure that has been passed to the
> -        *        library.
> -        * @buf: structure that contains the data associated with the buffer
> -        *
> -        * Returns 0 if the callback succeeds else not 0.
> -        *
> -        * It has to be thread safe, because it is called by many threads.
> -        */
> -       int (*on_read_subbuffer)(struct libustd_callbacks *data,
> -                               struct buffer_info *buf);
> -
> -       /**
> -        * on_read_partial_subbuffer - Is called when an incomplete subbuffer
> -        *                             is being salvaged from an app crash
> -        *
> -        * @data: pointer to the callbacks structure that has been passed to the
> -        *        library.
> -        * @buf: structure that contains the data associated with the buffer
> -        * @subbuf_index: index of the subbuffer to read in the buffer
> -        * @valid_length: number of bytes considered safe to read
> -        *
> -        * Returns 0 if the callback succeeds else not 0.
> -        *
> -        * It has to be thread safe, because it is called by many threads.
> -        */
> -       int (*on_read_partial_subbuffer)(struct libustd_callbacks *data,
> -                                       struct buffer_info *buf,
> -                                       long subbuf_index,
> -                                       unsigned long valid_length);
> -
> -       /**
> -        * on_put_error - Is called when a put error has occured and the last
> -        *                subbuffer read is no longer safe to keep
> -        *
> -        * @data: pointer to the callbacks structure that has been passed to the
> -        *        library.
> -        * @buf: structure that contains the data associated with the buffer
> -        *
> -        * Returns 0 if the callback succeeds else not 0.
> -        *
> -        * It has to be thread safe, because it is called by many threads.
> -        */
> -       int (*on_put_error)(struct libustd_callbacks *data,
> -                               struct buffer_info *buf);
> -
> -       /**
> -        * on_new_thread - Is called when a new thread is created
> -        *
> -        * @data: pointer to the callbacks structure that has been passed to the
> -        *        library.
> -        *
> -        * Returns 0 if the callback succeeds else not 0.
> -        *
> -        * It has to be thread safe, because it is called by many threads.
> -        */
> -       int (*on_new_thread)(struct libustd_callbacks *data);
> -
> -       /**
> -        * on_close_thread - Is called just before a thread is destroyed
> -        *
> -        * @data: pointer to the callbacks structure that has been passed to the
> -        *        library.
> -        *
> -        * Returns 0 if the callback succeeds else not 0.
> -        *
> -        * It has to be thread safe, because it is called by many threads.
> -        */
> -       int (*on_close_thread)(struct libustd_callbacks *data);
> -
> -       /**
> -        * on_trace_end - Is called at the very end of the tracing session. At
> -        * this time, everything has been closed and the threads have
> -        * been destroyed.
> -        *
> -        * @instance: pointer to the instance structure that has been passed to
> -        *            the library.
> -        *
> -        * Returns 0 if the callback succeeds else not 0.
> -        *
> -        * After this callback is called, no other callback will be called
> -        * again and the tracing instance will be deleted automatically by
> -        * libustd. After this call, the user must not use the libustd instance.
> -        */
> -       int (*on_trace_end)(struct libustd_instance *instance);
> -
> -       /**
> -        * The library's data.
> -        */
> -       void *user_data;
> -};
> -
> -/**
> - * libustd_new_instance - Is called to create a new tracing session.
> - *
> - * @callbacks:    Pointer to a callbacks structure that contain the user
> - *                callbacks and data.
> - * @sock_path:    Path to the socket used for communication with the traced app
> - *
> - * Returns the instance if the function succeeds else NULL.
> - */
> -struct libustd_instance *
> -libustd_new_instance(
> -       struct libustd_callbacks *callbacks, char *sock_path);
> -
> -/**
> - * libustd_delete_instance - Is called to free a libustd_instance struct
> - *
> - * @instance: The tracing session instance that needs to be freed.
> - *
> - * This function should only be called if the instance has not been started,
> - * as it will automatically be called at the end of libustd_start_instance.
> - */
> -void libustd_delete_instance(struct libustd_instance *instance);
> -
> -/**
> - * libustd_init_instance - Is called to initiliaze a new tracing session
> - *
> - * @instance: The tracing session instance that needs to be started.
> - *
> - * Returns 0 if the function succeeds.
> - *
> - * This function must be called between libustd_new_instance and
> - * libustd_start_instance. It sets up the communication between the library
> - * and the tracing application.
> - */
> -int libustd_init_instance(struct libustd_instance *instance);
> -
> -/**
> - * libustd_start_instance - Is called to start a new tracing session.
> - *
> - * @instance: The tracing session instance that needs to be started.
> - *
> - * Returns 0 if the function succeeds.
> - *
> - * This is a blocking function. The caller will be blocked on it until the
> - * tracing session is stopped by the user using libustd_stop_instance or until
> - * the traced application terminates
> - */
> -int libustd_start_instance(struct libustd_instance *instance);
> -
> -/**
> - * libustd_stop_instance - Is called to stop a tracing session.
> - *
> - * @instance: The tracing session instance that needs to be stoped.
> - * @send_msg: If true, a message will be sent to the listening thread through
> - *            the daemon socket to force it to return from the poll syscall
> - *            and realize that it must close. This is not necessary if the
> - *            instance is being stopped as part of an interrupt handler, as
> - *            the interrupt itself will cause poll to return.
> - *
> - * Returns 0 if the function succeeds.
> - *
> - * This function returns immediately, it only tells libustd to stop the
> - * instance. The on_trace_end callback will be called when the tracing session
> - * will really be stopped. The instance is deleted automatically by libustd
> - * after on_trace_end is called.
> - */
> -int libustd_stop_instance(struct libustd_instance *instance, int send_msg);
> -
> -#endif /* USTD_H */
> -
> diff --git a/libust/tracectl.c b/libust/tracectl.c
> index a7da945..b783c76 100644
> --- a/libust/tracectl.c
> +++ b/libust/tracectl.c
> @@ -122,10 +122,10 @@ static void print_trace_events(FILE *fp)
>         unlock_trace_events();
>  }
>
> -static int connect_ustd(void)
> +static int connect_ustconsumer(void)
>  {
>         int result, fd;
> -       char default_daemon_path[] = SOCK_DIR "/ustd";
> +       char default_daemon_path[] = SOCK_DIR "/ustconsumer";
>         char *explicit_daemon_path, *daemon_path;
>
>         explicit_daemon_path = getenv("UST_DAEMON_SOCKET");
> @@ -139,7 +139,7 @@ static int connect_ustd(void)
>
>         result = ustcomm_connect_path(daemon_path, &fd);
>         if (result < 0) {
> -               WARN("connect_ustd failed, daemon_path: %s",
> +               WARN("connect_ustconsumer failed, daemon_path: %s",
>                      daemon_path);
>                 return result;
>         }
> @@ -194,12 +194,12 @@ static void inform_consumer_daemon(const char *trace_name)
>         struct ust_trace *trace;
>         const char *ch_name;
>
> -       sock = connect_ustd();
> +       sock = connect_ustconsumer();
>         if (sock < 0) {
>                 return;
>         }
>
> -       DBG("Connected to ustd");
> +       DBG("Connected to ustconsumer");
>
>         ltt_lock_traces();
>
> @@ -1007,7 +1007,7 @@ static void process_client_cmd(struct ustcomm_header *recv_header,
>                 if (!sock_path_env) {
>                         result = ustcomm_pack_single_field(reply_header,
>                                                            sock_msg,
> -                                                          SOCK_DIR "/ustd");
> +                                                          SOCK_DIR "/ustconsumer");
>
>                 } else {
>                         result = ustcomm_pack_single_field(reply_header,
> @@ -1496,7 +1496,7 @@ static void stop_listener(void)
>  }
>
>  /* This destructor keeps the process alive for a few seconds in order
> - * to leave time to ustd to connect to its buffers. This is necessary
> + * to leave time for ustconsumer to connect to its buffers. This is necessary
>   * for programs whose execution is very short. It is also useful in all
>   * programs when tracing is started close to the end of the program
>   * execution.
> diff --git a/libustcmd/ustcmd.c b/libustcmd/ustcmd.c
> index 2c16e75..62c117f 100644
> --- a/libustcmd/ustcmd.c
> +++ b/libustcmd/ustcmd.c
> @@ -104,7 +104,7 @@ pid_t *ustcmd_get_online_pids(void)
>                 }
>
>                 if (dirent->d_type != DT_DIR &&
> -                   !!strcmp(dirent->d_name, "ustd")) {
> +                   !!strcmp(dirent->d_name, "ust-consumer")) {
>
>                         sscanf(dirent->d_name, "%u", (unsigned int *) &ret[i]);
>                         /* FIXME: Here we previously called pid_is_online, which
> diff --git a/libustconsumer/Makefile.am b/libustconsumer/Makefile.am
> new file mode 100644
> index 0000000..1f87479
> --- /dev/null
> +++ b/libustconsumer/Makefile.am
> @@ -0,0 +1,16 @@
> +AM_CPPFLAGS = -I$(top_srcdir)/libust -I$(top_srcdir)/libustcomm \
> +       -I$(top_srcdir)/include
> +AM_CFLAGS = -fno-strict-aliasing
> +
> +lib_LTLIBRARIES = libustconsumer.la
> +
> +libustconsumer_la_SOURCES = libustconsumer.c lowlevel.c lowlevel.h
> +
> +libustconsumer_la_LDFLAGS = -no-undefined -version-info 0:0:0
> +
> +libustconsumer_la_LIBADD = \
> +       -lpthread \
> +       $(top_builddir)/snprintf/libustsnprintf.la \
> +       $(top_builddir)/libustcomm/libustcomm.la
> +
> +libustconsumer_la_CFLAGS = -fno-strict-aliasing
> diff --git a/libustconsumer/libustconsumer.c b/libustconsumer/libustconsumer.c
> new file mode 100644
> index 0000000..6cb3dbf
> --- /dev/null
> +++ b/libustconsumer/libustconsumer.c
> @@ -0,0 +1,891 @@
> +/* Copyright (C) 2009  Pierre-Marc Fournier
> + *               2010  Alexis Halle
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
> + */
> +
> +#define _GNU_SOURCE
> +
> +#include <sys/epoll.h>
> +#include <sys/shm.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
> +#include <pthread.h>
> +#include <signal.h>
> +
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <assert.h>
> +
> +#include <ust/ustconsumer.h>
> +#include "lowlevel.h"
> +#include "usterr.h"
> +#include "ustcomm.h"
> +
> +#define GET_SUBBUF_OK 1
> +#define GET_SUBBUF_DONE 0
> +#define GET_SUBBUF_DIED 2
> +
> +#define PUT_SUBBUF_OK 1
> +#define PUT_SUBBUF_DIED 0
> +#define PUT_SUBBUF_PUSHED 2
> +#define PUT_SUBBUF_DONE 3
> +
> +#define UNIX_PATH_MAX 108
> +
> +static int get_subbuffer(struct buffer_info *buf)
> +{
> +       struct ustcomm_header _send_hdr, *send_hdr;
> +       struct ustcomm_header _recv_hdr, *recv_hdr;
> +       struct ustcomm_buffer_info _send_msg, _recv_msg;
> +       struct ustcomm_buffer_info *send_msg, *recv_msg;
> +       int result;
> +
> +       send_hdr = &_send_hdr;
> +       recv_hdr = &_recv_hdr;
> +       send_msg = &_send_msg;
> +       recv_msg = &_recv_msg;
> +
> +       result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace,
> +                                         buf->channel, buf->channel_cpu);
> +       if (result < 0) {
> +               return result;
> +       }
> +
> +       send_hdr->command = GET_SUBBUFFER;
> +
> +       result = ustcomm_req(buf->app_sock, send_hdr, (char *)send_msg,
> +                            recv_hdr, (char *)recv_msg);
> +       if ((result < 0 && (errno == ECONNRESET || errno == EPIPE)) ||
> +           result == 0) {
> +               DBG("app died while being traced");
> +               return GET_SUBBUF_DIED;
> +       } else if (result < 0) {
> +               ERR("get_subbuffer: ustcomm_req failed");
> +               return result;
> +       }
> +
> +       if (!recv_hdr->result) {
> +               DBG("got subbuffer %s", buf->name);
> +               buf->consumed_old = recv_msg->consumed_old;
> +               return GET_SUBBUF_OK;
> +       } else if (recv_hdr->result == -ENODATA) {
> +               DBG("For buffer %s, the trace was not found. This likely means"
> +                   " it was destroyed by the user.", buf->name);
> +               return GET_SUBBUF_DIED;
> +       }
> +
> +       DBG("error getting subbuffer %s", buf->name);
> +       return recv_hdr->result;
> +}
> +
> +static int put_subbuffer(struct buffer_info *buf)
> +{
> +       struct ustcomm_header _send_hdr, *send_hdr;
> +       struct ustcomm_header _recv_hdr, *recv_hdr;
> +       struct ustcomm_buffer_info _send_msg, *send_msg;
> +       int result;
> +
> +       send_hdr = &_send_hdr;
> +       recv_hdr = &_recv_hdr;
> +       send_msg = &_send_msg;
> +
> +       result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace,
> +                                         buf->channel, buf->channel_cpu);
> +       if (result < 0) {
> +               return result;
> +       }
> +
> +       send_hdr->command = PUT_SUBBUFFER;
> +       send_msg->consumed_old = buf->consumed_old;
> +
> +       result = ustcomm_req(buf->app_sock, send_hdr, (char *)send_msg,
> +                            recv_hdr, NULL);
> +       if ((result < 0 && (errno == ECONNRESET || errno == EPIPE)) ||
> +           result == 0) {
> +               DBG("app died while being traced");
> +               return PUT_SUBBUF_DIED;
> +       } else if (result < 0) {
> +               ERR("put_subbuffer: ustcomm_req failed");
> +               return result;
> +       }
> +
> +       if (!recv_hdr->result) {
> +               DBG("put subbuffer %s", buf->name);
> +               return PUT_SUBBUF_OK;
> +       } else if (recv_hdr->result == -ENODATA) {
> +               DBG("For buffer %s, the trace was not found. This likely means"
> +                   " it was destroyed by the user.", buf->name);
> +               return PUT_SUBBUF_DIED;
> +       }
> +
> +       DBG("error getting subbuffer %s", buf->name);
> +       return recv_hdr->result;
> +}
> +
> +void decrement_active_buffers(void *arg)
> +{
> +       struct ustconsumer_instance *instance = arg;
> +       pthread_mutex_lock(&instance->mutex);
> +       instance->active_buffers--;
> +       pthread_mutex_unlock(&instance->mutex);
> +}
> +
> +static int get_pidunique(int sock, s64 *pidunique)
> +{
> +       struct ustcomm_header _send_hdr, *send_hdr;
> +       struct ustcomm_header _recv_hdr, *recv_hdr;
> +       struct ustcomm_pidunique _recv_msg, *recv_msg;
> +       int result;
> +
> +       send_hdr = &_send_hdr;
> +       recv_hdr = &_recv_hdr;
> +       recv_msg = &_recv_msg;
> +
> +       memset(send_hdr, 0, sizeof(*send_hdr));
> +
> +       send_hdr->command = GET_PIDUNIQUE;
> +       result = ustcomm_req(sock, send_hdr, NULL, recv_hdr, (char *)recv_msg);
> +       if (result < 1) {
> +               return -ENOTCONN;
> +       }
> +       if (recv_hdr->result < 0) {
> +               ERR("App responded with error: %s", strerror(recv_hdr->result));
> +               return recv_hdr->result;
> +       }
> +
> +       *pidunique = recv_msg->pidunique;
> +
> +       return 0;
> +}
> +
> +static int get_buf_shmid_pipe_fd(int sock, struct buffer_info *buf,
> +                                int *buf_shmid, int *buf_struct_shmid,
> +                                int *buf_pipe_fd)
> +{
> +       struct ustcomm_header _send_hdr, *send_hdr;
> +       struct ustcomm_header _recv_hdr, *recv_hdr;
> +       struct ustcomm_buffer_info _send_msg, *send_msg;
> +       struct ustcomm_buffer_info _recv_msg, *recv_msg;
> +       int result, recv_pipe_fd;
> +
> +       send_hdr = &_send_hdr;
> +       recv_hdr = &_recv_hdr;
> +       send_msg = &_send_msg;
> +       recv_msg = &_recv_msg;
> +
> +       result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace,
> +                                         buf->channel, buf->channel_cpu);
> +       if (result < 0) {
> +               ERR("Failed to pack buffer info");
> +               return result;
> +       }
> +
> +       send_hdr->command = GET_BUF_SHMID_PIPE_FD;
> +
> +       result = ustcomm_send(sock, send_hdr, (char *)send_msg);
> +       if (result < 1) {
> +               ERR("Failed to send request");
> +               return -ENOTCONN;
> +       }
> +       result = ustcomm_recv_fd(sock, recv_hdr, (char *)recv_msg, &recv_pipe_fd);
> +       if (result < 1) {
> +               ERR("Failed to receive message and fd");
> +               return -ENOTCONN;
> +       }
> +       if (recv_hdr->result < 0) {
> +               ERR("App responded with error %s", strerror(recv_hdr->result));
> +               return recv_hdr->result;
> +       }
> +
> +       *buf_shmid = recv_msg->buf_shmid;
> +       *buf_struct_shmid = recv_msg->buf_struct_shmid;
> +       *buf_pipe_fd = recv_pipe_fd;
> +
> +       return 0;
> +}
> +
> +static int get_subbuf_num_size(int sock, struct buffer_info *buf,
> +                              int *subbuf_num, int *subbuf_size)
> +{
> +       struct ustcomm_header _send_hdr, *send_hdr;
> +       struct ustcomm_header _recv_hdr, *recv_hdr;
> +       struct ustcomm_channel_info _send_msg, *send_msg;
> +       struct ustcomm_channel_info _recv_msg, *recv_msg;
> +       int result;
> +
> +       send_hdr = &_send_hdr;
> +       recv_hdr = &_recv_hdr;
> +       send_msg = &_send_msg;
> +       recv_msg = &_recv_msg;
> +
> +       result = ustcomm_pack_channel_info(send_hdr, send_msg, buf->trace,
> +                                          buf->channel);
> +       if (result < 0) {
> +               return result;
> +       }
> +
> +       send_hdr->command = GET_SUBBUF_NUM_SIZE;
> +
> +       result = ustcomm_req(sock, send_hdr, (char *)send_msg,
> +                            recv_hdr, (char *)recv_msg);
> +       if (result < 1) {
> +               return -ENOTCONN;
> +       }
> +
> +       *subbuf_num = recv_msg->subbuf_num;
> +       *subbuf_size = recv_msg->subbuf_size;
> +
> +       return recv_hdr->result;
> +}
> +
> +
> +static int notify_buffer_mapped(int sock, struct buffer_info *buf)
> +{
> +       struct ustcomm_header _send_hdr, *send_hdr;
> +       struct ustcomm_header _recv_hdr, *recv_hdr;
> +       struct ustcomm_buffer_info _send_msg, *send_msg;
> +       int result;
> +
> +       send_hdr = &_send_hdr;
> +       recv_hdr = &_recv_hdr;
> +       send_msg = &_send_msg;
> +
> +       result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace,
> +                                         buf->channel, buf->channel_cpu);
> +       if (result < 0) {
> +               return result;
> +       }
> +
> +       send_hdr->command = NOTIFY_BUF_MAPPED;
> +
> +       result = ustcomm_req(sock, send_hdr, (char *)send_msg,
> +                            recv_hdr, NULL);
> +       if (result < 1) {
> +               return -ENOTCONN;
> +       }
> +
> +       return recv_hdr->result;
> +}
> +
> +
> +struct buffer_info *connect_buffer(struct ustconsumer_instance *instance, pid_t pid,
> +                                  const char *trace, const char *channel,
> +                                  int channel_cpu)
> +{
> +       struct buffer_info *buf;
> +       int result;
> +       struct shmid_ds shmds;
> +
> +       buf = (struct buffer_info *) zmalloc(sizeof(struct buffer_info));
> +       if(buf == NULL) {
> +               ERR("add_buffer: insufficient memory");
> +               return NULL;
> +       }
> +
> +       buf->trace = strdup(trace);
> +       if (!buf->trace) {
> +               goto free_buf;
> +       }
> +
> +       buf->channel = strdup(channel);
> +       if (!buf->channel) {
> +               goto free_buf_trace;
> +       }
> +
> +       result = asprintf(&buf->name, "%s_%d", channel, channel_cpu);
> +       if (result < 0 || buf->name == NULL) {
> +               goto free_buf_channel;
> +       }
> +
> +       buf->channel_cpu = channel_cpu;
> +       buf->pid = pid;
> +
> +       result = ustcomm_connect_app(buf->pid, &buf->app_sock);
> +       if(result) {
> +               WARN("unable to connect to process, it probably died before we were able to connect");
> +               goto free_buf_name;
> +       }
> +
> +       /* get pidunique */
> +       result = get_pidunique(buf->app_sock, &buf->pidunique);
> +       if (result < 0) {
> +               ERR("Failed to get pidunique");
> +               goto close_app_sock;
> +       }
> +
> +       /* get shmid and pipe fd */
> +       result = get_buf_shmid_pipe_fd(buf->app_sock, buf, &buf->shmid,
> +                                      &buf->bufstruct_shmid, &buf->pipe_fd);
> +       if (result < 0) {
> +               ERR("Failed to get buf_shmid and pipe_fd");
> +               goto close_app_sock;
> +       } else {
> +               struct stat temp;
> +               fstat(buf->pipe_fd, &temp);
> +               if (!S_ISFIFO(temp.st_mode)) {
> +                       ERR("Didn't receive a fifo from the app");
> +                       goto close_app_sock;
> +               }
> +       }
> +
> +
> +       /* get number of subbufs and subbuf size */
> +       result = get_subbuf_num_size(buf->app_sock, buf, &buf->n_subbufs,
> +                                    &buf->subbuf_size);
> +       if (result < 0) {
> +               ERR("Failed to get subbuf number and size");
> +               goto close_fifo;
> +       }
> +
> +       /* attach memory */
> +       buf->mem = shmat(buf->shmid, NULL, 0);
> +       if(buf->mem == (void *) 0) {
> +               PERROR("shmat");
> +               goto close_fifo;
> +       }
> +       DBG("successfully attached buffer memory");
> +
> +       buf->bufstruct_mem = shmat(buf->bufstruct_shmid, NULL, 0);
> +       if(buf->bufstruct_mem == (void *) 0) {
> +               PERROR("shmat");
> +               goto shmdt_mem;
> +       }
> +       DBG("successfully attached buffer bufstruct memory");
> +
> +       /* obtain info on the memory segment */
> +       result = shmctl(buf->shmid, IPC_STAT, &shmds);
> +       if(result == -1) {
> +               PERROR("shmctl");
> +               goto shmdt_bufstruct_mem;
> +       }
> +       buf->memlen = shmds.shm_segsz;
> +
> +       /* Notify the application that we have mapped the buffer */
> +       result = notify_buffer_mapped(buf->app_sock, buf);
> +       if (result < 0) {
> +               goto shmdt_bufstruct_mem;
> +       }
> +
> +       if(instance->callbacks->on_open_buffer)
> +               instance->callbacks->on_open_buffer(instance->callbacks, buf);
> +
> +       pthread_mutex_lock(&instance->mutex);
> +       instance->active_buffers++;
> +       pthread_mutex_unlock(&instance->mutex);
> +
> +       return buf;
> +
> +shmdt_bufstruct_mem:
> +       shmdt(buf->bufstruct_mem);
> +
> +shmdt_mem:
> +       shmdt(buf->mem);
> +
> +close_fifo:
> +       close(buf->pipe_fd);
> +
> +close_app_sock:
> +       close(buf->app_sock);
> +
> +free_buf_name:
> +       free(buf->name);
> +
> +free_buf_channel:
> +       free(buf->channel);
> +
> +free_buf_trace:
> +       free(buf->trace);
> +
> +free_buf:
> +       free(buf);
> +       return NULL;
> +}
> +
> +static void destroy_buffer(struct ustconsumer_callbacks *callbacks,
> +                       struct buffer_info *buf)
> +{
> +       int result;
> +
> +       result = close(buf->app_sock);
> +       if(result == -1) {
> +               WARN("problem calling ustcomm_close_app");
> +       }
> +
> +       result = shmdt(buf->mem);
> +       if(result == -1) {
> +               PERROR("shmdt");
> +       }
> +
> +       result = shmdt(buf->bufstruct_mem);
> +       if(result == -1) {
> +               PERROR("shmdt");
> +       }
> +
> +       if(callbacks->on_close_buffer)
> +               callbacks->on_close_buffer(callbacks, buf);
> +
> +       free(buf);
> +}
> +
> +int consumer_loop(struct ustconsumer_instance *instance, struct buffer_info *buf)
> +{
> +       int result, read_result;
> +       char read_buf;
> +
> +       pthread_cleanup_push(decrement_active_buffers, instance);
> +
> +       for(;;) {
> +               read_result = read(buf->pipe_fd, &read_buf, 1);
> +               /* get the subbuffer */
> +               if (read_result == 1) {
> +                       result = get_subbuffer(buf);
> +                       if (result < 0) {
> +                               ERR("error getting subbuffer");
> +                               continue;
> +                       } else if (result == GET_SUBBUF_DIED) {
> +                               finish_consuming_dead_subbuffer(instance->callbacks, buf);
> +                               break;
> +                       }
> +               } else if ((read_result == -1 && (errno == ECONNRESET || errno == EPIPE)) ||
> +                          result == 0) {
> +                       DBG("App died while being traced");
> +                       finish_consuming_dead_subbuffer(instance->callbacks, buf);
> +                       break;
> +               }
> +
> +               if(instance->callbacks->on_read_subbuffer)
> +                       instance->callbacks->on_read_subbuffer(instance->callbacks, buf);
> +
> +               /* put the subbuffer */
> +               result = put_subbuffer(buf);
> +               if(result == -1) {
> +                       ERR("unknown error putting subbuffer (channel=%s)", buf->name);
> +                       break;
> +               }
> +               else if(result == PUT_SUBBUF_PUSHED) {
> +                       ERR("Buffer overflow (channel=%s), reader pushed. This channel will not be usable passed this point.", buf->name);
> +                       break;
> +               }
> +               else if(result == PUT_SUBBUF_DIED) {
> +                       DBG("application died while putting subbuffer");
> +                       /* Skip the first subbuffer. We are not sure it is trustable
> +                        * because the put_subbuffer() did not complete.
> +                        */
> +                       if(instance->callbacks->on_put_error)
> +                               instance->callbacks->on_put_error(instance->callbacks, buf);
> +
> +                       finish_consuming_dead_subbuffer(instance->callbacks, buf);
> +                       break;
> +               }
> +               else if(result == PUT_SUBBUF_DONE) {
> +                       /* Done with this subbuffer */
> +                       /* FIXME: add a case where this branch is used? Upon
> +                        * normal trace termination, at put_subbuf time, a
> +                        * special last-subbuffer code could be returned by
> +                        * the listener.
> +                        */
> +                       break;
> +               }
> +               else if(result == PUT_SUBBUF_OK) {
> +               }
> +       }
> +
> +       DBG("thread for buffer %s is stopping", buf->name);
> +
> +       /* FIXME: destroy, unalloc... */
> +
> +       pthread_cleanup_pop(1);
> +
> +       return 0;
> +}
> +
> +struct consumer_thread_args {
> +       pid_t pid;
> +       const char *trace;
> +       const char *channel;
> +       int channel_cpu;
> +       struct ustconsumer_instance *instance;
> +};
> +
> +void *consumer_thread(void *arg)
> +{
> +       struct buffer_info *buf;
> +       struct consumer_thread_args *args = (struct consumer_thread_args *) arg;
> +       int result;
> +       sigset_t sigset;
> +
> +       if(args->instance->callbacks->on_new_thread)
> +               args->instance->callbacks->on_new_thread(args->instance->callbacks);
> +
> +       /* Block signals that should be handled by the main thread. */
> +       result = sigemptyset(&sigset);
> +       if(result == -1) {
> +               PERROR("sigemptyset");
> +               goto end;
> +       }
> +       result = sigaddset(&sigset, SIGTERM);
> +       if(result == -1) {
> +               PERROR("sigaddset");
> +               goto end;
> +       }
> +       result = sigaddset(&sigset, SIGINT);
> +       if(result == -1) {
> +               PERROR("sigaddset");
> +               goto end;
> +       }
> +       result = sigprocmask(SIG_BLOCK, &sigset, NULL);
> +       if(result == -1) {
> +               PERROR("sigprocmask");
> +               goto end;
> +       }
> +
> +       buf = connect_buffer(args->instance, args->pid, args->trace,
> +                            args->channel, args->channel_cpu);
> +       if(buf == NULL) {
> +               ERR("failed to connect to buffer");
> +               goto end;
> +       }
> +
> +       consumer_loop(args->instance, buf);
> +
> +       destroy_buffer(args->instance->callbacks, buf);
> +
> +       end:
> +
> +       if(args->instance->callbacks->on_close_thread)
> +               args->instance->callbacks->on_close_thread(args->instance->callbacks);
> +
> +       free((void *)args->channel);
> +       free(args);
> +       return NULL;
> +}
> +
> +int start_consuming_buffer(struct ustconsumer_instance *instance, pid_t pid,
> +                          const char *trace, const char *channel,
> +                          int channel_cpu)
> +{
> +       pthread_t thr;
> +       struct consumer_thread_args *args;
> +       int result;
> +
> +       DBG("beginning of start_consuming_buffer: args: pid %d bufname %s_%d", pid, channel,
> +           channel_cpu);
> +
> +       args = (struct consumer_thread_args *) zmalloc(sizeof(struct consumer_thread_args));
> +       if (!args) {
> +               return -ENOMEM;
> +       }
> +
> +       args->pid = pid;
> +       args->trace = strdup(trace);
> +       args->channel = strdup(channel);
> +       args->channel_cpu = channel_cpu;
> +       args->instance = instance;
> +       DBG("beginning2 of start_consuming_buffer: args: pid %d trace %s"
> +           " bufname %s_%d", args->pid, args->channel, args->channel_cpu);
> +
> +       result = pthread_create(&thr, NULL, consumer_thread, args);
> +       if(result == -1) {
> +               ERR("pthread_create failed");
> +               return -1;
> +       }
> +       result = pthread_detach(thr);
> +       if(result == -1) {
> +               ERR("pthread_detach failed");
> +               return -1;
> +       }
> +       DBG("end of start_consuming_buffer: args: pid %d trace %s "
> +           "bufname %s_%d", args->pid, args->channel, args->channel_cpu);
> +
> +       return 0;
> +}
> +static void process_client_cmd(int sock, struct ustcomm_header *req_header,
> +                              char *recvbuf, struct ustconsumer_instance *instance)
> +{
> +       int result;
> +       struct ustcomm_header _res_header;
> +       struct ustcomm_header *res_header = &_res_header;
> +       struct ustcomm_buffer_info *buf_inf;
> +
> +       DBG("Processing client command");
> +
> +       switch (req_header->command) {
> +       case CONSUME_BUFFER:
> +
> +               buf_inf = (struct ustcomm_buffer_info *)recvbuf;
> +               result = ustcomm_unpack_buffer_info(buf_inf);
> +               if (result < 0) {
> +                       ERR("Couldn't unpack buffer info");
> +                       return;
> +               }
> +
> +               DBG("Going to consume trace %s buffer %s_%d in process %d",
> +                   buf_inf->trace, buf_inf->channel, buf_inf->ch_cpu,
> +                   buf_inf->pid);
> +               result = start_consuming_buffer(instance, buf_inf->pid,
> +                                               buf_inf->trace,
> +                                               buf_inf->channel,
> +                                               buf_inf->ch_cpu);
> +               if (result < 0) {
> +                       ERR("error in add_buffer");
> +                       return;
> +               }
> +
> +               res_header->result = 0;
> +               break;
> +       case EXIT:
> +               res_header->result = 0;
> +               /* Only there to force poll to return */
> +               break;
> +       default:
> +               res_header->result = -EINVAL;
> +               WARN("unknown command: %d", req_header->command);
> +       }
> +
> +       if (ustcomm_send(sock, res_header, NULL) <= 0) {
> +               ERR("couldn't send command response");
> +       }
> +}
> +
> +#define MAX_EVENTS 10
> +
> +int ustconsumer_start_instance(struct ustconsumer_instance *instance)
> +{
> +       struct ustcomm_header recv_hdr;
> +       char recv_buf[USTCOMM_BUFFER_SIZE];
> +       struct ustcomm_sock *epoll_sock;
> +       struct epoll_event events[MAX_EVENTS];
> +       struct sockaddr addr;
> +       int result, epoll_fd, accept_fd, nfds, i, addr_size, timeout;
> +
> +       if(!instance->is_init) {
> +               ERR("libustconsumer instance not initialized");
> +               return 1;
> +       }
> +       epoll_fd = instance->epoll_fd;
> +
> +       timeout = -1;
> +
> +       /* app loop */
> +       for(;;) {
> +               nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, timeout);
> +               if (nfds == -1 && errno == EINTR) {
> +                       /* Caught signal */
> +               } else if (nfds == -1) {
> +                       PERROR("ustconsumer_start_instance: epoll_wait failed");
> +                       continue;
> +               }
> +
> +               for (i = 0; i < nfds; ++i) {
> +                       epoll_sock = (struct ustcomm_sock *)events[i].data.ptr;
> +                       if (epoll_sock == instance->listen_sock) {
> +                               addr_size = sizeof(struct sockaddr);
> +                               accept_fd = accept(epoll_sock->fd,
> +                                                  &addr,
> +                                                  (socklen_t *)&addr_size);
> +                               if (accept_fd == -1) {
> +                                       PERROR("ustconsumer_start_instance: "
> +                                              "accept failed");
> +                                       continue;
> +                               }
> +                               ustcomm_init_sock(accept_fd, epoll_fd,
> +                                                &instance->connections);
> +                       } else {
> +                               result = ustcomm_recv(epoll_sock->fd, &recv_hdr,
> +                                                     recv_buf);
> +                               if (result < 1) {
> +                                       ustcomm_del_sock(epoll_sock, 0);
> +                               } else {
> +                                       process_client_cmd(epoll_sock->fd,
> +                                                          &recv_hdr, recv_buf,
> +                                                          instance);
> +                               }
> +
> +                       }
> +               }
> +
> +               if (instance->quit_program) {
> +                       pthread_mutex_lock(&instance->mutex);
> +                       if(instance->active_buffers == 0) {
> +                               pthread_mutex_unlock(&instance->mutex);
> +                               break;
> +                       }
> +                       pthread_mutex_unlock(&instance->mutex);
> +                       timeout = 100;
> +               }
> +       }
> +
> +       if(instance->callbacks->on_trace_end)
> +               instance->callbacks->on_trace_end(instance);
> +
> +       ustconsumer_delete_instance(instance);
> +
> +       return 0;
> +}
> +
> +/* FIXME: threads and connections !? */
> +void ustconsumer_delete_instance(struct ustconsumer_instance *instance)
> +{
> +       if (instance->is_init) {
> +               ustcomm_del_named_sock(instance->listen_sock, 0);
> +               close(instance->epoll_fd);
> +       }
> +
> +       pthread_mutex_destroy(&instance->mutex);
> +       free(instance->sock_path);
> +       free(instance);
> +}
> +
> +/* FIXME: Do something about the fixed path length, maybe get rid
> + * of the whole concept and use a pipe?
> + */
> +int ustconsumer_stop_instance(struct ustconsumer_instance *instance, int send_msg)
> +{
> +       int result;
> +       int fd;
> +       int bytes = 0;
> +
> +       char msg[] = "exit";
> +
> +       instance->quit_program = 1;
> +
> +       if(!send_msg)
> +               return 0;
> +
> +       /* Send a message through the socket to force poll to return */
> +
> +       struct sockaddr_un addr;
> +
> +       result = fd = socket(PF_UNIX, SOCK_STREAM, 0);
> +       if(result == -1) {
> +               PERROR("socket");
> +               return 1;
> +       }
> +
> +       addr.sun_family = AF_UNIX;
> +
> +       strncpy(addr.sun_path, instance->sock_path, UNIX_PATH_MAX);
> +       addr.sun_path[UNIX_PATH_MAX-1] = '\0';
> +
> +       result = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
> +       if(result == -1) {
> +               PERROR("connect");
> +       }
> +
> +       while(bytes != sizeof(msg))
> +               bytes += send(fd, msg, sizeof(msg), 0);
> +
> +       close(fd);
> +
> +       return 0;
> +}
> +
> +struct ustconsumer_instance
> +*ustconsumer_new_instance(struct ustconsumer_callbacks *callbacks,
> +                     char *sock_path)
> +{
> +       struct ustconsumer_instance *instance =
> +               zmalloc(sizeof(struct ustconsumer_instance));
> +       if(!instance) {
> +               return NULL;
> +       }
> +
> +       instance->callbacks = callbacks;
> +       instance->quit_program = 0;
> +       instance->is_init = 0;
> +       instance->active_buffers = 0;
> +       pthread_mutex_init(&instance->mutex, NULL);
> +
> +       if (sock_path) {
> +               instance->sock_path = strdup(sock_path);
> +       } else {
> +               instance->sock_path = NULL;
> +       }
> +
> +       return instance;
> +}
> +
> +static int init_ustconsumer_socket(struct ustconsumer_instance *instance)
> +{
> +       char *name;
> +
> +       if (instance->sock_path) {
> +               if (asprintf(&name, "%s", instance->sock_path) < 0) {
> +                       ERR("ustcomm_init_ustconsumer : asprintf failed (sock_path %s)",
> +                           instance->sock_path);
> +                       return -1;
> +               }
> +       } else {
> +               int result;
> +
> +               /* Only check if socket dir exists if we are using the default directory */
> +               result = ensure_dir_exists(SOCK_DIR);
> +               if (result == -1) {
> +                       ERR("Unable to create socket directory %s", SOCK_DIR);
> +                       return -1;
> +               }
> +
> +               if (asprintf(&name, "%s/%s", SOCK_DIR, "ustconsumer") < 0) {
> +                       ERR("ustcomm_init_ustconsumer : asprintf failed (%s/ustconsumer)",
> +                           SOCK_DIR);
> +                       return -1;
> +               }
> +       }
> +
> +       /* Set up epoll */
> +       instance->epoll_fd = epoll_create(MAX_EVENTS);
> +       if (instance->epoll_fd == -1) {
> +               ERR("epoll_create failed, start instance bailing");
> +               goto free_name;
> +       }
> +
> +       /* Create the named socket */
> +       instance->listen_sock = ustcomm_init_named_socket(name,
> +                                                         instance->epoll_fd);
> +       if(!instance->listen_sock) {
> +               ERR("error initializing named socket at %s", name);
> +               goto close_epoll;
> +       }
> +
> +       CDS_INIT_LIST_HEAD(&instance->connections);
> +
> +       free(name);
> +
> +       return 0;
> +
> +close_epoll:
> +       close(instance->epoll_fd);
> +free_name:
> +       free(name);
> +
> +       return -1;
> +}
> +
> +int ustconsumer_init_instance(struct ustconsumer_instance *instance)
> +{
> +       int result;
> +       result = init_ustconsumer_socket(instance);
> +       if(result == -1) {
> +               ERR("failed to initialize socket");
> +               return 1;
> +       }
> +       instance->is_init = 1;
> +       return 0;
> +}
> +
> diff --git a/libustconsumer/lowlevel.c b/libustconsumer/lowlevel.c
> new file mode 100644
> index 0000000..7eb124b
> --- /dev/null
> +++ b/libustconsumer/lowlevel.c
> @@ -0,0 +1,143 @@
> +/* Copyright (C) 2009  Pierre-Marc Fournier
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
> + */
> +
> +#include <stdlib.h>
> +#include <assert.h>
> +#include <byteswap.h>
> +
> +#include "ust/ustconsumer.h"
> +#include "buffers.h"
> +#include "tracer.h"
> +#include "usterr.h"
> +
> +/* This truncates to an offset in the buffer. */
> +#define USTD_BUFFER_TRUNC(offset, bufinfo) \
> +       ((offset) & (~(((bufinfo)->subbuf_size*(bufinfo)->n_subbufs)-1)))
> +
> +#define LTT_MAGIC_NUMBER 0x00D6B7ED
> +#define LTT_REV_MAGIC_NUMBER 0xEDB7D600
> +
> +/* Returns the size of a subbuffer size. This is the size that
> + * will need to be written to disk.
> + *
> + * @subbuffer: pointer to the beginning of the subbuffer (the
> + *             beginning of its header)
> + */
> +
> +size_t subbuffer_data_size(void *subbuf)
> +{
> +       struct ltt_subbuffer_header *header = subbuf;
> +       int reverse;
> +       u32 data_size;
> +
> +       if(header->magic_number == LTT_MAGIC_NUMBER) {
> +               reverse = 0;
> +       }
> +       else if(header->magic_number == LTT_REV_MAGIC_NUMBER) {
> +               reverse = 1;
> +       }
> +       else {
> +               return -1;
> +       }
> +
> +       data_size = header->sb_size;
> +       if(reverse)
> +               data_size = bswap_32(data_size);
> +
> +       return data_size;
> +}
> +
> +
> +void finish_consuming_dead_subbuffer(struct ustconsumer_callbacks *callbacks, struct buffer_info *buf)
> +{
> +       struct ust_buffer *ustbuf = buf->bufstruct_mem;
> +
> +       long write_offset = uatomic_read(&ustbuf->offset);
> +       long consumed_offset = uatomic_read(&ustbuf->consumed);
> +
> +       long i_subbuf;
> +
> +       DBG("processing dead buffer (%s)", buf->name);
> +       DBG("consumed offset is %ld (%s)", consumed_offset, buf->name);
> +       DBG("write offset is %ld (%s)", write_offset, buf->name);
> +
> +       /* First subbuf that we need to consume now. It is not modulo'd.
> +        * Consumed_offset is the next byte to consume.  */
> +       long first_subbuf = consumed_offset / buf->subbuf_size;
> +       /* Last subbuf that we need to consume now. It is not modulo'd.
> +        * Write_offset is the next place to write so write_offset-1 is the
> +        * last place written. */
> +       long last_subbuf = (write_offset - 1) / buf->subbuf_size;
> +
> +       DBG("first_subbuf=%ld", first_subbuf);
> +       DBG("last_subbuf=%ld", last_subbuf);
> +
> +       if(last_subbuf - first_subbuf >= buf->n_subbufs) {
> +               DBG("an overflow has occurred, nothing can be recovered");
> +               return;
> +       }
> +
> +       /* Iterate on subbuffers to recover. */
> +       for(i_subbuf = first_subbuf % buf->n_subbufs; ; i_subbuf++, i_subbuf %= buf->n_subbufs) {
> +               /* commit_seq is the offset in the buffer of the end of the last sequential commit.
> +                * Bytes beyond this limit cannot be recovered. This is a free-running counter. */
> +               long commit_seq = uatomic_read(&ustbuf->commit_seq[i_subbuf]);
> +
> +               unsigned long valid_length = buf->subbuf_size;
> +               long n_subbufs_order = get_count_order(buf->n_subbufs);
> +               long commit_seq_mask = (~0UL >> n_subbufs_order);
> +
> +               struct ltt_subbuffer_header *header = (struct ltt_subbuffer_header *)((char *)buf->mem+i_subbuf*buf->subbuf_size);
> +
> +               if((commit_seq & commit_seq_mask) == 0) {
> +                       /* There is nothing to do. */
> +                       /* FIXME: is this needed? */
> +                       break;
> +               }
> +
> +               /* Check if subbuf was fully written. This is from Mathieu's algorithm/paper. */
> +               /* FIXME: not sure data_size = 0xffffffff when the buffer is not full. It might
> +                * take the value of the header size initially */
> +               if (((commit_seq - buf->subbuf_size) & commit_seq_mask)
> +                   - (USTD_BUFFER_TRUNC(consumed_offset, buf) >> n_subbufs_order) == 0
> +                    && header->data_size != 0xffffffff && header->sb_size != 0xffffffff) {
> +                       /* If it was, we only check the data_size. This is the amount of valid data at
> +                        * the beginning of the subbuffer. */
> +                       valid_length = header->data_size;
> +                       DBG("writing full subbuffer (%d) with valid_length = %ld", i_subbuf, valid_length);
> +               }
> +               else {
> +                       /* If the subbuffer was not fully written, then we don't check data_size because
> +                        * it hasn't been written yet. Instead we check commit_seq and use it to choose
> +                        * a value for data_size. The viewer will need this value when parsing.
> +                        */
> +
> +                       valid_length = commit_seq & (buf->subbuf_size-1);
> +                       DBG("writing unfull subbuffer (%d) with valid_length = %ld", i_subbuf, valid_length);
> +                       header->data_size = valid_length;
> +                       header->sb_size = PAGE_ALIGN(valid_length);
> +                       assert(i_subbuf == (last_subbuf % buf->n_subbufs));
> +               }
> +
> +               if(callbacks->on_read_partial_subbuffer)
> +                       callbacks->on_read_partial_subbuffer(callbacks, buf, i_subbuf, valid_length);
> +
> +               if(i_subbuf == last_subbuf % buf->n_subbufs)
> +                       break;
> +       }
> +}
> +
> diff --git a/libustconsumer/lowlevel.h b/libustconsumer/lowlevel.h
> new file mode 100644
> index 0000000..6ae6476
> --- /dev/null
> +++ b/libustconsumer/lowlevel.h
> @@ -0,0 +1,35 @@
> +/*
> + * lowlevel libustd header file
> + *
> + * Copyright 2005-2010 -
> + *              Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
> + * Copyright 2010-
> + *              Oumarou Dicko <oumarou.dicko at polymtl.ca>
> + *              Michael Sills-Lavoie <michael.sills-lavoie at polymtl.ca>
> + *              Alexis Halle <alexis.halle at polymtl.ca>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef LOWLEVEL_H
> +#define LOWLEVEL_H
> +
> +#include "ust/ustconsumer.h"
> +
> +void finish_consuming_dead_subbuffer(struct ustconsumer_callbacks *callbacks, struct buffer_info *buf);
> +size_t subbuffer_data_size(void *subbuf);
> +
> +#endif /* LOWLEVEL_H */
> +
> diff --git a/libustd/Makefile.am b/libustd/Makefile.am
> deleted file mode 100644
> index 1b9a961..0000000
> --- a/libustd/Makefile.am
> +++ /dev/null
> @@ -1,17 +0,0 @@
> -AM_CPPFLAGS = -I$(top_srcdir)/libust -I$(top_srcdir)/libustcomm \
> -       -I$(top_srcdir)/include
> -AM_CFLAGS = -fno-strict-aliasing
> -
> -lib_LTLIBRARIES = libustd.la
> -
> -libustd_la_SOURCES = libustd.c lowlevel.c lowlevel.h
> -
> -libustd_la_LDFLAGS = -no-undefined -version-info 0:0:0
> -
> -libustd_la_LIBADD = \
> -       -lpthread \
> -       $(top_builddir)/snprintf/libustsnprintf.la \
> -       $(top_builddir)/libustcomm/libustcomm.la
> -
> -libustd_la_CFLAGS = -fno-strict-aliasing
> -
> diff --git a/libustd/libustd.c b/libustd/libustd.c
> deleted file mode 100644
> index 0dc6940..0000000
> --- a/libustd/libustd.c
> +++ /dev/null
> @@ -1,891 +0,0 @@
> -/* Copyright (C) 2009  Pierre-Marc Fournier
> - *               2010  Alexis Halle
> - *
> - * This library is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU Lesser General Public
> - * License as published by the Free Software Foundation; either
> - * version 2.1 of the License, or (at your option) any later version.
> - *
> - * This library is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public
> - * License along with this library; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
> - */
> -
> -#define _GNU_SOURCE
> -
> -#include <sys/epoll.h>
> -#include <sys/shm.h>
> -#include <sys/types.h>
> -#include <sys/stat.h>
> -#include <unistd.h>
> -#include <pthread.h>
> -#include <signal.h>
> -
> -#include <stdlib.h>
> -#include <stdio.h>
> -#include <string.h>
> -#include <errno.h>
> -#include <assert.h>
> -
> -#include <ust/ustd.h>
> -#include "lowlevel.h"
> -#include "usterr.h"
> -#include "ustcomm.h"
> -
> -#define GET_SUBBUF_OK 1
> -#define GET_SUBBUF_DONE 0
> -#define GET_SUBBUF_DIED 2
> -
> -#define PUT_SUBBUF_OK 1
> -#define PUT_SUBBUF_DIED 0
> -#define PUT_SUBBUF_PUSHED 2
> -#define PUT_SUBBUF_DONE 3
> -
> -#define UNIX_PATH_MAX 108
> -
> -static int get_subbuffer(struct buffer_info *buf)
> -{
> -       struct ustcomm_header _send_hdr, *send_hdr;
> -       struct ustcomm_header _recv_hdr, *recv_hdr;
> -       struct ustcomm_buffer_info _send_msg, _recv_msg;
> -       struct ustcomm_buffer_info *send_msg, *recv_msg;
> -       int result;
> -
> -       send_hdr = &_send_hdr;
> -       recv_hdr = &_recv_hdr;
> -       send_msg = &_send_msg;
> -       recv_msg = &_recv_msg;
> -
> -       result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace,
> -                                         buf->channel, buf->channel_cpu);
> -       if (result < 0) {
> -               return result;
> -       }
> -
> -       send_hdr->command = GET_SUBBUFFER;
> -
> -       result = ustcomm_req(buf->app_sock, send_hdr, (char *)send_msg,
> -                            recv_hdr, (char *)recv_msg);
> -       if ((result < 0 && (errno == ECONNRESET || errno == EPIPE)) ||
> -           result == 0) {
> -               DBG("app died while being traced");
> -               return GET_SUBBUF_DIED;
> -       } else if (result < 0) {
> -               ERR("get_subbuffer: ustcomm_req failed");
> -               return result;
> -       }
> -
> -       if (!recv_hdr->result) {
> -               DBG("got subbuffer %s", buf->name);
> -               buf->consumed_old = recv_msg->consumed_old;
> -               return GET_SUBBUF_OK;
> -       } else if (recv_hdr->result == -ENODATA) {
> -               DBG("For buffer %s, the trace was not found. This likely means"
> -                   " it was destroyed by the user.", buf->name);
> -               return GET_SUBBUF_DIED;
> -       }
> -
> -       DBG("error getting subbuffer %s", buf->name);
> -       return recv_hdr->result;
> -}
> -
> -static int put_subbuffer(struct buffer_info *buf)
> -{
> -       struct ustcomm_header _send_hdr, *send_hdr;
> -       struct ustcomm_header _recv_hdr, *recv_hdr;
> -       struct ustcomm_buffer_info _send_msg, *send_msg;
> -       int result;
> -
> -       send_hdr = &_send_hdr;
> -       recv_hdr = &_recv_hdr;
> -       send_msg = &_send_msg;
> -
> -       result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace,
> -                                         buf->channel, buf->channel_cpu);
> -       if (result < 0) {
> -               return result;
> -       }
> -
> -       send_hdr->command = PUT_SUBBUFFER;
> -       send_msg->consumed_old = buf->consumed_old;
> -
> -       result = ustcomm_req(buf->app_sock, send_hdr, (char *)send_msg,
> -                            recv_hdr, NULL);
> -       if ((result < 0 && (errno == ECONNRESET || errno == EPIPE)) ||
> -           result == 0) {
> -               DBG("app died while being traced");
> -               return PUT_SUBBUF_DIED;
> -       } else if (result < 0) {
> -               ERR("put_subbuffer: ustcomm_req failed");
> -               return result;
> -       }
> -
> -       if (!recv_hdr->result) {
> -               DBG("put subbuffer %s", buf->name);
> -               return PUT_SUBBUF_OK;
> -       } else if (recv_hdr->result == -ENODATA) {
> -               DBG("For buffer %s, the trace was not found. This likely means"
> -                   " it was destroyed by the user.", buf->name);
> -               return PUT_SUBBUF_DIED;
> -       }
> -
> -       DBG("error getting subbuffer %s", buf->name);
> -       return recv_hdr->result;
> -}
> -
> -void decrement_active_buffers(void *arg)
> -{
> -       struct libustd_instance *instance = arg;
> -       pthread_mutex_lock(&instance->mutex);
> -       instance->active_buffers--;
> -       pthread_mutex_unlock(&instance->mutex);
> -}
> -
> -static int get_pidunique(int sock, s64 *pidunique)
> -{
> -       struct ustcomm_header _send_hdr, *send_hdr;
> -       struct ustcomm_header _recv_hdr, *recv_hdr;
> -       struct ustcomm_pidunique _recv_msg, *recv_msg;
> -       int result;
> -
> -       send_hdr = &_send_hdr;
> -       recv_hdr = &_recv_hdr;
> -       recv_msg = &_recv_msg;
> -
> -       memset(send_hdr, 0, sizeof(*send_hdr));
> -
> -       send_hdr->command = GET_PIDUNIQUE;
> -       result = ustcomm_req(sock, send_hdr, NULL, recv_hdr, (char *)recv_msg);
> -       if (result < 1) {
> -               return -ENOTCONN;
> -       }
> -       if (recv_hdr->result < 0) {
> -               ERR("App responded with error: %s", strerror(recv_hdr->result));
> -               return recv_hdr->result;
> -       }
> -
> -       *pidunique = recv_msg->pidunique;
> -
> -       return 0;
> -}
> -
> -static int get_buf_shmid_pipe_fd(int sock, struct buffer_info *buf,
> -                                int *buf_shmid, int *buf_struct_shmid,
> -                                int *buf_pipe_fd)
> -{
> -       struct ustcomm_header _send_hdr, *send_hdr;
> -       struct ustcomm_header _recv_hdr, *recv_hdr;
> -       struct ustcomm_buffer_info _send_msg, *send_msg;
> -       struct ustcomm_buffer_info _recv_msg, *recv_msg;
> -       int result, recv_pipe_fd;
> -
> -       send_hdr = &_send_hdr;
> -       recv_hdr = &_recv_hdr;
> -       send_msg = &_send_msg;
> -       recv_msg = &_recv_msg;
> -
> -       result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace,
> -                                         buf->channel, buf->channel_cpu);
> -       if (result < 0) {
> -               ERR("Failed to pack buffer info");
> -               return result;
> -       }
> -
> -       send_hdr->command = GET_BUF_SHMID_PIPE_FD;
> -
> -       result = ustcomm_send(sock, send_hdr, (char *)send_msg);
> -       if (result < 1) {
> -               ERR("Failed to send request");
> -               return -ENOTCONN;
> -       }
> -       result = ustcomm_recv_fd(sock, recv_hdr, (char *)recv_msg, &recv_pipe_fd);
> -       if (result < 1) {
> -               ERR("Failed to receive message and fd");
> -               return -ENOTCONN;
> -       }
> -       if (recv_hdr->result < 0) {
> -               ERR("App responded with error %s", strerror(recv_hdr->result));
> -               return recv_hdr->result;
> -       }
> -
> -       *buf_shmid = recv_msg->buf_shmid;
> -       *buf_struct_shmid = recv_msg->buf_struct_shmid;
> -       *buf_pipe_fd = recv_pipe_fd;
> -
> -       return 0;
> -}
> -
> -static int get_subbuf_num_size(int sock, struct buffer_info *buf,
> -                              int *subbuf_num, int *subbuf_size)
> -{
> -       struct ustcomm_header _send_hdr, *send_hdr;
> -       struct ustcomm_header _recv_hdr, *recv_hdr;
> -       struct ustcomm_channel_info _send_msg, *send_msg;
> -       struct ustcomm_channel_info _recv_msg, *recv_msg;
> -       int result;
> -
> -       send_hdr = &_send_hdr;
> -       recv_hdr = &_recv_hdr;
> -       send_msg = &_send_msg;
> -       recv_msg = &_recv_msg;
> -
> -       result = ustcomm_pack_channel_info(send_hdr, send_msg, buf->trace,
> -                                          buf->channel);
> -       if (result < 0) {
> -               return result;
> -       }
> -
> -       send_hdr->command = GET_SUBBUF_NUM_SIZE;
> -
> -       result = ustcomm_req(sock, send_hdr, (char *)send_msg,
> -                            recv_hdr, (char *)recv_msg);
> -       if (result < 1) {
> -               return -ENOTCONN;
> -       }
> -
> -       *subbuf_num = recv_msg->subbuf_num;
> -       *subbuf_size = recv_msg->subbuf_size;
> -
> -       return recv_hdr->result;
> -}
> -
> -
> -static int notify_buffer_mapped(int sock, struct buffer_info *buf)
> -{
> -       struct ustcomm_header _send_hdr, *send_hdr;
> -       struct ustcomm_header _recv_hdr, *recv_hdr;
> -       struct ustcomm_buffer_info _send_msg, *send_msg;
> -       int result;
> -
> -       send_hdr = &_send_hdr;
> -       recv_hdr = &_recv_hdr;
> -       send_msg = &_send_msg;
> -
> -       result = ustcomm_pack_buffer_info(send_hdr, send_msg, buf->trace,
> -                                         buf->channel, buf->channel_cpu);
> -       if (result < 0) {
> -               return result;
> -       }
> -
> -       send_hdr->command = NOTIFY_BUF_MAPPED;
> -
> -       result = ustcomm_req(sock, send_hdr, (char *)send_msg,
> -                            recv_hdr, NULL);
> -       if (result < 1) {
> -               return -ENOTCONN;
> -       }
> -
> -       return recv_hdr->result;
> -}
> -
> -
> -struct buffer_info *connect_buffer(struct libustd_instance *instance, pid_t pid,
> -                                  const char *trace, const char *channel,
> -                                  int channel_cpu)
> -{
> -       struct buffer_info *buf;
> -       int result;
> -       struct shmid_ds shmds;
> -
> -       buf = (struct buffer_info *) zmalloc(sizeof(struct buffer_info));
> -       if(buf == NULL) {
> -               ERR("add_buffer: insufficient memory");
> -               return NULL;
> -       }
> -
> -       buf->trace = strdup(trace);
> -       if (!buf->trace) {
> -               goto free_buf;
> -       }
> -
> -       buf->channel = strdup(channel);
> -       if (!buf->channel) {
> -               goto free_buf_trace;
> -       }
> -
> -       result = asprintf(&buf->name, "%s_%d", channel, channel_cpu);
> -       if (result < 0 || buf->name == NULL) {
> -               goto free_buf_channel;
> -       }
> -
> -       buf->channel_cpu = channel_cpu;
> -       buf->pid = pid;
> -
> -       result = ustcomm_connect_app(buf->pid, &buf->app_sock);
> -       if(result) {
> -               WARN("unable to connect to process, it probably died before we were able to connect");
> -               goto free_buf_name;
> -       }
> -
> -       /* get pidunique */
> -       result = get_pidunique(buf->app_sock, &buf->pidunique);
> -       if (result < 0) {
> -               ERR("Failed to get pidunique");
> -               goto close_app_sock;
> -       }
> -
> -       /* get shmid and pipe fd */
> -       result = get_buf_shmid_pipe_fd(buf->app_sock, buf, &buf->shmid,
> -                                      &buf->bufstruct_shmid, &buf->pipe_fd);
> -       if (result < 0) {
> -               ERR("Failed to get buf_shmid and pipe_fd");
> -               goto close_app_sock;
> -       } else {
> -               struct stat temp;
> -               fstat(buf->pipe_fd, &temp);
> -               if (!S_ISFIFO(temp.st_mode)) {
> -                       ERR("Didn't receive a fifo from the app");
> -                       goto close_app_sock;
> -               }
> -       }
> -
> -
> -       /* get number of subbufs and subbuf size */
> -       result = get_subbuf_num_size(buf->app_sock, buf, &buf->n_subbufs,
> -                                    &buf->subbuf_size);
> -       if (result < 0) {
> -               ERR("Failed to get subbuf number and size");
> -               goto close_fifo;
> -       }
> -
> -       /* attach memory */
> -       buf->mem = shmat(buf->shmid, NULL, 0);
> -       if(buf->mem == (void *) 0) {
> -               PERROR("shmat");
> -               goto close_fifo;
> -       }
> -       DBG("successfully attached buffer memory");
> -
> -       buf->bufstruct_mem = shmat(buf->bufstruct_shmid, NULL, 0);
> -       if(buf->bufstruct_mem == (void *) 0) {
> -               PERROR("shmat");
> -               goto shmdt_mem;
> -       }
> -       DBG("successfully attached buffer bufstruct memory");
> -
> -       /* obtain info on the memory segment */
> -       result = shmctl(buf->shmid, IPC_STAT, &shmds);
> -       if(result == -1) {
> -               PERROR("shmctl");
> -               goto shmdt_bufstruct_mem;
> -       }
> -       buf->memlen = shmds.shm_segsz;
> -
> -       /* Notify the application that we have mapped the buffer */
> -       result = notify_buffer_mapped(buf->app_sock, buf);
> -       if (result < 0) {
> -               goto shmdt_bufstruct_mem;
> -       }
> -
> -       if(instance->callbacks->on_open_buffer)
> -               instance->callbacks->on_open_buffer(instance->callbacks, buf);
> -
> -       pthread_mutex_lock(&instance->mutex);
> -       instance->active_buffers++;
> -       pthread_mutex_unlock(&instance->mutex);
> -
> -       return buf;
> -
> -shmdt_bufstruct_mem:
> -       shmdt(buf->bufstruct_mem);
> -
> -shmdt_mem:
> -       shmdt(buf->mem);
> -
> -close_fifo:
> -       close(buf->pipe_fd);
> -
> -close_app_sock:
> -       close(buf->app_sock);
> -
> -free_buf_name:
> -       free(buf->name);
> -
> -free_buf_channel:
> -       free(buf->channel);
> -
> -free_buf_trace:
> -       free(buf->trace);
> -
> -free_buf:
> -       free(buf);
> -       return NULL;
> -}
> -
> -static void destroy_buffer(struct libustd_callbacks *callbacks,
> -                       struct buffer_info *buf)
> -{
> -       int result;
> -
> -       result = close(buf->app_sock);
> -       if(result == -1) {
> -               WARN("problem calling ustcomm_close_app");
> -       }
> -
> -       result = shmdt(buf->mem);
> -       if(result == -1) {
> -               PERROR("shmdt");
> -       }
> -
> -       result = shmdt(buf->bufstruct_mem);
> -       if(result == -1) {
> -               PERROR("shmdt");
> -       }
> -
> -       if(callbacks->on_close_buffer)
> -               callbacks->on_close_buffer(callbacks, buf);
> -
> -       free(buf);
> -}
> -
> -int consumer_loop(struct libustd_instance *instance, struct buffer_info *buf)
> -{
> -       int result, read_result;
> -       char read_buf;
> -
> -       pthread_cleanup_push(decrement_active_buffers, instance);
> -
> -       for(;;) {
> -               read_result = read(buf->pipe_fd, &read_buf, 1);
> -               /* get the subbuffer */
> -               if (read_result == 1) {
> -                       result = get_subbuffer(buf);
> -                       if (result < 0) {
> -                               ERR("error getting subbuffer");
> -                               continue;
> -                       } else if (result == GET_SUBBUF_DIED) {
> -                               finish_consuming_dead_subbuffer(instance->callbacks, buf);
> -                               break;
> -                       }
> -               } else if ((read_result == -1 && (errno == ECONNRESET || errno == EPIPE)) ||
> -                          result == 0) {
> -                       DBG("App died while being traced");
> -                       finish_consuming_dead_subbuffer(instance->callbacks, buf);
> -                       break;
> -               }
> -
> -               if(instance->callbacks->on_read_subbuffer)
> -                       instance->callbacks->on_read_subbuffer(instance->callbacks, buf);
> -
> -               /* put the subbuffer */
> -               result = put_subbuffer(buf);
> -               if(result == -1) {
> -                       ERR("unknown error putting subbuffer (channel=%s)", buf->name);
> -                       break;
> -               }
> -               else if(result == PUT_SUBBUF_PUSHED) {
> -                       ERR("Buffer overflow (channel=%s), reader pushed. This channel will not be usable passed this point.", buf->name);
> -                       break;
> -               }
> -               else if(result == PUT_SUBBUF_DIED) {
> -                       DBG("application died while putting subbuffer");
> -                       /* Skip the first subbuffer. We are not sure it is trustable
> -                        * because the put_subbuffer() did not complete.
> -                        */
> -                       if(instance->callbacks->on_put_error)
> -                               instance->callbacks->on_put_error(instance->callbacks, buf);
> -
> -                       finish_consuming_dead_subbuffer(instance->callbacks, buf);
> -                       break;
> -               }
> -               else if(result == PUT_SUBBUF_DONE) {
> -                       /* Done with this subbuffer */
> -                       /* FIXME: add a case where this branch is used? Upon
> -                        * normal trace termination, at put_subbuf time, a
> -                        * special last-subbuffer code could be returned by
> -                        * the listener.
> -                        */
> -                       break;
> -               }
> -               else if(result == PUT_SUBBUF_OK) {
> -               }
> -       }
> -
> -       DBG("thread for buffer %s is stopping", buf->name);
> -
> -       /* FIXME: destroy, unalloc... */
> -
> -       pthread_cleanup_pop(1);
> -
> -       return 0;
> -}
> -
> -struct consumer_thread_args {
> -       pid_t pid;
> -       const char *trace;
> -       const char *channel;
> -       int channel_cpu;
> -       struct libustd_instance *instance;
> -};
> -
> -void *consumer_thread(void *arg)
> -{
> -       struct buffer_info *buf;
> -       struct consumer_thread_args *args = (struct consumer_thread_args *) arg;
> -       int result;
> -       sigset_t sigset;
> -
> -       if(args->instance->callbacks->on_new_thread)
> -               args->instance->callbacks->on_new_thread(args->instance->callbacks);
> -
> -       /* Block signals that should be handled by the main thread. */
> -       result = sigemptyset(&sigset);
> -       if(result == -1) {
> -               PERROR("sigemptyset");
> -               goto end;
> -       }
> -       result = sigaddset(&sigset, SIGTERM);
> -       if(result == -1) {
> -               PERROR("sigaddset");
> -               goto end;
> -       }
> -       result = sigaddset(&sigset, SIGINT);
> -       if(result == -1) {
> -               PERROR("sigaddset");
> -               goto end;
> -       }
> -       result = sigprocmask(SIG_BLOCK, &sigset, NULL);
> -       if(result == -1) {
> -               PERROR("sigprocmask");
> -               goto end;
> -       }
> -
> -       buf = connect_buffer(args->instance, args->pid, args->trace,
> -                            args->channel, args->channel_cpu);
> -       if(buf == NULL) {
> -               ERR("failed to connect to buffer");
> -               goto end;
> -       }
> -
> -       consumer_loop(args->instance, buf);
> -
> -       destroy_buffer(args->instance->callbacks, buf);
> -
> -       end:
> -
> -       if(args->instance->callbacks->on_close_thread)
> -               args->instance->callbacks->on_close_thread(args->instance->callbacks);
> -
> -       free((void *)args->channel);
> -       free(args);
> -       return NULL;
> -}
> -
> -int start_consuming_buffer(struct libustd_instance *instance, pid_t pid,
> -                          const char *trace, const char *channel,
> -                          int channel_cpu)
> -{
> -       pthread_t thr;
> -       struct consumer_thread_args *args;
> -       int result;
> -
> -       DBG("beginning of start_consuming_buffer: args: pid %d bufname %s_%d", pid, channel,
> -           channel_cpu);
> -
> -       args = (struct consumer_thread_args *) zmalloc(sizeof(struct consumer_thread_args));
> -       if (!args) {
> -               return -ENOMEM;
> -       }
> -
> -       args->pid = pid;
> -       args->trace = strdup(trace);
> -       args->channel = strdup(channel);
> -       args->channel_cpu = channel_cpu;
> -       args->instance = instance;
> -       DBG("beginning2 of start_consuming_buffer: args: pid %d trace %s"
> -           " bufname %s_%d", args->pid, args->channel, args->channel_cpu);
> -
> -       result = pthread_create(&thr, NULL, consumer_thread, args);
> -       if(result == -1) {
> -               ERR("pthread_create failed");
> -               return -1;
> -       }
> -       result = pthread_detach(thr);
> -       if(result == -1) {
> -               ERR("pthread_detach failed");
> -               return -1;
> -       }
> -       DBG("end of start_consuming_buffer: args: pid %d trace %s "
> -           "bufname %s_%d", args->pid, args->channel, args->channel_cpu);
> -
> -       return 0;
> -}
> -static void process_client_cmd(int sock, struct ustcomm_header *req_header,
> -                              char *recvbuf, struct libustd_instance *instance)
> -{
> -       int result;
> -       struct ustcomm_header _res_header;
> -       struct ustcomm_header *res_header = &_res_header;
> -       struct ustcomm_buffer_info *buf_inf;
> -
> -       DBG("Processing client command");
> -
> -       switch (req_header->command) {
> -       case CONSUME_BUFFER:
> -
> -               buf_inf = (struct ustcomm_buffer_info *)recvbuf;
> -               result = ustcomm_unpack_buffer_info(buf_inf);
> -               if (result < 0) {
> -                       ERR("Couldn't unpack buffer info");
> -                       return;
> -               }
> -
> -               DBG("Going to consume trace %s buffer %s_%d in process %d",
> -                   buf_inf->trace, buf_inf->channel, buf_inf->ch_cpu,
> -                   buf_inf->pid);
> -               result = start_consuming_buffer(instance, buf_inf->pid,
> -                                               buf_inf->trace,
> -                                               buf_inf->channel,
> -                                               buf_inf->ch_cpu);
> -               if (result < 0) {
> -                       ERR("error in add_buffer");
> -                       return;
> -               }
> -
> -               res_header->result = 0;
> -               break;
> -       case EXIT:
> -               res_header->result = 0;
> -               /* Only there to force poll to return */
> -               break;
> -       default:
> -               res_header->result = -EINVAL;
> -               WARN("unknown command: %d", req_header->command);
> -       }
> -
> -       if (ustcomm_send(sock, res_header, NULL) <= 0) {
> -               ERR("couldn't send command response");
> -       }
> -}
> -
> -#define MAX_EVENTS 10
> -
> -int libustd_start_instance(struct libustd_instance *instance)
> -{
> -       struct ustcomm_header recv_hdr;
> -       char recv_buf[USTCOMM_BUFFER_SIZE];
> -       struct ustcomm_sock *epoll_sock;
> -       struct epoll_event events[MAX_EVENTS];
> -       struct sockaddr addr;
> -       int result, epoll_fd, accept_fd, nfds, i, addr_size, timeout;
> -
> -       if(!instance->is_init) {
> -               ERR("libustd instance not initialized");
> -               return 1;
> -       }
> -       epoll_fd = instance->epoll_fd;
> -
> -       timeout = -1;
> -
> -       /* app loop */
> -       for(;;) {
> -               nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, timeout);
> -               if (nfds == -1 && errno == EINTR) {
> -                       /* Caught signal */
> -               } else if (nfds == -1) {
> -                       PERROR("libustd_start_instance: epoll_wait failed");
> -                       continue;
> -               }
> -
> -               for (i = 0; i < nfds; ++i) {
> -                       epoll_sock = (struct ustcomm_sock *)events[i].data.ptr;
> -                       if (epoll_sock == instance->listen_sock) {
> -                               addr_size = sizeof(struct sockaddr);
> -                               accept_fd = accept(epoll_sock->fd,
> -                                                  &addr,
> -                                                  (socklen_t *)&addr_size);
> -                               if (accept_fd == -1) {
> -                                       PERROR("libustd_start_instance: "
> -                                              "accept failed");
> -                                       continue;
> -                               }
> -                               ustcomm_init_sock(accept_fd, epoll_fd,
> -                                                &instance->connections);
> -                       } else {
> -                               result = ustcomm_recv(epoll_sock->fd, &recv_hdr,
> -                                                     recv_buf);
> -                               if (result < 1) {
> -                                       ustcomm_del_sock(epoll_sock, 0);
> -                               } else {
> -                                       process_client_cmd(epoll_sock->fd,
> -                                                          &recv_hdr, recv_buf,
> -                                                          instance);
> -                               }
> -
> -                       }
> -               }
> -
> -               if (instance->quit_program) {
> -                       pthread_mutex_lock(&instance->mutex);
> -                       if(instance->active_buffers == 0) {
> -                               pthread_mutex_unlock(&instance->mutex);
> -                               break;
> -                       }
> -                       pthread_mutex_unlock(&instance->mutex);
> -                       timeout = 100;
> -               }
> -       }
> -
> -       if(instance->callbacks->on_trace_end)
> -               instance->callbacks->on_trace_end(instance);
> -
> -       libustd_delete_instance(instance);
> -
> -       return 0;
> -}
> -
> -/* FIXME: threads and connections !? */
> -void libustd_delete_instance(struct libustd_instance *instance)
> -{
> -       if (instance->is_init) {
> -               ustcomm_del_named_sock(instance->listen_sock, 0);
> -               close(instance->epoll_fd);
> -       }
> -
> -       pthread_mutex_destroy(&instance->mutex);
> -       free(instance->sock_path);
> -       free(instance);
> -}
> -
> -/* FIXME: Do something about the fixed path length, maybe get rid
> - * of the whole concept and use a pipe?
> - */
> -int libustd_stop_instance(struct libustd_instance *instance, int send_msg)
> -{
> -       int result;
> -       int fd;
> -       int bytes = 0;
> -
> -       char msg[] = "exit";
> -
> -       instance->quit_program = 1;
> -
> -       if(!send_msg)
> -               return 0;
> -
> -       /* Send a message through the socket to force poll to return */
> -
> -       struct sockaddr_un addr;
> -
> -       result = fd = socket(PF_UNIX, SOCK_STREAM, 0);
> -       if(result == -1) {
> -               PERROR("socket");
> -               return 1;
> -       }
> -
> -       addr.sun_family = AF_UNIX;
> -
> -       strncpy(addr.sun_path, instance->sock_path, UNIX_PATH_MAX);
> -       addr.sun_path[UNIX_PATH_MAX-1] = '\0';
> -
> -       result = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
> -       if(result == -1) {
> -               PERROR("connect");
> -       }
> -
> -       while(bytes != sizeof(msg))
> -               bytes += send(fd, msg, sizeof(msg), 0);
> -
> -       close(fd);
> -
> -       return 0;
> -}
> -
> -struct libustd_instance
> -*libustd_new_instance(struct libustd_callbacks *callbacks,
> -                     char *sock_path)
> -{
> -       struct libustd_instance *instance =
> -               zmalloc(sizeof(struct libustd_instance));
> -       if(!instance) {
> -               return NULL;
> -       }
> -
> -       instance->callbacks = callbacks;
> -       instance->quit_program = 0;
> -       instance->is_init = 0;
> -       instance->active_buffers = 0;
> -       pthread_mutex_init(&instance->mutex, NULL);
> -
> -       if (sock_path) {
> -               instance->sock_path = strdup(sock_path);
> -       } else {
> -               instance->sock_path = NULL;
> -       }
> -
> -       return instance;
> -}
> -
> -static int init_ustd_socket(struct libustd_instance *instance)
> -{
> -       char *name;
> -
> -       if (instance->sock_path) {
> -               if (asprintf(&name, "%s", instance->sock_path) < 0) {
> -                       ERR("ustcomm_init_ustd : asprintf failed (sock_path %s)",
> -                           instance->sock_path);
> -                       return -1;
> -               }
> -       } else {
> -               int result;
> -
> -               /* Only check if socket dir exists if we are using the default directory */
> -               result = ensure_dir_exists(SOCK_DIR);
> -               if (result == -1) {
> -                       ERR("Unable to create socket directory %s", SOCK_DIR);
> -                       return -1;
> -               }
> -
> -               if (asprintf(&name, "%s/%s", SOCK_DIR, "ustd") < 0) {
> -                       ERR("ustcomm_init_ustd : asprintf failed (%s/ustd)",
> -                           SOCK_DIR);
> -                       return -1;
> -               }
> -       }
> -
> -       /* Set up epoll */
> -       instance->epoll_fd = epoll_create(MAX_EVENTS);
> -       if (instance->epoll_fd == -1) {
> -               ERR("epoll_create failed, start instance bailing");
> -               goto free_name;
> -       }
> -
> -       /* Create the named socket */
> -       instance->listen_sock = ustcomm_init_named_socket(name,
> -                                                         instance->epoll_fd);
> -       if(!instance->listen_sock) {
> -               ERR("error initializing named socket at %s", name);
> -               goto close_epoll;
> -       }
> -
> -       CDS_INIT_LIST_HEAD(&instance->connections);
> -
> -       free(name);
> -
> -       return 0;
> -
> -close_epoll:
> -       close(instance->epoll_fd);
> -free_name:
> -       free(name);
> -
> -       return -1;
> -}
> -
> -int libustd_init_instance(struct libustd_instance *instance)
> -{
> -       int result;
> -       result = init_ustd_socket(instance);
> -       if(result == -1) {
> -               ERR("failed to initialize socket");
> -               return 1;
> -       }
> -       instance->is_init = 1;
> -       return 0;
> -}
> -
> diff --git a/libustd/lowlevel.c b/libustd/lowlevel.c
> deleted file mode 100644
> index a8abf92..0000000
> --- a/libustd/lowlevel.c
> +++ /dev/null
> @@ -1,143 +0,0 @@
> -/* Copyright (C) 2009  Pierre-Marc Fournier
> - *
> - * This library is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU Lesser General Public
> - * License as published by the Free Software Foundation; either
> - * version 2.1 of the License, or (at your option) any later version.
> - *
> - * This library is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public
> - * License along with this library; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
> - */
> -
> -#include <stdlib.h>
> -#include <assert.h>
> -#include <byteswap.h>
> -
> -#include "ust/ustd.h"
> -#include "buffers.h"
> -#include "tracer.h"
> -#include "usterr.h"
> -
> -/* This truncates to an offset in the buffer. */
> -#define USTD_BUFFER_TRUNC(offset, bufinfo) \
> -       ((offset) & (~(((bufinfo)->subbuf_size*(bufinfo)->n_subbufs)-1)))
> -
> -#define LTT_MAGIC_NUMBER 0x00D6B7ED
> -#define LTT_REV_MAGIC_NUMBER 0xEDB7D600
> -
> -/* Returns the size of a subbuffer size. This is the size that
> - * will need to be written to disk.
> - *
> - * @subbuffer: pointer to the beginning of the subbuffer (the
> - *             beginning of its header)
> - */
> -
> -size_t subbuffer_data_size(void *subbuf)
> -{
> -       struct ltt_subbuffer_header *header = subbuf;
> -       int reverse;
> -       u32 data_size;
> -
> -       if(header->magic_number == LTT_MAGIC_NUMBER) {
> -               reverse = 0;
> -       }
> -       else if(header->magic_number == LTT_REV_MAGIC_NUMBER) {
> -               reverse = 1;
> -       }
> -       else {
> -               return -1;
> -       }
> -
> -       data_size = header->sb_size;
> -       if(reverse)
> -               data_size = bswap_32(data_size);
> -
> -       return data_size;
> -}
> -
> -
> -void finish_consuming_dead_subbuffer(struct libustd_callbacks *callbacks, struct buffer_info *buf)
> -{
> -       struct ust_buffer *ustbuf = buf->bufstruct_mem;
> -
> -       long write_offset = uatomic_read(&ustbuf->offset);
> -       long consumed_offset = uatomic_read(&ustbuf->consumed);
> -
> -       long i_subbuf;
> -
> -       DBG("processing dead buffer (%s)", buf->name);
> -       DBG("consumed offset is %ld (%s)", consumed_offset, buf->name);
> -       DBG("write offset is %ld (%s)", write_offset, buf->name);
> -
> -       /* First subbuf that we need to consume now. It is not modulo'd.
> -        * Consumed_offset is the next byte to consume.  */
> -       long first_subbuf = consumed_offset / buf->subbuf_size;
> -       /* Last subbuf that we need to consume now. It is not modulo'd.
> -        * Write_offset is the next place to write so write_offset-1 is the
> -        * last place written. */
> -       long last_subbuf = (write_offset - 1) / buf->subbuf_size;
> -
> -       DBG("first_subbuf=%ld", first_subbuf);
> -       DBG("last_subbuf=%ld", last_subbuf);
> -
> -       if(last_subbuf - first_subbuf >= buf->n_subbufs) {
> -               DBG("an overflow has occurred, nothing can be recovered");
> -               return;
> -       }
> -
> -       /* Iterate on subbuffers to recover. */
> -       for(i_subbuf = first_subbuf % buf->n_subbufs; ; i_subbuf++, i_subbuf %= buf->n_subbufs) {
> -               /* commit_seq is the offset in the buffer of the end of the last sequential commit.
> -                * Bytes beyond this limit cannot be recovered. This is a free-running counter. */
> -               long commit_seq = uatomic_read(&ustbuf->commit_seq[i_subbuf]);
> -
> -               unsigned long valid_length = buf->subbuf_size;
> -               long n_subbufs_order = get_count_order(buf->n_subbufs);
> -               long commit_seq_mask = (~0UL >> n_subbufs_order);
> -
> -               struct ltt_subbuffer_header *header = (struct ltt_subbuffer_header *)((char *)buf->mem+i_subbuf*buf->subbuf_size);
> -
> -               if((commit_seq & commit_seq_mask) == 0) {
> -                       /* There is nothing to do. */
> -                       /* FIXME: is this needed? */
> -                       break;
> -               }
> -
> -               /* Check if subbuf was fully written. This is from Mathieu's algorithm/paper. */
> -               /* FIXME: not sure data_size = 0xffffffff when the buffer is not full. It might
> -                * take the value of the header size initially */
> -               if (((commit_seq - buf->subbuf_size) & commit_seq_mask)
> -                   - (USTD_BUFFER_TRUNC(consumed_offset, buf) >> n_subbufs_order) == 0
> -                    && header->data_size != 0xffffffff && header->sb_size != 0xffffffff) {
> -                       /* If it was, we only check the data_size. This is the amount of valid data at
> -                        * the beginning of the subbuffer. */
> -                       valid_length = header->data_size;
> -                       DBG("writing full subbuffer (%d) with valid_length = %ld", i_subbuf, valid_length);
> -               }
> -               else {
> -                       /* If the subbuffer was not fully written, then we don't check data_size because
> -                        * it hasn't been written yet. Instead we check commit_seq and use it to choose
> -                        * a value for data_size. The viewer will need this value when parsing.
> -                        */
> -
> -                       valid_length = commit_seq & (buf->subbuf_size-1);
> -                       DBG("writing unfull subbuffer (%d) with valid_length = %ld", i_subbuf, valid_length);
> -                       header->data_size = valid_length;
> -                       header->sb_size = PAGE_ALIGN(valid_length);
> -                       assert(i_subbuf == (last_subbuf % buf->n_subbufs));
> -               }
> -
> -               if(callbacks->on_read_partial_subbuffer)
> -                       callbacks->on_read_partial_subbuffer(callbacks, buf, i_subbuf, valid_length);
> -
> -               if(i_subbuf == last_subbuf % buf->n_subbufs)
> -                       break;
> -       }
> -}
> -
> diff --git a/libustd/lowlevel.h b/libustd/lowlevel.h
> deleted file mode 100644
> index a1d8da5..0000000
> --- a/libustd/lowlevel.h
> +++ /dev/null
> @@ -1,35 +0,0 @@
> -/*
> - * lowlevel libustd header file
> - *
> - * Copyright 2005-2010 -
> - *              Mathieu Desnoyers <mathieu.desnoyers at polymtl.ca>
> - * Copyright 2010-
> - *              Oumarou Dicko <oumarou.dicko at polymtl.ca>
> - *              Michael Sills-Lavoie <michael.sills-lavoie at polymtl.ca>
> - *              Alexis Halle <alexis.halle at polymtl.ca>
> - *
> - * This library is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU Lesser General Public
> - * License as published by the Free Software Foundation; either
> - * version 2.1 of the License, or (at your option) any later version.
> - *
> - * This library is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public
> - * License along with this library; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> - */
> -
> -#ifndef LOWLEVEL_H
> -#define LOWLEVEL_H
> -
> -#include <ust/ustd.h>
> -
> -void finish_consuming_dead_subbuffer(struct libustd_callbacks *callbacks, struct buffer_info *buf);
> -size_t subbuffer_data_size(void *subbuf);
> -
> -#endif /* LOWLEVEL_H */
> -
> diff --git a/tests/manual_mode_tracing.sh b/tests/manual_mode_tracing.sh
> index 3f203b1..09f0764 100755
> --- a/tests/manual_mode_tracing.sh
> +++ b/tests/manual_mode_tracing.sh
> @@ -34,11 +34,11 @@ TRACE_DIR="/tmp/ust-testsuite-manual-trace"
>  rm -rf "$TRACE_DIR"
>  mkdir "$TRACE_DIR"
>
> -pidfilepath="/tmp/ust-testsuite-$USER-$(date +%Y%m%d%H%M%S%N)-ustd-pid"
> +pidfilepath="/tmp/ust-testsuite-$USER-$(date +%Y%m%d%H%M%S%N)-ust-consumerd-pid"
>  mkfifo -m 0600 "$pidfilepath"
>
> -ustd --pidfile "$pidfilepath" -o "$TRACE_DIR" >/dev/null 2>&1 &
> -USTD_PID="$(<$pidfilepath)"
> +ust-consumerd --pidfile "$pidfilepath" -o "$TRACE_DIR" >/dev/null 2>&1 &
> +UST_CONSUMERD_PID="$(<$pidfilepath)"
>
>  LD_PRELOAD=/usr/local/lib/libust.so.0.0.0:/usr/local/lib/libustinstr-malloc.so find -L / >/dev/null 2>&1 &
>  PID=$!
> @@ -54,7 +54,7 @@ sleep 0.5
>  okx ustctl --stop-trace $PID
>  okx ustctl --destroy-trace $PID
>  kill $PID
> -kill -SIGTERM $USTD_PID
> -wait $USTD_PID
> +kill -SIGTERM $UST_CONSUMERD_PID
> +wait $UST_CONSUMERD_PID
>
>  trace_matches -N "ust.malloc" "^ust.malloc:" "$TRACE_DIR"
> diff --git a/tests/runtests b/tests/runtests
> index 9560c46..afc1e21 100755
> --- a/tests/runtests
> +++ b/tests/runtests
> @@ -37,7 +37,7 @@ simple_harness_run test-libustinstr-malloc/test-libustinstr-malloc.sh
>
>  simple_harness_run ./manual_mode_tracing.sh
>
> -simple_harness_run ./valgrind_ustd.sh
> +simple_harness_run ./valgrind_ust-consumerd.sh
>
>  simple_harness_run dlopen/dlopen.sh
>
> diff --git a/tests/valgrind_ust-consumerd.sh b/tests/valgrind_ust-consumerd.sh
> new file mode 100755
> index 0000000..53b1208
> --- /dev/null
> +++ b/tests/valgrind_ust-consumerd.sh
> @@ -0,0 +1,54 @@
> +#!/bin/bash
> +#
> +# Copyright 2010 Ericsson AB
> +#
> +#    This file is part of LTTng-UST.
> +#
> +#    LTTng-UST is free software: you can redistribute it and/or modify
> +#    it under the terms of the GNU General Public License as published by
> +#    the Free Software Foundation, either version 3 of the License, or
> +#    (at your option) any later version.
> +#
> +#    LTTng-UST is distributed in the hope that it will be useful,
> +#    but WITHOUT ANY WARRANTY; without even the implied warranty of
> +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +#    GNU General Public License for more details.
> +#
> +#    You should have received a copy of the GNU General Public License
> +#    along with LTTng-UST.  If not, see <http://www.gnu.org/licenses/>.
> +
> +TESTDIR=$(dirname $0)
> +
> +source $TESTDIR/test_functions.sh
> +source $TESTDIR/tap.sh
> +
> +starttest "ust-consumerd valgrind check"
> +
> +plan_tests 2
> +
> +TRACE_DIR="/tmp/ust-testsuite-ust-consumerdvalgrind-trace"
> +rm -rf "$TRACE_DIR"
> +mkdir "$TRACE_DIR"
> +
> +pidfilepath="/tmp/ust-testsuite-$USER-$(date +%Y%m%d%H%M%S%N)-ust-consumerd-pid"
> +mkfifo -m 0600 "$pidfilepath"
> +
> +VALG_OUT=/tmp/ust-testsuite-valg.txt
> +valgrind --suppressions=$TESTDIR/valgrind_suppress.txt -q ust-consumerd --pidfile "$pidfilepath" -o "$TRACE_DIR" >/dev/null 2>"$VALG_OUT" &
> +VALG_PID=$!
> +UST_CONSUMERD_PID="$(<$pidfilepath)"
> +
> +okx usttrace -s $TESTDIR/basic/.libs/basic
> +
> +kill -SIGTERM $UST_CONSUMERD_PID
> +wait $!
> +
> +echo "Valgrind output is in $VALG_OUT"
> +if [ -z "$(<$VALG_OUT)" ]; then
> +    pass "Valgrind found no errors in ust-consumerd"
> +else
> +    fail "Valgrind found errors in ust-consumerd:"
> +    cat $VALG_OUT | while read; do
> +       diag $REPLY
> +    done
> +fi
> diff --git a/tests/valgrind_ustd.sh b/tests/valgrind_ustd.sh
> deleted file mode 100755
> index 541d8ca..0000000
> --- a/tests/valgrind_ustd.sh
> +++ /dev/null
> @@ -1,54 +0,0 @@
> -#!/bin/bash
> -#
> -# Copyright 2010 Ericsson AB
> -#
> -#    This file is part of LTTng-UST.
> -#
> -#    LTTng-UST is free software: you can redistribute it and/or modify
> -#    it under the terms of the GNU General Public License as published by
> -#    the Free Software Foundation, either version 3 of the License, or
> -#    (at your option) any later version.
> -#
> -#    LTTng-UST is distributed in the hope that it will be useful,
> -#    but WITHOUT ANY WARRANTY; without even the implied warranty of
> -#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> -#    GNU General Public License for more details.
> -#
> -#    You should have received a copy of the GNU General Public License
> -#    along with LTTng-UST.  If not, see <http://www.gnu.org/licenses/>.
> -
> -TESTDIR=$(dirname $0)
> -
> -source $TESTDIR/test_functions.sh
> -source $TESTDIR/tap.sh
> -
> -starttest "ustd valgrind check"
> -
> -plan_tests 2
> -
> -TRACE_DIR="/tmp/ust-testsuite-ustdvalgrind-trace"
> -rm -rf "$TRACE_DIR"
> -mkdir "$TRACE_DIR"
> -
> -pidfilepath="/tmp/ust-testsuite-$USER-$(date +%Y%m%d%H%M%S%N)-ustd-pid"
> -mkfifo -m 0600 "$pidfilepath"
> -
> -VALG_OUT=/tmp/ust-testsuite-valg.txt
> -valgrind --suppressions=$TESTDIR/valgrind_suppress.txt -q ustd --pidfile "$pidfilepath" -o "$TRACE_DIR" >/dev/null 2>"$VALG_OUT" &
> -VALG_PID=$!
> -USTD_PID="$(<$pidfilepath)"
> -
> -okx usttrace -s $TESTDIR/basic/.libs/basic
> -
> -kill -SIGTERM $USTD_PID
> -wait $!
> -
> -echo "Valgrind output is in $VALG_OUT"
> -if [ -z "$(<$VALG_OUT)" ]; then
> -    pass "Valgrind found no errors in ustd"
> -else
> -    fail "Valgrind found errors in ustd:"
> -    cat $VALG_OUT | while read; do
> -       diag $REPLY
> -    done
> -fi
> diff --git a/ust-consumerd/Makefile.am b/ust-consumerd/Makefile.am
> new file mode 100644
> index 0000000..01e3b82
> --- /dev/null
> +++ b/ust-consumerd/Makefile.am
> @@ -0,0 +1,14 @@
> +AM_CPPFLAGS = -I$(top_srcdir)/libust -I$(top_srcdir)/libustcomm \
> +       -I$(top_srcdir)/include -I$(top_srcdir)/libustconsumer
> +AM_CFLAGS = -fno-strict-aliasing
> +
> +bin_PROGRAMS = ust-consumerd
> +
> +ust_consumerd_SOURCES = ust-consumerd.c
> +
> +ust_consumerd_LDADD = \
> +       $(top_builddir)/snprintf/libustsnprintf.la \
> +       $(top_builddir)/libustcomm/libustcomm.la \
> +       $(top_builddir)/libustconsumer/libustconsumer.la
> +
> +ust_consumerd_CFLAGS = -DUST_COMPONENT=ust-consumerd -fno-strict-aliasing
> diff --git a/ust-consumerd/README b/ust-consumerd/README
> new file mode 100644
> index 0000000..6df4015
> --- /dev/null
> +++ b/ust-consumerd/README
> @@ -0,0 +1,3 @@
> +This is ust-consumerd, the UST consumer daemon.
> +
> +This daemon is used to collect the traces for the traced programs and write them to disk.
> diff --git a/ust-consumerd/ust-consumerd.c b/ust-consumerd/ust-consumerd.c
> new file mode 100644
> index 0000000..fae4efa
> --- /dev/null
> +++ b/ust-consumerd/ust-consumerd.c
> @@ -0,0 +1,505 @@
> +/* Copyright (C) 2009  Pierre-Marc Fournier
> + *               2010  Alexis Halle
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
> + */
> +
> +#define _GNU_SOURCE
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/shm.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <signal.h>
> +
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <assert.h>
> +#include <getopt.h>
> +
> +#include "ust/ustconsumer.h"
> +#include "usterr.h"
> +
> +char *sock_path=NULL;
> +char *trace_path=NULL;
> +int daemon_mode = 0;
> +char *pidfile = NULL;
> +
> +struct ustconsumer_instance *instance;
> +
> +struct buffer_info_local {
> +       /* output file */
> +       int file_fd;
> +       /* the offset we must truncate to, to unput the last subbuffer */
> +       off_t previous_offset;
> +};
> +
> +static int write_pidfile(const char *file_name, pid_t pid)
> +{
> +       FILE *pidfp;
> +
> +       pidfp = fopen(file_name, "w");
> +       if(!pidfp) {
> +               PERROR("fopen (%s)", file_name);
> +               WARN("killing child process");
> +               return -1;
> +       }
> +
> +       fprintf(pidfp, "%d\n", pid);
> +
> +       fclose(pidfp);
> +
> +       return 0;
> +}
> +
> +int create_dir_if_needed(char *dir)
> +{
> +       int result;
> +       result = mkdir(dir, 0777);
> +       if(result == -1) {
> +               if(errno != EEXIST) {
> +                       PERROR("mkdir");
> +                       return -1;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +int unwrite_last_subbuffer(struct buffer_info *buf)
> +{
> +       int result;
> +       struct buffer_info_local *buf_local = buf->user_data;
> +
> +       result = ftruncate(buf_local->file_fd, buf_local->previous_offset);
> +       if(result == -1) {
> +               PERROR("ftruncate");
> +               return -1;
> +       }
> +
> +       result = lseek(buf_local->file_fd, buf_local->previous_offset, SEEK_SET);
> +       if(result == (int)(off_t)-1) {
> +               PERROR("lseek");
> +               return -1;
> +       }
> +
> +       return 0;
> +}
> +
> +int write_current_subbuffer(struct buffer_info *buf)
> +{
> +       int result;
> +       struct buffer_info_local *buf_local = buf->user_data;
> +
> +       void *subbuf_mem = buf->mem + (buf->consumed_old & (buf->n_subbufs * buf->subbuf_size-1));
> +
> +       size_t cur_sb_size = subbuffer_data_size(subbuf_mem);
> +
> +       off_t cur_offset = lseek(buf_local->file_fd, 0, SEEK_CUR);
> +       if(cur_offset == (off_t)-1) {
> +               PERROR("lseek");
> +               return -1;
> +       }
> +
> +       buf_local->previous_offset = cur_offset;
> +       DBG("previous_offset: %ld", cur_offset);
> +
> +       result = patient_write(buf_local->file_fd, subbuf_mem, cur_sb_size);
> +       if(result == -1) {
> +               PERROR("write");
> +               return -1;
> +       }
> +
> +       return 0;
> +}
> +
> +int on_read_subbuffer(struct ustconsumer_callbacks *data, struct buffer_info *buf)
> +{
> +       return write_current_subbuffer(buf);
> +}
> +
> +int on_read_partial_subbuffer(struct ustconsumer_callbacks *data, struct buffer_info *buf,
> +                               long subbuf_index, unsigned long valid_length)
> +{
> +       struct buffer_info_local *buf_local = buf->user_data;
> +       char *tmp;
> +       int result;
> +       unsigned long pad_size;
> +
> +       result = patient_write(buf_local->file_fd, buf->mem + subbuf_index * buf->subbuf_size, valid_length);
> +       if(result == -1) {
> +               ERR("Error writing to buffer file");
> +               return;
> +       }
> +
> +       /* pad with empty bytes */
> +       pad_size = PAGE_ALIGN(valid_length)-valid_length;
> +       if(pad_size) {
> +               tmp = zmalloc(pad_size);
> +               result = patient_write(buf_local->file_fd, tmp, pad_size);
> +               if(result == -1) {
> +                       ERR("Error writing to buffer file");
> +                       return;
> +               }
> +               free(tmp);
> +       }
> +
> +}
> +
> +int on_open_buffer(struct ustconsumer_callbacks *data, struct buffer_info *buf)
> +{
> +       char *tmp;
> +       int result;
> +       int fd;
> +       struct buffer_info_local *buf_local =
> +               zmalloc(sizeof(struct buffer_info_local));
> +
> +       if(!buf_local) {
> +               ERR("could not allocate buffer_info_local struct");
> +               return 1;
> +       }
> +
> +       buf->user_data = buf_local;
> +
> +       /* open file for output */
> +       if(!trace_path) {
> +               /* Only create the directory if using the default path, because
> +                * of the risk of typo when using trace path override. We don't
> +                * want to risk creating plenty of useless directories in that case.
> +                */
> +               result = create_dir_if_needed(USTCONSUMER_DEFAULT_TRACE_PATH);
> +               if(result == -1) {
> +                       ERR("could not create directory %s", USTCONSUMER_DEFAULT_TRACE_PATH);
> +                       return 1;
> +               }
> +
> +               trace_path = USTCONSUMER_DEFAULT_TRACE_PATH;
> +       }
> +
> +       if (asprintf(&tmp, "%s/%u_%lld", trace_path, buf->pid, buf->pidunique) < 0) {
> +               ERR("on_open_buffer : asprintf failed (%s/%u_%lld)",
> +                   trace_path, buf->pid, buf->pidunique);
> +               return 1;
> +       }
> +       result = create_dir_if_needed(tmp);
> +       if(result == -1) {
> +               ERR("could not create directory %s", tmp);
> +               free(tmp);
> +               return 1;
> +       }
> +       free(tmp);
> +
> +       if (asprintf(&tmp, "%s/%u_%lld/%s", trace_path, buf->pid, buf->pidunique, buf->name) < 0) {
> +               ERR("on_open_buffer : asprintf failed (%s/%u_%lld/%s)",
> +                   trace_path, buf->pid, buf->pidunique, buf->name);
> +               return 1;
> +       }
> +       result = fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 00600);
> +       if(result == -1) {
> +               PERROR("open");
> +               ERR("failed opening trace file %s", tmp);
> +               return 1;
> +       }
> +       buf_local->file_fd = fd;
> +       free(tmp);
> +
> +       return 0;
> +}
> +
> +int on_close_buffer(struct ustconsumer_callbacks *data, struct buffer_info *buf)
> +{
> +       struct buffer_info_local *buf_local = buf->user_data;
> +       int result = close(buf_local->file_fd);
> +       free(buf_local);
> +       if(result == -1) {
> +               PERROR("close");
> +       }
> +       return 0;
> +}
> +
> +int on_put_error(struct ustconsumer_callbacks *data, struct buffer_info *buf)
> +{
> +       unwrite_last_subbuffer(buf);
> +}
> +
> +struct ustconsumer_callbacks *new_callbacks()
> +{
> +       struct ustconsumer_callbacks *callbacks =
> +               zmalloc(sizeof(struct ustconsumer_callbacks));
> +
> +       if(!callbacks)
> +               return NULL;
> +
> +       callbacks->on_open_buffer = on_open_buffer;
> +       callbacks->on_close_buffer = on_close_buffer;
> +       callbacks->on_read_subbuffer = on_read_subbuffer;
> +       callbacks->on_read_partial_subbuffer = on_read_partial_subbuffer;
> +       callbacks->on_put_error = on_put_error;
> +       callbacks->on_new_thread = NULL;
> +       callbacks->on_close_thread = NULL;
> +       callbacks->on_trace_end = NULL;
> +
> +       return callbacks;
> +
> +}
> +
> +int is_directory(const char *dir)
> +{
> +       int result;
> +       struct stat st;
> +
> +       result = stat(dir, &st);
> +       if(result == -1) {
> +               PERROR("stat");
> +               return 0;
> +       }
> +
> +       if(!S_ISDIR(st.st_mode)) {
> +               return 0;
> +       }
> +
> +       return 1;
> +}
> +
> +void usage(void)
> +{
> +       fprintf(stderr, "Usage:\nust-consumerd OPTIONS\n\nOptions:\n"
> +                       "\t-h\t\tDisplay this usage.\n"
> +                       "\t-o DIR\t\tSpecify the directory where to output the traces.\n"
> +                       "\t-s PATH\t\tSpecify the path to use for the daemon socket.\n"
> +                       "\t-d\t\tStart as a daemon.\n"
> +                       "\t--pidfile FILE\tWrite the PID in this file (when using -d).\n");
> +}
> +
> +int parse_args(int argc, char **argv)
> +{
> +       int c;
> +
> +       while (1) {
> +               int option_index = 0;
> +               static struct option long_options[] = {
> +                       {"pidfile", 1, 0, 'p'},
> +                       {"help", 0, 0, 'h'},
> +                       {"version", 0, 0, 'V'},
> +                       {0, 0, 0, 0}
> +               };
> +
> +               c = getopt_long(argc, argv, "hs:o:d", long_options, &option_index);
> +               if (c == -1)
> +                       break;
> +
> +               switch (c) {
> +               case 0:
> +                       printf("option %s", long_options[option_index].name);
> +                       if (optarg)
> +                               printf(" with arg %s", optarg);
> +                       printf("\n");
> +                       break;
> +               case 's':
> +                       sock_path = optarg;
> +                       break;
> +               case 'o':
> +                       trace_path = optarg;
> +                       if(!is_directory(trace_path)) {
> +                               ERR("Not a valid directory. (%s)", trace_path);
> +                               return -1;
> +                       }
> +                       break;
> +               case 'd':
> +                       daemon_mode = 1;
> +                       break;
> +               case 'p':
> +                       pidfile = strdup(optarg);
> +                       break;
> +               case 'h':
> +                       usage();
> +                       exit(0);
> +               case 'V':
> +                       printf("Version 0.0\n");
> +                       break;
> +
> +               default:
> +                       /* unknown option or other error; error is
> +                       printed by getopt, just return */
> +                       return -1;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +void sigterm_handler(int sig)
> +{
> +       ustconsumer_stop_instance(instance, 0);
> +}
> +
> +int start_ustconsumer(int fd)
> +{
> +       int result;
> +       sigset_t sigset;
> +       struct sigaction sa;
> +
> +       struct ustconsumer_callbacks *callbacks = new_callbacks();
> +       if(!callbacks) {
> +               PERROR("new_callbacks");
> +               return 1;
> +       }
> +
> +       result = sigemptyset(&sigset);
> +       if(result == -1) {
> +               PERROR("sigemptyset");
> +               return 1;
> +       }
> +       sa.sa_handler = sigterm_handler;
> +       sa.sa_mask = sigset;
> +       sa.sa_flags = 0;
> +       result = sigaction(SIGTERM, &sa, NULL);
> +       if(result == -1) {
> +               PERROR("sigaction");
> +               return 1;
> +       }
> +       result = sigaction(SIGINT, &sa, NULL);
> +       if(result == -1) {
> +               PERROR("sigaction");
> +               return 1;
> +       }
> +
> +       instance = ustconsumer_new_instance(callbacks, sock_path);
> +       if(!instance) {
> +               ERR("failed to create ustconsumer instance");
> +               return 1;
> +       }
> +
> +       result = ustconsumer_init_instance(instance);
> +       if(result) {
> +               ERR("failed to initialize ustconsumer instance");
> +               return 1;
> +       }
> +
> +       /* setup handler for SIGPIPE */
> +       result = sigemptyset(&sigset);
> +       if(result == -1) {
> +               PERROR("sigemptyset");
> +               return 1;
> +       }
> +       result = sigaddset(&sigset, SIGPIPE);
> +       if(result == -1) {
> +               PERROR("sigaddset");
> +               return 1;
> +       }
> +       result = sigprocmask(SIG_BLOCK, &sigset, NULL);
> +       if(result == -1) {
> +               PERROR("sigprocmask");
> +               return 1;
> +       }
> +
> +       /* Write pidfile */
> +       if(pidfile) {
> +               result = write_pidfile(pidfile, getpid());
> +               if(result == -1) {
> +                       ERR("failed to write pidfile");
> +                       return 1;
> +               }
> +       }
> +
> +       /* Notify parent that we are successfully started. */
> +       if(fd != -1) {
> +               /* write any one character */
> +               result = write(fd, "!", 1);
> +               if(result == -1) {
> +                       PERROR("write");
> +                       return -1;
> +               }
> +               if(result != 1) {
> +                       ERR("Problem sending confirmation of daemon start to parent");
> +                       return -1;
> +               }
> +               result = close(fd);
> +               if(result == -1) {
> +                       PERROR("close");
> +               }
> +       }
> +
> +       ustconsumer_start_instance(instance);
> +
> +       free(callbacks);
> +
> +       return 0;
> +}
> +
> +int start_ustconsumer_daemon()
> +{
> +       int result;
> +       int fd[2];
> +       pid_t child_pid;
> +
> +       result = pipe(fd);
> +
> +       result = child_pid = fork();
> +       if(result == -1) {
> +               PERROR("fork");
> +               return -1;
> +       }
> +       else if(result == 0) {
> +               return start_ustconsumer(fd[1]);
> +       }
> +       else {
> +               char buf;
> +
> +               result = read(fd[0], &buf, 1);
> +               if(result == -1) {
> +                       PERROR("read");
> +                       return -1;
> +               }
> +               if(result != 1) {
> +                       ERR("did not receive valid confirmation that the daemon is started");
> +                       return -1;
> +               }
> +
> +               result = close(fd[0]);
> +               if(result == -1) {
> +                       PERROR("close");
> +               }
> +
> +               DBG("The daemon is now successfully started");
> +       }
> +
> +       /* Wait for confirmation that the server is ready. */
> +
> +
> +       return 0;
> +}
> +
> +int main(int argc, char **argv)
> +{
> +       int result;
> +
> +       result = parse_args(argc, argv);
> +       if(result == -1) {
> +               exit(1);
> +       }
> +
> +       if(daemon_mode) {
> +               result = start_ustconsumer_daemon();
> +       }
> +       else {
> +               result = start_ustconsumer(-1);
> +       }
> +
> +       return result;
> +}
> diff --git a/ustd/Makefile.am b/ustd/Makefile.am
> deleted file mode 100644
> index 991c717..0000000
> --- a/ustd/Makefile.am
> +++ /dev/null
> @@ -1,14 +0,0 @@
> -AM_CPPFLAGS = -I$(top_srcdir)/libust -I$(top_srcdir)/libustcomm \
> -       -I$(top_srcdir)/include -I$(top_srcdir)/libustd
> -AM_CFLAGS = -fno-strict-aliasing
> -
> -bin_PROGRAMS = ustd
> -
> -ustd_SOURCES = ustd.c
> -
> -ustd_LDADD = \
> -       $(top_builddir)/snprintf/libustsnprintf.la \
> -       $(top_builddir)/libustcomm/libustcomm.la \
> -       $(top_builddir)/libustd/libustd.la
> -
> -ustd_CFLAGS = -DUST_COMPONENT=ustd -fno-strict-aliasing
> diff --git a/ustd/README b/ustd/README
> deleted file mode 100644
> index 8fcd218..0000000
> --- a/ustd/README
> +++ /dev/null
> @@ -1,3 +0,0 @@
> -This is ustd, the UST daemon.
> -
> -This daemon is used to collect the traces for the traced programs.
> diff --git a/ustd/ustd.c b/ustd/ustd.c
> deleted file mode 100644
> index e75fd9d..0000000
> --- a/ustd/ustd.c
> +++ /dev/null
> @@ -1,505 +0,0 @@
> -/* Copyright (C) 2009  Pierre-Marc Fournier
> - *               2010  Alexis Halle
> - *
> - * This library is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU Lesser General Public
> - * License as published by the Free Software Foundation; either
> - * version 2.1 of the License, or (at your option) any later version.
> - *
> - * This library is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> - * Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public
> - * License along with this library; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
> - */
> -
> -#define _GNU_SOURCE
> -
> -#include <sys/types.h>
> -#include <sys/stat.h>
> -#include <sys/shm.h>
> -#include <fcntl.h>
> -#include <unistd.h>
> -#include <signal.h>
> -
> -#include <stdlib.h>
> -#include <stdio.h>
> -#include <string.h>
> -#include <errno.h>
> -#include <assert.h>
> -#include <getopt.h>
> -
> -#include "ust/ustd.h"
> -#include "usterr.h"
> -
> -char *sock_path=NULL;
> -char *trace_path=NULL;
> -int daemon_mode = 0;
> -char *pidfile = NULL;
> -
> -struct libustd_instance *instance;
> -
> -struct buffer_info_local {
> -       /* output file */
> -       int file_fd;
> -       /* the offset we must truncate to, to unput the last subbuffer */
> -       off_t previous_offset;
> -};
> -
> -static int write_pidfile(const char *file_name, pid_t pid)
> -{
> -       FILE *pidfp;
> -
> -       pidfp = fopen(file_name, "w");
> -       if(!pidfp) {
> -               PERROR("fopen (%s)", file_name);
> -               WARN("killing child process");
> -               return -1;
> -       }
> -
> -       fprintf(pidfp, "%d\n", pid);
> -
> -       fclose(pidfp);
> -
> -       return 0;
> -}
> -
> -int create_dir_if_needed(char *dir)
> -{
> -       int result;
> -       result = mkdir(dir, 0777);
> -       if(result == -1) {
> -               if(errno != EEXIST) {
> -                       PERROR("mkdir");
> -                       return -1;
> -               }
> -       }
> -
> -       return 0;
> -}
> -
> -int unwrite_last_subbuffer(struct buffer_info *buf)
> -{
> -       int result;
> -       struct buffer_info_local *buf_local = buf->user_data;
> -
> -       result = ftruncate(buf_local->file_fd, buf_local->previous_offset);
> -       if(result == -1) {
> -               PERROR("ftruncate");
> -               return -1;
> -       }
> -
> -       result = lseek(buf_local->file_fd, buf_local->previous_offset, SEEK_SET);
> -       if(result == (int)(off_t)-1) {
> -               PERROR("lseek");
> -               return -1;
> -       }
> -
> -       return 0;
> -}
> -
> -int write_current_subbuffer(struct buffer_info *buf)
> -{
> -       int result;
> -       struct buffer_info_local *buf_local = buf->user_data;
> -
> -       void *subbuf_mem = buf->mem + (buf->consumed_old & (buf->n_subbufs * buf->subbuf_size-1));
> -
> -       size_t cur_sb_size = subbuffer_data_size(subbuf_mem);
> -
> -       off_t cur_offset = lseek(buf_local->file_fd, 0, SEEK_CUR);
> -       if(cur_offset == (off_t)-1) {
> -               PERROR("lseek");
> -               return -1;
> -       }
> -
> -       buf_local->previous_offset = cur_offset;
> -       DBG("previous_offset: %ld", cur_offset);
> -
> -       result = patient_write(buf_local->file_fd, subbuf_mem, cur_sb_size);
> -       if(result == -1) {
> -               PERROR("write");
> -               return -1;
> -       }
> -
> -       return 0;
> -}
> -
> -int on_read_subbuffer(struct libustd_callbacks *data, struct buffer_info *buf)
> -{
> -       return write_current_subbuffer(buf);
> -}
> -
> -int on_read_partial_subbuffer(struct libustd_callbacks *data, struct buffer_info *buf,
> -                               long subbuf_index, unsigned long valid_length)
> -{
> -       struct buffer_info_local *buf_local = buf->user_data;
> -       char *tmp;
> -       int result;
> -       unsigned long pad_size;
> -
> -       result = patient_write(buf_local->file_fd, buf->mem + subbuf_index * buf->subbuf_size, valid_length);
> -       if(result == -1) {
> -               ERR("Error writing to buffer file");
> -               return;
> -       }
> -
> -       /* pad with empty bytes */
> -       pad_size = PAGE_ALIGN(valid_length)-valid_length;
> -       if(pad_size) {
> -               tmp = zmalloc(pad_size);
> -               result = patient_write(buf_local->file_fd, tmp, pad_size);
> -               if(result == -1) {
> -                       ERR("Error writing to buffer file");
> -                       return;
> -               }
> -               free(tmp);
> -       }
> -
> -}
> -
> -int on_open_buffer(struct libustd_callbacks *data, struct buffer_info *buf)
> -{
> -       char *tmp;
> -       int result;
> -       int fd;
> -       struct buffer_info_local *buf_local =
> -               zmalloc(sizeof(struct buffer_info_local));
> -
> -       if(!buf_local) {
> -               ERR("could not allocate buffer_info_local struct");
> -               return 1;
> -       }
> -
> -       buf->user_data = buf_local;
> -
> -       /* open file for output */
> -       if(!trace_path) {
> -               /* Only create the directory if using the default path, because
> -                * of the risk of typo when using trace path override. We don't
> -                * want to risk creating plenty of useless directories in that case.
> -                */
> -               result = create_dir_if_needed(USTD_DEFAULT_TRACE_PATH);
> -               if(result == -1) {
> -                       ERR("could not create directory %s", USTD_DEFAULT_TRACE_PATH);
> -                       return 1;
> -               }
> -
> -               trace_path = USTD_DEFAULT_TRACE_PATH;
> -       }
> -
> -       if (asprintf(&tmp, "%s/%u_%lld", trace_path, buf->pid, buf->pidunique) < 0) {
> -               ERR("on_open_buffer : asprintf failed (%s/%u_%lld)",
> -                   trace_path, buf->pid, buf->pidunique);
> -               return 1;
> -       }
> -       result = create_dir_if_needed(tmp);
> -       if(result == -1) {
> -               ERR("could not create directory %s", tmp);
> -               free(tmp);
> -               return 1;
> -       }
> -       free(tmp);
> -
> -       if (asprintf(&tmp, "%s/%u_%lld/%s", trace_path, buf->pid, buf->pidunique, buf->name) < 0) {
> -               ERR("on_open_buffer : asprintf failed (%s/%u_%lld/%s)",
> -                   trace_path, buf->pid, buf->pidunique, buf->name);
> -               return 1;
> -       }
> -       result = fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 00600);
> -       if(result == -1) {
> -               PERROR("open");
> -               ERR("failed opening trace file %s", tmp);
> -               return 1;
> -       }
> -       buf_local->file_fd = fd;
> -       free(tmp);
> -
> -       return 0;
> -}
> -
> -int on_close_buffer(struct libustd_callbacks *data, struct buffer_info *buf)
> -{
> -       struct buffer_info_local *buf_local = buf->user_data;
> -       int result = close(buf_local->file_fd);
> -       free(buf_local);
> -       if(result == -1) {
> -               PERROR("close");
> -       }
> -       return 0;
> -}
> -
> -int on_put_error(struct libustd_callbacks *data, struct buffer_info *buf)
> -{
> -       unwrite_last_subbuffer(buf);
> -}
> -
> -struct libustd_callbacks *new_callbacks()
> -{
> -       struct libustd_callbacks *callbacks =
> -               zmalloc(sizeof(struct libustd_callbacks));
> -
> -       if(!callbacks)
> -               return NULL;
> -
> -       callbacks->on_open_buffer = on_open_buffer;
> -       callbacks->on_close_buffer = on_close_buffer;
> -       callbacks->on_read_subbuffer = on_read_subbuffer;
> -       callbacks->on_read_partial_subbuffer = on_read_partial_subbuffer;
> -       callbacks->on_put_error = on_put_error;
> -       callbacks->on_new_thread = NULL;
> -       callbacks->on_close_thread = NULL;
> -       callbacks->on_trace_end = NULL;
> -
> -       return callbacks;
> -
> -}
> -
> -int is_directory(const char *dir)
> -{
> -       int result;
> -       struct stat st;
> -
> -       result = stat(dir, &st);
> -       if(result == -1) {
> -               PERROR("stat");
> -               return 0;
> -       }
> -
> -       if(!S_ISDIR(st.st_mode)) {
> -               return 0;
> -       }
> -
> -       return 1;
> -}
> -
> -void usage(void)
> -{
> -       fprintf(stderr, "Usage:\nustd OPTIONS\n\nOptions:\n"
> -                       "\t-h\t\tDisplay this usage.\n"
> -                       "\t-o DIR\t\tSpecify the directory where to output the traces.\n"
> -                       "\t-s PATH\t\tSpecify the path to use for the daemon socket.\n"
> -                       "\t-d\t\tStart as a daemon.\n"
> -                       "\t--pidfile FILE\tWrite the PID in this file (when using -d).\n");
> -}
> -
> -int parse_args(int argc, char **argv)
> -{
> -       int c;
> -
> -       while (1) {
> -               int option_index = 0;
> -               static struct option long_options[] = {
> -                       {"pidfile", 1, 0, 'p'},
> -                       {"help", 0, 0, 'h'},
> -                       {"version", 0, 0, 'V'},
> -                       {0, 0, 0, 0}
> -               };
> -
> -               c = getopt_long(argc, argv, "hs:o:d", long_options, &option_index);
> -               if (c == -1)
> -                       break;
> -
> -               switch (c) {
> -               case 0:
> -                       printf("option %s", long_options[option_index].name);
> -                       if (optarg)
> -                               printf(" with arg %s", optarg);
> -                       printf("\n");
> -                       break;
> -               case 's':
> -                       sock_path = optarg;
> -                       break;
> -               case 'o':
> -                       trace_path = optarg;
> -                       if(!is_directory(trace_path)) {
> -                               ERR("Not a valid directory. (%s)", trace_path);
> -                               return -1;
> -                       }
> -                       break;
> -               case 'd':
> -                       daemon_mode = 1;
> -                       break;
> -               case 'p':
> -                       pidfile = strdup(optarg);
> -                       break;
> -               case 'h':
> -                       usage();
> -                       exit(0);
> -               case 'V':
> -                       printf("Version 0.0\n");
> -                       break;
> -
> -               default:
> -                       /* unknown option or other error; error is
> -                       printed by getopt, just return */
> -                       return -1;
> -               }
> -       }
> -
> -       return 0;
> -}
> -
> -void sigterm_handler(int sig)
> -{
> -       libustd_stop_instance(instance, 0);
> -}
> -
> -int start_ustd(int fd)
> -{
> -       int result;
> -       sigset_t sigset;
> -       struct sigaction sa;
> -
> -       struct libustd_callbacks *callbacks = new_callbacks();
> -       if(!callbacks) {
> -               PERROR("new_callbacks");
> -               return 1;
> -       }
> -
> -       result = sigemptyset(&sigset);
> -       if(result == -1) {
> -               PERROR("sigemptyset");
> -               return 1;
> -       }
> -       sa.sa_handler = sigterm_handler;
> -       sa.sa_mask = sigset;
> -       sa.sa_flags = 0;
> -       result = sigaction(SIGTERM, &sa, NULL);
> -       if(result == -1) {
> -               PERROR("sigaction");
> -               return 1;
> -       }
> -       result = sigaction(SIGINT, &sa, NULL);
> -       if(result == -1) {
> -               PERROR("sigaction");
> -               return 1;
> -       }
> -
> -       instance = libustd_new_instance(callbacks, sock_path);
> -       if(!instance) {
> -               ERR("failed to create libustd instance");
> -               return 1;
> -       }
> -
> -       result = libustd_init_instance(instance);
> -       if(result) {
> -               ERR("failed to initialize libustd instance");
> -               return 1;
> -       }
> -
> -       /* setup handler for SIGPIPE */
> -       result = sigemptyset(&sigset);
> -       if(result == -1) {
> -               PERROR("sigemptyset");
> -               return 1;
> -       }
> -       result = sigaddset(&sigset, SIGPIPE);
> -       if(result == -1) {
> -               PERROR("sigaddset");
> -               return 1;
> -       }
> -       result = sigprocmask(SIG_BLOCK, &sigset, NULL);
> -       if(result == -1) {
> -               PERROR("sigprocmask");
> -               return 1;
> -       }
> -
> -       /* Write pidfile */
> -       if(pidfile) {
> -               result = write_pidfile(pidfile, getpid());
> -               if(result == -1) {
> -                       ERR("failed to write pidfile");
> -                       return 1;
> -               }
> -       }
> -
> -       /* Notify parent that we are successfully started. */
> -       if(fd != -1) {
> -               /* write any one character */
> -               result = write(fd, "!", 1);
> -               if(result == -1) {
> -                       PERROR("write");
> -                       return -1;
> -               }
> -               if(result != 1) {
> -                       ERR("Problem sending confirmation of daemon start to parent");
> -                       return -1;
> -               }
> -               result = close(fd);
> -               if(result == -1) {
> -                       PERROR("close");
> -               }
> -       }
> -
> -       libustd_start_instance(instance);
> -
> -       free(callbacks);
> -
> -       return 0;
> -}
> -
> -int start_ustd_daemon()
> -{
> -       int result;
> -       int fd[2];
> -       pid_t child_pid;
> -
> -       result = pipe(fd);
> -
> -       result = child_pid = fork();
> -       if(result == -1) {
> -               PERROR("fork");
> -               return -1;
> -       }
> -       else if(result == 0) {
> -               return start_ustd(fd[1]);
> -       }
> -       else {
> -               char buf;
> -
> -               result = read(fd[0], &buf, 1);
> -               if(result == -1) {
> -                       PERROR("read");
> -                       return -1;
> -               }
> -               if(result != 1) {
> -                       ERR("did not receive valid confirmation that the daemon is started");
> -                       return -1;
> -               }
> -
> -               result = close(fd[0]);
> -               if(result == -1) {
> -                       PERROR("close");
> -               }
> -
> -               DBG("The daemon is now successfully started");
> -       }
> -
> -       /* Wait for confirmation that the server is ready. */
> -
> -
> -       return 0;
> -}
> -
> -int main(int argc, char **argv)
> -{
> -       int result;
> -
> -       result = parse_args(argc, argv);
> -       if(result == -1) {
> -               exit(1);
> -       }
> -
> -       if(daemon_mode) {
> -               result = start_ustd_daemon();
> -       }
> -       else {
> -               result = start_ustd(-1);
> -       }
> -
> -       return result;
> -}
> diff --git a/usttrace b/usttrace
> index 94404dd..5d6729e 100755
> --- a/usttrace
> +++ b/usttrace
> @@ -9,14 +9,14 @@ function error() {
>
>  function sighandler() {
>         echo "Caught Ctrl-C"
> -       if [ -z "$USTDPID" ]; then
> -               USTDPID="$(<$pidfilepath)"
> +       if [ -z "$UST_CONSUMERDPID" ]; then
> +               UST_CONSUMERDPID="$(<$pidfilepath)"
>         fi
>         # Tell the daemon to die
> -       kill -SIGTERM "$USTDPID"
> +       kill -SIGTERM "$UST_CONSUMERDPID"
>
> -       echo "Waiting for ustd to shutdown..."
> -       wait "$USTDPID"
> +       echo "Waiting for ust-consumerd to shutdown..."
> +       wait "$UST_CONSUMERDPID"
>
>         rm "$pidfilepath"
>
> @@ -24,17 +24,17 @@ function sighandler() {
>  }
>
>  USTTRACE_DIR="$(dirname $0)"
> -if [ -x "${USTTRACE_DIR}/ustd/ustd" ] ; then
> +if [ -x "${USTTRACE_DIR}/ust-consumerd/ust-consumerd" ] ; then
>      # Use the not installed libraries instead
> -    USTD="${USTTRACE_DIR}/ustd/ustd"
> +    UST_CONSUMERD="${USTTRACE_DIR}/ust-consumerd/ust-consumerd"
>      LIBINTERFORK_PATH="${USTTRACE_DIR}/libustfork/.libs/libustfork.so"
>      LIBMALLOCWRAP_PATH="${USTTRACE_DIR}/libustinstr-malloc/.libs/libustinstr-malloc.so"
>      LIBUST_PATH="${USTTRACE_DIR}/libust/.libs/libust.so"
>  else
>      # Use the libraries that the dynamic link finds
> -    USTD="ustd"
> -    if [ ! -x "$(which ustd 2>/dev/null)" ]; then
> -        error "cannot find an executable ustd; make sure its location is in the PATH"
> +    UST_CONSUMERD="ust-consumerd"
> +    if [ ! -x "$(which ust-consumerd 2>/dev/null)" ]; then
> +        error "cannot find an executable ust-consumerd; make sure its location is in the PATH"
>          exit 1
>      fi
>      LIBINTERFORK_PATH="libustfork.so"
> @@ -117,25 +117,25 @@ if [ ! -d "$OUTDIR" ]; then
>         fi
>  fi
>
> -# Choose ustd socket path
> -USTDSOCKPATH="/tmp/ustd-sock-$$"
> +# Choose ust-consumerd socket path
> +UST_CONSUMERDSOCKPATH="/tmp/ust-consumerd-sock-$$"
>
>  if [ "$arg_syswide_daemon" != "1" ];
>  then
> -       pidfilepath="/tmp/usttrace-$USER-$(date +%Y%m%d%H%M%S%N)-ustd-pid"
> +       pidfilepath="/tmp/usttrace-$USER-$(date +%Y%m%d%H%M%S%N)-ust-consumerd-pid"
>         trap "sighandler $pidfilepath" SIGINT
>         mkfifo -m 0600 "$pidfilepath"
>         # Start daemon
> -       $USTD --pidfile "$pidfilepath" -s "$USTDSOCKPATH" -o "$OUTDIR" >"$OUTDIR/ustd.log" 2>&1 &
> -       # ustd sets up its server socket
> -       # ustd opens the pidfile, blocks because no one has opened it
> +       $UST_CONSUMERD --pidfile "$pidfilepath" -s "$UST_CONSUMERDSOCKPATH" -o "$OUTDIR" >"$OUTDIR/ust-consumerd.log" 2>&1 &
> +       # ust-consumerd sets up its server socket
> +       # ust-consumerd opens the pidfile, blocks because no one has opened it
>         # we open pidfile
>         # we block reading pidfile
> -       # ustd writes to pidfile
> -       # ustd closes pidfile
> +       # ust-consumerd writes to pidfile
> +       # ust-consumerd closes pidfile
>         # we unblock reading pidfile
> -       USTDPID="$(<$pidfilepath)"
> -       export UST_DAEMON_SOCKET="$USTDSOCKPATH"
> +       UST_CONSUMERDPID="$(<$pidfilepath)"
> +       export UST_DAEMON_SOCKET="$UST_CONSUMERDSOCKPATH"
>  fi
>
>  # Establish the environment for the command
> @@ -206,10 +206,10 @@ fi
>  if [ "$arg_syswide_daemon" != "1" ];
>  then
>         # Tell the daemon to die
> -       kill -SIGTERM "$USTDPID"
> +       kill -SIGTERM "$UST_CONSUMERDPID"
>
> -       echo "Waiting for ustd to shutdown..."
> -       wait "$USTDPID"
> +       echo "Waiting for ust-consumerd to shutdown..."
> +       wait "$UST_CONSUMERDPID"
>
>         rm "$pidfilepath"
>  fi
> --
> 1.7.1
>
>   





More information about the lttng-dev mailing list