Implement ctf.lttng-live component
[babeltrace.git] / plugins / ctf / lttng-live / metadata.c
1 /*
2 * Copyright 2016 - Philippe Proulx <pproulx@efficios.com>
3 * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation
4 *
5 * Some functions are based on older functions written by Mathieu Desnoyers.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26 #include <stdio.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <stdbool.h>
30 #include <glib.h>
31 #include <babeltrace/compat/uuid-internal.h>
32 #include <babeltrace/compat/memstream-internal.h>
33
34 #define PRINT_ERR_STREAM lttng_live->error_fp
35 #define PRINT_PREFIX "lttng-live-metadata"
36 #define PRINT_DBG_CHECK lttng_live_debug
37 #include "../print.h"
38
39 #include "metadata.h"
40 #include "../common/metadata/decoder.h"
41
42 #define TSDL_MAGIC 0x75d11d57
43
44 struct packet_header {
45 uint32_t magic;
46 uint8_t uuid[16];
47 uint32_t checksum;
48 uint32_t content_size;
49 uint32_t packet_size;
50 uint8_t compression_scheme;
51 uint8_t encryption_scheme;
52 uint8_t checksum_scheme;
53 uint8_t major;
54 uint8_t minor;
55 } __attribute__((__packed__));
56
57 static
58 enum bt_ctf_lttng_live_iterator_status lttng_live_update_clock_map(
59 struct lttng_live_trace *trace)
60 {
61 enum bt_ctf_lttng_live_iterator_status status =
62 BT_CTF_LTTNG_LIVE_ITERATOR_STATUS_OK;
63 size_t i;
64 int count, ret;
65
66 BT_PUT(trace->cc_prio_map);
67 trace->cc_prio_map = bt_clock_class_priority_map_create();
68 if (!trace->cc_prio_map) {
69 goto error;
70 }
71
72 count = bt_ctf_trace_get_clock_class_count(trace->trace);
73 assert(count >= 0);
74
75 for (i = 0; i < count; i++) {
76 struct bt_ctf_clock_class *clock_class =
77 bt_ctf_trace_get_clock_class_by_index(trace->trace, i);
78
79 assert(clock_class);
80 ret = bt_clock_class_priority_map_add_clock_class(
81 trace->cc_prio_map, clock_class, 0);
82 BT_PUT(clock_class);
83
84 if (ret) {
85 goto error;
86 }
87 }
88
89 goto end;
90 error:
91 status = BT_CTF_LTTNG_LIVE_ITERATOR_STATUS_ERROR;
92 end:
93 return status;
94 }
95
96 BT_HIDDEN
97 enum bt_ctf_lttng_live_iterator_status lttng_live_metadata_update(
98 struct lttng_live_trace *trace)
99 {
100 struct lttng_live_session *session = trace->session;
101 struct lttng_live_component *lttng_live = session->lttng_live;
102 struct lttng_live_metadata *metadata = trace->metadata;
103 ssize_t ret = 0;
104 size_t size, len_read = 0;
105 char *metadata_buf = NULL;
106 FILE *fp = NULL;
107 enum ctf_metadata_decoder_status decoder_status;
108 enum bt_ctf_lttng_live_iterator_status status =
109 BT_CTF_LTTNG_LIVE_ITERATOR_STATUS_OK;
110
111 /* No metadata stream yet. */
112 if (!metadata) {
113 if (session->new_streams_needed) {
114 status = BT_CTF_LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
115 } else {
116 session->new_streams_needed = true;
117 status = BT_CTF_LTTNG_LIVE_ITERATOR_STATUS_CONTINUE;
118 }
119 goto end;
120 }
121
122 if (!trace->new_metadata_needed) {
123 goto end;
124 }
125
126 /* Open for writing */
127 fp = bt_open_memstream(&metadata_buf, &size);
128 if (!fp) {
129 PERR("Metadata open_memstream: %s\n", strerror(errno));
130 goto error;
131 }
132
133 /* Grab all available metadata. */
134 do {
135 /*
136 * get_one_metadata_packet returns the number of bytes
137 * received, 0 when we have received everything, a
138 * negative value on error.
139 */
140 ret = lttng_live_get_one_metadata_packet(trace, fp);
141 if (ret > 0) {
142 len_read += ret;
143 }
144 } while (ret > 0);
145
146 /*
147 * Consider metadata closed as soon as we get an error reading
148 * it (e.g. cannot be found).
149 */
150 if (ret < 0) {
151 if (!metadata->closed) {
152 metadata->closed = true;
153 /*
154 * Release our reference on the trace as soon as
155 * we know the metadata stream is not available
156 * anymore. This won't necessarily teardown the
157 * metadata objects immediately, but only when
158 * the data streams are done.
159 */
160 lttng_live_unref_trace(metadata->trace);
161 }
162 }
163
164 if (bt_close_memstream(&metadata_buf, &size, fp)) {
165 BT_LOGE("bt_close_memstream: %s", strerror(errno));
166 }
167 ret = 0;
168 fp = NULL;
169
170 if (len_read == 0) {
171 if (!trace->trace) {
172 status = BT_CTF_LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
173 goto end;
174 }
175 trace->new_metadata_needed = false;
176 goto end;
177 }
178
179 if (babeltrace_debug) {
180 // yydebug = 1;
181 }
182
183 fp = bt_fmemopen(metadata_buf, len_read, "rb");
184 if (!fp) {
185 PERR("Cannot memory-open metadata buffer: %s\n",
186 strerror(errno));
187 goto error;
188 }
189
190 decoder_status = ctf_metadata_decoder_decode(metadata->decoder, fp);
191 switch (decoder_status) {
192 case CTF_METADATA_DECODER_STATUS_OK:
193 BT_PUT(trace->trace);
194 trace->trace = ctf_metadata_decoder_get_trace(metadata->decoder);
195 trace->new_metadata_needed = false;
196 status = lttng_live_update_clock_map(trace);
197 if (status != BT_CTF_LTTNG_LIVE_ITERATOR_STATUS_OK) {
198 goto end;
199 }
200 break;
201 case CTF_METADATA_DECODER_STATUS_INCOMPLETE:
202 status = BT_CTF_LTTNG_LIVE_ITERATOR_STATUS_AGAIN;
203 break;
204 case CTF_METADATA_DECODER_STATUS_ERROR:
205 case CTF_METADATA_DECODER_STATUS_INVAL_VERSION:
206 case CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR:
207 goto error;
208 }
209
210 goto end;
211 error:
212 status = BT_CTF_LTTNG_LIVE_ITERATOR_STATUS_ERROR;
213 end:
214 if (fp) {
215 int closeret;
216
217 closeret = fclose(fp);
218 if (closeret) {
219 PERR("Error on fclose");
220 }
221 }
222 return status;
223 }
224
225 BT_HIDDEN
226 int lttng_live_metadata_create_stream(struct lttng_live_session *session,
227 uint64_t ctf_trace_id,
228 uint64_t stream_id)
229 {
230 struct lttng_live_metadata *metadata = NULL;
231 struct lttng_live_trace *trace;
232
233 metadata = g_new0(struct lttng_live_metadata, 1);
234 if (!metadata) {
235 return -1;
236 }
237 metadata->stream_id = stream_id;
238 //TODO: add clock offset option
239 metadata->decoder = ctf_metadata_decoder_create(
240 session->lttng_live->error_fp, 0);
241 if (!metadata->decoder) {
242 goto error;
243 }
244 trace = lttng_live_ref_trace(session, ctf_trace_id);
245 if (!trace) {
246 goto error;
247 }
248 metadata->trace = trace;
249 trace->metadata = metadata;
250 return 0;
251
252 error:
253 ctf_metadata_decoder_destroy(metadata->decoder);
254 g_free(metadata);
255 return -1;
256 }
257
258 BT_HIDDEN
259 void lttng_live_metadata_fini(struct lttng_live_trace *trace)
260 {
261 struct lttng_live_metadata *metadata = trace->metadata;
262
263 if (!metadata) {
264 return;
265 }
266 if (metadata->text) {
267 free(metadata->text);
268 }
269 ctf_metadata_decoder_destroy(metadata->decoder);
270 trace->metadata = NULL;
271 lttng_live_unref_trace(trace);
272 if (!metadata->closed) {
273 lttng_live_unref_trace(metadata->trace);
274 }
275 g_free(metadata);
276 }
This page took 0.035119 seconds and 4 git commands to generate.