artdaq  v3_09_03
BoardReaderApp.cc
1 #include "artdaq/Application/BoardReaderApp.hh"
2 #include "artdaq-core/Utilities/ExceptionHandler.hh"
3 
4 #include "artdaq/DAQdata/Globals.hh"
5 #define TRACE_NAME (app_name + "_BoardReaderApp").c_str() // NOLINT
6 
7 #include <memory>
8 #include <string>
9 
11  : fragment_receiver_ptr_(nullptr)
12 {
13 }
14 
15 // *******************************************************************
16 // *** The following methods implement the state machine operations.
17 // *******************************************************************
18 
19 bool artdaq::BoardReaderApp::do_initialize(fhicl::ParameterSet const& pset, uint64_t timeout, uint64_t timestamp)
20 {
21  report_string_ = "";
22  external_request_status_ = true;
23 
24  // in the following block, we first destroy the existing BoardReader
25  // instance, then create a new one. Doing it in one step does not
26  // produce the desired result since that creates a new instance and
27  // then deletes the old one, and we need the opposite order.
28  TLOG(TLVL_DEBUG) << "Initializing first deleting old instance " << static_cast<void*>(fragment_receiver_ptr_.get());
29  fragment_receiver_ptr_.reset(nullptr);
30  fragment_receiver_ptr_ = std::make_unique<BoardReaderCore>(*this);
31  TLOG(TLVL_DEBUG) << "Initializing new BoardReaderCore at " << static_cast<void*>(fragment_receiver_ptr_.get()) << " with pset " << pset.to_string();
32  external_request_status_ = fragment_receiver_ptr_->initialize(pset, timeout, timestamp);
33  if (!external_request_status_)
34  {
35  report_string_ = "Error initializing ";
36  report_string_.append(app_name + " ");
37  report_string_.append("with ParameterSet = \"" + pset.to_string() + "\".");
38  }
39 
40  TLOG(TLVL_DEBUG) << "do_initialize(fhicl::ParameterSet, uint64_t, uint64_t): "
41  << "Done initializing.";
42  return external_request_status_;
43 }
44 
45 bool artdaq::BoardReaderApp::do_start(art::RunID id, uint64_t timeout, uint64_t timestamp)
46 {
47  report_string_ = "";
48  if (timeout == 0)
49  {
50  timeout = 3600; // seconds
51  }
52  fragment_receiver_ptr_->SetStartTransitionTimeout(timeout);
53  external_request_status_ = true;
54 
55  boost::thread::attributes attrs;
56  attrs.set_stack_size(4096 * 2000); // 8 MB
57  try
58  {
59  fragment_output_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::send_fragments, fragment_receiver_ptr_.get()));
60  fragment_input_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::receive_fragments, fragment_receiver_ptr_.get()));
61  }
62  catch (const boost::exception& e)
63  {
64  std::stringstream exception_string;
65  exception_string << "Caught boost::exception starting Fragment Processing threads: " << boost::diagnostic_information(e) << ", errno=" << errno;
66 
67  ExceptionHandler(ExceptionHandlerRethrow::yes, exception_string.str());
68  }
69 
70  auto start_wait = std::chrono::steady_clock::now();
71  while (!fragment_receiver_ptr_->GetSenderThreadActive() || !fragment_receiver_ptr_->GetReceiverThreadActive())
72  {
73  if (TimeUtils::GetElapsedTime(start_wait) > timeout)
74  {
75  TLOG(TLVL_ERROR) << "Timeout occurred waiting for BoardReaderCore threads to start. Timeout = " << timeout << " s, Time waited = " << TimeUtils::GetElapsedTime(start_wait) << " s,"
76  << " Receiver ready: " << std::boolalpha << fragment_receiver_ptr_->GetReceiverThreadActive() << ", Sender ready: " << fragment_receiver_ptr_->GetSenderThreadActive();
77  external_request_status_ = false;
78  break;
79  }
80  usleep(10000);
81  }
82 
83  // Only if starting threads successful
84  if (external_request_status_)
85  {
86  external_request_status_ = fragment_receiver_ptr_->start(id, timeout, timestamp);
87  }
88 
89  if (!external_request_status_)
90  {
91  report_string_ = "Error starting ";
92  report_string_.append(app_name + " ");
93  report_string_.append("for run number ");
94  report_string_.append(boost::lexical_cast<std::string>(id.run()));
95  report_string_.append(", timeout ");
96  report_string_.append(boost::lexical_cast<std::string>(timeout));
97  report_string_.append(", timestamp ");
98  report_string_.append(boost::lexical_cast<std::string>(timestamp));
99  report_string_.append(".");
100  }
101 
102  return external_request_status_;
103 }
104 
105 bool artdaq::BoardReaderApp::do_stop(uint64_t timeout, uint64_t timestamp)
106 {
107  report_string_ = "";
108  external_request_status_ = fragment_receiver_ptr_->stop(timeout, timestamp);
109  if (!external_request_status_)
110  {
111  report_string_ = "Error stopping ";
112  report_string_.append(app_name + ".");
113  return false;
114  }
115  if (fragment_input_thread_.joinable())
116  {
117  TLOG(TLVL_DEBUG) << "Joining fragment input (Generator) thread";
118  fragment_input_thread_.join();
119  }
120  if (fragment_output_thread_.joinable())
121  {
122  TLOG(TLVL_DEBUG) << "Joining fragment output (Sender) thread";
123  fragment_output_thread_.join();
124  }
125 
126  TLOG(TLVL_DEBUG) << "BoardReader Stopped. Getting run statistics";
127  int number_of_fragments_sent = -1;
128  if (fragment_receiver_ptr_)
129  {
130  number_of_fragments_sent = fragment_receiver_ptr_->GetFragmentsProcessed();
131  }
132  TLOG(TLVL_DEBUG) << "do_stop(uint64_t, uint64_t): "
133  << "Number of fragments sent = " << number_of_fragments_sent
134  << ".";
135 
136  return external_request_status_;
137 }
138 
139 bool artdaq::BoardReaderApp::do_pause(uint64_t timeout, uint64_t timestamp)
140 {
141  report_string_ = "";
142  external_request_status_ = fragment_receiver_ptr_->pause(timeout, timestamp);
143  if (!external_request_status_)
144  {
145  report_string_ = "Error pausing ";
146  report_string_.append(app_name + ".");
147  }
148 
149  if (fragment_input_thread_.joinable()) fragment_input_thread_.join();
150  if (fragment_output_thread_.joinable()) fragment_output_thread_.join();
151  int number_of_fragments_sent = fragment_receiver_ptr_->GetFragmentsProcessed();
152  TLOG(TLVL_DEBUG) << "do_pause(uint64_t, uint64_t): "
153  << "Number of fragments sent = " << number_of_fragments_sent
154  << ".";
155 
156  return external_request_status_;
157 }
158 
159 bool artdaq::BoardReaderApp::do_resume(uint64_t timeout, uint64_t timestamp)
160 {
161  report_string_ = "";
162  if (timeout == 0)
163  {
164  timeout = 3600; // seconds
165  }
166  external_request_status_ = true;
167 
168  boost::thread::attributes attrs;
169  attrs.set_stack_size(4096 * 2000); // 8 MB
170  try
171  {
172  fragment_output_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::send_fragments, fragment_receiver_ptr_.get()));
173  fragment_input_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::receive_fragments, fragment_receiver_ptr_.get()));
174  }
175  catch (const boost::exception& e)
176  {
177  std::stringstream exception_string;
178  exception_string << "Caught boost::exception starting Fragment Processing threads: " << boost::diagnostic_information(e) << ", errno=" << errno;
179 
180  ExceptionHandler(ExceptionHandlerRethrow::yes, exception_string.str());
181  }
182 
183  auto start_wait = std::chrono::steady_clock::now();
184  while (!fragment_receiver_ptr_->GetSenderThreadActive() || !fragment_receiver_ptr_->GetReceiverThreadActive())
185  {
186  if (TimeUtils::GetElapsedTimeMicroseconds(start_wait) > timeout * 1000000)
187  {
188  TLOG(TLVL_ERROR) << "Timeout occurred waiting for BoardReaderCore threads to start. Timeout = " << timeout << " s, Time waited = " << TimeUtils::GetElapsedTime(start_wait) << " s,"
189  << " Receiver ready: " << std::boolalpha << fragment_receiver_ptr_->GetReceiverThreadActive() << ", Sender ready: " << fragment_receiver_ptr_->GetSenderThreadActive();
190  external_request_status_ = false;
191  break;
192  }
193  usleep(10000);
194  }
195 
196  // Only if starting threads successful
197  if (external_request_status_)
198  {
199  external_request_status_ = fragment_receiver_ptr_->resume(timeout, timestamp);
200  }
201  if (!external_request_status_)
202  {
203  report_string_ = "Error resuming ";
204  report_string_.append(app_name + ".");
205  }
206  return external_request_status_;
207 }
208 
210 {
211  report_string_ = "";
212  external_request_status_ = fragment_receiver_ptr_->shutdown(timeout);
213  // 02-Jun-2018, ELF & KAB: it's very, very unlikely that the following call is needed,
214  // but just in case...
215  if (fragment_input_thread_.joinable()) fragment_input_thread_.join();
216  if (fragment_output_thread_.joinable()) fragment_output_thread_.join();
217  if (!external_request_status_)
218  {
219  report_string_ = "Error shutting down ";
220  report_string_.append(app_name + ".");
221  }
222  return external_request_status_;
223 }
224 
225 bool artdaq::BoardReaderApp::do_soft_initialize(fhicl::ParameterSet const& pset, uint64_t timeout, uint64_t timestamp)
226 {
227  report_string_ = "";
228  external_request_status_ = fragment_receiver_ptr_->soft_initialize(pset, timeout, timestamp);
229  if (!external_request_status_)
230  {
231  report_string_ = "Error soft-initializing ";
232  report_string_.append(app_name + " ");
233  report_string_.append("with ParameterSet = \"" + pset.to_string() + "\".");
234  }
235  return external_request_status_;
236 }
237 
238 bool artdaq::BoardReaderApp::do_reinitialize(fhicl::ParameterSet const& pset, uint64_t timeout, uint64_t timestamp)
239 {
240  external_request_status_ = fragment_receiver_ptr_->reinitialize(pset, timeout, timestamp);
241  if (!external_request_status_)
242  {
243  report_string_ = "Error reinitializing ";
244  report_string_.append(app_name + " ");
245  report_string_.append("with ParameterSet = \"" + pset.to_string() + "\".");
246  }
247  return external_request_status_;
248 }
249 
251 {
252  TLOG(TLVL_DEBUG) << "Booted state entry action called.";
253 
254  // the destruction of any existing BoardReaderCore has to happen in the
255  // Booted Entry action rather than the Initialized Exit action because the
256  // Initialized Exit action is only called after the "init" transition guard
257  // condition is executed.
258  fragment_receiver_ptr_.reset(nullptr);
259 }
260 
261 bool artdaq::BoardReaderApp::do_meta_command(std::string const& command, std::string const& arg)
262 {
263  external_request_status_ = fragment_receiver_ptr_->metaCommand(command, arg);
264  if (!external_request_status_)
265  {
266  report_string_ = "Error running meta-command on ";
267  report_string_.append(app_name + " ");
268  report_string_.append("with command = \"" + command + "\", arg = \"" + arg + "\".");
269  }
270  return external_request_status_;
271 }
272 
273 std::string artdaq::BoardReaderApp::report(std::string const& which) const
274 {
275  std::string resultString;
276 
277  // if all that is requested is the latest state change result, return it
278  if (which == "transition_status")
279  {
280  if (report_string_.length() > 0) { return report_string_; }
281 
282  return "Success";
283  }
284 
287  //if (report_string_.length() > 0) {
288  // resultString.append("*** Overall status message:\r\n");
289  // resultString.append(report_string_ + "\r\n");
290  // resultString.append("*** Requested report response:\r\n");
291  //}
292 
293  // pass the request to the BoardReaderCore instance, if it's available
294  if (fragment_receiver_ptr_ != nullptr)
295  {
296  resultString.append(fragment_receiver_ptr_->report(which));
297  }
298  else
299  {
300  resultString.append("This BoardReader has not yet been initialized and ");
301  resultString.append("therefore can not provide reporting.");
302  }
303 
304  return resultString;
305 }
bool do_soft_initialize(fhicl::ParameterSet const &pset, uint64_t timeout, uint64_t timestamp) override
Soft-Initialize the BoardReaderCore.
bool do_resume(uint64_t timeout, uint64_t timestamp) override
Resume the BoardReaderCore.
bool do_stop(uint64_t timeout, uint64_t timestamp) override
Stop the BoardReaderCore.
bool do_meta_command(std::string const &command, std::string const &arg) override
Perform a user-defined command (passed to CommandableFragmentGenerator)
bool do_shutdown(uint64_t timeout) override
Shutdown the BoardReaderCore.
bool do_reinitialize(fhicl::ParameterSet const &pset, uint64_t timeout, uint64_t timestamp) override
Reinitialize the BoardReaderCore.
std::string report(std::string const &which) const override
If which is &quot;transition_status&quot;, report the status of the last transition. Otherwise pass through to ...
void send_fragments()
Main working loop of the BoardReaderCore, pt. 2.
BoardReaderApp()
BoardReaderApp Constructor.
void BootedEnter() override
Action taken upon entering the &quot;Booted&quot; state.
void receive_fragments()
Main working loop of the BoardReaderCore.
bool do_start(art::RunID id, uint64_t timeout, uint64_t timestamp) override
Start the BoardReaderCore.
bool do_initialize(fhicl::ParameterSet const &pset, uint64_t timeout, uint64_t timestamp) override
Initialize the BoardReaderCore.
bool do_pause(uint64_t timeout, uint64_t timestamp) override
Pause the BoardReaderCore.