src.ctf.fs: make ds_file_group_insert_ds_file_info_sorted a method of ctf_fs_ds_file_...
[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"
7cdc2bab 10
5656cea5
PP
11#include "../common/src/metadata/tsdl/ctf-meta-configure-ir-trace.hpp"
12#include "../common/src/metadata/tsdl/decoder.hpp"
13#include "lttng-live.hpp"
c802cacb 14#include "metadata.hpp"
7cdc2bab 15
4164020e 16#define TSDL_MAGIC 0x75d11d57
7cdc2bab 17
4164020e
SM
18struct packet_header
19{
20 uint32_t magic;
21 uint8_t uuid[16];
22 uint32_t checksum;
23 uint32_t content_size;
24 uint32_t packet_size;
25 uint8_t compression_scheme;
26 uint8_t encryption_scheme;
27 uint8_t checksum_scheme;
28 uint8_t major;
29 uint8_t minor;
30} __attribute__((__packed__));
14f28187 31
4164020e 32static bool stream_classes_all_have_default_clock_class(bt_trace_class *tc,
0f5c5d5c 33 const bt2c::Logger& logger)
7cdc2bab 34{
4164020e
SM
35 uint64_t i, sc_count;
36 const bt_clock_class *cc = NULL;
37 const bt_stream_class *sc;
38 bool ret = true;
39
40 sc_count = bt_trace_class_get_stream_class_count(tc);
41 for (i = 0; i < sc_count; i++) {
42 sc = bt_trace_class_borrow_stream_class_by_index_const(tc, i);
43
44 BT_ASSERT(sc);
45
46 cc = bt_stream_class_borrow_default_clock_class_const(sc);
47 if (!cc) {
48 ret = false;
0f5c5d5c
SM
49 BT_CPPLOGE_APPEND_CAUSE_SPEC(logger,
50 "Stream class doesn't have a default clock class: "
51 "sc-id={}, sc-name=\"{}\"",
52 bt_stream_class_get_id(sc), bt_stream_class_get_name(sc));
4164020e
SM
53 goto end;
54 }
55 }
7cdc2bab 56
7cdc2bab 57end:
4164020e 58 return ret;
14f28187
FD
59}
60/*
61 * Iterate over the stream classes and returns the first clock class
62 * encountered. This is useful to create message iterator inactivity message as
63 * we don't need a particular clock class.
64 */
4164020e 65static const bt_clock_class *borrow_any_clock_class(bt_trace_class *tc)
14f28187 66{
4164020e
SM
67 uint64_t i, sc_count;
68 const bt_clock_class *cc = NULL;
69 const bt_stream_class *sc;
70
71 sc_count = bt_trace_class_get_stream_class_count(tc);
72 for (i = 0; i < sc_count; i++) {
73 sc = bt_trace_class_borrow_stream_class_by_index_const(tc, i);
74 BT_ASSERT_DBG(sc);
75
76 cc = bt_stream_class_borrow_default_clock_class_const(sc);
77 if (cc) {
78 goto end;
79 }
80 }
14f28187 81end:
4164020e
SM
82 BT_ASSERT_DBG(cc);
83 return cc;
7cdc2bab
MD
84}
85
4164020e 86enum lttng_live_iterator_status lttng_live_metadata_update(struct lttng_live_trace *trace)
7cdc2bab 87{
4164020e
SM
88 struct lttng_live_session *session = trace->session;
89 struct lttng_live_metadata *metadata = trace->metadata;
90 size_t size, len_read = 0;
91 char *metadata_buf = NULL;
92 bool keep_receiving;
93 FILE *fp = NULL;
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
123 /*
124 * Open a new write only file handle to populate the `metadata_buf`
125 * memory buffer so we can write in loop in it easily.
126 */
127 fp = bt_open_memstream(&metadata_buf, &size);
128 if (!fp) {
129 if (errno == EINTR && lttng_live_graph_is_canceled(session->lttng_live_msg_iter)) {
130 session->lttng_live_msg_iter->was_interrupted = true;
131 status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
132 } else {
0f5c5d5c 133 BT_CPPLOGE_ERRNO_APPEND_CAUSE_SPEC(metadata->logger, "Metadata open_memstream", ".");
4164020e
SM
134 status = LTTNG_LIVE_ITERATOR_STATUS_ERROR;
135 }
136 goto end;
137 }
138
139 keep_receiving = true;
140 /* Grab all available metadata. */
141 while (keep_receiving) {
142 size_t reply_len = 0;
143 /*
144 * lttng_live_get_one_metadata_packet() asks the Relay Daemon
145 * for new metadata. If new metadata is received, the function
146 * writes it to the provided file handle and updates the
147 * reply_len output parameter. We call this function in loop
148 * until it returns _END meaning that no new metadata is
149 * available.
150 * We may receive a _CLOSED status if the metadata stream we
151 * are requesting is no longer available on the relay.
152 * If we receive an _ERROR status, it means there was a
153 * networking, allocating, or some other unrecoverable error.
154 */
155 metadata_status = lttng_live_get_one_metadata_packet(trace, fp, &reply_len);
156
157 switch (metadata_status) {
158 case LTTNG_LIVE_GET_ONE_METADATA_STATUS_OK:
159 len_read += reply_len;
160 break;
161 case LTTNG_LIVE_GET_ONE_METADATA_STATUS_END:
162 keep_receiving = false;
163 break;
164 case LTTNG_LIVE_GET_ONE_METADATA_STATUS_CLOSED:
0f5c5d5c
SM
165 BT_CPPLOGD_SPEC(
166 metadata->logger,
167 "Metadata stream was closed by the Relay, the trace is no longer active: "
168 "trace-id={}, metadata-stream-id={}",
169 trace->id, metadata->stream_id);
4164020e
SM
170 /*
171 * The stream was closed and we received everything
172 * there was to receive for this metadata stream.
173 * We go on with the decoding of what we received. So
174 * that data stream can be decoded.
175 */
176 keep_receiving = false;
177 trace->metadata_stream_state = LTTNG_LIVE_METADATA_STREAM_STATE_CLOSED;
178 break;
179 case LTTNG_LIVE_GET_ONE_METADATA_STATUS_ERROR:
0f5c5d5c
SM
180 BT_CPPLOGE_APPEND_CAUSE_SPEC(metadata->logger,
181 "Error getting one trace metadata packet: trace-id={}",
182 trace->id);
4164020e
SM
183 goto error;
184 default:
185 bt_common_abort();
186 }
187 }
188
189 /* The memory buffer `metadata_buf` contains all the metadata. */
190 if (bt_close_memstream(&metadata_buf, &size, fp)) {
0f5c5d5c 191 BT_CPPLOGW_ERRNO_SPEC(metadata->logger, "Metadata bt_close_memstream", ".");
4164020e
SM
192 }
193
194 fp = NULL;
195
196 if (len_read == 0) {
197 if (!trace->trace) {
198 status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
199 goto end;
200 }
201
e7401568 202 /* The relay sent zero bytes of metadata. */
4164020e
SM
203 trace->metadata_stream_state = LTTNG_LIVE_METADATA_STREAM_STATE_NOT_NEEDED;
204 goto end;
205 }
206
207 /*
208 * Open a new reading file handle on the `metadata_buf` and pass it to
209 * the metadata decoder.
210 */
211 fp = bt_fmemopen(metadata_buf, len_read, "rb");
212 if (!fp) {
213 if (errno == EINTR && lttng_live_graph_is_canceled(session->lttng_live_msg_iter)) {
214 session->lttng_live_msg_iter->was_interrupted = true;
215 status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
216 } else {
0f5c5d5c
SM
217 BT_CPPLOGE_ERRNO_APPEND_CAUSE_SPEC(metadata->logger,
218 "Cannot memory-open metadata buffer", ".");
4164020e
SM
219 status = LTTNG_LIVE_ITERATOR_STATUS_ERROR;
220 }
221 goto end;
222 }
223
224 /*
225 * The call to ctf_metadata_decoder_append_content() will append
226 * new metadata to our current trace class.
227 */
0f5c5d5c 228 BT_CPPLOGD_SPEC(metadata->logger, "Appending new metadata to the ctf_trace class");
1fa280c9 229 decoder_status = ctf_metadata_decoder_append_content(metadata->decoder.get(), fp);
4164020e
SM
230 switch (decoder_status) {
231 case CTF_METADATA_DECODER_STATUS_OK:
232 if (!trace->trace_class) {
233 struct ctf_trace_class *tc =
1fa280c9 234 ctf_metadata_decoder_borrow_ctf_trace_class(metadata->decoder.get());
4164020e 235
70923576
SM
236 trace->trace_class = ctf_metadata_decoder_get_ir_trace_class(metadata->decoder.get())
237 .release()
238 .libObjPtr();
4164020e
SM
239 trace->trace = bt_trace_create(trace->trace_class);
240 if (!trace->trace) {
0f5c5d5c 241 BT_CPPLOGE_APPEND_CAUSE_SPEC(metadata->logger, "Failed to create bt_trace");
4164020e
SM
242 goto error;
243 }
244 if (ctf_trace_class_configure_ir_trace(tc, trace->trace)) {
0f5c5d5c
SM
245 BT_CPPLOGE_APPEND_CAUSE_SPEC(metadata->logger,
246 "Failed to configure ctf trace class");
4164020e
SM
247 goto error;
248 }
0f5c5d5c
SM
249 if (!stream_classes_all_have_default_clock_class(trace->trace_class,
250 metadata->logger)) {
4164020e
SM
251 /* Error logged in function. */
252 goto error;
253 }
254 trace->clock_class = borrow_any_clock_class(trace->trace_class);
255 }
256
e7401568 257 /* The metadata was updated successfully. */
4164020e
SM
258 trace->metadata_stream_state = LTTNG_LIVE_METADATA_STREAM_STATE_NOT_NEEDED;
259
260 break;
261 default:
262 goto error;
263 }
264
265 goto end;
c28512ab 266
7cdc2bab 267error:
4164020e 268 status = LTTNG_LIVE_ITERATOR_STATUS_ERROR;
7cdc2bab 269end:
4164020e
SM
270 if (fp) {
271 int closeret;
272
273 closeret = fclose(fp);
274 if (closeret) {
0f5c5d5c 275 BT_CPPLOGW_ERRNO_SPEC(metadata->logger, "Error on fclose", ".");
4164020e
SM
276 }
277 }
278 free(metadata_buf);
279 return status;
7cdc2bab
MD
280}
281
4164020e 282int lttng_live_metadata_create_stream(struct lttng_live_session *session, uint64_t ctf_trace_id,
44bd6303 283 uint64_t stream_id)
7cdc2bab 284{
4164020e
SM
285 struct lttng_live_trace *trace;
286
0f5c5d5c 287 ctf_metadata_decoder_config cfg {session->logger};
4164020e 288 cfg.self_comp = session->self_comp;
4164020e
SM
289 cfg.create_trace_class = true;
290
0f5c5d5c 291 lttng_live_metadata *metadata = new lttng_live_metadata {session->logger};
4164020e
SM
292 metadata->stream_id = stream_id;
293
294 metadata->decoder = ctf_metadata_decoder_create(&cfg);
295 if (!metadata->decoder) {
0f5c5d5c 296 BT_CPPLOGE_APPEND_CAUSE_SPEC(session->logger, "Failed to create CTF metadata decoder");
4164020e
SM
297 goto error;
298 }
299 trace = lttng_live_session_borrow_or_create_trace_by_id(session, ctf_trace_id);
300 if (!trace) {
0f5c5d5c 301 BT_CPPLOGE_APPEND_CAUSE_SPEC(session->logger, "Failed to borrow trace");
4164020e
SM
302 goto error;
303 }
304 trace->metadata = metadata;
305 return 0;
7cdc2bab
MD
306
307error:
afb0f12b 308 delete metadata;
4164020e 309 return -1;
7cdc2bab
MD
310}
311
7cdc2bab
MD
312void lttng_live_metadata_fini(struct lttng_live_trace *trace)
313{
4164020e
SM
314 struct lttng_live_metadata *metadata = trace->metadata;
315
316 if (!metadata) {
317 return;
318 }
4164020e 319 trace->metadata = NULL;
afb0f12b 320 delete metadata;
7cdc2bab 321}
This page took 0.111935 seconds and 4 git commands to generate.