artdaq  v3_02_01
RequestReceiver.hh
1 #ifndef ARTDAQ_DAQRATE_REQUEST_RECEVIER_HH
2 #define ARTDAQ_DAQRATE_REQUEST_RECEVIER_HH
3 
4 #include <boost/thread.hpp>
5 #include "artdaq-core/Data/Fragment.hh"
6 #include "fhiclcpp/ParameterSet.h"
7 #include "fhiclcpp/types/Atom.h"
8 #if MESSAGEFACILITY_HEX_VERSION >= 0x20103
9 #include "fhiclcpp/types/ConfigurationTable.h"
10 #endif
11 
12 #include <mutex>
13 #include <condition_variable>
14 
15 namespace artdaq
16 {
21  {
22  public:
23 
27  struct Config
28  {
30  fhicl::Atom<int> request_port{ fhicl::Name{"request_port"}, fhicl::Comment{"Port to listen for request messages on"}, 3001 };
32  fhicl::Atom<std::string> request_addr{ fhicl::Name{"request_address"}, fhicl::Comment{"Multicast address to listen for request messages on"}, "227.128.12.26" };
34  fhicl::Atom<std::string> output_address{ fhicl::Name{ "multicast_interface_ip" }, fhicl::Comment{ "Use this hostname for multicast (to assign to the proper NIC)" }, "0.0.0.0" };
36  fhicl::Atom<size_t> end_of_run_timeout_ms{ fhicl::Name{"end_of_run_quiet_timeout_ms"}, fhicl::Comment{"Amount of time (in ms) to wait for no new requests when a Stop transition is pending"}, 1000 };
38  fhicl::Atom<artdaq::Fragment::sequence_id_t> request_increment{ fhicl::Name{"request_increment"}, fhicl::Comment{"Expected increment of sequence ID between each request"}, 1 };
39  };
40 #if MESSAGEFACILITY_HEX_VERSION >= 0x20103
41  using Parameters = fhicl::WrappedTable<Config>;
42 #endif
43 
48 
53  RequestReceiver(const fhicl::ParameterSet& ps);
54  virtual ~RequestReceiver();
55 
59  void setupRequestListener();
60 
65  void stopRequestReceiverThread(bool force = false);
66 
71 
75  void receiveRequestsLoop();
76 
81  std::map<artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t> GetRequests() const
82  {
83  std::unique_lock<std::mutex> lk(request_mutex_);
84  std::map<artdaq::Fragment::sequence_id_t, Fragment::timestamp_t> out;
85  for (auto& in : requests_)
86  {
87  out[in.first] = in.second;
88  }
89  return out;
90  }
91 
96  void RemoveRequest(artdaq::Fragment::sequence_id_t reqID);
97 
102  bool isRunning() { return running_; }
103 
108  {
109  std::unique_lock<std::mutex> lk(request_mutex_);
110  requests_.clear();
111  }
112 
117  size_t size() { return requests_.size(); }
118 
124  bool WaitForRequests(int timeout_ms)
125  {
126  std::unique_lock<std::mutex> lk(request_mutex_);
127  return request_cv_.wait_for(lk, std::chrono::milliseconds(timeout_ms), [this]() { return requests_.size() > 0; });
128  }
129 
135  std::chrono::steady_clock::time_point GetRequestTime(artdaq::Fragment::sequence_id_t reqID)
136  {
137  std::unique_lock<std::mutex> lk(request_mutex_);
138  return request_timing_.count(reqID) ? request_timing_[reqID] : std::chrono::steady_clock::now();
139  }
140  private:
141  // FHiCL-configurable variables. Note that the C++ variable names
142  // are the FHiCL variable names with a "_" appended
143  int request_port_;
144  std::string request_addr_;
145  std::string multicast_out_addr_;
146  bool running_;
147 
148  //Socket parameters
149  int request_socket_;
150  std::map<artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t> requests_;
151  std::map<artdaq::Fragment::sequence_id_t, std::chrono::steady_clock::time_point> request_timing_;
152  std::atomic<bool> request_stop_requested_;
153  std::chrono::steady_clock::time_point request_stop_timeout_;
154  std::atomic<bool> request_received_;
155  size_t end_of_run_timeout_ms_;
156  std::atomic<bool> should_stop_;
157  mutable std::mutex request_mutex_;
158  mutable std::mutex state_mutex_;
159  std::condition_variable request_cv_;
160  boost::thread requestThread_;
161 
162  std::atomic<artdaq::Fragment::sequence_id_t> highest_seen_request_;
163  std::set<artdaq::Fragment::sequence_id_t> out_of_order_requests_;
164  artdaq::Fragment::sequence_id_t request_increment_;
165  };
166 }
167 
168 
169 #endif //ARTDAQ_DAQRATE_REQUEST_RECEVIER_HH
fhicl::Atom< size_t > end_of_run_timeout_ms
&quot;end_of_run_quiet_timeout_ms&quot; (Default: 1000) : Time, in milliseconds, that the entire system must be...
std::chrono::steady_clock::time_point GetRequestTime(artdaq::Fragment::sequence_id_t reqID)
Get the time a given request was received
void startRequestReceiverThread()
Function that launches the data request receiver thread (receiveRequestsLoop())
size_t size()
Get the number of requests currently stored in the RequestReceiver
fhicl::Atom< std::string > request_addr
&quot;request_address&quot; (Default: &quot;227.128.12.26&quot;) : Address which CommandableFragmentGenerator will listen...
fhicl::Atom< std::string > output_address
&quot;multicast_interface_ip&quot; (Default: &quot;0.0.0.0&quot;) : Use this hostname for multicast(to assign to the prop...
RequestReceiver()
RequestReceiver Default Constructor.
bool isRunning()
Determine if the RequestReceiver is receiving requests
void stopRequestReceiverThread(bool force=false)
Stop the data request receiver thread (receiveRequestsLoop)
void setupRequestListener()
Opens the socket used to listen for data requests.
void receiveRequestsLoop()
This function receives data request packets, adding new requests to the request list.
Receive data requests and make them available to CommandableFragmentGenerator or other interested par...
void ClearRequests()
Clear all requests from the map
bool WaitForRequests(int timeout_ms)
Wait for a new request message, up to the timeout given
fhicl::Atom< int > request_port
&quot;request_port&quot; (Default: 3001) : Port on which data requests will be received
void RemoveRequest(artdaq::Fragment::sequence_id_t reqID)
Remove the request with the given sequence ID from the request map
fhicl::Atom< artdaq::Fragment::sequence_id_t > request_increment
&quot;request_increment&quot; (Default: 1) : Expected increment of sequence ID between each request ...
std::map< artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t > GetRequests() const
Get the current requests
Configuration of the RequestReceiver. May be used for parameter validation