artdaq  v3_02_00
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 {
18  {
19  public:
20 
21  struct Config
22  {
23  fhicl::Atom<int> request_port{ fhicl::Name{"request_port"}, fhicl::Comment{"Port to listen for request messages on"}, 3001 };
24  fhicl::Atom<std::string> request_addr{ fhicl::Name{"request_address"}, fhicl::Comment{"Multicast address to listen for request messages on"}, "227.128.12.26" };
25  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" };
26  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 };
27  };
28 #if MESSAGEFACILITY_HEX_VERSION >= 0x20103
29  using Parameters = fhicl::WrappedTable<Config>;
30 #endif
31 
33  RequestReceiver(const fhicl::ParameterSet& ps);
34  virtual ~RequestReceiver();
35 
39  void setupRequestListener();
40 
45 
50 
54  void receiveRequestsLoop();
55 
56  std::map<artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t> GetRequests() const
57  {
58  std::unique_lock<std::mutex> lk(request_mutex_);
59  std::map<artdaq::Fragment::sequence_id_t, Fragment::timestamp_t> out;
60  for (auto& in : requests_)
61  {
62  out[in.first] = in.second;
63  }
64  return out;
65  }
66 
67  void RemoveRequest(artdaq::Fragment::sequence_id_t reqID);
68 
69  bool isRunning() { return running_; }
70 
71  void ClearRequests()
72  {
73  std::unique_lock<std::mutex> lk(request_mutex_);
74  requests_.clear();
75  }
76 
77  size_t size() { return requests_.size(); }
78 
79  bool WaitForRequests(int timeout_ms)
80  {
81  std::unique_lock<std::mutex> lk(request_mutex_);
82  return request_cv_.wait_for(lk, std::chrono::milliseconds(timeout_ms), [this]() { return requests_.size() > 0; });
83  }
84  private:
85  // FHiCL-configurable variables. Note that the C++ variable names
86  // are the FHiCL variable names with a "_" appended
87  int request_port_;
88  std::string request_addr_;
89  std::string multicast_out_addr_;
90  bool running_;
91 
92  //Socket parameters
93  int request_socket_;
94  std::map<artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t> requests_;
95  std::map<artdaq::Fragment::sequence_id_t, std::chrono::steady_clock::time_point> request_timing_;
96  std::atomic<bool> request_stop_requested_;
97  std::chrono::steady_clock::time_point request_stop_timeout_;
98  std::atomic<bool> request_received_;
99  size_t end_of_run_timeout_ms_;
100  std::atomic<bool> should_stop_;
101  mutable std::mutex request_mutex_;
102  mutable std::mutex state_mutex_;
103  std::condition_variable request_cv_;
104  boost::thread requestThread_;
105 
106  std::atomic<artdaq::Fragment::sequence_id_t> highest_seen_request_;
107  };
108 }
109 
110 
111 #endif //ARTDAQ_DAQRATE_REQUEST_RECEVIER_HH
void startRequestReceiverThread()
Function that launches 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.
void stopRequestReceiverThread()
Stop the data request receiver thread (receiveRequestsLoop)