Rename libustd to libustconsumer and ustd to ust-consumerd
authorNils Carlson <nils.carlson@ericsson.com>
Wed, 5 Jan 2011 12:53:43 +0000 (13:53 +0100)
committerNils Carlson <nils.carlson@ericsson.com>
Wed, 5 Jan 2011 14:26:40 +0000 (15:26 +0100)
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@ericsson.com>
40 files changed:
.gitignore
Makefile.am
README
TODO
configure.ac
doc/Makefile.am
doc/info/ust.texi
doc/man/Makefile.am
doc/man/ust-consumerd.1 [new file with mode: 0644]
doc/man/ust-consumerd.1.md [new file with mode: 0644]
doc/man/ustctl.1
doc/man/ustctl.1.md
doc/man/ustd.1 [deleted file]
doc/man/ustd.1.md [deleted file]
doc/man/usttrace.1
doc/man/usttrace.1.md
include/Makefile.am
include/ust/ustconsumer.h [new file with mode: 0644]
include/ust/ustd.h [deleted file]
libust/tracectl.c
libustcmd/ustcmd.c
libustconsumer/Makefile.am [new file with mode: 0644]
libustconsumer/libustconsumer.c [new file with mode: 0644]
libustconsumer/lowlevel.c [new file with mode: 0644]
libustconsumer/lowlevel.h [new file with mode: 0644]
libustd/Makefile.am [deleted file]
libustd/libustd.c [deleted file]
libustd/lowlevel.c [deleted file]
libustd/lowlevel.h [deleted file]
tests/manual_mode_tracing.sh
tests/runtests
tests/valgrind_ust-consumerd.sh [new file with mode: 0755]
tests/valgrind_ustd.sh [deleted file]
ust-consumerd/Makefile.am [new file with mode: 0644]
ust-consumerd/README [new file with mode: 0644]
ust-consumerd/ust-consumerd.c [new file with mode: 0644]
ustd/Makefile.am [deleted file]
ustd/README [deleted file]
ustd/ustd.c [deleted file]
usttrace

index 020c2f4c699db890997f4a4a632ca77cf6108d9c..9935f115fde6396b46d99398eba1e461c478e48b 100644 (file)
@@ -23,4 +23,4 @@ stamp-h1
 libtool
 
 ustctl/ustctl
-ustd/ustd
+ust-consumerd/ust-consumerd
index 5132d59fc547db4d80270ca13179e6eb8f625189..249bf026d5cad0f4deb282f937f41a16a42759ab 100644 (file)
@@ -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 8eaf618ed9a28c1b150da2fa56fcf71a42f514ea..a381c951a376f1debab6e3583c67ba3f1cebcacb 100644 (file)
--- 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 46d5b6420dd81eb785dc5027dd68062d4d2a1ec8..0d0758967466898592b559c1372ed3d0ca028a36 100644 (file)
--- 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
index 189ab1227d259f98690c9278985b47ce02971e1e..b6cf946137d46454fc1243c2907dd7ae350989e6 100644 (file)
@@ -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
index 37a55ac2a57cafac0e9bf5598c81d73b9ea083ee..463203c27c86041e7bd9e1b563f8d879c186b4d0 100644 (file)
@@ -1 +1 @@
-SUBDIRS = man info
\ No newline at end of file
+SUBDIRS = man info
index e0565f39a96261c73e291fca68eeee6dd58760c9..a0ccdf17707de80bb21333f8fb9724b398af7570 100644 (file)
@@ -92,7 +92,7 @@ Components licensed as GPL v2:
 @itemize @bullet
 @item ustctl
 @item libustcmd
