$treeview $search $mathjax $extrastylesheet
artdaq
v3_04_01
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #ifndef ARTDAQ_DAQRATE_REQUEST_RECEVIER_HH 00002 #define ARTDAQ_DAQRATE_REQUEST_RECEVIER_HH 00003 00004 #include <boost/thread.hpp> 00005 #include "artdaq-core/Data/Fragment.hh" 00006 #include "fhiclcpp/ParameterSet.h" 00007 #include "fhiclcpp/types/Atom.h" 00008 #include "fhiclcpp/types/ConfigurationTable.h" 00009 00010 #include <mutex> 00011 #include <condition_variable> 00012 00013 namespace artdaq 00014 { 00018 class RequestReceiver 00019 { 00020 public: 00021 00025 struct Config 00026 { 00028 fhicl::Atom<int> request_port{ fhicl::Name{"request_port"}, fhicl::Comment{"Port to listen for request messages on"}, 3001 }; 00030 fhicl::Atom<std::string> request_addr{ fhicl::Name{"request_address"}, fhicl::Comment{"Multicast address to listen for request messages on"}, "227.128.12.26" }; 00032 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" }; 00034 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 }; 00036 fhicl::Atom<artdaq::Fragment::sequence_id_t> request_increment{ fhicl::Name{"request_increment"}, fhicl::Comment{"Expected increment of sequence ID between each request"}, 1 }; 00037 }; 00039 using Parameters = fhicl::WrappedTable<Config>; 00040 00044 RequestReceiver(); 00045 00050 RequestReceiver(const fhicl::ParameterSet& ps); 00051 virtual ~RequestReceiver(); 00052 00056 void setupRequestListener(); 00057 00062 void stopRequestReception(bool force = false); 00063 00067 void startRequestReception(); 00068 00072 void receiveRequestsLoop(); 00073 00078 std::map<artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t> GetRequests() const 00079 { 00080 std::unique_lock<std::mutex> lk(request_mutex_); 00081 std::map<artdaq::Fragment::sequence_id_t, Fragment::timestamp_t> out; 00082 for (auto& in : requests_) 00083 { 00084 out[in.first] = in.second; 00085 } 00086 return out; 00087 } 00088 00093 void RemoveRequest(artdaq::Fragment::sequence_id_t reqID); 00094 00099 bool isRunning() { return running_; } 00100 00104 void ClearRequests() 00105 { 00106 std::unique_lock<std::mutex> lk(request_mutex_); 00107 requests_.clear(); 00108 } 00109 00114 std::map<artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t> GetAndClearRequests() 00115 { 00116 std::unique_lock<std::mutex> lk(request_mutex_); 00117 std::map<artdaq::Fragment::sequence_id_t, Fragment::timestamp_t> out; 00118 for (auto& in : requests_) 00119 { 00120 out[in.first] = in.second; 00121 } 00122 if(requests_.size()) {highest_seen_request_ = requests_.rbegin()->first;} 00123 out_of_order_requests_.clear(); 00124 requests_.clear(); 00125 request_timing_.clear(); 00126 return out; 00127 } 00128 00133 size_t size() { 00134 std::unique_lock<std::mutex> tlk(request_mutex_); 00135 return requests_.size(); 00136 } 00137 00143 bool WaitForRequests(int timeout_ms) 00144 { 00145 std::unique_lock<std::mutex> lk(request_mutex_); // Lock needed by wait_for 00146 // See if we have to wait at all 00147 if (requests_.size() > 0) return true; 00148 // If we do have to wait, check requests_.size to make sure we're not being notified spuriously 00149 return request_cv_.wait_for(lk, std::chrono::milliseconds(timeout_ms), [this]() { return requests_.size() > 0; }); 00150 } 00151 00157 std::chrono::steady_clock::time_point GetRequestTime(artdaq::Fragment::sequence_id_t reqID) 00158 { 00159 std::unique_lock<std::mutex> lk(request_mutex_); 00160 return request_timing_.count(reqID) ? request_timing_[reqID] : std::chrono::steady_clock::now(); 00161 } 00162 00167 void SetRunNumber(uint32_t run) {run_number_ = run;} 00168 private: 00169 // FHiCL-configurable variables. Note that the C++ variable names 00170 // are the FHiCL variable names with a "_" appended 00171 int request_port_; 00172 std::string request_addr_; 00173 std::string multicast_out_addr_; 00174 bool running_; 00175 uint32_t run_number_; 00176 00177 //Socket parameters 00178 int request_socket_; 00179 std::map<artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t> requests_; 00180 std::map<artdaq::Fragment::sequence_id_t, std::chrono::steady_clock::time_point> request_timing_; 00181 std::atomic<bool> request_stop_requested_; 00182 std::chrono::steady_clock::time_point request_stop_timeout_; 00183 std::atomic<bool> request_received_; 00184 size_t end_of_run_timeout_ms_; 00185 std::atomic<bool> should_stop_; 00186 mutable std::mutex request_mutex_; 00187 mutable std::mutex state_mutex_; 00188 std::condition_variable request_cv_; 00189 boost::thread requestThread_; 00190 00191 std::atomic<artdaq::Fragment::sequence_id_t> highest_seen_request_; 00192 std::set<artdaq::Fragment::sequence_id_t> out_of_order_requests_; 00193 artdaq::Fragment::sequence_id_t request_increment_; 00194 }; 00195 } 00196 00197 00198 #endif //ARTDAQ_DAQRATE_REQUEST_RECEVIER_HH