1 #include "otsdaq-core/ConfigurationInterface/ConfigurationManagerRW.h"
31 #define __MF_SUBJECT__ "ConfigurationManagerRW"
33 #define CONFIGURATION_INFO_PATH std::string(getenv("CONFIGURATION_INFO_PATH")) + "/"
34 #define CONFIGURATION_INFO_EXT "Info.xml"
38 ConfigurationManagerRW::ConfigurationManagerRW(std::string username)
41 __COUT__ <<
"Using Config Mgr with Write Access! (for " << username <<
")" << std::endl;
45 theInterface_ = ConfigurationInterface::getInstance(
false);
55 const std::map<std::string, ConfigurationInfo>& ConfigurationManagerRW::getAllConfigurationInfo(
56 bool refresh, std::string *accumulatedErrors,
const std::string &errorFilterName)
60 if(accumulatedErrors) *accumulatedErrors =
"";
62 if(!refresh)
return allConfigurationInfo_;
65 allConfigurationInfo_.clear();
72 __COUT__ <<
"======================================================== getAllConfigurationInfo start" << std::endl;
73 __COUT__ <<
"Refreshing all! Extracting list of Configuration tables..." << std::endl;
76 std::string path = CONFIGURATION_INFO_PATH;
77 char fileExt[] = CONFIGURATION_INFO_EXT;
78 const unsigned char MIN_CONFIG_NAME_SZ = 3;
79 if( (pDIR=opendir( path.c_str() )) != 0 )
81 while((entry = readdir(pDIR)) != 0)
84 if(strlen(entry->d_name) < strlen(fileExt)+MIN_CONFIG_NAME_SZ)
89 &(entry->d_name[strlen(entry->d_name) - strlen(fileExt)]),
94 entry->d_name[strlen(entry->d_name) - strlen(fileExt)] =
'\0';
103 theInterface_->get(configuration,
108 catch(cet::exception)
110 if(configuration)
delete configuration;
113 __COUT__ <<
"Skipping! No valid class found for... " << entry->d_name <<
"\n";
116 catch(std::runtime_error &e)
118 if(configuration)
delete configuration;
121 __COUT__ <<
"Skipping! No valid class found for... " << entry->d_name <<
"\n";
122 __COUT__ <<
"Error: " << e.what() << std::endl;
128 if(accumulatedErrors)
131 if(errorFilterName ==
"" ||
132 errorFilterName == entry->d_name)
134 *accumulatedErrors += std::string(
"\nIn table '") + entry->d_name +
137 __SS__ <<
"Attempting to allow illegal columns!" << std::endl;
138 *accumulatedErrors += ss.str();
142 __COUT__ <<
"Attempting to allow illegal columns!" << std::endl;
145 std::string returnedAccumulatedErrors;
149 configuration =
new ConfigurationBase(entry->d_name, &returnedAccumulatedErrors);
153 __COUT__ <<
"Skipping! Allowing illegal columns didn't work either... " <<
154 entry->d_name <<
"\n";
157 __COUT__ <<
"Error (but allowed): " << returnedAccumulatedErrors << std::endl;
159 if(errorFilterName ==
"" ||
160 errorFilterName == entry->d_name)
161 *accumulatedErrors += std::string(
"\nIn table '") + entry->d_name +
162 "'..." + returnedAccumulatedErrors;
170 if(nameToConfigurationMap_[entry->d_name])
173 std::set<ConfigurationVersion> versions =
174 nameToConfigurationMap_[entry->d_name]->getStoredVersions();
175 for(
auto &version:versions)
176 if(version.isTemporaryVersion())
178 __COUT__ <<
"copying tmp = " << version << std::endl;
182 nameToConfigurationMap_[entry->d_name]->setActiveView(version);
183 configuration->copyView(
184 nameToConfigurationMap_[entry->d_name]->getView(),
192 delete nameToConfigurationMap_[entry->d_name];
193 nameToConfigurationMap_[entry->d_name] = 0;
196 nameToConfigurationMap_[entry->d_name] = configuration;
198 allConfigurationInfo_[entry->d_name].configurationPtr_ = configuration;
199 allConfigurationInfo_[entry->d_name].versions_ = theInterface_->getVersions(configuration);
203 std::set<ConfigurationVersion> versions =
204 nameToConfigurationMap_[entry->d_name]->getStoredVersions();
205 for(
auto &version:versions)
206 if(version.isTemporaryVersion())
208 __COUT__ <<
"surviving tmp = " << version << std::endl;
209 allConfigurationInfo_[entry->d_name].versions_.emplace(version);
214 __COUT__ <<
"Extracting list of Configuration tables complete" << std::endl;
217 init(accumulatedErrors);
219 __COUT__ <<
"======================================================== getAllConfigurationInfo end" << std::endl;
221 return allConfigurationInfo_;
227 std::map<std::string,std::map<std::string,ConfigurationVersion> >
228 ConfigurationManagerRW::getActiveVersionAliases(
void)
const
230 __COUT__ <<
"getActiveVersionAliases()" << std::endl;
231 std::map<std::string,std::map<std::string,ConfigurationVersion> > retMap;
233 std::map<std::string, ConfigurationVersion> activeVersions = getActiveVersions();
234 std::string versionAliasesTableName =
"VersionAliasesConfiguration";
235 if(activeVersions.find(versionAliasesTableName) == activeVersions.end())
237 __SS__ <<
"Active version of VersionAliases missing!" <<
238 "Make sure you have a valid active Backbone Group." << std::endl;
239 __COUT_WARN__ <<
"\n" << ss.str();
243 __COUT__ <<
"activeVersions[\"VersionAliasesConfiguration\"]=" <<
244 activeVersions[versionAliasesTableName] << std::endl;
247 if(!ConfigurationInterface::isVersionTrackingEnabled())
248 for(
const auto &tableInfo:allConfigurationInfo_)
249 for(
const auto &version:tableInfo.second.versions_)
250 if(version.isScratchVersion())
251 retMap[tableInfo.first][ConfigurationManager::SCRATCH_VERSION_ALIAS] =
254 std::vector<std::pair<std::string,ConfigurationTree> > aliasNodePairs =
255 getNode(versionAliasesTableName).getChildren();
260 std::string configName, versionAlias;
261 for(
auto& aliasNodePair:aliasNodePairs)
263 configName = aliasNodePair.second.getNode(
264 "ConfigurationName").getValueAsString();
265 versionAlias = aliasNodePair.second.getNode(
266 "VersionAlias").getValueAsString();
268 if(retMap.find(configName) != retMap.end() &&
269 retMap[configName].find(versionAlias) != retMap[configName].end())
274 aliasNodePair.second.getNode(
"Version").getValueAsString());
284 void ConfigurationManagerRW::activateConfigurationGroup(
const std::string &configGroupName,
287 loadConfigurationGroup(configGroupName,configGroupKey,
290 accumulatedTreeErrors);
292 if(accumulatedTreeErrors &&
293 *accumulatedTreeErrors !=
"")
295 __COUT_ERR__ <<
"Errors were accumulated so de-activating group: " <<
296 configGroupName <<
" (" << configGroupKey <<
")" << std::endl;
298 { destroyConfigurationGroup(configGroupName,
true); }
302 __MOUT_INFO__ <<
"Updating persistent active groups to " <<
303 ConfigurationManager::ACTIVE_GROUP_FILENAME <<
" ..." << std::endl;
305 std::string fn = ConfigurationManager::ACTIVE_GROUP_FILENAME;
306 FILE *fp = fopen(fn.c_str(),
"w");
309 __SS__ <<
"Fatal Error! Unable to open the file " <<
310 ConfigurationManager::ACTIVE_GROUP_FILENAME <<
" for editing! Is there a permissions problem?" << std::endl;
311 __COUT_ERR__ << ss.str();
312 throw std::runtime_error(ss.str());
316 __MOUT_INFO__ <<
"Active Context: " << theContextGroup_ <<
"(" <<
317 (theContextGroupKey_?theContextGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
318 __MOUT_INFO__ <<
"Active Backbone: " << theBackboneGroup_ <<
"(" <<
319 (theBackboneGroupKey_?theBackboneGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
320 __MOUT_INFO__ <<
"Active Iterate: " << theIterateGroup_ <<
"(" <<
321 (theIterateGroupKey_?theIterateGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
322 __MOUT_INFO__ <<
"Active Configuration: " << theConfigurationGroup_ <<
"(" <<
323 (theConfigurationGroupKey_?theConfigurationGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
325 fprintf(fp,
"%s\n",theContextGroup_.c_str());
326 fprintf(fp,
"%s\n",theContextGroupKey_?theContextGroupKey_->toString().c_str():
"-1");
327 fprintf(fp,
"%s\n",theBackboneGroup_.c_str());
328 fprintf(fp,
"%s\n",theBackboneGroupKey_?theBackboneGroupKey_->toString().c_str():
"-1");
329 fprintf(fp,
"%s\n",theIterateGroup_.c_str());
330 fprintf(fp,
"%s\n",theIterateGroupKey_?theIterateGroupKey_->toString().c_str():
"-1");
331 fprintf(fp,
"%s\n",theConfigurationGroup_.c_str());
332 fprintf(fp,
"%s\n",theConfigurationGroupKey_?theConfigurationGroupKey_->toString().c_str():
"-1");
342 __COUT_INFO__ <<
"Creating temporary backbone view from version " <<
343 sourceViewVersion << std::endl;
348 auto backboneMemberNames = ConfigurationManager::getBackboneMemberNames();
349 for (
auto& name : backboneMemberNames)
351 retTmpVersion = ConfigurationManager::getConfigurationByName(name)->getNextTemporaryVersion();
352 if(retTmpVersion < tmpVersion)
353 tmpVersion = retTmpVersion;
356 __COUT__ <<
"Common temporary backbone version found as " <<
357 tmpVersion << std::endl;
360 for (
auto& name : backboneMemberNames)
362 retTmpVersion = getConfigurationByName(name)->createTemporaryView(sourceViewVersion, tmpVersion);
363 if(retTmpVersion != tmpVersion)
365 __SS__ <<
"Failure! Temporary view requested was " <<
366 tmpVersion <<
". Mismatched temporary view created: " << retTmpVersion << std::endl;
367 __COUT_ERR__ << ss.str();
368 throw std::runtime_error(ss.str());
378 ConfigurationBase* ConfigurationManagerRW::getConfigurationByName(
const std::string &configurationName)
380 if(nameToConfigurationMap_.find(configurationName) == nameToConfigurationMap_.end())
382 __SS__ <<
"Configuration not found with name: " << configurationName << std::endl;
384 if((f=configurationName.find(
' ')) != std::string::npos)
385 ss <<
"There was a space character found in the configuration name needle at position " <<
386 f <<
" in the string (was this intended?). " << std::endl;
387 __COUT_ERR__ <<
"\n" << ss.str();
388 throw std::runtime_error(ss.str());
390 return nameToConfigurationMap_[configurationName];
398 ConfigurationBase* ConfigurationManagerRW::getVersionedConfigurationByName(
const std::string &configurationName,
401 auto it = nameToConfigurationMap_.find(configurationName);
402 if(it == nameToConfigurationMap_.end())
404 __SS__ <<
"\nCan not find configuration named '" <<
406 "'\n\n\n\nYou need to load the configuration before it can be used." <<
407 "It probably is missing from the member list of the Configuration Group that was loaded?\n\n\n\n\n"
409 throw std::runtime_error(ss.str());
412 theInterface_->get(configuration, configurationName, 0 , 0,
416 looseColumnMatching);
417 return configuration;
423 ConfigurationVersion ConfigurationManagerRW::saveNewConfiguration(
const std::string &configurationName,
430 config->getTemporaryView(temporaryVersion)->setAuthor(username_);
434 newVersion = theInterface_->saveNewVersion(config, temporaryVersion);
436 config->setActiveView(newVersion);
439 while(!makeTemporary && !newVersion.isScratchVersion() &&
440 allConfigurationInfo_[configurationName].versions_.find(newVersion) !=
441 allConfigurationInfo_[configurationName].versions_.end())
443 __COUT_ERR__ <<
"What happenened!?? ERROR::: new persistent version v" << newVersion <<
444 " already exists!? How is it possible? Retrace your steps and tell an admin." << std::endl;
447 temporaryVersion = config->createTemporaryView(newVersion);
449 if(newVersion.isTemporaryVersion())
450 newVersion = temporaryVersion;
452 newVersion = ConfigurationVersion::getNextVersion(newVersion);
454 __COUT_WARN__ <<
"Attempting to recover and use v" << newVersion << std::endl;
458 newVersion = theInterface_->saveNewVersion(config, temporaryVersion, newVersion);
460 config->setActiveView(newVersion);
463 if(newVersion.isInvalid())
465 __SS__ <<
"Something went wrong saving the new version v" << newVersion <<
466 ". What happened?! (duplicates? database error?)" << std::endl;
467 __COUT_ERR__ <<
"\n" << ss.str();
468 throw std::runtime_error(ss.str());
472 allConfigurationInfo_[configurationName].versions_.insert(newVersion);
474 __COUT__ <<
"New version added to info " << newVersion << std::endl;
484 void ConfigurationManagerRW::eraseTemporaryVersion(
const std::string &configurationName,
489 config->trimTemporary(targetVersion);
492 if(allConfigurationInfo_.find(configurationName) ==
493 allConfigurationInfo_.end())
return;
496 if(targetVersion.isInvalid())
499 for(
auto it = allConfigurationInfo_[configurationName].versions_.begin();
500 it != allConfigurationInfo_[configurationName].versions_.end(); )
502 if(it->isTemporaryVersion())
504 __COUT__ <<
"Removing version info: " << *it << std::endl;
505 allConfigurationInfo_[configurationName].versions_.erase(it++);
513 __COUT__ <<
"Removing version info: " << targetVersion << std::endl;
514 auto it = allConfigurationInfo_[configurationName].versions_.find(targetVersion);
515 if(it == allConfigurationInfo_[configurationName].versions_.end())
517 __COUT__ <<
"Target version was not found in info versions..." << std::endl;
520 allConfigurationInfo_[configurationName].versions_.erase(
521 allConfigurationInfo_[configurationName].versions_.find(targetVersion));
522 __COUT__ <<
"Target version was erased from info." << std::endl;
531 void ConfigurationManagerRW::clearCachedVersions(
const std::string &configurationName)
535 config->trimCache(0);
543 void ConfigurationManagerRW::clearAllCachedVersions()
545 for(
auto configInfo: allConfigurationInfo_)
546 configInfo.second.configurationPtr_->trimCache(0);
551 ConfigurationVersion ConfigurationManagerRW::copyViewToCurrentColumns(
const std::string &configurationName,
554 getConfigurationByName(configurationName)->reset();
566 allConfigurationInfo_[configurationName].versions_.insert(newTemporaryVersion);
568 return newTemporaryVersion;
583 const std::map<std::string, ConfigurationVersion> &groupMemberMap)
585 std::set<std::string > fullGroupNames =
586 theInterface_->getAllConfigurationGroupNames(groupName);
593 const unsigned int MAX_DEPTH_TO_CHECK = 20;
594 unsigned int keyMinToCheck = 0;
597 if(fullGroupNames.size() > MAX_DEPTH_TO_CHECK)
600 for(
const std::string& fullName: fullGroupNames)
602 ConfigurationGroupKey::getGroupNameAndKey(fullName,name,key);
603 if(key.key() > keyMinToCheck)
604 keyMinToCheck = key.key();
608 if(keyMinToCheck >= MAX_DEPTH_TO_CHECK - 1)
609 keyMinToCheck -= MAX_DEPTH_TO_CHECK - 1;
613 __COUT__ <<
"Checking groups back to key... " << keyMinToCheck << std::endl;
616 __COUT__ <<
"Checking all groups." << std::endl;
619 for(
const std::string& fullName: fullGroupNames)
621 ConfigurationGroupKey::getGroupNameAndKey(fullName,name,key);
623 if(key.key() < keyMinToCheck)
continue;
628 __COUT__ <<
"checking group... " << fullName << std::endl;
629 compareToMemberMap = theInterface_->getConfigurationGroupMembers(fullName);
632 for(
auto &memberPair: groupMemberMap)
635 if(compareToMemberMap.find(memberPair.first) == compareToMemberMap.end() ||
636 memberPair.second != compareToMemberMap[memberPair.first])
643 if(isDifferent)
continue;
646 if(groupMemberMap.size() != compareToMemberMap.size())
continue;
648 __COUT__ <<
"Found exact match with key: " << key << std::endl;
652 __COUT__ <<
"No match found - this group is new!" << std::endl;
665 ConfigurationGroupKey ConfigurationManagerRW::saveNewConfigurationGroup(
const std::string &groupName,
666 std::map<std::string, ConfigurationVersion> &groupMembers,
676 if(groupMembers.size() == 0)
678 __SS__ <<
"Empty group member list. Can not create a group without members!" << std::endl;
679 __COUT_ERR__ << ss.str();
680 throw std::runtime_error(ss.str());
685 if(!previousVersion.isInvalid())
686 newKey = ConfigurationGroupKey::getNextKey(previousVersion);
689 std::set<ConfigurationGroupKey> keys = theInterface_->getKeys(groupName);
691 newKey = ConfigurationGroupKey::getNextKey(*(keys.crbegin()));
693 newKey = ConfigurationGroupKey::getDefaultKey();
696 __COUT__ <<
"New Key for group: " << groupName <<
" found as " << newKey << std::endl;
700 std::map<std::string, ConfigurationInfo> allCfgInfo = getAllConfigurationInfo();
701 for(
auto &memberPair : groupMembers )
704 if(allCfgInfo.find(memberPair.first) == allCfgInfo.end())
706 __COUT_ERR__ <<
"Group member \"" << memberPair.first <<
"\" not found in configuration!";
708 if(groupMetadataTable_.getConfigurationName() ==
711 __COUT_WARN__ <<
"Looks like this is the groupMetadataTable_. " <<
712 "Note that this table is added to the member map when groups are saved." <<
713 "It should not be part of member map when calling this function." << std::endl;
714 __COUT__ <<
"Attempting to recover." << std::endl;
715 groupMembers.erase(groupMembers.find(memberPair.first));
719 __SS__ << (
"Group member not found!") << std::endl;
720 __COUT_ERR__ << ss.str();
721 throw std::runtime_error(ss.str());
725 if(allCfgInfo[memberPair.first].versions_.find(memberPair.second) ==
726 allCfgInfo[memberPair.first].versions_.end())
728 __SS__ <<
"Group member \"" << memberPair.first <<
"\" version \"" <<
729 memberPair.second <<
"\" not found in configuration!";
730 __COUT_ERR__ << ss.str();
731 throw std::runtime_error(ss.str());
740 __COUT__ << username_ <<
" " << time(0) <<
" " << groupComment << std::endl;
742 groupMetadataTable_.getViewP()->setValue(groupComment,0,1);
743 groupMetadataTable_.getViewP()->setValue(username_,0,2);
744 groupMetadataTable_.getViewP()->setValue(time(0),0,3);
747 groupMetadataTable_.getViewP()->setVersion(
748 ConfigurationVersion::getNextVersion(theInterface_->findLatestVersion(&groupMetadataTable_))
753 theInterface_->saveActiveVersion(&groupMetadataTable_);
756 groupMembers[groupMetadataTable_.getConfigurationName()] =
757 groupMetadataTable_.getViewVersion();
759 theInterface_->saveConfigurationGroup(groupMembers,
760 ConfigurationGroupKey::getFullGroupString(groupName,newKey));
761 __COUT__ <<
"Created config group: " << groupName <<
":" << newKey << std::endl;
763 catch(std::runtime_error &e)
765 __COUT_ERR__ <<
"Failed to create config group: " << groupName <<
":" << newKey << std::endl;
766 __COUT_ERR__ <<
"\n\n" << e.what() << std::endl;
771 __COUT_ERR__ <<
"Failed to create config group: " << groupName <<
":" << newKey << std::endl;
785 __COUT_INFO__ <<
"Creating new backbone from temporary version " <<
786 temporaryVersion << std::endl;
791 auto backboneMemberNames = ConfigurationManager::getBackboneMemberNames();
792 for (
auto& name : backboneMemberNames)
794 retNewVersion = ConfigurationManager::getConfigurationByName(name)->getNextVersion();
795 __COUT__ <<
"New version for backbone member (" << name <<
"): " <<
796 retNewVersion << std::endl;
797 if(retNewVersion > newVersion)
798 newVersion = retNewVersion;
801 __COUT__ <<
"Common new backbone version found as " <<
802 newVersion << std::endl;
805 for (
auto& name : backboneMemberNames)
808 retNewVersion = getConfigurationInterface()->saveNewVersion(
809 getConfigurationByName(name), temporaryVersion, newVersion);
810 if(retNewVersion != newVersion)
812 __SS__ <<
"Failure! New view requested was " <<
813 newVersion <<
". Mismatched new view created: " << retNewVersion << std::endl;
814 __COUT_ERR__ << ss.str();
815 throw std::runtime_error(ss.str());
823 void ConfigurationManagerRW::testXDAQContext()
979 __COUT__ <<
"Loading config..." << std::endl;
985 __COUT__ << std::endl;
987 __COUT__ <<
"Value: " << v << std::endl;
988 __COUT__ <<
"Value index: " << t.getValue<
int>() << std::endl;
1030 __COUT__ <<
"Failed to load config..." << std::endl;