FairMQ  1.2.0
C++ Message Passing Framework
PluginServices.h
1 /********************************************************************************
2  * Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
3  * *
4  * This software is distributed under the terms of the *
5  * GNU Lesser General Public Licence (LGPL) version 3, *
6  * copied verbatim in the file "LICENSE" *
7  ********************************************************************************/
8 
9 #ifndef FAIR_MQ_PLUGINSERVICES_H
10 #define FAIR_MQ_PLUGINSERVICES_H
11 
12 #include <fairmq/Tools.h>
13 #include <FairMQDevice.h>
14 #include <options/FairMQProgOptions.h>
15 
16 #include <boost/optional.hpp>
17 #include <boost/optional/optional_io.hpp>
18 
19 #include <functional>
20 #include <string>
21 #include <unordered_map>
22 #include <mutex>
23 #include <condition_variable>
24 
25 namespace fair
26 {
27 namespace mq
28 {
29 
38 {
39  public:
40  PluginServices() = delete;
41  PluginServices(FairMQProgOptions* config, std::shared_ptr<FairMQDevice> device)
42  : fConfig{config}
43  , fDevice{device}
44  , fDeviceController()
45  , fDeviceControllerMutex()
46  , fReleaseDeviceControlCondition()
47  {
48  }
49 
50  PluginServices(const PluginServices&) = delete;
51  PluginServices operator=(const PluginServices&) = delete;
52 
54  enum class DeviceState : int
55  {
56  Ok,
57  Error,
58  Idle,
59  InitializingDevice,
60  DeviceReady,
61  InitializingTask,
62  Ready,
63  Running,
64  Paused,
65  ResettingTask,
66  ResettingDevice,
67  Exiting
68  };
69 
70  enum class DeviceStateTransition : int // transition event between DeviceStates
71  {
72  InitDevice,
73  InitTask,
74  Run,
75  Pause,
76  Resume,
77  Stop,
78  ResetTask,
79  ResetDevice,
80  End,
81  ErrorFound
82  };
83 
84  // Control API
85 
90  static auto ToDeviceState(const std::string& state) -> DeviceState { return fkDeviceStateStrMap.at(state); }
91 
96  static auto ToDeviceStateTransition(const std::string& transition) -> DeviceStateTransition { return fkDeviceStateTransitionStrMap.at(transition); }
97 
101  static auto ToStr(DeviceState state) -> std::string { return fkStrDeviceStateMap.at(state); }
102 
106  static auto ToStr(DeviceStateTransition transition) -> std::string { return fkStrDeviceStateTransitionMap.at(transition); }
107 
108  friend auto operator<<(std::ostream& os, const DeviceState& state) -> std::ostream& { return os << ToStr(state); }
109  friend auto operator<<(std::ostream& os, const DeviceStateTransition& transition) -> std::ostream& { return os << ToStr(transition); }
110 
112  auto GetCurrentDeviceState() const -> DeviceState { return fkDeviceStateMap.at(static_cast<FairMQDevice::State>(fDevice->GetCurrentState())); }
113 
119  auto TakeDeviceControl(const std::string& controller) -> void;
120  struct DeviceControlError : std::runtime_error { using std::runtime_error::runtime_error; };
121 
127  auto StealDeviceControl(const std::string& controller) -> void;
128 
132  auto ReleaseDeviceControl(const std::string& controller) -> void;
133 
135  auto GetDeviceController() const -> boost::optional<std::string>;
136 
138  auto WaitForReleaseDeviceControl() -> void;
139 
148  auto ChangeDeviceState(const std::string& controller, const DeviceStateTransition next) -> void;
149 
156  auto SubscribeToDeviceStateChange(const std::string& subscriber, std::function<void(DeviceState /*newState*/)> callback) -> void
157  {
158  fDevice->SubscribeToStateChange(subscriber, [&,callback](FairMQDevice::State newState){
159  callback(fkDeviceStateMap.at(newState));
160  });
161  }
162 
165  auto UnsubscribeFromDeviceStateChange(const std::string& subscriber) -> void { fDevice->UnsubscribeFromStateChange(subscriber); }
166 
167  // Config API
168  struct PropertyNotFoundError : std::runtime_error { using std::runtime_error::runtime_error; };
169 
170  auto PropertyExists(const std::string& key) const -> bool { return fConfig->Count(key) > 0; }
171 
179  template<typename T>
180  auto SetProperty(const std::string& key, T val) -> void
181  {
182  auto currentState = GetCurrentDeviceState();
183  if (currentState == DeviceState::InitializingDevice)
184  {
185  fConfig->SetValue(key, val);
186  }
187  else
188  {
189  throw InvalidStateError{tools::ToString("PluginServices::SetProperty is not supported in device state ", currentState, ". Supported state is ", DeviceState::InitializingDevice, ".")};
190  }
191  }
192  struct InvalidStateError : std::runtime_error { using std::runtime_error::runtime_error; };
193 
200  template<typename T>
201  auto GetProperty(const std::string& key) const -> T {
202  if (PropertyExists(key)) {
203  return fConfig->GetValue<T>(key);
204  }
205  throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key));
206  }
207 
213  auto GetPropertyAsString(const std::string& key) const -> std::string {
214  if (PropertyExists(key)) {
215  return fConfig->GetStringValue(key);
216  }
217  throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key));
218  }
219 
220  auto GetChannelInfo() const -> std::unordered_map<std::string, int> { return fConfig->GetChannelInfo(); }
221 
224  auto GetPropertyKeys() const -> std::vector<std::string> { return fConfig->GetPropertyKeys(); }
225 
231  template<typename T>
232  auto SubscribeToPropertyChange(const std::string& subscriber, std::function<void(const std::string& key, T)> callback) const -> void
233  {
234  fConfig->Subscribe<T>(subscriber, callback);
235  }
236 
239  template<typename T>
240  auto UnsubscribeFromPropertyChange(const std::string& subscriber) -> void { fConfig->Unsubscribe<T>(subscriber); }
241 
247  auto SubscribeToPropertyChangeAsString(const std::string& subscriber, std::function<void(const std::string& key, std::string)> callback) const -> void
248  {
249  fConfig->SubscribeAsString(subscriber, callback);
250  }
251 
254  auto UnsubscribeFromPropertyChangeAsString(const std::string& subscriber) -> void { fConfig->UnsubscribeAsString(subscriber); }
255 
256 
257  static const std::unordered_map<std::string, DeviceState> fkDeviceStateStrMap;
258  static const std::unordered_map<DeviceState, std::string, tools::HashEnum<DeviceState>> fkStrDeviceStateMap;
259  static const std::unordered_map<std::string, DeviceStateTransition> fkDeviceStateTransitionStrMap;
260  static const std::unordered_map<DeviceStateTransition, std::string, tools::HashEnum<DeviceStateTransition>> fkStrDeviceStateTransitionMap;
261  static const std::unordered_map<FairMQDevice::State, DeviceState, tools::HashEnum<FairMQDevice::State>> fkDeviceStateMap;
262  static const std::unordered_map<DeviceStateTransition, FairMQDevice::Event, tools::HashEnum<DeviceStateTransition>> fkDeviceStateTransitionMap;
263 
264  private:
265  FairMQProgOptions* fConfig; // TODO make it a shared pointer, once old AliceO2 code is cleaned up
266  std::shared_ptr<FairMQDevice> fDevice;
267  boost::optional<std::string> fDeviceController;
268  mutable std::mutex fDeviceControllerMutex;
269  std::condition_variable fReleaseDeviceControlCondition;
270 }; /* class PluginServices */
271 
272 } /* namespace mq */
273 } /* namespace fair */
274 
275 #endif /* FAIR_MQ_PLUGINSERVICES_H */
Facilitates communication between devices and plugins.
Definition: PluginServices.h:37
auto StealDeviceControl(const std::string &controller) -> void
Become device controller by force.
Definition: PluginServices.cxx:133
auto UnsubscribeFromPropertyChange(const std::string &subscriber) -> void
Unsubscribe from property updates of type T.
Definition: PluginServices.h:240
auto TakeDeviceControl(const std::string &controller) -> void
Become device controller.
Definition: PluginServices.cxx:112
auto SubscribeToPropertyChange(const std::string &subscriber, std::function< void(const std::string &key, T)> callback) const -> void
Subscribe to property updates of type T.
Definition: PluginServices.h:232
static auto ToStr(DeviceStateTransition transition) -> std::string
Convert DeviceStateTransition to string.
Definition: PluginServices.h:106
auto UnsubscribeFromDeviceStateChange(const std::string &subscriber) -> void
Unsubscribe from device state changes.
Definition: PluginServices.h:165
static auto ToStr(DeviceState state) -> std::string
Convert DeviceState to string.
Definition: PluginServices.h:101
Definition: Transports.h:53
auto GetCurrentDeviceState() const -> DeviceState
Definition: PluginServices.h:112
Definition: PluginServices.h:120
auto GetPropertyAsString(const std::string &key) const -> std::string
Read config property as string.
Definition: PluginServices.h:213
Definition: FairMQProgOptions.h:41
auto ReleaseDeviceControl(const std::string &controller) -> void
Release device controller role.
Definition: PluginServices.cxx:140
auto SubscribeToDeviceStateChange(const std::string &subscriber, std::function< void(DeviceState)> callback) -> void
Subscribe with a callback to device state changes.
Definition: PluginServices.h:156
Definition: PluginServices.h:168
static auto ToDeviceState(const std::string &state) -> DeviceState
Convert string to DeviceState.
Definition: PluginServices.h:90
auto GetProperty(const std::string &key) const -> T
Read config property.
Definition: PluginServices.h:201
auto SubscribeToPropertyChangeAsString(const std::string &subscriber, std::function< void(const std::string &key, std::string)> callback) const -> void
Subscribe to property updates.
Definition: PluginServices.h:247
DeviceState
See https://github.com/FairRootGroup/FairRoot/blob/dev/fairmq/docs/Device.md#13-state-machine.
Definition: PluginServices.h:54
auto SetProperty(const std::string &key, T val) -> void
Set config property.
Definition: PluginServices.h:180
auto UnsubscribeFromPropertyChangeAsString(const std::string &subscriber) -> void
Unsubscribe from property updates that convert to string.
Definition: PluginServices.h:254
Definition: PluginServices.h:192
static auto ToDeviceStateTransition(const std::string &transition) -> DeviceStateTransition
Convert string to DeviceStateTransition.
Definition: PluginServices.h:96
auto WaitForReleaseDeviceControl() -> void
Block until control is released.
Definition: PluginServices.cxx:165
Definition: DeviceRunner.h:23
auto GetPropertyKeys() const -> std::vector< std::string >
Discover the list of property keys.
Definition: PluginServices.h:224
auto ChangeDeviceState(const std::string &controller, const DeviceStateTransition next) -> void
Request a device state transition.
Definition: PluginServices.cxx:93
auto GetDeviceController() const -> boost::optional< std::string >
Get current device controller.
Definition: PluginServices.cxx:158