1 #include "artdaq/DAQdata/Globals.hh"
2 #define TRACE_NAME (app_name + "_RequestBuffer").c_str() // include these 2 first -
4 #include "artdaq/DAQrate/RequestBuffer.hh"
6 artdaq::RequestBuffer::RequestBuffer(artdaq::Fragment::sequence_id_t request_increment)
10 , highest_seen_request_(0)
11 , last_next_request_(0)
12 , out_of_order_requests_()
13 , request_increment_(request_increment)
14 , receiver_running_(false)
18 artdaq::RequestBuffer::~RequestBuffer() {}
20 void artdaq::RequestBuffer::push(artdaq::Fragment::sequence_id_t seq, artdaq::Fragment::timestamp_t ts)
22 std::lock_guard<std::mutex> tlk(request_mutex_);
23 if (requests_.count(seq) && requests_[seq] != ts)
25 TLOG(TLVL_ERROR) <<
"Received conflicting request for SeqID "
27 <<
" Old ts=" << requests_[seq]
28 <<
", new ts=" << ts <<
". Keeping OLD!";
30 else if (!requests_.count(seq))
32 int delta = seq - highest_seen_request_;
33 TLOG(11) <<
"Received request for sequence ID " << seq
34 <<
" and timestamp " << ts <<
" (delta: " << delta <<
")";
35 if (delta <= 0 || out_of_order_requests_.count(seq))
37 TLOG(11) <<
"Already serviced this request ( sequence ID " << seq <<
")! Ignoring...";
42 request_timing_[seq] = std::chrono::steady_clock::now();
45 request_cv_.notify_all();
48 void artdaq::RequestBuffer::reset()
51 request_timing_.clear();
52 highest_seen_request_ = 0;
53 last_next_request_ = 0;
54 out_of_order_requests_.clear();
64 std::lock_guard<std::mutex> lk(request_mutex_);
65 std::map<artdaq::Fragment::sequence_id_t, Fragment::timestamp_t> out;
66 for (
auto& in : requests_)
68 out[in.first] = in.second;
75 std::lock_guard<std::mutex> lk(request_mutex_);
77 auto it = requests_.begin();
78 while (it != requests_.end() && it->first <= last_next_request_) { ++it; }
80 if (it == requests_.end())
82 return std::make_pair<artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t>(0, 0);
85 last_next_request_ = it->first;
91 TLOG(10) <<
"RemoveRequest: Removing request for id " << reqID;
92 std::lock_guard<std::mutex> lk(request_mutex_);
93 requests_.erase(reqID);
95 if (reqID > highest_seen_request_)
97 TLOG(10) <<
"RemoveRequest: out_of_order_requests_.size() == " << out_of_order_requests_.size() <<
", reqID=" << reqID <<
", expected=" << highest_seen_request_ + request_increment_;
98 if (out_of_order_requests_.size() || reqID != highest_seen_request_ + request_increment_)
100 out_of_order_requests_.insert(reqID);
102 auto it = out_of_order_requests_.begin();
103 while (it != out_of_order_requests_.end())
105 if (*it == highest_seen_request_ + request_increment_)
107 highest_seen_request_ = *it;
108 it = out_of_order_requests_.erase(it);
118 highest_seen_request_ = reqID;
120 TLOG(10) <<
"RemoveRequest: reqID=" << reqID <<
" Setting highest_seen_request_ to " << highest_seen_request_;
122 if (metricMan && request_timing_.count(reqID))
124 metricMan->sendMetric(
"Request Response Time", TimeUtils::GetElapsedTime(request_timing_[reqID]),
"seconds", 2, MetricMode::Average);
126 request_timing_.erase(reqID);
135 std::lock_guard<std::mutex> lk(request_mutex_);
146 std::lock_guard<std::mutex> lk(request_mutex_);
147 std::map<artdaq::Fragment::sequence_id_t, Fragment::timestamp_t> out;
148 for (
auto& in : requests_)
150 out[in.first] = in.second;
152 if (requests_.size()) { highest_seen_request_ = requests_.rbegin()->first; }
153 out_of_order_requests_.clear();
155 request_timing_.clear();
166 std::lock_guard<std::mutex> tlk(request_mutex_);
167 return requests_.size();
178 std::unique_lock<std::mutex> lk(request_mutex_);
180 if (requests_.size() > 0)
return true;
182 return request_cv_.wait_for(lk, std::chrono::milliseconds(timeout_ms), [
this]() {
return requests_.size() > 0; });
193 std::lock_guard<std::mutex> lk(request_mutex_);
194 return request_timing_.count(reqID) ? request_timing_[reqID] : std::chrono::steady_clock::now();
void ClearRequests()
Clear all requests from the map
std::map< artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t > GetAndClearRequests()
Get the current requests, then clear the map
std::pair< artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t > GetNextRequest()
Get the "next" request, i.e. the first unsatisfied request that has not already been returned by GetN...
std::map< artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t > GetRequests() const
Get the current requests
std::chrono::steady_clock::time_point GetRequestTime(artdaq::Fragment::sequence_id_t reqID)
Get the time a given request was received
bool WaitForRequests(int timeout_ms)
Wait for a new request message, up to the timeout given
void RemoveRequest(artdaq::Fragment::sequence_id_t reqID)
Remove the request with the given sequence ID from the request map
size_t size()
Get the number of requests currently stored in the RequestReceiver