2 * SPDX-License-Identifier: MIT
4 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
7 #define BT_LOG_TAG "LIB/MIP"
8 #include "lib/logging.h"
10 #include "lib/assert-cond.h"
14 #include <babeltrace2/graph/graph.h>
16 #include "common/assert.h"
17 #include "compat/compiler.h"
18 #include "common/common.h"
19 #include "lib/func-status.h"
20 #include "lib/graph/component-class.h"
21 #include "lib/value.h"
22 #include "component-descriptor-set.h"
23 #include "lib/integer-range-set.h"
25 #define MAX_MIP_VERSION 1
28 bool unsigned_integer_range_set_contains(
29 const struct bt_integer_range_set
*range_set
, uint64_t value
)
31 bool contains
= false;
36 for (i
= 0; i
< range_set
->ranges
->len
; i
++) {
37 const struct bt_integer_range
*range
=
38 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(range_set
, i
);
40 if (value
>= range
->lower
.u
&& value
<= range
->upper
.u
) {
51 * Log the MIP versions (in `range_set`) supported by the component described by
55 void log_supported_mip_versions_range_set(const bt_integer_range_set_unsigned
*range_set
,
56 const struct bt_component_descriptor_set_entry
*descr
)
61 if (!BT_LOG_ON_DEBUG
) {
65 range_count
= bt_integer_range_set_get_range_count(
66 bt_integer_range_set_unsigned_as_range_set_const(range_set
));
68 BT_LIB_LOGD("Supported MIP version ranges: %![cc-]C", descr
->comp_cls
);
70 for (i
= 0; i
< range_count
; ++i
) {
71 const bt_integer_range_unsigned
*range
=
72 bt_integer_range_set_unsigned_borrow_range_by_index_const(
74 uint64_t lower
= bt_integer_range_unsigned_get_lower(range
);
75 uint64_t upper
= bt_integer_range_unsigned_get_upper(range
);
77 BT_LIB_LOGD(" [%" PRIu64
", %" PRIu64
"]", lower
, upper
);
85 * Get the MIP version ranges supported by descriptors in `descriptors`, append
86 * them to `supported_ranges`.
88 * The elements of `descriptors` are `struct bt_component_descriptor_set_entry *`.
89 * The elements of `supported_ranges` are `bt_integer_range_set_unsigned *`.
92 int get_supported_mip_version_ranges(GPtrArray
*descriptors
,
93 GPtrArray
*supported_ranges
,
94 enum bt_logging_level log_level
)
96 typedef bt_component_class_get_supported_mip_versions_method_status
98 void * /* component class */,
99 const struct bt_value
*,
100 void * /* init method data */,
101 enum bt_logging_level
,
102 bt_integer_range_set_unsigned
*);
106 struct bt_integer_range_set_unsigned
*range_set
= NULL
;
108 for (i
= 0; i
< descriptors
->len
; i
++) {
109 struct bt_component_descriptor_set_entry
*descr
=
110 descriptors
->pdata
[i
];
111 method_t method
= NULL
;
112 const char *method_name
= NULL
;
113 bt_component_class_get_supported_mip_versions_method_status method_status
;
115 switch (descr
->comp_cls
->type
) {
116 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
118 struct bt_component_class_source
*src_cc
= (void *)
121 method
= (method_t
) src_cc
->methods
.get_supported_mip_versions
;
122 method_name
= "bt_component_class_source_get_supported_mip_versions_method";
125 case BT_COMPONENT_CLASS_TYPE_FILTER
:
127 struct bt_component_class_filter
*flt_cc
= (void *)
130 method
= (method_t
) flt_cc
->methods
.get_supported_mip_versions
;
131 method_name
= "bt_component_class_filter_get_supported_mip_versions_method";
134 case BT_COMPONENT_CLASS_TYPE_SINK
:
136 struct bt_component_class_sink
*sink_cc
= (void *)
139 method
= (method_t
) sink_cc
->methods
.get_supported_mip_versions
;
140 method_name
= "bt_component_class_sink_get_supported_mip_versions_method";
147 range_set
= bt_integer_range_set_unsigned_create();
149 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
154 BT_ASSERT(descr
->params
);
155 BT_LIB_LOGD("Calling user's \"get supported MIP versions\" method: "
156 "%![cc-]+C, %![params-]+v, init-method-data=%p, "
158 descr
->comp_cls
, descr
->params
,
159 descr
->init_method_data
,
160 bt_common_logging_level_string(log_level
));
161 method_status
= method(descr
->comp_cls
, descr
->params
,
162 descr
->init_method_data
, log_level
,
164 BT_LIB_LOGD("User method returned: status=%s",
165 bt_common_func_status_string(method_status
));
166 BT_ASSERT_POST(method_name
, "status-ok-with-at-least-one-range",
167 method_status
!= BT_FUNC_STATUS_OK
||
168 bt_integer_range_set_get_range_count(
169 bt_integer_range_set_unsigned_as_range_set_const(range_set
)) > 0,
170 "User method returned `BT_FUNC_STATUS_OK` without "
171 "adding a range to the supported MIP version range set.");
172 BT_ASSERT_POST_NO_ERROR_IF_NO_ERROR_STATUS(method_name
,
174 if (method_status
< 0) {
175 BT_LIB_LOGW_APPEND_CAUSE(
176 "Component class's \"get supported MIP versions\" method failed: "
177 "%![cc-]+C, %![params-]+v, init-method-data=%p, "
179 descr
->comp_cls
, descr
->params
,
180 descr
->init_method_data
,
181 bt_common_logging_level_string(log_level
));
182 status
= (int) method_status
;
187 * Component class does not implement the
188 * get_supported_mip_versions method, it means it only
189 * supports version 0.
191 bt_integer_range_set_add_range_status add_range_status
192 = bt_integer_range_set_unsigned_add_range(range_set
, 0, 0);
193 if (add_range_status
!= BT_INTEGER_RANGE_SET_ADD_RANGE_STATUS_OK
) {
194 status
= (int) add_range_status
;
199 log_supported_mip_versions_range_set(range_set
, descr
);
201 /* Transfer ownership of `range_set` */
202 g_ptr_array_add(supported_ranges
, range_set
);
206 status
= BT_FUNC_STATUS_OK
;
209 bt_object_put_ref(range_set
);
214 * Given `supported_ranges`, an array of `bt_integer_range_set_unsigned *`
215 * representing the supported MIP version ranges of multiple eventual
216 * components, find the greatest version supported by all.
219 bt_get_greatest_operative_mip_version_status
find_greatest_compatible_mip_version(
220 const GPtrArray
*supported_ranges
,
221 const bt_integer_range_set_unsigned
*mip_version_restriction
,
222 uint64_t *operative_mip_version
)
224 bool versions
[MAX_MIP_VERSION
+ 1];
227 bt_get_greatest_operative_mip_version_status status
;
229 /* Start by assuming all existing MIP versions are supported. */
230 for (v
= 0; v
<= MAX_MIP_VERSION
; ++v
) {
235 * Disable specific versions based on `mip_version_restriction`,
238 if (mip_version_restriction
) {
239 for (v
= 0; v
<= MAX_MIP_VERSION
; ++v
) {
240 if (!unsigned_integer_range_set_contains(
241 bt_integer_range_set_unsigned_as_range_set_const(
242 mip_version_restriction
), v
)) {
249 * Go over each (soon-to-be) component's range set of support MIP
252 for (range_set_i
= 0; range_set_i
< supported_ranges
->len
; ++range_set_i
) {
253 const struct bt_integer_range_set
*range_set
=
254 supported_ranges
->pdata
[range_set_i
];
258 * For each existing MIP version, clear the flag if that
259 * component would not support it.
261 for (i
= 0; i
<= MAX_MIP_VERSION
; ++i
) {
262 if (!unsigned_integer_range_set_contains(range_set
, i
)) {
268 /* Find the greatest MIP version with the flag still set. */
269 for (v
= MAX_MIP_VERSION
; v
>= 0; --v
) {
271 *operative_mip_version
= v
;
272 status
= BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_OK
;
277 status
= BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_NO_MATCH
;
283 enum bt_get_greatest_operative_mip_version_status
284 bt_get_greatest_operative_mip_version_with_restriction(
285 const struct bt_component_descriptor_set
*comp_descr_set
,
286 enum bt_logging_level log_level
,
287 const bt_integer_range_set_unsigned
*mip_version_restriction
,
288 uint64_t *mip_version
)
291 GPtrArray
*supported_ranges
;
292 unsigned int comp_count
=
293 comp_descr_set
->sources
->len
+
294 comp_descr_set
->filters
->len
+
295 comp_descr_set
->sinks
->len
;
297 BT_ASSERT_PRE_NO_ERROR();
298 BT_ASSERT_PRE_COMP_DESCR_SET_NON_NULL(comp_descr_set
);
299 BT_ASSERT_PRE_NON_NULL("operative-mip-version-output",
301 "Operative MIP version (output)");
302 BT_ASSERT_PRE("component-descriptor-set-is-not-empty",
304 "Component descriptor set is empty: addr=%p", comp_descr_set
);
306 supported_ranges
= g_ptr_array_new_with_free_func(
307 (void *) bt_integer_range_set_unsigned_put_ref
);
308 if (!supported_ranges
) {
309 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN("Get greatest MIP",
310 "Failed to allocate one GPtrArray");
311 status
= BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_MEMORY_ERROR
;
315 status
= get_supported_mip_version_ranges(
316 comp_descr_set
->sources
, supported_ranges
, log_level
);
321 status
= get_supported_mip_version_ranges(
322 comp_descr_set
->filters
, supported_ranges
, log_level
);
327 status
= get_supported_mip_version_ranges(
328 comp_descr_set
->sinks
, supported_ranges
, log_level
);
333 status
= find_greatest_compatible_mip_version(
334 supported_ranges
, mip_version_restriction
, mip_version
);
335 if (status
== BT_GET_GREATEST_OPERATIVE_MIP_VERSION_STATUS_OK
) {
336 BT_LIB_LOGD("Found a compatible MIP version: version=%d",
339 BT_LIB_LOGD("Failed to find a compatible MIP version: status=%s",
340 bt_common_func_status_string(status
));
344 g_ptr_array_free(supported_ranges
, TRUE
);
349 enum bt_get_greatest_operative_mip_version_status
350 bt_get_greatest_operative_mip_version(
351 const struct bt_component_descriptor_set
*comp_descr_set
,
352 enum bt_logging_level log_level
,
353 uint64_t *mip_version
)
355 return bt_get_greatest_operative_mip_version_with_restriction(
356 comp_descr_set
, log_level
, NULL
, mip_version
);
360 uint64_t bt_get_maximal_mip_version(void)
362 return MAX_MIP_VERSION
;