/* * (c) Copyright, Real-Time Innovations, 2017. * All rights reserved. * * No duplications, whole or partial, manual or electronic, may be made * without express written permission. Any such copies, or * revisions thereof, must display this notice unaltered. * This code contains trade secrets of Real-Time Innovations, Inc. */ #ifndef RTI_ROUTING_SERVICE_HPP_ #define RTI_ROUTING_SERVICE_HPP_ #include #include #include "routingservice/routingservice_adapter_new.h" #include #include #include #include #include namespace rti { namespace routing { /*e \defgroup RTI_RoutingServiceLibModule RTI Routing Library API * \ingroup ROUTER * * @brief @product can be deployed as a native library linked into your * application in select architectures. * * This API allows you to create, configure and start @product instances from * your application. * * The following code shows the typical use of the API: * * \code * * int main () * { * rti::routing::Service service( * rti::routing::ServiceProperty() * .cfg_file("MyRouter.xml") * .cfg_name("MyRouter")); * ... * * service.start(); * * while(keep_running) { * sleep(); * ... * } * * return 0; * } * * \endcode * * Instead of a file, you can use XML strings to configure @product. * See ServiceProperty for more information. *

* To build your application you need to link with the @product native library * in <@ndds home>/bin/<architecture>/ . * * ### Development Requirements * * | | Linux/macOS Systems | Windows Systems | * | --------------: | :----------------: | :-------------: | * | Shared Libraries| libnddscpp2.so | nddscpp2.dll | * | ^ | librtirsinfrastructure.so | rtirsinfrastructure.dll | * | ^ | librtiserviceadmincpp.so | rtiserviceadmincpp.dll | * | ^ | librtidlc.so | rtidlc.dll | * | ^ | librtiapputilsc.so | rtiapputilsc.dll | * | ^ | libnddsmetp.so | nddsmetp.dll | * | ^ | librticonnextmsgc.so | rticonnextmsgc.dll | * | ^ | libnddsc.so | nddsc.dll | * | ^ | librtixml2.so | rtixml2.dll | * | ^ | libnddscore.so | nddscore.dll | * | Headers | rti/routing/RoutingService.hpp || * */ /** \ingroup RTI_RoutingServiceLibModule * * @brief The @product. * */ class Service : public dds::core::Reference { public: typedef RTI::Service::Admin::CommandRequest CommandRequest; typedef RTI::Service::Admin::CommandReply CommandReply; typedef dds::core::Reference Base; OMG_DDS_REF_TYPE_NOTYPENAME( Service, dds::core::Reference, RoutingServiceImpl); /** * @brief Creates a @product instance * * @param property * @rs_st_in The property to configure @product instance. * * @mtsafety On non-Linux, non-Windows systems (i.e. VxWorks): * UNSAFE for multiple threads to simultaneously make the FIRST * call to any of the Service constructors. Subsequent calls are * thread safe. * On Windows and Linux systems, these calls are thread-safe. */ explicit Service(const ServiceProperty& property) : Base(new RoutingServiceImpl(property)) { this->delegate()->remember_reference(this->delegate()); } /** * @brief Creates a @product instance * * A callable shutdown hook can optionally be provided to handle the * shutdown command received through remote administration. Upon reception * of this command, @product will notify the installed hook. * * The following example shows simple implementation of a shutdown hook * that sets a boolean flag to true when invoked: * * \code * * // Hook implementation * struct FlagShutdownHook { * public: * FlagShutdownHook(bool& the_flag) : flag(the_flag) { * flag = false; * } * void operator()() { * flag = true; * } * * bool& flag; * }; * * // Instantiate service with hook * bool my_flag; * FlagShutdownHook my_hook(my_flag) * rti::routing::Service routing_service( * property, * my_hook); * ... * * * \endcode * * * @param[in] property * The property to configure @product instance. * * @param[in] shutdown_hook * Callable object to handle the shutdown command. The expected * type is a void operator()() (C++11 equivalent is * std::function) * * @mtsafety On non-Linux, non-Windows systems (i.e. VxWorks): * UNSAFE for multiple threads to simultaneously make the FIRST * call to any of the Service constructors. Subsequent calls are * thread safe. * On Windows and Linux systems, these calls are thread-safe. */ template Service( const ServiceProperty& property, HookFunc& shutdown_hook) : Base(new RoutingServiceImpl(property, shutdown_hook)) { this->delegate()->remember_reference(this->delegate()); } Service(const RTI_RoutingServiceProperty& property) : Base(new RoutingServiceImpl(property)) { this->delegate()->remember_reference(this->delegate()); } explicit Service(Base::DELEGATE_REF_T reference) : Base(reference) { if (this->delegate()) { this->delegate()->remember_reference(this->delegate()); } } /** * @brief Starts @product. * * This is a non-blocking operation. @product will create its own set of * threads to perform its tasks. */ void start() { this->delegate()->start(); } /** * @brief Stops @product. * * This operation will bloc the instance is fully stopped. */ void stop() { this->delegate()->stop(); } /** * @brief Attaches an Adapter plugin to be used by @product when it is * started. * * By using this function an adapter can be statically compiled, created * in your application and have the service load it, instead of registering * a shared library and a create function in the configuration. * * The name passed in this function is the name that has to be used in the * configuration to instantiate connections from the plugin. * * Example: * * \code * * rti::routing::RoutingService service(property); * * service.attach_adapter_plugin(myAdapter, "MyAdapter"); * * service.start(); * ... * * \endcode * * And our configuration would look like this: * * \code * * * * * * * ... * * * ... * * * * * \endcode * * This function can be called as many times as desired to attach * several plugins. * * @pre Routing Service must not be started * * @param adapter_plugin * @rs_st_in The adapter plugin object to be attached. The object * shall remain alive during the execution of the service. Once the * plugin is attached, the memory is owned by @product and will delete * it upon service stop. * * @param plugin_name * @rs_st_in * The name used for this plugin in the <connection> * tag in the configuration. * */ void attach_adapter_plugin( rti::routing::adapter::AdapterPlugin *adapter_plugin, const std::string& plugin_name) { this->delegate()->attach_adapter_plugin( adapter_plugin, plugin_name); } /** * @brief Attaches a Processor plugin to be used by @product when it is * started. * * @see attach_adapter_plugin */ void attach_processor_plugin( rti::routing::processor::ProcessorPlugin *processor_plugin, const std::string& plugin_name) { this->delegate()->attach_processor_plugin( processor_plugin, plugin_name); } /** * @brief Attaches a Transformation plugin to be used by @product when it * is started. * * @see attach_adapter_plugin */ void attach_transformation_plugin( rti::routing::transf::TransformationPlugin *transformation_plugin, const std::string& plugin_name) { this->delegate()->attach_transformation_plugin( transformation_plugin, plugin_name); } /** * @brief Executes an Administration command on this service. * * This operation directly executes the specified \p request in this * service as if it was directly received from an administration requester. * * The request can represent any of the available administration operations * as documented in the Administration chapter in the user's manual. This * operation gives you an alternative way to control the service using * the same remote administration interface but allowing you to call * the operation directly. * * This operation can also throw an exception if an internal error * occurs. * * Example: * * \code * * using namespace rti::routing; * using namespace RTI::Service; * using namespace RTI::Service::Admin; * * // Instantiate a RoutingServicee * RoutingService service(...); * * // Prepare a request for any command, for example stop the service * CommandRequest request; * request.action(CommandActionKind::UPDATE_ACTION); * request.resource_identifier("/routing_services/MyRouter"); * dds::topic::topic_type_support::to_cdr_buffer( * reinterpret_cast &>(request.octet_body()), * EntityState(EntityStateKind::DISABLED)); * // Execute and check result * CommandReply reply = service.execute_command(request); * if (reply.retcode().underlying() != CommandReplyRetcode::OK_RETCODE) { * Logger.instance().error( * std::string("Command returned: ") + reply.string_body()); * //handle * ... * } * * \endcode * * @param[in] request Representation of the command to be executed * @return The reply with the result of the command execution. * */ CommandReply execute_command(const CommandRequest& request) { return this->delegate()->execute_command(request); } /** * @brief Executes an Administration command on this service. * * Similar to execute_command(const CommandRequest& request) except * the caller provides the CommandReply object. * * @param[out] reply Representation of the reply containing the result of * the operation * @param[in] request Representation of the command to be executed * * @return A reference to the same reply object provided as a parameter */ CommandReply& execute_command( CommandReply& reply, const CommandRequest& request) { return this->delegate()->execute_command(reply, request); } /** * @deprecated Calling this function at the end of the application is no * longer necessary. It will be removed in future versions. */ static void finalize_globals() { rti::routing::Logger::instance().warn( "Calling 'rti::routing::Service::finalize_globals()' is no " "longer necessary and the function will be removed in future " "versions"); } }; typedef Service RoutingService; }} #endif // RTI_ROUTING_SERVICE_HPP_