lttng add-context name --kernel [--event name] [--channel name] --type context_type [context options]
lttng add-context name --userspace [--event name] [--channel name] [--all/--pid n/cmd_name] --type context_type [context options]
+
+lttng consume [PATH] --continue --snapshot --stop
enum lttng_kernel_instrumentation {
LTTNG_KERNEL_TRACEPOINTS,
LTTNG_KERNEL_KPROBES,
- LTTNG_KERNEL_FUNCTION_TRACER,
+ LTTNG_KERNEL_FUNCTION,
};
/*
* LTTng DebugFS ABI structures.
+ *
+ * This is the kernel ABI copied from lttng-modules tree.
*/
-struct lttng_kernel_channel {
- int overwrite; /* 1: overwrite, 0: discard */
- uint64_t subbuf_size; /* in bytes */
- uint64_t num_subbuf;
- unsigned int switch_timer_interval; /* usecs */
- unsigned int read_timer_interval; /* usecs */
-};
-
-struct lttng_kernel_tracepoint {
-};
-
-/*
- * Either addr is used, or symbol_name and offset.
- */
+/* Either addr is used or symbol_name and offset. */
struct lttng_kernel_kprobe {
uint64_t addr;
};
struct lttng_kernel_event {
- char name[LTTNG_SYM_NAME_LEN]; /* event name */
+ char name[LTTNG_SYM_NAME_LEN];
enum lttng_kernel_instrumentation instrumentation;
/* Per instrumentation type configuration */
union {
- struct lttng_kernel_tracepoint tracepoint;
struct lttng_kernel_kprobe kprobe;
struct lttng_kernel_function_tracer ftrace;
} u;
#define LTTNG_RUNDIR "/var/run/lttng"
+/* Default channel attributes */
+#define DEFAULT_CHANNEL_NAME "channel0"
+#define DEFAULT_CHANNEL_OVERWRITE 0
+#define DEFAULT_CHANNEL_SUBBUF_SIZE 4096 /* bytes */
+#define DEFAULT_CHANNEL_SUBBUF_NUM 8 /* Must always be a power of 2 */
+#define DEFAULT_CHANNEL_SWITCH_TIMER 0 /* usec */
+#define DEFAULT_CHANNEL_READ_TIMER 200 /* usec */
+
+/*
+ * lttng user-space instrumentation type
+ */
+enum lttng_ust_instrumentation {
+ LTTNG_UST_TRACEPOINT,
+ LTTNG_UST_MARKER,
+};
+
#endif /* _LTTNG_SHARE_H */
#ifndef _LTTNG_H
#define _LTTNG_H
+#include <asm/types.h>
+#include <stdint.h>
#include <limits.h>
-#include <uuid/uuid.h>
/* Default unix group name for tracing. */
#define LTTNG_DEFAULT_TRACING_GROUP "tracing"
#define LTTNG_SESSIOND_PATH_ENV "LTTNG_SESSIOND_PATH"
/*
- * Trace type for lttng_trace.
+ * Event symbol length.
*/
-enum lttng_trace_type {
- KERNEL,
- USERSPACE,
+#define LTTNG_SYMBOL_NAME_LEN 128
+
+enum lttng_event_type {
+ LTTNG_EVENT_TRACEPOINTS,
+ LTTNG_EVENT_KPROBES,
+ LTTNG_EVENT_FUNCTION,
};
/*
- * Basic trace information exposed.
+ * Either addr is used or symbol_name and offset.
*/
-struct lttng_trace {
- char name[NAME_MAX];
- pid_t pid; /* Only useful for user-space trace */
- enum lttng_trace_type type;
+struct lttng_event_kprobe_attr {
+ uint64_t addr;
+
+ uint64_t offset;
+ char symbol_name[LTTNG_SYMBOL_NAME_LEN];
};
/*
- * Basic session information exposed.
+ * Function tracer
+ */
+struct lttng_event_function_attr {
+ char symbol_name[LTTNG_SYMBOL_NAME_LEN];
+};
+
+/*
+ * Generic lttng event
+ */
+struct lttng_event {
+ char name[LTTNG_SYMBOL_NAME_LEN];
+ enum lttng_event_type type;
+ /* Per event type configuration */
+ union {
+ struct lttng_event_kprobe_attr kprobe;
+ struct lttng_event_function_attr ftrace;
+ } attr;
+};
+
+/* Tracer channel attributes */
+struct lttng_channel_attr {
+ int overwrite; /* 1: overwrite, 0: discard */
+ uint64_t subbuf_size; /* bytes */
+ uint64_t num_subbuf; /* power of 2 */
+ unsigned int switch_timer_interval; /* usec */
+ unsigned int read_timer_interval; /* usec */
+};
+
+/*
+ * Basic session information.
*/
struct lttng_session {
char name[NAME_MAX];
- uuid_t uuid;
+ char path[PATH_MAX];
+};
+
+/* Channel information structure */
+struct lttng_channel {
+ char name[NAME_MAX];
+ struct lttng_channel_attr attr;
};
/*
* Session daemon control
*/
extern int lttng_connect_sessiond(void);
-extern int lttng_create_session(char *name);
-extern int lttng_destroy_session(uuid_t *uuid);
+
+extern int lttng_create_session(char *name, char *path);
+
+extern int lttng_destroy_session(char *name);
+
extern int lttng_disconnect_sessiond(void);
+
/* Return an allocated array of lttng_session */
extern int lttng_list_sessions(struct lttng_session **sessions);
-/* Return an allocated array of lttng_traces */
-extern int lttng_list_traces(uuid_t *uuid, struct lttng_trace **traces);
+
extern int lttng_session_daemon_alive(void);
+
/* Set tracing group for the current execution */
extern int lttng_set_tracing_group(const char *name);
-/* Set session uuid for the current execution */
-extern void lttng_set_current_session_uuid(uuid_t *uuid);
+
+extern void lttng_set_session_name(char *name);
+
extern const char *lttng_get_readable_code(int code);
+extern int lttng_start_tracing(char *session_name);
+
+extern int lttng_stop_tracing(char *session_name);
+
+//extern int lttng_ust_list_traceable_apps(pid_t **pids);
+
/*
- * User-space tracer control
+ * LTTng Kernel tracer control
*/
-extern int lttng_ust_create_trace(pid_t pid);
-/* Return an allocated array of pids */
-extern int lttng_ust_list_apps(pid_t **pids);
-extern int lttng_ust_start_trace(pid_t pid);
-extern int lttng_ust_stop_trace(pid_t pid);
+extern int lttng_kernel_create_channel(struct lttng_channel *chan);
+
+extern int lttng_kernel_enable_event(struct lttng_event *ev, char *channel_name);
+
+extern int lttng_kernel_enable_channel(char *name);
+
+extern int lttng_kernel_disable_event(char *name, char *channel_name);
+
+extern int lttng_kernel_disable_channel(char *name);
+
+extern int lttng_kernel_list_events(char **event_list);
/*
- * Kernel tracer control
+ * LTTng User-space tracer control
*/
-extern int lttng_kernel_create_channel(void);
-extern int lttng_kernel_create_session(void);
-extern int lttng_kernel_create_stream(void);
-extern int lttng_kernel_disable_event(char *event_name);
-extern int lttng_kernel_enable_event(char *event_name);
-extern int lttng_kernel_list_events(char **event_list);
-extern int lttng_kernel_open_metadata(void);
-extern int lttng_kernel_start_tracing(void);
-extern int lttng_kernel_stop_tracing(void);
#endif /* _LTTNG_H */
#define _LTT_KERNEL_IOCTL_H
/* Get a snapshot of the current ring buffer producer and consumer positions */
-#define RING_BUFFER_SNAPSHOT _IO(0xF6, 0x00)
+#define RING_BUFFER_SNAPSHOT _IO(0xF6, 0x00)
/* Get the consumer position (iteration start) */
#define RING_BUFFER_SNAPSHOT_GET_CONSUMED _IOR(0xF6, 0x01, unsigned long)
/* Get the producer position (iteration end) */
#define RING_BUFFER_SNAPSHOT_GET_PRODUCED _IOR(0xF6, 0x02, unsigned long)
/* Get exclusive read access to the specified sub-buffer position */
-#define RING_BUFFER_GET_SUBBUF _IOW(0xF6, 0x03, unsigned long)
+#define RING_BUFFER_GET_SUBBUF _IOW(0xF6, 0x03, unsigned long)
/* Release exclusive sub-buffer access */
-#define RING_BUFFER_PUT_SUBBUF _IO(0xF6, 0x04)
+#define RING_BUFFER_PUT_SUBBUF _IO(0xF6, 0x04)
/* Get exclusive read access to the next sub-buffer that can be read. */
-#define RING_BUFFER_GET_NEXT_SUBBUF _IO(0xF6, 0x05)
+#define RING_BUFFER_GET_NEXT_SUBBUF _IO(0xF6, 0x05)
/* Release exclusive sub-buffer access, move consumer forward. */
-#define RING_BUFFER_PUT_NEXT_SUBBUF _IO(0xF6, 0x06)
+#define RING_BUFFER_PUT_NEXT_SUBBUF _IO(0xF6, 0x06)
/* returns the size of the current sub-buffer, without padding (for mmap). */
-#define RING_BUFFER_GET_SUBBUF_SIZE _IOR(0xF6, 0x07, unsigned long)
+#define RING_BUFFER_GET_SUBBUF_SIZE _IOR(0xF6, 0x07, unsigned long)
/* returns the size of the current sub-buffer, with padding (for splice). */
#define RING_BUFFER_GET_PADDED_SUBBUF_SIZE _IOR(0xF6, 0x08, unsigned long)
/* returns the maximum size for sub-buffers. */
#define RING_BUFFER_GET_MAX_SUBBUF_SIZE _IOR(0xF6, 0x09, unsigned long)
/* returns the length to mmap. */
-#define RING_BUFFER_GET_MMAP_LEN _IOR(0xF6, 0x0A, unsigned long)
+#define RING_BUFFER_GET_MMAP_LEN _IOR(0xF6, 0x0A, unsigned long)
/* returns the offset of the subbuffer belonging to the mmap reader. */
#define RING_BUFFER_GET_MMAP_READ_OFFSET _IOR(0xF6, 0x0B, unsigned long)
+/* flush the current sub-buffer */
+#define RING_BUFFER_FLUSH _IO(0xF6, 0x0C)
+
+#define LTTNG_KERNEL_SESSION _IO(0xF6, 0x40)
+#define LTTNG_KERNEL_TRACER_VERSION \
+ _IOR(0xF6, 0x41, struct lttng_kernel_tracer_version)
-#define LTTNG_KERNEL_SESSION _IO(0xF6, 0x40)
-#define LTTNG_KERNEL_TRACER_VERSION \
- _IOR(0xF6, 0x41, struct lttng_kernel_tracer_version)
#define LTTNG_KERNEL_TRACEPOINT_LIST _IO(0xF6, 0x42)
+#define LTTNG_KERNEL_WAIT_QUIESCENT _IO(0xF6, 0x43)
/* Session FD ioctl */
-#define LTTNG_KERNEL_METADATA \
- _IOW(0xF6, 0x50, struct lttng_kernel_channel)
-#define LTTNG_KERNEL_CHANNEL \
- _IOW(0xF6, 0x51, struct lttng_kernel_channel)
-#define LTTNG_KERNEL_SESSION_START _IO(0xF6, 0x52)
-#define LTTNG_KERNEL_SESSION_STOP _IO(0xF6, 0x53)
+#define LTTNG_KERNEL_METADATA \
+ _IOW(0xF6, 0x50, struct lttng_channel_attr)
+
+#define LTTNG_KERNEL_CHANNEL \
+ _IOW(0xF6, 0x51, struct lttng_channel_attr)
+
+#define LTTNG_KERNEL_SESSION_START _IO(0xF6, 0x52)
+#define LTTNG_KERNEL_SESSION_STOP _IO(0xF6, 0x53)
/* Channel FD ioctl */
-#define LTTNG_KERNEL_STREAM _IO(0xF6, 0x60)
-#define LTTNG_KERNEL_EVENT \
- _IOW(0xF6, 0x61, struct lttng_kernel_event)
+#define LTTNG_KERNEL_STREAM _IO(0xF6, 0x60)
+
+#define LTTNG_KERNEL_EVENT \
+ _IOW(0xF6, 0x61, struct lttng_kernel_event)
+
+/* Event, Channel and Session ioctl */
+#define LTTNG_KERNEL_ENABLE _IO(0xF6, 0x80)
+#define LTTNG_KERNEL_DISABLE _IO(0xF6, 0x81)
#endif /* _LTT_KERNEL_IOCTL_H */
#include "kernel-ioctl.h"
#include "libkernelctl.h"
-#include "lttngerr.h"
-int kernctl_create_channel(int fd, struct lttng_kernel_channel *chops)
+int kernctl_buffer_flush(int fd)
+{
+ return ioctl(fd, RING_BUFFER_FLUSH);
+}
+
+int kernctl_create_channel(int fd, struct lttng_channel_attr *chops)
{
return ioctl(fd, LTTNG_KERNEL_CHANNEL, chops);
}
return ioctl(fd, LTTNG_KERNEL_STREAM);
}
+/* Enable event, channel and session ioctl */
+int kernctl_enable(int fd)
+{
+ return ioctl(fd, LTTNG_KERNEL_ENABLE);
+}
+
+/* Disable event, channel and session ioctl */
+int kernctl_disable(int fd)
+{
+ return ioctl(fd, LTTNG_KERNEL_DISABLE);
+}
+
/* returns the maximum size for sub-buffers. */
int kernctl_get_max_subbuf_size(int fd, unsigned long *len)
{
}
/* open the metadata global channel */
-int kernctl_open_metadata(int fd, struct lttng_kernel_channel *chops)
+int kernctl_open_metadata(int fd, struct lttng_channel_attr *chops)
{
return ioctl(fd, LTTNG_KERNEL_METADATA, chops);
}
{
return ioctl(fd, LTTNG_KERNEL_TRACER_VERSION, v);
}
+
+int kernctl_wait_quiescent(int fd)
+{
+ return ioctl(fd, LTTNG_KERNEL_WAIT_QUIESCENT);
+}
#ifndef _LTT_LIBKERNELCTL_H
#define _LTT_LIBKERNELCTL_H
+#include <lttng/lttng.h>
+
#include "lttng-kernel.h"
-int kernctl_create_channel(int fd, struct lttng_kernel_channel *chops);
+int kernctl_buffer_flush(int fd);
+int kernctl_create_channel(int fd, struct lttng_channel_attr *chops);
int kernctl_create_event(int fd, struct lttng_kernel_event *ev);
+int kernctl_enable(int fd);
+int kernctl_disable(int fd);
int kernctl_create_session(int fd);
int kernctl_create_stream(int fd);
int kernctl_get_max_subbuf_size(int fd, unsigned long *len);
int kernctl_get_padded_subbuf_size(int fd, unsigned long *len);
int kernctl_get_subbuf(int fd, unsigned long *len);
int kernctl_get_subbuf_size(int fd, unsigned long *len);
-int kernctl_open_metadata(int fd, struct lttng_kernel_channel *chops);
+int kernctl_open_metadata(int fd, struct lttng_channel_attr *chops);
int kernctl_put_next_subbuf(int fd);
int kernctl_put_subbuf(int fd);
int kernctl_snapshot(int fd);
int kernctl_stop_session(int fd);
int kernctl_tracepoint_list(int fd);
int kernctl_tracer_version(int fd, struct lttng_kernel_tracer_version *v);
+int kernctl_wait_quiescent(int fd);
#endif /* _LTT_LIBKERNELCTL_H */
#include "liblttsessiondcomm.h"
#include "lttngerr.h"
+#include "lttng-share.h"
/* Socket to session daemon for communication */
static int sessiond_socket;
goto end;
}
- size = llm.trace_name_offset + llm.data_size;
+ size = llm.data_size;
if (size == 0) {
goto end;
}
}
/*
- * BEGIN KERNEL CONTROL
+ * lttng_start_tracing
+ *
+ * Start tracing for all trace of the session.
*/
+int lttng_start_tracing(char *session_name)
+{
+ strncpy(lsm.session_name, session_name, NAME_MAX);
+ return ask_sessiond(LTTNG_START_TRACE, NULL);
+}
/*
- * lttng_kernel_enable_event
+ * lttng_stop_tracing
*
- * Enable an event in the kernel tracer.
+ * Stop tracing for all trace of the session.
+ */
+int lttng_stop_tracing(char *session_name)
+{
+ strncpy(lsm.session_name, session_name, NAME_MAX);
+ return ask_sessiond(LTTNG_STOP_TRACE, NULL);
+}
+
+/*
+ * BEGIN Kernel control API
*/
-int lttng_kernel_enable_event(char *event_name)
+
+/*
+ * lttng_kernel_enable_event
+ */
+int lttng_kernel_enable_event(struct lttng_event *ev, char *channel_name)
{
int ret;
- if (event_name == NULL) {
- ret = ask_sessiond(KERNEL_ENABLE_ALL_EVENT, NULL);
+ if (strlen(channel_name) == 0) {
+ strncpy(lsm.u.enable.channel_name, DEFAULT_CHANNEL_NAME, NAME_MAX);
} else {
- strncpy(lsm.u.event.event_name, event_name, NAME_MAX);
- ret = ask_sessiond(KERNEL_ENABLE_EVENT, NULL);
+ strncpy(lsm.u.enable.channel_name, channel_name, NAME_MAX);
+ }
+
+ if (ev == NULL) {
+ ret = ask_sessiond(LTTNG_KERNEL_ENABLE_ALL_EVENT, NULL);
+ } else {
+ memcpy(&lsm.u.enable.event, ev, sizeof(struct lttng_event));
+ ret = ask_sessiond(LTTNG_KERNEL_ENABLE_EVENT, NULL);
}
return ret;
*
* Disable an event in the kernel tracer.
*/
-int lttng_kernel_disable_event(char *event_name)
+int lttng_kernel_disable_event(char *name, char *channel_name)
{
- strncpy(lsm.u.event.event_name, event_name, NAME_MAX);
- return ask_sessiond(KERNEL_DISABLE_EVENT, NULL);
-}
+ int ret;
-/*
- * lttng_kernel_create_session
- *
- * Create a session in the kernel tracer.
- */
-int lttng_kernel_create_session(void)
-{
- return ask_sessiond(KERNEL_CREATE_SESSION, NULL);
+ if (strlen(channel_name) == 0) {
+ strncpy(lsm.u.disable.channel_name, DEFAULT_CHANNEL_NAME, NAME_MAX);
+ } else {
+ strncpy(lsm.u.disable.channel_name, channel_name, NAME_MAX);
+ }
+
+ if (name == NULL) {
+ ret = ask_sessiond(LTTNG_KERNEL_DISABLE_ALL_EVENT, NULL);
+ } else {
+ strncpy(lsm.u.disable.name, name, NAME_MAX);
+ ret = ask_sessiond(LTTNG_KERNEL_DISABLE_EVENT, NULL);
+ }
+
+ return ret;
}
/*
- * lttng_kernel_create_channel
+ * lttng_kernel_enable_channel
*
- * Create a channel in the kernel tracer.
+ * Enable recording for a channel for the kernel tracer.
*/
-int lttng_kernel_create_channel(void)
+int lttng_kernel_enable_channel(char *name)
{
- return ask_sessiond(KERNEL_CREATE_CHANNEL, NULL);
+ return ask_sessiond(LTTNG_KERNEL_ENABLE_CHANNEL, NULL);
}
/*
- * lttng_kernel_open_metadata
+ * lttng_kernel_disable_channel
*
- * Open metadata in the kernel tracer.
+ * Disable recording for the channel for the kernel tracer.
*/
-int lttng_kernel_open_metadata(void)
+int lttng_kernel_disable_channel(char *name)
{
- return ask_sessiond(KERNEL_OPEN_METADATA, NULL);
+ return ask_sessiond(LTTNG_KERNEL_DISABLE_CHANNEL, NULL);
}
/*
- * lttng_kernel_create_stream
+ * lttng_kernel_create_channel
*
- * Create stream in the kernel tracer.
+ * Create a channel in the kernel tracer.
*/
-int lttng_kernel_create_stream(void)
+int lttng_kernel_create_channel(struct lttng_channel *chan)
{
- return ask_sessiond(KERNEL_CREATE_STREAM, NULL);
+ memcpy(&lsm.u.channel.chan, chan, sizeof(struct lttng_channel));
+ return ask_sessiond(LTTNG_KERNEL_CREATE_CHANNEL, NULL);
}
/*
- * lttng_kernel_list_events
+ * lttng_list_events
*
* List all available events in the kernel.
*
*/
int lttng_kernel_list_events(char **event_list)
{
- return ask_sessiond(KERNEL_LIST_EVENTS, (void **) event_list);
+ return ask_sessiond(LTTNG_KERNEL_LIST_EVENTS, (void **) event_list);
}
/*
- * lttng_kernel_start_tracing
- *
- * Start kernel tracing.
- */
-int lttng_kernel_start_tracing(void)
-{
- return ask_sessiond(KERNEL_START_TRACE, NULL);
-}
-
-/*
- * lttng_kernel_stop_tracing
- *
- * Stop kernel tracing.
- */
-int lttng_kernel_stop_tracing(void)
-{
- return ask_sessiond(KERNEL_STOP_TRACE, NULL);
-}
-
-/*
- * END KERNEL CONTROL
+ * END Kernel control API
*/
/*
return lttcomm_get_readable_code(code);
}
-/*
- * lttng_ust_start_trace
- *
- * Request a trace start for pid.
- */
-int lttng_ust_start_trace(pid_t pid)
-{
- lsm.pid = pid;
- return ask_sessiond(UST_START_TRACE, NULL);
-}
-
-/*
- * lttng_ust_stop_trace
- *
- * Request a trace stop for pid.
- */
-int lttng_ust_stop_trace(pid_t pid)
-{
- lsm.pid = pid;
- return ask_sessiond(UST_STOP_TRACE, NULL);
-}
-
-/*
- * lttng_ust_create_trace
- *
- * Request a trace creation for pid.
- */
-int lttng_ust_create_trace(pid_t pid)
-{
- lsm.pid = pid;
- return ask_sessiond(UST_CREATE_TRACE, NULL);
-}
-
/*
* lttng_ust_list_apps
*
* Return the number of pids.
* On error, return negative value.
*/
-int lttng_ust_list_apps(pid_t **pids)
+int lttng_ust_list_traceable_apps(pid_t **pids)
{
int ret;
- ret = ask_sessiond(UST_LIST_APPS, (void**) pids);
+ ret = ask_sessiond(LTTNG_LIST_TRACEABLE_APPS, (void**) pids);
if (ret < 0) {
return ret;
}
* lttng_list_traces
*
* Ask the session daemon for all traces (kernel and ust) for the session
- * identified by uuid.
+ * identified by name.
*
* Return the number of traces.
* On error, return negative value.
*/
-int lttng_list_traces(uuid_t *uuid, struct lttng_trace **traces)
+/*
+int lttng_list_traces(char *session_name, struct lttng_trace **traces)
{
int ret;
- uuid_copy(lsm.session_uuid, *uuid);
+ strncpy(lsm.session_name, session_name, NAME_MAX);
ret = ask_sessiond(LTTNG_LIST_TRACES, (void **) traces);
if (ret < 0) {
return ret / sizeof(struct lttng_trace);
}
+*/
/*
* lttng_create_session
*
* Create a brand new session using name.
*/
-int lttng_create_session(char *name)
+int lttng_create_session(char *name, char *path)
{
strncpy(lsm.session_name, name, NAME_MAX);
+ strncpy(lsm.path, path, PATH_MAX);
return ask_sessiond(LTTNG_CREATE_SESSION, NULL);
}
*
* Destroy session using name.
*/
-int lttng_destroy_session(uuid_t *uuid)
+int lttng_destroy_session(char *name)
{
- uuid_copy(lsm.session_uuid, *uuid);
+ strncpy(lsm.session_name, name, NAME_MAX);
return ask_sessiond(LTTNG_DESTROY_SESSION, NULL);
}
return ret;
}
-/*
- * lttng_set_current_session_uuid
- *
- * Set the session uuid for current lsm.
- */
-void lttng_set_current_session_uuid(uuid_t *uuid)
+void lttng_set_session_name(char *name)
{
- uuid_copy(lsm.session_uuid, *uuid);
+ strncpy(lsm.session_name, name, NAME_MAX);
}
/*
[ LTTCOMM_ERR_INDEX(LTTCOMM_NO_SESSION) ] = "No session found",
[ LTTCOMM_ERR_INDEX(LTTCOMM_LIST_FAIL) ] = "Unable to list traceable apps",
[ LTTCOMM_ERR_INDEX(LTTCOMM_NO_APPS) ] = "No traceable apps found",
- [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_SESS) ] = "No session found",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_SESS_NOT_FOUND) ] = "Session name not found",
[ LTTCOMM_ERR_INDEX(LTTCOMM_NO_TRACE) ] = "No trace found",
[ LTTCOMM_ERR_INDEX(LTTCOMM_FATAL) ] = "Fatal error of the session daemon",
[ LTTCOMM_ERR_INDEX(LTTCOMM_CREATE_FAIL) ] = "Create trace failed",
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_NA) ] = "Kernel tracer not available",
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_SESS_FAIL) ] = "Kernel create session failed",
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_CHAN_FAIL) ] = "Kernel create channel failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_CHAN_NOT_FOUND) ] = "Kernel channel not found",
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_ENABLE_FAIL) ] = "Enable kernel event failed",
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_DISABLE_FAIL) ] = "Disable kernel event failed",
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_META_FAIL) ] = "Opening metadata failed",
#define _LIBLTTSESSIONDCOMM_H
#include <limits.h>
-#include <uuid/uuid.h>
+#include <lttng/lttng.h>
#include "lttng-share.h"
/* Default unix socket path */
#define LTTCOMM_ERR_INDEX(code) (code - LTTCOMM_OK)
enum lttcomm_sessiond_command {
- KERNEL_CREATE_CHANNEL,
- KERNEL_CREATE_SESSION,
- KERNEL_CREATE_STREAM,
- KERNEL_DISABLE_EVENT,
- KERNEL_ENABLE_EVENT,
- KERNEL_ENABLE_ALL_EVENT,
- KERNEL_LIST_EVENTS,
- KERNEL_OPEN_METADATA,
- KERNEL_START_TRACE,
- KERNEL_STOP_TRACE,
+ /* Tracer context command */
+ LTTNG_KERNEL_CREATE_CHANNEL,
+ LTTNG_KERNEL_DISABLE_CHANNEL,
+ LTTNG_KERNEL_DISABLE_EVENT,
+ LTTNG_KERNEL_DISABLE_ALL_EVENT,
+ LTTNG_KERNEL_ENABLE_CHANNEL,
+ LTTNG_KERNEL_ENABLE_EVENT,
+ LTTNG_KERNEL_ENABLE_ALL_EVENT,
+ LTTNG_KERNEL_LIST_EVENTS,
+ /* Session daemon context command */
LTTNG_CREATE_SESSION,
LTTNG_DESTROY_SESSION,
- LTTNG_FORCE_SUBBUF_SWITCH,
- LTTNG_GET_ALL_SESSION,
- LTTNG_GET_SOCK_PATH,
- LTTNG_GET_SUBBUF_NUM_SIZE,
- LTTNG_LIST_MARKERS,
LTTNG_LIST_SESSIONS,
LTTNG_LIST_TRACES,
- LTTNG_LIST_TRACE_EVENTS,
- LTTNG_SETUP_TRACE,
- LTTNG_SET_SOCK_PATH,
- LTTNG_SET_SUBBUF_NUM,
- LTTNG_SET_SUBBUF_SIZE,
- UST_ALLOC_TRACE,
- UST_CREATE_TRACE,
- UST_DESTROY_TRACE,
- UST_DISABLE_MARKER,
- UST_ENABLE_MARKER,
- UST_LIST_APPS,
- UST_START_TRACE,
- UST_STOP_TRACE,
+ LTTNG_LIST_EVENTS,
+ LTTNG_LIST_TRACEABLE_APPS,
+ LTTNG_START_TRACE,
+ LTTNG_STOP_TRACE,
};
/*
LTTCOMM_STOP_FAIL, /* Stop tracing fail */
LTTCOMM_LIST_FAIL, /* Listing apps fail */
LTTCOMM_NO_APPS, /* No traceable application */
- LTTCOMM_NO_SESS, /* No sessions available */
+ LTTCOMM_SESS_NOT_FOUND, /* Session name not found */
LTTCOMM_NO_TRACE, /* No trace exist */
LTTCOMM_FATAL, /* Session daemon had a fatal error */
LTTCOMM_NO_TRACEABLE, /* Error for non traceable app */
LTTCOMM_KERN_NA, /* Kernel tracer unavalable */
LTTCOMM_KERN_SESS_FAIL, /* Kernel create session failed */
LTTCOMM_KERN_CHAN_FAIL, /* Kernel create channel failed */
+ LTTCOMM_KERN_CHAN_NOT_FOUND, /* Kernel channel not found */
LTTCOMM_KERN_ENABLE_FAIL, /* Kernel enable event failed */
LTTCOMM_KERN_DISABLE_FAIL, /* Kernel disable event failed */
LTTCOMM_KERN_META_FAIL, /* Kernel open metadata failed */
*/
struct lttcomm_session_msg {
u32 cmd_type; /* enum lttcomm_sessiond_command */
- uuid_t session_uuid;
- char trace_name[NAME_MAX];
char session_name[NAME_MAX];
- u32 pid; /* pid_t */
+ char path[PATH_MAX];
+ pid_t pid;
union {
struct {
- int auto_session;
- } create_session;
- /* Marker data */
+ char channel_name[NAME_MAX];
+ char name[NAME_MAX];
+ } disable;
+ /* Event data */
struct {
- char event_name[NAME_MAX];
- } event;
+ char channel_name[NAME_MAX];
+ struct lttng_event event;
+ } enable;
+ /* Create channel */
+ struct {
+ struct lttng_channel chan;
+ } channel;
} u;
};
u32 cmd_type; /* enum lttcomm_sessiond_command */
u32 ret_code; /* enum lttcomm_return_code */
u32 pid; /* pid_t */
- u32 trace_name_offset;
u32 data_size;
- uuid_t session_uuid;
/* Contains: trace_name + data */
char payload[];
};
}
lks->fd = ret;
+ lks->kconsumer_fds_sent = 0;
session->kernel_session = lks;
session->kern_session_count++;
* Create a kernel channel, register it to the kernel tracer and add it to the
* kernel session.
*/
-int kernel_create_channel(struct ltt_kernel_session *session)
+int kernel_create_channel(struct ltt_kernel_session *session, struct lttng_channel *chan)
{
int ret;
struct ltt_kernel_channel *lkc;
/* Allocate kernel channel */
- lkc = trace_create_kernel_channel();
+ lkc = trace_create_kernel_channel(chan);
if (lkc == NULL) {
goto error;
}
/* Kernel tracer channel creation */
- ret = kernctl_create_channel(session->fd, lkc->channel);
+ ret = kernctl_create_channel(session->fd, &lkc->channel->attr);
if (ret < 0) {
perror("ioctl kernel create channel");
goto error;
cds_list_add(&lkc->list, &session->channel_list.head);
session->channel_count++;
- DBG("Kernel channel created (fd: %d and path: %s)", lkc->fd, lkc->pathname);
+ DBG("Kernel channel %s created (fd: %d and path: %s)",
+ lkc->channel->name, lkc->fd, lkc->pathname);
return 0;
}
/*
- * kernel_enable_event
+ * kernel_create_event
*
* Create a kernel event, enable it to the kernel tracer and add it to the
* channel event list of the kernel session.
*/
-int kernel_enable_event(struct ltt_kernel_session *session, char *name)
+int kernel_create_event(struct ltt_kernel_channel *channel, struct lttng_event *ev)
{
int ret;
- struct ltt_kernel_channel *chan;
struct ltt_kernel_event *event;
- event = trace_create_kernel_event(name, LTTNG_KERNEL_TRACEPOINTS);
+ event = trace_create_kernel_event(ev);
if (event == NULL) {
goto error;
}
- cds_list_for_each_entry(chan, &session->channel_list.head, list) {
- ret = kernctl_create_event(chan->fd, event->event);
- if (ret < 0) {
- ERR("Unable to enable event %s", name);
- goto error;
- }
-
- event->fd = ret;
- /* Add event to event list */
- cds_list_add(&event->list, &chan->events_list.head);
- DBG("Event %s enabled (fd: %d)", name, event->fd);
+ ret = kernctl_create_event(channel->fd, event->event);
+ if (ret < 0) {
+ ERR("Unable to enable event %s for channel %s", ev->name, channel->channel->name);
+ goto error;
}
+ event->fd = ret;
+ /* Add event to event list */
+ cds_list_add(&event->list, &channel->events_list.head);
+ DBG("Event %s enabled (fd: %d)", ev->name, event->fd);
+
return 0;
error:
}
/* Kernel tracer metadata creation */
- ret = kernctl_open_metadata(session->fd, lkm->conf);
+ ret = kernctl_open_metadata(session->fd, &lkm->conf->attr);
if (ret < 0) {
goto error;
}
ret = kernctl_start_session(session->fd);
if (ret < 0) {
+ perror("ioctl start session");
goto error;
}
return ret;
}
+/*
+ * kernel_wait_quiescent
+ *
+ * Make a kernel wait to make sure in-flight probe have completed.
+ */
+void kernel_wait_quiescent(int fd)
+{
+ int ret;
+
+ DBG("Kernel quiescent wait on %d", fd);
+
+ ret = kernctl_wait_quiescent(fd);
+ if (ret < 0) {
+ perror("wait quiescent ioctl");
+ ERR("Kernel quiescent wait failed");
+ }
+}
+
+/*
+ * kernel_metadata_flush_buffer
+ *
+ * Force flush buffer of metadata.
+ */
+int kernel_metadata_flush_buffer(int fd)
+{
+ int ret;
+
+ ret = kernctl_buffer_flush(fd);
+ if (ret < 0) {
+ ERR("Fail to flush metadata buffers %d (ret: %d", fd, ret);
+ }
+
+ return 0;
+}
+
+/*
+ * kernel_flush_buffer
+ *
+ * Force flush buffer for channel.
+ */
+int kernel_flush_buffer(struct ltt_kernel_channel *channel)
+{
+ int ret;
+ struct ltt_kernel_stream *stream;
+
+ DBG("Flush buffer for channel %s", channel->channel->name);
+
+ cds_list_for_each_entry(stream, &channel->stream_list.head, list) {
+ DBG("Flushing channel stream %d", stream->fd);
+ ret = kernctl_buffer_flush(stream->fd);
+ if (ret < 0) {
+ perror("ioctl");
+ ERR("Fail to flush buffer for stream %d (ret: %d)",
+ stream->fd, ret);
+ }
+ }
+
+ return 0;
+}
+
/*
* kernel_stop_session
*
}
/*
- * kernel_create_channel_stream
+ * kernel_open_channel_stream
*
- * Create a stream for a channel, register it to the kernel tracer and add it
+ * Open stream of channel, register it to the kernel tracer and add it
* to the stream list of the channel.
*
* Return the number of created stream. Else, a negative value.
*/
-int kernel_create_channel_stream(struct ltt_kernel_channel *channel)
+int kernel_open_channel_stream(struct ltt_kernel_channel *channel)
{
int ret;
struct ltt_kernel_stream *lks;
}
/*
- * kernel_create_metadata_stream
+ * kernel_open_metadata_stream
*
- * Create the metadata stream and set it to the kernel session.
+ * Open the metadata stream and set it to the kernel session.
*/
-int kernel_create_metadata_stream(struct ltt_kernel_session *session)
+int kernel_open_metadata_stream(struct ltt_kernel_session *session)
{
int ret;
error:
return -1;
}
-
#define KERNEL_EVENT_LIST_SIZE 2000
int kernel_create_session(struct ltt_session *session, int tracer_fd);
-int kernel_create_channel(struct ltt_kernel_session *session);
-int kernel_enable_event(struct ltt_kernel_session *session, char *name);
+int kernel_create_channel(struct ltt_kernel_session *session, struct lttng_channel *chan);
+int kernel_create_event(struct ltt_kernel_channel *channel, struct lttng_event *ev);
int kernel_open_metadata(struct ltt_kernel_session *session);
-int kernel_create_metadata_stream(struct ltt_kernel_session *session);
-int kernel_create_channel_stream(struct ltt_kernel_channel *channel);
+int kernel_open_metadata_stream(struct ltt_kernel_session *session);
+int kernel_open_channel_stream(struct ltt_kernel_channel *channel);
+int kernel_flush_buffer(struct ltt_kernel_channel *channel);
+int kernel_metadata_flush_buffer(int fd);
int kernel_start_session(struct ltt_kernel_session *session);
int kernel_stop_session(struct ltt_kernel_session *session);
ssize_t kernel_list_events(int tracer_fd, char **event_list);
+void kernel_wait_quiescent(int fd);
#endif /* _LTT_KERNEL_CTL_H */
/*
+ DBG("Creating kernel event %s for channel %s.",
+ cmd_ctx->lsm->u.enable.event.name, cmd_ctx->lsm->u.enable.channel_name);
+
* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
*
* This program is free software; you can redistribute it and/or
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <unistd.h>
#include <urcu/list.h> /* URCU list library (-lurcu) */
// TODO complete session cleanup (including UST)
}
+ DBG("Closing kernel fd");
close(kernel_tracer_fd);
}
}
}
+/*
+ * send_kconsumerd_fds
+ *
+ * Send all stream fds of the kernel session to the consumer.
+ */
+static int send_kconsumerd_fds(int sock, struct ltt_kernel_session *session)
+{
+ int ret;
+ size_t nb_fd;
+ struct ltt_kernel_stream *stream;
+ struct ltt_kernel_channel *chan;
+ struct lttcomm_kconsumerd_header lkh;
+ struct lttcomm_kconsumerd_msg lkm;
+
+ nb_fd = session->stream_count_global;
+
+ /* Setup header */
+ lkh.payload_size = (nb_fd + 1) * sizeof(struct lttcomm_kconsumerd_msg);
+ lkh.cmd_type = ADD_STREAM;
+
+ DBG("Sending kconsumerd header");
+
+ ret = lttcomm_send_unix_sock(sock, &lkh, sizeof(struct lttcomm_kconsumerd_header));
+ if (ret < 0) {
+ perror("send kconsumerd header");
+ goto error;
+ }
+
+ DBG("Sending metadata stream fd");
+
+ /* Send metadata stream fd first */
+ lkm.fd = session->metadata_stream_fd;
+ lkm.state = ACTIVE_FD;
+ lkm.max_sb_size = session->metadata->conf->attr.subbuf_size;
+ strncpy(lkm.path_name, session->metadata->pathname, PATH_MAX);
+
+ ret = lttcomm_send_fds_unix_sock(sock, &lkm, &lkm.fd, 1, sizeof(lkm));
+ if (ret < 0) {
+ perror("send kconsumerd fd");
+ goto error;
+ }
+
+ cds_list_for_each_entry(chan, &session->channel_list.head, list) {
+ cds_list_for_each_entry(stream, &chan->stream_list.head, list) {
+ lkm.fd = stream->fd;
+ lkm.state = stream->state;
+ lkm.max_sb_size = chan->channel->attr.subbuf_size;
+ strncpy(lkm.path_name, stream->pathname, PATH_MAX);
+
+ DBG("Sending fd %d to kconsumerd", lkm.fd);
+
+ ret = lttcomm_send_fds_unix_sock(sock, &lkm, &lkm.fd, 1, sizeof(lkm));
+ if (ret < 0) {
+ perror("send kconsumerd fd");
+ goto error;
+ }
+ }
+ }
+
+ DBG("Kconsumerd fds sent");
+
+ return 0;
+
+error:
+ return ret;
+}
+
+/*
+ * create_trace_dir
+ *
+ * Create the trace output directory.
+ */
+static int create_trace_dir(struct ltt_kernel_session *session)
+{
+ int ret;
+ struct ltt_kernel_channel *chan;
+
+ /* Create all channel directories */
+ cds_list_for_each_entry(chan, &session->channel_list.head, list) {
+ DBG("Creating trace directory at %s", chan->pathname);
+ // TODO: recursive create dir
+ ret = mkdir(chan->pathname, S_IRWXU | S_IRWXG );
+ if (ret < 0) {
+ if (ret != EEXIST) {
+ perror("mkdir trace path");
+ ret = -errno;
+ goto error;
+ }
+ }
+ }
+
+ return 0;
+
+error:
+ return ret;
+}
+
/*
* ust_connect_app
*
*/
static int setup_lttng_msg(struct command_ctx *cmd_ctx, size_t size)
{
- int ret, buf_size, trace_name_size;
+ int ret, buf_size;
- /*
- * Check for the trace_name. If defined, it's part of the payload data of
- * the llm structure.
- */
- trace_name_size = strlen(cmd_ctx->lsm->trace_name);
- buf_size = trace_name_size + size;
+ buf_size = size;
cmd_ctx->llm = malloc(sizeof(struct lttcomm_lttng_msg) + buf_size);
if (cmd_ctx->llm == NULL) {
/* Copy common data */
cmd_ctx->llm->cmd_type = cmd_ctx->lsm->cmd_type;
cmd_ctx->llm->pid = cmd_ctx->lsm->pid;
- if (!uuid_is_null(cmd_ctx->lsm->session_uuid)) {
- uuid_copy(cmd_ctx->llm->session_uuid, cmd_ctx->lsm->session_uuid);
- }
- cmd_ctx->llm->trace_name_offset = trace_name_size;
cmd_ctx->llm->data_size = size;
cmd_ctx->lttng_msg_size = sizeof(struct lttcomm_lttng_msg) + buf_size;
- /* Copy trace name to the llm structure. Begining of the payload. */
- memcpy(cmd_ctx->llm->payload, cmd_ctx->lsm->trace_name, trace_name_size);
-
return buf_size;
error:
}
/*
- * send_kconsumerd_fds
+ * init_kernel_tracer
*
- * Send all stream fds of the kernel session to the consumer.
+ * Setup necessary data for kernel tracer action.
*/
-static int send_kconsumerd_fds(int sock, struct ltt_kernel_session *session)
+static void init_kernel_tracer(void)
{
- int ret;
- size_t nb_fd;
- struct ltt_kernel_stream *stream;
- struct ltt_kernel_channel *chan;
- struct lttcomm_kconsumerd_header lkh;
- struct lttcomm_kconsumerd_msg lkm;
-
- nb_fd = session->stream_count_global;
-
- /* Setup header */
- lkh.payload_size = (nb_fd + 1) * sizeof(struct lttcomm_kconsumerd_msg);
- lkh.cmd_type = ADD_STREAM;
-
- DBG("Sending kconsumerd header");
-
- ret = lttcomm_send_unix_sock(sock, &lkh, sizeof(struct lttcomm_kconsumerd_header));
- if (ret < 0) {
- perror("send kconsumerd header");
- goto error;
+ /* Set the global kernel tracer fd */
+ kernel_tracer_fd = open(DEFAULT_KERNEL_TRACER_PATH, O_RDWR);
+ if (kernel_tracer_fd < 0) {
+ WARN("No kernel tracer available");
+ kernel_tracer_fd = 0;
}
- DBG("Sending metadata stream fd");
+ DBG("Kernel tracer fd %d", kernel_tracer_fd);
+}
- /* Send metadata stream fd first */
- lkm.fd = session->metadata_stream_fd;
- lkm.state = ACTIVE_FD;
- lkm.max_sb_size = session->metadata->conf->subbuf_size;
- strncpy(lkm.path_name, session->metadata->pathname, PATH_MAX);
+/*
+ * start_kernel_trace
+ *
+ * Start tracing by creating trace directory and sending FDs to the kernel
+ * consumer.
+ */
+static int start_kernel_trace(struct ltt_kernel_session *session)
+{
+ int ret;
- ret = lttcomm_send_fds_unix_sock(sock, &lkm, &lkm.fd, 1, sizeof(lkm));
+ /* Create trace directory */
+ ret = create_trace_dir(session);
if (ret < 0) {
- perror("send kconsumerd fd");
- goto error;
- }
-
- cds_list_for_each_entry(chan, &session->channel_list.head, list) {
- cds_list_for_each_entry(stream, &chan->stream_list.head, list) {
- lkm.fd = stream->fd;
- lkm.state = stream->state;
- lkm.max_sb_size = chan->channel->subbuf_size;
- strncpy(lkm.path_name, stream->pathname, PATH_MAX);
-
- DBG("Sending fd %d to kconsumerd", lkm.fd);
-
- ret = lttcomm_send_fds_unix_sock(sock, &lkm, &lkm.fd, 1, sizeof(lkm));
- if (ret < 0) {
- perror("send kconsumerd fd");
- goto error;
- }
+ if (ret == -EEXIST) {
+ ret = LTTCOMM_KERN_DIR_EXIST;
+ } else {
+ ret = LTTCOMM_KERN_DIR_FAIL;
+ goto error;
}
}
- DBG("Kconsumerd fds sent");
+ if (session->kconsumer_fds_sent == 0) {
+ ret = send_kconsumerd_fds(kconsumerd_cmd_sock, session);
+ if (ret < 0) {
+ ERR("Send kconsumerd fds failed");
+ ret = LTTCOMM_KERN_CONSUMER_FAIL;
+ goto error;
+ }
- return 0;
+ session->kconsumer_fds_sent = 1;
+ }
error:
return ret;
}
/*
- * create_trace_dir
+ * init_default_channel
*
- * Create the trace output directory.
+ * Allocate a channel structure and fill it.
*/
-static int create_trace_dir(struct ltt_kernel_session *session)
+static struct lttng_channel *init_default_channel(void)
{
- int ret;
- struct ltt_kernel_channel *chan;
+ struct lttng_channel *chan;
- /* Create all channel directories */
- cds_list_for_each_entry(chan, &session->channel_list.head, list) {
- DBG("Creating trace directory at %s", chan->pathname);
- // TODO: recursive create dir
- ret = mkdir(chan->pathname, S_IRWXU | S_IRWXG );
- if (ret < 0) {
- if (ret != EEXIST) {
- perror("mkdir trace path");
- ret = -errno;
- goto error;
- }
- }
+ chan = malloc(sizeof(struct lttng_channel));
+ if (chan == NULL) {
+ perror("init channel malloc");
+ goto error;
}
- return 0;
+ if (snprintf(chan->name, NAME_MAX, DEFAULT_CHANNEL_NAME) < 0) {
+ perror("snprintf defautl channel name");
+ return NULL;
+ }
+
+ chan->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE;
+ chan->attr.subbuf_size = DEFAULT_CHANNEL_SUBBUF_SIZE;
+ chan->attr.num_subbuf = DEFAULT_CHANNEL_SUBBUF_NUM;
+ chan->attr.switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER;
+ chan->attr.read_timer_interval = DEFAULT_CHANNEL_READ_TIMER;
error:
- return ret;
+ return chan;
}
/*
- * init_kernel_tracer
+ * create_kernel_session
*
- * Setup necessary data for kernel tracer action.
+ * Create a kernel tracer session then create the default channel.
*/
-static void init_kernel_tracer(void)
+static int create_kernel_session(struct ltt_session *session)
{
- /* Set the global kernel tracer fd */
- kernel_tracer_fd = open(DEFAULT_KERNEL_TRACER_PATH, O_RDWR);
- if (kernel_tracer_fd < 0) {
- WARN("No kernel tracer available");
- kernel_tracer_fd = 0;
+ int ret;
+ struct lttng_channel *chan;
+
+ DBG("Creating kernel session");
+
+ ret = kernel_create_session(session, kernel_tracer_fd);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_SESS_FAIL;
+ goto error;
}
- DBG("Kernel tracer fd %d", kernel_tracer_fd);
+ chan = init_default_channel();
+ if (chan == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+
+ DBG("Creating default kernel channel %s", DEFAULT_CHANNEL_NAME);
+
+ ret = kernel_create_channel(session->kernel_session, chan);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_CHAN_FAIL;
+ goto error;
+ }
+
+error:
+ return ret;
}
/*
DBG("Processing client command %d", cmd_ctx->lsm->cmd_type);
- /* Check command that needs a session */
+ /* Listing commands don't need a session */
switch (cmd_ctx->lsm->cmd_type) {
case LTTNG_CREATE_SESSION:
case LTTNG_LIST_SESSIONS:
- case KERNEL_LIST_EVENTS:
- case UST_LIST_APPS:
+ case LTTNG_LIST_EVENTS:
+ case LTTNG_KERNEL_LIST_EVENTS:
+ case LTTNG_LIST_TRACEABLE_APPS:
break;
default:
- cmd_ctx->session = find_session_by_uuid(cmd_ctx->lsm->session_uuid);
+ DBG("Getting session %s by name", cmd_ctx->lsm->session_name);
+ cmd_ctx->session = find_session_by_name(cmd_ctx->lsm->session_name);
if (cmd_ctx->session == NULL) {
- ret = LTTCOMM_SELECT_SESS;
+ /* If session name not found */
+ if (cmd_ctx->lsm->session_name != NULL) {
+ ret = LTTCOMM_SESS_NOT_FOUND;
+ } else { /* If no session name specified */
+ ret = LTTCOMM_SELECT_SESS;
+ }
goto error;
}
break;
}
- /* Check command for kernel tracing */
+ /*
+ * Check kernel command for kernel session.
+ */
switch (cmd_ctx->lsm->cmd_type) {
- case KERNEL_CREATE_SESSION:
- case KERNEL_CREATE_CHANNEL:
- case KERNEL_CREATE_STREAM:
- case KERNEL_DISABLE_EVENT:
- case KERNEL_ENABLE_EVENT:
- case KERNEL_LIST_EVENTS:
- case KERNEL_OPEN_METADATA:
- case KERNEL_START_TRACE:
- case KERNEL_STOP_TRACE:
+ case LTTNG_KERNEL_CREATE_CHANNEL:
+ case LTTNG_KERNEL_DISABLE_ALL_EVENT:
+ case LTTNG_KERNEL_DISABLE_CHANNEL:
+ case LTTNG_KERNEL_DISABLE_EVENT:
+ case LTTNG_KERNEL_ENABLE_ALL_EVENT:
+ case LTTNG_KERNEL_ENABLE_CHANNEL:
+ case LTTNG_KERNEL_ENABLE_EVENT:
+ case LTTNG_KERNEL_LIST_EVENTS:
/* Kernel tracer check */
if (kernel_tracer_fd == 0) {
init_kernel_tracer();
goto error;
}
}
- break;
+
+ /* Need a session for kernel command */
+ if (cmd_ctx->lsm->cmd_type != LTTNG_KERNEL_LIST_EVENTS &&
+ cmd_ctx->session->kernel_session == NULL) {
+ ret = create_kernel_session(cmd_ctx->session);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_SESS_FAIL;
+ goto error;
+ }
+
+ if (kconsumerd_pid == 0) {
+ ret = start_kconsumerd();
+ if (ret < 0) {
+ goto error;
+ }
+ }
+ }
}
/* Connect to ust apps if available pid */
/* Process by command type */
switch (cmd_ctx->lsm->cmd_type) {
- case KERNEL_CREATE_SESSION:
- {
- ret = setup_lttng_msg(cmd_ctx, 0);
- if (ret < 0) {
- goto setup_error;
- }
-
- ret = start_kconsumerd();
- if (ret < 0) {
- goto error;
- }
-
- DBG("Creating kernel session");
-
- ret = kernel_create_session(cmd_ctx->session, kernel_tracer_fd);
- if (ret < 0) {
- ret = LTTCOMM_KERN_SESS_FAIL;
- goto error;
- }
-
- ret = LTTCOMM_OK;
- break;
- }
- case KERNEL_CREATE_CHANNEL:
+ case LTTNG_KERNEL_CREATE_CHANNEL:
{
+ /* Setup lttng message with no payload */
ret = setup_lttng_msg(cmd_ctx, 0);
if (ret < 0) {
goto setup_error;
}
+ /* Kernel tracer */
DBG("Creating kernel channel");
- ret = kernel_create_channel(cmd_ctx->session->kernel_session);
-
+ ret = kernel_create_channel(cmd_ctx->session->kernel_session,
+ &cmd_ctx->lsm->u.channel.chan);
if (ret < 0) {
ret = LTTCOMM_KERN_CHAN_FAIL;
goto error;
ret = LTTCOMM_OK;
break;
}
- case KERNEL_ENABLE_EVENT:
+ case LTTNG_KERNEL_ENABLE_EVENT:
{
+ int found = 0;
+ struct ltt_kernel_channel *chan;
+
/* Setup lttng message with no payload */
ret = setup_lttng_msg(cmd_ctx, 0);
if (ret < 0) {
goto setup_error;
}
- DBG("Enabling kernel event %s", cmd_ctx->lsm->u.event.event_name);
-
- ret = kernel_enable_event(cmd_ctx->session->kernel_session, cmd_ctx->lsm->u.event.event_name);
- if (ret < 0) {
- ret = LTTCOMM_KERN_ENABLE_FAIL;
- goto error;
+ /* Get channel by name and create event for that channel */
+ cds_list_for_each_entry(chan, &cmd_ctx->session->kernel_session->channel_list.head, list) {
+ if (strcmp(cmd_ctx->lsm->u.enable.channel_name, chan->channel->name) == 0) {
+ DBG("Creating kernel event %s for channel %s.",
+ cmd_ctx->lsm->u.enable.event.name, cmd_ctx->lsm->u.enable.channel_name);
+
+ ret = kernel_create_event(chan, &cmd_ctx->lsm->u.enable.event);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_ENABLE_FAIL;
+ goto error;
+ }
+ found = 1;
+ break;
+ }
}
- ret = LTTCOMM_OK;
+ if (!found) {
+ ret = LTTCOMM_KERN_CHAN_NOT_FOUND;
+ } else {
+ kernel_wait_quiescent(kernel_tracer_fd);
+ ret = LTTCOMM_OK;
+ }
break;
}
- case KERNEL_ENABLE_ALL_EVENT:
+ case LTTNG_KERNEL_ENABLE_ALL_EVENT:
{
- int pos, size;
+ int pos, size, found;
char *event_list, *event, *ptr;
+ struct ltt_kernel_channel *chan;
+ struct lttng_event ev;
/* Setup lttng message with no payload */
ret = setup_lttng_msg(cmd_ctx, 0);
goto error;
}
+ /* Get channel by name and create event for that channel */
+ cds_list_for_each_entry(chan, &cmd_ctx->session->kernel_session->channel_list.head, list) {
+ if (strcmp(cmd_ctx->lsm->u.enable.channel_name, chan->channel->name) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ ret = LTTCOMM_KERN_CHAN_NOT_FOUND;
+ goto error;
+ }
+
ptr = event_list;
while ((size = sscanf(ptr, "event { name = %m[^;]; };%n\n", &event, &pos)) == 1) {
- /* Enable each single event */
- ret = kernel_enable_event(cmd_ctx->session->kernel_session, event);
+ strncpy(ev.name, event, LTTNG_SYM_NAME_LEN);
+ /* Default event type for enable all */
+ ev.type = LTTNG_EVENT_TRACEPOINTS;
+ /* Enable each single tracepoint event */
+ ret = kernel_create_event(chan, &ev);
if (ret < 0) {
ret = LTTCOMM_KERN_ENABLE_FAIL;
goto error;
free(event_list);
+ /* Quiescent wait after event enable */
+ kernel_wait_quiescent(kernel_tracer_fd);
ret = LTTCOMM_OK;
break;
}
- case KERNEL_LIST_EVENTS:
+ case LTTNG_KERNEL_LIST_EVENTS:
{
char *event_list;
- ssize_t size;
+ ssize_t size = 0;
+
+ DBG("Listing kernel events");
size = kernel_list_events(kernel_tracer_fd, &event_list);
if (size < 0) {
ret = LTTCOMM_OK;
break;
}
- case KERNEL_OPEN_METADATA:
- {
- /* Setup lttng message with no payload */
- ret = setup_lttng_msg(cmd_ctx, 0);
- if (ret < 0) {
- goto setup_error;
- }
-
- DBG("Open kernel metadata");
-
- ret = kernel_open_metadata(cmd_ctx->session->kernel_session);
- if (ret < 0) {
- ret = LTTCOMM_KERN_META_FAIL;
- goto error;
- }
-
- ret = LTTCOMM_OK;
- break;
- }
- case KERNEL_CREATE_STREAM:
+ case LTTNG_START_TRACE:
{
struct ltt_kernel_channel *chan;
+
/* Setup lttng message with no payload */
ret = setup_lttng_msg(cmd_ctx, 0);
if (ret < 0) {
goto setup_error;
}
- DBG("Creating kernel stream");
+ /* Kernel tracing */
+ if (cmd_ctx->session->kernel_session != NULL) {
+ if (cmd_ctx->session->kernel_session->metadata == NULL) {
+ DBG("Open kernel metadata");
+ ret = kernel_open_metadata(cmd_ctx->session->kernel_session);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_META_FAIL;
+ goto error;
+ }
+ }
- ret = kernel_create_metadata_stream(cmd_ctx->session->kernel_session);
- if (ret < 0) {
- ERR("Kernel create metadata stream failed");
- ret = LTTCOMM_KERN_STREAM_FAIL;
- goto error;
- }
+ if (cmd_ctx->session->kernel_session->metadata_stream_fd == 0) {
+ DBG("Opening kernel metadata stream");
+ if (cmd_ctx->session->kernel_session->metadata_stream_fd == 0) {
+ ret = kernel_open_metadata_stream(cmd_ctx->session->kernel_session);
+ if (ret < 0) {
+ ERR("Kernel create metadata stream failed");
+ ret = LTTCOMM_KERN_STREAM_FAIL;
+ goto error;
+ }
+ }
+ }
- /* For each channel */
- cds_list_for_each_entry(chan, &cmd_ctx->session->kernel_session->channel_list.head, list) {
- ret = kernel_create_channel_stream(chan);
+ /* For each channel */
+ cds_list_for_each_entry(chan, &cmd_ctx->session->kernel_session->channel_list.head, list) {
+ if (chan->stream_count == 0) {
+ ret = kernel_open_channel_stream(chan);
+ if (ret < 0) {
+ ERR("Kernel create channel stream failed");
+ ret = LTTCOMM_KERN_STREAM_FAIL;
+ goto error;
+ }
+ /* Update the stream global counter */
+ cmd_ctx->session->kernel_session->stream_count_global += ret;
+ }
+ }
+
+ DBG("Start kernel tracing");
+ ret = kernel_start_session(cmd_ctx->session->kernel_session);
if (ret < 0) {
- ERR("Kernel create channel stream failed");
- ret = LTTCOMM_KERN_STREAM_FAIL;
+ ERR("Kernel start session failed");
+ ret = LTTCOMM_KERN_START_FAIL;
goto error;
}
- /* Update the stream global counter */
- cmd_ctx->session->kernel_session->stream_count_global += ret;
- }
-
- ret = LTTCOMM_OK;
- break;
- }
- case KERNEL_START_TRACE:
- {
- /* Setup lttng message with no payload */
- ret = setup_lttng_msg(cmd_ctx, 0);
- if (ret < 0) {
- goto setup_error;
- }
- DBG("Start kernel tracing");
-
- ret = create_trace_dir(cmd_ctx->session->kernel_session);
- if (ret < 0) {
- if (ret == -EEXIST) {
- ret = LTTCOMM_KERN_DIR_EXIST;
- } else {
- ret = LTTCOMM_KERN_DIR_FAIL;
+ ret = start_kernel_trace(cmd_ctx->session->kernel_session);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_START_FAIL;
goto error;
}
- }
- ret = kernel_start_session(cmd_ctx->session->kernel_session);
- if (ret < 0) {
- ERR("Kernel start session failed");
- ret = LTTCOMM_KERN_START_FAIL;
- goto error;
+ /* Quiescent wait after starting trace */
+ kernel_wait_quiescent(kernel_tracer_fd);
}
- ret = send_kconsumerd_fds(kconsumerd_cmd_sock, cmd_ctx->session->kernel_session);
- if (ret < 0) {
- ERR("Send kconsumerd fds failed");
- ret = LTTCOMM_KERN_CONSUMER_FAIL;
- goto error;
- }
+ /* TODO: Start all UST traces */
ret = LTTCOMM_OK;
break;
}
- case KERNEL_STOP_TRACE:
+ case LTTNG_STOP_TRACE:
{
+ struct ltt_kernel_channel *chan;
/* Setup lttng message with no payload */
ret = setup_lttng_msg(cmd_ctx, 0);
if (ret < 0) {
goto setup_error;
}
- if (cmd_ctx->session->kernel_session == NULL) {
- ret = LTTCOMM_KERN_NO_SESSION;
- goto error;
- }
+ /* Kernel tracer */
+ if (cmd_ctx->session->kernel_session != NULL) {
+ DBG("Stop kernel tracing");
- DBG("Stop kernel tracing");
+ ret = kernel_metadata_flush_buffer(cmd_ctx->session->kernel_session->metadata_stream_fd);
+ if (ret < 0) {
+ ERR("Kernel metadata flush failed");
+ }
- ret = kernel_stop_session(cmd_ctx->session->kernel_session);
- if (ret < 0) {
- ERR("Kernel stop session failed");
- ret = LTTCOMM_KERN_STOP_FAIL;
- goto error;
+ cds_list_for_each_entry(chan, &cmd_ctx->session->kernel_session->channel_list.head, list) {
+ ret = kernel_flush_buffer(chan);
+ if (ret < 0) {
+ ERR("Kernel flush buffer error");
+ }
+ }
+
+ ret = kernel_stop_session(cmd_ctx->session->kernel_session);
+ if (ret < 0) {
+ ERR("Kernel stop session failed");
+ ret = LTTCOMM_KERN_STOP_FAIL;
+ goto error;
+ }
+
+ /* Quiescent wait after stopping trace */
+ kernel_wait_quiescent(kernel_tracer_fd);
}
- /* Clean kernel session teardown */
- teardown_kernel_session(cmd_ctx->session);
+ /* TODO : User-space tracer */
ret = LTTCOMM_OK;
break;
goto setup_error;
}
- ret = create_session(cmd_ctx->lsm->session_name, &cmd_ctx->llm->session_uuid);
+ ret = create_session(cmd_ctx->lsm->session_name, cmd_ctx->lsm->path);
if (ret < 0) {
- if (ret == -1) {
+ if (ret == -EEXIST) {
ret = LTTCOMM_EXIST_SESS;
} else {
ret = LTTCOMM_FATAL;
goto setup_error;
}
- ret = destroy_session(&cmd_ctx->lsm->session_uuid);
+ /* Clean kernel session teardown */
+ teardown_kernel_session(cmd_ctx->session);
+
+ ret = destroy_session(cmd_ctx->lsm->session_name);
if (ret < 0) {
- ret = LTTCOMM_NO_SESS;
+ ret = LTTCOMM_FATAL;
goto error;
}
ret = LTTCOMM_OK;
break;
}
+ /*
case LTTNG_LIST_TRACES:
{
unsigned int trace_count;
ret = LTTCOMM_OK;
break;
}
+ */
+ /*
case UST_CREATE_TRACE:
{
- /* Setup lttng message with no payload */
ret = setup_lttng_msg(cmd_ctx, 0);
if (ret < 0) {
goto setup_error;
ret = ust_create_trace(cmd_ctx);
if (ret < 0) {
- goto setup_error;
+ goto error;
}
break;
}
- case UST_LIST_APPS:
+ */
+ case LTTNG_LIST_TRACEABLE_APPS:
{
unsigned int app_count;
ret = LTTCOMM_OK;
break;
}
+ /*
case UST_START_TRACE:
{
- /* Setup lttng message with no payload */
ret = setup_lttng_msg(cmd_ctx, 0);
if (ret < 0) {
goto setup_error;
}
case UST_STOP_TRACE:
{
- /* Setup lttng message with no payload */
ret = setup_lttng_msg(cmd_ctx, 0);
if (ret < 0) {
goto setup_error;
}
break;
}
+ */
case LTTNG_LIST_SESSIONS:
{
unsigned int session_count;
session_count = get_session_count();
if (session_count == 0) {
- ret = LTTCOMM_NO_SESS;
+ ret = LTTCOMM_NO_SESSION;
goto error;
}
return ret;
}
+/*
+ * set_ulimit
+ *
+ * Set open files limit to unlimited. This daemon can open a large number of
+ * file descriptors in order to consumer multiple kernel traces.
+ */
+static void set_ulimit(void)
+{
+ int ret;
+ struct rlimit lim;
+
+ lim.rlim_cur = 65535;
+ lim.rlim_max = 65535;
+
+ ret = setrlimit(RLIMIT_NOFILE, &lim);
+ if (ret < 0) {
+ perror("failed to set open files limit");
+ }
+}
+
/*
* main
*/
/* Setup kernel tracer */
init_kernel_tracer();
+
+ /* Set ulimit for open files */
+ set_ulimit();
} else {
if (strlen(apps_unix_sock_path) == 0) {
snprintf(apps_unix_sock_path, PATH_MAX,
* Return -1 if no session is found.
* On success, return 1;
*/
-int destroy_session(uuid_t *uuid)
+int destroy_session(char *name)
{
int found = -1;
struct ltt_session *iter;
cds_list_for_each_entry(iter, <t_session_list.head, list) {
- if (uuid_compare(iter->uuid, *uuid) == 0) {
+ if (strcmp(iter->name, name) == 0) {
DBG("Destroying session %s", iter->name);
del_session_list(iter);
free(iter);
/*
* create_session
*
- * Create a brand new session and add it to the
- * global session list.
+ * Create a brand new session and add it to the global session list.
*/
-int create_session(char *name, uuid_t *session_id)
+int create_session(char *name, char *path)
{
+ int ret;
struct ltt_session *new_session;
- DBG("Creating session %s", name);
+ DBG("Creating session %s at %s", name, path);
new_session = find_session_by_name(name);
if (new_session != NULL) {
- goto error;
+ ret = -EEXIST;
+ goto error_exist;
}
/* Allocate session data structure */
new_session = malloc(sizeof(struct ltt_session));
if (new_session == NULL) {
perror("malloc");
- goto error_mem;
+ ret = -ENOMEM;
+ goto error_malloc;
}
+ /* Define session name */
if (name != NULL) {
if (asprintf(&new_session->name, "%s", name) < 0) {
- goto error_mem;
+ ret = -ENOMEM;
+ goto error_asprintf;
}
} else {
- /* Generate session name based on the session count */
- if (asprintf(&new_session->name, "%s%d", "lttng-", session_count) < 0) {
- goto error_mem;
+ ERR("No session name given");
+ ret = -1;
+ goto error;
+ }
+
+ /* Define session system path */
+ if (path != NULL) {
+ if (asprintf(&new_session->path, "%s", path) < 0) {
+ ret = -ENOMEM;
+ goto error_asprintf;
}
+ } else {
+ ERR("No session path given");
+ ret = -1;
+ goto error;
}
/* UUID generation */
uuid_generate(new_session->uuid);
- uuid_copy(*session_id, new_session->uuid);
/*
* Set consumer (identifier) to 0. This means that there is
return 0;
error:
- return -1;
+error_asprintf:
+ if (new_session != NULL) {
+ free(new_session);
+ }
-error_mem:
- return -ENOMEM;
+error_exist:
+error_malloc:
+ return ret;
}
/*
* get_lttng_session
*
- * Iterate over the global session list and
- * fill the lttng_session array.
+ * Iterate over the global session list and fill the lttng_session array.
*/
void get_lttng_session(struct lttng_session *sessions)
{
* the control struct in the buffer.
*/
cds_list_for_each_entry(iter, <t_session_list.head, list) {
- /* Copy name and uuid */
- uuid_copy(lsess.uuid, iter->uuid);
+ strncpy(lsess.path, iter->path, sizeof(lsess.path));
+ lsess.path[sizeof(lsess.path) - 1] = '\0';
strncpy(lsess.name, iter->name, sizeof(lsess.name));
lsess.name[sizeof(lsess.name) - 1] = '\0';
memcpy(&sessions[i], &lsess, sizeof(lsess));
struct ltt_session {
struct cds_list_head list;
char *name;
+ char *path;
uuid_t uuid;
struct cds_list_head ust_traces;
struct ltt_kernel_session *kernel_session;
};
/* Prototypes */
-int create_session(char *name, uuid_t *session_id);
-int destroy_session(uuid_t *uuid);
+int create_session(char *name, char *path);
+int destroy_session(char *name);
void get_lttng_session(struct lttng_session *sessions);
struct ltt_session *find_session_by_uuid(uuid_t session_id);
struct ltt_session *find_session_by_name(char *name);
*
* Return pointer to structure or NULL.
*/
-struct ltt_kernel_channel *trace_create_kernel_channel(void)
+struct ltt_kernel_channel *trace_create_kernel_channel(struct lttng_channel *chan)
{
int ret;
struct ltt_kernel_channel *lkc;
- struct lttng_kernel_channel *chan;
lkc = malloc(sizeof(struct ltt_kernel_channel));
- chan = malloc(sizeof(struct lttng_kernel_channel));
- if (lkc == NULL || chan == NULL) {
- perror("kernel channel malloc");
+ if (lkc == NULL) {
+ perror("ltt_kernel_channel malloc");
goto error;
}
- /* Default value to channel */
- chan->overwrite = DEFAULT_KERNEL_OVERWRITE;
- chan->subbuf_size = DEFAULT_KERNEL_SUBBUF_SIZE;
- chan->num_subbuf = DEFAULT_KERNEL_SUBBUF_NUM;
- chan->switch_timer_interval = DEFAULT_KERNEL_SWITCH_TIMER;
- chan->read_timer_interval = DEFAULT_KERNEL_READ_TIMER;
+ lkc->channel = malloc(sizeof(struct lttng_channel));
+ if (lkc->channel == NULL) {
+ perror("lttng_channel malloc");
+ goto error;
+ }
+ memcpy(lkc->channel, chan, sizeof(struct lttng_channel));
lkc->fd = 0;
lkc->stream_count = 0;
- lkc->channel = chan;
/* Init linked list */
CDS_INIT_LIST_HEAD(&lkc->events_list.head);
CDS_INIT_LIST_HEAD(&lkc->stream_list.head);
*
* Return pointer to structure or NULL.
*/
-struct ltt_kernel_event *trace_create_kernel_event(char *name,
- enum lttng_kernel_instrumentation type)
+struct ltt_kernel_event *trace_create_kernel_event(struct lttng_event *ev)
{
struct ltt_kernel_event *lke;
struct lttng_kernel_event *attr;
goto error;
}
- /* Init event attribute */
- attr->instrumentation = type;
- strncpy(attr->name, name, LTTNG_SYM_NAME_LEN);
+ switch (ev->type) {
+ case LTTNG_EVENT_KPROBES:
+ attr->instrumentation = LTTNG_KERNEL_KPROBES;
+ attr->u.kprobe.addr = ev->attr.kprobe.addr;
+ attr->u.kprobe.offset = ev->attr.kprobe.offset;
+ strncpy(attr->u.kprobe.symbol_name,
+ ev->attr.kprobe.symbol_name, LTTNG_SYM_NAME_LEN);
+ break;
+ case LTTNG_EVENT_FUNCTION:
+ attr->instrumentation = LTTNG_KERNEL_FUNCTION;
+ strncpy(attr->u.ftrace.symbol_name,
+ ev->attr.ftrace.symbol_name, LTTNG_SYM_NAME_LEN);
+ break;
+ case LTTNG_EVENT_TRACEPOINTS:
+ attr->instrumentation = LTTNG_KERNEL_TRACEPOINTS;
+ break;
+ default:
+ ERR("Unknown kernel instrumentation type (%d)", ev->type);
+ goto error;
+ }
+
+ /* Copy event name */
+ strncpy(attr->name, ev->name, LTTNG_SYM_NAME_LEN);
+
/* Setting up a kernel event */
lke->fd = 0;
lke->event = attr;
{
int ret;
struct ltt_kernel_metadata *lkm;
- struct lttng_kernel_channel *attr;
+ struct lttng_channel *chan;
lkm = malloc(sizeof(struct ltt_kernel_metadata));
- attr = malloc(sizeof(struct lttng_kernel_channel));
- if (lkm == NULL || attr == NULL) {
+ chan = malloc(sizeof(struct lttng_channel));
+ if (lkm == NULL || chan == NULL) {
perror("kernel metadata malloc");
goto error;
}
/* Set default attributes */
- attr->overwrite = DEFAULT_KERNEL_OVERWRITE;
- attr->subbuf_size = DEFAULT_KERNEL_SUBBUF_SIZE;
- attr->num_subbuf = DEFAULT_KERNEL_SUBBUF_NUM;
- attr->switch_timer_interval = DEFAULT_KERNEL_SWITCH_TIMER;
- attr->read_timer_interval = DEFAULT_KERNEL_READ_TIMER;
+ chan->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE;
+ chan->attr.subbuf_size = DEFAULT_CHANNEL_SUBBUF_SIZE;
+ chan->attr.num_subbuf = DEFAULT_CHANNEL_SUBBUF_NUM;
+ chan->attr.switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER;
+ chan->attr.read_timer_interval = DEFAULT_CHANNEL_READ_TIMER;
/* Init metadata */
lkm->fd = 0;
- lkm->conf = attr;
+ lkm->conf = chan;
/* Set default metadata path */
ret = asprintf(&lkm->pathname, "%s/metadata", DEFAULT_TRACE_OUTPUT);
if (ret < 0) {
#include <limits.h>
#include <urcu/list.h>
-#include "lttng-kernel.h"
-/* Default kernel channel attributes */
-#define DEFAULT_KERNEL_OVERWRITE 0
-#define DEFAULT_KERNEL_SUBBUF_SIZE 4096 /* bytes */
-#define DEFAULT_KERNEL_SUBBUF_NUM 8 /* Must always be a power of 2 */
-#define DEFAULT_KERNEL_SWITCH_TIMER 0 /* usec */
-#define DEFAULT_KERNEL_READ_TIMER 200 /* usec */
+#include <lttng/lttng.h>
+
+#include "lttng-kernel.h"
/* Kernel event list */
struct ltt_kernel_event_list {
int fd;
char *pathname;
unsigned int stream_count;
- struct lttng_kernel_channel *channel;
+ struct lttng_channel *channel;
struct ltt_kernel_event_list events_list;
struct ltt_kernel_stream_list stream_list;
struct cds_list_head list;
struct ltt_kernel_metadata {
int fd;
char *pathname;
- struct lttng_kernel_channel *conf;
+ struct lttng_channel *conf;
};
/* Channel stream */
struct ltt_kernel_session {
int fd;
int metadata_stream_fd;
+ int kconsumer_fds_sent;
unsigned int channel_count;
unsigned int stream_count_global;
struct ltt_kernel_metadata *metadata;
* Create functions malloc() the data structure.
*/
struct ltt_kernel_session *trace_create_kernel_session(void);
-struct ltt_kernel_channel *trace_create_kernel_channel(void);
-struct ltt_kernel_event *trace_create_kernel_event(char *name,
- enum lttng_kernel_instrumentation type);
+struct ltt_kernel_channel *trace_create_kernel_channel(struct lttng_channel *chan);
+struct ltt_kernel_event *trace_create_kernel_event(struct lttng_event *ev);
struct ltt_kernel_metadata *trace_create_kernel_metadata(void);
struct ltt_kernel_stream *trace_create_kernel_stream(void);
* Fill the lttng_trace array of all the
* available trace of the session.
*/
+/*
void get_traces_per_session(struct ltt_session *session, struct lttng_trace *traces)
{
int i = 0;
DBG("Getting userspace traces for session %s", session->name);
- /* Getting userspace traces */
cds_list_for_each_entry(ust_iter, &session->ust_traces, list) {
trace.type = USERSPACE;
trace.pid = ust_iter->pid;
DBG("Getting kernel traces for session %s", session->name);
- /* Getting kernel traces */
if (session->kern_session_count > 0) {
trace.type = KERNEL;
strncpy(trace.name, "kernel", 6);
memcpy(&traces[i], &trace, sizeof(trace));
}
}
+*/
/*
* ust_create_trace
#include "trace.h"
int get_trace_count_per_session(struct ltt_session *session);
-void get_traces_per_session(struct ltt_session *session, struct lttng_trace *traces);
+//void get_traces_per_session(struct ltt_session *session, struct lttng_trace *traces);
int ust_create_trace(struct command_ctx *cmd_ctx);
int ust_start_trace(struct command_ctx *cmd_ctx);
int ust_stop_trace(struct command_ctx *cmd_ctx);
AM_CPPFLAGS = -I$(top_srcdir)/include
-#AM_CFLAGS = $(LTTNG_LIBS) -lpopt
bin_PROGRAMS = lttng
-lttng_SOURCES = options.c lttng.c
+lttng_SOURCES = config.c commands/start.c commands/add_channel.c \
+ commands/list.c commands/create.c commands/destroy.c \
+ commands/stop.c commands/enable_events.c \
+ utils.c lttng.c
lttng_LDADD = \
$(top_builddir)/liblttngctl/liblttngctl.la
-# $(top_builddir)/liblttsessiondcomm/liblttsessiondcomm.la
--- /dev/null
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _LTTNG_CMD_H
+#define _LTTNG_CMD_H
+
+#include <lttng/lttng.h>
+#include "lttngerr.h"
+#include "lttng-share.h"
+#include "lttng-kernel.h"
+
+enum cmd_error_code {
+ CMD_SUCCESS,
+ CMD_ERROR,
+ CMD_UNDEFINED,
+ CMD_NOT_IMPLEMENTED,
+ CMD_FATAL,
+};
+
+struct cmd_struct {
+ const char *name;
+ int (*func)(int argc, const char **argv);
+};
+
+extern int cmd_list(int argc, const char **argv);
+extern int cmd_create(int argc, const char **argv);
+extern int cmd_destroy(int argc, const char **argv);
+extern int cmd_add_channel(int argc, const char **argv);
+extern int cmd_start(int argc, const char **argv);
+extern int cmd_stop(int argc, const char **argv);
+extern int cmd_enable_events(int argc, const char **argv);
+
+#endif /* _LTTNG_CMD_H */
--- /dev/null
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define _GNU_SOURCE
+#include <popt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "cmd.h"
+#include "config.h"
+#include "utils.h"
+
+static char *opt_channel_name;
+static char *opt_kernel;
+static char *opt_cmd_name;
+static int opt_pid_all;
+static int opt_userspace;
+static pid_t opt_pid;
+static struct lttng_channel chan;
+
+enum {
+ OPT_HELP = 1,
+ OPT_DISCARD,
+ OPT_OVERWRITE,
+ OPT_SUBBUF_SIZE,
+ OPT_NUM_SUBBUF,
+ OPT_SWITCH_TIMER,
+ OPT_READ_TIMER,
+ OPT_USERSPACE,
+};
+
+static struct poptOption long_options[] = {
+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
+ {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
+ {"userspace", 'u', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, 0, OPT_USERSPACE, 0, 0},
+ {"all", 0, POPT_ARG_VAL, &opt_pid_all, 1, 0, 0},
+ {"pid", 'p', POPT_ARG_INT, &opt_pid, 0, 0, 0},
+ {"discard", 0, POPT_ARG_NONE, 0, OPT_DISCARD, 0, 0},
+ {"overwrite", 0, POPT_ARG_NONE, 0, OPT_OVERWRITE, 0, 0},
+ {"subbuf_size", 0, POPT_ARG_DOUBLE, 0, OPT_SUBBUF_SIZE, 0, 0},
+ {"num_subbuf", 0, POPT_ARG_INT, 0, OPT_NUM_SUBBUF, 0, 0},
+ {"switch_timer", 0, POPT_ARG_INT, 0, OPT_SWITCH_TIMER, 0, 0},
+ {"read_timer", 0, POPT_ARG_INT, 0, OPT_READ_TIMER, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+/*
+ * usage
+ */
+static void usage(FILE *ofp)
+{
+ fprintf(ofp, "usage: lttng add-channel NAME [options] [channel_options]\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, " -h, --help Show this help\n");
+ fprintf(ofp, " -k, --kernel Apply on the kernel tracer\n");
+ fprintf(ofp, " -u, --userspace [CMD] Apply on the user-space tracer\n");
+ fprintf(ofp, " --all If -u, apply on all traceable apps\n");
+ fprintf(ofp, " -p, --pid PID If -u, apply on a specific PID\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, "Channel options:\n");
+ fprintf(ofp, " --discard Discard event when buffers are full (default)\n");
+ fprintf(ofp, " --overwrite Flight recorder mode\n");
+ fprintf(ofp, " --subbuf_size Subbuffer size in bytes (default: 4096)\n");
+ fprintf(ofp, " --num_subbuf Number of subbufers (default: 2)\n");
+ fprintf(ofp, " --switch_timer Switch timer interval in usec (default: 0)\n");
+ fprintf(ofp, " --read_timer Read timer interval in usec (default: 200)\n");
+ fprintf(ofp, "\n");
+}
+
+/*
+ * add_channel
+ *
+ * Adding channel using the lttng API.
+ */
+static int add_channel(void)
+{
+ int ret = CMD_SUCCESS;
+
+ if (set_session_name() < 0) {
+ ret = CMD_ERROR;
+ goto error;
+ }
+
+ /* Copy channel name and normalize it */
+ strncpy(chan.name, opt_channel_name, NAME_MAX);
+ chan.name[NAME_MAX - 1] = '\0';
+
+ /* Kernel tracer action */
+ if (opt_kernel) {
+ /* Create kernel channel */
+ ret = lttng_kernel_create_channel(&chan);
+ if (ret < 0) {
+ goto error;
+ }
+ } else if (opt_userspace) { /* User-space tracer action */
+ /*
+ * TODO: Waiting on lttng UST 2.0
+ */
+ if (opt_pid_all) {
+ } else if (opt_pid != 0) {
+ }
+ ret = CMD_NOT_IMPLEMENTED;
+ goto error;
+ } else {
+ ERR("Please specify a tracer (kernel or user-space)");
+ goto error;
+ }
+
+ MSG("Channel %s created", opt_channel_name);
+
+error:
+ return ret;
+}
+
+/*
+ * init_channel_config
+ *
+ * Default value for channel configuration.
+ */
+static void init_channel_config(void)
+{
+ chan.attr.overwrite = DEFAULT_CHANNEL_OVERWRITE;
+ chan.attr.subbuf_size = DEFAULT_CHANNEL_SUBBUF_SIZE;
+ chan.attr.num_subbuf = DEFAULT_CHANNEL_SUBBUF_NUM;
+ chan.attr.switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER;
+ chan.attr.read_timer_interval = DEFAULT_CHANNEL_READ_TIMER;
+}
+
+/*
+ * cmd_add_channel
+ *
+ * Add channel to trace session
+ */
+int cmd_add_channel(int argc, const char **argv)
+{
+ int opt, ret;
+ static poptContext pc;
+
+ init_channel_config();
+
+ pc = poptGetContext(NULL, argc, argv, long_options, 0);
+ poptReadDefaultConfig(pc, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ usage(stderr);
+ ret = CMD_SUCCESS;
+ goto end;
+ case OPT_USERSPACE:
+ opt_userspace = 1;
+ opt_cmd_name = poptGetOptArg(pc);
+ break;
+ case OPT_DISCARD:
+ chan.attr.overwrite = 0;
+ DBG("Channel set to discard");
+ break;
+ case OPT_OVERWRITE:
+ chan.attr.overwrite = 1;
+ DBG("Channel set to overwrite");
+ break;
+ case OPT_SUBBUF_SIZE:
+ chan.attr.subbuf_size = atol(poptGetOptArg(pc));
+ DBG("Channel subbuf size set to %lu", chan.attr.subbuf_size);
+ break;
+ case OPT_NUM_SUBBUF:
+ chan.attr.num_subbuf = atoi(poptGetOptArg(pc));
+ DBG("Channel subbuf num set to %lu", chan.attr.num_subbuf);
+ break;
+ case OPT_SWITCH_TIMER:
+ chan.attr.switch_timer_interval = atoi(poptGetOptArg(pc));
+ DBG("Channel switch timer interval set to %d", chan.attr.switch_timer_interval);
+ break;
+ case OPT_READ_TIMER:
+ chan.attr.read_timer_interval = atoi(poptGetOptArg(pc));
+ DBG("Channel read timer interval set to %d", chan.attr.read_timer_interval);
+ break;
+ default:
+ usage(stderr);
+ ret = CMD_UNDEFINED;
+ goto end;
+ }
+ }
+
+ opt_channel_name = (char*) poptGetArg(pc);
+ if (opt_channel_name == NULL) {
+ ERR("Missing channel name.\n");
+ usage(stderr);
+ ret = CMD_SUCCESS;
+ goto end;
+ }
+
+ ret = add_channel();
+
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define _GNU_SOURCE
+#include <popt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "cmd.h"
+#include "config.h"
+
+static char *opt_output_path;
+static char *opt_session_name;
+
+enum {
+ OPT_HELP = 1,
+};
+
+static struct poptOption long_options[] = {
+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
+ {"output", 'o', POPT_ARG_STRING, &opt_output_path, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+/*
+ * usage
+ */
+static void usage(FILE *ofp)
+{
+ fprintf(ofp, "usage: lttng create [options] [NAME]\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, " -h, --help Show this help\n");
+ fprintf(ofp, " -o, --output PATH Specify output path\n");
+ fprintf(ofp, "\n");
+}
+
+/*
+ * create_session
+ *
+ * Create a tracing session. If no name specified, a default name will be
+ * generated.
+ */
+static int create_session()
+{
+ int ret;
+ char name[NAME_MAX];
+ char *session_name, *path = NULL, *alloc_path;
+ time_t rawtime;
+ struct tm *timeinfo;
+
+ /* Auto session name creation */
+ if (opt_session_name == NULL) {
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+ strftime(name, sizeof(name), "auto-%Y%m%d-%H%M%S", timeinfo);
+ session_name = name;
+ DBG("Auto session name set to %s", session_name);
+ } else {
+ session_name = opt_session_name;
+ }
+
+ /* Auto output path */
+ if (opt_output_path == NULL) {
+ alloc_path = config_get_default_path();
+ if (alloc_path == NULL) {
+ ret = CMD_FATAL;
+ goto error;
+ }
+ } else {
+ alloc_path = opt_output_path;
+ }
+
+ path = config_generate_dir_path(alloc_path);
+ if (path == NULL) {
+ ret = CMD_FATAL;
+ goto error;
+ }
+
+ /* Init lttng session config */
+ ret = config_init(path);
+ if (ret < 0) {
+ goto error;
+ }
+
+ ret = config_add_session_name(path, session_name);
+ if (ret < 0) {
+ goto error;
+ }
+
+ ret = lttng_create_session(session_name, path);
+ if (ret < 0) {
+ goto error;
+ }
+
+ MSG("Session %s created.", session_name);
+ MSG("Working directory of created session is %s", path);
+
+ ret = CMD_SUCCESS;
+
+error:
+ if (alloc_path) {
+ free(alloc_path);
+ }
+
+ if (path) {
+ free(path);
+ }
+ return ret;
+}
+
+/*
+ * cmd_list
+ *
+ * The 'list <options>' first level command
+ */
+int cmd_create(int argc, const char **argv)
+{
+ int opt, ret = CMD_SUCCESS;
+ static poptContext pc;
+
+ pc = poptGetContext(NULL, argc, argv, long_options, 0);
+ poptReadDefaultConfig(pc, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ usage(stderr);
+ goto end;
+ default:
+ usage(stderr);
+ ret = CMD_UNDEFINED;
+ goto end;
+ }
+ }
+
+ opt_session_name = (char*) poptGetArg(pc);
+
+ ret = create_session();
+
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define _GNU_SOURCE
+#include <popt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "cmd.h"
+#include "config.h"
+#include "utils.h"
+
+static char *opt_session_name;
+
+enum {
+ OPT_HELP = 1,
+};
+
+static struct poptOption long_options[] = {
+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+/*
+ * usage
+ */
+static void usage(FILE *ofp)
+{
+ fprintf(ofp, "usage: lttng destroy [options] [NAME]\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, "Where NAME is an optional session name. If not specified, lttng will\n");
+ fprintf(ofp, "get it from the configuration directory (.lttng).\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, " -h, --help Show this help\n");
+ fprintf(ofp, "\n");
+}
+
+/*
+ * destroy_session
+ *
+ * Destroy a session removing the config directory and unregistering to the
+ * session daemon.
+ */
+static int destroy_session()
+{
+ int ret;
+ char *session_name, *path;
+
+ if (opt_session_name == NULL) {
+ session_name = get_session_name();
+ if (session_name == NULL) {
+ ret = CMD_ERROR;
+ goto error;
+ }
+ } else {
+ session_name = opt_session_name;
+ }
+
+ ret = lttng_destroy_session(session_name);
+ if (ret < 0) {
+ goto free_name;
+ }
+
+ path = get_config_file_path();
+ if (path == NULL) {
+ ret = CMD_FATAL;
+ goto free_name;
+ }
+
+ if (opt_session_name == NULL) {
+ config_destroy(path);
+ MSG("Session %s destroyed at %s", session_name, path);
+ } else {
+ MSG("Session %s destroyed", session_name);
+ }
+
+ free(path);
+ ret = CMD_SUCCESS;
+
+free_name:
+ free(session_name);
+error:
+ return ret;
+}
+
+/*
+ * cmd_destroy
+ *
+ * The 'destroy <options>' first level command
+ */
+int cmd_destroy(int argc, const char **argv)
+{
+ int opt, ret = CMD_SUCCESS;
+ static poptContext pc;
+
+ pc = poptGetContext(NULL, argc, argv, long_options, 0);
+ poptReadDefaultConfig(pc, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ usage(stderr);
+ goto end;
+ default:
+ usage(stderr);
+ ret = CMD_UNDEFINED;
+ goto end;
+ }
+ }
+
+ opt_session_name = (char*) poptGetArg(pc);
+
+ ret = destroy_session();
+
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define _GNU_SOURCE
+#include <popt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "cmd.h"
+#include "config.h"
+#include "utils.h"
+
+static char *opt_event_list;
+static int opt_event_type;
+static char *opt_kernel;
+static char *opt_cmd_name;
+static int opt_pid_all;
+static int opt_userspace;
+static int opt_enable_all;
+static pid_t opt_pid;
+static char *opt_kprobe_addr;
+static char *opt_function_symbol;
+static char *opt_channel_name;
+
+enum {
+ OPT_HELP = 1,
+ OPT_USERSPACE,
+ OPT_TRACEPOINT,
+ OPT_MARKER,
+ OPT_KPROBE,
+ OPT_FUNCTION,
+};
+
+static struct poptOption long_options[] = {
+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
+ {"all-events", 'a', POPT_ARG_VAL, &opt_enable_all, 1, 0, 0},
+ {"channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0},
+ {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
+ {"userspace", 'u', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, 0, OPT_USERSPACE, 0, 0},
+ {"all", 0, POPT_ARG_VAL, &opt_pid_all, 1, 0, 0},
+ {"pid", 'p', POPT_ARG_INT, &opt_pid, 0, 0, 0},
+ {"tracepoint", 0, POPT_ARG_NONE, 0, OPT_TRACEPOINT, 0, 0},
+ {"marker", 0, POPT_ARG_NONE, 0, OPT_MARKER, 0, 0},
+ {"kprobe", 0, POPT_ARG_STRING, 0, OPT_KPROBE, 0, 0},
+ {"function", 0, POPT_ARG_STRING, 0, OPT_FUNCTION, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+/*
+ * usage
+ */
+static void usage(FILE *ofp)
+{
+ fprintf(ofp, "usage: lttng enable-event NAME[,NAME2,...] [options] [event_options]\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, " -h, --help Show this help\n");
+ fprintf(ofp, " -c, --channel Apply on this channel\n");
+ fprintf(ofp, " -a, --all-events Enable all tracepoints\n");
+ fprintf(ofp, " -k, --kernel Apply for the kernel tracer\n");
+ fprintf(ofp, " -u, --userspace [CMD] Apply for the user-space tracer\n");
+ fprintf(ofp, " --all If -u, apply on all traceable apps\n");
+ fprintf(ofp, " -p, --pid PID If -u, apply on a specific PID\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, "Event options:\n");
+ fprintf(ofp, " --tracepoint Tracepoint event (default)\n");
+ fprintf(ofp, " --kprobe ADDR Kernel Kprobe\n");
+ fprintf(ofp, " --function SYMBOL Function tracer event\n");
+ fprintf(ofp, " --marker User-space marker (deprecated)\n");
+ fprintf(ofp, "\n");
+}
+
+/*
+ * enable_events
+ *
+ * Enabling event using the lttng API.
+ */
+static int enable_events(void)
+{
+ int err, ret = CMD_SUCCESS;
+ char *event_name, *channel_name;
+ struct lttng_event ev;
+
+ if (set_session_name() < 0) {
+ ret = CMD_ERROR;
+ goto error;
+ }
+
+ if (opt_channel_name == NULL) {
+ err = asprintf(&channel_name, DEFAULT_CHANNEL_NAME);
+ if (err < 0) {
+ ret = CMD_FATAL;
+ goto error;
+ }
+ } else {
+ channel_name = opt_channel_name;
+ }
+
+ if (opt_enable_all) {
+ if (opt_kernel) {
+ ret = lttng_kernel_enable_event(NULL, channel_name);
+ goto error;
+ }
+
+ /* TODO: User-space tracer */
+ }
+
+ /* Strip event list */
+ event_name = strtok(opt_event_list, ",");
+ while (event_name != NULL) {
+ /* Kernel tracer action */
+ if (opt_kernel) {
+ DBG("Enabling kernel event %s for channel %s",
+ event_name, channel_name);
+ /* Copy name and type of the event */
+ strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN);
+ ev.type = opt_event_type;
+
+ switch (opt_event_type) {
+ case LTTNG_EVENT_TRACEPOINTS:
+ ret = lttng_kernel_enable_event(&ev, channel_name);
+ break;
+ case LTTNG_EVENT_KPROBES:
+ /* FIXME: check addr format */
+ ev.attr.kprobe.addr = atoll(opt_kprobe_addr);
+ ret = lttng_kernel_enable_event(&ev, channel_name);
+ break;
+ case LTTNG_EVENT_FUNCTION:
+ strncpy(ev.attr.ftrace.symbol_name, opt_function_symbol, LTTNG_SYMBOL_NAME_LEN);
+ ret = lttng_kernel_enable_event(&ev, channel_name);
+ break;
+ default:
+ ret = CMD_NOT_IMPLEMENTED;
+ goto error;
+ }
+
+ if (ret > 0) {
+ MSG("Kernel event %s created in channel %s", event_name, channel_name);
+ }
+ } else if (opt_userspace) { /* User-space tracer action */
+ /*
+ * TODO: Waiting on lttng UST 2.0
+ */
+ if (opt_pid_all) {
+ } else if (opt_pid != 0) {
+ }
+ ret = CMD_NOT_IMPLEMENTED;
+ goto error;
+ } else {
+ ERR("Please specify a tracer (kernel or user-space)");
+ goto error;
+ }
+
+ /* Next event */
+ event_name = strtok(NULL, ",");
+ }
+
+error:
+ return ret;
+}
+
+/*
+ * cmd_enable_events
+ *
+ * Add event to trace session
+ */
+int cmd_enable_events(int argc, const char **argv)
+{
+ int opt, ret;
+ static poptContext pc;
+
+ pc = poptGetContext(NULL, argc, argv, long_options, 0);
+ poptReadDefaultConfig(pc, 0);
+
+ /* Default event type */
+ opt_event_type = LTTNG_KERNEL_TRACEPOINTS;
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ usage(stderr);
+ ret = CMD_SUCCESS;
+ goto end;
+ case OPT_USERSPACE:
+ opt_userspace = 1;
+ opt_cmd_name = poptGetOptArg(pc);
+ break;
+ case OPT_TRACEPOINT:
+ opt_event_type = LTTNG_EVENT_TRACEPOINTS;
+ break;
+ case OPT_MARKER:
+ ret = CMD_NOT_IMPLEMENTED;
+ goto end;
+ case OPT_KPROBE:
+ opt_event_type = LTTNG_EVENT_KPROBES;
+ opt_kprobe_addr = poptGetOptArg(pc);
+ break;
+ case OPT_FUNCTION:
+ opt_event_type = LTTNG_EVENT_FUNCTION;
+ opt_function_symbol = poptGetOptArg(pc);
+ break;
+ default:
+ usage(stderr);
+ ret = CMD_UNDEFINED;
+ goto end;
+ }
+ }
+
+ opt_event_list = (char*) poptGetArg(pc);
+ if (opt_event_list == NULL && opt_enable_all == 0) {
+ ERR("Missing event name(s).\n");
+ usage(stderr);
+ ret = CMD_SUCCESS;
+ goto end;
+ }
+
+ ret = enable_events();
+
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define _GNU_SOURCE
+#include <popt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cmd.h"
+
+static int opt_pid;
+static int opt_channels;
+
+enum {
+ OPT_HELP = 1,
+ OPT_EVENTS,
+ OPT_KERNEL,
+ OPT_APPS,
+ OPT_SESSIONS,
+ OPT_CHANNEL,
+};
+
+static struct poptOption long_options[] = {
+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
+ {"events", 'e', POPT_ARG_NONE, 0, OPT_EVENTS, 0, 0},
+ {"kernel", 'k', POPT_ARG_NONE, 0, OPT_KERNEL, 0, 0},
+ {"pid", 'p', POPT_ARG_INT, &opt_pid, 0, 0, 0},
+ {"apps", 'a', POPT_ARG_NONE, 0, OPT_APPS, 0, 0},
+ {"session", 's', POPT_ARG_NONE, 0, OPT_SESSIONS, 0, 0},
+ {"channel", 'c', POPT_ARG_VAL, &opt_channels, 1, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+/*
+ * usage
+ */
+static void usage(FILE *ofp)
+{
+ fprintf(ofp, "usage: lttng list [options] [<executable>]\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, " -h, --help Show this help\n");
+ fprintf(ofp, " -e, --events List all available instrumentation\n");
+ fprintf(ofp, " -k, --kernel List kernel instrumentation\n");
+ fprintf(ofp, " -p, --pid PID List user-space instrumentation by PID\n");
+ fprintf(ofp, " -a, --apps List traceable user-space applications/pids\n");
+ fprintf(ofp, " -s, --sessions List tracing session\n");
+ fprintf(ofp, "\n");
+}
+
+/*
+ * get_cmdline_by_pid
+ *
+ * Get command line from /proc for a specific pid.
+ *
+ * On success, return an allocated string pointer pointing to the proc
+ * cmdline.
+ * On error, return NULL.
+ */
+static char *get_cmdline_by_pid(pid_t pid)
+{
+ int ret;
+ FILE *fp;
+ char *cmdline = NULL;
+ char path[24]; /* Can't go bigger than /proc/65535/cmdline */
+
+ snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
+ fp = fopen(path, "r");
+ if (fp == NULL) {
+ goto end;
+ }
+
+ /* Caller must free() *cmdline */
+ cmdline = malloc(PATH_MAX);
+ ret = fread(cmdline, 1, PATH_MAX, fp);
+ fclose(fp);
+
+end:
+ return cmdline;
+}
+
+/*
+ * list_kernel
+ *
+ * Ask for all trace events in the kernel and pretty print them.
+ */
+static int list_kernel(void)
+{
+ int ret, pos, size;
+ char *event_list, *event, *ptr;
+
+ DBG("Getting all tracing events");
+
+ ret = lttng_kernel_list_events(&event_list);
+ if (ret < 0) {
+ ERR("Unable to list kernel instrumentation");
+ return ret;
+ }
+
+ MSG("Kernel tracepoints:\n-------------");
+
+ ptr = event_list;
+ while ((size = sscanf(ptr, "event { name = %m[^;]; };%n\n", &event, &pos)) == 1) {
+ MSG(" - %s", event);
+ /* Move pointer to the next line */
+ ptr += pos + 1;
+ free(event);
+ }
+
+ free(event_list);
+
+ return CMD_SUCCESS;
+}
+
+/*
+ * list_sessions
+ *
+ * Get the list of available sessions from the session daemon and print it to
+ * user.
+ */
+static int list_sessions(void)
+{
+ int ret, count, i;
+ struct lttng_session *sessions;
+
+ count = lttng_list_sessions(&sessions);
+ DBG("Session count %d", count);
+ if (count < 0) {
+ ret = count;
+ goto error;
+ }
+
+ MSG("Available sessions:");
+ for (i = 0; i < count; i++) {
+ MSG(" %d) %s (%s)", i+1, sessions[i].name, sessions[i].path);
+ }
+
+ free(sessions);
+
+ return CMD_SUCCESS;
+
+error:
+ return ret;
+}
+
+/*
+ * list_apps
+ *
+ * Get the UST traceable pid list and print them to the user.
+ */
+static int list_apps(void)
+{
+ int i, ret, count;
+ pid_t *pids;
+ char *cmdline;
+
+ count = 0;
+ //count = lttng_ust_list_traceable_apps(&pids);
+ if (count < 0) {
+ ret = count;
+ goto error;
+ }
+
+ MSG("LTTng UST traceable application [name (pid)]:");
+ for (i=0; i < count; i++) {
+ cmdline = get_cmdline_by_pid(pids[i]);
+ if (cmdline == NULL) {
+ MSG("\t(not running) (%d)", pids[i]);
+ continue;
+ }
+ MSG("\t%s (%d)", cmdline, pids[i]);
+ free(cmdline);
+ }
+
+ /* Allocated by lttng_ust_list_apps() */
+ free(pids);
+
+ return CMD_SUCCESS;
+
+error:
+ return ret;
+}
+
+/*
+ * list_pid
+ *
+ * List all instrumentation for a specific pid
+ */
+/*
+static int list_pid(int pid)
+{
+ int ret;
+
+ return CMD_SUCCESS;
+
+error:
+ return ret;
+}
+*/
+
+/*
+ * list_executable
+ *
+ * List all instrumentation for an executable on the system
+ */
+/*
+static int list_executable(char *name)
+{
+}
+*/
+
+/*
+ * cmd_list
+ *
+ * The 'list <options>' first level command
+ */
+int cmd_list(int argc, const char **argv)
+{
+ int opt, ret = CMD_SUCCESS;
+ const char *command_name;
+ static poptContext pc;
+
+ if (argc < 2) {
+ usage(stderr);
+ goto end;
+ }
+
+ pc = poptGetContext(NULL, argc, argv, long_options, 0);
+ poptReadDefaultConfig(pc, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ usage(stderr);
+ goto end;
+ case OPT_EVENTS:
+ ret = CMD_NOT_IMPLEMENTED;
+ goto end;
+ case OPT_APPS:
+ ret = list_apps();
+ break;
+ case OPT_KERNEL:
+ ret = list_kernel();
+ break;
+ case OPT_SESSIONS:
+ ret = list_sessions();
+ break;
+ default:
+ usage(stderr);
+ ret = CMD_UNDEFINED;
+ goto end;
+ }
+ }
+
+ if (opt_pid != 0) {
+ //ret = list_pid(pid);
+ ret = CMD_NOT_IMPLEMENTED;
+ }
+
+ command_name = poptGetArg(pc);
+ if (command_name != NULL) {
+ // ret = list_executable(command_name);
+ ret = CMD_NOT_IMPLEMENTED;
+ }
+
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define _GNU_SOURCE
+#include <popt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "cmd.h"
+#include "config.h"
+#include "utils.h"
+
+static char *opt_session_name;
+
+enum {
+ OPT_HELP = 1,
+};
+
+static struct poptOption long_options[] = {
+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+/*
+ * usage
+ */
+static void usage(FILE *ofp)
+{
+ fprintf(ofp, "usage: lttng start [options] [NAME]\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, "Where NAME is an optional session name. If not specified, lttng will\n");
+ fprintf(ofp, "get it from the configuration directory (.lttng).\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, " -h, --help Show this help\n");
+ fprintf(ofp, "\n");
+}
+
+/*
+ * start_tracing
+ *
+ * Start tracing for all trace of the session.
+ */
+static int start_tracing(void)
+{
+ int ret = CMD_SUCCESS;
+ char *session_name;
+
+ if (opt_session_name == NULL) {
+ session_name = get_session_name();
+ if (session_name == NULL) {
+ ret = CMD_ERROR;
+ goto error;
+ }
+ } else {
+ session_name = opt_session_name;
+ }
+
+ DBG("Starting tracing for session %s", session_name);
+
+ ret = lttng_start_tracing(session_name);
+ if (ret < 0) {
+ goto free_name;
+ }
+
+ MSG("Tracing started for session %s", session_name);
+
+free_name:
+ free(session_name);
+error:
+ return ret;
+}
+
+/*
+ * cmd_start
+ *
+ * The 'start <options>' first level command
+ */
+int cmd_start(int argc, const char **argv)
+{
+ int opt, ret;
+ static poptContext pc;
+
+ pc = poptGetContext(NULL, argc, argv, long_options, 0);
+ poptReadDefaultConfig(pc, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ usage(stderr);
+ ret = CMD_SUCCESS;
+ goto end;
+ default:
+ usage(stderr);
+ ret = CMD_UNDEFINED;
+ goto end;
+ }
+ }
+
+ opt_session_name = (char*) poptGetArg(pc);
+
+ ret = start_tracing();
+
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define _GNU_SOURCE
+#include <popt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "cmd.h"
+#include "config.h"
+#include "utils.h"
+
+static char *opt_session_name;
+
+enum {
+ OPT_HELP = 1,
+};
+
+static struct poptOption long_options[] = {
+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
+ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+/*
+ * usage
+ */
+static void usage(FILE *ofp)
+{
+ fprintf(ofp, "usage: lttng stop [options] [NAME]\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, "Where NAME is an optional session name. If not specified, lttng will\n");
+ fprintf(ofp, "get it from the configuration directory (.lttng).\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, " -h, --help Show this help\n");
+ fprintf(ofp, "\n");
+}
+
+/*
+ * stop_tracing
+ *
+ * Start tracing for all trace of the session.
+ */
+static int stop_tracing(void)
+{
+ int ret = CMD_SUCCESS;
+ char *session_name;
+
+ if (opt_session_name == NULL) {
+ session_name = get_session_name();
+ if (session_name == NULL) {
+ ret = CMD_ERROR;
+ goto error;
+ }
+ } else {
+ session_name = opt_session_name;
+ }
+
+ ret = lttng_stop_tracing(session_name);
+ if (ret < 0) {
+ goto free_name;
+ }
+
+ MSG("Tracing stopped for session %s", session_name);
+
+free_name:
+ free(session_name);
+error:
+ return ret;
+}
+
+/*
+ * cmd_stop
+ *
+ * The 'stop <options>' first level command
+ */
+int cmd_stop(int argc, const char **argv)
+{
+ int opt, ret;
+ static poptContext pc;
+
+ pc = poptGetContext(NULL, argc, argv, long_options, 0);
+ poptReadDefaultConfig(pc, 0);
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ switch (opt) {
+ case OPT_HELP:
+ usage(stderr);
+ ret = CMD_SUCCESS;
+ goto end;
+ default:
+ usage(stderr);
+ ret = CMD_UNDEFINED;
+ goto end;
+ }
+ }
+
+ opt_session_name = (char*) poptGetArg(pc);
+
+ ret = stop_tracing();
+
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (c) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "lttngerr.h"
+
+/*
+ * get_config_file_path
+ *
+ * Return the path with '/CONFIG_FILENAME' added to it.
+ */
+static char *get_config_file_path(char *path)
+{
+ int ret;
+ char *file_path;
+
+ ret = asprintf(&file_path, "%s/%s", path, CONFIG_FILENAME);
+ if (ret < 0) {
+ ERR("Fail allocating config file path");
+ }
+
+ return file_path;
+}
+
+/*
+ * open_config
+ *
+ * Return an open FILE pointer to the config file.
+ */
+static FILE *open_config(char *path, const char *mode)
+{
+ FILE *fp = NULL;
+ char *file_path;
+
+ file_path = get_config_file_path(path);
+ if (file_path == NULL) {
+ goto error;
+ }
+
+ fp = fopen(file_path, mode);
+ if (fp == NULL) {
+ perror("config file");
+ goto error;
+ }
+
+error:
+ if (file_path) {
+ free(file_path);
+ }
+ return fp;
+}
+
+/*
+ * create_config_file
+ *
+ * Create the empty config file a the path.
+ */
+static int create_config_file(char *path)
+{
+ int ret;
+ FILE *fp;
+
+ fp = open_config(path, "w+");
+ if (fp == NULL) {
+ ERR("Unable to create config file");
+ ret = -1;
+ goto error;
+ }
+
+ ret = fclose(fp);
+
+error:
+ return ret;
+}
+
+/*
+ * create_config_dir
+ *
+ * Create the empty config dir.
+ */
+static int create_config_dir(char *path)
+{
+ int ret;
+
+ /* Create session directory .lttng */
+ ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP);
+ if (ret < 0) {
+ if (errno == EEXIST) {
+ ERR("Session already exist at %s", path);
+ } else {
+ perror("mkdir config");
+ ERR("Couldn't init config directory at %s", path);
+ }
+ ret = -errno;
+ goto error;
+ }
+
+error:
+ return ret;
+}
+
+/*
+ * write_config
+ *
+ * Append data to the config file in file_path
+ */
+static void write_config(char *file_path, size_t size, char *data)
+{
+ FILE *fp;
+
+ fp = open_config(file_path, "a");
+ if (fp == NULL) {
+ goto error;
+ }
+
+ /* Write session name into config file */
+ fwrite(data, size, 1, fp);
+ fclose(fp);
+
+error:
+ return;
+}
+
+/*
+ * config_get_default_path
+ *
+ * Return the default path to config directory which is the current working
+ * directory. User must free() the returned allocated string.
+ */
+char *config_get_default_path(void)
+{
+ char *alloc_path;
+
+ alloc_path = getcwd(NULL, 0);
+ if (alloc_path == NULL) {
+ perror("getcwd");
+ }
+
+ return alloc_path;
+}
+
+/*
+ * config_destroy
+ *
+ * Destroy directory config and file config.
+ */
+void config_destroy(char *path)
+{
+ int ret;
+ char *config_path;
+
+ config_path = get_config_file_path(path);
+
+ ret = remove(config_path);
+ if (ret < 0) {
+ perror("remove config file");
+ }
+
+ ret = rmdir(path);
+ if (ret < 0) {
+ perror("rmdir config dir");
+ }
+
+ free(config_path);
+}
+
+/*
+ * config_read_session_name
+ *
+ * Return sesson name from the config file.
+ */
+char *config_read_session_name(char *path)
+{
+ int ret;
+ FILE *fp;
+ char var[NAME_MAX], *session_name;
+
+ fp = open_config(path, "r");
+ if (fp == NULL) {
+ ERR("Can't find valid lttng config in %s", path);
+ goto error;
+ }
+
+ session_name = malloc(NAME_MAX);
+ while (!feof(fp)) {
+ if ((ret = fscanf(fp, "%[^'=']=%s\n", var, session_name)) != 2) {
+ if (ret == -1) {
+ ERR("Missing session=NAME in config file.");
+ goto error;
+ }
+ continue;
+ }
+
+ if (strcmp(var, "session") == 0) {
+ goto found;
+ }
+ }
+
+ fclose(fp);
+
+error:
+ return NULL;
+
+found:
+ fclose(fp);
+ return session_name;
+
+}
+
+/*
+ * config_add_session_name
+ *
+ * Write session name option to the config file.
+ */
+int config_add_session_name(char *path, char *name)
+{
+ int ret;
+ char session_name[NAME_MAX];
+
+ ret = snprintf(session_name, NAME_MAX, "session=%s\n", name);
+ if (ret < 0) {
+ goto error;
+ }
+
+ write_config(path, ret, session_name);
+ ret = 0;
+
+error:
+ return ret;
+}
+
+/*
+ * config_generate_dir_path
+ *
+ * Return allocated path string to path/CONFIG_DIRNAME.
+ */
+char *config_generate_dir_path(char *path)
+{
+ int ret;
+ char *new_path;
+
+ ret = asprintf(&new_path, "%s/%s", path, CONFIG_DIRNAME);
+ if (ret < 0) {
+ perror("config path problem");
+ goto error;
+ }
+
+error:
+ return new_path;
+}
+
+/*
+ * config_init
+ *
+ * Init configuration directory and file.
+ */
+int config_init(char *path)
+{
+ int ret;
+
+ /* Create config directory (.lttng) */
+ ret = create_config_dir(path);
+ if (ret < 0) {
+ goto error;
+ }
+
+ /* Create default config file */
+ ret = create_config_file(path);
+ if (ret < 0) {
+ goto error;
+ }
+
+ DBG("Init config session in %s", path);
+
+error:
+ return ret;
+}
*/
#define _GNU_SOURCE
-#include <errno.h>
-#include <fcntl.h>
#include <getopt.h>
-#include <grp.h>
-#include <limits.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
#include <unistd.h>
#include <lttng/lttng.h>
+#include "cmd.h"
+#include "config.h"
#include "lttngerr.h"
-#include "options.h"
/* Variables */
static char *progname;
-static char *session_name;
-static uuid_t current_uuid;
-static int auto_session;
-static int auto_trace;
-
-/* Prototypes */
-static int process_client_opt(void);
-static int process_opt_list_apps(void);
-static int process_opt_list_sessions(void);
-static int process_opt_list_traces(void);
-static int process_opt_kernel_list_events(void);
-static int process_opt_create_session(void);
-static int process_kernel_create_trace(void);
-static int process_opt_kernel_event(void);
-static int process_kernel_start_trace(void);
-static int set_session_uuid(void);
-static void sighandler(int sig);
-static int set_signal_handler(void);
-static int validate_options(void);
-static char *get_cmdline_by_pid(pid_t pid);
-static void set_opt_session_info(void);
-/*
- * start_client
- *
- * Process client request from the command line
- * options. Every tracing action is done by the
- * liblttngctl API.
- */
-static int process_client_opt(void)
-{
- int ret;
-
- set_opt_session_info();
-
- if (opt_list_apps) {
- ret = process_opt_list_apps();
- if (ret < 0) {
- goto end;
- }
- goto error;
- }
-
- if (opt_list_session) {
- ret = process_opt_list_sessions();
- if (ret < 0) {
- goto end;
- }
- goto error;
- }
-
- if (opt_list_events) {
- if (opt_trace_kernel) {
- ret = process_opt_kernel_list_events();
- if (ret < 0) {
- goto end;
- }
- } else if (opt_trace_pid != 0) {
- // TODO
- }
- goto error;
- }
-
- /* Session creation or auto session set on */
- if (auto_session || opt_create_session) {
- DBG("Creating a new session");
- ret = process_opt_create_session();
- if (ret < 0) {
- goto end;
- }
- }
-
- ret = set_session_uuid();
- if (ret < 0) {
- ERR("Session %s not found", opt_session_name);
- goto error;
- }
-
- if (opt_destroy_session) {
- ret = lttng_destroy_session(¤t_uuid);
- if (ret < 0) {
- goto end;
- }
- MSG("Session %s destroyed.", opt_session_name);
- }
-
- if (opt_list_traces) {
- ret = process_opt_list_traces();
- if (ret < 0) {
- goto end;
- }
- }
-
- /*
- * Action on traces (kernel or/and userspace).
- */
-
- if (opt_trace_kernel) {
- if (auto_trace || opt_create_trace) {
- DBG("Creating a kernel trace");
- ret = process_kernel_create_trace();
- if (ret < 0) {
- goto end;
- }
- }
-
- if (opt_event_list != NULL || opt_enable_all_event) {
- ret = process_opt_kernel_event();
- if (ret < 0) {
- goto end;
- }
- }
-
- if (auto_trace || opt_start_trace) {
- DBG("Starting kernel tracing");
- ret = process_kernel_start_trace();
- if (ret < 0) {
- goto end;
- }
- }
-
- if (opt_stop_trace) {
- DBG("Stopping kernel tracing");
- ret = lttng_kernel_stop_tracing();
- if (ret < 0) {
- goto end;
- }
- }
- }
-
- if (opt_trace_pid != 0) {
- if (auto_trace || opt_create_trace) {
- DBG("Create a userspace trace for pid %d", opt_trace_pid);
- ret = lttng_ust_create_trace(opt_trace_pid);
- if (ret < 0) {
- goto end;
- }
- MSG("Trace created successfully!");
- }
-
- if (auto_trace || opt_start_trace) {
- DBG("Start trace for pid %d", opt_trace_pid);
- ret = lttng_ust_start_trace(opt_trace_pid);
- if (ret < 0) {
- goto end;
- }
- MSG("Trace started successfully!");
- } else if (opt_stop_trace) {
- DBG("Stop trace for pid %d", opt_trace_pid);
- ret = lttng_ust_stop_trace(opt_trace_pid);
- if (ret < 0) {
- goto end;
- }
- MSG("Trace stopped successfully!");
- }
-
- }
-
- return 0;
-
-end:
- ERR("%s", lttng_get_readable_code(ret));
-error: /* fall through */
- return ret;
-}
-
-/*
- * process_kernel_start_trace
- *
- * Start a kernel trace.
- */
-static int process_kernel_start_trace(void)
+int opt_quiet;
+int opt_verbose;
+static int opt_no_sessiond;
+static char *opt_sessiond_path;
+
+enum {
+ OPT_NO_SESSIOND,
+ OPT_SESSION_PATH,
+};
+
+/* Getopt options. No first level command. */
+static struct option long_options[] = {
+ {"help", 0, NULL, 'h'},
+ {"group", 1, NULL, 'g'},
+ {"verbose", 0, NULL, 'v'},
+ {"quiet", 0, NULL, 'q'},
+ {"no-sessiond", 0, NULL, OPT_NO_SESSIOND},
+ {"sessiond-path", 1, NULL, OPT_SESSION_PATH},
+ {NULL, 0, NULL, 0}
+};
+
+/* First level command */
+static struct cmd_struct commands[] = {
+ { "list", cmd_list},
+ { "create", cmd_create},
+ { "destroy", cmd_destroy},
+ { "add-channel", cmd_add_channel},
+ { "start", cmd_start},
+ { "stop", cmd_stop},
+ { "enable-event", cmd_enable_events},
+ { NULL, NULL} /* Array closure */
+};
+
+static void usage(FILE *ofp)
{
- int ret;
-
- ret = lttng_kernel_create_stream();
- if (ret < 0) {
- goto error;
- }
-
- ret = lttng_kernel_start_tracing();
- if (ret < 0) {
- goto error;
- }
-
- MSG("Kernel tracing started");
-
- return 0;
-
-error:
- return ret;
+ fprintf(ofp, "LTTng Trace Control " VERSION"\n\n");
+ fprintf(ofp, "usage: lttng [options] <command>\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, "Options:\n");
+ fprintf(ofp, " -h, --help Show this help\n");
+ fprintf(ofp, " -g, --group NAME Unix tracing group name. (default: tracing)\n");
+ fprintf(ofp, " -v, --verbose Verbose mode\n");
+ fprintf(ofp, " -q, --quiet Quiet mode\n");
+ fprintf(ofp, " --no-sessiond Don't spawn a session daemon\n");
+ fprintf(ofp, " --sessiond-path Session daemon full path\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, "Commands:\n");
+ fprintf(ofp, " add-channel Add channel to tracer\n");
+ fprintf(ofp, " create Create tracing session\n");
+ fprintf(ofp, " destroy Teardown tracing session\n");
+ fprintf(ofp, " enable-event Enable tracing event\n");
+ fprintf(ofp, " disable-event Disable tracing event\n");
+ fprintf(ofp, " list List possible tracing options\n");
+ fprintf(ofp, " start Start tracing\n");
+ fprintf(ofp, " stop Stop tracing\n");
+ fprintf(ofp, " version Show version information\n");
+ fprintf(ofp, "\n");
+ fprintf(ofp, "Please see the lttng(1) man page for full documentation.\n");
+ fprintf(ofp, "See http://lttng.org for updates, bug reports and news.\n");
}
/*
- * process_kernel_create_trace
- *
- * Create a kernel trace.
+ * clean_exit
*/
-static int process_kernel_create_trace(void)
+static void clean_exit(int code)
{
- int ret;
-
- /* Setup kernel session */
- ret = lttng_kernel_create_session();
- if (ret < 0) {
- goto error;
- }
-
- /* Create an empty channel (with no event) */
- ret = lttng_kernel_create_channel();
- if (ret < 0) {
- goto error;
- }
-
- /* Opening metadata for session */
- ret = lttng_kernel_open_metadata();
- if (ret < 0) {
- goto error;
- }
-
- return 0;
-
-error:
- return ret;
+ DBG("Clean exit");
+ exit(code);
}
/*
- * process_opt_kernel_list_events
+ * sighandler
*
- * Ask for all trace events in the kernel and pretty print them.
+ * Signal handler for the daemon
*/
-static int process_opt_kernel_list_events(void)
+static void sighandler(int sig)
{
- int ret, pos, size;
- char *event_list, *event, *ptr;
-
- DBG("Getting all tracing events");
-
- ret = lttng_kernel_list_events(&event_list);
- if (ret < 0) {
- ERR("Unable to list events.");
- return ret;
- }
-
- MSG("Kernel tracepoints:\n-------------");
-
- ptr = event_list;
- while ((size = sscanf(ptr, "event { name = %m[^;]; };%n\n", &event, &pos)) == 1) {
- MSG(" - %s", event);
- /* Move pointer to the next line */
- ptr += pos + 1;
- free(event);
+ switch (sig) {
+ case SIGTERM:
+ DBG("SIGTERM catched");
+ clean_exit(EXIT_FAILURE);
+ break;
+ case SIGCHLD:
+ /* Notify is done */
+ DBG("SIGCHLD catched");
+ break;
+ default:
+ DBG("Unknown signal %d catched", sig);
+ break;
}
- free(event_list);
-
- return 0;
+ return;
}
/*
- * process_opt_kernel_event
+ * set_signal_handler
*
- * Enable kernel event from the command line list given.
+ * Setup signal handler for SIGCHLD and SIGTERM.
*/
-static int process_opt_kernel_event(void)
+static int set_signal_handler(void)
{
- int ret;
- char *event_name;
-
- if (opt_enable_all_event) {
- ret = lttng_kernel_enable_event(NULL);
- if (ret < 0) {
- ERR("%s", lttng_get_readable_code(ret));
- } else {
- MSG("All kernel event enabled");
- }
+ int ret = 0;
+ struct sigaction sa;
+ sigset_t sigset;
+ if ((ret = sigemptyset(&sigset)) < 0) {
+ perror("sigemptyset");
goto end;
}
- event_name = strtok(opt_event_list, ",");
- while (event_name != NULL) {
- DBG("Enabling kernel event %s", event_name);
- ret = lttng_kernel_enable_event(event_name);
- if (ret < 0) {
- ERR("%s %s", lttng_get_readable_code(ret), event_name);
- } else {
- MSG("Kernel event %s enabled.", event_name);
- }
- /* Next event */
- event_name = strtok(NULL, ",");
- }
-
-end:
- return 0;
-}
-
-/*
- * set_opt_session_info
- *
- * Setup session_name, current_uuid, short_str_uuid and
- * long_str_uuid using the command line options.
- */
-static void set_opt_session_info(void)
-{
- if (opt_session_name != NULL) {
- session_name = strndup(opt_session_name, NAME_MAX);
- DBG("Session name set to %s", session_name);
- }
-}
-
-/*
- * set_session_uuid
- *
- * Set current session uuid to the current flow of command(s) using the
- * session_name.
- */
-static int set_session_uuid(void)
-{
- int ret, count, i, found = 0;
- struct lttng_session *sessions;
-
- if (!uuid_is_null(current_uuid)) {
- lttng_set_current_session_uuid(¤t_uuid);
+ sa.sa_handler = sighandler;
+ sa.sa_mask = sigset;
+ sa.sa_flags = 0;
+ if ((ret = sigaction(SIGCHLD, &sa, NULL)) < 0) {
+ perror("sigaction");
goto end;
}
- count = lttng_list_sessions(&sessions);
- if (count < 0) {
- ret = count;
- goto error;
- }
-
- for (i = 0; i < count; i++) {
- if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
- lttng_set_current_session_uuid(&sessions[i].uuid);
- uuid_copy(current_uuid, sessions[i].uuid);
- found = 1;
- break;
- }
- }
-
- free(sessions);
-
- if (!found) {
- return -1;
+ if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) {
+ perror("sigaction");
+ goto end;
}
end:
- DBG("Session UUID set");
- return 0;
-
-error:
- return ret;
-}
-
-/*
- * process_opt_list_traces
- *
- * Get list of all traces for a specific session uuid.
- */
-static int process_opt_list_traces(void)
-{
- int ret, i;
- struct lttng_trace *traces;
-
- ret = lttng_list_traces(¤t_uuid, &traces);
- DBG("Number of traces to list %d", ret);
- if (ret < 0) {
- goto error;
- }
-
- /* No traces */
- if (ret == 0) {
- MSG("No traces found.");
- goto error;
- }
-
- MSG("Userspace traces:");
- for (i = 0; i < ret; i++) {
- if (traces[i].type == USERSPACE) {
- MSG("\t%d) %s (pid: %d): %s",
- i, traces[i].name, traces[i].pid,
- get_cmdline_by_pid(traces[i].pid));
- } else {
- break;
- }
- }
-
- MSG("Kernel traces:");
- for (;i < ret; i++) {
- if (traces[i].type == KERNEL) {
- MSG("\t%d) %s", i, traces[i].name);
- }
- }
-
- free(traces);
-
-error:
- return ret;
-}
-
-/*
- * process_opt_create_session
- *
- * Create a new session using the name pass
- * to the command line.
- */
-static int process_opt_create_session(void)
-{
- int ret;
- char name[NAME_MAX];
- time_t rawtime;
- struct tm *timeinfo;
-
- /* Auto session name creation */
- if (opt_session_name == NULL) {
- time(&rawtime);
- timeinfo = localtime(&rawtime);
- strftime(name, sizeof(name), "auto-%Y%m%d-%H%M%S", timeinfo);
- session_name = strndup(name, sizeof(name));
- DBG("Auto session name set to %s", session_name);
- }
-
- ret = lttng_create_session(session_name);
- if (ret < 0) {
- goto error;
- }
-
- MSG("Session created: %s", session_name);
-
-error:
- return ret;
-}
-
-/*
- * process_opt_list_sessions
- *
- * Get the list of available sessions from
- * the session daemon and print it to user.
- */
-static int process_opt_list_sessions(void)
-{
- int ret, count, i;
- struct lttng_session *sessions;
-
- count = lttng_list_sessions(&sessions);
- DBG("Session count %d", count);
- if (count < 0) {
- ret = count;
- goto error;
- }
-
- MSG("Available sessions (UUIDs):");
- for (i = 0; i < count; i++) {
- MSG(" %d) %s", i+1, sessions[i].name);
- }
-
- free(sessions);
- MSG("\nTo select a session, use -s, --session UUID.");
-
- return 0;
-
-error:
return ret;
}
/*
- * process_opt_list_apps
+ * handle_command
*
- * Get the UST traceable pid list and print
- * them to the user.
- */
-static int process_opt_list_apps(void)
-{
- int i, ret, count;
- pid_t *pids;
- char *cmdline;
-
- count = lttng_ust_list_apps(&pids);
- if (count < 0) {
- ret = count;
- goto error;
- }
-
- MSG("LTTng UST traceable application [name (pid)]:");
- for (i=0; i < count; i++) {
- cmdline = get_cmdline_by_pid(pids[i]);
- if (cmdline == NULL) {
- MSG("\t(not running) (%d)", pids[i]);
- continue;
- }
- MSG("\t%s (%d)", cmdline, pids[i]);
- free(cmdline);
- }
-
- /* Allocated by lttng_ust_list_apps() */
- free(pids);
-
- return 0;
-
-error:
- return ret;
-}
-
-/*
- * get_cmdline_by_pid
- *
- * Get command line from /proc for a specific pid.
+ * Handle the full argv list of a first level command. Will find the command
+ * in the global commands array and call the function callback associated.
*
- * On success, return an allocated string pointer pointing to
- * the proc cmdline.
- * On error, return NULL.
+ * If command not found, return -1
+ * else, return function command error code.
*/
-static char *get_cmdline_by_pid(pid_t pid)
+static int handle_command(int argc, char **argv)
{
- int ret;
- FILE *fp;
- char *cmdline = NULL;
- char path[24]; /* Can't go bigger than /proc/65535/cmdline */
+ int i = 0, ret;
+ struct cmd_struct *cmd;
- snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
- fp = fopen(path, "r");
- if (fp == NULL) {
+ if (*argv == NULL) {
+ ret = CMD_SUCCESS;
goto end;
}
- /* Caller must free() *cmdline */
- cmdline = malloc(PATH_MAX);
- ret = fread(cmdline, 1, PATH_MAX, fp);
- fclose(fp);
-
-end:
- return cmdline;
-}
-
-/*
- * validate_options
- *
- * Make sure that all options passed to the command line are compatible with
- * each others.
- *
- * On error, return -1
- * On success, return 0
- */
-static int validate_options(void)
-{
- /* If listing options, jump validation */
- if (opt_list_apps || opt_list_session) {
- goto end;
- }
- /* Conflicting command */
- if (opt_start_trace && opt_stop_trace) {
- ERR("Can't use --start and --stop together.");
- goto error;
- /* If no PID specified and trace_kernel is off */
- } else if ((opt_trace_pid == 0 && !opt_trace_kernel) &&
- (opt_create_trace || opt_start_trace || opt_stop_trace || opt_destroy_trace)) {
- ERR("Please specify for which tracer (-k or -p PID).");
- goto error;
- /* List traces, we need a session name */
- } else if (opt_list_traces && opt_session_name == NULL) {
- ERR("Can't use -t without -s, --session option.");
- goto error;
- /* Can't set event for both kernel and userspace at the same time */
- } else if (opt_event_list != NULL && (opt_trace_kernel && opt_trace_pid)) {
- ERR("Please don't use --event for both kernel and userspace.\nOne at a time to enable events.");
- goto error;
- /* Don't need a trace name for kernel tracig */
- } else if (opt_trace_name != NULL && opt_trace_kernel) {
- ERR("For action on a kernel trace, please don't specify a trace name.");
- goto error;
- } else if (opt_destroy_trace && opt_session_name == NULL) {
- ERR("Please specify a session in order to destroy a trace");
- goto error;
- } else if (opt_create_trace || opt_destroy_trace) {
- /* Both kernel and user-space are denied for these options */
- if (opt_trace_pid != 0 && opt_trace_kernel) {
- ERR("Kernel and user-space trace creation and destruction can't be used together.");
- goto error;
- /* Need a trace name for user-space tracing */
- } else if (opt_trace_name == NULL && opt_trace_pid != 0) {
- ERR("Please specify a trace name for user-space tracing");
- goto error;
+ cmd = &commands[i];
+ while (cmd->func != NULL) {
+ /* Find command */
+ if (strcmp(argv[0], cmd->name) == 0) {
+ ret = cmd->func(argc, (const char**) argv);
+ switch (ret) {
+ case CMD_ERROR:
+ ERR("Command error");
+ break;
+ case CMD_NOT_IMPLEMENTED:
+ ERR("Options not implemented");
+ break;
+ case CMD_UNDEFINED:
+ ERR("Undefined command");
+ break;
+ case CMD_FATAL:
+ ERR("Fatal error");
+ break;
+ }
+ goto end;
}
- } else if (opt_stop_trace && opt_trace_pid != 0 && opt_trace_name == NULL) {
- ERR("Please specify a trace name for user-space tracing");
- goto error;
- } else if (opt_stop_trace && opt_session_name == NULL) {
- ERR("Please specify a session to stop tracing");
- goto error;
- }
-
- /* If start trace, auto start tracing */
- if (opt_start_trace || opt_event_list != NULL || opt_enable_all_event) {
- DBG("Requesting auto tracing");
- auto_trace = 1;
+ i++;
+ cmd = &commands[i];
}
- /* If no session, auto create one */
- if (opt_session_name == NULL) {
- DBG("Requesting an auto session creation");
- auto_session = 1;
- }
+ /* Command not found */
+ ret = -1;
end:
- return 0;
-
-error:
- return -1;
+ return ret;
}
/*
int ret = 0;
pid_t pid;
- MSG("Spawning session daemon");
+ MSG("Spawning a session daemon");
pid = fork();
if (pid == 0) {
/*
}
/*
- * check_ltt_sessiond
+ * check_sessiond
*
* Check if the session daemon is available using
* the liblttngctl API for the check. If not, try to
* spawn a daemon.
*/
-static int check_ltt_sessiond(void)
+static int check_sessiond(void)
{
int ret;
char *pathname = NULL, *alloc_pathname = NULL;
}
/*
- * set_signal_handler
+ * parse_args
*
- * Setup signal handler for SIGCHLD and SIGTERM.
+ * Parse command line arguments.
+ * Return 0 if OK, else -1
*/
-static int set_signal_handler(void)
+static int parse_args(int argc, char **argv)
{
- int ret = 0;
- struct sigaction sa;
- sigset_t sigset;
+ int opt, ret;
- if ((ret = sigemptyset(&sigset)) < 0) {
- perror("sigemptyset");
- goto end;
+ if (argc < 2) {
+ usage(stderr);
+ clean_exit(EXIT_FAILURE);
}
- sa.sa_handler = sighandler;
- sa.sa_mask = sigset;
- sa.sa_flags = 0;
- if ((ret = sigaction(SIGCHLD, &sa, NULL)) < 0) {
- perror("sigaction");
- goto end;
+ while ((opt = getopt_long(argc, argv, "+hvqg:", long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'h':
+ usage(stderr);
+ goto error;
+ case 'v':
+ opt_verbose = 1;
+ break;
+ case 'q':
+ opt_quiet = 1;
+ break;
+ case 'g':
+ lttng_set_tracing_group(optarg);
+ break;
+ case OPT_NO_SESSIOND:
+ opt_no_sessiond = 1;
+ break;
+ case OPT_SESSION_PATH:
+ opt_sessiond_path = strdup(optarg);
+ break;
+ default:
+ usage(stderr);
+ goto error;
+ }
}
- if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) {
- perror("sigaction");
- goto end;
+ /* If both options are specified, quiet wins */
+ if (opt_verbose && opt_quiet) {
+ opt_verbose = 0;
}
-end:
- return ret;
-}
-
-/*
- * sighandler
- *
- * Signal handler for the daemon
- */
-static void sighandler(int sig)
-{
- switch (sig) {
- case SIGTERM:
- DBG("SIGTERM catched");
- clean_exit(EXIT_FAILURE);
- break;
- case SIGCHLD:
- /* Notify is done */
- DBG("SIGCHLD catched");
- break;
- default:
- DBG("Unknown signal %d catched", sig);
- break;
+ /* Spawn session daemon if needed */
+ if (opt_no_sessiond == 0 && (check_sessiond() < 0)) {
+ goto error;
}
- return;
-}
+ /* No leftovers, print usage and quit */
+ if ((argc - optind) == 0) {
+ usage(stderr);
+ goto error;
+ }
-/*
- * clean_exit
- */
-void clean_exit(int code)
-{
- DBG("Clean exit");
- if (session_name) {
- free(session_name);
+ /*
+ * Handle leftovers which is a first level command with the trailing
+ * options.
+ */
+ ret = handle_command(argc - optind, argv + optind);
+ if (ret < 0) {
+ if (ret == -1) {
+ usage(stderr);
+ goto error;
+ } else {
+ ERR("%s", lttng_get_readable_code(ret));
+ }
}
- exit(code);
+ return ret;
+
+error:
+ return -1;
}
+
/*
* main
*/
MSG("%c[%d;%dmWelcome back Dr Tracing!%c[%dm\n\n", 27,1,33,27,0);
}
- ret = parse_args(argc, (const char **) argv);
- if (ret < 0) {
- clean_exit(EXIT_FAILURE);
- }
-
- ret = validate_options();
- if (ret < 0) {
- return EXIT_FAILURE;
- }
-
ret = set_signal_handler();
if (ret < 0) {
clean_exit(ret);
}
- if (opt_tracing_group != NULL) {
- DBG("Set tracing group to '%s'", opt_tracing_group);
- lttng_set_tracing_group(opt_tracing_group);
- }
-
- /* If ask for kernel tracing, need root perms */
- if (opt_trace_kernel) {
- DBG("Kernel tracing activated");
- if (getuid() != 0) {
- ERR("%s must be setuid root", progname);
- clean_exit(-EPERM);
- }
- }
-
- /* Check if the lttng session daemon is running.
- * If no, a daemon will be spawned.
- */
- if (opt_no_sessiond == 0 && (check_ltt_sessiond() < 0)) {
- clean_exit(EXIT_FAILURE);
- }
-
- ret = process_client_opt();
- if (ret < 0) {
- clean_exit(ret);
- }
-
- clean_exit(0);
+ ret = parse_args(argc, argv);
+ clean_exit(ret);
return 0;
}
+++ /dev/null
-/*
- * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <popt.h>
-#include <stdlib.h>
-
-#include "options.h"
-
-/* Option variables */
-char *opt_event_list;
-char *opt_tracing_group;
-char *opt_sessiond_path;
-char *opt_session_name;
-char *opt_trace_name;
-int opt_destroy_trace;
-int opt_create_session;
-int opt_destroy_session;
-int opt_trace_kernel;
-int opt_quiet;
-int opt_verbose;
-int opt_list_apps;
-int opt_list_events;
-int opt_no_sessiond;
-int opt_list_session;
-int opt_list_traces;
-int opt_create_trace;
-int opt_start_trace;
-int opt_stop_trace;
-int opt_enable_event;
-int opt_enable_all_event;
-int opt_disable_event;
-int opt_kern_create_channel;
-pid_t opt_trace_pid;
-
-enum {
- OPT_HELP = 1,
- OPT_ENABLE_EVENT,
- OPT_DISABLE_EVENT,
- OPT_CREATE_SESSION,
- OPT_CREATE_TRACE,
- OPT_DESTROY_SESSION,
- OPT_DESTROY_TRACE,
- OPT_START_TRACE,
- OPT_STOP_TRACE,
-};
-
-static struct poptOption long_options[] = {
- /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
- {"create-session", 'c', POPT_ARG_STRING, 0, OPT_CREATE_SESSION, 0, 0},
- {"create-trace", 'C', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, 0, OPT_CREATE_TRACE, 0, 0},
- {"destroy-trace", 'D', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, 0, OPT_DESTROY_TRACE, 0, 0},
- {"destroy-session", 'd', POPT_ARG_STRING, 0, OPT_DESTROY_SESSION, 0, 0},
- {"disable-event", 0, POPT_ARG_STRING, 0, OPT_DISABLE_EVENT, 0, 0},
- {"enable-event", 'e', POPT_ARG_STRING, 0, OPT_ENABLE_EVENT, 0, 0},
- {"enable-all-event",'a', POPT_ARG_VAL, &opt_enable_all_event, 1, 0, 0},
- {"group", 0, POPT_ARG_STRING, &opt_tracing_group, 0, 0, 0},
- {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
- {"kernel", 'k', POPT_ARG_VAL, &opt_trace_kernel, 1, 0, 0},
- {"kern-create-channel",0, POPT_ARG_VAL, &opt_kern_create_channel, 1, 0, 0},
- {"list-apps", 'L', POPT_ARG_VAL, &opt_list_apps, 1, 0, 0},
- {"list-events", 0, POPT_ARG_VAL, &opt_list_events, 1, 0, 0},
- {"list-sessions", 'l', POPT_ARG_VAL, &opt_list_session, 1, 0, 0},
- {"list-traces", 't', POPT_ARG_VAL, &opt_list_traces, 1, 0, 0},
- {"no-kernel", 0, POPT_ARG_VAL, &opt_trace_kernel, 0, 0, 0},
- {"no-sessiond", 0, POPT_ARG_VAL, &opt_no_sessiond, 1, 0, 0},
- {"pid", 'p', POPT_ARG_INT, &opt_trace_pid, 0, 0, 0},
- {"quiet", 'q', POPT_ARG_VAL, &opt_quiet, 1, 0, 0},
- {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
- {"sessiond-path", 0, POPT_ARG_STRING, &opt_sessiond_path, 0, 0, 0},
- {"start", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, 0, OPT_START_TRACE, 0, 0},
- {"stop", 0, POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, 0, OPT_STOP_TRACE, 0, 0},
- {"verbose", 'v', POPT_ARG_VAL, &opt_verbose, 1, 0, 0},
- {0, 0, 0, 0, 0, 0, 0}
-};
-
-
-/*
- * usage
- */
-static void usage(FILE *ofp)
-{
- fprintf(ofp, "LTTng Trace Control " VERSION"\n\n");
- fprintf(ofp, "usage : lttng [OPTION]\n");
- fprintf(ofp, "\n");
- fprintf(ofp, "Options:\n");
- fprintf(ofp, " -v, --verbose Verbose mode\n");
- fprintf(ofp, " -q, --quiet Quiet mode\n");
- fprintf(ofp, " --help Show help\n");
- fprintf(ofp, " --group NAME Unix tracing group name. (default: tracing)\n");
- fprintf(ofp, " --no-sessiond Don't spawn a session daemon\n");
- fprintf(ofp, " --sessiond-path Session daemon full path\n");
- fprintf(ofp, " -L, --list-apps List traceable user-space applications\n");
- fprintf(ofp, "\n");
- fprintf(ofp, "Session options:\n");
- fprintf(ofp, " -c, --create-session NAME Create a new session\n");
- fprintf(ofp, " -l, --list-sessions List all available sessions by name\n");
- fprintf(ofp, " -s, --session UUID Specify tracing session using UUID\n");
- fprintf(ofp, " -d, --destroy-session NAME Destroy the session specified by NAME\n");
- fprintf(ofp, " -t, --list-traces List session's traces. Use -s to specify the session\n");
- fprintf(ofp, "\n");
- fprintf(ofp, "Tracing options:\n");
- fprintf(ofp, " -p, --pid PID Specify action on user-space tracer for PID\n");
- fprintf(ofp, " -k, --kernel Specify action on kernel tracer\n");
- fprintf(ofp, " --list-events List all available tracing events\n");
- fprintf(ofp, " -e, --enable-event LIST Enable tracing event (support marker and tracepoint)\n");
- fprintf(ofp, " -a, --enable-all-event Enable all tracing event\n");
- fprintf(ofp, " --disable-event LIST Disable tracing event (support marker and tracepoint)\n");
- fprintf(ofp, " -C, --create-trace Create a trace. Allocate and setup a trace\n");
- fprintf(ofp, " -D, --destroy-trace [NAME] Destroy a trace. Use NAME to identify user-space trace\n");
- fprintf(ofp, " --start [NAME] Start tracing. Use NAME to identify user-space trace\n");
- fprintf(ofp, " --stop [NAME] Stop tracing. Use NAME to identify user-space trace\n");
- fprintf(ofp, "\n");
- fprintf(ofp, "Kernel tracing options:\n");
- fprintf(ofp, " --kern-create-channel Create a kernel channel\n");
- fprintf(ofp, "\n");
- fprintf(ofp, "User-space tracing options:\n");
- fprintf(ofp, "\n");
- fprintf(ofp, "Please see the lttng(1) man page for full documentation.\n");
- fprintf(ofp, "See http://lttng.org for updates, bug reports and news.\n");
-}
-
-/*
- * parse_args
- *
- * Parse command line arguments.
- * Return 0 if OK, else -1
- */
-int parse_args(int argc, const char **argv)
-{
- static poptContext pc;
- int opt;
-
- /* If no options, fail */
- if (argc < 2) {
- return -1;
- }
-
- pc = poptGetContext(NULL, argc, argv, long_options, 0);
- poptReadDefaultConfig(pc, 0);
-
- while ((opt = poptGetNextOpt(pc)) != -1) {
- switch (opt) {
- case OPT_HELP:
- usage(stderr);
- clean_exit(EXIT_SUCCESS);
- break;
- case OPT_CREATE_SESSION:
- opt_create_session = 1;
- opt_session_name = poptGetOptArg(pc);
- break;
- case OPT_DESTROY_SESSION:
- opt_destroy_session = 1;
- opt_session_name = poptGetOptArg(pc);
- break;
- case OPT_ENABLE_EVENT:
- opt_enable_event = 1;
- opt_event_list = poptGetOptArg(pc);
- break;
- case OPT_DESTROY_TRACE:
- opt_destroy_trace = 1;
- opt_trace_name = poptGetOptArg(pc);
- break;
- case OPT_START_TRACE:
- opt_start_trace = 1;
- opt_trace_name = poptGetOptArg(pc);
- break;
- case OPT_STOP_TRACE:
- opt_stop_trace = 1;
- opt_trace_name = poptGetOptArg(pc);
- break;
- case OPT_CREATE_TRACE:
- opt_create_trace = 1;
- opt_trace_name = poptGetOptArg(pc);
- break;
- default:
- usage(stderr);
- clean_exit(EXIT_FAILURE);
- break;
- }
- }
-
- if (pc) {
- poptFreeContext(pc);
- }
-
- return 0;
-}
+++ /dev/null
-/* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _LTTNG_OPTIONS_H
-#define _LTTNG_OPTIONS_H_
-
-/* Function prototypes */
-int parse_args(int argc, const char **argv);
-void clean_exit(int code);
-
-/* Command line options */
-extern int opt_trace_kernel;
-extern int opt_verbose;
-extern int opt_quiet;
-extern char *opt_tracing_group;
-extern char *opt_session_uuid;
-extern char *opt_sessiond_path;
-extern char *opt_session_name;
-extern char *opt_event_list;
-extern char *opt_trace_name;
-extern int opt_destroy_trace;
-extern int opt_enable_event;
-extern int opt_enable_all_event;
-extern int opt_disable_event;
-extern int opt_destroy_session;
-extern int opt_create_session;
-extern int opt_kern_create_channel;
-extern int opt_list_apps;
-extern int opt_list_events;
-extern int opt_no_sessiond;
-extern int opt_list_session;
-extern int opt_list_traces;
-extern int opt_create_trace;
-extern int opt_start_trace;
-extern int opt_stop_trace;
-extern pid_t opt_trace_pid;
-
-#endif /* _LTTNG_OPTIONS_H */
--- /dev/null
+/*
+ * Copyright (c) 2011 David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+
+#include <lttng/lttng.h>
+
+#include "config.h"
+
+/*
+ * get_config_file_path
+ *
+ * Return absolute path to the configuration file.
+ */
+char *get_config_file_path(void)
+{
+ char *alloc_path, *path = NULL;
+
+ /* Get path to config directory */
+ alloc_path = config_get_default_path();
+ if (alloc_path == NULL) {
+ goto error;
+ }
+
+ /* Get path to config file */
+ path = config_generate_dir_path(alloc_path);
+ if (path == NULL) {
+ goto free_alloc_path;
+ }
+
+free_alloc_path:
+ free(alloc_path);
+error:
+ return path;
+}
+
+/*
+ * get_session_name
+ *
+ * Return allocated string with the session name found in the config
+ * directory.
+ */
+char *get_session_name(void)
+{
+ char *path, *session_name = NULL;
+
+ /* Get path to config file */
+ path = get_config_file_path();
+ if (path == NULL) {
+ goto error;
+ }
+
+ /* Get session name from config */
+ session_name = config_read_session_name(path);
+ if (session_name == NULL) {
+ goto free_path;
+ }
+
+free_path:
+ free(path);
+error:
+ return session_name;
+}
+
+/*
+ * set_session_name
+ *
+ * Get session name and set it for the lttng control lib.
+ */
+int set_session_name(void)
+{
+ int ret;
+ char *session_name;
+
+ session_name = get_session_name();
+ if (session_name == NULL) {
+ ret = -1;
+ goto error;
+ }
+
+ lttng_set_session_name(session_name);
+ free(session_name);
+
+ ret = 0;
+
+error:
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _LTTNG_UTILS_H
+#define _LTTNG_UTILS_H
+
+char *get_config_file_path(void);
+char *get_session_name(void);
+int set_session_name(void);
+
+#endif /* _LTTNG_UTILS_H */