+ enum lttng_error_code status = LTTNG_OK;
+ struct lttng_ht_iter iter;
+ struct consumer_socket *socket;
+ LTTNG_OPTIONAL(uint64_t) current_chunk_id = {};
+
+ assert(consumer);
+ assert(snap_output);
+ assert(session);
+
+ DBG2("Set relayd object from snapshot output");
+
+ if (session->current_trace_chunk) {
+ enum lttng_trace_chunk_status status = lttng_trace_chunk_get_id(
+ session->current_trace_chunk, ¤t_chunk_id.value);
+
+ if (status == LTTNG_TRACE_CHUNK_STATUS_OK) {
+ current_chunk_id.is_set = true;
+ } else {
+ ERR("Failed to get current trace chunk id");
+ status = LTTNG_ERR_UNK;
+ goto error;
+ }
+ }
+
+ /* Ignore if snapshot consumer output is not network. */
+ if (snap_output->consumer->type != CONSUMER_DST_NET) {
+ goto error;
+ }
+
+ /*
+ * For each consumer socket, create and send the relayd object of the
+ * snapshot output.
+ */
+ rcu_read_lock();
+ cds_lfht_for_each_entry(snap_output->consumer->socks->ht, &iter.iter,
+ socket, node.node) {
+ pthread_mutex_lock(socket->lock);
+ status = send_consumer_relayd_sockets(0, session->id,
+ snap_output->consumer, socket,
+ session->name, session->hostname,
+ session->live_timer,
+ current_chunk_id.is_set ? ¤t_chunk_id.value : NULL);
+ pthread_mutex_unlock(socket->lock);
+ if (status != LTTNG_OK) {
+ rcu_read_unlock();
+ goto error;
+ }
+ }
+ rcu_read_unlock();
+
+error:
+ return status;
+}
+
+/*
+ * Record a kernel snapshot.
+ *
+ * Return LTTNG_OK on success or a LTTNG_ERR code.
+ */
+static enum lttng_error_code record_kernel_snapshot(
+ struct ltt_kernel_session *ksess,
+ const struct snapshot_output *output,
+ const struct ltt_session *session,
+ int wait, uint64_t nb_packets_per_stream)
+{
+ int ret;
+ enum lttng_error_code status;
+
+ assert(ksess);
+ assert(output);
+ assert(session);
+
+ /*
+ * Copy kernel session sockets so we can communicate with the right
+ * consumer for the snapshot record command.
+ */
+ ret = consumer_copy_sockets(output->consumer, ksess->consumer);
+ if (ret < 0) {
+ status = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+
+ status = set_relayd_for_snapshot(ksess->consumer, output, session);
+ if (status != LTTNG_OK) {
+ goto error_snapshot;
+ }
+
+ status = kernel_snapshot_record(ksess, output, wait, nb_packets_per_stream);
+ if (status != LTTNG_OK) {
+ goto error_snapshot;
+ }
+
+ goto end;
+
+error_snapshot:
+ /* Clean up copied sockets so this output can use some other later on. */
+ consumer_destroy_output_sockets(output->consumer);
+error:
+end:
+ return status;
+}
+
+/*
+ * Record a UST snapshot.
+ *
+ * Returns LTTNG_OK on success or a LTTNG_ERR error code.
+ */
+static enum lttng_error_code record_ust_snapshot(struct ltt_ust_session *usess,
+ const struct snapshot_output *output,
+ const struct ltt_session *session, int wait,
+ uint64_t nb_packets_per_stream)
+{
+ int ret;
+ enum lttng_error_code status;
+
+ assert(usess);
+ assert(output);
+ assert(session);
+
+ /*
+ * Copy UST session sockets so we can communicate with the right
+ * consumer for the snapshot record command.
+ */
+ ret = consumer_copy_sockets(output->consumer, usess->consumer);
+ if (ret < 0) {
+ status = LTTNG_ERR_NOMEM;
+ goto error;
+ }
+
+ status = set_relayd_for_snapshot(usess->consumer, output, session);
+ if (status != LTTNG_OK) {
+ goto error_snapshot;
+ }
+
+ status = ust_app_snapshot_record(usess, output, wait,
+ nb_packets_per_stream);
+ if (status != LTTNG_OK) {
+ goto error_snapshot;
+ }
+
+ goto end;
+
+error_snapshot:
+ /* Clean up copied sockets so this output can use some other later on. */
+ consumer_destroy_output_sockets(output->consumer);
+error:
+end:
+ return status;
+}
+
+static
+uint64_t get_session_size_one_more_packet_per_stream(
+ const struct ltt_session *session, uint64_t cur_nr_packets)
+{
+ uint64_t tot_size = 0;