registry.h 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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 "actor_base.h"
  8. #include "messages.hpp"
  9. #include <unordered_map>
  10. #include <set>
  11. #include <list>
  12. namespace rotor {
  13. /** \struct registry_t
  14. * \brief keeps name-to-service_address mapping at runtime
  15. *
  16. * The class solves the following problem: one actor needs to know
  17. * somehow the address of other actor. Instead of tightly couple
  18. * them, i.e. manually binding addresses, it is possible to just
  19. * take the registry everywhere and ask it (or register there)
  20. * just on actor startup (initialization)
  21. *
  22. * The "server-actor" must register it's address first. The name
  23. * must be unique (in the scope of registry); the same address
  24. * can be registered on different names, if need. It is good
  25. * practice to unregister addresses when actor is going to be
  26. * shutdown (it is done by {@link plugin::registry_plugin_t}).
  27. * It is possible to unregister single name, or all
  28. * names associated with an address.
  29. *
  30. * The discovery response returned to "client-actor" might contain
  31. * error code if there is no address associated with the asked name.
  32. *
  33. * The actor has syncornization facilities, i.e. it is possible to
  34. * ask the actor to notify when some name has been registered
  35. * (discovery promise/future).
  36. *
  37. */
  38. struct registry_t : public actor_base_t {
  39. using actor_base_t::actor_base_t;
  40. void configure(plugin::plugin_base_t &plugin) noexcept override;
  41. /** \brief registers address on the service. Fails, if the name already exists */
  42. virtual void on_reg(message::registration_request_t &request) noexcept;
  43. /** \brief deregisters the name in the registry */
  44. virtual void on_dereg_service(message::deregistration_service_t &message) noexcept;
  45. /** \brief deregisters all names assosiccated with the service address */
  46. virtual void on_dereg(message::deregistration_notify_t &message) noexcept;
  47. /** \brief returns service address associated with the name or error */
  48. virtual void on_discovery(message::discovery_request_t &request) noexcept;
  49. /** \brief notify the requestee when service name/address becomes available */
  50. virtual void on_promise(message::discovery_promise_t &request) noexcept;
  51. /** \brief cancels previously asked discovery promise */
  52. virtual void on_cancel(message::discovery_cancel_t &notify) noexcept;
  53. /** \brief generic non-public fields accessor */
  54. template <typename T> auto &access() noexcept;
  55. protected:
  56. /** \brief intrusive pointer to discovery promise message (type) */
  57. using promise_ptr_t = intrusive_ptr_t<message::discovery_promise_t>;
  58. /** \brief list of intrusive pointers to discovery promise messages (type) */
  59. using promises_list_t = std::list<promise_ptr_t>;
  60. /** \brief name-to-address mapping type */
  61. using registered_map_t = std::unordered_map<std::string, address_ptr_t>;
  62. /** \brief set of registered names type (for single address) */
  63. using registered_names_t = std::set<std::string>;
  64. /** \brief service address to registered names mapping type */
  65. using revese_map_t = std::unordered_map<address_ptr_t, registered_names_t>;
  66. /** \brief name-to-address mapping */
  67. registered_map_t registered_map;
  68. /** \brief address-to-list_of_names mapping */
  69. revese_map_t revese_map;
  70. /** \brief list of intrusive pointers to discovery promise messages */
  71. promises_list_t promises;
  72. };
  73. } // namespace rotor