RTC Toolkit  2.0.0
rtcComponentMain.hpp
Go to the documentation of this file.
1 
12 #ifndef RTCTK_COMPONENTFRAMEWORK_RTCCOMPONENTMAIN_HPP
13 #define RTCTK_COMPONENTFRAMEWORK_RTCCOMPONENTMAIN_HPP
14 
15 #include <mal/Cii.hpp>
16 #include <memory>
17 #include <string>
18 
20 
33 
34 #include <rtctk/componentFramework/events.rad.hpp> // TODO: should not be needed
35 
36 namespace rtctk::componentFramework {
38 }
39 
50 
51 
52 namespace rtctk::componentFramework {
53 
70 template <class BL, class BLF>
71 void RunAsRtcComponent(Args const& args, BLF factory) {
72  using namespace std;
73 
74  auto component_name = args.GetComponentName();
75  LOG4CPLUS_INFO(GetLogger(), "RtcComponent '" << component_name << "' started.");
76  LOG4CPLUS_DEBUG(GetLogger(), "BusinessLogic is '" << detail::GetTypeName(typeid(BL)) << "'");
77 
78  ServiceContainer services;
79 
80  auto svc_disc_endpoint = args.GetServiceDiscEndpoint();
81  services.Add<ServiceDiscovery>(
82  make_unique<ServiceDiscovery>(std::make_unique<FileServiceRegistryAdapter>(svc_disc_endpoint), component_name));
83 
84  ServiceDiscovery& svc_disc = services.Get<ServiceDiscovery>();
85 
86  // Runtime repository
87  auto rtr_endpoint = svc_disc.GetRuntimeRepoEndpoint();
88  auto rtr_adapter = std::shared_ptr(RuntimeRepoIf::CreateAdapter(rtr_endpoint));
89  services.Add<RuntimeRepoIf>(rtr_adapter);
90 
91  // OLDB
92  auto oldb_endpoint = svc_disc.GetOldbEndpoint();
93  auto oldb_adapter = std::shared_ptr(OldbIf::CreateAdapter(oldb_endpoint));
94  services.Add<OldbIf>(oldb_adapter);
95 
96  // Telemetry service
97  auto component_metrics = std::make_shared<ComponentMetrics>(
98  oldb_adapter,
99  DataPointPath("/") / DataPointPath(component_name) / DataPointPath("metrics/default"),
100  GetLogger());
101  services.Add<ComponentMetricsIf>(component_metrics);
102  ComponentMetricsConfigurator component_metrics_configurator(
103  component_metrics,
104  rtr_adapter,
105  DataPointPath("/") / DataPointPath(component_name) / DataPointPath("dynamic/metrics/default"),
106  GetLogger());
107 
108  // Event Service
109  auto event_service = std::make_shared<MalDdsEventService>();
110  services.Add<EventServiceIf>(event_service);
111 
112  // Alert service and standard observers
113  auto alert_service = std::make_shared<AlertService>(GetLogger());
114  AlertLogger alert_logger(GetLogger(), *alert_service);
115  AlertEventPublisher alert_publisher(component_name, *alert_service, *event_service, GetLogger());
116  services.Add<AlertServiceIf>(alert_service);
117 
118  auto rr_endpoint = svc_disc.GetReqRepEndpoint();
119  CommandReplier replier(rr_endpoint);
120 
121  auto ps_endpoint = svc_disc.GetPubSubEndpoint();
122  StatePublisher publisher(ps_endpoint, component_name);
123 
124  StateMachineEngine engine(make_unique<events::Exit>());
125 
126  engine.RegisterStateChangeHandler([&](string const& state) {
127  publisher.PublishState(state);
128  OldbIf& oldb = services.Get<OldbIf>();
129  DataPointPath dp_name = DataPointPath("/" + component_name + "/state");
130  if (not oldb.DataPointExists(dp_name)) {
131  oldb.CreateDataPoint<std::string>(dp_name);
132  }
133  oldb.SetDataPoint(dp_name, state);
134  });
135 
136  static_assert(is_base_of_v<typename BL::ComponentType::BizLogicIf, BL>,
137  "BusinessLogic must implement BusinessLogicInterface");
138 
139  static_assert(is_invocable_v<BLF, string const&, ServiceContainer&>,
140  "Factory must be invocable with 'std::string const&' and 'ServiceContainer&'");
141 
142  static_assert(is_same_v<invoke_result_t<BLF, string const&, ServiceContainer&>, unique_ptr<BL>>,
143  "Factory must return type 'std::unique_ptr<BusinessLogic>'");
144 
145  // Invoking user factory here -> catch and rethrow RtctkException
146  unique_ptr<BL> biz_logic;
147  try {
148  biz_logic = invoke(factory, component_name, services);
149  if (!biz_logic) {
150  throw std::runtime_error("BusinessLogic factory did not return a valid object");
151  }
152  } catch (...) {
153  std::throw_with_nested(RtctkException("BusinessLogic factory failed"));
154  }
155 
156  typename BL::ComponentType::InputStage input_stage(replier, engine);
157 
158  typename BL::ComponentType::OutputStage output_stage(engine, *biz_logic);
159 
160  typename BL::ComponentType::ModelBuilder model_builder(engine);
161 
162  if (auto emf = args.GetModelExportFile(); emf) {
163  model_builder.ExportModel(emf->path().to_string());
164  }
165 
166  model_builder.RegisterModel();
167  input_stage.Start();
168  component_metrics->StartMonitoring();
169  engine.Work();
170 
171  LOG4CPLUS_INFO(GetLogger(), "RtcComponent '" << component_name << "' terminated.");
172 }
173 
185 template <class BL>
186 void RunAsRtcComponent(Args const& args) {
187  using namespace std;
188 
189  static_assert(
190  is_constructible_v<BL, string const&, ServiceContainer&>,
191  "BusinessLogic must be constructible with 'std::string const&' and 'ServiceContainer&'");
192 
193  RunAsRtcComponent<BL>(args, make_unique<BL, string const&, ServiceContainer&>);
194 }
195 
196 } // namespace rtctk::componentFramework
197 
198 #ifndef RTCTK_NOMAIN
199 namespace rtctk::componentFramework {
200 
207 int Main(int argc, char* argv[]) {
208  LogInitializer initializer;
209 
210  try {
211  Args args{argc, argv};
212 
213  auto component_name = args.GetComponentName();
214  auto log_props_file = args.GetLogPropsFile();
215 
216  if (log_props_file.has_value()) {
217  auto props_file = log_props_file.value().path().to_string();
218  LogConfigure(props_file);
219  SetDefaultLogger(component_name);
220  LOG4CPLUS_INFO(GetLogger(), "Custom log properties file loaded: " << props_file);
221  } else {
222  LogConfigure();
223  MakeLogger(component_name, log4cplus::INFO_LOG_LEVEL);
224  SetDefaultLogger(component_name);
225  }
226 
227  // Call user implementation of RtcComponentMain
228  ::RtcComponentMain(args);
229 
230  return EXIT_SUCCESS;
231 
232  } catch (detail::HelpOnly const & e) {
233  std::cout << e.what() << std::endl;
234  return EXIT_SUCCESS;
235  } catch (detail::ArgNotSet const& e) {
236  std::cerr << e.what() << std::endl;
237  } catch (std::exception const& e) {
238  LOG4CPLUS_FATAL(GetLogger(), NestedExceptionPrinter(e));
239  } catch (...) {
240  LOG4CPLUS_FATAL(GetLogger(), NestedExceptionPrinter(std::current_exception()));
241  }
242  return EXIT_FAILURE;
243 }
244 
245 } // namespace rtctk::componentFramework
246 
247 
251 int main(int argc, char* argv[]) {
252  try {
253  return rtctk::componentFramework::Main(argc, argv);
254  } catch (...) {
255  // Note: Use minimal formatting to avoid further exception leaks.
256  // This handler is only here to avoid std::terminate due to exception-leaks.
257  constexpr std::string_view msg =
258  "Caught exception leaked from rtctk::componentFramework::Main\n";
259  std::cerr.write(msg.data(), msg.size());
260  }
261 }
262 #endif // RTCTK_NOMAIN
263 
264 #endif // RTCTK_COMPONENTFRAMEWORK_RTCCOMPONENTMAIN_HPP
serviceContainer.hpp
A container that can hold any type of service.
rtctk::componentFramework::ServiceDiscovery::GetRuntimeRepoEndpoint
ServiceEndpoint GetRuntimeRepoEndpoint()
Get the Runtime Repository Endpoint from the ServiceDiscovery.
Definition: serviceDiscovery.cpp:35
rtctk::componentFramework::detail::GetTypeName
std::string GetTypeName(const std::type_info &tid)
Definition: rtcComponent.hpp:114
commandReplier.hpp
Receive commands via MAL.
rtctk::componentFramework::RepositoryIf::SetDataPoint
void SetDataPoint(const DataPointPath &path, const T value)
Sets a datapoint in the repository.
Definition: repositoryIf.hpp:573
rtctk::componentFramework::detail::HelpOnly
Definition: rtcComponent.hpp:24
rtctk::componentFramework::StateMachineEngine::Work
void Work()
Runs the event loop of the state machine.
Definition: stateMachineEngine.cpp:133
stateMachineEngine.hpp
Wrapper around the SCXML State Machine Engine.
rtctk::componentFramework::ServiceContainer::Get
Service & Get(const std::string &name="")
Get a handle to a service.
Definition: serviceContainer.hpp:85
rtctk::componentFramework::detail::ArgNotSet
Definition: rtcComponent.hpp:30
rtctk::componentFramework::LogConfigure
void LogConfigure(const std::string &cfg_file_name="")
Initial logging system configuration.
componentMetrics.hpp
Declares ComponentMetrics.
rtctk::componentFramework::ServiceContainer::Add
void Add(Service &&service, const std::string &name="")
Insert new service into the container.
Definition: serviceContainer.hpp:48
statePublisher.hpp
Publishes the stdif state topic via MAL.
rtctk::componentFramework::Args
detail::Args Args
Definition: rtcComponentMain.hpp:37
rtctk::componentFramework
Definition: commandReplier.cpp:20
serviceDiscovery.hpp
Class that implements a very basic service discover mechanism.
RtcComponentMain
void RtcComponentMain(rtctk::componentFramework::Args const &args)
Main entry point for user code, method must be implemented by component developers.
Definition: main.cpp:22
rtctk::componentFramework::RepositoryIf::DataPointExists
virtual bool DataPointExists(const DataPointPath &path) const =0
Checks for the existence of a datapoint in the repository.
rtctk::componentFramework::StatePublisher
Class used to publish state-changed-topic using MAL.
Definition: statePublisher.hpp:33
malDdsEventService.hpp
Implementation of the event service.
rtctk::componentFramework::ServiceDiscovery
Class that implements a very basic service discovery mechanism.
Definition: serviceDiscovery.hpp:29
rtctk::componentFramework::detail::Args
Definition: rtcComponent.hpp:38
rtctk::componentFramework::RtctkException
The RtctkException class is the base class for all Rtctk exceptions.
Definition: exceptions.hpp:207
rtcComponent.hpp
Provides details for core functionality of an RTC Component.
rtctk::componentFramework::StateMachineEngine
Definition: stateMachineEngine.hpp:31
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::AlertEventPublisher
Alert observer that publishes alerts to event service using the typed event AlertStatusEvent.
Definition: alertService.hpp:100
rtctk::componentFramework::ComponentMetricsIf
Component metrics interface.
Definition: componentMetricsIf.hpp:177
rtctk::componentFramework::RuntimeRepoIf::CreateAdapter
static std::unique_ptr< RuntimeRepoIf > CreateAdapter(const elt::mal::Uri &uri)
Factory method used to create the appropriate Runtime Configuration Repository adapter depending on t...
Definition: runtimeRepoIf.cpp:18
rtctk::componentFramework::LogInitializer
RAII class to clean-up logging without leaking memory.
Definition: logger.hpp:23
rtctk::componentFramework::GetLogger
log4cplus::Logger & GetLogger(const std::string &name="")
Get handle to a specific logger (used with logging macros)
rtctk::componentFramework::StatePublisher::PublishState
void PublishState(const std::string &state)
Definition: statePublisher.cpp:36
rtctk::componentFramework::AlertLogger
Simple alert observer that writes alerts to log.
Definition: alertService.hpp:84
rtctk::componentFramework::ServiceContainer
Container class that holds services of any type.
Definition: serviceContainer.hpp:35
rtctk::componentFramework::ComponentMetricsConfigurator
Configures ComponentMetrics from a runtime repository.
Definition: componentMetrics.hpp:39
rtctk::componentFramework::AlertServiceIf
Alert Service interface.
Definition: alertServiceIf.hpp:303
rtctk::componentFramework::Main
int Main(int argc, char *argv[])
Main function implementation.
Definition: rtcComponentMain.hpp:207
rtctk::componentFramework::detail::Args::GetComponentName
std::string GetComponentName() const
Definition: rtcComponent.hpp:44
main
int main(int argc, char *argv[])
Main function, this is private to the RTC Tk and shall NOT be used by component developers.
Definition: rtcComponentMain.hpp:251
rtctk_ctrl_mon_tool.state
def state(ctx, str component)
Definition: rtctk_ctrl_mon_tool.py:158
rtctk::componentFramework::detail::Args::GetServiceDiscEndpoint
elt::mal::Uri GetServiceDiscEndpoint() const
Definition: rtcComponent.hpp:48
rtctk::componentFramework::OldbIf
Definition: oldbIf.hpp:20
rtctk::componentFramework::CommandReplier
Class that handles reception of commands using MAL.
Definition: commandReplier.hpp:26
rtctk::componentFramework::EventServiceIf
Interface class for providing pub/sub facilities for JSON events.
Definition: eventServiceIf.hpp:26
rtctk::componentFramework::MakeLogger
void MakeLogger(const std::string &name, log4cplus::LogLevel ll, bool log_to_file=true, bool additive=false, log4cplus::LogLevel log_to_console_threshold=log4cplus::NOT_SET_LOG_LEVEL)
Retrieve new logger programmatically.
rtctk::componentFramework::RunAsRtcComponent
void RunAsRtcComponent(Args const &args, BLF factory)
RTC Component runner function, needed to run custom BusinessLogic as RTC Component.
Definition: rtcComponentMain.hpp:71
rtctk::componentFramework::RuntimeRepoIf
Definition: runtimeRepoIf.hpp:20
std
Definition: mudpiProcessingError.hpp:119
rtctk::componentFramework::OldbIf::CreateAdapter
static std::unique_ptr< OldbIf > CreateAdapter(const elt::mal::Uri &uri)
Factory method used to create the appropriate OLDB adapter depending on the URI scheme.
Definition: oldbIf.cpp:18
logger.hpp
Logging Support Library based on log4cplus.
rtctk::componentFramework::StateMachineEngine::RegisterStateChangeHandler
void RegisterStateChangeHandler(StateMethod on_statechange)
Register state changed handler.
Definition: stateMachineEngine.cpp:111
rtctk::componentFramework::SetDefaultLogger
void SetDefaultLogger(const std::string &name)
Set the default logger.
Definition: logger.cpp:66
fileServiceRegistryAdapter.hpp
Class that implements a very basic service discover mechanism.
alertService.hpp
Declares AlertService.
rtctk::componentFramework::RepositoryIf::CreateDataPoint
virtual void CreateDataPoint(const DataPointPath &path, const std::type_info &type)=0
Creates a new datapoint in the repository with a specified type.
rtctk::componentFramework::detail::Args::GetModelExportFile
std::optional< elt::mal::Uri > GetModelExportFile() const
Definition: rtcComponent.hpp:60
rtctk::componentFramework::DataPointPath
This class provides a wrapper for a data point path.
Definition: dataPointPath.hpp:65
runtimeRepoIf.hpp
Header file for RuntimeRepoIf, which defines the API for RuntimeRepoAdapters.
oldbIf.hpp
Header file for OldbIf, which defines the API for OldbAdapters.