+ if (add_group && ds_file_group) {
+ g_ptr_array_add(ctf_fs_trace->ds_file_groups, ds_file_group);
+ }
+
+ ctf_fs_ds_file_destroy(ds_file);
+
+ if (notif_iter) {
+ bt_notif_iter_destroy(notif_iter);
+ }
+
+ ctf_fs_ds_index_destroy(index);
+ return ret;
+}
+
+static
+int create_ds_file_groups(struct ctf_fs_trace *ctf_fs_trace)
+{
+ int ret = 0;
+ const char *basename;
+ GError *error = NULL;
+ GDir *dir = NULL;
+ size_t i;
+
+ /* Check each file in the path directory, except specific ones */
+ dir = g_dir_open(ctf_fs_trace->path->str, 0, &error);
+ if (!dir) {
+ BT_LOGE("Cannot open directory `%s`: %s (code %d)",
+ ctf_fs_trace->path->str, error->message,
+ error->code);
+ goto error;
+ }
+
+ while ((basename = g_dir_read_name(dir))) {
+ struct ctf_fs_file *file;
+
+ if (!strcmp(basename, CTF_FS_METADATA_FILENAME)) {
+ /* Ignore the metadata stream. */
+ BT_LOGD("Ignoring metadata file `%s" G_DIR_SEPARATOR_S "%s`",
+ ctf_fs_trace->path->str, basename);
+ continue;
+ }
+
+ if (basename[0] == '.') {
+ BT_LOGD("Ignoring hidden file `%s" G_DIR_SEPARATOR_S "%s`",
+ ctf_fs_trace->path->str, basename);
+ continue;
+ }
+
+ /* Create the file. */
+ file = ctf_fs_file_create();
+ if (!file) {
+ BT_LOGE("Cannot create stream file object for file `%s" G_DIR_SEPARATOR_S "%s`",
+ ctf_fs_trace->path->str, basename);
+ goto error;
+ }
+
+ /* Create full path string. */
+ g_string_append_printf(file->path, "%s" G_DIR_SEPARATOR_S "%s",
+ ctf_fs_trace->path->str, basename);
+ if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) {
+ BT_LOGD("Ignoring non-regular file `%s`",
+ file->path->str);
+ ctf_fs_file_destroy(file);
+ file = NULL;
+ continue;
+ }
+
+ ret = ctf_fs_file_open(file, "rb");
+ if (ret) {
+ BT_LOGE("Cannot open stream file `%s`", file->path->str);
+ goto error;
+ }
+
+ if (file->size == 0) {
+ /* Skip empty stream. */
+ BT_LOGD("Ignoring empty file `%s`", file->path->str);
+ ctf_fs_file_destroy(file);
+ continue;
+ }
+
+ ret = add_ds_file_to_ds_file_group(ctf_fs_trace,
+ file->path->str);
+ if (ret) {
+ BT_LOGE("Cannot add stream file `%s` to stream file group",
+ file->path->str);
+ ctf_fs_file_destroy(file);
+ goto error;
+ }
+
+ ctf_fs_file_destroy(file);
+ }
+
+ /*
+ * At this point, DS file groupes are created, but their
+ * associated stream objects do not exist yet. This is because
+ * we need to name the created stream object with the data
+ * stream file's path. We have everything we need here to do
+ * this.
+ */
+ for (i = 0; i < ctf_fs_trace->ds_file_groups->len; i++) {
+ struct ctf_fs_ds_file_group *ds_file_group =
+ g_ptr_array_index(ctf_fs_trace->ds_file_groups, i);
+ GString *name = get_stream_instance_unique_name(ds_file_group);
+
+ if (!name) {
+ goto error;
+ }
+
+ if (ds_file_group->stream_id == -1ULL) {
+ /* No stream ID: use 0 */
+ ds_file_group->stream = bt_stream_create(
+ ds_file_group->stream_class, name->str,
+ ctf_fs_trace->next_stream_id);
+ ctf_fs_trace->next_stream_id++;
+ } else {
+ /* Specific stream ID */
+ ds_file_group->stream = bt_stream_create(
+ ds_file_group->stream_class, name->str,
+ ds_file_group->stream_id);
+ }
+
+ g_string_free(name, TRUE);
+
+ if (!ds_file_group->stream) {
+ BT_LOGE("Cannot create stream for DS file group: "
+ "addr=%p, stream-name=\"%s\"",
+ ds_file_group, name->str);
+ goto error;
+ }
+ }
+
+ goto end;
+
+error:
+ ret = -1;
+
+end:
+ if (dir) {
+ g_dir_close(dir);
+ dir = NULL;
+ }
+
+ if (error) {
+ g_error_free(error);
+ }
+
+ return ret;
+}
+
+static
+int create_cc_prio_map(struct ctf_fs_trace *ctf_fs_trace)
+{
+ int ret = 0;
+ size_t i;
+ int count;
+
+ BT_ASSERT(ctf_fs_trace);
+ ctf_fs_trace->cc_prio_map = bt_clock_class_priority_map_create();
+ if (!ctf_fs_trace->cc_prio_map) {
+ ret = -1;
+ goto end;
+ }
+
+ count = bt_trace_get_clock_class_count(
+ ctf_fs_trace->metadata->trace);
+ BT_ASSERT(count >= 0);
+
+ for (i = 0; i < count; i++) {
+ struct bt_clock_class *clock_class =
+ bt_trace_borrow_clock_class_by_index(
+ ctf_fs_trace->metadata->trace, i);
+
+ BT_ASSERT(clock_class);
+ ret = bt_clock_class_priority_map_add_clock_class(
+ ctf_fs_trace->cc_prio_map, clock_class, 0);
+
+ if (ret) {
+ goto end;
+ }
+ }
+
+end:
+ return ret;