00001 #ifndef _ots_Iterator_h
00002 #define _ots_Iterator_h
00003
00004
00005 #include "otsdaq-core/ConfigurationPluginDataFormats/IterateConfiguration.h"
00006 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
00007 #include <mutex>
00008 #include <string>
00009
00010 #include "otsdaq-core/ConfigurationInterface/ConfigurationManagerRW.h"
00011
00012 namespace ots
00013 {
00014
00015 class GatewaySupervisor;
00016 class ConfigurationManagerRW;
00017
00018 class Iterator
00019 {
00020 friend class GatewaySupervisor;
00021
00022 public:
00023 Iterator (GatewaySupervisor* supervisor);
00024 ~Iterator(void);
00025
00026 void playIterationPlan (HttpXmlDocument& xmldoc, const std::string& planName);
00027 void pauseIterationPlan (HttpXmlDocument& xmldoc);
00028 void haltIterationPlan (HttpXmlDocument& xmldoc);
00029 void getIterationPlanStatus (HttpXmlDocument& xmldoc);
00030
00031 bool handleCommandRequest (HttpXmlDocument& xmldoc, const std::string& command, const std::string& parameter);
00032
00033 private:
00034
00035
00036 struct IteratorWorkLoopStruct
00037 {
00038 IteratorWorkLoopStruct(Iterator* iterator, ConfigurationManagerRW* cfgMgr)
00039 :theIterator_ (iterator)
00040 ,cfgMgr_ (cfgMgr)
00041 ,originalTrackChanges_ (false)
00042 ,running_ (false)
00043 ,commandBusy_ (false)
00044 ,doPauseAction_ (false)
00045 ,doHaltAction_ (false)
00046 ,doResumeAction_ (false)
00047 ,commandIndex_ ((unsigned int)-1)
00048 {}
00049
00050 Iterator * theIterator_;
00051 ConfigurationManagerRW* cfgMgr_;
00052 bool originalTrackChanges_;
00053 std::string originalConfigGroup_;
00054 ConfigurationGroupKey originalConfigKey_;
00055
00056 bool running_, commandBusy_;
00057 bool doPauseAction_, doHaltAction_, doResumeAction_;
00058
00059 std::string activePlan_;
00060 std::vector<IterateConfiguration::Command> commands_;
00061 std::vector<unsigned int> commandIterations_;
00062 unsigned int commandIndex_;
00063 std::vector<unsigned int> stepIndexStack_;
00064
00065
00066 std::string fsmName_, fsmRunAlias_;
00067 unsigned int fsmNextRunNumber_;
00068 bool runIsDone_;
00069
00070 std::vector<std::string> fsmCommandParameters_;
00071
00072
00073 };
00074
00075 static void IteratorWorkLoop (Iterator *iterator);
00076 static void startCommand (IteratorWorkLoopStruct *iteratorStruct);
00077 static bool checkCommand (IteratorWorkLoopStruct *iteratorStruct);
00078
00079 static void startCommandChooseFSM (IteratorWorkLoopStruct *iteratorStruct, const std::string& fsmName);
00080
00081 static void startCommandConfigureActive (IteratorWorkLoopStruct *iteratorStruct);
00082 static void startCommandConfigureAlias (IteratorWorkLoopStruct *iteratorStruct, const std::string& systemAlias);
00083 static void startCommandConfigureGroup (IteratorWorkLoopStruct *iteratorStruct);
00084 static bool checkCommandConfigure (IteratorWorkLoopStruct *iteratorStruct);
00085
00086 static void startCommandModifyActive (IteratorWorkLoopStruct *iteratorStruct);
00087
00088
00089 static void startCommandBeginLabel (IteratorWorkLoopStruct *iteratorStruct);
00090 static void startCommandRepeatLabel (IteratorWorkLoopStruct *iteratorStruct);
00091
00092 static void startCommandRun (IteratorWorkLoopStruct *iteratorStruct);
00093 static bool checkCommandRun (IteratorWorkLoopStruct *iteratorStruct);
00094
00095 static bool haltIterator (Iterator *iterator, IteratorWorkLoopStruct *iteratorStruct = 0);
00096
00097 std::mutex accessMutex_;
00098 volatile bool workloopRunning_;
00099 volatile bool activePlanIsRunning_;
00100 volatile bool iteratorBusy_;
00101 volatile bool commandPlay_, commandPause_, commandHalt_;
00102 std::string activePlanName_, lastStartedPlanName_, lastFinishedPlanName_;
00103 volatile unsigned int activeCommandIndex_, activeCommandIteration_;
00104 std::vector<unsigned int> depthIterationStack_;
00105 volatile time_t activeCommandStartTime_;
00106 std::string lastFsmName_;
00107 std::string errorMessage_;
00108
00109 GatewaySupervisor* theSupervisor_;
00110
00111
00112
00113
00114 template<class T>
00115 static void helpCommandModifyActive(
00116 IteratorWorkLoopStruct *iteratorStruct,
00117 const T& setValue,
00118 bool doTrackGroupChanges)
00119 try
00120 {
00121 __COUT__ << "Set value " << setValue << __E__;
00122 __COUT__ << "doTrackGroupChanges " << doTrackGroupChanges << __E__;
00123
00124
00125 const std::string& pathToField =
00126 iteratorStruct->commands_[iteratorStruct->commandIndex_].params_
00127 [IterateConfiguration::commandModifyActiveParams_.RelativePathToField_];
00128
00129 __COUT__ << "pathToField " << pathToField << std::endl;
00130
00131 ConfigurationManagerRW* cfgMgr = iteratorStruct->cfgMgr_;
00132
00133 std::stringstream valSS;
00134 valSS << setValue;
00135
00136 std::string groupName = cfgMgr->getActiveGroupName();
00137 ConfigurationGroupKey originalKey = cfgMgr->getActiveGroupKey();
00138
00139 __COUT__ << "Active group is '" << groupName << " (" <<
00140 originalKey << ")'" << __E__;
00141
00142
00143
00144
00145 std::map<std::string , ConfigurationVersion > memberMap;
00146 try
00147 {
00148 cfgMgr->loadConfigurationGroup(
00149 groupName,
00150 originalKey,
00151 0,&memberMap,
00152 0,0,0,0,0,
00153 true);
00154 }
00155 catch(const std::runtime_error& e)
00156 {
00157 __SS__ << "Failed to load the active configuration group. Is there a valid one activated? " <<
00158 e.what() << __E__;
00159 throw std::runtime_error(ss.str());
00160 }
00161
00162 for(const auto& member: memberMap)
00163 __COUT__ << "newGroup " << member.first << "-v" << member.second << __E__;
00164
00165 for(const auto& target:
00166 iteratorStruct->commands_[iteratorStruct->commandIndex_].targets_)
00167 {
00168 __COUT__ << "target " << target.table_ << ":" << target.UID_ << __E__;
00169 ConfigurationTree node = cfgMgr->getNode(
00170 target.table_).getNode(
00171 target.UID_).getNode(
00172 pathToField);
00173
00174 if(!node.isValueNode())
00175 {
00176 __SS__ << "Invalid target node. The target path '" << pathToField <<
00177 "' must be a value node." << __E__;
00178 throw std::runtime_error(ss.str());
00179 }
00180
00181 __COUT__ << "value node table: " << node.getConfigurationName() << __E__;
00182 __COUT__ << "value node UID: " << node.getUIDAsString() << __E__;
00183
00184 __COUT__ << "value node row: " << node.getFieldRow() << __E__;
00185 __COUT__ << "value node column: " << node.getFieldColumn() << __E__;
00186
00187
00188
00189 TableEditStruct valueTable(node.getConfigurationName(),cfgMgr);
00190
00191 try
00192 {
00193 valueTable.cfgView_->setValueAsString(
00194 valSS.str(),
00195 node.getFieldRow(),
00196 node.getFieldColumn()
00197 );
00198
00199
00200 valueTable.cfgView_->print();
00201 valueTable.cfgView_->init();
00202 }
00203 catch(...)
00204 {
00205 __COUT__ << "Handling command table errors while saving. Erasing all newly created versions." << std::endl;
00206
00207 if(valueTable.createdTemporaryVersion_)
00208 {
00209 __COUT__ << "Erasing temporary version " << valueTable.configName_ <<
00210 "-v" << valueTable.temporaryVersion_ << std::endl;
00211
00212 cfgMgr->eraseTemporaryVersion(valueTable.configName_,valueTable.temporaryVersion_);
00213 }
00214
00215 throw;
00216 }
00217
00218
00219
00220 ConfigurationVersion newAssignedVersion;
00221
00222
00223
00224 {
00225 const std::string& configName = valueTable.configName_;
00226 ConfigurationBase* config = valueTable.config_;
00227 ConfigurationVersion& temporaryModifiedVersion = valueTable.temporaryVersion_;
00228
00229
00230
00231 if(doTrackGroupChanges)
00232 {
00233 __COUT__ << "Checking for duplicate tables..." << std::endl;
00234
00235 {
00236
00237
00238
00239 const std::map<std::string, ConfigurationInfo>& allCfgInfo =
00240 cfgMgr->getAllConfigurationInfo();
00241
00242 auto versionReverseIterator = allCfgInfo.at(configName).versions_.rbegin();
00243 __COUT__ << "Filling up cached from " <<
00244 config->getNumberOfStoredViews() <<
00245 " to max count of " << config->MAX_VIEWS_IN_CACHE << std::endl;
00246 for(;config->getNumberOfStoredViews() < config->MAX_VIEWS_IN_CACHE &&
00247 versionReverseIterator != allCfgInfo.at(configName).versions_.rend();++versionReverseIterator)
00248 {
00249 __COUT__ << "Versions in reverse order " << *versionReverseIterator << std::endl;
00250 cfgMgr->getVersionedConfigurationByName(configName,*versionReverseIterator);
00251 }
00252 }
00253
00254
00255 newAssignedVersion = config->checkForDuplicate(temporaryModifiedVersion);
00256
00257 __COUT__ << "Check for duplicate tables complete." << std::endl;
00258 }
00259
00260
00261 if(!newAssignedVersion.isInvalid())
00262 {
00263
00264 __COUT__ << "Equivalent table found in version v" << newAssignedVersion << std::endl;
00265
00266
00267 cfgMgr->eraseTemporaryVersion(configName,temporaryModifiedVersion);
00268 }
00269 else
00270 {
00271
00272
00273 __COUT__ << "\t\t**************************** Save v" <<
00274 temporaryModifiedVersion << " as new table version" << std::endl;
00275
00276 newAssignedVersion =
00277 cfgMgr->saveNewConfiguration(configName,temporaryModifiedVersion,
00278 false );
00279
00280 }
00281
00282 __COUT__ << "\t\t newAssignedVersion: " << newAssignedVersion << std::endl;
00283
00284 }
00285
00286
00287
00288 __COUT__ << "Final plan version is " << valueTable.configName_ << "-v" <<
00289 newAssignedVersion << std::endl;
00290
00291
00292 memberMap[valueTable.configName_] = newAssignedVersion;
00293
00294 }
00295
00296
00297 for(const auto& member: memberMap)
00298 __COUT__ << "newGroup " << member.first << "-v" << member.second << __E__;
00299
00300 __COUT__ << "Checking for duplicate groups..." << std::endl;
00301 ConfigurationGroupKey theKey =
00302 cfgMgr->findConfigurationGroup(groupName,memberMap);
00303
00304 if(!theKey.isInvalid())
00305 {
00306 __COUT__ << "Found equivalent group key (" << theKey << ") for " <<
00307 groupName << "." << std::endl;
00308 }
00309 else
00310 {
00311 __COUT__ << "Saving new group..." << __E__;
00312
00313
00314 theKey = cfgMgr->saveNewConfigurationGroup(
00315 groupName,
00316 memberMap,
00317 "Created by Iterator modify active configuration command.");
00318 }
00319
00320 __COUT__ << "Final group key is " << groupName << "(" <<
00321 theKey << ")" << std::endl;
00322
00323
00324 __COUT__ << "Activating new group..." << __E__;
00325 cfgMgr->activateConfigurationGroup(groupName,theKey);
00326
00327 }
00328 catch(const std::runtime_error& e)
00329 {
00330 __SS__ << "Modify command failed! " << e.what() << __E__;
00331
00332
00333 throw std::runtime_error(ss.str());
00334 }
00335 };
00336
00337 }
00338
00339 #endif