otsdaq  3.11.00
IterateTableImpl.cc
1 #include "otsdaq/ConfigurationInterface/ConfigurationManager.h"
2 #include "otsdaq/Macros/StringMacros.h"
3 #include "otsdaq/TablePlugins/IterateTable.h"
4 
5 #include <iostream>
6 #include <string>
7 
8 using namespace ots;
9 
12 const std::string IterateTable::COMMAND_BEGIN_LABEL = "BEGIN_LABEL";
13 const std::string IterateTable::COMMAND_CHOOSE_FSM = "CHOOSE_FSM";
14 const std::string IterateTable::COMMAND_CONFIGURE_ACTIVE_GROUP = "CONFIGURE_ACTIVE_GROUP";
15 const std::string IterateTable::COMMAND_CONFIGURE_ALIAS = "CONFIGURE_ALIAS";
16 const std::string IterateTable::COMMAND_CONFIGURE_GROUP = "CONFIGURE_GROUP";
17 const std::string IterateTable::COMMAND_ACTIVATE_ALIAS = "ACTIVATE_ALIAS";
18 const std::string IterateTable::COMMAND_ACTIVATE_GROUP = "ACTIVATE_GROUP";
19 const std::string IterateTable::COMMAND_EXECUTE_FE_MACRO = "EXECUTE_FE_MACRO";
20 const std::string IterateTable::COMMAND_EXECUTE_MM_MACRO = "EXECUTE_MM_MACRO";
21 const std::string IterateTable::COMMAND_MODIFY_ACTIVE_GROUP = "MODIFY_ACTIVE_GROUP";
22 const std::string IterateTable::COMMAND_REPEAT_LABEL = "REPEAT_LABEL";
23 const std::string IterateTable::COMMAND_RUN = "RUN";
24 const std::string IterateTable::COMMAND_WAIT = "WAIT";
25 const std::string IterateTable::COMMAND_START = "START";
26 const std::string IterateTable::COMMAND_STOP = "STOP";
27 const std::string IterateTable::COMMAND_PAUSE = "PAUSE";
28 const std::string IterateTable::COMMAND_RESUME = "RESUME";
29 const std::string IterateTable::COMMAND_HALT = "HALT";
30 
31 const std::string IterateTable::ITERATE_TABLE = "IterateTable";
32 const std::string IterateTable::PLAN_TABLE = "IterationPlanTable";
33 const std::string IterateTable::TARGET_TABLE = "IterationTargetTable";
34 const std::string IterateTable::MACRO_DIM_LOOP_TABLE =
35  "IterationCommandMacroDimensionalLoopTable";
36 const std::string IterateTable::MACRO_DIM_LOOP_PARAM_TABLE =
37  "IterationCommandMacroDimensionalLoopParameterTable";
38 
39 const std::map<std::string, std::string> IterateTable::commandToTableMap_ =
41 
42 // clang-format off
43 IterateTable::PlanTableColumns IterateTable::planTableCols_;
44 IterateTable::IterateTableColumns IterateTable::iterateTableCols_;
45 
46 IterateTable::CommandBeginLabelParams IterateTable::commandBeginLabelParams_;
47 IterateTable::CommandConfigureActiveParams IterateTable::commandConfigureActiveParams_;
48 IterateTable::CommandConfigureAliasParams IterateTable::commandConfigureAliasParams_;
49 IterateTable::CommandConfigureGroupParams IterateTable::commandConfigureGroupParams_;
50 IterateTable::CommandActivateAliasParams IterateTable::commandActivateAliasParams_;
51 IterateTable::CommandActivateGroupParams IterateTable::commandActivateGroupParams_;
52 IterateTable::CommandExecuteMacroParams IterateTable::commandExecuteMacroParams_;
53 IterateTable::CommandModifyActiveParams IterateTable::commandModifyActiveParams_;
54 IterateTable::CommandRepeatLabelParams IterateTable::commandRepeatLabelParams_;
55 
56 IterateTable::CommandRunParams IterateTable::commandRunParams_;
57 IterateTable::CommandWaitParams IterateTable::commandWaitParams_;
58 
59 IterateTable::CommandChooseFSMParams IterateTable::commandChooseFSMParams_;
60 
61 IterateTable::TargetParams IterateTable::targetParams_;
62 IterateTable::TargetTableColumns IterateTable::targetCols_;
63 IterateTable::CommandTargetColumns IterateTable::commandTargetCols_;
64 
65 IterateTable::MacroDimLoopTableColumns IterateTable::macroDimLoopCols_;
66 IterateTable::MacroParamTableColumns IterateTable::macroParamCols_;
67 // clang-format on
68 
69 //==============================================================================
70 IterateTable::IterateTable(void) : TableBase(IterateTable::ITERATE_TABLE) {}
71 
72 //==============================================================================
73 IterateTable::~IterateTable(void) {}
74 
75 //==============================================================================
76 void IterateTable::init(ConfigurationManager* /*configManager*/)
77 {
78  // do something to validate or refactor table
79  // __COUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << std::endl;
80  // __COUT__ << configManager->__SELF_NODE__ << std::endl;
81 
82  /*
83  std::string value;
84  auto childrenMap = configManager->__SELF_NODE__.getChildren();
85  for(auto& childPair : childrenMap)
86  {
87  // do something for each row in table
88  //__COUT__ << childPair.first << std::endl;
89  // __COUT__ << childPair.second.getNode(colNames_.colColumnName_) <<
90  // std::endl; childPair.second.getNode(colNames_.colColumnName_
91  // ).getValue(value);
92  }
93  */
94 }
95 
96 //==============================================================================
97 std::vector<IterateTable::Command> IterateTable::getPlanCommands(
98  ConfigurationManager* configManager, const std::string& plan) const
99 {
100  __COUT__ << configManager->__SELF_NODE__ << std::endl;
101 
102  ConfigurationTree planNode = configManager->__SELF_NODE__.getNode(plan);
103 
104  if(!planNode.getNode(IterateTable::planTableCols_.Status_).getValue<bool>())
105  {
106  __SS__ << "Error! Attempt to access disabled plan (Status=FALSE)." << std::endl;
107  __COUT_ERR__ << ss.str();
108  __SS_THROW__;
109  }
110 
111  std::vector<IterateTable::Command> commands;
112 
113  auto commandChildren =
114  planNode.getNode(IterateTable::iterateTableCols_.PlanLink_).getChildren();
115 
116  for(auto& commandChild : commandChildren)
117  {
118  __COUT__ << "Command \t" << commandChild.first << std::endl;
119 
120  __COUT__ << "\t\tStatus \t"
121  << commandChild.second.getNode(IterateTable::planTableCols_.Status_)
122  << std::endl;
123 
124  __COUT__ << "\t\tType \t"
125  << commandChild.second.getNode(IterateTable::planTableCols_.CommandType_)
126  << std::endl;
127 
128  if(!commandChild.second.getNode(IterateTable::planTableCols_.Status_)
129  .getValue<bool>())
130  continue; // skip disabled commands
131 
132  commands.push_back(IterateTable::Command());
133  commands.back().type_ =
134  commandChild.second.getNode(IterateTable::planTableCols_.CommandType_)
135  .getValue<std::string>();
136 
137  try
138  {
139  // getValueWithDefault: a newly added column holds the DEFAULT sentinel, which
140  // must read as "" (Self), not as a remote subsystem literally named DEFAULT
141  commands.back().targetSubsystem_ =
142  commandChild.second.getNode(IterateTable::planTableCols_.TargetSubsystem_)
143  .getValueWithDefault<std::string>("");
144  }
145  catch(...)
146  {
147  commands.back().targetSubsystem_ = "";
148  }
149 
150  if(commandChild.second.getNode(IterateTable::planTableCols_.CommandLink_)
151  .isDisconnected())
152  continue; // skip if no command parameters
153 
154  auto commandSpecificFields =
155  commandChild.second.getNode(IterateTable::planTableCols_.CommandLink_)
156  .getChildren();
157 
158  for(unsigned int i = 0; i < commandSpecificFields.size() - 3;
159  ++i) // ignore last three columns
160  {
161  // NOTE -- that links turn into one field with value LinkID/GroupID unless
162  // specially handled
163 
164  __COUT__ << "\t\tParameter \t" << commandSpecificFields[i].first << " = \t"
165  << commandSpecificFields[i].second << std::endl;
166 
167  if(commandSpecificFields[i].first ==
168  IterateTable::commandTargetCols_.TargetsLink_)
169  {
170  __COUT__ << "Extracting targets..." << __E__;
171  auto targets = commandSpecificFields[i].second.getChildren();
172 
173  __COUTV__(targets.size());
174 
175  for(auto& target : targets)
176  {
177  __COUT__ << "\t\t\tTarget \t" << target.first << __E__;
178 
179  ConfigurationTree targetNode =
180  target.second.getNode(IterateTable::targetCols_.TargetLink_);
181  if(targetNode.isDisconnected())
182  {
183  // The target table/UID may not exist in THIS gateway's configuration,
184  // e.g. a front-end that lives on a remote subsystem. Keep the stored
185  // table name and UID so the remote dispatch can resolve them there;
186  // only warn for local (Self) commands, where the link must resolve.
187  if(commands.back().targetSubsystem_ == "")
188  __COUT_WARN__
189  << "Disconnected target '"
190  << targetNode.getDisconnectedTableName() << "/"
191  << targetNode.getDisconnectedLinkID() << "' for command "
192  << commandChild.first
193  << " (no such record in the active configuration); "
194  "keeping it, but a local macro will fail on it."
195  << __E__;
196  else
197  __COUT__
198  << "\t\t = \tTable:"
199  << targetNode.getDisconnectedTableName()
200  << " UID:" << targetNode.getDisconnectedLinkID()
201  << " (not in local configuration; resolved on remote "
202  "subsystem '"
203  << commands.back().targetSubsystem_ << "')" << __E__;
204 
205  commands.back().addTarget();
206  commands.back().targets_.back().table_ =
207  targetNode.getDisconnectedTableName();
208  commands.back().targets_.back().UID_ =
209  targetNode.getDisconnectedLinkID();
210  continue;
211  }
212 
213  __COUT__ << "\t\t = \t"
214  << "Table:" << targetNode.getTableName()
215  << " UID:" << targetNode.getUIDAsString() << std::endl;
216  commands.back().addTarget();
217  commands.back().targets_.back().table_ = targetNode.getTableName();
218  commands.back().targets_.back().UID_ = targetNode.getUIDAsString();
219  }
220  }
221  else if(commandSpecificFields[i].first == // treat FE and Macro the same
222  IterateTable::commandExecuteMacroParams_.MacroParameterLink_)
223  {
224  // get Macro parameters, place them in params_
225  __COUT__ << "Extracting macro parameters..." << __E__;
226 
227  // need to extract input arguments
228  // by dimension (by priority)
229  //
230  // two vector by dimension <map of params>
231  // one vector for long and for double
232  //
233  // map of params :=
234  // name => {
235  // <long/double current value>
236  // <long/double init value>
237  // <long/double step size>
238  // }
239 
240  auto dimensionalLoops = commandSpecificFields[i].second.getChildren(
241  std::map<std::string /*relative-path*/,
242  std::string /*value*/>() /*no filter*/,
243  true /*by Priority*/);
244 
245  __COUTV__(dimensionalLoops.size());
246 
247  // inputs:
248  // - inputArgs: dimensional semi-colon-separated,
249  // comma separated: dimension iterations and arguments
250  //(colon-separated name/value/stepsize sets)
251  std::string argStr = "";
252  // inputArgsStr = "3;3,myOtherArg:5:2"; //example
253  // labelsStr: one ";"-separated StepLabel per dimension (same order);
254  // empty = innermost enclosing BEGIN_LABEL steps this dimension
255  std::string labelsStr = "";
256 
257  // std::string name, value;
258  unsigned long numberOfIterations;
259  bool firstDimension = true;
260 
261  for(auto& dimensionalLoop : dimensionalLoops)
262  {
263  __COUT__ << "\t\t\tDimensionalLoop \t" << dimensionalLoop.first
264  << __E__;
265 
266  numberOfIterations =
267  dimensionalLoop.second
268  .getNode(IterateTable::macroDimLoopCols_.NumberOfIterations_)
269  .getValue<unsigned long>();
270 
271  __COUTV__(numberOfIterations);
272 
273  if(numberOfIterations == 0)
274  {
275  __SS__ << "Illegal number of iterations value of '"
276  << numberOfIterations << ".' Must be a positive integer!"
277  << __E__;
278  __SS_THROW__;
279  }
280 
281  std::string stepLabel = "";
282  try // column added later; tolerate older table versions
283  {
284  // an unset Data column reads back as the literal "DEFAULT";
285  // blank/default means "innermost enclosing loop", i.e. ""
286  stepLabel =
287  dimensionalLoop.second
288  .getNode(IterateTable::macroDimLoopCols_.StepLabel_)
289  .getValueWithDefault<std::string>("");
290  }
291  catch(...)
292  {
293  }
294 
295  // at this point add dimension parameter with value numberOfIterations
296 
297  if(!firstDimension)
298  {
299  argStr += ";";
300  labelsStr += ";";
301  }
302  firstDimension = false;
303  argStr += std::to_string(numberOfIterations);
304  labelsStr += stepLabel;
305 
306  auto paramLinkNode = dimensionalLoop.second.getNode(
307  IterateTable::macroDimLoopCols_.ParamLink_);
308 
309  if(paramLinkNode.isDisconnected())
310  {
311  __COUT__ << "Disconnected parameter link, so no parameters for "
312  "this dimension."
313  << __E__;
314  continue;
315  }
316 
317  auto macroParams = paramLinkNode.getChildren();
318 
319  __COUTV__(macroParams.size());
320 
321  for(auto& macroParam : macroParams)
322  {
323  __COUT__ << "\t\t\tParam \t" << macroParam.first << __E__;
324 
325  // add parameter name:value:step
326 
327  argStr += ",";
328  argStr += StringMacros::encodeURIComponent(
329  macroParam.second.getNode(IterateTable::macroParamCols_.Name_)
330  .getValue<std::string>());
331  argStr += ":";
332  argStr += StringMacros::encodeURIComponent(
333  macroParam.second
334  .getNode(IterateTable::macroParamCols_.Value_)
335  .getValue<std::string>());
336  argStr += ":";
337  argStr += StringMacros::encodeURIComponent(
338  macroParam.second.getNode(IterateTable::macroParamCols_.Step_)
339  .getValue<std::string>());
340 
341  } // end parameter loop
342  } // end dimension loop
343 
344  // Macro argument string is done
345  __COUTV__(argStr);
346 
347  // assume no conflict with fixed parameters in map
348  // because of prepend
349  // IterateTable::commandExecuteMacroParams_.MacroParameterPrepend_
350  //+
351  commands.back().params_.emplace(
352  std::pair<std::string /*param name*/, std::string /*param value*/>(
353  IterateTable::commandExecuteMacroParams_.MacroArgumentString_,
354  argStr));
355  commands.back().params_.emplace(
356  std::pair<std::string /*param name*/, std::string /*param value*/>(
357  IterateTable::commandExecuteMacroParams_.MacroArgumentLabels_,
358  labelsStr));
359  }
360  else // all other non-special fields
361  {
362  if( // bool type, convert to 1 or 0
363  commandSpecificFields[i].second.isValueBoolType())
364  commands.back().params_.emplace(
365  std::pair<std::string /*param name*/,
366  std::string /*param value*/>(
367  commandSpecificFields[i].first,
368  commandSpecificFields[i].second.getValue<bool>() ? "1"
369  : "0"));
370  else if( // number data type, get raw value string (note: does not do
371  // math or variable substitution)
372  commandSpecificFields[i].second.isValueNumberDataType())
373  commands.back().params_.emplace(
374  std::pair<std::string /*param name*/,
375  std::string /*param value*/>(
376  commandSpecificFields[i].first,
377  commandSpecificFields[i].second.getValueAsString()));
378  else
379  commands.back().params_.emplace(
380  std::pair<std::string /*param name*/,
381  std::string /*param value*/>(
382  commandSpecificFields[i].first,
383  commandSpecificFields[i].second.getValue<std::string>()));
384  }
385  }
386  }
387 
388  return commands;
389 }
ConfigurationTree getNode(const std::string &nodeString, bool doNotThrowOnBrokenUIDLinks=false) const
"root/parent/parent/"
bool isDisconnected(void) const
ConfigurationTree getNode(const std::string &nodeName, bool doNotThrowOnBrokenUIDLinks=false) const
navigating between nodes
const std::string & getTableName(void) const
getTableName
void getValue(T &value) const
const std::string & getDisconnectedTableName(void) const
getDisconnectedTableName
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool byPriority=false, bool onlyStatusTrue=false) const
const std::string & getUIDAsString(void) const
const std::string & getDisconnectedLinkID(void) const
getDisconnectedLinkID
void init(ConfigurationManager *configManager)
Methods.
static std::map< std::string, std::string > createCommandToTableMap()
Definition: IterateTable.h:63
static const std::string COMMAND_BEGIN_LABEL
Definition: IterateTable.h:37
defines used also by OtsConfigurationWizardSupervisor
for macro dimensional loop parameters
Definition: IterateTable.h:186