2 * Copyright (c) 2023 Simon Marchi <simon.marchi@efficios.com>
3 * Copyright (c) 2023 Philippe Proulx <pproulx@efficios.com>
5 * SPDX-License-Identifier: MIT
8 #ifndef BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP
9 #define BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP
15 #include <babeltrace2/babeltrace.h>
17 #include "cpp-common/bt2c/c-string-view.hpp"
18 #include "cpp-common/bt2c/logging.hpp"
19 #include "cpp-common/vendor/fmt/core.h"
27 constexpr bt2c::CStringView unhandledExcLogStr() noexcept
29 return "Unhandled exception.";
32 constexpr bt2c::CStringView unhandledExcLogTag() noexcept
34 return "PLUGIN-DEV-HPP";
38 * Base class of any component class bridge.
40 * `UserCompClsT` is the actual C++ user component class and `LibTypesT`
41 * is a structure offering the following specific library types:
44 * Self component class.
50 * Self component configuration.
52 template <typename UserCompClsT, typename LibTypesT>
56 using _LibSelfCompPtr = typename LibTypesT::SelfComp *;
59 static UserCompClsT& userCompFromLibSelfCompPtr(const _LibSelfCompPtr libSelfCompPtr) noexcept
61 return wrap(libSelfCompPtr).template data<UserCompClsT>();
64 static bt_component_class_initialize_method_status init(const _LibSelfCompPtr libSelfCompPtr,
65 typename LibTypesT::SelfCompCfg *,
66 const bt_value * const libParamsPtr,
67 void * const initData) noexcept
69 const auto selfComp = wrap(libSelfCompPtr);
73 new UserCompClsT {selfComp, wrap(libParamsPtr).asMap(),
74 static_cast<typename UserCompClsT::InitData *>(initData)};
77 } catch (const std::bad_alloc&) {
78 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
79 } catch (const Error&) {
80 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
82 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(selfComp.loggingLevel()),
83 unhandledExcLogTag(), unhandledExcLogStr());
84 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
87 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK;
90 static void finalize(const _LibSelfCompPtr libSelfCompPtr) noexcept
92 delete &userCompFromLibSelfCompPtr(libSelfCompPtr);
95 static bt_component_class_get_supported_mip_versions_method_status
96 getSupportedMipVersions(typename LibTypesT::SelfCompCls * const libSelfCompClsPtr,
97 const bt_value * const libParamsPtr, void *,
98 const bt_logging_level logLevel,
99 bt_integer_range_set_unsigned * const libSupportedVersionsPtr) noexcept
102 UserCompClsT::getSupportedMipVersions(wrap(libSelfCompClsPtr), wrap(libParamsPtr),
103 static_cast<LoggingLevel>(logLevel),
104 wrap(libSupportedVersionsPtr));
105 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_OK;
106 } catch (const std::bad_alloc&) {
107 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_MEMORY_ERROR;
108 } catch (const Error&) {
109 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_ERROR;
111 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(logLevel), unhandledExcLogTag(),
112 unhandledExcLogStr());
113 return BT_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_STATUS_ERROR;
117 static bt_component_class_query_method_status
118 query(typename LibTypesT::SelfCompCls * const libSelfCompClsPtr,
119 bt_private_query_executor * const libPrivQueryExecPtr, const char * const object,
120 const bt_value * const libParamsPtr, void * const data,
121 const bt_value ** const libResultPtr) noexcept
123 const auto privQueryExec = wrap(libPrivQueryExecPtr);
126 auto result = UserCompClsT::query(
127 wrap(libSelfCompClsPtr), privQueryExec, object, wrap(libParamsPtr),
128 static_cast<typename UserCompClsT::QueryData *>(data));
130 *libResultPtr = result.release().libObjPtr();
131 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_OK;
132 } catch (const TryAgain&) {
133 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_AGAIN;
134 } catch (const UnknownObject&) {
135 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_UNKNOWN_OBJECT;
136 } catch (const std::bad_alloc&) {
137 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_MEMORY_ERROR;
138 } catch (const Error&) {
139 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
141 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, static_cast<int>(privQueryExec.loggingLevel()),
142 unhandledExcLogTag(), unhandledExcLogStr());
143 return BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_ERROR;
148 template <typename SpecCompClsBridgeT, typename LibTypesT>
149 struct CompClsBridgeWithInputPorts
151 static bt_component_class_port_connected_method_status
152 inputPortConnected(typename LibTypesT::SelfComp * const libSelfCompPtr,
153 bt_self_component_port_input * const libSelfCompPortPtr,
154 const bt_port_output * const libOtherPortPtr) noexcept
157 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
158 .inputPortConnected(wrap(libSelfCompPortPtr), wrap(libOtherPortPtr));
159 } catch (const std::bad_alloc&) {
160 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
161 } catch (const Error&) {
162 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
164 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
165 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
166 unhandledExcLogTag(), unhandledExcLogStr());
167 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
170 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
174 template <typename SpecCompClsBridgeT, typename LibTypesT>
175 struct CompClsBridgeWithOutputPorts
177 static bt_component_class_port_connected_method_status
178 outputPortConnected(typename LibTypesT::SelfComp * const libSelfCompPtr,
179 bt_self_component_port_output * const libSelfCompPortPtr,
180 const bt_port_input * const libOtherPortPtr) noexcept
183 SpecCompClsBridgeT::userCompFromLibSelfCompPtr(libSelfCompPtr)
184 .outputPortConnected(wrap(libSelfCompPortPtr), wrap(libOtherPortPtr));
185 } catch (const std::bad_alloc&) {
186 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_MEMORY_ERROR;
187 } catch (const Error&) {
188 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
190 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
191 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
192 unhandledExcLogTag(), unhandledExcLogStr());
193 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_ERROR;
196 return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
200 struct SrcCompClsLibTypes final
202 using SelfCompCls = bt_self_component_class_source;
203 using SelfComp = bt_self_component_source;
204 using SelfCompCfg = bt_self_component_source_configuration;
207 template <typename UserCompClsT>
208 class SrcCompClsBridge final :
209 public CompClsBridge<UserCompClsT, SrcCompClsLibTypes>,
210 public CompClsBridgeWithOutputPorts<SrcCompClsBridge<UserCompClsT>, SrcCompClsLibTypes>
214 struct FltCompClsLibTypes final
216 using SelfCompCls = bt_self_component_class_filter;
217 using SelfComp = bt_self_component_filter;
218 using SelfCompCfg = bt_self_component_filter_configuration;
221 template <typename UserCompClsT>
222 class FltCompClsBridge final :
223 public CompClsBridge<UserCompClsT, FltCompClsLibTypes>,
224 public CompClsBridgeWithInputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsLibTypes>,
225 public CompClsBridgeWithOutputPorts<FltCompClsBridge<UserCompClsT>, FltCompClsLibTypes>
229 struct SinkCompClsLibTypes final
231 using SelfCompCls = bt_self_component_class_sink;
232 using SelfComp = bt_self_component_sink;
233 using SelfCompCfg = bt_self_component_sink_configuration;
236 template <typename UserCompClsT>
237 class SinkCompClsBridge final :
238 CompClsBridge<UserCompClsT, SinkCompClsLibTypes>,
239 CompClsBridgeWithInputPorts<SinkCompClsBridge<UserCompClsT>, SinkCompClsLibTypes>
242 using CompClsBridge<UserCompClsT, SinkCompClsLibTypes>::userCompFromLibSelfCompPtr;
245 static bt_component_class_sink_consume_method_status
246 consume(bt_self_component_sink * const libSelfCompPtr) noexcept
249 if (userCompFromLibSelfCompPtr(libSelfCompPtr).consume()) {
250 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK;
252 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_END;
254 } catch (const TryAgain&) {
255 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN;
256 } catch (const std::bad_alloc&) {
257 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_MEMORY_ERROR;
258 } catch (const Error&) {
259 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
261 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
262 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
263 unhandledExcLogTag(), unhandledExcLogStr());
264 return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
268 static bt_component_class_sink_graph_is_configured_method_status
269 graphIsConfigured(bt_self_component_sink * const libSelfCompPtr) noexcept
272 userCompFromLibSelfCompPtr(libSelfCompPtr).graphIsConfigured();
273 } catch (const std::bad_alloc&) {
274 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_MEMORY_ERROR;
275 } catch (const Error&) {
276 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
278 BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING,
279 static_cast<int>(wrap(libSelfCompPtr).loggingLevel()),
280 unhandledExcLogTag(), unhandledExcLogStr());
281 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR;
286 template <typename UserMsgIterT>
287 class MsgIterClsBridge final
291 userMsgIterFromLibSelfMsgIterPtr(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
293 return bt2::wrap(libSelfMsgIterPtr).data<UserMsgIterT>();
296 static bt_message_iterator_class_initialize_method_status
297 init(bt_self_message_iterator * const libSelfMsgIterPtr,
298 bt_self_message_iterator_configuration * const libSelfMsgIterConfigPtr,
299 bt_self_component_port_output * const libSelfCompPortPtr) noexcept
301 const auto selfMsgIter = bt2::wrap(libSelfMsgIterPtr);
304 const auto msgIter = new UserMsgIterT {selfMsgIter, bt2::wrap(libSelfMsgIterConfigPtr),
305 bt2::wrap(libSelfCompPortPtr)};
307 selfMsgIter.data(*msgIter);
308 } catch (const std::bad_alloc&) {
309 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
310 } catch (const bt2::Error&) {
311 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
313 BT_LOG_WRITE_CUR_LVL(
315 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
316 unhandledExcLogTag(), unhandledExcLogStr());
317 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
320 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK;
323 static void finalize(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
325 delete &userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
328 static bt_message_iterator_class_next_method_status
329 next(bt_self_message_iterator * const libSelfMsgIterPtr, bt_message_array_const libMsgsPtr,
330 const uint64_t capacity, uint64_t * const count) noexcept
333 auto msgArray = bt2::ConstMessageArray::wrapEmpty(libMsgsPtr, capacity);
334 auto& msgIter = userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr);
336 msgIter.next(msgArray);
337 *count = msgArray.release();
339 if (G_LIKELY(*count > 0)) {
340 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK;
342 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END;
344 } catch (const bt2::TryAgain&) {
345 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN;
346 } catch (const std::bad_alloc&) {
347 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR;
348 } catch (const bt2::Error&) {
349 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
351 BT_LOG_WRITE_CUR_LVL(
353 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
354 unhandledExcLogTag(), unhandledExcLogStr());
355 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
359 static bt_message_iterator_class_can_seek_beginning_method_status
360 canSeekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr,
361 bt_bool * const canSeek) noexcept
364 *canSeek = static_cast<bt_bool>(
365 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).canSeekBeginning());
366 } catch (const bt2::TryAgain&) {
367 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
368 } catch (const std::bad_alloc&) {
369 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
370 } catch (const bt2::Error&) {
371 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
373 BT_LOG_WRITE_CUR_LVL(
375 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
376 unhandledExcLogTag(), unhandledExcLogStr());
377 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_ERROR;
380 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_BEGINNING_METHOD_STATUS_OK;
383 static bt_message_iterator_class_seek_beginning_method_status
384 seekBeginning(bt_self_message_iterator * const libSelfMsgIterPtr) noexcept
387 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekBeginning();
388 } catch (const bt2::TryAgain&) {
389 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_AGAIN;
390 } catch (const std::bad_alloc&) {
391 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_MEMORY_ERROR;
392 } catch (const bt2::Error&) {
393 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
395 BT_LOG_WRITE_CUR_LVL(
397 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
398 unhandledExcLogTag(), unhandledExcLogStr());
399 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_ERROR;
402 return BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_OK;
405 static bt_message_iterator_class_can_seek_ns_from_origin_method_status
406 canSeekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
407 const std::int64_t nsFromOrigin, bt_bool * const canSeek) noexcept
410 *canSeek = static_cast<bt_bool>(userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr)
411 .canSeekNsFromOrigin(nsFromOrigin));
412 } catch (const bt2::TryAgain&) {
413 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
414 } catch (const std::bad_alloc&) {
415 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
416 } catch (const bt2::Error&) {
417 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
419 BT_LOG_WRITE_CUR_LVL(
421 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
422 unhandledExcLogTag(), unhandledExcLogStr());
423 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
426 return BT_MESSAGE_ITERATOR_CLASS_CAN_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
429 static bt_message_iterator_class_seek_ns_from_origin_method_status
430 seekNsFromOrigin(bt_self_message_iterator * const libSelfMsgIterPtr,
431 const std::int64_t nsFromOrigin) noexcept
434 userMsgIterFromLibSelfMsgIterPtr(libSelfMsgIterPtr).seekNsFromOrigin(nsFromOrigin);
435 } catch (const bt2::TryAgain&) {
436 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_AGAIN;
437 } catch (const std::bad_alloc&) {
438 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_MEMORY_ERROR;
439 } catch (const bt2::Error&) {
440 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
442 BT_LOG_WRITE_CUR_LVL(
444 static_cast<int>(wrap(libSelfMsgIterPtr).component().loggingLevel()),
445 unhandledExcLogTag(), unhandledExcLogStr());
446 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_ERROR;
449 return BT_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHOD_STATUS_OK;
453 } /* namespace internal */
455 template <typename UserMessageIteratorT, typename UserComponentT>
456 class UserMessageIterator;
459 * Base class of any user component.
461 * See the specific `bt2::UserSourceComponent`,
462 * `bt2::UserFilterComponent`, and `bt2::UserSinkComponent`.
464 template <typename SelfCompT, typename InitDataT, typename QueryDataT>
467 /* Give a related message iterator access to this logger */
468 template <typename, typename>
469 friend class UserMessageIterator;
472 using InitData = InitDataT;
473 using QueryData = QueryDataT;
476 explicit UserComponent(const SelfCompT selfComp, const std::string& logTag) :
477 _mLogger {selfComp, fmt::format("{}/[{}]", logTag, selfComp.name())}, _mSelfComp {selfComp}
482 bt2c::CStringView _name() const noexcept
484 return _mSelfComp.name();
487 LoggingLevel _loggingLevel() const noexcept
489 return _mSelfComp.loggingLevel();
492 std::uint64_t _graphMipVersion() const noexcept
494 return _mSelfComp.graphMipVersion();
497 SelfCompT _selfComp() noexcept
502 bt2c::Logger _mLogger;
505 SelfCompT _mSelfComp;
509 * Base class of a user source component `UserComponentT` (CRTP).
511 * UserComponentT::UserComponentT() must accept, in this order:
513 * 1. A `bt2::SelfSourceComponent` parameter, which it needs to forward
514 * to bt2::UserSourceComponent::UserSourceComponent().
516 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
518 * 3. An `InitDataT *` parameter (the initialization method data).
520 * `UserMessageIteratorT`, the message iterator class to use, must inherit
521 * `UserMessageIterator`.
523 * UserComponentT::_query() receives a query method data pointer of type
524 * `QueryDataT *` as its last parameter.
526 template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void,
527 typename QueryDataT = void>
528 class UserSourceComponent : public UserComponent<SelfSourceComponent, InitDataT, QueryDataT>
530 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
531 UserMessageIteratorT>::value,
532 "`UserMessageIteratorT` inherits `UserMessageIterator`");
535 using MessageIterator = UserMessageIteratorT;
538 using _OutputPorts = SelfSourceComponent::OutputPorts;
540 explicit UserSourceComponent(const SelfSourceComponent selfComp, const std::string& logTag) :
541 UserComponent<SelfSourceComponent, InitDataT, QueryDataT> {selfComp, logTag}
546 static Value::Shared query(const SelfComponentClass selfCompCls,
547 const PrivateQueryExecutor privQueryExec,
548 const bt2c::CStringView obj, const ConstValue params,
549 QueryDataT * const data)
551 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
554 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
555 const ConstValue params, const LoggingLevel loggingLevel,
556 const UnsignedIntegerRangeSet ranges)
558 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
561 void outputPortConnected(const SelfComponentOutputPort outputPort,
562 const ConstInputPort inputPort)
564 static_cast<UserComponentT&>(*this).outputPortConnected(outputPort, inputPort);
569 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
570 ConstValue, QueryDataT *)
572 throw UnknownObject {};
576 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
577 const UnsignedIntegerRangeSet ranges)
579 ranges.addRange(0, 0);
583 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
587 template <typename DataT>
588 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT * const data)
590 return this->_selfComp().addOutputPort(name, data);
593 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
595 return this->_selfComp().addOutputPort(name);
598 _OutputPorts _outputPorts() noexcept
600 return this->_selfComp().outputPorts();
605 * Base class of a user filter component `UserComponentT` (CRTP).
607 * UserComponentT::UserComponentT() must accept, in this order:
609 * 1. A `bt2::SelfFilterComponent` parameter, which it needs to forward
610 * to bt2::UserFilterComponent::UserFilterComponent().
612 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
614 * 3. An `InitDataT *` parameter (the initialization method data).
616 * `UserMessageIteratorT`, the message iterator class to use, must inherit
617 * `UserMessageIterator`.
619 * UserComponentT::_query() receives a query method data pointer of type
620 * `QueryDataT *` as its last parameter.
622 template <typename UserComponentT, typename UserMessageIteratorT, typename InitDataT = void,
623 typename QueryDataT = void>
624 class UserFilterComponent : public UserComponent<SelfFilterComponent, InitDataT, QueryDataT>
626 static_assert(std::is_base_of<UserMessageIterator<UserMessageIteratorT, UserComponentT>,
627 UserMessageIteratorT>::value,
628 "`UserMessageIteratorT` inherits `UserMessageIterator`");
631 using MessageIterator = UserMessageIteratorT;
634 using _InputPorts = SelfFilterComponent::InputPorts;
635 using _OutputPorts = SelfFilterComponent::OutputPorts;
637 explicit UserFilterComponent(const SelfFilterComponent selfComp, const std::string& logTag) :
638 UserComponent<SelfFilterComponent, InitDataT, QueryDataT> {selfComp, logTag}
643 static Value::Shared query(const SelfComponentClass selfCompCls,
644 const PrivateQueryExecutor privQueryExec,
645 const bt2c::CStringView obj, const ConstValue params,
646 QueryDataT * const data)
648 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
651 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
652 const ConstValue params, const LoggingLevel loggingLevel,
653 const UnsignedIntegerRangeSet ranges)
655 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
658 void inputPortConnected(const SelfComponentInputPort inputPort,
659 const ConstOutputPort outputPort)
661 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
664 void outputPortConnected(const SelfComponentOutputPort outputPort,
665 const ConstInputPort inputPort)
667 static_cast<UserComponentT&>(*this)._outputPortConnected(outputPort, inputPort);
672 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
673 ConstValue, QueryDataT *)
675 throw UnknownObject {};
679 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
680 const UnsignedIntegerRangeSet ranges)
682 ranges.addRange(0, 0);
686 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
691 void _outputPortConnected(SelfComponentOutputPort, ConstInputPort)
695 template <typename DataT>
696 _OutputPorts::Port _addInputPort(const bt2c::CStringView name, DataT * const data)
698 return this->_selfComp().addInputPort(name, data);
701 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
703 return this->_selfComp().addInputPort(name);
706 _InputPorts _inputPorts() noexcept
708 return this->_selfComp().inputPorts();
711 template <typename DataT>
712 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name, DataT * const data)
714 return this->_selfComp().addOutputPort(name, data);
717 _OutputPorts::Port _addOutputPort(const bt2c::CStringView name)
719 return this->_selfComp().addOutputPort(name);
722 _OutputPorts _outputPorts() noexcept
724 return this->_selfComp().outputPorts();
729 * Base class of a user sink component `UserComponentT` (CRTP).
731 * UserComponentT::UserComponentT() must accept, in this order:
733 * 1. A `bt2::SelfSinkComponent` parameter, which it needs to forward
734 * to bt2::UserSinkComponent::UserSinkComponent().
736 * 2. A `bt2::ConstValue` parameter (the initialization parameters).
738 * 3. An `InitDataT *` parameter (the initialization method data).
740 * `UserComponentT` must implement:
744 * This method returns `true` if the sink component still needs to
745 * consume, or `false` if it's finished.
747 * UserComponentT::_query() receives a query method data pointer of type
748 * `QueryDataT *` as its last parameter.
751 template <typename UserComponentT, typename InitDataT = void, typename QueryDataT = void>
752 class UserSinkComponent : public UserComponent<SelfSinkComponent, InitDataT, QueryDataT>
755 using _InputPorts = SelfSinkComponent::InputPorts;
757 explicit UserSinkComponent(const SelfSinkComponent selfComp, const std::string& logTag) :
758 UserComponent<SelfSinkComponent, InitDataT, QueryDataT> {selfComp, logTag}
763 static Value::Shared query(const SelfComponentClass selfCompCls,
764 const PrivateQueryExecutor privQueryExec,
765 const bt2c::CStringView obj, const ConstValue params,
766 QueryDataT * const data)
768 return UserComponentT::_query(selfCompCls, privQueryExec, obj, params, data);
771 static void getSupportedMipVersions(const SelfComponentClass selfCompCls,
772 const ConstValue params, const LoggingLevel loggingLevel,
773 const UnsignedIntegerRangeSet ranges)
775 UserComponentT::_getSupportedMipVersions(selfCompCls, params, loggingLevel, ranges);
778 void graphIsConfigured()
780 static_cast<UserComponentT&>(*this)._graphIsConfigured();
783 void inputPortConnected(const SelfComponentInputPort inputPort,
784 const ConstOutputPort outputPort)
786 static_cast<UserComponentT&>(*this)._inputPortConnected(inputPort, outputPort);
791 return static_cast<UserComponentT&>(*this)._consume();
796 static Value::Shared _query(SelfComponentClass, PrivateQueryExecutor, bt2c::CStringView,
797 ConstValue, QueryDataT *)
799 throw UnknownObject {};
803 static void _getSupportedMipVersions(SelfComponentClass, ConstValue, LoggingLevel,
804 const UnsignedIntegerRangeSet ranges)
806 ranges.addRange(0, 0);
810 void _graphIsConfigured()
815 void _inputPortConnected(SelfComponentInputPort, ConstOutputPort)
819 MessageIterator::Shared _createMessageIterator(const _InputPorts::Port port)
821 return this->_selfComp().createMessageIterator(port);
824 template <typename DataT>
825 _InputPorts::Port _addInputPort(const bt2c::CStringView name, DataT * const data)
827 return this->_selfComp().addInputPort(name, data);
830 _InputPorts::Port _addInputPort(const bt2c::CStringView name)
832 return this->_selfComp().addInputPort(name);
835 _InputPorts _inputPorts() noexcept
837 return this->_selfComp().inputPorts();
842 * Base class of a user message iterator `UserMessageIteratorT` (CRTP)
843 * of which the parent user component class is `UserComponentT`.
845 * `UserMessageIteratorT::UserMessageIteratorT()` must accept a
846 * `bt2::SelfMessageIterator` parameter, which it needs to forward to
847 * bt2::UserMessageIterator::UserMessageIterator().
849 * The public next() method below (called by the bridge) implements the
850 * very common pattern of appending messages into the output array, and,
853 * If it catches a `bt2::TryAgain` exception:
854 * If the message array isn't empty, transform this into a success
859 * If it catches an error:
860 * If the message array isn't empty, transform this into a success
861 * (don't throw), but save the error of the current thread and the
862 * type of error to throw the next time the user calls next().
866 * `UserMessageIteratorT` must implement:
868 * void _next(bt2::ConstMessageArray& messages);
870 * This method fills `messages` with at most `messages.capacity()`
871 * messages and may throw `bt2::TryAgain` or a valid error whenever.
872 * Leaving an empty `messages` means the end of iteration.
874 template <typename UserMessageIteratorT, typename UserComponentT>
875 class UserMessageIterator
878 /* Type of `_mExcToThrowType` */
879 enum class _ExcToThrowType
887 explicit UserMessageIterator(const SelfMessageIterator selfMsgIter,
888 const std::string& logTagSuffix) :
889 _mSelfMsgIter {selfMsgIter},
890 _mLogger {selfMsgIter,
891 fmt::format("{}/{}", this->_component()._mLogger.tag(), logTagSuffix)}
896 ~UserMessageIterator()
901 void next(bt2::ConstMessageArray& messages)
903 /* Any saved error? Now is the time to throw */
904 if (G_UNLIKELY(_mExcToThrowType != _ExcToThrowType::NONE)) {
905 /* Move `_mSavedLibError`, if any, as current thread error */
906 if (_mSavedLibError) {
907 BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(_mSavedLibError);
910 /* Throw the corresponding exception */
911 if (_mExcToThrowType == _ExcToThrowType::ERROR) {
914 BT_ASSERT(_mExcToThrowType == _ExcToThrowType::MEM_ERROR);
915 throw bt2::MemoryError {};
920 * When catching some exception below, if our message array
921 * isn't empty, then return immediately before throwing to
922 * provide those messages to downstream.
924 * When catching an error, also save the current thread error,
925 * if any, so that we can restore it later (see the beginning of
928 BT_ASSERT_DBG(_mExcToThrowType == _ExcToThrowType::NONE);
931 this->_userObj()._next(messages);
933 /* We're done: everything below is exception handling */
935 } catch (const bt2::TryAgain&) {
936 if (messages.isEmpty()) {
939 } catch (const std::bad_alloc&) {
940 if (messages.isEmpty()) {
944 _mExcToThrowType = _ExcToThrowType::MEM_ERROR;
945 } catch (const bt2::Error&) {
946 if (messages.isEmpty()) {
950 _mExcToThrowType = _ExcToThrowType::ERROR;
953 if (_mExcToThrowType != _ExcToThrowType::NONE) {
955 "An error occurred, but there are {} messages to return: delaying the error reporting.",
957 BT_ASSERT(!_mSavedLibError);
958 _mSavedLibError = bt_current_thread_take_error();
962 bool canSeekBeginning()
965 return this->_userObj()._canSeekBeginning();
971 return this->_userObj()._seekBeginning();
974 bool canSeekNsFromOrigin(const std::int64_t nsFromOrigin)
977 return this->_userObj()._canSeekNsFromOrigin(nsFromOrigin);
980 void seekNsFromOrigin(const std::int64_t nsFromOrigin)
983 this->_userObj()._seekNsFromOrigin(nsFromOrigin);
988 bool _canSeekBeginning() noexcept
994 void _seekBeginning() noexcept
999 bool _canSeekNsFromOrigin(std::int64_t) noexcept
1005 void _seekNsFromOrigin(std::int64_t) noexcept
1009 MessageIterator::Shared _createMessageIterator(const SelfComponentInputPort port)
1011 return _mSelfMsgIter.createMessageIterator(port);
1014 UserComponentT& _component() noexcept
1016 return _mSelfMsgIter.component().template data<UserComponentT>();
1019 SelfComponentOutputPort _port() noexcept
1021 return _mSelfMsgIter.port();
1024 bool _isInterrupted() const noexcept
1026 return _mSelfMsgIter.isInterrupted();
1030 UserMessageIteratorT& _userObj() noexcept
1032 return static_cast<UserMessageIteratorT&>(*this);
1035 void _resetError() noexcept
1037 _mExcToThrowType = _ExcToThrowType::NONE;
1039 if (_mSavedLibError) {
1040 bt_error_release(_mSavedLibError);
1044 SelfMessageIterator _mSelfMsgIter;
1047 * next() may accumulate messages, and then catch an error before
1048 * returning. In that case, it saves the error of the current thread
1049 * here so that it can return its accumulated messages and throw the
1052 * It also saves the type of the exception to throw the next time.
1054 _ExcToThrowType _mExcToThrowType = _ExcToThrowType::NONE;
1055 const bt_error *_mSavedLibError = nullptr;
1058 bt2c::Logger _mLogger;
1061 } /* namespace bt2 */
1063 #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1064 _userComponentClass) \
1065 BT_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID( \
1066 _pluginId, _componentClassId, _name, \
1067 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::next); \
1068 BT_PLUGIN_SOURCE_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1069 _pluginId, _componentClassId, bt2::internal::SrcCompClsBridge<_userComponentClass>::init); \
1070 BT_PLUGIN_SOURCE_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1071 _pluginId, _componentClassId, \
1072 bt2::internal::SrcCompClsBridge<_userComponentClass>::finalize); \
1073 BT_PLUGIN_SOURCE_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1074 _pluginId, _componentClassId, \
1075 bt2::internal::SrcCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1076 BT_PLUGIN_SOURCE_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1077 _pluginId, _componentClassId, \
1078 bt2::internal::SrcCompClsBridge<_userComponentClass>::outputPortConnected); \
1079 BT_PLUGIN_SOURCE_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1080 _pluginId, _componentClassId, \
1081 bt2::internal::SrcCompClsBridge<_userComponentClass>::query); \
1082 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \
1083 _pluginId, _componentClassId, \
1084 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::init); \
1085 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \
1086 _pluginId, _componentClassId, \
1087 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::finalize); \
1088 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \
1089 _pluginId, _componentClassId, \
1090 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekBeginning, \
1091 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::canSeekBeginning); \
1092 BT_PLUGIN_SOURCE_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \
1093 _pluginId, _componentClassId, \
1094 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekNsFromOrigin, \
1095 bt2::internal::MsgIterClsBridge< \
1096 _userComponentClass::MessageIterator>::canSeekNsFromOrigin);
1098 #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1099 _userComponentClass) \
1100 BT_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID( \
1101 _pluginId, _componentClassId, _name, \
1102 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::next); \
1103 BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1104 _pluginId, _componentClassId, bt2::internal::FltCompClsBridge<_userComponentClass>::init); \
1105 BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1106 _pluginId, _componentClassId, \
1107 bt2::internal::FltCompClsBridge<_userComponentClass>::finalize); \
1108 BT_PLUGIN_FILTER_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1109 _pluginId, _componentClassId, \
1110 bt2::internal::FltCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1111 BT_PLUGIN_FILTER_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1112 _pluginId, _componentClassId, \
1113 bt2::internal::FltCompClsBridge<_userComponentClass>::inputPortConnected); \
1114 BT_PLUGIN_FILTER_COMPONENT_CLASS_OUTPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1115 _pluginId, _componentClassId, \
1116 bt2::internal::FltCompClsBridge<_userComponentClass>::outputPortConnected); \
1117 BT_PLUGIN_FILTER_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1118 _pluginId, _componentClassId, \
1119 bt2::internal::FltCompClsBridge<_userComponentClass>::query); \
1120 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID( \
1121 _pluginId, _componentClassId, \
1122 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::init); \
1123 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID( \
1124 _pluginId, _componentClassId, \
1125 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::finalize); \
1126 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHODS_WITH_ID( \
1127 _pluginId, _componentClassId, \
1128 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekBeginning, \
1129 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::canSeekBeginning); \
1130 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_SEEK_NS_FROM_ORIGIN_METHODS_WITH_ID( \
1131 _pluginId, _componentClassId, \
1132 bt2::internal::MsgIterClsBridge<_userComponentClass::MessageIterator>::seekNsFromOrigin, \
1133 bt2::internal::MsgIterClsBridge< \
1134 _userComponentClass::MessageIterator>::canSeekNsFromOrigin);
1136 #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(_pluginId, _componentClassId, _name, \
1137 _userComponentClass) \
1138 BT_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID( \
1139 _pluginId, _componentClassId, _name, \
1140 bt2::internal::SinkCompClsBridge<_userComponentClass>::consume); \
1141 BT_PLUGIN_SINK_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID( \
1142 _pluginId, _componentClassId, \
1143 bt2::internal::SinkCompClsBridge<_userComponentClass>::init); \
1144 BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID( \
1145 _pluginId, _componentClassId, \
1146 bt2::internal::SinkCompClsBridge<_userComponentClass>::finalize); \
1147 BT_PLUGIN_SINK_COMPONENT_CLASS_GET_SUPPORTED_MIP_VERSIONS_METHOD_WITH_ID( \
1148 _pluginId, _componentClassId, \
1149 bt2::internal::SinkCompClsBridge<_userComponentClass>::getSupportedMipVersions); \
1150 BT_PLUGIN_SINK_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD_WITH_ID( \
1151 _pluginId, _componentClassId, \
1152 bt2::internal::SinkCompClsBridge<_userComponentClass>::inputPortConnected); \
1153 BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD_WITH_ID( \
1154 _pluginId, _componentClassId, \
1155 bt2::internal::SinkCompClsBridge<_userComponentClass>::graphIsConfigured); \
1156 BT_PLUGIN_SINK_COMPONENT_CLASS_QUERY_METHOD_WITH_ID( \
1157 _pluginId, _componentClassId, \
1158 bt2::internal::SinkCompClsBridge<_userComponentClass>::query);
1160 #define BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS(_name, _userComponentClass) \
1161 BT_CPP_PLUGIN_SOURCE_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1163 #define BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS(_name, _userComponentClass) \
1164 BT_CPP_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1166 #define BT_CPP_PLUGIN_SINK_COMPONENT_CLASS(_name, _userComponentClass) \
1167 BT_CPP_PLUGIN_SINK_COMPONENT_CLASS_WITH_ID(auto, _name, #_name, _userComponentClass)
1169 #endif /* BABELTRACE_CPP_COMMON_BT2_PLUGIN_DEV_HPP */