+ char snapshot_chunk_name[LTTNG_NAME_MAX];
+ int ret;
+ enum lttng_error_code ret_code = LTTNG_OK;
+ struct lttng_trace_chunk *snapshot_trace_chunk;
+ struct consumer_output *original_ust_consumer_output = NULL;
+ struct consumer_output *original_kernel_consumer_output = NULL;
+ struct consumer_output *snapshot_ust_consumer_output = NULL;
+ struct consumer_output *snapshot_kernel_consumer_output = NULL;
+
+ ret = snprintf(snapshot_chunk_name, sizeof(snapshot_chunk_name),
+ "%s-%s-%" PRIu64,
+ snapshot_output->name,
+ snapshot_output->datetime,
+ snapshot_output->nb_snapshot);
+ if (ret < 0 || ret >= sizeof(snapshot_chunk_name)) {
+ ERR("Failed to format snapshot name");
+ ret_code = LTTNG_ERR_INVALID;
+ goto error;
+ }
+ DBG("Recording snapshot \"%s\" for session \"%s\" with chunk name \"%s\"",
+ snapshot_output->name, session->name,
+ snapshot_chunk_name);
+ if (!session->kernel_session && !session->ust_session) {
+ ERR("Failed to record snapshot as no channels exist");
+ ret_code = LTTNG_ERR_NO_CHANNEL;
+ goto error;
+ }
+
+ if (session->kernel_session) {
+ original_kernel_consumer_output =
+ 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) {
+ ERR("Failed to copy consumer sockets from snapshot output configuration");
+ ret_code = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+ ret_code = set_relayd_for_snapshot(
+ snapshot_kernel_consumer_output, session);
+ if (ret_code != LTTNG_OK) {
+ ERR("Failed to setup relay daemon for kernel tracer snapshot");
+ goto error;
+ }
+ session->kernel_session->consumer =
+ snapshot_kernel_consumer_output;
+ }
+ if (session->ust_session) {
+ 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) {
+ ERR("Failed to copy consumer sockets from snapshot output configuration");
+ ret_code = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+ ret_code = set_relayd_for_snapshot(
+ snapshot_ust_consumer_output, session);
+ if (ret_code != LTTNG_OK) {
+ ERR("Failed to setup relay daemon for userspace tracer snapshot");
+ goto error;
+ }
+ session->ust_session->consumer =
+ snapshot_ust_consumer_output;
+ }
+
+ snapshot_trace_chunk = session_create_new_trace_chunk(session,
+ snapshot_kernel_consumer_output ?:
+ snapshot_ust_consumer_output,
+ consumer_output_get_base_path(
+ snapshot_output->consumer),
+ snapshot_chunk_name);
+ if (!snapshot_trace_chunk) {
+ ERR("Failed to create temporary trace chunk to record a snapshot of session \"%s\"",
+ session->name);
+ ret_code = LTTNG_ERR_CREATE_DIR_FAIL;
+ goto error;
+ }
+ assert(!session->current_trace_chunk);
+ ret = session_set_trace_chunk(session, snapshot_trace_chunk, NULL);
+ lttng_trace_chunk_put(snapshot_trace_chunk);
+ snapshot_trace_chunk = NULL;
+ if (ret) {
+ ERR("Failed to set temporary trace chunk to record a snapshot of session \"%s\"",
+ session->name);
+ ret_code = LTTNG_ERR_CREATE_TRACE_CHUNK_FAIL_CONSUMER;
+ goto error;
+ }