otsdaq  v2_00_00
Iterator.h
1 #ifndef _ots_Iterator_h
2 #define _ots_Iterator_h
3 
4 
5 #include "otsdaq-core/ConfigurationPluginDataFormats/IterateConfiguration.h"
6 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
7 #include <mutex> //for std::mutex
8 #include <string>
9 
10 #include "otsdaq-core/ConfigurationInterface/ConfigurationManagerRW.h"
11 
12 namespace ots
13 {
14 
15 class GatewaySupervisor;
16 class ConfigurationManagerRW;
17 
18 class Iterator
19 {
20  friend class GatewaySupervisor;
21 
22 public:
23  Iterator (GatewaySupervisor* supervisor);
24  ~Iterator(void);
25 
26  void playIterationPlan (HttpXmlDocument& xmldoc, const std::string& planName);
27  void pauseIterationPlan (HttpXmlDocument& xmldoc);
28  void haltIterationPlan (HttpXmlDocument& xmldoc);
29  void getIterationPlanStatus (HttpXmlDocument& xmldoc);
30 
31  bool handleCommandRequest (HttpXmlDocument& xmldoc, const std::string& command, const std::string& parameter);
32 
33 private:
34 
35  //begin declaration of iterator workloop members
36  struct IteratorWorkLoopStruct
37  {
38  IteratorWorkLoopStruct(Iterator* iterator, ConfigurationManagerRW* cfgMgr)
39  :theIterator_ (iterator)
40  ,cfgMgr_ (cfgMgr)
41  ,originalTrackChanges_ (false)
42  ,running_ (false)
43  ,commandBusy_ (false)
44  ,doPauseAction_ (false)
45  ,doHaltAction_ (false)
46  ,doResumeAction_ (false)
47  ,commandIndex_ ((unsigned int)-1)
48  {}
49 
50  Iterator * theIterator_;
51  ConfigurationManagerRW* cfgMgr_;
52  bool originalTrackChanges_;
53  std::string originalConfigGroup_;
54  ConfigurationGroupKey originalConfigKey_;
55 
56  bool running_, commandBusy_;
57  bool doPauseAction_, doHaltAction_, doResumeAction_;
58 
59  std::string activePlan_;
60  std::vector<IterateConfiguration::Command> commands_;
61  std::vector<unsigned int> commandIterations_;
62  unsigned int commandIndex_;
63  std::vector<unsigned int> stepIndexStack_;
64 
65  //associated with FSM
66  std::string fsmName_, fsmRunAlias_;
67  unsigned int fsmNextRunNumber_;
68  bool runIsDone_;
69 
70  std::vector<std::string> fsmCommandParameters_;
71 
72 
73  }; //end declaration of iterator workloop members
74 
75  static void IteratorWorkLoop (Iterator *iterator);
76  static void startCommand (IteratorWorkLoopStruct *iteratorStruct);
77  static bool checkCommand (IteratorWorkLoopStruct *iteratorStruct);
78 
79  static void startCommandChooseFSM (IteratorWorkLoopStruct *iteratorStruct, const std::string& fsmName);
80 
81  static void startCommandConfigureActive (IteratorWorkLoopStruct *iteratorStruct);
82  static void startCommandConfigureAlias (IteratorWorkLoopStruct *iteratorStruct, const std::string& systemAlias);
83  static void startCommandConfigureGroup (IteratorWorkLoopStruct *iteratorStruct);
84  static bool checkCommandConfigure (IteratorWorkLoopStruct *iteratorStruct);
85 
86  static void startCommandModifyActive (IteratorWorkLoopStruct *iteratorStruct);
87 
88 
89  static void startCommandBeginLabel (IteratorWorkLoopStruct *iteratorStruct);
90  static void startCommandRepeatLabel (IteratorWorkLoopStruct *iteratorStruct);
91 
92  static void startCommandRun (IteratorWorkLoopStruct *iteratorStruct);
93  static bool checkCommandRun (IteratorWorkLoopStruct *iteratorStruct);
94 
95  static bool haltIterator (Iterator *iterator, IteratorWorkLoopStruct *iteratorStruct = 0);//(GatewaySupervisor* theSupervisor, const std::string& fsmName);
96 
97  std::mutex accessMutex_;
98  volatile bool workloopRunning_;
99  volatile bool activePlanIsRunning_;
100  volatile bool iteratorBusy_;
101  volatile bool commandPlay_, commandPause_, commandHalt_; //commands are set by supervisor thread, and cleared by iterator thread
102  std::string activePlanName_, lastStartedPlanName_, lastFinishedPlanName_;
103  volatile unsigned int activeCommandIndex_, activeCommandIteration_;
104  std::vector<unsigned int> depthIterationStack_;
105  volatile time_t activeCommandStartTime_;
106  std::string lastFsmName_;
107  std::string errorMessage_;
108 
109  GatewaySupervisor* theSupervisor_;
110 
111  //========================================================================================================================
112  //helpCommandModifyActive
113  // set the value to all targets
114  template<class T>
115  static void helpCommandModifyActive(
116  IteratorWorkLoopStruct *iteratorStruct,
117  const T& setValue,
118  bool doTrackGroupChanges)
119  try
120  {
121  __COUT__ << "Set value " << setValue << __E__;
122  __COUT__ << "doTrackGroupChanges " << doTrackGroupChanges << __E__;
123 
124 
125  const std::string& pathToField =
126  iteratorStruct->commands_[iteratorStruct->commandIndex_].params_
127  [IterateConfiguration::commandModifyActiveParams_.RelativePathToField_];
128 
129  __COUT__ << "pathToField " << pathToField << std::endl;
130 
131  ConfigurationManagerRW* cfgMgr = iteratorStruct->cfgMgr_;
132 
133  std::stringstream valSS;
134  valSS << setValue;
135 
136  std::string groupName = cfgMgr->getActiveGroupName();
137  ConfigurationGroupKey originalKey = cfgMgr->getActiveGroupKey();
138 
139  __COUT__ << "Active group is '" << groupName << " (" <<
140  originalKey << ")'" << __E__;
141 
142  //track member names and versions of active config group
143  // modify versions as tables are modified..
144  // then save new group at end
145  std::map<std::string /*name*/, ConfigurationVersion /*version*/> memberMap;
146  try
147  {
148  cfgMgr->loadConfigurationGroup(
149  groupName,
150  originalKey,
151  0,&memberMap,
152  0,0,0,0,0, //defaults
153  true); //doNotLoadMember
154  }
155  catch(const std::runtime_error& e)
156  {
157  __SS__ << "Failed to load the active configuration group. Is there a valid one activated? " <<
158  e.what() << __E__;
159  throw std::runtime_error(ss.str());
160  }
161 
162  for(const auto& member: memberMap)
163  __COUT__ << "newGroup " << member.first << "-v" << member.second << __E__;
164 
165  for(const auto& target:
166  iteratorStruct->commands_[iteratorStruct->commandIndex_].targets_)
167  {
168  __COUT__ << "target " << target.table_ << ":" << target.UID_ << __E__;
169  ConfigurationTree node = cfgMgr->getNode(
170  target.table_).getNode(
171  target.UID_).getNode(
172  pathToField);
173 
174  if(!node.isValueNode())
175  {
176  __SS__ << "Invalid target node. The target path '" << pathToField <<
177  "' must be a value node." << __E__;
178  throw std::runtime_error(ss.str());
179  }
180 
181  __COUT__ << "value node table: " << node.getConfigurationName() << __E__;
182  __COUT__ << "value node UID: " << node.getUIDAsString() << __E__;
183 
184  __COUT__ << "value node row: " << node.getFieldRow() << __E__;
185  __COUT__ << "value node column: " << node.getFieldColumn() << __E__;
186 
187 
188 
189  TableEditStruct valueTable(node.getConfigurationName(),cfgMgr); // Table ready for editing!
190 
191  try
192  {
193  valueTable.cfgView_->setValueAsString(
194  valSS.str(),
195  node.getFieldRow(),
196  node.getFieldColumn()
197  );
198 
199 
200  valueTable.cfgView_->print();
201  valueTable.cfgView_->init(); //verify new table (throws runtime_errors)
202  }
203  catch(...)
204  {
205  __COUT__ << "Handling command table errors while saving. Erasing all newly created versions." << std::endl;
206 
207  if(valueTable.createdTemporaryVersion_) //if temporary version created here
208  {
209  __COUT__ << "Erasing temporary version " << valueTable.configName_ <<
210  "-v" << valueTable.temporaryVersion_ << std::endl;
211  //erase with proper version management
212  cfgMgr->eraseTemporaryVersion(valueTable.configName_,valueTable.temporaryVersion_);
213  }
214 
215  throw; //re-throw
216  }
217 
218  //at this point valid edited table.. so save
219 
220  ConfigurationVersion newAssignedVersion;
221 
222  //start save table code
223  // do not check for duplicates if not tracking changes
224  {
225  const std::string& configName = valueTable.configName_;
226  ConfigurationBase* config = valueTable.config_;
227  ConfigurationVersion& temporaryModifiedVersion = valueTable.temporaryVersion_;
228 
229 
230  //check for duplicate tables already in cache
231  if(doTrackGroupChanges) //check for duplicates if tracking changes
232  {
233  __COUT__ << "Checking for duplicate tables..." << std::endl;
234 
235  {
236  //"DEEP" checking
237  // load into cache 'recent' versions for this table
238  // 'recent' := those already in cache, plus highest version numbers not in cache
239  const std::map<std::string, ConfigurationInfo>& allCfgInfo =
240  cfgMgr->getAllConfigurationInfo(); //do not refresh
241 
242  auto versionReverseIterator = allCfgInfo.at(configName).versions_.rbegin(); //get reverse iterator
243  __COUT__ << "Filling up cached from " <<
244  config->getNumberOfStoredViews() <<
245  " to max count of " << config->MAX_VIEWS_IN_CACHE << std::endl;
246  for(;config->getNumberOfStoredViews() < config->MAX_VIEWS_IN_CACHE &&
247  versionReverseIterator != allCfgInfo.at(configName).versions_.rend();++versionReverseIterator)
248  {
249  __COUT__ << "Versions in reverse order " << *versionReverseIterator << std::endl;
250  cfgMgr->getVersionedConfigurationByName(configName,*versionReverseIterator); //load to cache
251  }
252  }
253 
254  //check for duplicates (including original version)
255  newAssignedVersion = config->checkForDuplicate(temporaryModifiedVersion);
256 
257  __COUT__ << "Check for duplicate tables complete." << std::endl;
258  }
259 
260 
261  if(!newAssignedVersion.isInvalid())
262  {
263  //found an equivalent!
264  __COUT__ << "Equivalent table found in version v" << newAssignedVersion << std::endl;
265 
266  //erase modified temporary version
267  cfgMgr->eraseTemporaryVersion(configName,temporaryModifiedVersion);
268  }
269  else
270  {
271  //save as new table version
272 
273  __COUT__ << "\t\t**************************** Save v" <<
274  temporaryModifiedVersion << " as new table version" << std::endl;
275 
276  newAssignedVersion =
277  cfgMgr->saveNewConfiguration(configName,temporaryModifiedVersion,
278  false /*makeTemporary*/);
279 
280  }
281 
282  __COUT__ << "\t\t newAssignedVersion: " << newAssignedVersion << std::endl;
283 
284  } //end save table code
285 
286  //now have newAssignedVersion
287 
288  __COUT__ << "Final plan version is " << valueTable.configName_ << "-v" <<
289  newAssignedVersion << std::endl;
290 
291  //record new version in modified tables map
292  memberMap[valueTable.configName_] = newAssignedVersion;
293 
294  } //end target loop
295 
296  //member map should now be modified
297  for(const auto& member: memberMap)
298  __COUT__ << "newGroup " << member.first << "-v" << member.second << __E__;
299 
300  __COUT__ << "Checking for duplicate groups..." << std::endl;
301  ConfigurationGroupKey theKey =
302  cfgMgr->findConfigurationGroup(groupName,memberMap);
303 
304  if(!theKey.isInvalid())
305  {
306  __COUT__ << "Found equivalent group key (" << theKey << ") for " <<
307  groupName << "." << std::endl;
308  }
309  else
310  {
311  __COUT__ << "Saving new group..." << __E__;
312 
313  //save new group
314  theKey = cfgMgr->saveNewConfigurationGroup(
315  groupName,
316  memberMap,
317  "Created by Iterator modify active configuration command.");
318  }
319 
320  __COUT__ << "Final group key is " << groupName << "(" <<
321  theKey << ")" << std::endl;
322 
323  //now active new group
324  __COUT__ << "Activating new group..." << __E__;
325  cfgMgr->activateConfigurationGroup(groupName,theKey);
326 
327  } //end helpCommandModifyActive
328  catch(const std::runtime_error& e)
329  {
330  __SS__ << "Modify command failed! " << e.what() << __E__;
331 
332 
333  throw std::runtime_error(ss.str());
334  }
335 };
336 
337 }
338 
339 #endif