00001 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
00002 #include "otsdaq-core/ConfigurationInterface/ConfigurationInterface.h"
00003 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationGroupKey.h"
00004 #include "otsdaq-core/ProgressBar/ProgressBar.h"
00005
00006 #include <fstream>
00007
00008
00009 using namespace ots;
00010
00011
00012 #undef __MF_SUBJECT__
00013 #define __MF_SUBJECT__ "ConfigurationManager"
00014
00015 const std::string ConfigurationManager::READONLY_USER = "READONLY_USER";
00016
00017 const std::string ConfigurationManager::XDAQ_CONTEXT_CONFIG_NAME = "XDAQContextConfiguration";
00018
00019
00020 const std::string ConfigurationManager::ACTIVE_GROUP_FILENAME = ((getenv("SERVICE_DATA_PATH") == NULL)?(std::string(getenv("USER_DATA"))+"/ServiceData"):(std::string(getenv("SERVICE_DATA_PATH")))) + "/ActiveConfigurationGroups.cfg";
00021 const std::string ConfigurationManager::ALIAS_VERSION_PREAMBLE = "ALIAS:";
00022 const std::string ConfigurationManager::SCRATCH_VERSION_ALIAS = "Scratch";
00023
00024 #define CORE_TABLE_INFO_FILENAME ((getenv("SERVICE_DATA_PATH") == NULL)?(std::string(getenv("USER_DATA"))+"/ServiceData"):(std::string(getenv("SERVICE_DATA_PATH")))) + "/CoreTableInfoNames.dat"
00025
00026
00027 const std::string ConfigurationManager::ACTIVE_GROUP_NAME_CONTEXT = "Context";
00028 const std::string ConfigurationManager::ACTIVE_GROUP_NAME_BACKBONE = "Backbone";
00029 const std::string ConfigurationManager::ACTIVE_GROUP_NAME_CONFIGURATION = "Configuration";
00030
00031
00032
00033 ConfigurationManager::ConfigurationManager()
00034 : username_ (ConfigurationManager::READONLY_USER)
00035 , theInterface_ (0)
00036 , theConfigurationGroupKey_ (0)
00037 , theContextGroupKey_ (0)
00038 , theBackboneGroupKey_ (0)
00039 , theConfigurationGroup_ ("")
00040 , theContextGroup_ ("")
00041 , theBackboneGroup_ ("")
00042 , contextMemberNames_ ({XDAQ_CONTEXT_CONFIG_NAME,"XDAQApplicationConfiguration","DesktopIconConfiguration","MessageFacilityConfiguration","TheSupervisorConfiguration","StateMachineConfiguration","DesktopWindowParameterConfiguration"})
00043 , backboneMemberNames_ ({"GroupAliasesConfiguration","VersionAliasesConfiguration"})
00044 {
00045 theInterface_ = ConfigurationInterface::getInstance(false);
00046
00047
00048
00049 {
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 groupMetadataTable_.setConfigurationName(ConfigurationInterface::GROUP_METADATA_TABLE_NAME);
00060
00061 std::vector<ViewColumnInfo>* colInfo =
00062 groupMetadataTable_.getMockupViewP()->getColumnsInfoP();
00063
00064
00065 colInfo->push_back(ViewColumnInfo(
00066 ViewColumnInfo::TYPE_UID,
00067 "UnusedUID",
00068 "UNUSED_UID",
00069 ViewColumnInfo::DATATYPE_NUMBER,
00070 "",0
00071 ));
00072 colInfo->push_back(ViewColumnInfo(
00073 ViewColumnInfo::TYPE_COMMENT,
00074 "CommentDescription",
00075 "COMMENT_DESCRIPTION",
00076 ViewColumnInfo::DATATYPE_STRING,
00077 "",0
00078 ));
00079 colInfo->push_back(ViewColumnInfo(
00080 ViewColumnInfo::TYPE_AUTHOR,
00081 "GroupAuthor",
00082 "AUTHOR",
00083 ViewColumnInfo::DATATYPE_STRING,
00084 "",0
00085 ));
00086 colInfo->push_back(ViewColumnInfo(
00087 ViewColumnInfo::TYPE_TIMESTAMP,
00088 "GroupCreationTime",
00089 "GROUP_CREATION_TIME",
00090 ViewColumnInfo::DATATYPE_TIME,
00091 "",0
00092 ));
00093 auto tmpVersion = groupMetadataTable_.createTemporaryView();
00094 groupMetadataTable_.setActiveView(tmpVersion);
00095
00096 groupMetadataTable_.getViewP()->addRow();
00097 }
00098
00099
00100 {
00101 FILE * fp = fopen((CORE_TABLE_INFO_FILENAME).c_str(),"w");
00102 if(fp)
00103 {
00104 for(const auto &name:contextMemberNames_)
00105 fprintf(fp,"%s\n",name.c_str());
00106 for(const auto &name:backboneMemberNames_)
00107 fprintf(fp,"%s\n",name.c_str());
00108 fclose(fp);
00109 }
00110 else
00111 __MOUT__ << "Failed to open core table info file: " << CORE_TABLE_INFO_FILENAME << std::endl;
00112 }
00113
00114 init();
00115 }
00116
00117
00118 ConfigurationManager::ConfigurationManager(const std::string& username)
00119 : ConfigurationManager ()
00120 {
00121 username_ = username;
00122 }
00123
00124
00125 ConfigurationManager::~ConfigurationManager()
00126 {
00127 destroy();
00128 }
00129
00130
00131
00132
00133
00134 void ConfigurationManager::init(std::string *accumulatedErrors)
00135 {
00136 if(accumulatedErrors) *accumulatedErrors = "";
00137
00138
00139
00140
00141 if(theInterface_->getMode() == false)
00142 {
00143 try
00144 {
00145 restoreActiveConfigurationGroups(accumulatedErrors?true:false);
00146 }
00147 catch(std::runtime_error &e)
00148 {
00149 if(accumulatedErrors) *accumulatedErrors = e.what();
00150 else throw;
00151 }
00152 }
00153 }
00154
00155
00156
00157
00158
00159
00160 void ConfigurationManager::restoreActiveConfigurationGroups(bool throwErrors)
00161 {
00162 destroyConfigurationGroup("",true);
00163
00164 std::string fn = ACTIVE_GROUP_FILENAME;
00165 FILE *fp = fopen(fn.c_str(),"r");
00166
00167 __MOUT__ << "ACTIVE_GROUP_FILENAME = " << ACTIVE_GROUP_FILENAME << std::endl;
00168 __MOUT__ << "ARTDAQ_DATABASE_URI = " << std::string(getenv("ARTDAQ_DATABASE_URI")) << std::endl;
00169
00170 if(!fp) return;
00171
00172 __MOUT__ << "throwErrors: " << throwErrors << std::endl;
00173
00174 char tmp[500];
00175 char strVal[500];
00176
00177 std::string groupName;
00178 std::string errorStr = "";
00179 bool skip;
00180
00181 __SS__;
00182
00183 for(int i=0;i<3;++i)
00184 {
00185 skip = false;
00186 fgets(tmp,500,fp);
00187 sscanf(tmp,"%s",strVal);
00188 for(unsigned int j=0;j<strlen(strVal);++j)
00189 if(!(
00190 (strVal[j] >= 'a' && strVal[j] <= 'z') ||
00191 (strVal[j] >= 'A' && strVal[j] <= 'Z') ||
00192 (strVal[j] >= '0' && strVal[j] <= '9')))
00193 {
00194 strVal[j] = '\0';
00195 __MOUT_INFO__ << "Illegal character found, so skipping!" << std::endl;
00196
00197 skip = true;
00198 break;
00199 }
00200
00201 if(skip) continue;
00202
00203 groupName = strVal;
00204 fgets(tmp,500,fp);
00205 sscanf(tmp,"%s",strVal);
00206
00207 for(unsigned int j=0;j<strlen(strVal);++j)
00208 if(!(
00209 (strVal[j] >= '0' && strVal[j] <= '9')))
00210 {
00211 strVal[j] = '\0';
00212 __MOUT_INFO__ << "Illegal character found, so skipping!" << std::endl;
00213
00214 skip = true;
00215 break;
00216 }
00217
00218 if(skip) continue;
00219
00220 try
00221 {
00222
00223 loadConfigurationGroup(groupName,ConfigurationGroupKey(strVal),true);
00224 }
00225 catch(std::runtime_error &e)
00226 {
00227 ss << "Failed to load config group in ConfigurationManager::init() with name '" <<
00228 groupName << "_v" << strVal << "'" << std::endl;
00229 ss << e.what() << std::endl;
00230
00231 errorStr += ss.str();
00232 }
00233 catch(...)
00234 {
00235 ss << "Failed to load config group in ConfigurationManager::init() with name '" <<
00236 groupName << "_v" << strVal << "'" << std::endl;
00237
00238 errorStr += ss.str();
00239 }
00240 }
00241
00242 fclose(fp);
00243
00244 if(throwErrors && errorStr != "")
00245 {
00246 __MOUT_INFO__ << "\n" << ss.str();
00247 throw std::runtime_error(errorStr);
00248 }
00249 }
00250
00251
00252
00253
00254
00255
00256 void ConfigurationManager::destroyConfigurationGroup(const std::string& theGroup, bool onlyDeactivate)
00257 {
00258
00259 bool isContext = theGroup == "" || theGroup == theContextGroup_;
00260 bool isBackbone = theGroup == "" || theGroup == theBackboneGroup_;
00261 bool isConfiguration = theGroup == "" || theGroup == theConfigurationGroup_;
00262
00263 if(!isContext && !isBackbone && !isConfiguration)
00264 {
00265 __MOUT__ << "Invalid configuration group to destroy: " << theGroup << std::endl;
00266 throw std::runtime_error("Invalid configuration group to destroy!");
00267 }
00268
00269 std::string dbgHeader = onlyDeactivate?"Deactivating":"Destroying";
00270 if(theGroup != "")
00271 {
00272 if(isContext)
00273 __MOUT__ << dbgHeader << " Context group: " << theGroup << std::endl;
00274 if(isBackbone)
00275 __MOUT__ << dbgHeader << " Backbone group: " << theGroup << std::endl;
00276 if(isConfiguration)
00277 __MOUT__ << dbgHeader << " Configuration group: " << theGroup << std::endl;
00278 }
00279
00280 std::set<std::string>::const_iterator contextFindIt, backboneFindIt;
00281 for(auto it = nameToConfigurationMap_.begin(); it != nameToConfigurationMap_.end(); )
00282 {
00283 contextFindIt = contextMemberNames_.find(it->first);
00284 backboneFindIt = backboneMemberNames_.find(it->first);
00285 if(theGroup == "" || ( (isContext && contextFindIt != contextMemberNames_.end()) ||
00286 (isBackbone && backboneFindIt != backboneMemberNames_.end()) ||
00287 (!isContext && !isBackbone &&
00288 contextFindIt == contextMemberNames_.end() &&
00289 backboneFindIt == backboneMemberNames_.end())))
00290 {
00291
00292
00293
00294
00295
00296 if(onlyDeactivate)
00297 {
00298 it->second->deactivate();
00299 ++it;
00300 }
00301 else
00302 {
00303 delete it->second;
00304 nameToConfigurationMap_.erase(it++);
00305 }
00306 }
00307 else
00308 ++it;
00309 }
00310
00311 if(isConfiguration)
00312 {
00313 theConfigurationGroup_ = "";
00314 if(theConfigurationGroupKey_ != 0)
00315 {
00316 __MOUT__ << "Destroying Configuration Key: " << *theConfigurationGroupKey_ << std::endl;
00317 theConfigurationGroupKey_.reset();
00318 }
00319
00320
00321 }
00322 if(isBackbone)
00323 {
00324 theBackboneGroup_ = "";
00325 if(theBackboneGroupKey_ != 0)
00326 {
00327 __MOUT__ << "Destroying Backbone Key: " << *theBackboneGroupKey_ << std::endl;
00328 theBackboneGroupKey_.reset();
00329 }
00330 }
00331 if(isContext)
00332 {
00333 theContextGroup_ = "";
00334 if(theContextGroupKey_ != 0)
00335 {
00336 __MOUT__ << "Destroying Context Key: " << *theContextGroupKey_ << std::endl;
00337 theContextGroupKey_.reset();
00338 }
00339 }
00340 }
00341
00342
00343 void ConfigurationManager::destroy(void)
00344 {
00345
00346
00347
00348 destroyConfigurationGroup();
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358 const std::string& ConfigurationManager::convertGroupTypeIdToName(int groupTypeId)
00359 {
00360 return groupTypeId==CONTEXT_TYPE?
00361 ConfigurationManager::ACTIVE_GROUP_NAME_CONTEXT:
00362 (groupTypeId==BACKBONE_TYPE?
00363 ConfigurationManager::ACTIVE_GROUP_NAME_BACKBONE:
00364 ConfigurationManager::ACTIVE_GROUP_NAME_CONFIGURATION);
00365 }
00366
00367
00368
00369
00370
00371
00372
00373 int ConfigurationManager::getTypeOfGroup(
00374 const std::map<std::string /*name*/, ConfigurationVersion /*version*/> &memberMap)
00375 {
00376
00377 bool isContext = true;
00378 bool isBackbone = true;
00379 bool inGroup;
00380 bool inContext = false;
00381 bool inBackbone = false;
00382 unsigned int matchCount = 0;
00383
00384 for(auto &memberPair:memberMap)
00385 {
00386
00387 inGroup = false;
00388 for(auto &contextMemberString:contextMemberNames_)
00389 if(memberPair.first == contextMemberString)
00390 {
00391 inGroup = true;
00392 inContext = true;
00393 ++matchCount;
00394 break;
00395 }
00396 if(!inGroup)
00397 {
00398 isContext = false;
00399 if(inContext)
00400 {
00401 __SS__ << "This group is an incomplete match to a Context group.\n";
00402 ss << "\nTo be a Context group, the members must exactly match" <<
00403 "the following members:\n";
00404 int i = 0;
00405 for(auto &memberName:contextMemberNames_)
00406 ss << ++i << ". " << memberName << "\n";
00407 __MOUT_ERR__ << "\n" << ss.str();
00408 throw std::runtime_error(ss.str());
00409 }
00410 }
00411
00412 inGroup = false;
00413 for(auto &backboneMemberString:backboneMemberNames_)
00414 if(memberPair.first == backboneMemberString)
00415 {
00416 inGroup = true;
00417 inBackbone = true;
00418 ++matchCount;
00419 break;
00420 }
00421 if(!inGroup)
00422 {
00423 isBackbone = false;
00424 if(inBackbone)
00425 {
00426 __SS__ << "This group is an incomplete match to a Backbone group.\n";
00427 ss << "\nTo be a Backbone group, the members must exactly match" <<
00428 "the following members:\n";
00429 int i = 0;
00430 for(auto &memberName:backboneMemberNames_)
00431 ss << ++i << ". " << memberName << "\n";
00432 __MOUT_ERR__ << "\n" << ss.str();
00433 throw std::runtime_error(ss.str());
00434 }
00435 }
00436
00437 }
00438
00439 if(isContext && matchCount != contextMemberNames_.size())
00440 {
00441 __SS__ << "This group is an incomplete match to a Context group: " <<
00442 " Size=" << matchCount << " but should be " << contextMemberNames_.size() <<
00443 std::endl;
00444 ss << "\nThe members currently are...\n";
00445 int i = 0;
00446 for(auto &memberPair:memberMap)
00447 ss << ++i << ". " << memberPair.first << "\n";
00448 ss << "\nThe expected Context members are...\n";
00449 i = 0;
00450 for(auto &memberName:contextMemberNames_)
00451 ss << ++i << ". " << memberName << "\n";
00452 __MOUT_ERR__ << "\n" << ss.str();
00453 throw std::runtime_error(ss.str());
00454 }
00455
00456 if(isBackbone && matchCount != backboneMemberNames_.size())
00457 {
00458 __SS__ << "This group is an incomplete match to a Backbone group: " <<
00459 " Size=" << matchCount << " but should be " << backboneMemberNames_.size() <<
00460 std::endl;
00461 ss << "\nThe members currently are...\n";
00462 int i = 0;
00463 for(auto &memberPair:memberMap)
00464 ss << ++i << ". " << memberPair.first << "\n";
00465 ss << "\nThe expected Backbone members are...\n";
00466 i = 0;
00467 for(auto &memberName:backboneMemberNames_)
00468 ss << ++i << ". " << memberName << "\n";
00469 __MOUT_ERR__ << "\n" << ss.str();
00470 throw std::runtime_error(ss.str());
00471 }
00472
00473 return isContext?CONTEXT_TYPE:(isBackbone?BACKBONE_TYPE:CONFIGURATION_TYPE);
00474 }
00475
00476
00477
00478
00479
00480
00481
00482 const std::string& ConfigurationManager::getTypeNameOfGroup(
00483 const std::map<std::string /*name*/, ConfigurationVersion /*version*/> &memberMap)
00484 {
00485 return convertGroupTypeIdToName(getTypeOfGroup(memberMap));
00486 }
00487
00488
00489
00490
00491 void ConfigurationManager::dumpActiveConfiguration(
00492 const std::string &filePath, const std::string &dumpType) const
00493 {
00494 time_t rawtime = time(0);
00495 __MOUT__ << "filePath = " << filePath << std::endl;
00496 __MOUT__ << "dumpType = " << dumpType << std::endl;
00497
00498
00499 std::ofstream fs;
00500 fs.open(filePath, std::fstream::out | std::fstream::trunc);
00501
00502 std::ostream *out;
00503
00504
00505 if(fs.is_open())
00506 out = &fs;
00507 else
00508 out = &(std::cout);
00509
00510
00511 (*out) << "#################################" << std::endl;
00512 (*out) << "This is an ots configuration dump.\n\n" << std::endl;
00513 (*out) << "Source database is $ARTDAQ_DATABASE_URI = \t" << getenv("ARTDAQ_DATABASE_URI") << std::endl;
00514 (*out) << "\nOriginal location of dump: \t" << filePath << std::endl;
00515 (*out) << "Type of dump: \t" << dumpType << std::endl;
00516 (*out) << "Linux time for dump: \t" << rawtime << std::endl;
00517
00518 {
00519 struct tm * timeinfo = localtime (&rawtime);
00520 char buffer [100];
00521 strftime(buffer,100,"%c %Z",timeinfo);
00522 (*out) << "Display time for dump: \t" << buffer << std::endl;
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532 auto localDumpActiveGroups = [](const ConfigurationManager *cfgMgr, std::ostream *out) {
00533 std::map<std::string, std::pair<std::string, ConfigurationGroupKey>> activeGroups =
00534 cfgMgr->getActiveConfigurationGroups();
00535
00536 (*out) << "\n\n************************" << std::endl;
00537 (*out) << "Active Groups:" << std::endl;
00538 for(auto &group:activeGroups)
00539 {
00540 (*out) << "\t" << group.first << " := " <<
00541 group.second.first << " (" <<
00542 group.second.second << ")" << std::endl;
00543 }
00544 };
00545
00546 auto localDumpActiveTables = [](const ConfigurationManager *cfgMgr, std::ostream *out) {
00547 std::map<std::string, ConfigurationVersion> activeTables =
00548 cfgMgr->getActiveVersions();
00549
00550 (*out) << "\n\n************************" << std::endl;
00551 (*out) << "Active Tables:" << std::endl;
00552 (*out) << "Active Tables count = " << activeTables.size() << std::endl;
00553
00554 unsigned int i = 0;
00555 for(auto &table:activeTables)
00556 {
00557 (*out) << "\t" << ++i << ". " << table.first << "-v" <<
00558 table.second << std::endl;
00559 }
00560 };
00561
00562 auto localDumpActiveGroupMembers = [](const ConfigurationManager *cfgMgr, std::ostream *out) {
00563 std::map<std::string, std::pair<std::string, ConfigurationGroupKey>> activeGroups =
00564 cfgMgr->getActiveConfigurationGroups();
00565 (*out) << "\n\n************************" << std::endl;
00566 (*out) << "Active Group Members:" << std::endl;
00567 int tableCount = 0;
00568 for(auto &group:activeGroups)
00569 {
00570 (*out) << "\t" << group.first << " := " <<
00571 group.second.first << " (" <<
00572 group.second.second << ")" << std::endl;
00573
00574 std::map<std::string , ConfigurationVersion > memberMap =
00575 cfgMgr->theInterface_->getConfigurationGroupMembers(
00576 ConfigurationGroupKey::getFullGroupString(
00577 group.second.first,
00578 group.second.second));
00579
00580 (*out) << "\tMember table count = " << memberMap.size() << std::endl;
00581 tableCount += memberMap.size();
00582
00583 unsigned int i = 0;
00584 for(auto &member:memberMap)
00585 {
00586 (*out) << "\t\t" << ++i << ". " << member.first << "-v" <<
00587 member.second << std::endl;
00588 }
00589 }
00590 (*out) << "\nActive Group Members total table count = " << tableCount << std::endl;
00591 };
00592
00593 auto localDumpActiveTableContents = [](const ConfigurationManager *cfgMgr, std::ostream *out) {
00594 std::map<std::string, ConfigurationVersion> activeTables =
00595 cfgMgr->getActiveVersions();
00596
00597 (*out) << "\n\n************************" << std::endl;
00598 (*out) << "Active Table Contents (table count = " << activeTables.size()
00599 << "):" << std::endl;
00600 unsigned int i = 0;
00601 for(auto &table:activeTables)
00602 {
00603 (*out) << "\n\n==============================================================================" << std::endl;
00604 (*out) << "==============================================================================" << std::endl;
00605 (*out) << "\t" << ++i << ". " << table.first << "-v" <<
00606 table.second << std::endl;
00607
00608 cfgMgr->nameToConfigurationMap_.find(table.first)->second->print(*out);
00609 }
00610 };
00611
00612
00613
00614 if(dumpType == "GroupKeys")
00615 {
00616 localDumpActiveGroups(this,out);
00617 }
00618 else if(dumpType == "TableVersions")
00619 {
00620 localDumpActiveTables(this,out);
00621 }
00622 else if(dumpType == "GroupKeysAndTableVersions")
00623 {
00624 localDumpActiveGroups(this,out);
00625 localDumpActiveTables(this,out);
00626 }
00627 else if(dumpType == "All")
00628 {
00629 localDumpActiveGroups(this,out);
00630 localDumpActiveGroupMembers(this,out);
00631 localDumpActiveTables(this,out);
00632 localDumpActiveTableContents(this,out);
00633 }
00634 else
00635 {
00636 __SS__ << "Invalid dump type '" << dumpType <<
00637 "' given during dumpActiveConfiguration(). Valid types are as follows:\n" <<
00638
00639
00640 "GroupKeys" << ", " <<
00641 "TableVersions" << ", " <<
00642 "GroupsKeysAndTableVersions" << ", " <<
00643 "All" <<
00644
00645 "\n\nPlease change the State Machine configuration to a valid dump type." <<
00646 std::endl;
00647 throw std::runtime_error(ss.str());
00648 }
00649
00650 if(fs.is_open())
00651 fs.close();
00652 }
00653
00654
00655
00656
00657
00658 void ConfigurationManager::loadMemberMap(
00659 const std::map<std::string /*name*/, ConfigurationVersion /*version*/> &memberMap)
00660 {
00661 ConfigurationBase *tmpConfigBasePtr;
00662
00663
00664 for(auto &memberPair:memberMap)
00665 {
00666
00667
00668
00669
00670
00671
00672
00673
00674 tmpConfigBasePtr = 0;
00675 if(nameToConfigurationMap_.find(memberPair.first) != nameToConfigurationMap_.end())
00676 tmpConfigBasePtr = nameToConfigurationMap_[memberPair.first];
00677
00678 theInterface_->get(tmpConfigBasePtr,
00679 memberPair.first,
00680 0,
00681 0,
00682 false,
00683 memberPair.second,
00684 false
00685 );
00686
00687 nameToConfigurationMap_[memberPair.first] = tmpConfigBasePtr;
00688 if(nameToConfigurationMap_[memberPair.first]->getViewP())
00689 {
00690
00691 }
00692 else
00693 {
00694 __SS__ << nameToConfigurationMap_[memberPair.first]->getConfigurationName() <<
00695 ": View version not activated properly!";
00696 throw std::runtime_error(ss.str());
00697 }
00698 }
00699 }
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716 std::map<std::string, ConfigurationVersion> ConfigurationManager::loadConfigurationGroup(
00717 const std::string &configGroupName,
00718 ConfigurationGroupKey configGroupKey,
00719 bool doActivate,
00720 ProgressBar *progressBar,
00721 std::string *accumulatedTreeErrors,
00722 std::string *groupComment,
00723 std::string *groupAuthor,
00724 std::string *groupCreateTime,
00725 bool doNotLoadMember,
00726 std::string *groupTypeString)
00727 {
00728 if(accumulatedTreeErrors) *accumulatedTreeErrors = "";
00729 if(groupComment) *groupComment = "";
00730 if(groupAuthor) *groupAuthor = "";
00731 if(groupCreateTime) *groupCreateTime = "";
00732 if(groupTypeString) *groupTypeString = "";
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 __MOUT_INFO__ << "Loading Configuration Group: " << configGroupName <<
00747 "(" << configGroupKey << ")" << std::endl;
00748
00749 std::map<std::string , ConfigurationVersion > memberMap =
00750 theInterface_->getConfigurationGroupMembers(
00751 ConfigurationGroupKey::getFullGroupString(configGroupName,configGroupKey),
00752 true);
00753
00754
00755 if(progressBar) progressBar->step();
00756
00757
00758 auto metaTablePair = memberMap.find(groupMetadataTable_.getConfigurationName());
00759 if(metaTablePair !=
00760 memberMap.end())
00761 {
00762
00763
00764
00765 while(groupMetadataTable_.getView().getNumberOfRows())
00766 groupMetadataTable_.getViewP()->deleteRow(0);
00767 theInterface_->fill(&groupMetadataTable_,metaTablePair->second);
00768
00769 if(groupMetadataTable_.getView().getNumberOfRows() != 1)
00770 {
00771 groupMetadataTable_.print();
00772 __SS__ << "groupMetadataTable_ has wrong number of rows! Must be 1." << std::endl;
00773 __MOUT_ERR__ << "\n" << ss.str();
00774 throw std::runtime_error(ss.str());
00775 }
00776
00777
00778 memberMap.erase(metaTablePair);
00779
00780
00781 if(groupComment) *groupComment = groupMetadataTable_.getView().getValueAsString(0,1);
00782 if(groupAuthor) *groupAuthor = groupMetadataTable_.getView().getValueAsString(0,2);
00783 if(groupCreateTime) *groupCreateTime = groupMetadataTable_.getView().getValueAsString(0,3);
00784 }
00785
00786 if(progressBar) progressBar->step();
00787
00788
00789
00790 if(doNotLoadMember) return memberMap;
00791
00792 int groupType = -1;
00793
00794
00795 groupType = getTypeOfGroup(memberMap);
00796 if(groupTypeString) *groupTypeString = convertGroupTypeIdToName(groupType);
00797
00798 if(doActivate)
00799 {
00800 std::string groupToDeactivate =
00801 groupType==CONTEXT_TYPE?theContextGroup_:
00802 (groupType==BACKBONE_TYPE?theBackboneGroup_:theConfigurationGroup_);
00803
00804
00805 if(groupToDeactivate != "")
00806 {
00807 __MOUT__ << "groupToDeactivate '" << groupToDeactivate << "'" << std::endl;
00808 destroyConfigurationGroup(groupToDeactivate,true);
00809 }
00810
00811
00812
00813
00814
00815 }
00816
00817 if(progressBar) progressBar->step();
00818
00819
00820
00821
00822 loadMemberMap(memberMap);
00823
00824 if(progressBar) progressBar->step();
00825
00826 if(accumulatedTreeErrors)
00827 {
00828 __MOUT__ << "Checking chosen group for tree errors..." << std::endl;
00829
00830 getChildren(&memberMap, accumulatedTreeErrors);
00831 if(*accumulatedTreeErrors != "")
00832 {
00833 __MOUT_ERR__ << "Errors detected while loading Configuration Group: " << configGroupName <<
00834 "(" << configGroupKey << "). Aborting." << std::endl;
00835 return memberMap;
00836 }
00837 }
00838
00839 if(progressBar) progressBar->step();
00840
00841
00842
00843 if(doActivate)
00844 for(auto &memberPair:memberMap)
00845 {
00846
00847 if(ConfigurationInterface::isVersionTrackingEnabled() &&
00848 memberPair.second.isScratchVersion())
00849 {
00850 __SS__ << "Error while activating member Table '" <<
00851 nameToConfigurationMap_[memberPair.first]->getConfigurationName() <<
00852 "-v" << memberPair.second <<
00853 " for Configuration Group '" << configGroupName <<
00854 "(" << configGroupKey << ")'. When version tracking is enabled, Scratch views" <<
00855 " are not allowed! Please only use unique, persistent versions when version tracking is enabled."
00856 << std::endl;
00857 __MOUT_ERR__ << "\n" << ss.str();
00858 throw std::runtime_error(ss.str());
00859 }
00860
00861
00862
00863
00864 try
00865 {
00866 nameToConfigurationMap_[memberPair.first]->init(this);
00867 }
00868 catch(std::runtime_error& e)
00869 {
00870 __SS__ << "Error detected calling " <<
00871 nameToConfigurationMap_[memberPair.first]->getConfigurationName() <<
00872 ".init()!\n\n " << e.what() << std::endl;
00873 throw std::runtime_error(ss.str());
00874 }
00875 catch(...)
00876 {
00877 __SS__ << "Error detected calling " <<
00878 nameToConfigurationMap_[memberPair.first]->getConfigurationName() <<
00879 ".init()!\n\n " << std::endl;
00880 throw std::runtime_error(ss.str());
00881 }
00882
00883 }
00884
00885 if(progressBar) progressBar->step();
00886
00887
00888
00889
00890
00891 if(doActivate)
00892 {
00893 if(groupType == CONTEXT_TYPE)
00894 {
00895 __MOUT_INFO__ << "Context Configuration Group loaded: " << configGroupName <<
00896 "(" << configGroupKey << ")" << std::endl;
00897 theContextGroup_ = configGroupName;
00898 theContextGroupKey_ = std::shared_ptr<ConfigurationGroupKey>(new ConfigurationGroupKey(configGroupKey));
00899 }
00900 else if(groupType == BACKBONE_TYPE)
00901 {
00902 __MOUT_INFO__ << "Backbone Configuration Group loaded: " << configGroupName <<
00903 "(" << configGroupKey << ")" << std::endl;
00904 theBackboneGroup_ = configGroupName;
00905 theBackboneGroupKey_ = std::shared_ptr<ConfigurationGroupKey>(new ConfigurationGroupKey(configGroupKey));
00906 }
00907 else
00908 {
00909 __MOUT_INFO__ << "The Configuration Group loaded: " << configGroupName <<
00910 "(" << configGroupKey << ")" << std::endl;
00911 theConfigurationGroup_ = configGroupName;
00912 theConfigurationGroupKey_ = std::shared_ptr<ConfigurationGroupKey>(new ConfigurationGroupKey(configGroupKey));
00913 }
00914 }
00915
00916 if(progressBar) progressBar->step();
00917
00918 return memberMap;
00919 }
00920
00921
00922
00923
00924
00925
00926
00927
00928 std::map<std::string, std::pair<std::string, ConfigurationGroupKey> > ConfigurationManager::getActiveConfigurationGroups(void) const
00929 {
00930
00931 std::map<std::string, std::pair<std::string, ConfigurationGroupKey> > retMap;
00932
00933 retMap[ConfigurationManager::ACTIVE_GROUP_NAME_CONTEXT] =
00934 std::pair<std::string,ConfigurationGroupKey>(theContextGroup_ ,theContextGroupKey_ ?*theContextGroupKey_ : ConfigurationGroupKey());
00935 retMap[ConfigurationManager::ACTIVE_GROUP_NAME_BACKBONE] =
00936 std::pair<std::string,ConfigurationGroupKey>(theBackboneGroup_ ,theBackboneGroupKey_ ?*theBackboneGroupKey_ : ConfigurationGroupKey());
00937 retMap[ConfigurationManager::ACTIVE_GROUP_NAME_CONFIGURATION] =
00938 std::pair<std::string,ConfigurationGroupKey>(theConfigurationGroup_,theConfigurationGroupKey_?*theConfigurationGroupKey_: ConfigurationGroupKey());
00939 return retMap;
00940 }
00941
00942
00943 ConfigurationTree ConfigurationManager::getSupervisorConfigurationNode(
00944 const std::string &contextUID, const std::string &applicationUID) const
00945 {
00946 return getNode(
00947 "/" + getConfigurationByName(XDAQ_CONTEXT_CONFIG_NAME)->getConfigurationName() +
00948 "/" + contextUID +
00949 "/LinkToApplicationConfiguration/" + applicationUID +
00950 "/LinkToSupervisorConfiguration");
00951 }
00952
00953
00954 ConfigurationTree ConfigurationManager::getNode(const std::string& nodeString,
00955 bool doNotThrowOnBrokenUIDLinks) const
00956 {
00957
00958
00959
00960 if(nodeString.length() < 1) throw std::runtime_error("Invalid empty node name");
00961
00962 bool startingSlash = (nodeString[0] == '/');
00963
00964 std::string nodeName = nodeString.substr(startingSlash?1:0, nodeString.find('/',1)-(startingSlash?1:0));
00965
00966 if(nodeName.length() < 1) throw std::runtime_error("Invalid node name: " + nodeName);
00967
00968 std::string childPath = nodeString.substr(nodeName.length() + (startingSlash?1:0));
00969
00970
00971
00972 ConfigurationTree configTree(this, getConfigurationByName(nodeName));
00973
00974 if(childPath.length() > 1)
00975 return configTree.getNode(childPath,doNotThrowOnBrokenUIDLinks);
00976 else
00977 return configTree;
00978 }
00979
00980
00981
00982 std::string ConfigurationManager::getFirstPathToNode(const ConfigurationTree &node, const std::string &startPath) const
00983
00984 {
00985 std::string path = "/";
00986 return path;
00987 }
00988
00989
00990
00991
00992
00993
00994
00995 std::vector<std::pair<std::string,ConfigurationTree> > ConfigurationManager::getChildren(
00996 std::map<std::string, ConfigurationVersion> *memberMap,
00997 std::string *accumulatedTreeErrors) const
00998 {
00999 std::vector<std::pair<std::string,ConfigurationTree> > retMap;
01000 if(accumulatedTreeErrors) *accumulatedTreeErrors = "";
01001
01002 if(!memberMap || memberMap->empty())
01003 {
01004 for(auto &configPair:nameToConfigurationMap_)
01005 {
01006
01007
01008 if(configPair.second->isActive())
01009 {
01010 ConfigurationTree newNode(this, configPair.second);
01011
01012
01013 if(accumulatedTreeErrors)
01014 {
01015 try
01016 {
01017 std::vector<std::pair<std::string,ConfigurationTree> > newNodeChildren =
01018 newNode.getChildren();
01019 for(auto &newNodeChild: newNodeChildren)
01020 {
01021 std::vector<std::pair<std::string,ConfigurationTree> > twoDeepChildren =
01022 newNodeChild.second.getChildren();
01023
01024 for(auto &twoDeepChild: twoDeepChildren)
01025 {
01026
01027
01028 if(twoDeepChild.second.isLinkNode() &&
01029 twoDeepChild.second.isDisconnected() &&
01030 twoDeepChild.second.getDisconnectedTableName() !=
01031 ViewColumnInfo::DATATYPE_LINK_DEFAULT)
01032 *accumulatedTreeErrors += "\n\nAt node '" +
01033 configPair.first + "' with entry UID '" +
01034 newNodeChild.first + "' there is a disconnected child node at link column '" +
01035 twoDeepChild.first + "'" +
01036 " that points to table named '" +
01037 twoDeepChild.second.getDisconnectedTableName() +
01038 "' ...";
01039 }
01040 }
01041 }
01042 catch(std::runtime_error &e)
01043 {
01044 *accumulatedTreeErrors += "\n\nAt node '" +
01045 configPair.first + "' error detected descending through children:\n" +
01046 e.what();
01047 }
01048 }
01049
01050 retMap.push_back(std::pair<std::string,ConfigurationTree>(configPair.first,
01051 newNode));
01052 }
01053
01054
01055 }
01056 }
01057 else
01058 {
01059
01060 for(auto &memberPair: *memberMap)
01061 {
01062 auto mapIt = nameToConfigurationMap_.find(memberPair.first);
01063 if(mapIt == nameToConfigurationMap_.end())
01064 {
01065 __SS__ << "Get Children with member map requires a child '" <<
01066 memberPair.first << "' that is not present!" << std::endl;
01067 throw std::runtime_error(ss.str());
01068 }
01069 if(!(*mapIt).second->isActive())
01070 {
01071 __SS__ << "Get Children with member map requires a child '" <<
01072 memberPair.first << "' that is not active!" << std::endl;
01073 throw std::runtime_error(ss.str());
01074 }
01075
01076 ConfigurationTree newNode(this, (*mapIt).second);
01077
01078 if(accumulatedTreeErrors)
01079 {
01080 try
01081 {
01082 std::vector<std::pair<std::string,ConfigurationTree> > newNodeChildren =
01083 newNode.getChildren();
01084 for(auto &newNodeChild: newNodeChildren)
01085 {
01086 std::vector<std::pair<std::string,ConfigurationTree> > twoDeepChildren =
01087 newNodeChild.second.getChildren();
01088
01089 for(auto &twoDeepChild: twoDeepChildren)
01090 {
01091
01092
01093 if(twoDeepChild.second.isLinkNode() &&
01094 twoDeepChild.second.isDisconnected() &&
01095 twoDeepChild.second.getDisconnectedTableName() !=
01096 ViewColumnInfo::DATATYPE_LINK_DEFAULT)
01097 {
01098 *accumulatedTreeErrors += "\n\nAt node '" +
01099 memberPair.first + "' with entry UID '" +
01100 newNodeChild.first + "' there is a disconnected child node at link column '" +
01101 twoDeepChild.first + "'" +
01102 " that points to table named '" +
01103 twoDeepChild.second.getDisconnectedTableName() +
01104 "' ...";
01105
01106
01107
01108 bool found = false;
01109 for(auto &searchMemberPair: *memberMap)
01110 if(searchMemberPair.first ==
01111 twoDeepChild.second.getDisconnectedTableName())
01112 { found = true; break;}
01113 if(!found)
01114 *accumulatedTreeErrors +=
01115 std::string("\nNote: It may be safe to ignore this error ") +
01116 "since the link's target table " +
01117 twoDeepChild.second.getDisconnectedTableName() +
01118 " is not a member of this group (and may not be loaded yet).";
01119 }
01120 }
01121 }
01122 }
01123 catch(std::runtime_error &e)
01124 {
01125 *accumulatedTreeErrors += "\n\nAt node '" +
01126 memberPair.first + "' error detected descending through children:\n" +
01127 e.what();
01128 }
01129 }
01130
01131 retMap.push_back(std::pair<std::string,ConfigurationTree>(memberPair.first,
01132 newNode));
01133 }
01134 }
01135
01136 return retMap;
01137 }
01138
01139
01140
01141
01142
01143
01144 const ConfigurationBase* ConfigurationManager::getConfigurationByName(const std::string &configurationName) const
01145 {
01146 std::map<std::string, ConfigurationBase*>::const_iterator it;
01147 if((it = nameToConfigurationMap_.find(configurationName)) == nameToConfigurationMap_.end())
01148 {
01149 __SS__ << "\n\nCan not find configuration named '" <<
01150 configurationName <<
01151 "'\n\n\n\nYou need to load the configuration before it can be used." <<
01152 " It probably is missing from the member list of the Configuration Group that was loaded.\n" <<
01153 "\nYou may need to enter wiz mode to remedy the situation, use the following:\n" <<
01154 "\n\t StartOTS.sh --wiz" <<
01155 "\n\n\n\n"
01156 << std::endl;
01157
01158
01159
01160 throw std::runtime_error(ss.str());
01161 }
01162 return it->second;
01163 }
01164
01165
01166
01167
01168
01169 ConfigurationGroupKey ConfigurationManager::loadConfigurationBackbone()
01170 {
01171 if(!theBackboneGroupKey_)
01172 {
01173 __MOUT_WARN__ << "getConfigurationGroupKey() Failed! No active backbone currently." << std::endl;
01174 return ConfigurationGroupKey();
01175 }
01176
01177
01178 loadConfigurationGroup(theBackboneGroup_,*theBackboneGroupKey_);
01179
01180 return *theBackboneGroupKey_;
01181 }
01182
01183
01184
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219 std::pair<std::string, ConfigurationGroupKey> ConfigurationManager::getConfigurationGroupFromAlias(std::string runType, ProgressBar* progressBar)
01220 {
01221
01222
01223
01224
01225
01226 if(progressBar) progressBar->step();
01227
01228 loadConfigurationBackbone();
01229
01230 if(progressBar) progressBar->step();
01231
01232 try
01233 {
01234
01235 ConfigurationTree entry = getNode("GroupAliasesConfiguration").getNode(runType);
01236 return std::pair<std::string, ConfigurationGroupKey>(entry.getNode("GroupName").getValueAsString(), ConfigurationGroupKey(entry.getNode("GroupKey").getValueAsString()));
01237 }
01238 catch(...)
01239 {}
01240
01241 if(progressBar) progressBar->step();
01242
01243 return std::pair<std::string, ConfigurationGroupKey>("",ConfigurationGroupKey());
01244 }
01245
01246
01247
01248 std::map<std::string, std::pair<std::string, ConfigurationGroupKey> > ConfigurationManager::getGroupAliasesConfiguration(void)
01249 {
01250 restoreActiveConfigurationGroups();
01251
01252
01253 std::map<std::string ,
01254 std::pair<std::string , ConfigurationGroupKey> > retMap;
01255
01256 std::vector<std::pair<std::string,ConfigurationTree> > entries = getNode("GroupAliasesConfiguration").getChildren();
01257 for(auto &entryPair: entries)
01258 {
01259 retMap[entryPair.first] = std::pair<std::string, ConfigurationGroupKey>(
01260 entryPair.second.getNode("GroupName").getValueAsString(),
01261 ConfigurationGroupKey(entryPair.second.getNode("GroupKey").getValueAsString()));
01262
01263 }
01264 return retMap;
01265 }
01266
01267
01268
01269 std::map<std::string, ConfigurationVersion> ConfigurationManager::getActiveVersions(void) const
01270 {
01271 std::map<std::string, ConfigurationVersion> retMap;
01272 for(auto &config:nameToConfigurationMap_)
01273 {
01274
01275
01276
01277 if(config.second && config.second->isActive())
01278 {
01279
01280 retMap.insert(std::pair<std::string, ConfigurationVersion>(config.first, config.second->getViewVersion()));
01281 }
01282 }
01283 return retMap;
01284 }
01285
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308 std::shared_ptr<ConfigurationGroupKey> ConfigurationManager::makeTheConfigurationGroupKey(ConfigurationGroupKey key)
01309 {
01310 if(theConfigurationGroupKey_)
01311 {
01312 if(*theConfigurationGroupKey_ != key)
01313 destroyConfigurationGroup();
01314 else
01315 return theConfigurationGroupKey_;
01316 }
01317 return std::shared_ptr<ConfigurationGroupKey>(new ConfigurationGroupKey(key));
01318 }
01319
01320
01321 std::string ConfigurationManager::encodeURIComponent(const std::string &sourceStr)
01322 {
01323 std::string retStr = "";
01324 char encodeStr[4];
01325 for(const auto &c:sourceStr)
01326 if(
01327 (c >= 'a' && c <= 'z') ||
01328 (c >= 'A' && c <= 'Z') ||
01329 (c >= '0' && c <= '9') )
01330 retStr += c;
01331 else
01332 {
01333 sprintf(encodeStr,"%%%2.2X",c);
01334 retStr += encodeStr;
01335 }
01336 return retStr;
01337 }
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347