RTC Toolkit  2.0.0
optimisable.hpp
Go to the documentation of this file.
1 
12 #ifndef RTCTK_COMPONENTFRAMEWORK_OPTIMISABLE_HPP
13 #define RTCTK_COMPONENTFRAMEWORK_OPTIMISABLE_HPP
14 
20 
21 namespace rtctk::componentFramework {
22 namespace detail {
32 public:
39  OptimiseContext(rad::cii::Request<std::string, std::string> const& request)
40  : m_request(request), m_arg() {
41  m_arg = JsonPayload::parse(m_request.GetRequestPayload());
42  }
44 
48  JsonPayload const& GetArg() const noexcept {
49  return m_arg;
50  }
51 
57  void SendReply() noexcept {
58  try {
59  m_request.SetReplyValue(STD_OK_REPLY);
60  } catch (std::exception const& exception) {
61  LOG4CPLUS_ERROR(
62  GetLogger(),
63  "OptimiseContext::SendReply: Failed to send reply: " << exception.what());
64  } catch (...) {
65  LOG4CPLUS_ERROR(
66  GetLogger(),
67  "OptimiseContext::SendReply: Failed to send reply with unknown exception.");
68  }
69  }
70 
76  void SendErrorReply(std::exception_ptr eptr) noexcept {
77  try {
78  m_request.SetException(
79  RequestFailed(NestedExceptionPrinter(std::move(eptr)).Str()));
80  } catch (...) {
81  }
82  }
83 
84 private:
86  rad::cii::Request<std::string, std::string> m_request;
90  JsonPayload m_arg;
91 };
92 } // namespace detail
93 
121 template <typename Super>
122 struct Optimisable : Super {
123  static_assert(std::is_base_of_v<RtcComponent, Super>, "'Optimisable' requires 'RtcComponent'");
124 
128  class BizLogicIf : public Super::BizLogicIf {
129  public:
140  virtual void ActivityOptimising(StopToken st, JsonPayload const& arg) {
141  }
151  virtual bool GuardOptimisingAllowed(JsonPayload const& arg) {
152  return true;
153  }
154  };
155 
156  class InputStage : public Super::InputStage {
157  public:
158  using Super::InputStage::InputStage;
159 
160  void Start() override {
161  Super::InputStage::Start();
162 
163  OptCmdsImpl::Register(this->m_replier, this->m_engine);
164  }
165  };
166 
167  class OutputStage : public Super::OutputStage {
168  public:
170  // Handlers ###################################################################
171 
172  engine.RegisterRejectHandler<events::Optimise, RequestRejected>();
173 
174  m_optimise_success_handler = [this] {
175  this->m_engine.PostEvent(std::make_unique<events::OptimiseDone>());
176  };
177 
178  m_optimise_error_handler = [this](std::exception_ptr eptr) {
179  this->m_engine.PostEvent(std::make_unique<events::OptimiseError>(eptr));
180  };
181 
182  // No Disable in states ###############################################################
183 
184  this->m_no_disable_in_states.push_back("On:Operational:OptimiseBusy");
185 
186  // No Update in states ################################################################
187 
188  this->m_no_update_in_states.push_back("On:Operational:OptimiseBusy");
189 
190  // No Optimise in states ##############################################################
191 
192  this->m_no_optimise_in_states.push_back("On:Operational:UpdateBusy");
193 
194  // Guards #####################################################################
195 
196  engine.RegisterGuardStatic<events::Optimise>(
197  "GuardOptimisingAllowed",
198  [this](events::Optimise const& ev) -> bool {
207  auto act_state = this->m_engine.GetState();
208  for (auto& s : m_no_optimise_in_states) {
209  if (act_state.find(s) != std::string::npos) {
210  return false;
211  }
212  }
213  detail::OptimiseContext ctx(ev.GetPayload());
214  if (static_cast<BizLogicIf&>(this->m_logic)
215  .GuardOptimisingAllowed(ctx.GetArg())) {
216  // Optimise is allowed so context is stored.
217  // If there's an active context (and correspondingly an active
218  // request being processed something have gone terribly wrong)
219  assert(!m_optimise_ctx);
220  m_optimise_ctx.emplace(std::move(ctx));
221  return true;
222  }
223  return false;
224  });
225 
226  // Activities #####################################################################
227 
228  engine.RegisterActivity(
229  "ActivityOptimising",
230  [this](StopToken stop_token) {
231  assert(m_optimise_ctx);
232  static_cast<BizLogicIf&>(this->m_logic)
233  .ActivityOptimising(stop_token, m_optimise_ctx->GetArg());
234  },
237 
238  // Actions #####################################################################
239  engine.RegisterActionStatic<events::OptimiseDone>(
240  "ActionOptimisingDone",
241  [this](events::OptimiseDone const&) {
242  assert(m_optimise_ctx);
243  m_optimise_ctx->SendReply();
244  m_optimise_ctx.reset();
245  });
246 
247  engine.RegisterActionStatic<events::OptimiseError>(
248  "ActionOptimisingFailed",
249  [this](events::OptimiseError const& ev) {
250  m_optimise_ctx->SendErrorReply(ev.GetPayload());
251  m_optimise_ctx.reset();
252  });
253  }
254 
255  protected:
256  std::optional<detail::OptimiseContext> m_optimise_ctx;
257  std::function<void()> m_optimise_success_handler;
258  std::function<void(std::exception_ptr)> m_optimise_error_handler;
259  std::list<std::string> m_no_optimise_in_states;
260  };
261 
262  class ModelBuilder : public Super::ModelBuilder {
263  public:
265  this->RegisterLayer({"Optimisable", {}});
266 
267  this->mm.AddState(Composite, "On:Operational:RegionOptimise", "On:Operational");
268  this->mm.AddState(Initial, "On:Operational:OptimiseInitial", "On:Operational:RegionOptimise");
269  this->mm.AddState(Simple, "On:Operational:OptimiseIdle", "On:Operational:RegionOptimise");
270  this->mm.AddState(Simple, "On:Operational:OptimiseBusy", "On:Operational:RegionOptimise", "ActivityOptimising");
271 
272  this->mm.AddTrans("On:Operational:OptimiseInitial" , "On:Operational:OptimiseIdle" );
273  this->mm.AddTrans("On:Operational:OptimiseIdle",
274  "On:Operational:OptimiseBusy",
275  events::Optimise::ID,
276  "GuardOptimisingAllowed");
277  this->mm.AddTrans("On:Operational:OptimiseBusy",
278  "On:Operational:OptimiseIdle",
279  events::OptimiseDone::ID,
280  "",
281  "ActionOptimisingDone");
282  this->mm.AddTrans("On:Operational:OptimiseBusy",
283  "On:Operational:OptimiseIdle",
284  events::OptimiseError::ID,
285  "",
286  "ActionOptimisingFailed");
287  }
288  };
289 };
290 
291 } // namespace rtctk::componentFramework
292 
293 #endif
rtctk::componentFramework::detail::OptimiseContext::OptimiseContext
OptimiseContext(rad::cii::Request< std::string, std::string > const &request)
Construct context with provided request.
Definition: optimisable.hpp:39
rtctk::componentFramework::detail::OptimiseContext::OptimiseContext
OptimiseContext(OptimiseContext &&) noexcept=default
rtctk::componentFramework::Simple
@ Simple
Definition: model.hpp:23
rtctk::componentFramework::RequestRejected
Definition: rtcComponent.hpp:34
exceptions.hpp
Provides macros and utilities for exception handling.
rtctk::componentFramework::Optimisable::BizLogicIf::ActivityOptimising
virtual void ActivityOptimising(StopToken st, JsonPayload const &arg)
Activity executed in its own thread that performs the requested optimization.
Definition: optimisable.hpp:140
rtctk::componentFramework::OptCmdsImpl::Register
static void Register(CommandReplier &replier, StateMachineEngine &engine)
Definition: optCmdsImpl.hpp:34
rtctk::componentFramework::Optimisable::ModelBuilder::ModelBuilder
ModelBuilder(StateMachineEngine &engine)
Definition: optimisable.hpp:264
rtctk::componentFramework
Definition: commandReplier.cpp:20
rtctk::componentFramework::Optimisable::OutputStage::m_optimise_error_handler
std::function< void(std::exception_ptr)> m_optimise_error_handler
Definition: optimisable.hpp:258
rtctk::componentFramework::StateMachineEngine::RegisterGuardStatic
void RegisterGuardStatic(std::string const &id, std::function< bool(Event const &)> guard)
Register guard for statically known event type.
Definition: stateMachineEngine.hpp:112
rtctk::rtcSupervisor::Super
Runnable< RtcComponent > Super
Definition: rtcSupervisor.hpp:33
rtctk::componentFramework::STD_OK_REPLY
const std::string STD_OK_REPLY
Definition: stdComponent.hpp:83
rtctk::componentFramework::StopToken
rad::StopToken StopToken
Definition: stopToken.hpp:19
rtctk::componentFramework::StateMachineEngine::RegisterActionStatic
void RegisterActionStatic(std::string const &id, std::function< void(Event const &)> action)
Register action for statically known event type.
Definition: stateMachineEngine.hpp:79
rtctk::componentFramework::StateMachineEngine
Definition: stateMachineEngine.hpp:31
rtctk::componentFramework::Optimisable::BizLogicIf::GuardOptimisingAllowed
virtual bool GuardOptimisingAllowed(JsonPayload const &arg)
Determines if optimising is possible at this time with the provided argument.
Definition: optimisable.hpp:151
rtctk::componentFramework::NestedExceptionPrinter
Adapter object intended to be used in contexts without direct access to the output-stream object.
Definition: exceptions.hpp:157
rtctk::componentFramework::detail::OptimiseContext::SendReply
void SendReply() noexcept
Sends hardcoded string reply.
Definition: optimisable.hpp:57
rtctk::componentFramework::Optimisable::InputStage
Definition: optimisable.hpp:156
rtctk::componentFramework::Optimisable::OutputStage::OutputStage
OutputStage(StateMachineEngine &engine, BizLogicIf &bl)
Definition: optimisable.hpp:169
rtctk::componentFramework::GetLogger
log4cplus::Logger & GetLogger(const std::string &name="")
Get handle to a specific logger (used with logging macros)
rtctk::componentFramework::Optimisable
Life cycle extension to make RtcComponent Optimisable.
Definition: optimisable.hpp:122
rtctk::componentFramework::detail::OptimiseContext::SendErrorReply
void SendErrorReply(std::exception_ptr eptr) noexcept
Send exceptional reply.
Definition: optimisable.hpp:76
rtctk::componentFramework::Optimisable::ModelBuilder
Definition: optimisable.hpp:262
jsonPayload.hpp
Defines the JSON payload type JsonPayload.
rtctk::componentFramework::StateMachineEngine::RegisterRejectHandler
void RegisterRejectHandler(std::string const &id, RejectMethod reject)
Register reject handler.
Definition: stateMachineEngine.cpp:98
stopToken.hpp
A simple Stop Token.
rtctk::componentFramework::Initial
@ Initial
Definition: model.hpp:26
rtctk::componentFramework::Optimisable::InputStage::Start
void Start() override
Definition: optimisable.hpp:160
rtctk::componentFramework::Optimisable::OutputStage
Definition: optimisable.hpp:167
rtcComponent.hpp
Lifecycle of a basic 'RtcComponent'.
rtctk::componentFramework::RequestFailed
Definition: rtcComponent.hpp:44
rtctk::componentFramework::Optimisable::OutputStage::m_no_optimise_in_states
std::list< std::string > m_no_optimise_in_states
Definition: optimisable.hpp:259
rtctk::componentFramework::Optimisable::BizLogicIf
Business logic interface for Optimisable mixin.
Definition: optimisable.hpp:128
rtctk::componentFramework::Composite
@ Composite
Definition: model.hpp:25
rtctk::componentFramework::detail::OptimiseContext
Holds context necessary for processing a optimise request to completion.
Definition: optimisable.hpp:31
rtctk_config_tool.default
default
Enter an interactive shell.
Definition: rtctk_config_tool.py:119
rtctk::componentFramework::Optimisable::OutputStage::m_optimise_success_handler
std::function< void()> m_optimise_success_handler
Definition: optimisable.hpp:257
rtctk::componentFramework::StateMachineEngine::RegisterActivity
void RegisterActivity(std::string const &id, ActivityMethod activity, SuccessMethod on_success, FailureMethod on_failure)
Register activity.
Definition: stateMachineEngine.cpp:90
rtctk::componentFramework::JsonPayload
nlohmann::json JsonPayload
Type requirements:
Definition: jsonPayload.hpp:24
rtctk::componentFramework::detail::OptimiseContext::GetArg
JsonPayload const & GetArg() const noexcept
Definition: optimisable.hpp:48
rtctk::componentFramework::Optimisable::OutputStage::m_optimise_ctx
std::optional< detail::OptimiseContext > m_optimise_ctx
Definition: optimisable.hpp:256
optCmdsImpl.hpp
Implementation of MAL commands for layer 'Optimisable'.