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