3333#include " Framework/ComputingResource.h"
3434#include " Framework/Logger.h"
3535#include " Framework/RuntimeError.h"
36+ #include " Framework/RawDeviceService.h"
3637#include " ProcessingPoliciesHelpers.h"
3738
3839#include " WorkflowHelpers.h"
@@ -74,12 +75,12 @@ void signal_callback(uv_signal_t* handle, int)
7475struct ExpirationHandlerHelpers {
7576 static RouteConfigurator::CreationConfigurator dataDrivenConfigurator ()
7677 {
77- return [](DeviceState&, ConfigParamRegistry const &) { return LifetimeHelpers::dataDrivenCreation (); };
78+ return [](DeviceState&, ServiceRegistry&, ConfigParamRegistry const &) { return LifetimeHelpers::dataDrivenCreation (); };
7879 }
7980
8081 static RouteConfigurator::CreationConfigurator timeDrivenConfigurator (InputSpec const & matcher)
8182 {
82- return [matcher](DeviceState& state, ConfigParamRegistry const & options) {
83+ return [matcher](DeviceState& state, ServiceRegistry&, ConfigParamRegistry const & options) {
8384 std::string rateName = std::string{" period-" } + matcher.binding ;
8485 auto period = options.get <int >(rateName.c_str ());
8586 // We create a timer to wake us up. Notice the actual
@@ -97,7 +98,7 @@ struct ExpirationHandlerHelpers {
9798
9899 static RouteConfigurator::CreationConfigurator signalDrivenConfigurator (InputSpec const & matcher, size_t inputTimeslice, size_t maxInputTimeslices)
99100 {
100- return [matcher, inputTimeslice, maxInputTimeslices](DeviceState& state, ConfigParamRegistry const & options) {
101+ return [matcher, inputTimeslice, maxInputTimeslices](DeviceState& state, ServiceRegistry&, ConfigParamRegistry const & options) {
101102 std::string startName = std::string{" start-value-" } + matcher.binding ;
102103 std::string endName = std::string{" end-value-" } + matcher.binding ;
103104 std::string stepName = std::string{" step-value-" } + matcher.binding ;
@@ -119,7 +120,7 @@ struct ExpirationHandlerHelpers {
119120
120121 static RouteConfigurator::CreationConfigurator enumDrivenConfigurator (InputSpec const & matcher, size_t inputTimeslice, size_t maxInputTimeslices)
121122 {
122- return [matcher, inputTimeslice, maxInputTimeslices](DeviceState&, ConfigParamRegistry const & options) {
123+ return [matcher, inputTimeslice, maxInputTimeslices](DeviceState&, ServiceRegistry&, ConfigParamRegistry const & options) {
123124 std::string startName = std::string{" start-value-" } + matcher.binding ;
124125 std::string endName = std::string{" end-value-" } + matcher.binding ;
125126 std::string stepName = std::string{" step-value-" } + matcher.binding ;
@@ -164,6 +165,52 @@ struct ExpirationHandlerHelpers {
164165 };
165166 }
166167
168+ static RouteConfigurator::CreationConfigurator fairmqDrivenConfiguration (InputSpec const & spec, int inputTimeslice, int maxInputTimeslices)
169+ {
170+ return [spec, inputTimeslice, maxInputTimeslices](DeviceState& state, ServiceRegistry& services, ConfigParamRegistry const & options) {
171+ std::string channelNameOption = std::string{" out-of-band-channel-name-" } + spec.binding ;
172+ auto channelName = options.get <std::string>(channelNameOption.c_str ());
173+ auto device = services.get <RawDeviceService>().device ();
174+ auto & channel = device->fChannels [channelName];
175+
176+ // We assume there is always a ZeroMQ socket behind.
177+ int zmq_fd = 0 ;
178+ size_t zmq_fd_len = sizeof (zmq_fd);
179+ uv_poll_t * poller = (uv_poll_t *)malloc (sizeof (uv_poll_t ));
180+ channel[0 ].GetSocket ().GetOption (" fd" , &zmq_fd, &zmq_fd_len);
181+ if (zmq_fd == 0 ) {
182+ throw runtime_error_f (" Cannot get file descriptor for channel %s" , channelName.c_str ());
183+ }
184+ LOG (debug) << " Polling socket for " << channel[0 ].GetName ();
185+
186+ state.activeOutOfBandPollers .push_back (poller);
187+
188+ // We always create entries whenever we get invoked.
189+ // Notice this works only if we are the only input.
190+ // Otherwise we should check the channel for new data,
191+ // before we create an entry.
192+ return LifetimeHelpers::enumDrivenCreation (0 , -1 , 1 , inputTimeslice, maxInputTimeslices, 1 );
193+ };
194+ }
195+
196+ static RouteConfigurator::DanglingConfigurator danglingOutOfBandConfigurator ()
197+ {
198+ return [](DeviceState&, ConfigParamRegistry const & options) {
199+ // If the entry is there it means that something awoke
200+ // the loop, so we can materialise it immediately.
201+ return LifetimeHelpers::expireAlways ();
202+ };
203+ }
204+
205+ static RouteConfigurator::ExpirationConfigurator expiringOutOfBandConfigurator (InputSpec const & spec)
206+ {
207+ return [spec](DeviceState&, ConfigParamRegistry const & options) {
208+ std::string channelNameOption = std::string{" out-of-band-channel-name-" } + spec.binding ;
209+ auto channelName = options.get <std::string>(channelNameOption.c_str ());
210+ return LifetimeHelpers::fetchFromFairMQ (spec, channelName);
211+ };
212+ }
213+
167214 static RouteConfigurator::DanglingConfigurator danglingQAConfigurator ()
168215 {
169216 // FIXME: this should really be expireAlways. However, since we do not have
@@ -234,7 +281,7 @@ struct ExpirationHandlerHelpers {
234281 // / This behaves as data. I.e. we never create it unless data arrives.
235282 static RouteConfigurator::CreationConfigurator createOptionalConfigurator ()
236283 {
237- return [](DeviceState&, ConfigParamRegistry const &) { return LifetimeHelpers::dataDrivenCreation (); };
284+ return [](DeviceState&, ServiceRegistry&, ConfigParamRegistry const &) { return LifetimeHelpers::dataDrivenCreation (); };
238285 }
239286
240287 // / This will always exipire an optional record when no data is received.
@@ -663,6 +710,12 @@ void DeviceSpecHelpers::processInEdgeActions(std::vector<DeviceSpec>& devices,
663710 std::nullopt };
664711
665712 switch (consumer.inputs [edge.consumerInputIndex ].lifetime ) {
713+ case Lifetime::OutOfBand:
714+ route.configurator = {
715+ ExpirationHandlerHelpers::fairmqDrivenConfiguration (inputSpec, consumerDevice.inputTimesliceId , consumerDevice.maxInputTimeslices ),
716+ ExpirationHandlerHelpers::danglingOutOfBandConfigurator (),
717+ ExpirationHandlerHelpers::expiringOutOfBandConfigurator (inputSpec)};
718+ break ;
666719 case Lifetime::Condition:
667720 route.configurator = {
668721 ExpirationHandlerHelpers::dataDrivenConfigurator (),
0 commit comments