struct consumer_output *consumer,
struct consumer_socket *consumer_sock,
const char *session_name, const char *hostname,
- int session_live_timer,
+ const char *base_path, int session_live_timer,
const uint64_t *current_chunk_id,
- time_t session_creation_time)
+ time_t session_creation_time,
+ bool session_name_contains_creation_time)
{
int ret;
struct lttcomm_relayd_sock *rsock = NULL;
/* Send relayd socket to consumer. */
ret = consumer_send_relayd_socket(consumer_sock, rsock, consumer,
relayd_uri->stype, session_id,
- session_name, hostname, session_live_timer,
- current_chunk_id, session_creation_time);
+ session_name, hostname, base_path,
+ session_live_timer, current_chunk_id,
+ session_creation_time, session_name_contains_creation_time);
if (ret < 0) {
status = LTTNG_ERR_ENABLE_CONSUMER_FAIL;
goto close_sock;
enum lttng_domain_type domain,
unsigned int session_id, struct consumer_output *consumer,
struct consumer_socket *sock, const char *session_name,
- const char *hostname, int session_live_timer,
- const uint64_t *current_chunk_id, time_t session_creation_time)
+ const char *hostname, const char *base_path, int session_live_timer,
+ const uint64_t *current_chunk_id, time_t session_creation_time,
+ bool session_name_contains_creation_time)
{
enum lttng_error_code status = LTTNG_OK;
if (!sock->control_sock_sent) {
status = send_consumer_relayd_socket(session_id,
&consumer->dst.net.control, consumer, sock,
- session_name, hostname, session_live_timer,
- current_chunk_id, session_creation_time);
+ session_name, hostname, base_path, session_live_timer,
+ current_chunk_id, session_creation_time,
+ session_name_contains_creation_time);
if (status != LTTNG_OK) {
goto error;
}
if (!sock->data_sock_sent) {
status = send_consumer_relayd_socket(session_id,
&consumer->dst.net.data, consumer, sock,
- session_name, hostname, session_live_timer,
- current_chunk_id, session_creation_time);
+ session_name, hostname, base_path, session_live_timer,
+ current_chunk_id, session_creation_time,
+ session_name_contains_creation_time);
if (status != LTTNG_OK) {
goto error;
}
ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_UST, session->id,
usess->consumer, socket,
session->name, session->hostname,
+ session->base_path,
session->live_timer,
current_chunk_id.is_set ? ¤t_chunk_id.value : NULL,
- session->creation_time);
+ session->creation_time,
+ session->name_contains_creation_time);
pthread_mutex_unlock(socket->lock);
if (ret != LTTNG_OK) {
goto error;
ret = send_consumer_relayd_sockets(LTTNG_DOMAIN_KERNEL, session->id,
ksess->consumer, socket,
session->name, session->hostname,
+ session->base_path,
session->live_timer,
current_chunk_id.is_set ? ¤t_chunk_id.value : NULL,
- session->creation_time);
+ session->creation_time,
+ session->name_contains_creation_time);
pthread_mutex_unlock(socket->lock);
if (ret != LTTNG_OK) {
goto error;
/*
* Start a kernel session by opening all necessary streams.
*/
-static int start_kernel_session(struct ltt_kernel_session *ksess, int wpipe)
+static int start_kernel_session(struct ltt_kernel_session *ksess)
{
int ret;
struct ltt_kernel_channel *kchan;
}
/* Quiescent wait after starting trace */
- kernel_wait_quiescent(wpipe);
+ kernel_wait_quiescent();
ksess->active = 1;
goto error;
}
- kernel_wait_quiescent(kernel_tracer_fd);
+ kernel_wait_quiescent();
break;
}
case LTTNG_DOMAIN_UST:
goto error;
}
- kernel_wait_quiescent(kernel_tracer_fd);
+ kernel_wait_quiescent();
break;
}
case LTTNG_DOMAIN_UST:
goto error;
}
- kernel_wait_quiescent(kernel_tracer_fd);
+ kernel_wait_quiescent();
break;
}
case LTTNG_DOMAIN_UST:
switch (domain->type) {
case LTTNG_DOMAIN_KERNEL:
{
- if (kernel_supports_ring_buffer_snapshot_sample_positions(kernel_tracer_fd) != 1) {
+ if (kernel_supports_ring_buffer_snapshot_sample_positions() != 1) {
/* Sampling position of buffer is not supported */
WARN("Kernel tracer does not support buffer monitoring. "
"Setting the monitor interval timer to 0 "
goto error;
}
- kernel_wait_quiescent(kernel_tracer_fd);
+ kernel_wait_quiescent();
break;
}
case LTTNG_DOMAIN_UST:
goto error_unlock;
}
- kernel_wait_quiescent(kernel_tracer_fd);
+ kernel_wait_quiescent();
break;
}
case LTTNG_DOMAIN_UST:
goto error;
}
- kernel_wait_quiescent(kernel_tracer_fd);
+ kernel_wait_quiescent();
break;
}
case LTTNG_DOMAIN_UST:
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
- nb_events = kernel_list_events(kernel_tracer_fd, events);
+ nb_events = kernel_list_events(events);
if (nb_events < 0) {
ret = LTTNG_ERR_KERN_LIST_FAIL;
goto error;
goto error;
}
- if (session->output_traces && !session->current_trace_chunk &&
- session_output_supports_trace_chunks(session)) {
+ if (session->output_traces && !session->current_trace_chunk) {
struct lttng_trace_chunk *trace_chunk;
trace_chunk = session_create_new_trace_chunk(
/* Kernel tracing */
if (ksession != NULL) {
DBG("Start kernel tracing session %s", session->name);
- ret = start_kernel_session(ksession, kernel_tracer_fd);
+ ret = start_kernel_session(ksession);
if (ret != LTTNG_OK) {
goto error;
}
goto error;
}
- kernel_wait_quiescent(kernel_tracer_fd);
+ kernel_wait_quiescent();
/* Flush metadata after stopping (if exists) */
if (ksession->metadata_stream_fd >= 0) {
const char *session_name;
struct ltt_session *new_session = NULL;
enum lttng_session_descriptor_status descriptor_status;
+ const char *base_path;
session_lock_list();
if (home_path) {
ret_code = LTTNG_ERR_INVALID;
goto end;
}
+ ret = lttng_session_descriptor_get_base_path(descriptor, &base_path);
+ if (ret) {
+ ret_code = LTTNG_ERR_INVALID;
+ goto end;
+ }
ret_code = session_create(session_name, creds->uid, creds->gid,
- &new_session);
+ base_path, &new_session);
if (ret_code != LTTNG_OK) {
goto end;
}
* Perform a last rotation on destruction if rotations have
* occurred during the session's lifetime.
*/
- ret = cmd_rotate_session(session, NULL);
+ ret = cmd_rotate_session(session, NULL, false);
if (ret != LTTNG_OK) {
ERR("Failed to perform an implicit rotation as part of the destruction of session \"%s\": %s",
session->name, lttng_strerror(-ret));
if (reply_context) {
reply_context->implicit_rotation_on_destroy = true;
}
- }
+ } else if (session->has_been_started && session->current_trace_chunk) {
+ /*
+ * The user has not triggered a session rotation. However, to
+ * ensure all data has been consumed, the session is rotated
+ * to a 'null' trace chunk before it is destroyed.
+ *
+ * This is a "quiet" rotation meaning that no notification is
+ * emitted and no renaming of the current trace chunk takes
+ * place.
+ */
+ ret = cmd_rotate_session(session, NULL, true);
+ if (ret != LTTNG_OK) {
+ ERR("Failed to perform a quiet rotation as part of the destruction of session \"%s\": %s",
+ session->name, lttng_strerror(-ret));
+ }
+ }
if (session->shm_path[0]) {
/*
struct lttng_ht_iter iter;
struct consumer_socket *socket;
LTTNG_OPTIONAL(uint64_t) current_chunk_id = {};
+ const char *base_path;
assert(output);
assert(session);
goto error;
}
+ /*
+ * The snapshot record URI base path overrides the session
+ * base path.
+ */
+ if (output->dst.net.control.subdir[0] != '\0') {
+ base_path = output->dst.net.control.subdir;
+ } else {
+ base_path = session->base_path;
+ }
+
/*
* For each consumer socket, create and send the relayd object of the
* snapshot output.
status = send_consumer_relayd_sockets(0, session->id,
output, socket,
session->name, session->hostname,
+ base_path,
session->live_timer,
current_chunk_id.is_set ? ¤t_chunk_id.value : NULL,
- session->creation_time);
+ session->creation_time,
+ session->name_contains_creation_time);
pthread_mutex_unlock(socket->lock);
if (status != LTTNG_OK) {
rcu_read_unlock();
session->kernel_session->consumer;
snapshot_kernel_consumer_output =
consumer_copy_output(snapshot_output->consumer);
+ strcpy(snapshot_kernel_consumer_output->chunk_path,
+ snapshot_chunk_name);
ret = consumer_copy_sockets(snapshot_kernel_consumer_output,
original_kernel_consumer_output);
if (ret < 0) {
original_ust_consumer_output = session->ust_session->consumer;
snapshot_ust_consumer_output =
consumer_copy_output(snapshot_output->consumer);
+ strcpy(snapshot_ust_consumer_output->chunk_path,
+ snapshot_chunk_name);
ret = consumer_copy_sockets(snapshot_ust_consumer_output,
original_ust_consumer_output);
if (ret < 0) {
}
if (session_close_trace_chunk(
- session, session->current_trace_chunk, NULL)) {
+ session, session->current_trace_chunk, NULL, NULL)) {
/*
* Don't goto end; make sure the chunk is closed for the session
* to allow future snapshots.
* Returns LTTNG_OK on success or else a negative LTTng error code.
*/
int cmd_rotate_session(struct ltt_session *session,
- struct lttng_rotate_session_return *rotate_return)
+ struct lttng_rotate_session_return *rotate_return,
+ bool quiet_rotation)
{
int ret;
uint64_t ongoing_rotation_chunk_id;
goto end;
}
- if (session->live_timer || !session->output_traces) {
+ /*
+ * Explicit rotation is not supported for live sessions.
+ * However, live sessions can perform a quiet rotation on
+ * destroy.
+ * Rotation is not supported for snapshot traces (no output).
+ */
+ if ((!quiet_rotation && session->live_timer) ||
+ !session->output_traces) {
cmd_ret = LTTNG_ERR_ROTATION_NOT_AVAILABLE;
goto end;
}
/* Unsupported feature in lttng-relayd before 2.11. */
- if (session->consumer->type == CONSUMER_DST_NET &&
+ if (!quiet_rotation && session->consumer->type == CONSUMER_DST_NET &&
(session->consumer->relay_major_version == 2 &&
session->consumer->relay_minor_version < 11)) {
cmd_ret = LTTNG_ERR_ROTATION_NOT_AVAILABLE_RELAY;
}
ret = session_close_trace_chunk(session, chunk_being_archived,
- &((enum lttng_trace_chunk_command_type) {
- LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED}));
+ quiet_rotation ?
+ NULL :
+ &((enum lttng_trace_chunk_command_type){
+ LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED}),
+ session->last_chunk_path);
if (ret) {
cmd_ret = LTTNG_ERR_CLOSE_TRACE_CHUNK_FAIL_CONSUMER;
goto error;
}
+ session->quiet_rotation = quiet_rotation;
ret = timer_session_rotation_pending_check_start(session,
DEFAULT_ROTATE_PENDING_TIMER);
if (ret) {
session->chunk_being_archived = chunk_being_archived;
chunk_being_archived = NULL;
- ret = notification_thread_command_session_rotation_ongoing(
- notification_thread_handle,
- session->name, session->uid, session->gid,
- ongoing_rotation_chunk_id);
- if (ret != LTTNG_OK) {
- ERR("Failed to notify notification thread that a session rotation is ongoing for session %s",
- session->name);
- cmd_ret = ret;
+ if (!quiet_rotation) {
+ ret = notification_thread_command_session_rotation_ongoing(
+ notification_thread_handle,
+ session->name, session->uid, session->gid,
+ ongoing_rotation_chunk_id);
+ if (ret != LTTNG_OK) {
+ ERR("Failed to notify notification thread that a session rotation is ongoing for session %s",
+ session->name);
+ cmd_ret = ret;
+ }
}
DBG("Cmd rotate session %s, archive_id %" PRIu64 " sent",
sizeof(info_return->location.local.absolute_path);
info_return->location_type =
(int8_t) LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL;
+ fmt_ret = asprintf(&chunk_path,
+ "%s/" DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY "/%s",
+ session_get_base_path(session),
+ session->last_archived_chunk_name);
+ if (fmt_ret == -1) {
+ PERROR("Failed to format the path of the last archived trace chunk");
+ info_return->status = LTTNG_ROTATION_STATUS_ERROR;
+ cmd_ret = LTTNG_ERR_UNK;
+ goto end;
+ }
break;
case CONSUMER_DST_NET:
current_tracing_path_reply =
&info_return->location.relay.ports.data);
info_return->location_type =
(int8_t) LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_RELAY;
+ chunk_path = strdup(session->last_chunk_path);
+ if (!chunk_path) {
+ ERR("Failed to allocate the path of the last archived trace chunk");
+ info_return->status = LTTNG_ROTATION_STATUS_ERROR;
+ cmd_ret = LTTNG_ERR_UNK;
+ goto end;
+ }
break;
default:
abort();
}
- fmt_ret = asprintf(&chunk_path,
- "%s/" DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY "/%s",
- session_get_base_path(session),
- session->last_archived_chunk_name);
- if (fmt_ret == -1) {
- PERROR("Failed to format the path of the last archived trace chunk");
- info_return->status = LTTNG_ROTATION_STATUS_ERROR;
- cmd_ret = LTTNG_ERR_UNK;
- goto end;
- }
fmt_ret = lttng_strncpy(current_tracing_path_reply,
chunk_path, current_tracing_path_reply_len);