otsdaq  v2_01_00
FEVInterfacesManager.cc
1 #include "otsdaq-core/FECore/FEVInterfacesManager.h"
2 #include "otsdaq-core/MessageFacility/MessageFacility.h"
3 #include "otsdaq-core/Macros/CoutMacros.h"
4 #include "otsdaq-core/FECore/FEVInterface.h"
5 #include "otsdaq-core/PluginMakers/MakeInterface.h"
6 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
7 
8 #include "messagefacility/MessageLogger/MessageLogger.h"
9 #include "artdaq-core/Utilities/configureMessageFacility.hh"
10 #include "artdaq/BuildInfo/GetPackageBuildInfo.hh"
11 #include "fhiclcpp/make_ParameterSet.h"
12 
13 #include <iostream>
14 #include <sstream>
15 
16 using namespace ots;
17 
18 //========================================================================================================================
19 FEVInterfacesManager::FEVInterfacesManager(const ConfigurationTree& theXDAQContextConfigTree, const std::string& supervisorConfigurationPath)
20 : Configurable(theXDAQContextConfigTree, supervisorConfigurationPath)
21 {
22  init();
23 }
24 
25 //========================================================================================================================
26 FEVInterfacesManager::~FEVInterfacesManager(void)
27 {
28  destroy();
29 }
30 
31 //========================================================================================================================
32 void FEVInterfacesManager::init(void)
33 {
34 }
35 
36 //========================================================================================================================
37 void FEVInterfacesManager::destroy(void)
38 {
39  for(auto& it : theFEInterfaces_)
40  it.second.reset();
41 
42  theFEInterfaces_.clear();
43 }
44 
45 //========================================================================================================================
46 void FEVInterfacesManager::createInterfaces(void)
47 {
48  destroy();
49 
50  __COUT__ << "Path: "<< theConfigurationPath_+"/LinkToFEInterfaceConfiguration" << std::endl;
51  for(const auto& interface: theXDAQContextConfigTree_.getNode(theConfigurationPath_+"/LinkToFEInterfaceConfiguration").getChildren())
52  {
53  try
54  {
55  if(!interface.second.getNode(ViewColumnInfo::COL_NAME_STATUS).getValue<bool>()) continue;
56  }
57  catch(...) //if Status column not there ignore (for backwards compatibility)
58  {
59  __COUT_INFO__ << "Ignoring FE Status since Status column is missing!" << std::endl;
60  }
61 
62  __COUT__ << "Interface Plugin Name: "<< interface.second.getNode("FEInterfacePluginName").getValue<std::string>() << std::endl;
63  __COUT__ << "Interface Name: "<< interface.first << std::endl;
64  __COUT__ << "XDAQContext Node: "<< theXDAQContextConfigTree_ << std::endl;
65  __COUT__ << "Path to configuration: "<< (theConfigurationPath_ + "/LinkToFEInterfaceConfiguration/" + interface.first + "/LinkToFETypeConfiguration") << std::endl;
66 
67  try
68  {
69  theFEInterfaces_[interface.first] = makeInterface(
70  interface.second.getNode("FEInterfacePluginName").getValue<std::string>(),
71  interface.first,
72  theXDAQContextConfigTree_,
73  (theConfigurationPath_ + "/LinkToFEInterfaceConfiguration/" + interface.first + "/LinkToFETypeConfiguration")
74  );
75  }
76  catch(const cet::exception& e)
77  {
78  __SS__ << "Failed to instantiate plugin named '" <<
79  interface.first << "' of type '" <<
80  interface.second.getNode("FEInterfacePluginName").getValue<std::string>()
81  << "' due to the following error: \n" << e.what() << __E__;
82  __COUT_ERR__ << ss.str();
83  __MOUT_ERR__ << ss.str();
84  throw std::runtime_error(ss.str());
85  }
86  }
87  __COUT__ << "Done creating interfaces" << std::endl;
88 }
89 
90 //========================================================================================================================
91 //used by MacroMaker
92 int FEVInterfacesManager::universalRead(const std::string &interfaceID, char* address, char* returnValue)
93 {
94  if(theFEInterfaces_.find(interfaceID) == theFEInterfaces_.end())
95  {
96  __SS__ << "Interface ID '" << interfaceID << "' not found in configured interfaces." << __E__;
97  throw std::runtime_error(ss.str());
98  }
99 
100  __COUT__ << "interfaceID: " << interfaceID << " and size: " << theFEInterfaces_.size() << std::endl;
101 
102  if (theFEInterfaces_[interfaceID]->universalRead(address, returnValue) < 0) return -1;
103  return 0;
104 }
105 
106 
107 //========================================================================================================================
108 //used by MacroMaker
109 unsigned int FEVInterfacesManager::getInterfaceUniversalAddressSize(const std::string &interfaceID)
110 {
111  if(theFEInterfaces_.find(interfaceID) == theFEInterfaces_.end())
112  {
113  __SS__ << "Interface ID '" << interfaceID << "' not found in configured interfaces." << __E__;
114  throw std::runtime_error(ss.str());
115  }
116  return theFEInterfaces_[interfaceID]->getUniversalAddressSize();
117 } //used by MacroMaker
118 
119 //========================================================================================================================
120 //used by MacroMaker
121 unsigned int FEVInterfacesManager::getInterfaceUniversalDataSize(const std::string &interfaceID)
122 {
123  if(theFEInterfaces_.find(interfaceID) == theFEInterfaces_.end())
124  {
125  __SS__ << "Interface ID '" << interfaceID << "' not found in configured interfaces." << __E__;
126  throw std::runtime_error(ss.str());
127  }
128  return theFEInterfaces_[interfaceID]->getUniversalDataSize();
129 } //used by MacroMaker
130 
131 //========================================================================================================================
132 //used by MacroMaker
133 void FEVInterfacesManager::universalWrite(const std::string &interfaceID, char* address, char* writeValue)
134 {
135  if(theFEInterfaces_.find(interfaceID) == theFEInterfaces_.end())
136  {
137  __SS__ << "Interface ID '" << interfaceID << "' not found in configured interfaces." << __E__;
138  throw std::runtime_error(ss.str());
139  }
140 
141  __COUT__ << "interfaceID: " << interfaceID << " and size: " << theFEInterfaces_.size() << std::endl;
142 
143  theFEInterfaces_[interfaceID]->universalWrite(address, writeValue);
144 
145 // if(interfaceIndex >= theFEInterfaces_.size())
146 // {
147 // __COUT__ << "ERROR!!!! Invalid interface index" << std::endl;
148 // return; //invalid interface index
149 // }
150 
151 
152 }
153 
154 //========================================================================================================================
155 //getFEListString
156 // returns string with each new line indicating the macros for a FE
157 // each line:
158 // <interface type>:<parent supervisor lid>:<interface UID>
159 std::string FEVInterfacesManager::getFEListString(const std::string &supervisorLid)
160 {
161  std::string retList = "";
162 
163  for(const auto& it : theFEInterfaces_)
164  {
165  __COUT__ << "FE name = " << it.first << std::endl;
166 
167  retList += it.second->getInterfaceType() +
168  ":" + supervisorLid + ":" +
169  it.second->getInterfaceUID() + "\n";
170  }
171  return retList;
172 }
173 
174 //========================================================================================================================
175 //runFEMacro
176 // Runs the FE Macro in the specified FE interface.
177 //
178 // inputs:
179 // - inputArgs: colon-separated name/value pairs, and then comma-separated
180 // - outputArgs: comma-separated
181 //
182 // outputs:
183 // - throws exception on failure
184 // - outputArgs: colon-separate name/value pairs, and then comma-separated
185 void FEVInterfacesManager::runFEMacro(const std::string &interfaceID,
186  const std::string &feMacroName, const std::string &inputArgs, std::string &outputArgs)
187 {
188  //check for interfaceID
189  auto FEVInterfaceIt = theFEInterfaces_.find(interfaceID);
190  if(FEVInterfaceIt == theFEInterfaces_.end())
191  {
192  __SS__ << "interfaceID '" << interfaceID << "' was not found!" << std::endl;
193  __COUT_ERR__ << "\n" << ss.str();
194  throw std::runtime_error(ss.str());
195  }
196 
197  //have pointer to virtual FEInterface, find Macro structure
198  auto FEMacroIt = FEVInterfaceIt->second->getMapOfFEMacroFunctions().find(feMacroName);
199  if(FEMacroIt == FEVInterfaceIt->second->getMapOfFEMacroFunctions().end())
200  {
201  __SS__ << "FE Macro '" << feMacroName << "' of interfaceID '" <<
202  interfaceID << "' was not found!" << std::endl;
203  __COUT_ERR__ << "\n" << ss.str();
204  throw std::runtime_error(ss.str());
205  }
206 
207  //build input arguments
208  // parse args, colon-separated pairs, and then comma-separated
209  std::vector<FEVInterface::frontEndMacroInArg_t> argsIn;
210  {
211  std::istringstream inputStream(inputArgs);
212  std::string splitVal, argName, argValue;
213  while (getline(inputStream, splitVal, ';'))
214  {
215  std::istringstream pairInputStream(splitVal);
216  getline(pairInputStream, argName, ',');
217  getline(pairInputStream, argValue, ',');
218  argsIn.push_back(std::pair<std::string,std::string>(argName,argValue));
219  }
220  }
221 
222  //check namesOfInputArguments_
223  if(FEMacroIt->second.namesOfInputArguments_.size() != argsIn.size())
224  {
225  __SS__ << "FE Macro '" << feMacroName << "' of interfaceID '" <<
226  interfaceID << "' was attempted with a mismatch in" <<
227  " number of input arguments. " << argsIn.size() <<
228  " were given. " << FEMacroIt->second.namesOfInputArguments_.size() <<
229  " expected." << std::endl;
230  __COUT_ERR__ << "\n" << ss.str();
231  throw std::runtime_error(ss.str());
232  }
233  for(unsigned int i=0;i<argsIn.size();++i)
234  if(argsIn[i].first != FEMacroIt->second.namesOfInputArguments_[i])
235  {
236  __SS__ << "FE Macro '" << feMacroName << "' of interfaceID '" <<
237  interfaceID << "' was attempted with a mismatch in" <<
238  " a name of an input argument. " <<
239  argsIn[i].first << " were given. " <<
240  FEMacroIt->second.namesOfInputArguments_[i] <<
241  " expected." << std::endl;
242  __COUT_ERR__ << "\n" << ss.str();
243  throw std::runtime_error(ss.str());
244  }
245 
246 
247 
248  //build output arguments
249  std::vector<std::string> returnStrings;
250  std::vector<FEVInterface::frontEndMacroOutArg_t> argsOut;
251 
252  {
253  std::istringstream inputStream(outputArgs);
254  std::string argName;
255  while (getline(inputStream, argName, ','))
256  {
257  __COUT__ << "argName " << argName << std::endl;
258 
259  returnStrings.push_back( "DEFAULT" );//std::string());
260  argsOut.push_back(FEVInterface::frontEndMacroOutArg_t(
261  argName,
262  returnStrings[returnStrings.size()-1]));
263  //
264  // __COUT__ << argsOut[argsOut.size()-1].first << std::endl;
265  __COUT__ << (uint64_t) &(returnStrings[returnStrings.size()-1]) << std::endl;
266  }
267  }
268 
269  //check namesOfOutputArguments_
270  if(FEMacroIt->second.namesOfOutputArguments_.size() != argsOut.size())
271  {
272  __SS__ << "FE Macro '" << feMacroName << "' of interfaceID '" <<
273  interfaceID << "' was attempted with a mismatch in" <<
274  " number of output arguments. " << argsOut.size() <<
275  " were given. " << FEMacroIt->second.namesOfOutputArguments_.size() <<
276  " expected." << std::endl;
277  __COUT_ERR__ << "\n" << ss.str();
278  throw std::runtime_error(ss.str());
279  }
280  for(unsigned int i=0;i<argsOut.size();++i)
281  if(argsOut[i].first != FEMacroIt->second.namesOfOutputArguments_[i])
282  {
283  __SS__ << "FE Macro '" << feMacroName << "' of interfaceID '" <<
284  interfaceID << "' was attempted with a mismatch in" <<
285  " a name of an output argument. " <<
286  argsOut[i].first << " were given. " <<
287  FEMacroIt->second.namesOfOutputArguments_[i] <<
288  " expected." << std::endl;
289  __COUT_ERR__ << "\n" << ss.str();
290  throw std::runtime_error(ss.str());
291  }
292 
293 
294 
295 
296 
297 
298  __COUT__ << "# of input args = " << argsIn.size() << std::endl;
299  for(auto &argIn:argsIn)
300  __COUT__ << argIn.first << ": " << argIn.second << std::endl;
301 
302  // __COUT__ << "# of output args = " << argsOut.size() << std::endl;
303  // for(unsigned int i=0;i<argsOut.size();++i)
304  // __COUT__ << i << ": " << argsOut[i].first << std::endl;
305  // for(unsigned int i=0;i<returnStrings.size();++i)
306  // __COUT__ << i << ": " << returnStrings[i] << std::endl;
307 
308 
309 
310 
311  __MOUT__ << "Launching FE Macro '" << feMacroName << "' ..." << std::endl;
312  __COUT__ << "Launching FE Macro '" << feMacroName << "' ..." << std::endl;
313 
314  //have pointer to Macro structure, so run it
315  (FEVInterfaceIt->second.get()->*(FEMacroIt->second.macroFunction_))(argsIn,argsOut);
316 
317  __COUT__ << "FE Macro complete!" << std::endl;
318 
319  __COUT__ << "# of output args = " << argsOut.size() << std::endl;
320  for(const auto &arg:argsOut)
321  __COUT__ << arg.first << ": " << arg.second << std::endl;
322 
323 
324 
325 
326 
327  //check namesOfOutputArguments_ size
328  if(FEMacroIt->second.namesOfOutputArguments_.size() != argsOut.size())
329  {
330  __SS__ << "FE Macro '" << feMacroName << "' of interfaceID '" <<
331  interfaceID << "' was attempted but the FE macro "
332  "manipulated the output arguments vector. It is illegal "
333  "to add or remove output vector name/value pairs." << std::endl;
334  __COUT_ERR__ << "\n" << ss.str();
335  throw std::runtime_error(ss.str());
336  }
337 
338 
339 
340  //Success! at this point so return the output string
341  outputArgs = "";
342  for(unsigned int i=0; i<argsOut.size(); ++i)
343  {
344  if(i) outputArgs += ";";
345  outputArgs += argsOut[i].first + "," + argsOut[i].second;
346  }
347 
348  __COUT__ << "outputArgs = " << outputArgs << std::endl;
349 
350 }
351 
352 //========================================================================================================================
353 //getFEMacrosString
354 // returns string with each new line indicating the macros for a FE
355 // each line:
356 // <interface type>:<parent supervisor lid>:<interface UID>
357 // :<macro name>:<macro permissions req>:<macro num of inputs>:...<input names : separated>...
358 // :<macro num of outputs>:...<output names : separated>...
359 std::string FEVInterfacesManager::getFEMacrosString(const std::string &supervisorLid)
360 {
361  std::string retList = "";
362 
363  for(const auto& it : theFEInterfaces_)
364  {
365  __COUT__ << "FE interface UID = " << it.first << std::endl;
366 
367  retList += it.second->getInterfaceType() +
368  ":" + supervisorLid + ":" +
369  it.second->getInterfaceUID();
370 
371  for(const auto& macroPair : it.second->getMapOfFEMacroFunctions())
372  {
373  __COUT__ << "FE Macro name = " << macroPair.first << std::endl;
374  retList +=
375  ":" + macroPair.first +
376  ":" + std::to_string(macroPair.second.requiredUserPermissions_) +
377  ":" + std::to_string(macroPair.second.namesOfInputArguments_.size());
378  for(const auto& name:macroPair.second.namesOfInputArguments_)
379  retList += ":" + name;
380 
381  retList +=
382  ":" + std::to_string(macroPair.second.namesOfOutputArguments_.size());
383  for(const auto& name:macroPair.second.namesOfOutputArguments_)
384  retList += ":" + name;
385  }
386 
387  retList += "\n";
388  }
389  return retList;
390 }
391 
392 //========================================================================================================================
393 bool FEVInterfacesManager::allFEWorkloopsAreDone(void)
394 {
395  bool allFEWorkloopsAreDone = true;
396  bool isActive;
397 
398  for(const auto& FEInterface: theFEInterfaces_)
399  {
400  isActive = FEInterface.second->isActive();
401  __COUT__ << FEInterface.second->getInterfaceUID() << " of type " <<
402  FEInterface.second->getInterfaceType() << ": \t" <<
403  "workLoop_->isActive() " <<
404  (isActive?"yes":"no") << std::endl;
405 
406  if(isActive) //then not done
407  {
408  allFEWorkloopsAreDone = false;
409  break;
410  }
411  }
412 
413  return allFEWorkloopsAreDone;
414 }
415 
416 //========================================================================================================================
417 void FEVInterfacesManager::configure(void)
418 {
419  createInterfaces();
420  for(const auto& it : theFEInterfaces_)
421  {
422 // if(supervisorType_ == "FER")
423 // it.second->initLocalGroup((int)local_group_comm_);
424 
425  __COUT__ << "Configuring interface " << it.first << std::endl;
426  __COUT__ << "Configuring interface " << it.first << std::endl;
427  __COUT__ << "Configuring interface " << it.first << std::endl;
428 
429  it.second->configure();
430 
431  //configure slow controls and start slow controls workloop
432  // slow controls workloop stays alive through start/stop.. and dies on halt
433  //LOREit.second->configureSlowControls();
434  //WAS ALREADY COMMENTED OUTit.second->startSlowControlsWorkLooop();
435 
436 // if((supervisorType_ == "FEW") || (supervisorType_ == "FEWR") )
437 // {
438 
439  __COUT__ << "Done configuring interface " << it.first << std::endl;
440  __COUT__ << "Done configuring interface " << it.first << std::endl;
441  __COUT__ << "Done configuring interface " << it.first << std::endl;
442  //throw std::runtime_error(ss.str());
443  // it.second->configureDetector(theConfigurationManager_->getDACStream(it.first));
444 
445 // }
446  }
447 
448 
449  __COUT__ << "Done Configure" << std::endl;
450 }
451 
452 //========================================================================================================================
453 void FEVInterfacesManager::halt(void)
454 {
455  for(const auto& it : theFEInterfaces_)
456  {
457  it.second->halt();
458  it.second->stopWorkLoop();
459  //it.second->stopSlowControlsWorkLooop();
460  }
461 
462  destroy(); //destroy all FE interfaces on halt, must be configured for FE interfaces to exist
463 }
464 
465 //========================================================================================================================
466 void FEVInterfacesManager::pause(void)
467 {
468  for(const auto& it : theFEInterfaces_)
469  {
470  it.second->pause();
471  it.second->stopWorkLoop();
472  }
473 }
474 
475 //========================================================================================================================
476 void FEVInterfacesManager::resume(void)
477 {
478  for(const auto& it : theFEInterfaces_)
479  {
480  it.second->resume();
481  it.second->startWorkLoop();
482  }
483 }
484 
485 //========================================================================================================================
486 void FEVInterfacesManager::start(std::string runNumber)
487 {
488  for(const auto& it : theFEInterfaces_)
489  {
490  it.second->start(runNumber);
491  it.second->startWorkLoop();
492  }
493 }
494 //========================================================================================================================
495 void FEVInterfacesManager::stop(void)
496 {
497  for(const auto& it : theFEInterfaces_)
498  {
499  it.second->stopWorkLoop();
500  it.second->stop();
501  }
502 }