-@item ustd
+@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
index 7e18b8e89ae7c76d61fc927d0a798e56b11b6eff..5adbba4e4e7f7500411baea1f09be4156369ee35 100644 (file)
@@ -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 (file)
index 0000000..c6ce6a4
--- /dev/null
@@ -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@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 (file)
index 0000000..1b93f47
--- /dev/null
@@ -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 &lt;jbernard@debian.org&gt;, for
+the Debian project (and may be used by others).
index 4f171c61ecd247c192852265ac275334d9c6f8ee..b0f97d9a774e5898a91b2b30f053061867d9606d 100644 (file)
@@ -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.
index 208e1dd88c05b6fb01ff3f0e2de65a3919570852..c8ad1f1722fc907bb03a31e0f88a2cfb59b44b55 100644 (file)
@@ -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 (file)
index f423978..0000000
+++ /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@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 (file)
index 296d1c4..0000000
+++ /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 &lt;jbernard@debian.org&gt;, for
-the Debian project (and may be used by others).
index e789e451199da86425689350cac6ff8ba30b2a26..a56cfc439b1b7e0107a8de880d1f119958c06754 100644 (file)
@@ -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.
index 34acb363aff50cc3e754af714a4c65ea0d3a809f..75cff9a0d4ddabce8477302e090b02a5741c8611 100644 (file)
@@ -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
index 0ace775745d33bd4f245c5e4a9f276522f4207a9..400e8b1a8fde99f3fbefb139d1dcaef4f588651f 100644 (file)
@@ -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 (file)
index 0000000..e07b75e
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * libustconsumer header file
+ *
+ * Copyright 2005-2010 -
+ *              Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
+ * Copyright 2010-
+ *              Oumarou Dicko <oumarou.dicko@polymtl.ca>
+ *              Michael Sills-Lavoie <michael.sills-lavoie@polymtl.ca>
+ *              Alexis Halle <alexis.halle@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 (file)
index 6336e69..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * libustd header file
- *
- * Copyright 2005-2010 -
- *              Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
- * Copyright 2010-
- *              Oumarou Dicko <oumarou.dicko@polymtl.ca>
- *              Michael Sills-Lavoie <michael.sills-lavoie@polymtl.ca>
- *              Alexis Halle <alexis.halle@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 */
-
index a7da94569a896d464227f50315a364d42e105a37..b783c76e2ba8c87f0aa7280408c7c60236c885fe 100644 (file)
@@ -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.
index 2c16e754da425d2f9c1fcc9b71fdb84f0db77347..62c117f8cfa87de2d162370acc35f9e91242e572 100644 (file)
@@ -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 (file)
index 0000000..1f87479
--- /dev/null
@@ -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 (file)
index 0000000..6cb3dbf
--- /dev/null
@@ -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 (file)
index 0000000..7eb124b
--- /dev/null
@@ -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 (file)
index 0000000..6ae6476
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * lowlevel libustd header file
+ *
+ * Copyright 2005-2010 -
+ *              Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
+ * Copyright 2010-
+ *              Oumarou Dicko <oumarou.dicko@polymtl.ca>
+ *              Michael Sills-Lavoie <michael.sills-lavoie@polymtl.ca>
+ *              Alexis Halle <alexis.halle@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 (file)
index 1b9a961..0000000
+++ /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 (file)
index 0dc6940..0000000
+++ /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 (file)
index a8abf92..0000000
+++ /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 (file)
index a1d8da5..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * lowlevel libustd header file
- *
- * Copyright 2005-2010 -
- *              Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
- * Copyright 2010-
- *              Oumarou Dicko <oumarou.dicko@polymtl.ca>
- *              Michael Sills-Lavoie <michael.sills-lavoie@polymtl.ca>
- *              Alexis Halle <alexis.halle@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 */
-
index 3f203b1c8d8ecd1636ae7050759bb7add0438bd4..09f07645ca08515261790f362d6a684bd10e4162 100755 (executable)
@@ -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"
index 9560c46f29ebd29b2f2f88f11f9b50da03512bfd..afc1e21170a9b64777abc5dc7b558fbf475593e7 100755 (executable)
@@ -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 (executable)
index 0000000..53b1208
--- /dev/null
@@ -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 (executable)
index 541d8ca..0000000
+++ /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 (file)
index 0000000..01e3b82
--- /dev/null
@@ -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 (file)
index 0000000..6df4015
--- /dev/null
@@ -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 (file)
index 0000000..fae4efa
--- /dev/null
@@ -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 (file)
index 991c717..0000000
+++ /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 (file)
index 8fcd218..0000000
+++ /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 (file)
index e75fd9d..0000000
+++ /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;
-}
index 94404dde6d56e0bba1ef9aee9f299d328ba9f361..5d6729ebe356a59a662db96421cf619676f8c2be 100755 (executable)
--- 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
This page took 0.116466 seconds and 4 git commands to generate.