Fix: uninitialized variable
[babeltrace.git] / plugins / ctf / fs-src / query.c
CommitLineData
04c0ba87
JG
1/*
2 * query.c
3 *
4 * Babeltrace CTF file system Reader Component queries
5 *
6 * Copyright 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27#include "query.h"
28#include <stdbool.h>
29#include <assert.h>
30#include "metadata.h"
31#include "../common/metadata/decoder.h"
55314f2a 32#include <babeltrace/common-internal.h>
97ade20b
JG
33#include <babeltrace/babeltrace-internal.h>
34#include <babeltrace/ctf-ir/stream.h>
35#include "fs.h"
55314f2a
JG
36
37#define BT_LOG_TAG "PLUGIN-CTF-FS-QUERY-SRC"
38#include "logging.h"
04c0ba87
JG
39
40#define METADATA_TEXT_SIG "/* CTF 1.8"
41
97ade20b
JG
42struct range {
43 int64_t begin_ns;
44 int64_t end_ns;
45 bool set;
46};
47
04c0ba87
JG
48BT_HIDDEN
49struct bt_value *metadata_info_query(struct bt_component_class *comp_class,
50 struct bt_value *params)
51{
97ade20b 52 struct bt_value *result = NULL;
04c0ba87
JG
53 struct bt_value *path_value = NULL;
54 char *metadata_text = NULL;
55 FILE *metadata_fp = NULL;
56 GString *g_metadata_text = NULL;
57 int ret;
58 int bo;
59 const char *path;
60 bool is_packetized;
61
97ade20b
JG
62 result = bt_value_map_create();
63 if (!result) {
04c0ba87
JG
64 goto error;
65 }
66
67 if (!bt_value_is_map(params)) {
68 fprintf(stderr,
69 "Query parameters is not a map value object\n");
70 goto error;
71 }
72
73 path_value = bt_value_map_get(params, "path");
74 ret = bt_value_string_get(path_value, &path);
75 if (ret) {
76 fprintf(stderr,
77 "Cannot get `path` string parameter\n");
78 goto error;
79 }
80
81 assert(path);
82 metadata_fp = ctf_fs_metadata_open_file(path);
83 if (!metadata_fp) {
84 fprintf(stderr,
85 "Cannot open trace at path `%s`\n", path);
86 goto error;
87 }
88
89 is_packetized = ctf_metadata_decoder_is_packetized(metadata_fp,
90 &bo);
91
92 if (is_packetized) {
93 ret = ctf_metadata_decoder_packetized_file_stream_to_buf(
94 metadata_fp, &metadata_text, bo);
95 if (ret) {
96 fprintf(stderr,
97 "Cannot decode packetized metadata file\n");
98 goto error;
99 }
100 } else {
101 long filesize;
102
103 fseek(metadata_fp, 0, SEEK_END);
104 filesize = ftell(metadata_fp);
105 rewind(metadata_fp);
106 metadata_text = malloc(filesize + 1);
107 if (!metadata_text) {
108 fprintf(stderr,
109 "Cannot allocate buffer for metadata text\n");
110 goto error;
111 }
112
113 if (fread(metadata_text, filesize, 1, metadata_fp) != 1) {
114 fprintf(stderr,
115 "Cannot read metadata file\n");
116 goto error;
117 }
118
119 metadata_text[filesize] = '\0';
120 }
121
122 g_metadata_text = g_string_new(NULL);
123 if (!g_metadata_text) {
124 goto error;
125 }
126
127 if (strncmp(metadata_text, METADATA_TEXT_SIG,
128 sizeof(METADATA_TEXT_SIG) - 1) != 0) {
129 g_string_assign(g_metadata_text, METADATA_TEXT_SIG);
130 g_string_append(g_metadata_text, " */\n\n");
131 }
132
133 g_string_append(g_metadata_text, metadata_text);
134
97ade20b 135 ret = bt_value_map_insert_string(result, "text",
04c0ba87
JG
136 g_metadata_text->str);
137 if (ret) {
97ade20b 138 fprintf(stderr, "Cannot insert metadata text into result\n");
04c0ba87
JG
139 goto error;
140 }
141
97ade20b 142 ret = bt_value_map_insert_bool(result, "is-packetized",
04c0ba87
JG
143 is_packetized);
144 if (ret) {
97ade20b 145 fprintf(stderr, "Cannot insert is packetized into result\n");
04c0ba87
JG
146 goto error;
147 }
148
149 goto end;
150
151error:
97ade20b 152 BT_PUT(result);
04c0ba87
JG
153
154end:
155 bt_put(path_value);
156 free(metadata_text);
157
158 if (g_metadata_text) {
159 g_string_free(g_metadata_text, TRUE);
160 }
161
162 if (metadata_fp) {
163 fclose(metadata_fp);
164 }
97ade20b
JG
165 return result;
166}
167static
168int add_range(struct bt_value *info, struct range *range,
169 const char *range_name)
170{
171 int ret = 0;
172 enum bt_value_status status;
173 struct bt_value *range_map = NULL;
174
175 if (!range->set) {
176 /* Not an error. */
177 goto end;
178 }
179
180 range_map = bt_value_map_create();
181 if (!range_map) {
182 ret = -1;
183 goto end;
184 }
185
186 status = bt_value_map_insert_integer(range_map, "begin",
187 range->begin_ns);
188 if (status != BT_VALUE_STATUS_OK) {
189 ret = -1;
190 goto end;
191 }
192
193 status = bt_value_map_insert_integer(range_map, "end",
194 range->end_ns);
195 if (status != BT_VALUE_STATUS_OK) {
196 ret = -1;
197 goto end;
198 }
199
200 status = bt_value_map_insert(info, range_name, range_map);
201 if (status != BT_VALUE_STATUS_OK) {
202 ret = -1;
203 goto end;
204 }
205end:
206 bt_put(range_map);
207 return ret;
208}
209
210static
211int add_stream_ids(struct bt_value *info, struct bt_ctf_stream *stream)
212{
213 int ret = 0;
214 int64_t stream_class_id, stream_instance_id;
215 enum bt_value_status status;
256eb8a0 216 struct bt_ctf_stream_class *stream_class = NULL;
97ade20b
JG
217
218 stream_instance_id = bt_ctf_stream_get_id(stream);
219 if (stream_instance_id != -1) {
220 status = bt_value_map_insert_integer(info, "id",
221 stream_instance_id);
222 if (status != BT_VALUE_STATUS_OK) {
223 ret = -1;
224 goto end;
225 }
226 }
227
228 stream_class = bt_ctf_stream_get_class(stream);
229 if (!stream_class) {
230 ret = -1;
231 goto end;
232 }
233
234 stream_class_id = bt_ctf_stream_class_get_id(stream_class);
235 if (stream_class_id == -1) {
236 ret = -1;
237 goto end;
238 }
239
240 status = bt_value_map_insert_integer(info, "class-id", stream_class_id);
241 if (status != BT_VALUE_STATUS_OK) {
242 ret = -1;
243 goto end;
244 }
245end:
246 bt_put(stream_class);
247 return ret;
248}
249
250static
251int populate_stream_info(struct ctf_fs_ds_file_group *group,
252 struct bt_value *group_info,
253 struct range *stream_range)
254{
255 int ret = 0;
256 size_t file_idx;
257 enum bt_value_status status;
258 struct bt_value *file_paths;
259
260 stream_range->begin_ns = INT64_MAX;
261 stream_range->end_ns = 0;
262
263 file_paths = bt_value_array_create();
264 if (!file_paths) {
265 ret = -1;
266 goto end;
267 }
268
269 for (file_idx = 0; file_idx < group->ds_file_infos->len; file_idx++) {
270 int64_t file_begin_epoch, file_end_epoch;
271 struct ctf_fs_ds_file_info *info =
272 g_ptr_array_index(group->ds_file_infos,
273 file_idx);
274
275 if (!info->index || info->index->entries->len == 0) {
276 BT_LOGW("Cannot determine range of unindexed stream file \'%s\'",
277 info->path->str);
278 ret = -1;
279 goto end;
280 }
281
282 status = bt_value_array_append_string(file_paths,
283 info->path->str);
284 if (status != BT_VALUE_STATUS_OK) {
285 ret = -1;
286 goto end;
287 }
288
289 /*
290 * file range is from timestamp_begin of the first entry to the
291 * timestamp_end of the last entry.
292 */
293 file_begin_epoch = ((struct ctf_fs_ds_index_entry *) &g_array_index(info->index->entries,
294 struct ctf_fs_ds_index_entry, 0))->timestamp_begin_ns;
295 file_end_epoch = ((struct ctf_fs_ds_index_entry *) &g_array_index(info->index->entries,
296 struct ctf_fs_ds_index_entry, info->index->entries->len - 1))->timestamp_end_ns;
297
298 stream_range->begin_ns = min(stream_range->begin_ns, file_begin_epoch);
299 stream_range->end_ns = max(stream_range->end_ns, file_end_epoch);
300 stream_range->set = true;
301 }
302
303 if (stream_range->set) {
304 ret = add_range(group_info, stream_range, "range-ns");
305 if (ret) {
306 goto end;
307 }
308 }
309
310 status = bt_value_map_insert(group_info, "paths", file_paths);
311 if (status != BT_VALUE_STATUS_OK) {
312 ret = -1;
313 goto end;
314 }
315
316 ret = add_stream_ids(group_info, group->stream);
317 if (ret) {
318 goto end;
319 }
320end:
321 bt_put(file_paths);
322 return ret;
323}
324
325static
326int populate_trace_info(const char *trace_path, const char *trace_name,
327 struct bt_value *trace_info)
328{
329 int ret = 0;
330 size_t group_idx;
331 struct ctf_fs_trace *trace = NULL;
332 enum bt_value_status status;
333 struct bt_value *file_groups;
334 struct range trace_range = {
335 .begin_ns = INT64_MAX,
336 .end_ns = 0,
337 .set = false,
338 };
339 struct range trace_intersection = {
340 .begin_ns = 0,
341 .end_ns = INT64_MAX,
342 .set = false,
343 };
344
345 file_groups = bt_value_array_create();
346 if (!file_groups) {
347 goto end;
348 }
349
350 status = bt_value_map_insert_string(trace_info, "name",
351 trace_name);
352 if (status != BT_VALUE_STATUS_OK) {
353 ret = -1;
354 goto end;
355 }
356 status = bt_value_map_insert_string(trace_info, "path",
357 trace_path);
358 if (status != BT_VALUE_STATUS_OK) {
359 ret = -1;
360 goto end;
361 }
362
363 trace = ctf_fs_trace_create(trace_path, trace_name, NULL);
364 if (!trace) {
365 BT_LOGE("Failed to create fs trace at \'%s\'", trace_path);
366 ret = -1;
367 goto end;
368 }
369
370 assert(trace->ds_file_groups);
371 /* Add trace range info only if it contains streams. */
372 if (trace->ds_file_groups->len == 0) {
373 ret = -1;
374 goto end;
375 }
376
377 /* Find range of all stream groups, and of the trace. */
378 for (group_idx = 0; group_idx < trace->ds_file_groups->len;
379 group_idx++) {
380 struct bt_value *group_info;
381 struct range group_range = { .set = false };
382 struct ctf_fs_ds_file_group *group = g_ptr_array_index(
383 trace->ds_file_groups, group_idx);
384
385 group_info = bt_value_map_create();
386 if (!group_info) {
387 ret = -1;
388 goto end;
389 }
390
391 ret = populate_stream_info(group, group_info, &group_range);
392 if (ret) {
393 bt_put(group_info);
394 goto end;
395 }
396
397 if (group_range.set) {
398 trace_range.begin_ns = min(trace_range.begin_ns,
399 group_range.begin_ns);
400 trace_range.end_ns = max(trace_range.end_ns,
401 group_range.end_ns);
402 trace_range.set = true;
403
404 trace_intersection.begin_ns = max(trace_intersection.begin_ns,
405 group_range.begin_ns);
406 trace_intersection.end_ns = min(trace_intersection.end_ns,
407 group_range.end_ns);
408 trace_intersection.set = true;
409 status = bt_value_array_append(file_groups, group_info);
410 bt_put(group_info);
411 if (status != BT_VALUE_STATUS_OK) {
412 goto end;
413 }
414 }
415 }
416
417 ret = add_range(trace_info, &trace_range, "range-ns");
418 if (ret) {
419 goto end;
420 }
421 ret = add_range(trace_info, &trace_intersection,
422 "intersection-range-ns");
423 if (ret) {
424 goto end;
425 }
426
427 status = bt_value_map_insert(trace_info, "streams", file_groups);
428 BT_PUT(file_groups);
429 if (status != BT_VALUE_STATUS_OK) {
430 ret = -1;
431 goto end;
432 }
433
434end:
435 bt_put(file_groups);
436 ctf_fs_trace_destroy(trace);
437 return ret;
438}
439
440BT_HIDDEN
441struct bt_value *trace_info_query(struct bt_component_class *comp_class,
442 struct bt_value *params)
443{
444 struct bt_value *trace_infos = NULL;
445 struct bt_value *path_value = NULL;
446 int ret = 0;
447 const char *path = NULL;
448 GList *trace_paths = NULL;
449 GList *trace_names = NULL;
450 GList *tp_node = NULL;
451 GList *tn_node = NULL;
452 GString *normalized_path = NULL;
453
454 if (!bt_value_is_map(params)) {
455 BT_LOGE("Query parameters is not a map value object.");
456 goto error;
457 }
458
459 path_value = bt_value_map_get(params, "path");
460 ret = bt_value_string_get(path_value, &path);
461 if (ret) {
462 BT_LOGE("Cannot get `path` string parameter.");
463 goto error;
464 }
465
466 normalized_path = bt_common_normalize_path(path, NULL);
467 if (!normalized_path) {
468 BT_LOGE("Failed to normalize path: `%s`.", path);
469 goto error;
470 }
471 assert(path);
472
473 ret = ctf_fs_find_traces(&trace_paths, normalized_path->str);
474 if (ret) {
475 goto error;
476 }
477
478 trace_names = ctf_fs_create_trace_names(trace_paths,
479 normalized_path->str);
480 if (!trace_names) {
481 BT_LOGE("Cannot create trace names from trace paths.");
482 goto error;
483 }
484
485 trace_infos = bt_value_array_create();
486 if (!trace_infos) {
487 goto error;
488 }
489
490 /* Iterates over both trace paths and names simultaneously. */
491 for (tp_node = trace_paths, tn_node = trace_names; tp_node;
492 tp_node = g_list_next(tp_node),
493 tn_node = g_list_next(tn_node)) {
494 GString *trace_path = tp_node->data;
495 GString *trace_name = tn_node->data;
496 enum bt_value_status status;
497 struct bt_value *trace_info;
498
499 trace_info = bt_value_map_create();
500 if (!trace_info) {
501 BT_LOGE("Failed to create trace info map.");
502 goto error;
503 }
504
505 ret = populate_trace_info(trace_path->str, trace_name->str,
506 trace_info);
507 if (ret) {
508 bt_put(trace_info);
509 goto error;
510 }
511
512 status = bt_value_array_append(trace_infos, trace_info);
513 bt_put(trace_info);
514 if (status != BT_VALUE_STATUS_OK) {
515 goto error;
516 }
517 }
518
519 goto end;
520
521error:
522 BT_PUT(trace_infos);
523end:
524 if (normalized_path) {
525 g_string_free(normalized_path, TRUE);
526 }
527 if (trace_paths) {
528 for (tp_node = trace_paths; tp_node; tp_node = g_list_next(tp_node)) {
529 if (tp_node->data) {
530 g_string_free(tp_node->data, TRUE);
531 }
532 }
533 g_list_free(trace_paths);
534 }
535 if (trace_names) {
536 for (tn_node = trace_names; tn_node; tn_node = g_list_next(tn_node)) {
537 if (tn_node->data) {
538 g_string_free(tn_node->data, TRUE);
539 }
540 }
541 g_list_free(trace_names);
542 }
543 /* "path" becomes invalid with the release of path_value. */
544 bt_put(path_value);
545 return trace_infos;
04c0ba87 546}
This page took 0.043022 seconds and 4 git commands to generate.