RTC Toolkit 4.0.1
Loading...
Searching...
No Matches
measurable.hpp
Go to the documentation of this file.
1
13#ifndef RTCTK_COMPONENTFRAMEWORK_MEASURABLE_HPP
14#define RTCTK_COMPONENTFRAMEWORK_MEASURABLE_HPP
15
16#include <optional>
17
24
26namespace detail {
39public:
46 explicit MeasureContext(rad::cii::Request<std::string, std::string> const& request)
47 : m_logger(GetLogger("rtctk")), m_request(request), m_arg() {
48 m_arg = JsonPayload::parse(m_request.GetRequestPayload());
49 }
50 MeasureContext(MeasureContext&&) noexcept = default;
51
52 JsonPayload const& GetArg() const noexcept {
53 return m_arg;
54 }
55
62 void SetResult(JsonPayload const& result) {
63 m_result = result.dump();
64 }
65
71 void SendReply() noexcept {
72 try {
73 m_request.SetReplyValue(m_result);
74 } catch (std::exception const& exception) {
75 LOG4CPLUS_ERROR(
76 m_logger, "MeasureContext::SendReply: Failed to send reply: " << exception.what());
77 } catch (...) {
78 LOG4CPLUS_ERROR(
79 m_logger,
80 "MeasureContext::SendReply: Failed to send reply with unknown exception.");
81 }
82 }
83
87 void SendErrorReply(std::exception_ptr eptr) noexcept {
88 try {
89 m_request.SetException(RequestFailed(NestedExceptionPrinter(std::move(eptr)).Str()));
90 } catch (RtctkException const& exception) {
91 LOG4CPLUS_ERROR(
92 m_logger,
93 "MeasureContext::SendErrorReply: Failed to send reply: " << exception.what());
94 } catch (...) {
95 LOG4CPLUS_ERROR(
96 m_logger,
97 "MeasureContext::SendErrorReply: Failed to send reply with unknown exception.");
98 }
99 }
100
101private:
102 log4cplus::Logger& m_logger;
103 rad::cii::Request<std::string, std::string> m_request;
107 JsonPayload m_arg;
111 std::string m_result;
112};
113} // namespace detail
114
150template <typename Super>
151struct Measurable : Super {
152 static_assert(std::is_base_of_v<RtcComponent, Super>, "'Measurable' requires 'RtcComponent'");
153
158 class BizLogicIf : public Super::BizLogicIf {
159 public:
172 virtual JsonPayload ActivityMeasuring(StopToken stop_token, JsonPayload const& arg) {
173 (void)stop_token;
174 return JsonPayload("42");
175 }
176
186 virtual bool GuardMeasuringAllowed(JsonPayload const& arg) {
187 return true;
188 }
189 };
190
194 class InputStage : public Super::InputStage {
195 public:
196 using Super::InputStage::InputStage;
197
198 void Start() override {
199 Super::InputStage::Start();
200
201 MeasCmdsImpl::Register(this->m_replier, this->m_engine);
202 }
203 };
204
208 class OutputStage : public Super::OutputStage {
209 public:
210 OutputStage(StateMachineEngine& engine, BizLogicIf& bl) : Super::OutputStage(engine, bl) {
211 // Handlers ###################################################################
212
213 engine.RegisterRejectHandler<events::Measure, RequestRejected>();
214
216 this->m_engine.PostEvent(std::make_unique<events::MeasureDone>());
217 };
218
219 m_measure_error_handler = [this](std::exception_ptr eptr) {
220 this->m_engine.PostEvent(std::make_unique<events::MeasureError>(std::move(eptr)));
221 };
222
223 // No Disable in states ###############################################################
224
225 this->m_no_disable_in_states.push_back("On::Operational:Measure:Busy");
226
227 // No Update in states ################################################################
228
229 this->m_no_update_in_states.push_back("On::Operational:Measure:Busy");
230
231 // No Measure in states ###############################################################
232
233 this->m_no_measure_in_states.push_back("On:Update:Busy");
234
235 // Guards #####################################################################
236
237 engine.RegisterGuardStatic<events::Measure>(
238 "GuardMeasuringAllowed", [this](events::Measure const& ev) {
247 auto act_state = this->m_engine.GetState();
248 for (auto& s : m_no_measure_in_states) {
249 if (act_state.find(s) != std::string::npos) {
250 return false;
251 }
252 }
253 detail::MeasureContext ctx(ev.GetPayload());
254 if (static_cast<BizLogicIf&>(this->m_logic)
255 .GuardMeasuringAllowed(ctx.GetArg())) {
256 // Measure is allowed so context is stored.
257 assert(!m_measure_ctx);
258 m_measure_ctx.emplace(std::move(ctx));
259 return true;
260 }
261 return false;
262 });
263
264 // Activities #####################################################################
265 engine.RegisterActivity(
266 "ActivityMeasuring",
267 [this](StopToken stop_token) {
268 assert(m_measure_ctx);
269 JsonPayload result =
270 static_cast<BizLogicIf&>(this->m_logic)
271 .ActivityMeasuring(std::move(stop_token), m_measure_ctx->GetArg());
272 // note: SetResult may throw
273 m_measure_ctx->SetResult(result);
274 },
277
278 // Actions #####################################################################
279 engine.RegisterAction("ActionMeasuringDone", [this](auto c) {
280 assert(m_measure_ctx);
281 m_measure_ctx->SendReply();
282 m_measure_ctx.reset();
283 });
284
285 engine.RegisterActionStatic<events::MeasureError>(
286 "ActionMeasuringFailed", [this](events::MeasureError const& ev) {
287 assert(m_measure_ctx);
288 m_measure_ctx->SendErrorReply(ev.GetPayload());
289 m_measure_ctx.reset();
290 });
291 }
292
293 protected:
295 std::optional<detail::MeasureContext> m_measure_ctx;
296 std::function<void()> m_measure_success_handler;
297 std::function<void(std::exception_ptr)> m_measure_error_handler;
298 std::list<std::string> m_no_measure_in_states;
299 };
300
304 class ModelBuilder : public Super::ModelBuilder {
305 public:
306 explicit ModelBuilder(StateMachineEngine& engine) : Super::ModelBuilder(engine) {
307 // clang-format off
308 this->mm.ModStateType("On::Operational", Parallel);
309
310 this->mm.AddState(Composite, "On::Operational:Measure:", "On::Operational");
311 this->mm.AddState(Initial, "On::Operational:Measure:Initial", "On::Operational:Measure:");
312 this->mm.AddState(Simple, "On::Operational:Measure:Idle", "On::Operational:Measure:");
313 this->mm.AddState(Simple, "On::Operational:Measure:Busy", "On::Operational:Measure:", "ActivityMeasuring");
314
315 this->mm.AddTrans("On::Operational:Measure:Initial" , "On::Operational:Measure:Idle" );
316 this->mm.AddTrans("On::Operational:Measure:Idle" , "On::Operational:Measure:Busy", events::Measure::ID, "GuardMeasuringAllowed");
317 this->mm.AddTrans("On::Operational:Measure:Busy" , "On::Operational:Measure:Idle", events::MeasureDone::ID, "", "ActionMeasuringDone");
318 this->mm.AddTrans("On::Operational:Measure:Busy" , "On::Operational:Measure:Idle", events::MeasureError::ID, "", "ActionMeasuringFailed");
319 // clang-format on
320 }
321 };
322};
323
324} // namespace rtctk::componentFramework
325
326#endif
static void Register(CommandReplier &replier, StateMachineEngine &engine)
Definition: measCmdsImpl.hpp:37
Business logic interface for Measurable mixin.
Definition: measurable.hpp:158
virtual bool GuardMeasuringAllowed(JsonPayload const &arg)
Determines if measurement is possible at this time with the provided argument.
Definition: measurable.hpp:186
virtual JsonPayload ActivityMeasuring(StopToken stop_token, JsonPayload const &arg)
Activity executed in its own thread that peforms the requested measurement specified by JSON argument...
Definition: measurable.hpp:172
void Start() override
Definition: measurable.hpp:198
ModelBuilder(StateMachineEngine &engine)
Definition: measurable.hpp:306
std::function< void()> m_measure_success_handler
Definition: measurable.hpp:296
std::function< void(std::exception_ptr)> m_measure_error_handler
Definition: measurable.hpp:297
std::optional< detail::MeasureContext > m_measure_ctx
Context storage used for each accepted Measure request.
Definition: measurable.hpp:295
std::list< std::string > m_no_measure_in_states
Definition: measurable.hpp:298
OutputStage(StateMachineEngine &engine, BizLogicIf &bl)
Definition: measurable.hpp:210
Adapter object intended to be used in contexts without direct access to the output-stream object.
Definition: exceptions.hpp:185
Thrown if the command was accepted but the task to run failed.
Definition: rtcComponent.hpp:53
Thrown if a command is not allowed in current state or guard.
Definition: rtcComponent.hpp:40
The RtctkException class is the base class for all Rtctk exceptions.
Definition: exceptions.hpp:237
Definition: stateMachineEngine.hpp:35
void RegisterRejectHandler(std::string const &id, RejectMethod reject)
Register reject handler.
Definition: stateMachineEngine.cpp:131
void RegisterActivity(std::string const &id, ActivityMethod activity, SuccessMethod on_success, FailureMethod on_failure)
Register activity.
Definition: stateMachineEngine.cpp:123
void RegisterGuardStatic(std::string const &id, std::function< bool(Event const &)> guard)
Register guard for statically known event type.
Definition: stateMachineEngine.hpp:126
void RegisterAction(std::string const &id, ActionMethod action)
Register action.
Definition: stateMachineEngine.cpp:86
void RegisterActionStatic(std::string const &id, std::function< void(Event const &)> action)
Register action for statically known event type.
Definition: stateMachineEngine.hpp:93
Holds context necessary for processing a measure request to completion.
Definition: measurable.hpp:38
void SendErrorReply(std::exception_ptr eptr) noexcept
If reply is pending, set exception to the provided value.
Definition: measurable.hpp:87
void SetResult(JsonPayload const &result)
Sets serialized reply from JSON payload, but does not send it.
Definition: measurable.hpp:62
MeasureContext(rad::cii::Request< std::string, std::string > const &request)
Construct context with provided request.
Definition: measurable.hpp:46
MeasureContext(MeasureContext &&) noexcept=default
JsonPayload const & GetArg() const noexcept
Definition: measurable.hpp:52
void SendReply() noexcept
Send reply using result set with SetResult().
Definition: measurable.hpp:71
Provides macros and utilities for exception handling.
log4cplus::Logger & GetLogger(const std::string &name="app")
Get handle to a specific logger.
Definition: logger.cpp:180
Defines the JSON payload type JsonPayload.
Logging Support Library based on log4cplus.
Implementation of MAL commands for layer 'Measurable'.
Definition: commandReplier.cpp:22
nlohmann::json JsonPayload
Type requirements:
Definition: jsonPayload.hpp:25
rad::StopToken StopToken
Definition: stopToken.hpp:20
@ Simple
Definition: model.hpp:22
@ Composite
Definition: model.hpp:22
@ Parallel
Definition: model.hpp:22
@ Initial
Definition: model.hpp:22
Lifecycle of a basic 'RtcComponent'.
A simple Stop Token.
Life cycle extension to make RtcComponent Measurable.
Definition: measurable.hpp:151