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();
66 allGroupInfo_.clear();
73 __COUT__ <<
"======================================================== getAllConfigurationInfo start" << std::endl;
74 __COUT__ <<
"Refreshing all! Extracting list of Configuration tables..." << std::endl;
77 std::string path = CONFIGURATION_INFO_PATH;
78 char fileExt[] = CONFIGURATION_INFO_EXT;
79 const unsigned char MIN_CONFIG_NAME_SZ = 3;
80 if( (pDIR=opendir( path.c_str() )) != 0 )
82 while((entry = readdir(pDIR)) != 0)
85 if(strlen(entry->d_name) < strlen(fileExt)+MIN_CONFIG_NAME_SZ)
90 &(entry->d_name[strlen(entry->d_name) - strlen(fileExt)]),
95 entry->d_name[strlen(entry->d_name) - strlen(fileExt)] =
'\0';
104 theInterface_->get(configuration,
109 catch(cet::exception)
111 if(configuration)
delete configuration;
114 __COUT__ <<
"Skipping! No valid class found for... " << entry->d_name <<
"\n";
117 catch(std::runtime_error &e)
119 if(configuration)
delete configuration;
122 __COUT__ <<
"Skipping! No valid class found for... " << entry->d_name <<
"\n";
123 __COUT__ <<
"Error: " << e.what() << std::endl;
129 if(accumulatedErrors)
132 if(errorFilterName ==
"" ||
133 errorFilterName == entry->d_name)
135 *accumulatedErrors += std::string(
"\nIn table '") + entry->d_name +
138 __SS__ <<
"Attempting to allow illegal columns!" << std::endl;
139 *accumulatedErrors += ss.str();
143 __COUT__ <<
"Attempting to allow illegal columns!" << std::endl;
146 std::string returnedAccumulatedErrors;
150 configuration =
new ConfigurationBase(entry->d_name, &returnedAccumulatedErrors);
154 __COUT__ <<
"Skipping! Allowing illegal columns didn't work either... " <<
155 entry->d_name <<
"\n";
158 __COUT__ <<
"Error (but allowed): " << returnedAccumulatedErrors << std::endl;
160 if(errorFilterName ==
"" ||
161 errorFilterName == entry->d_name)
162 *accumulatedErrors += std::string(
"\nIn table '") + entry->d_name +
163 "'..." + returnedAccumulatedErrors;
171 if(nameToConfigurationMap_[entry->d_name])
174 std::set<ConfigurationVersion> versions =
175 nameToConfigurationMap_[entry->d_name]->getStoredVersions();
176 for(
auto &version:versions)
177 if(version.isTemporaryVersion())
179 __COUT__ <<
"copying tmp = " << version << std::endl;
183 nameToConfigurationMap_[entry->d_name]->setActiveView(version);
184 configuration->copyView(
185 nameToConfigurationMap_[entry->d_name]->getView(),
193 delete nameToConfigurationMap_[entry->d_name];
194 nameToConfigurationMap_[entry->d_name] = 0;
197 nameToConfigurationMap_[entry->d_name] = configuration;
199 allConfigurationInfo_[entry->d_name].configurationPtr_ = configuration;
200 allConfigurationInfo_[entry->d_name].versions_ = theInterface_->getVersions(configuration);
204 std::set<ConfigurationVersion> versions =
205 nameToConfigurationMap_[entry->d_name]->getStoredVersions();
206 for(
auto &version:versions)
207 if(version.isTemporaryVersion())
209 __COUT__ <<
"surviving tmp = " << version << std::endl;
210 allConfigurationInfo_[entry->d_name].versions_.emplace(version);
215 __COUT__ <<
"Extracting list of Configuration tables complete" << std::endl;
218 init(accumulatedErrors);
220 __COUT__ <<
"======================================================== getAllConfigurationInfo end" << std::endl;
225 std::set<std::string > configGroups = theInterface_->getAllConfigurationGroupNames();
226 __COUT__ <<
"Number of Groups: " << configGroups.size() << std::endl;
230 for(
const auto& fullName:configGroups)
232 ConfigurationGroupKey::getGroupNameAndKey(fullName,name,key);
233 cacheGroupKey(name,key);
237 for(
auto& groupInfo:allGroupInfo_)
241 loadConfigurationGroup(
243 groupInfo.second.getLatestKey(),
245 &groupInfo.second.latestKeyMemberMap_ ,
247 &groupInfo.second.latestKeyGroupComment_,
248 &groupInfo.second.latestKeyGroupAuthor_,
249 &groupInfo.second.latestKeyGroupCreationTime_,
251 &groupInfo.second.latestKeyGroupTypeString_);
255 __COUT_WARN__ <<
"Error occurred loading latest group info into cache for '" <<
256 groupInfo.first <<
"'..." << __E__;
257 groupInfo.second.latestKeyGroupComment_ =
"UNKNOWN";
258 groupInfo.second.latestKeyGroupAuthor_ =
"UNKNOWN";
259 groupInfo.second.latestKeyGroupCreationTime_ =
"0";
260 groupInfo.second.latestKeyGroupTypeString_ =
"UNKNOWN";
264 return allConfigurationInfo_;
270 std::map<std::string,std::map<std::string,ConfigurationVersion> >
271 ConfigurationManagerRW::getActiveVersionAliases(
void)
const
273 __COUT__ <<
"getActiveVersionAliases()" << std::endl;
274 std::map<std::string,std::map<std::string,ConfigurationVersion> > retMap;
276 std::map<std::string, ConfigurationVersion> activeVersions = getActiveVersions();
277 std::string versionAliasesTableName =
"VersionAliasesConfiguration";
278 if(activeVersions.find(versionAliasesTableName) == activeVersions.end())
280 __SS__ <<
"Active version of VersionAliases missing!" <<
281 "Make sure you have a valid active Backbone Group." << std::endl;
282 __COUT_WARN__ <<
"\n" << ss.str();
286 __COUT__ <<
"activeVersions[\"VersionAliasesConfiguration\"]=" <<
287 activeVersions[versionAliasesTableName] << std::endl;
290 if(!ConfigurationInterface::isVersionTrackingEnabled())
291 for(
const auto &tableInfo:allConfigurationInfo_)
292 for(
const auto &version:tableInfo.second.versions_)
293 if(version.isScratchVersion())
294 retMap[tableInfo.first][ConfigurationManager::SCRATCH_VERSION_ALIAS] =
297 std::vector<std::pair<std::string,ConfigurationTree> > aliasNodePairs =
298 getNode(versionAliasesTableName).getChildren();
303 std::string configName, versionAlias;
304 for(
auto& aliasNodePair:aliasNodePairs)
306 configName = aliasNodePair.second.getNode(
307 "ConfigurationName").getValueAsString();
308 versionAlias = aliasNodePair.second.getNode(
309 "VersionAlias").getValueAsString();
311 if(retMap.find(configName) != retMap.end() &&
312 retMap[configName].find(versionAlias) != retMap[configName].end())
317 aliasNodePair.second.getNode(
"Version").getValueAsString());
327 void ConfigurationManagerRW::activateConfigurationGroup(
const std::string &configGroupName,
330 loadConfigurationGroup(configGroupName,configGroupKey,
334 accumulatedTreeErrors);
336 if(accumulatedTreeErrors &&
337 *accumulatedTreeErrors !=
"")
339 __COUT_ERR__ <<
"Errors were accumulated so de-activating group: " <<
340 configGroupName <<
" (" << configGroupKey <<
")" << std::endl;
342 { destroyConfigurationGroup(configGroupName,
true); }
346 __COUT_INFO__ <<
"Updating persistent active groups to " <<
347 ConfigurationManager::ACTIVE_GROUP_FILENAME <<
" ..." << std::endl;
348 __MOUT_INFO__ <<
"Updating persistent active groups to " <<
349 ConfigurationManager::ACTIVE_GROUP_FILENAME <<
" ..." << std::endl;
351 std::string fn = ConfigurationManager::ACTIVE_GROUP_FILENAME;
352 FILE *fp = fopen(fn.c_str(),
"w");
355 __SS__ <<
"Fatal Error! Unable to open the file " <<
356 ConfigurationManager::ACTIVE_GROUP_FILENAME <<
" for editing! Is there a permissions problem?" << std::endl;
357 __COUT_ERR__ << ss.str();
358 throw std::runtime_error(ss.str());
362 __COUT_INFO__ <<
"Active Context: " << theContextGroup_ <<
"(" <<
363 (theContextGroupKey_?theContextGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
364 __COUT_INFO__ <<
"Active Backbone: " << theBackboneGroup_ <<
"(" <<
365 (theBackboneGroupKey_?theBackboneGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
366 __COUT_INFO__ <<
"Active Iterate: " << theIterateGroup_ <<
"(" <<
367 (theIterateGroupKey_?theIterateGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
368 __COUT_INFO__ <<
"Active Configuration: " << theConfigurationGroup_ <<
"(" <<
369 (theConfigurationGroupKey_?theConfigurationGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
371 __MOUT_INFO__ <<
"Active Context: " << theContextGroup_ <<
"(" <<
372 (theContextGroupKey_?theContextGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
373 __MOUT_INFO__ <<
"Active Backbone: " << theBackboneGroup_ <<
"(" <<
374 (theBackboneGroupKey_?theBackboneGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
375 __MOUT_INFO__ <<
"Active Iterate: " << theIterateGroup_ <<
"(" <<
376 (theIterateGroupKey_?theIterateGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
377 __MOUT_INFO__ <<
"Active Configuration: " << theConfigurationGroup_ <<
"(" <<
378 (theConfigurationGroupKey_?theConfigurationGroupKey_->toString().c_str():
"-1") <<
")" << std::endl;
380 fprintf(fp,
"%s\n",theContextGroup_.c_str());
381 fprintf(fp,
"%s\n",theContextGroupKey_?theContextGroupKey_->toString().c_str():
"-1");
382 fprintf(fp,
"%s\n",theBackboneGroup_.c_str());
383 fprintf(fp,
"%s\n",theBackboneGroupKey_?theBackboneGroupKey_->toString().c_str():
"-1");
384 fprintf(fp,
"%s\n",theIterateGroup_.c_str());
385 fprintf(fp,
"%s\n",theIterateGroupKey_?theIterateGroupKey_->toString().c_str():
"-1");
386 fprintf(fp,
"%s\n",theConfigurationGroup_.c_str());
387 fprintf(fp,
"%s\n",theConfigurationGroupKey_?theConfigurationGroupKey_->toString().c_str():
"-1");
397 __COUT_INFO__ <<
"Creating temporary backbone view from version " <<
398 sourceViewVersion << std::endl;
403 auto backboneMemberNames = ConfigurationManager::getBackboneMemberNames();
404 for (
auto& name : backboneMemberNames)
406 retTmpVersion = ConfigurationManager::getConfigurationByName(name)->getNextTemporaryVersion();
407 if(retTmpVersion < tmpVersion)
408 tmpVersion = retTmpVersion;
411 __COUT__ <<
"Common temporary backbone version found as " <<
412 tmpVersion << std::endl;
415 for (
auto& name : backboneMemberNames)
417 retTmpVersion = getConfigurationByName(name)->createTemporaryView(sourceViewVersion, tmpVersion);
418 if(retTmpVersion != tmpVersion)
420 __SS__ <<
"Failure! Temporary view requested was " <<
421 tmpVersion <<
". Mismatched temporary view created: " << retTmpVersion << std::endl;
422 __COUT_ERR__ << ss.str();
423 throw std::runtime_error(ss.str());
433 ConfigurationBase* ConfigurationManagerRW::getConfigurationByName(
const std::string &configurationName)
435 if(nameToConfigurationMap_.find(configurationName) == nameToConfigurationMap_.end())
437 __SS__ <<
"Configuration not found with name: " << configurationName << std::endl;
439 if((f=configurationName.find(
' ')) != std::string::npos)
440 ss <<
"There was a space character found in the configuration name needle at position " <<
441 f <<
" in the string (was this intended?). " << std::endl;
442 __COUT_ERR__ <<
"\n" << ss.str();
443 throw std::runtime_error(ss.str());
445 return nameToConfigurationMap_[configurationName];
453 ConfigurationBase* ConfigurationManagerRW::getVersionedConfigurationByName(
const std::string &configurationName,
456 auto it = nameToConfigurationMap_.find(configurationName);
457 if(it == nameToConfigurationMap_.end())
459 __SS__ <<
"\nCan not find configuration named '" <<
461 "'\n\n\n\nYou need to load the configuration before it can be used." <<
462 "It probably is missing from the member list of the Configuration Group that was loaded?\n\n\n\n\n"
464 throw std::runtime_error(ss.str());
467 theInterface_->get(configuration, configurationName, 0 , 0,
471 looseColumnMatching);
472 return configuration;
479 const std::string &configurationName,
488 config->getTemporaryView(temporaryVersion)->setAuthor(username_);
492 newVersion = theInterface_->saveNewVersion(config, temporaryVersion);
494 config->setActiveView(newVersion);
497 while(!makeTemporary && !newVersion.isScratchVersion() &&
498 allConfigurationInfo_[configurationName].versions_.find(newVersion) !=
499 allConfigurationInfo_[configurationName].versions_.end())
501 __COUT_ERR__ <<
"What happenened!?? ERROR::: new persistent version v" << newVersion <<
502 " already exists!? How is it possible? Retrace your steps and tell an admin." << std::endl;
505 temporaryVersion = config->createTemporaryView(newVersion);
507 if(newVersion.isTemporaryVersion())
508 newVersion = temporaryVersion;
510 newVersion = ConfigurationVersion::getNextVersion(newVersion);
512 __COUT_WARN__ <<
"Attempting to recover and use v" << newVersion << std::endl;
516 newVersion = theInterface_->saveNewVersion(config, temporaryVersion, newVersion);
518 config->setActiveView(newVersion);
521 if(newVersion.isInvalid())
523 __SS__ <<
"Something went wrong saving the new version v" << newVersion <<
524 ". What happened?! (duplicates? database error?)" << std::endl;
525 __COUT_ERR__ <<
"\n" << ss.str();
526 throw std::runtime_error(ss.str());
530 allConfigurationInfo_[configurationName].versions_.insert(newVersion);
532 __COUT__ <<
"New version added to info " << newVersion << std::endl;
542 void ConfigurationManagerRW::eraseTemporaryVersion(
const std::string &configurationName,
547 config->trimTemporary(targetVersion);
550 if(allConfigurationInfo_.find(configurationName) ==
551 allConfigurationInfo_.end())
return;
554 if(targetVersion.isInvalid())
557 for(
auto it = allConfigurationInfo_[configurationName].versions_.begin();
558 it != allConfigurationInfo_[configurationName].versions_.end(); )
560 if(it->isTemporaryVersion())
562 __COUT__ <<
"Removing version info: " << *it << std::endl;
563 allConfigurationInfo_[configurationName].versions_.erase(it++);
571 __COUT__ <<
"Removing version info: " << targetVersion << std::endl;
572 auto it = allConfigurationInfo_[configurationName].versions_.find(targetVersion);
573 if(it == allConfigurationInfo_[configurationName].versions_.end())
575 __COUT__ <<
"Target version was not found in info versions..." << std::endl;
578 allConfigurationInfo_[configurationName].versions_.erase(
579 allConfigurationInfo_[configurationName].versions_.find(targetVersion));
580 __COUT__ <<
"Target version was erased from info." << std::endl;
589 void ConfigurationManagerRW::clearCachedVersions(
const std::string &configurationName)
593 config->trimCache(0);
601 void ConfigurationManagerRW::clearAllCachedVersions()
603 for(
auto configInfo: allConfigurationInfo_)
604 configInfo.second.configurationPtr_->trimCache(0);
609 ConfigurationVersion ConfigurationManagerRW::copyViewToCurrentColumns(
const std::string &configurationName,
612 getConfigurationByName(configurationName)->reset();
624 allConfigurationInfo_[configurationName].versions_.insert(newTemporaryVersion);
626 return newTemporaryVersion;
631 void ConfigurationManagerRW::cacheGroupKey(
const std::string &groupName,
634 allGroupInfo_[groupName].keys_.emplace(key);
641 const GroupInfo& ConfigurationManagerRW::getGroupInfo(
const std::string &groupName)
649 auto it = allGroupInfo_.find(groupName);
650 if(it == allGroupInfo_.end())
652 __SS__ <<
"Group name '" << groupName <<
"' not found in group info! (creating empty info)" << __E__;
653 __COUT_WARN__ << ss.str();
655 return allGroupInfo_[groupName];
670 const std::map<std::string, ConfigurationVersion> &groupMemberMap)
680 const GroupInfo& groupInfo = getGroupInfo(groupName);
687 const unsigned int MAX_DEPTH_TO_CHECK = 20;
688 unsigned int keyMinToCheck = 0;
690 if(groupInfo.keys_.size())
691 keyMinToCheck = groupInfo.keys_.rbegin()->key();
692 if(keyMinToCheck > MAX_DEPTH_TO_CHECK)
694 keyMinToCheck -= MAX_DEPTH_TO_CHECK;
695 __COUT__ <<
"Checking groups back to key... " << keyMinToCheck << std::endl;
700 __COUT__ <<
"Checking all groups." << std::endl;
727 std::string fullName;
728 for(
const auto& key: groupInfo.keys_)
732 if(key.key() < keyMinToCheck)
continue;
737 fullName = ConfigurationGroupKey::getFullGroupString(groupName,key);
739 __COUT__ <<
"checking group... " << fullName << std::endl;
740 compareToMemberMap = theInterface_->getConfigurationGroupMembers(fullName);
743 for(
auto &memberPair: groupMemberMap)
746 if(compareToMemberMap.find(memberPair.first) == compareToMemberMap.end() ||
747 memberPair.second != compareToMemberMap[memberPair.first])
754 if(isDifferent)
continue;
757 if(groupMemberMap.size() != compareToMemberMap.size())
continue;
759 __COUT__ <<
"Found exact match with key: " << key << std::endl;
763 __COUT__ <<
"No match found - this group is new!" << std::endl;
777 const std::string &groupName,
778 std::map<std::string, ConfigurationVersion> &groupMembers,
779 const std::string &groupComment)
788 if(groupMembers.size() == 0)
790 __SS__ <<
"Empty group member list. Can not create a group without members!" << std::endl;
791 __COUT_ERR__ << ss.str();
792 throw std::runtime_error(ss.str());
802 std::set<ConfigurationGroupKey> keys = theInterface_->getKeys(groupName);
804 newKey = ConfigurationGroupKey::getNextKey(*(keys.crbegin()));
806 newKey = ConfigurationGroupKey::getDefaultKey();
809 __COUT__ <<
"New Key for group: " << groupName <<
" found as " << newKey << std::endl;
813 std::map<std::string, ConfigurationInfo> allCfgInfo = getAllConfigurationInfo();
814 for(
auto &memberPair : groupMembers )
817 if(allCfgInfo.find(memberPair.first) == allCfgInfo.end())
819 __COUT_ERR__ <<
"Group member \"" << memberPair.first <<
"\" not found in configuration!";
821 if(groupMetadataTable_.getConfigurationName() ==
824 __COUT_WARN__ <<
"Looks like this is the groupMetadataTable_. " <<
825 "Note that this table is added to the member map when groups are saved." <<
826 "It should not be part of member map when calling this function." << std::endl;
827 __COUT__ <<
"Attempting to recover." << std::endl;
828 groupMembers.erase(groupMembers.find(memberPair.first));
832 __SS__ << (
"Group member not found!") << std::endl;
833 __COUT_ERR__ << ss.str();
834 throw std::runtime_error(ss.str());
838 if(allCfgInfo[memberPair.first].versions_.find(memberPair.second) ==
839 allCfgInfo[memberPair.first].versions_.end())
841 __SS__ <<
"Group member \"" << memberPair.first <<
"\" version \"" <<
842 memberPair.second <<
"\" not found in configuration!";
843 __COUT_ERR__ << ss.str();
844 throw std::runtime_error(ss.str());
853 __COUT__ << username_ <<
" " << time(0) <<
" " << groupComment << std::endl;
855 groupMetadataTable_.getViewP()->setValue(groupComment,0,1);
856 groupMetadataTable_.getViewP()->setValue(username_,0,2);
857 groupMetadataTable_.getViewP()->setValue(time(0),0,3);
860 groupMetadataTable_.getViewP()->setVersion(
861 ConfigurationVersion::getNextVersion(theInterface_->findLatestVersion(&groupMetadataTable_))
866 theInterface_->saveActiveVersion(&groupMetadataTable_);
869 groupMembers[groupMetadataTable_.getConfigurationName()] =
870 groupMetadataTable_.getViewVersion();
872 theInterface_->saveConfigurationGroup(groupMembers,
873 ConfigurationGroupKey::getFullGroupString(groupName,newKey));
874 __COUT__ <<
"Created config group: " << groupName <<
":" << newKey << std::endl;
876 catch(std::runtime_error &e)
878 __COUT_ERR__ <<
"Failed to create config group: " << groupName <<
":" << newKey << std::endl;
879 __COUT_ERR__ <<
"\n\n" << e.what() << std::endl;
884 __COUT_ERR__ <<
"Failed to create config group: " << groupName <<
":" << newKey << std::endl;
890 cacheGroupKey(groupName,newKey);
902 __COUT_INFO__ <<
"Creating new backbone from temporary version " <<
903 temporaryVersion << std::endl;
908 auto backboneMemberNames = ConfigurationManager::getBackboneMemberNames();
909 for (
auto& name : backboneMemberNames)
911 retNewVersion = ConfigurationManager::getConfigurationByName(name)->getNextVersion();
912 __COUT__ <<
"New version for backbone member (" << name <<
"): " <<
913 retNewVersion << std::endl;
914 if(retNewVersion > newVersion)
915 newVersion = retNewVersion;
918 __COUT__ <<
"Common new backbone version found as " <<
919 newVersion << std::endl;
922 for (
auto& name : backboneMemberNames)
925 retNewVersion = getConfigurationInterface()->saveNewVersion(
926 getConfigurationByName(name), temporaryVersion, newVersion);
927 if(retNewVersion != newVersion)
929 __SS__ <<
"Failure! New view requested was " <<
930 newVersion <<
". Mismatched new view created: " << retNewVersion << std::endl;
931 __COUT_ERR__ << ss.str();
932 throw std::runtime_error(ss.str());
940 void ConfigurationManagerRW::testXDAQContext()
1096 __COUT__ <<
"Loading config..." << std::endl;
1102 __COUT__ << std::endl;
1104 __COUT__ <<
"Value: " << v << std::endl;
1105 __COUT__ <<
"Value index: " << t.getValue<
int>() << std::endl;
1147 __COUT__ <<
"Failed to load config..." << std::endl;