src.ctf.lttng-live: make lttng_live_trace::trace_class a bt2::TraceClass::Shared
[babeltrace.git] / src / plugins / ctf / lttng-live / metadata.cpp
CommitLineData
7cdc2bab 1/*
0235b0db 2 * SPDX-License-Identifier: MIT
7cdc2bab 3 *
0235b0db
MJ
4 * Copyright 2019 Francis Deslauriers <francis.deslauriers@efficios.com>
5 * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
7cdc2bab
MD
7 */
8
578e048b 9#include "compat/memstream.h"
15fcc425 10#include "cpp-common/bt2c/libc-up.hpp"
7cdc2bab 11
5656cea5
PP
12#include "../common/src/metadata/tsdl/ctf-meta-configure-ir-trace.hpp"
13#include "../common/src/metadata/tsdl/decoder.hpp"
14#include "lttng-live.hpp"
c802cacb 15#include "metadata.hpp"
7cdc2bab 16
4164020e 17#define TSDL_MAGIC 0x75d11d57
7cdc2bab 18
4164020e
SM
19struct packet_header
20{
21 uint32_t magic;
22 uint8_t uuid[16];
23 uint32_t checksum;
24 uint32_t content_size;
25 uint32_t packet_size;
26 uint8_t compression_scheme;
27 uint8_t encryption_scheme;
28 uint8_t checksum_scheme;
29 uint8_t major;
30 uint8_t minor;
31} __attribute__((__packed__));
14f28187 32
4164020e 33static bool stream_classes_all_have_default_clock_class(bt_trace_class *tc,
0f5c5d5c 34 const bt2c::Logger& logger)
7cdc2bab 35{
4164020e
SM
36 uint64_t i, sc_count;
37 const bt_clock_class *cc = NULL;
38 const bt_stream_class *sc;
39 bool ret = true;
40
41 sc_count = bt_trace_class_get_stream_class_count(tc);
42 for (i = 0; i < sc_count; i++) {
43 sc = bt_trace_class_borrow_stream_class_by_index_const(tc, i);
44
45 BT_ASSERT(sc);
46
47 cc = bt_stream_class_borrow_default_clock_class_const(sc);
48 if (!cc) {
49 ret = false;
0f5c5d5c
SM
50 BT_CPPLOGE_APPEND_CAUSE_SPEC(logger,
51 "Stream class doesn't have a default clock class: "
52 "sc-id={}, sc-name=\"{}\"",
53 bt_stream_class_get_id(sc), bt_stream_class_get_name(sc));
4164020e
SM
54 goto end;
55 }
56 }
7cdc2bab 57
7cdc2bab 58end:
4164020e 59 return ret;
14f28187
FD
60}
61/*
62 * Iterate over the stream classes and returns the first clock class
63 * encountered. This is useful to create message iterator inactivity message as
64 * we don't need a particular clock class.
65 */
4164020e 66static const bt_clock_class *borrow_any_clock_class(bt_trace_class *tc)
14f28187 67{
4164020e
SM
68 uint64_t i, sc_count;
69 const bt_clock_class *cc = NULL;
70 const bt_stream_class *sc;
71
72 sc_count = bt_trace_class_get_stream_class_count(tc);
73 for (i = 0; i < sc_count; i++) {
74 sc = bt_trace_class_borrow_stream_class_by_index_const(tc, i);
75 BT_ASSERT_DBG(sc);
76
77 cc = bt_stream_class_borrow_default_clock_class_const(sc);
78 if (cc) {
79 goto end;
80 }
81 }
14f28187 82end:
4164020e
SM
83 BT_ASSERT_DBG(cc);
84 return cc;
7cdc2bab
MD
85}
86
4164020e 87enum lttng_live_iterator_status lttng_live_metadata_update(struct lttng_live_trace *trace)
7cdc2bab 88{
4164020e
SM
89 struct lttng_live_session *session = trace->session;
90 struct lttng_live_metadata *metadata = trace->metadata;
15fcc425 91 std::vector<char> metadataBuf;
4164020e 92 bool keep_receiving;
15fcc425 93 bt2c::FileUP fp;
4164020e
SM
94 enum ctf_metadata_decoder_status decoder_status;
95 enum lttng_live_iterator_status status = LTTNG_LIVE_ITERATOR_STATUS_OK;
4164020e
SM
96 enum lttng_live_get_one_metadata_status metadata_status;
97
0f5c5d5c
SM
98 BT_CPPLOGD_SPEC(metadata->logger, "Updating metadata for trace: session-id={}, trace-id={}",
99 session->id, trace->id);
4164020e
SM
100
101 /* No metadata stream yet. */
102 if (!metadata) {
86080481
FD
103 if (session->closed) {
104 /*
105 * The session is closed AND we never received any
106 * metadata this indicates that we will never receive
107 * any metadata.
108 */
109 status = LTTNG_LIVE_ITERATOR_STATUS_END;
110 } else if (session->new_streams_needed) {
4164020e
SM
111 status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
112 } else {
113 session->new_streams_needed = true;
114 status = LTTNG_LIVE_ITERATOR_STATUS_CONTINUE;
115 }
116 goto end;
117 }
118
119 if (trace->metadata_stream_state != LTTNG_LIVE_METADATA_STREAM_STATE_NEEDED) {
120 goto end;
121 }
122
4164020e
SM
123 keep_receiving = true;
124 /* Grab all available metadata. */
125 while (keep_receiving) {
4164020e
SM
126 /*
127 * lttng_live_get_one_metadata_packet() asks the Relay Daemon
128 * for new metadata. If new metadata is received, the function
129 * writes it to the provided file handle and updates the
130 * reply_len output parameter. We call this function in loop
131 * until it returns _END meaning that no new metadata is
132 * available.
133 * We may receive a _CLOSED status if the metadata stream we
134 * are requesting is no longer available on the relay.
135 * If we receive an _ERROR status, it means there was a
136 * networking, allocating, or some other unrecoverable error.
137 */
15fcc425 138 metadata_status = lttng_live_get_one_metadata_packet(trace, metadataBuf);
4164020e
SM
139
140 switch (metadata_status) {
141 case LTTNG_LIVE_GET_ONE_METADATA_STATUS_OK:
4164020e
SM
142 break;
143 case LTTNG_LIVE_GET_ONE_METADATA_STATUS_END:
144 keep_receiving = false;
145 break;
146 case LTTNG_LIVE_GET_ONE_METADATA_STATUS_CLOSED:
0f5c5d5c
SM
147 BT_CPPLOGD_SPEC(
148 metadata->logger,
149 "Metadata stream was closed by the Relay, the trace is no longer active: "
150 "trace-id={}, metadata-stream-id={}",
151 trace->id, metadata->stream_id);
4164020e
SM
152 /*
153 * The stream was closed and we received everything
154 * there was to receive for this metadata stream.
155 * We go on with the decoding of what we received. So
156 * that data stream can be decoded.
157 */
158 keep_receiving = false;
159 trace->metadata_stream_state = LTTNG_LIVE_METADATA_STREAM_STATE_CLOSED;
160 break;
161 case LTTNG_LIVE_GET_ONE_METADATA_STATUS_ERROR:
0f5c5d5c
SM
162 BT_CPPLOGE_APPEND_CAUSE_SPEC(metadata->logger,
163 "Error getting one trace metadata packet: trace-id={}",
164 trace->id);
4164020e
SM
165 goto error;
166 default:
167 bt_common_abort();
168 }
169 }
170
15fcc425 171 if (metadataBuf.empty()) {
4164020e
SM
172 if (!trace->trace) {
173 status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
174 goto end;
175 }
176
e7401568 177 /* The relay sent zero bytes of metadata. */
4164020e
SM
178 trace->metadata_stream_state = LTTNG_LIVE_METADATA_STREAM_STATE_NOT_NEEDED;
179 goto end;
180 }
181
182 /*
183 * Open a new reading file handle on the `metadata_buf` and pass it to
184 * the metadata decoder.
185 */
15fcc425 186 fp.reset(bt_fmemopen(metadataBuf.data(), metadataBuf.size(), "rb"));
4164020e
SM
187 if (!fp) {
188 if (errno == EINTR && lttng_live_graph_is_canceled(session->lttng_live_msg_iter)) {
189 session->lttng_live_msg_iter->was_interrupted = true;
190 status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
191 } else {
0f5c5d5c
SM
192 BT_CPPLOGE_ERRNO_APPEND_CAUSE_SPEC(metadata->logger,
193 "Cannot memory-open metadata buffer", ".");
4164020e
SM
194 status = LTTNG_LIVE_ITERATOR_STATUS_ERROR;
195 }
196 goto end;
197 }
198
199 /*
200 * The call to ctf_metadata_decoder_append_content() will append
201 * new metadata to our current trace class.
202 */
0f5c5d5c 203 BT_CPPLOGD_SPEC(metadata->logger, "Appending new metadata to the ctf_trace class");
15fcc425 204 decoder_status = ctf_metadata_decoder_append_content(metadata->decoder.get(), fp.get());
4164020e
SM
205 switch (decoder_status) {
206 case CTF_METADATA_DECODER_STATUS_OK:
207 if (!trace->trace_class) {
208 struct ctf_trace_class *tc =
1fa280c9 209 ctf_metadata_decoder_borrow_ctf_trace_class(metadata->decoder.get());
4164020e 210
a52f1f2e
SM
211 trace->trace_class = ctf_metadata_decoder_get_ir_trace_class(metadata->decoder.get());
212 trace->trace = bt_trace_create(trace->trace_class->libObjPtr());
4164020e 213 if (!trace->trace) {
0f5c5d5c 214 BT_CPPLOGE_APPEND_CAUSE_SPEC(metadata->logger, "Failed to create bt_trace");
4164020e
SM
215 goto error;
216 }
217 if (ctf_trace_class_configure_ir_trace(tc, trace->trace)) {
0f5c5d5c
SM
218 BT_CPPLOGE_APPEND_CAUSE_SPEC(metadata->logger,
219 "Failed to configure ctf trace class");
4164020e
SM
220 goto error;
221 }
a52f1f2e 222 if (!stream_classes_all_have_default_clock_class(trace->trace_class->libObjPtr(),
0f5c5d5c 223 metadata->logger)) {
4164020e
SM
224 /* Error logged in function. */
225 goto error;
226 }
a52f1f2e 227 trace->clock_class = borrow_any_clock_class(trace->trace_class->libObjPtr());
4164020e
SM
228 }
229
e7401568 230 /* The metadata was updated successfully. */
4164020e
SM
231 trace->metadata_stream_state = LTTNG_LIVE_METADATA_STREAM_STATE_NOT_NEEDED;
232
233 break;
234 default:
235 goto error;
236 }
237
238 goto end;
c28512ab 239
7cdc2bab 240error:
4164020e 241 status = LTTNG_LIVE_ITERATOR_STATUS_ERROR;
7cdc2bab 242end:
4164020e 243 return status;
7cdc2bab
MD
244}
245
4164020e 246int lttng_live_metadata_create_stream(struct lttng_live_session *session, uint64_t ctf_trace_id,
44bd6303 247 uint64_t stream_id)
7cdc2bab 248{
4164020e
SM
249 struct lttng_live_trace *trace;
250
0f5c5d5c 251 ctf_metadata_decoder_config cfg {session->logger};
4164020e 252 cfg.self_comp = session->self_comp;
4164020e
SM
253 cfg.create_trace_class = true;
254
0f5c5d5c 255 lttng_live_metadata *metadata = new lttng_live_metadata {session->logger};
4164020e
SM
256 metadata->stream_id = stream_id;
257
258 metadata->decoder = ctf_metadata_decoder_create(&cfg);
259 if (!metadata->decoder) {
0f5c5d5c 260 BT_CPPLOGE_APPEND_CAUSE_SPEC(session->logger, "Failed to create CTF metadata decoder");
4164020e
SM
261 goto error;
262 }
263 trace = lttng_live_session_borrow_or_create_trace_by_id(session, ctf_trace_id);
264 if (!trace) {
0f5c5d5c 265 BT_CPPLOGE_APPEND_CAUSE_SPEC(session->logger, "Failed to borrow trace");
4164020e
SM
266 goto error;
267 }
268 trace->metadata = metadata;
269 return 0;
7cdc2bab
MD
270
271error:
afb0f12b 272 delete metadata;
4164020e 273 return -1;
7cdc2bab
MD
274}
275
7cdc2bab
MD
276void lttng_live_metadata_fini(struct lttng_live_trace *trace)
277{
4164020e
SM
278 struct lttng_live_metadata *metadata = trace->metadata;
279
280 if (!metadata) {
281 return;
282 }
4164020e 283 trace->metadata = NULL;
afb0f12b 284 delete metadata;
7cdc2bab 285}
This page took 0.117009 seconds and 4 git commands to generate.