registry.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #pragma once
  2. //
  3. // Copyright (c) 2019-2020 Ivan Baidakou (basiliscos) (the dot dmol at gmail dot com)
  4. //
  5. // Distributed under the MIT Software License
  6. //
  7. #include "plugin_base.h"
  8. #include "link_client.h"
  9. #include "rotor/error_code.h"
  10. #include <string>
  11. #include <unordered_map>
  12. namespace rotor::plugin {
  13. /** \struct registry_plugin_t
  14. *
  15. * \brief handy access to {@link registry_t}, for name registration and discovery
  16. *
  17. * Can use {@link registry_t} to register name/address during actor init phase
  18. * and perform the reverse operation to deregister name/address during shutdown phase.
  19. *
  20. * Simialary the {@link registry_t} can be used to discover name in the registry
  21. * and link the current actor to the target address during init phase; there is
  22. * no reverse operation during shutdown phase, because unlinking will be handled
  23. * by {@link plugin::link_client_plugin_t} plugin.
  24. *
  25. */
  26. struct registry_plugin_t : public plugin_base_t {
  27. using plugin_base_t::plugin_base_t;
  28. /** \brief phase for each discovery task: discovering or linking */
  29. enum class phase_t { discovering, linking };
  30. /** \struct discovery_task_t
  31. * \brief helper class to invoke callback upon address discovery
  32. */
  33. struct discovery_task_t {
  34. /** \brief callback for the discovery progress */
  35. using callback_t = std::function<void(phase_t phase, const extended_error_ptr_t &)>;
  36. /** \brief stat of the discovery task */
  37. enum class state_t { PASSIVE, DISCOVERING, LINKING, OPERATIONAL, CANCELLING };
  38. /** \brief sets that linking should be performed on operational-only discovered address */
  39. discovery_task_t &link(bool operational_only_ = true) noexcept {
  40. link_on_discovery = true;
  41. operational_only = operational_only_;
  42. return *this;
  43. }
  44. /** \brief discovery progress callback setter */
  45. template <typename Callback> void callback(Callback &&cb) noexcept {
  46. task_callback = std::forward<Callback>(cb);
  47. }
  48. /** \brief generic non-public methods accessor */
  49. template <typename T, typename... Args> auto access(Args... args) noexcept;
  50. private:
  51. discovery_task_t(registry_plugin_t &plugin_, address_ptr_t *address_, std::string service_name_, bool delayed_)
  52. : plugin{plugin_},
  53. address(address_), service_name{service_name_}, delayed{delayed_}, state{state_t::PASSIVE} {}
  54. operator bool() const noexcept { return address; }
  55. void do_discover() noexcept;
  56. void on_discovery(address_ptr_t *service_addr, const extended_error_ptr_t &ec) noexcept;
  57. bool do_cancel() noexcept;
  58. void post_discovery(const extended_error_ptr_t &ec) noexcept;
  59. registry_plugin_t &plugin;
  60. address_ptr_t *address;
  61. std::string service_name;
  62. bool delayed;
  63. state_t state;
  64. request_id_t request_id = 0;
  65. callback_t task_callback;
  66. bool link_on_discovery = false;
  67. bool operational_only = false;
  68. friend struct registry_plugin_t;
  69. };
  70. /** The plugin unique identity to allow further static_cast'ing*/
  71. static const void *class_identity;
  72. const void *identity() const noexcept override;
  73. void activate(actor_base_t *actor) noexcept override;
  74. /** \brief reaction on registration response */
  75. virtual void on_registration(message::registration_response_t &) noexcept;
  76. /** \brief reaction on discovery response */
  77. virtual void on_discovery(message::discovery_response_t &) noexcept;
  78. /** \brief reaction on discovery future */
  79. virtual void on_future(message::discovery_future_t &message) noexcept;
  80. /** \brief enqueues name/address registration
  81. *
  82. * It links with registry actor first upon demand, and then sends to it
  83. * name registration request(s).
  84. */
  85. virtual void register_name(const std::string &name, const address_ptr_t &address) noexcept;
  86. /** \brief creates name discovery task
  87. *
  88. * The address pointer is the place, where the discovered address should be stored.
  89. *
  90. * The `delayed` means: if the name is missing in the registry, do not response
  91. * with error (which will cause shutdown of client), but wait until the name be
  92. * registered, and only then reply with found address. In other words: instead
  93. * of sending discovery request, it will send discovery future.
  94. *
  95. */
  96. virtual discovery_task_t &discover_name(const std::string &name, address_ptr_t &address,
  97. bool delayed = false) noexcept;
  98. bool handle_shutdown(message::shutdown_request_t *message) noexcept override;
  99. bool handle_init(message::init_request_t *message) noexcept override;
  100. /** \brief generic non-public fields accessor */
  101. template <typename T> auto &access() noexcept;
  102. /** \brief service name to task mapping */
  103. using discovery_map_t = std::unordered_map<std::string, discovery_task_t>;
  104. private:
  105. enum class state_t { REGISTERING, LINKING, OPERATIONAL, UNREGISTERING };
  106. struct register_info_t {
  107. address_ptr_t address;
  108. state_t state;
  109. };
  110. using register_map_t = std::unordered_map<std::string, register_info_t>;
  111. enum plugin_state_t : std::uint32_t {
  112. CONFIGURED = 1 << 0,
  113. LINKING = 1 << 1,
  114. LINKED = 1 << 2,
  115. };
  116. std::uint32_t plugin_state = 0;
  117. register_map_t register_map;
  118. discovery_map_t discovery_map;
  119. void link_registry() noexcept;
  120. void on_link(const extended_error_ptr_t &ec) noexcept;
  121. bool has_registering() noexcept;
  122. virtual void continue_init(const error_code_t &possible_ec, const extended_error_ptr_t &root_ec) noexcept;
  123. };
  124. } // namespace rotor::plugin