artdaq  v3_09_00
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  external_request_status_ = fragment_receiver_ptr_->start(id, timeout, timestamp);
49  if (!external_request_status_)
50  {
51  report_string_ = "Error starting ";
52  report_string_.append(app_name + " ");
53  report_string_.append("for run number ");
54  report_string_.append(boost::lexical_cast<std::string>(id.run()));
55  report_string_.append(", timeout ");
56  report_string_.append(boost::lexical_cast<std::string>(timeout));
57  report_string_.append(", timestamp ");
58  report_string_.append(boost::lexical_cast<std::string>(timestamp));
59  report_string_.append(".");
60  }
61 
62  boost::thread::attributes attrs;
63  attrs.set_stack_size(4096 * 2000); // 8 MB
64  try
65  {
66  fragment_input_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::receive_fragments, fragment_receiver_ptr_.get()));
67  fragment_output_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::send_fragments, fragment_receiver_ptr_.get()));
68  }
69  catch (const boost::exception& e)
70  {
71  std::stringstream exception_string;
72  exception_string << "Caught boost::exception starting Fragment Processing threads: " << boost::diagnostic_information(e) << ", errno=" << errno;
73 
74  ExceptionHandler(ExceptionHandlerRethrow::yes, exception_string.str());
75  }
76 
77  return external_request_status_;
78 }
79 
80 bool artdaq::BoardReaderApp::do_stop(uint64_t timeout, uint64_t timestamp)
81 {
82  report_string_ = "";
83  external_request_status_ = fragment_receiver_ptr_->stop(timeout, timestamp);
84  if (!external_request_status_)
85  {
86  report_string_ = "Error stopping ";
87  report_string_.append(app_name + ".");
88  return false;
89  }
90  if (fragment_input_thread_.joinable())
91  {
92  TLOG(TLVL_DEBUG) << "Joining fragment input (Generator) thread";
93  fragment_input_thread_.join();
94  }
95  if (fragment_output_thread_.joinable())
96  {
97  TLOG(TLVL_DEBUG) << "Joining fragment output (Sender) thread";
98  fragment_output_thread_.join();
99  }
100 
101 
102  TLOG(TLVL_DEBUG) << "BoardReader Stopped. Getting run statistics";
103  int number_of_fragments_sent = -1;
104  if (fragment_receiver_ptr_)
105  {
106  number_of_fragments_sent = fragment_receiver_ptr_->GetFragmentsProcessed();
107  }
108  TLOG(TLVL_DEBUG) << "do_stop(uint64_t, uint64_t): "
109  << "Number of fragments sent = " << number_of_fragments_sent
110  << ".";
111 
112  return external_request_status_;
113 }
114 
115 bool artdaq::BoardReaderApp::do_pause(uint64_t timeout, uint64_t timestamp)
116 {
117  report_string_ = "";
118  external_request_status_ = fragment_receiver_ptr_->pause(timeout, timestamp);
119  if (!external_request_status_)
120  {
121  report_string_ = "Error pausing ";
122  report_string_.append(app_name + ".");
123  }
124 
125  if (fragment_input_thread_.joinable()) fragment_input_thread_.join();
126  if (fragment_output_thread_.joinable()) fragment_output_thread_.join();
127  int number_of_fragments_sent = fragment_receiver_ptr_->GetFragmentsProcessed();
128  TLOG(TLVL_DEBUG) << "do_pause(uint64_t, uint64_t): "
129  << "Number of fragments sent = " << number_of_fragments_sent
130  << ".";
131 
132  return external_request_status_;
133 }
134 
135 bool artdaq::BoardReaderApp::do_resume(uint64_t timeout, uint64_t timestamp)
136 {
137  report_string_ = "";
138  external_request_status_ = fragment_receiver_ptr_->resume(timeout, timestamp);
139  if (!external_request_status_)
140  {
141  report_string_ = "Error resuming ";
142  report_string_.append(app_name + ".");
143  }
144 
145  boost::thread::attributes attrs;
146  attrs.set_stack_size(4096 * 2000); // 8 MB
147  fragment_input_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::receive_fragments, fragment_receiver_ptr_.get()));
148  fragment_output_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::send_fragments, fragment_receiver_ptr_.get()));
149 
150  return external_request_status_;
151 }
152 
154 {
155  report_string_ = "";
156  external_request_status_ = fragment_receiver_ptr_->shutdown(timeout);
157  // 02-Jun-2018, ELF & KAB: it's very, very unlikely that the following call is needed,
158  // but just in case...
159  if (fragment_input_thread_.joinable()) fragment_input_thread_.join();
160  if (fragment_output_thread_.joinable()) fragment_output_thread_.join();
161  if (!external_request_status_)
162  {
163  report_string_ = "Error shutting down ";
164  report_string_.append(app_name + ".");
165  }
166  return external_request_status_;
167 }
168 
169 bool artdaq::BoardReaderApp::do_soft_initialize(fhicl::ParameterSet const& pset, uint64_t timeout, uint64_t timestamp)
170 {
171  report_string_ = "";
172  external_request_status_ = fragment_receiver_ptr_->soft_initialize(pset, timeout, timestamp);
173  if (!external_request_status_)
174  {
175  report_string_ = "Error soft-initializing ";
176  report_string_.append(app_name + " ");
177  report_string_.append("with ParameterSet = \"" + pset.to_string() + "\".");
178  }
179  return external_request_status_;
180 }
181 
182 bool artdaq::BoardReaderApp::do_reinitialize(fhicl::ParameterSet const& pset, uint64_t timeout, uint64_t timestamp)
183 {
184  external_request_status_ = fragment_receiver_ptr_->reinitialize(pset, timeout, timestamp);
185  if (!external_request_status_)
186  {
187  report_string_ = "Error reinitializing ";
188  report_string_.append(app_name + " ");
189  report_string_.append("with ParameterSet = \"" + pset.to_string() + "\".");
190  }
191  return external_request_status_;
192 }
193 
195 {
196  TLOG(TLVL_DEBUG) << "Booted state entry action called.";
197 
198  // the destruction of any existing BoardReaderCore has to happen in the
199  // Booted Entry action rather than the Initialized Exit action because the
200  // Initialized Exit action is only called after the "init" transition guard
201  // condition is executed.
202  fragment_receiver_ptr_.reset(nullptr);
203 }
204 
205 bool artdaq::BoardReaderApp::do_meta_command(std::string const& command, std::string const& arg)
206 {
207  external_request_status_ = fragment_receiver_ptr_->metaCommand(command, arg);
208  if (!external_request_status_)
209  {
210  report_string_ = "Error running meta-command on ";
211  report_string_.append(app_name + " ");
212  report_string_.append("with command = \"" + command + "\", arg = \"" + arg + "\".");
213  }
214  return external_request_status_;
215 }
216 
217 std::string artdaq::BoardReaderApp::report(std::string const& which) const
218 {
219  std::string resultString;
220 
221  // if all that is requested is the latest state change result, return it
222  if (which == "transition_status")
223  {
224  if (report_string_.length() > 0) { return report_string_; }
225 
226  return "Success";
227  }
228 
231  //if (report_string_.length() > 0) {
232  // resultString.append("*** Overall status message:\r\n");
233  // resultString.append(report_string_ + "\r\n");
234  // resultString.append("*** Requested report response:\r\n");
235  //}
236 
237  // pass the request to the BoardReaderCore instance, if it's available
238  if (fragment_receiver_ptr_ != nullptr)
239  {
240  resultString.append(fragment_receiver_ptr_->report(which));
241  }
242  else
243  {
244  resultString.append("This BoardReader has not yet been initialized and ");
245  resultString.append("therefore can not provide reporting.");
246  }
247 
248  return resultString;
249 }
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.