Remove Babeltrace 1 files and reorganize the tree
[babeltrace.git] / plugins / ctf / fs / fs.c
CommitLineData
7a278c8e 1/*
ea0b4b9e 2 * fs.c
7a278c8e 3 *
ea0b4b9e 4 * Babeltrace CTF file system Reader Component
7a278c8e 5 *
f3bc2010 6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7a278c8e
JG
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
5b29e799 29#include <babeltrace/ctf-ir/packet.h>
ac0c6bdd 30#include <babeltrace/ctf-ir/clock-class.h>
4f1f88a6 31#include <babeltrace/graph/private-port.h>
b2e0c907 32#include <babeltrace/graph/private-component.h>
4f1f88a6
PP
33#include <babeltrace/graph/private-component-source.h>
34#include <babeltrace/graph/private-notification-iterator.h>
b2e0c907
PP
35#include <babeltrace/graph/component.h>
36#include <babeltrace/graph/notification-iterator.h>
7d61fa8e 37#include <plugins-common.h>
ea0b4b9e
JG
38#include <glib.h>
39#include <assert.h>
56a1cced
JG
40#include <unistd.h>
41#include "fs.h"
413bc2c4
JG
42#include "metadata.h"
43#include "data-stream.h"
e7a4393b
JG
44#include "file.h"
45
46#define PRINT_ERR_STREAM ctf_fs->error_fp
47#define PRINT_PREFIX "ctf-fs"
48#include "print.h"
33f93973 49#define METADATA_TEXT_SIG "/* CTF 1.8"
ea0b4b9e 50
78bb6992
MD
51BT_HIDDEN
52bool ctf_fs_debug;
ea0b4b9e 53
41a2b7ae 54struct bt_notification_iterator_next_return ctf_fs_iterator_next(
4f1f88a6 55 struct bt_private_notification_iterator *iterator)
ea0b4b9e 56{
4f1f88a6
PP
57 struct ctf_fs_stream *fs_stream =
58 bt_private_notification_iterator_get_user_data(iterator);
d01e0f33 59
4f1f88a6 60 return ctf_fs_stream_next(fs_stream);
ea0b4b9e 61}
bfd20a42 62
4f1f88a6 63void ctf_fs_iterator_finalize(struct bt_private_notification_iterator *it)
760051fa 64{
4f1f88a6
PP
65 void *ctf_fs_stream =
66 bt_private_notification_iterator_get_user_data(it);
760051fa 67
4f1f88a6 68 ctf_fs_stream_destroy(ctf_fs_stream);
760051fa
JG
69}
70
4f1f88a6
PP
71enum bt_notification_iterator_status ctf_fs_iterator_init(
72 struct bt_private_notification_iterator *it,
73 struct bt_private_port *port)
4c1456f0 74{
4f1f88a6
PP
75 struct ctf_fs_stream *stream = NULL;
76 struct ctf_fs_component *ctf_fs;
77 struct ctf_fs_port_data *port_data;
78 struct bt_private_component *priv_comp =
79 bt_private_notification_iterator_get_private_component(it);
80 enum bt_notification_iterator_status ret =
81 BT_NOTIFICATION_ITERATOR_STATUS_OK;
760051fa 82
4f1f88a6 83 assert(priv_comp);
5b29e799 84
4f1f88a6
PP
85 ctf_fs = bt_private_component_get_user_data(priv_comp);
86 if (!ctf_fs) {
87 ret = BT_NOTIFICATION_ITERATOR_STATUS_INVAL;
88 goto error;
760051fa
JG
89 }
90
4f1f88a6
PP
91 port_data = bt_private_port_get_user_data(port);
92 if (!port_data) {
93 ret = BT_NOTIFICATION_ITERATOR_STATUS_INVAL;
94 goto error;
95 }
5b29e799 96
4f1f88a6 97 stream = ctf_fs_stream_create(ctf_fs, port_data->path->str);
5b29e799 98 if (!stream) {
4f1f88a6 99 goto error;
760051fa
JG
100 }
101
4f1f88a6
PP
102 ret = bt_private_notification_iterator_set_user_data(it, stream);
103 if (ret) {
104 goto error;
760051fa
JG
105 }
106
4f1f88a6
PP
107 stream = NULL;
108 goto end;
5b29e799 109
4f1f88a6
PP
110error:
111 (void) bt_private_notification_iterator_set_user_data(it, NULL);
112
113 if (ret == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
114 ret = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
760051fa 115 }
5b29e799 116
760051fa 117end:
4f1f88a6
PP
118 ctf_fs_stream_destroy(stream);
119 bt_put(priv_comp);
760051fa
JG
120 return ret;
121}
122
760051fa 123static
4f1f88a6 124void ctf_fs_destroy_data(struct ctf_fs_component *ctf_fs)
760051fa 125{
4f1f88a6 126 if (!ctf_fs) {
8fa760ba
JG
127 return;
128 }
4f1f88a6
PP
129
130 if (ctf_fs->trace_path) {
131 g_string_free(ctf_fs->trace_path, TRUE);
56a1cced 132 }
4f1f88a6
PP
133
134 if (ctf_fs->port_data) {
135 g_ptr_array_free(ctf_fs->port_data, TRUE);
c14d7e26 136 }
760051fa 137
4f1f88a6
PP
138 if (ctf_fs->metadata) {
139 ctf_fs_metadata_fini(ctf_fs->metadata);
140 g_free(ctf_fs->metadata);
141 }
760051fa 142
4f1f88a6 143 g_free(ctf_fs);
4c1456f0
JG
144}
145
4f1f88a6 146void ctf_fs_finalize(struct bt_private_component *component)
a4792757 147{
4f1f88a6
PP
148 void *data = bt_private_component_get_user_data(component);
149
150 ctf_fs_destroy_data(data);
a4792757
JG
151}
152
e7a4393b 153static
4f1f88a6
PP
154void port_data_destroy(void *data) {
155 struct ctf_fs_port_data *port_data = data;
156
157 if (!port_data) {
158 return;
159 }
160
161 if (port_data->path) {
162 g_string_free(port_data->path, TRUE);
163 }
164
165 g_free(port_data);
5b29e799
JG
166}
167
168static
4f1f88a6
PP
169int create_one_port(struct ctf_fs_component *ctf_fs,
170 const char *stream_basename, const char *stream_path)
5b29e799 171{
4f1f88a6
PP
172 int ret = 0;
173 struct bt_private_port *port = NULL;
174 struct ctf_fs_port_data *port_data = NULL;
175 GString *port_name = NULL;
176
177 port_name = g_string_new(NULL);
178 if (!port_name) {
179 goto error;
180 }
181
182 /* Assign the name for the new output port */
183 g_string_assign(port_name, "");
184 g_string_printf(port_name, "trace0-stream-%s", stream_basename);
185 PDBG("Creating one port named `%s` associated with path `%s`\n",
186 port_name->str, stream_path);
187
188 /* Create output port for this file */
189 port = bt_private_component_source_add_output_private_port(
190 ctf_fs->priv_comp, port_name->str);
191 if (!port) {
192 goto error;
193 }
194
195 port_data = g_new0(struct ctf_fs_port_data, 1);
196 if (!port_data) {
197 goto error;
198 }
199
200 port_data->path = g_string_new(stream_path);
201 if (!port_data->path) {
202 goto error;
203 }
204
205 ret = bt_private_port_set_user_data(port, port_data);
206 if (ret) {
207 goto error;
208 }
209
210 g_ptr_array_add(ctf_fs->port_data, port_data);
211 port_data = NULL;
212 goto end;
213
214error:
215 ret = -1;
216
217end:
218 if (port_name) {
219 g_string_free(port_name, TRUE);
220 }
221
222 bt_put(port);
223 port_data_destroy(port_data);
224 return ret;
5b29e799
JG
225}
226
227static
4f1f88a6 228int create_ports(struct ctf_fs_component *ctf_fs)
e7a4393b
JG
229{
230 int ret = 0;
4f1f88a6 231 const char *basename;
e7a4393b 232 GError *error = NULL;
4f1f88a6
PP
233 GDir *dir = NULL;
234 struct bt_private_port *def_port;
235 struct ctf_fs_file *file = NULL;
e7a4393b 236
4f1f88a6
PP
237 /* Remove default port if needed */
238 def_port = bt_private_component_source_get_default_output_private_port(
239 ctf_fs->priv_comp);
240 if (def_port) {
241 bt_private_port_remove_from_component(def_port);
242 bt_put(def_port);
243 }
244
245 /* Create one output port for each stream file */
246 dir = g_dir_open(ctf_fs->trace_path->str, 0, &error);
e7a4393b 247 if (!dir) {
4f1f88a6
PP
248 PERR("Cannot open directory `%s`: %s (code %d)\n",
249 ctf_fs->trace_path->str, error->message,
250 error->code);
e7a4393b
JG
251 goto error;
252 }
253
4f1f88a6
PP
254 while ((basename = g_dir_read_name(dir))) {
255 if (!strcmp(basename, CTF_FS_METADATA_FILENAME)) {
e7a4393b 256 /* Ignore the metadata stream. */
4f1f88a6 257 PDBG("Ignoring metadata file `%s`\n", basename);
e7a4393b
JG
258 continue;
259 }
260
4f1f88a6
PP
261 if (basename[0] == '.') {
262 PDBG("Ignoring hidden file `%s`\n", basename);
e7a4393b
JG
263 continue;
264 }
265
266 /* Create the file. */
267 file = ctf_fs_file_create(ctf_fs);
268 if (!file) {
4f1f88a6
PP
269 PERR("Cannot create stream file object for file `%s`\n",
270 basename);
e7a4393b
JG
271 goto error;
272 }
273
274 /* Create full path string. */
275 g_string_append_printf(file->path, "%s/%s",
4f1f88a6 276 ctf_fs->trace_path->str, basename);
e7a4393b 277 if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) {
4f1f88a6 278 PDBG("Ignoring non-regular file `%s`\n", basename);
e7a4393b 279 ctf_fs_file_destroy(file);
4f1f88a6 280 file = NULL;
e7a4393b
JG
281 continue;
282 }
283
4f1f88a6
PP
284 ret = ctf_fs_file_open(ctf_fs, file, "rb");
285 if (ret) {
286 PERR("Cannot open stream file `%s`\n", basename);
e7a4393b
JG
287 goto error;
288 }
289
9fa0891a
JG
290 if (file->size == 0) {
291 /* Skip empty stream. */
4f1f88a6 292 PDBG("Ignoring empty file `%s`\n", basename);
9fa0891a 293 ctf_fs_file_destroy(file);
4f1f88a6 294 file = NULL;
9fa0891a
JG
295 continue;
296 }
297
4f1f88a6
PP
298 ret = create_one_port(ctf_fs, basename, file->path->str);
299 if (ret) {
300 PERR("Cannot create output port for file `%s`\n",
301 basename);
e7a4393b
JG
302 goto error;
303 }
304
4f1f88a6
PP
305 ctf_fs_file_destroy(file);
306 file = NULL;
e7a4393b
JG
307 }
308
309 goto end;
4f1f88a6 310
e7a4393b
JG
311error:
312 ret = -1;
4f1f88a6 313
e7a4393b
JG
314end:
315 if (dir) {
316 g_dir_close(dir);
317 dir = NULL;
318 }
4f1f88a6 319
e7a4393b
JG
320 if (error) {
321 g_error_free(error);
322 }
5b29e799 323
4f1f88a6 324 ctf_fs_file_destroy(file);
91457551 325 return ret;
5b29e799
JG
326}
327
328static
4f1f88a6
PP
329struct ctf_fs_component *ctf_fs_create(struct bt_private_component *priv_comp,
330 struct bt_value *params)
56a1cced
JG
331{
332 struct ctf_fs_component *ctf_fs;
1ef09eb5 333 struct bt_value *value = NULL;
56a1cced 334 const char *path;
4f1f88a6 335 int ret;
56a1cced
JG
336
337 ctf_fs = g_new0(struct ctf_fs_component, 1);
338 if (!ctf_fs) {
339 goto end;
340 }
341
4f1f88a6
PP
342 /*
343 * We don't need to get a new reference here because as long as
344 * our private ctf_fs_component object exists, the containing
345 * private component should also exist.
346 */
347 ctf_fs->priv_comp = priv_comp;
348
56a1cced
JG
349 /* FIXME: should probably look for a source URI */
350 value = bt_value_map_get(params, "path");
351 if (!value || bt_value_is_null(value) || !bt_value_is_string(value)) {
352 goto error;
353 }
354
355 ret = bt_value_string_get(value, &path);
4f1f88a6
PP
356 if (ret) {
357 goto error;
358 }
359
360 ctf_fs->port_data = g_ptr_array_new_with_free_func(port_data_destroy);
361 if (!ctf_fs->port_data) {
56a1cced
JG
362 goto error;
363 }
364
365 ctf_fs->trace_path = g_string_new(path);
366 if (!ctf_fs->trace_path) {
367 goto error;
368 }
56a1cced
JG
369 ctf_fs->error_fp = stderr;
370 ctf_fs->page_size = (size_t) getpagesize();
e7a4393b
JG
371
372 // FIXME: check error.
5b29e799
JG
373 ctf_fs->metadata = g_new0(struct ctf_fs_metadata, 1);
374 if (!ctf_fs->metadata) {
e7a4393b
JG
375 goto error;
376 }
4f1f88a6
PP
377
378 ret = ctf_fs_metadata_set_trace(ctf_fs);
379 if (ret) {
380 goto error;
381 }
382
383 ret = create_ports(ctf_fs);
384 if (ret) {
385 goto error;
386 }
387
1ef09eb5
JG
388 goto end;
389
56a1cced
JG
390error:
391 ctf_fs_destroy_data(ctf_fs);
e7a4393b 392 ctf_fs = NULL;
1ef09eb5
JG
393end:
394 BT_PUT(value);
56a1cced
JG
395 return ctf_fs;
396}
397
ea0b4b9e 398BT_HIDDEN
4f1f88a6 399enum bt_component_status ctf_fs_init(struct bt_private_component *priv_comp,
7d61fa8e 400 struct bt_value *params, UNUSED_VAR void *init_method_data)
ea0b4b9e
JG
401{
402 struct ctf_fs_component *ctf_fs;
403 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
404
4f1f88a6 405 assert(priv_comp);
ea0b4b9e 406 ctf_fs_debug = g_strcmp0(getenv("CTF_FS_DEBUG"), "1") == 0;
4f1f88a6 407 ctf_fs = ctf_fs_create(priv_comp, params);
ea0b4b9e
JG
408 if (!ctf_fs) {
409 ret = BT_COMPONENT_STATUS_NOMEM;
410 goto end;
411 }
4c1456f0 412
4f1f88a6 413 ret = bt_private_component_set_user_data(priv_comp, ctf_fs);
ea0b4b9e
JG
414 if (ret != BT_COMPONENT_STATUS_OK) {
415 goto error;
416 }
ea0b4b9e
JG
417end:
418 return ret;
419error:
4f1f88a6 420 (void) bt_private_component_set_user_data(priv_comp, NULL);
760051fa 421 ctf_fs_destroy_data(ctf_fs);
ea0b4b9e
JG
422 return ret;
423}
33f93973
PP
424
425BT_HIDDEN
a67681c1
PP
426struct bt_value *ctf_fs_query(struct bt_component_class *comp_class,
427 const char *object, struct bt_value *params)
33f93973
PP
428{
429 struct bt_value *results = NULL;
430 struct bt_value *path_value = NULL;
431 char *metadata_text = NULL;
432 FILE *metadata_fp = NULL;
433 GString *g_metadata_text = NULL;
434
a67681c1 435 if (strcmp(object, "metadata-info") == 0) {
33f93973
PP
436 int ret;
437 int bo;
438 const char *path;
439 bool is_packetized;
440
441 results = bt_value_map_create();
442 if (!results) {
443 goto error;
444 }
445
446 if (!bt_value_is_map(params)) {
447 fprintf(stderr,
a67681c1 448 "Query parameters is not a map value object\n");
33f93973
PP
449 goto error;
450 }
451
452 path_value = bt_value_map_get(params, "path");
453 ret = bt_value_string_get(path_value, &path);
454 if (ret) {
455 fprintf(stderr,
456 "Cannot get `path` string parameter\n");
457 goto error;
458 }
459
460 assert(path);
461 metadata_fp = ctf_fs_metadata_open_file(path);
462 if (!metadata_fp) {
463 fprintf(stderr,
464 "Cannot open trace at path `%s`\n", path);
465 goto error;
466 }
467
468 is_packetized = ctf_metadata_is_packetized(metadata_fp, &bo);
469
470 if (is_packetized) {
471 ret = ctf_metadata_packetized_file_to_buf(NULL,
472 metadata_fp, (uint8_t **) &metadata_text, bo);
473 if (ret) {
474 fprintf(stderr,
475 "Cannot decode packetized metadata file\n");
476 goto error;
477 }
478 } else {
479 long filesize;
480
481 fseek(metadata_fp, 0, SEEK_END);
482 filesize = ftell(metadata_fp);
483 rewind(metadata_fp);
484 metadata_text = malloc(filesize + 1);
485 if (!metadata_text) {
486 fprintf(stderr,
487 "Cannot allocate buffer for metadata text\n");
488 goto error;
489 }
490
491 if (fread(metadata_text, filesize, 1, metadata_fp) !=
492 1) {
493 fprintf(stderr,
494 "Cannot read metadata file\n");
495 goto error;
496 }
497
498 metadata_text[filesize] = '\0';
499 }
500
501 g_metadata_text = g_string_new(NULL);
502 if (!g_metadata_text) {
503 goto error;
504 }
505
506 if (strncmp(metadata_text, METADATA_TEXT_SIG,
507 sizeof(METADATA_TEXT_SIG) - 1) != 0) {
508 g_string_assign(g_metadata_text, METADATA_TEXT_SIG);
509 g_string_append(g_metadata_text, " */\n\n");
510 }
511
512 g_string_append(g_metadata_text, metadata_text);
513
514 ret = bt_value_map_insert_string(results, "text",
515 g_metadata_text->str);
516 if (ret) {
517 fprintf(stderr, "Cannot insert metadata text into results\n");
518 goto error;
519 }
520
521 ret = bt_value_map_insert_bool(results, "is-packetized",
522 is_packetized);
523 if (ret) {
524 fprintf(stderr, "Cannot insert is packetized into results\n");
525 goto error;
526 }
527 } else {
a67681c1 528 fprintf(stderr, "Unknown query object `%s`\n", object);
33f93973
PP
529 goto error;
530 }
531
532 goto end;
533
534error:
535 BT_PUT(results);
536
537end:
538 bt_put(path_value);
539 free(metadata_text);
540
541 if (g_metadata_text) {
542 g_string_free(g_metadata_text, TRUE);
543 }
544
545 if (metadata_fp) {
546 fclose(metadata_fp);
547 }
548 return results;
549}
This page took 0.055092 seconds and 4 git commands to generate.