1 #include "otsdaq-utilities/ConfigurationGUI/ConfigurationGUISupervisor.h"
3 #include "otsdaq/CgiDataUtilities/CgiDataUtilities.h"
4 #include "otsdaq/Macros/CoutMacros.h"
5 #include "otsdaq/MessageFacility/MessageFacility.h"
6 #include "otsdaq/TablePlugins/IterateTable.h"
7 #include "otsdaq/XmlUtilities/HttpXmlDocument.h"
9 #include <boost/stacktrace.hpp>
11 #include "otsdaq/GatewaySupervisor/GatewaySupervisor.h"
12 #include "otsdaq/TablePlugins/ARTDAQTableBase/ARTDAQTableBase.h"
13 #include "otsdaq/TablePlugins/XDAQContextTable/XDAQContextTable.h"
15 #include <xdaq/NamespaceURI.h>
25 #define __MF_SUBJECT__ "CfgGUI"
27 #define TABLE_INFO_PATH std::string(__ENV__("TABLE_INFO_PATH")) + "/"
28 #define TABLE_INFO_EXT std::string("Info.xml")
44 __SUP_COUT__ <<
"Constructor started." << __E__;
49 mkdir(((std::string)ARTDAQTableBase::ARTDAQ_CONFIG_LAYOUTS_PATH).c_str(), 0755);
52 __SUP_COUT__ <<
"Constructor complete." << __E__;
56 ConfigurationGUISupervisor::~ConfigurationGUISupervisor(
void) { destroy(); }
59 void ConfigurationGUISupervisor::init(
void)
61 __SUP_COUT__ <<
"Initializing..." << __E__;
65 __SUP_COUT__ <<
"Activating saved context, which may prepare for normal mode..."
70 __SUP_COUT__ <<
"Done with test context." << __E__;
74 __COUT_WARN__ <<
"Failed test context group activation. otsdaq, in Normal mode, "
75 "will not launch when this test fails. "
76 <<
"Check the active context group from within Wizard Mode."
81 refreshUserSession(
"" , 1);
84 if(CorePropertySupervisorBase::allSupervisorInfo_.isWizardMode())
87 <<
"After successful Config GUI init, marking alive for wiz mode!" << __E__;
88 CorePropertySupervisorBase::
94 void ConfigurationGUISupervisor::destroy(
void)
96 __SUP_COUT__ <<
"Destructing..." << __E__;
99 for(std::map<std::string, ConfigurationManagerRW*>::iterator it =
100 userConfigurationManagers_.begin();
101 it != userConfigurationManagers_.end();
107 userConfigurationManagers_.clear();
109 if(ConfigurationInterface::getInstance() !=
nullptr)
110 delete ConfigurationInterface::getInstance();
115 void ConfigurationGUISupervisor::defaultPage(xgi::Input* in, xgi::Output* out)
117 cgicc::Cgicc cgiIn(in);
118 std::string configWindowName =
120 if(configWindowName ==
"tableEditor")
121 *out <<
"<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame "
122 "src='/WebPath/html/ConfigurationTableEditor.html?urn="
123 << this->getApplicationDescriptor()->getLocalId() <<
"'></frameset></html>";
124 if(configWindowName ==
"iterate")
125 *out <<
"<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame "
126 "src='/WebPath/html/Iterate.html?urn="
127 << this->getApplicationDescriptor()->getLocalId() <<
"'></frameset></html>";
129 *out <<
"<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame "
130 "src='/WebPath/html/ConfigurationGUI.html?urn="
131 << this->getApplicationDescriptor()->getLocalId() <<
"'></frameset></html>";
139 CorePropertySupervisorBase::setSupervisorProperty(
140 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold,
141 "*=10 | deleteTreeNodeRecords=255 | saveTableInfo=255 | "
142 "deleteTableInfo=255");
144 CorePropertySupervisorBase::setSupervisorProperty(
145 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.RequireUserLockRequestTypes,
149 CorePropertySupervisorBase::setSupervisorProperty(
150 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
"get*");
158 CorePropertySupervisorBase::addSupervisorProperty(
159 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
160 "getActiveTableGroups");
163 CorePropertySupervisorBase::setSupervisorProperty(
164 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.CheckUserLockRequestTypes,
169 void ConfigurationGUISupervisor::request(
const std::string& requestType,
172 const WebUsers::RequestUserInfo& userInfo)
177 __COUTTV__(requestType);
250 refreshUserSession(userInfo.username_, (refresh ==
"1"));
251 __COUTTV__(userInfo.username_);
257 const std::set<TableGroupKey>& sortedKeys = groupInfo.getKeys();
258 __COUTTV__(sortedKeys.size());
261 if(requestType ==
"saveTableInfo")
263 std::string tableName =
265 std::string columnCSV =
267 std::string allowOverwrite =
269 std::string tableDescription =
271 std::string columnChoicesCSV =
274 __SUP_COUT__ <<
"tableName: " << tableName << __E__;
275 __SUP_COUT__ <<
"columnCSV: " << columnCSV << __E__;
276 __SUP_COUT__ <<
"tableDescription: " << tableDescription << __E__;
277 __SUP_COUT__ <<
"columnChoicesCSV: " << columnChoicesCSV << __E__;
278 __SUP_COUT__ <<
"allowOverwrite: " << allowOverwrite << __E__;
280 if(!allSupervisorInfo_.isWizardMode())
282 __SUP_SS__ <<
"Improper permissions for saving table info." << __E__;
283 xmlOut.addTextElementToData(
"Error", ss.str());
286 handleSaveTableInfoXML(xmlOut,
292 allowOverwrite ==
"1");
294 else if(requestType ==
"deleteTableInfo")
296 std::string tableName =
298 __SUP_COUT__ <<
"tableName: " << tableName << __E__;
299 handleDeleteTableInfoXML(xmlOut, cfgMgr, tableName);
301 else if(requestType ==
"gatewayLaunchOTS" || requestType ==
"gatewayLaunchWiz" ||
302 requestType ==
"flattenToSystemAliases")
305 __SUP_COUT_WARN__ << requestType <<
" command received! " << __E__;
306 __COUT_WARN__ << requestType <<
" command received! " << __E__;
309 __SUP_COUT_INFO__ <<
"Launching " << requestType <<
"... " << __E__;
311 __SUP_COUT__ <<
"Extracting target context hostnames... " << __E__;
312 std::vector<std::string> hostnames;
315 if(requestType ==
"flattenToSystemAliases" &&
316 CorePropertySupervisorBase::allSupervisorInfo_.isWizardMode())
318 hostnames.push_back(__ENV__(
"OTS_CONFIGURATION_WIZARD_SUPERVISOR_SERVER"));
319 __SUP_COUT__ <<
"hostname = " << hostnames.back() << __E__;
330 auto contexts = contextTable->getContexts();
332 for(
const auto& context : contexts)
339 for(i = 0; i < context.address_.size(); ++i)
340 if(context.address_[i] ==
'/')
342 hostnames.push_back(context.address_.substr(j));
343 __SUP_COUT__ <<
"hostname = " << hostnames.back() << __E__;
348 __SUP_SS__ <<
"The Configuration Manager could not be initialized to "
355 catch(
const std::exception& e)
357 ss <<
"Exception message: " << e.what();
363 __SUP_COUT_ERR__ <<
"\n" << ss.str();
368 if(hostnames.size() == 0)
370 __SUP_SS__ <<
"No hostnames found to launch command '" + requestType +
371 "'... Is there a valid Context group activated?"
373 __SUP_COUT_ERR__ <<
"\n" << ss.str();
375 xmlOut.addTextElementToData(
"Error", ss.str());
378 for(
const auto& hostname : hostnames)
380 std::string fn = (std::string(__ENV__(
"SERVICE_DATA_PATH")) +
381 "/StartOTS_action_" + hostname +
".cmd");
382 FILE* fp = fopen(fn.c_str(),
"w");
385 if(requestType ==
"gatewayLaunchOTS")
386 fprintf(fp,
"LAUNCH_OTS");
387 else if(requestType ==
"gatewayLaunchWiz")
388 fprintf(fp,
"LAUNCH_WIZ");
389 else if(requestType ==
"flattenToSystemAliases")
391 fprintf(fp,
"FLATTEN_TO_SYSTEM_ALIASES");
399 __SUP_COUT_ERR__ <<
"Unable to open command file: " << fn << __E__;
402 else if(requestType ==
"versionTracking" || requestType ==
"getVersionTracking")
405 if(requestType ==
"getVersionTracking")
409 __SUP_COUT__ <<
"type: " << type << __E__;
412 xmlOut.addTextElementToData(
413 "versionTrackingStatus",
414 ConfigurationInterface::isVersionTrackingEnabled() ?
"ON" :
"OFF");
415 else if(type ==
"ON")
417 ConfigurationInterface::setVersionTrackingEnabled(
true);
418 xmlOut.addTextElementToData(
419 "versionTrackingStatus",
420 ConfigurationInterface::isVersionTrackingEnabled() ?
"ON" :
"OFF");
422 else if(type ==
"OFF")
424 ConfigurationInterface::setVersionTrackingEnabled(
false);
425 xmlOut.addTextElementToData(
426 "versionTrackingStatus",
427 ConfigurationInterface::isVersionTrackingEnabled() ?
"ON" :
"OFF");
430 else if(requestType ==
"getColumnTypes")
433 std::vector<std::string> allTypes = TableViewColumnInfo::getAllTypesForGUI();
434 std::vector<std::string> allDataTypes =
435 TableViewColumnInfo::getAllDataTypesForGUI();
436 std::map<std::pair<std::string, std::string>, std::string> allDefaults =
439 for(
const auto& type : allTypes)
440 xmlOut.addTextElementToData(
"columnTypeForGUI", type);
441 for(
const auto& dataType : allDataTypes)
442 xmlOut.addTextElementToData(
"columnDataTypeForGUI", dataType);
444 for(
const auto& colDefault : allDefaults)
446 xmlOut.addTextElementToData(
"columnDefaultDataType", colDefault.first.first);
447 xmlOut.addTextElementToData(
"columnDefaultTypeFilter",
448 colDefault.first.second);
449 xmlOut.addTextElementToData(
"columnDefaultValue", colDefault.second);
453 else if(requestType ==
"getGroupAliases")
458 1 == CgiDataUtilities::getDataAsInt(cgiIn,
"reloadActiveGroups");
460 __SUP_COUT__ <<
"reloadActive: " << reloadActive << __E__;
468 catch(std::runtime_error& e)
470 __SUP_SS__ << (
"Error loading active groups!\n\n" + std::string(e.what()))
472 __SUP_COUT_ERR__ <<
"\n" << ss.str();
473 xmlOut.addTextElementToData(
"Error", ss.str());
477 __SUP_SS__ << (
"Error loading active groups!\n\n") << __E__;
482 catch(
const std::exception& e)
484 ss <<
"Exception message: " << e.what();
489 __SUP_COUT_ERR__ <<
"\n" << ss.str();
490 xmlOut.addTextElementToData(
"Error", ss.str());
494 handleGroupAliasesXML(xmlOut, cfgMgr);
496 else if(requestType ==
"setGroupAliasInActiveBackbone")
498 std::string groupAliasCSV =
500 std::string groupNameCSV =
502 std::string groupKeyCSV =
505 __SUP_COUTV__(groupAliasCSV);
506 __SUP_COUTV__(groupNameCSV);
507 __SUP_COUTV__(groupKeyCSV);
509 handleSetGroupAliasInBackboneXML(
510 xmlOut, cfgMgr, groupAliasCSV, groupNameCSV, groupKeyCSV, userInfo.username_);
512 else if(requestType ==
"setTableAliasInActiveBackbone")
514 std::string tableAlias =
516 std::string tableName =
520 __SUP_COUT__ <<
"tableAlias: " << tableAlias << __E__;
521 __SUP_COUT__ <<
"tableName: " << tableName << __E__;
522 __SUP_COUT__ <<
"version: " << version << __E__;
524 handleSetTableAliasInBackboneXML(xmlOut,
531 else if(requestType ==
"setAliasOfGroupMembers")
533 std::string versionAlias =
535 std::string groupName =
539 __SUP_COUT__ <<
"versionAlias: " << versionAlias << __E__;
540 __SUP_COUT__ <<
"groupName: " << groupName << __E__;
541 __SUP_COUT__ <<
"groupKey: " << groupKey << __E__;
543 handleAliasGroupMembersInBackboneXML(xmlOut,
550 else if(requestType ==
"getVersionAliases")
552 handleVersionAliasesXML(xmlOut, cfgMgr);
554 else if(requestType ==
"getTableGroups")
556 bool doNotReturnMembers =
557 CgiDataUtilities::getDataAsInt(cgiIn,
"doNotReturnMembers") == 1
561 __SUP_COUT__ <<
"doNotReturnMembers: " << doNotReturnMembers << __E__;
562 handleTableGroupsXML(xmlOut, cfgMgr, !doNotReturnMembers);
564 else if(requestType ==
"getTableGroupType")
566 std::string tableList =
568 __SUP_COUT__ <<
"tableList: " << tableList << __E__;
570 handleGetTableGroupTypeXML(xmlOut, cfgMgr, tableList);
572 else if(requestType ==
"getTables")
578 filterMode =
"created";
579 __COUT__ <<
"startTime: " << filterStartTime << __E__;
580 __COUT__ <<
"endTime: " << filterEndTime << __E__;
581 __COUT__ <<
"filterMode: " << filterMode << __E__;
583 handleTablesXML(xmlOut, cfgMgr, filterStartTime, filterEndTime, filterMode);
585 else if(requestType ==
"getContextMemberNames")
587 std::set<std::string> members = cfgMgr->getFixedContextMemberNames();
589 for(
auto& member : members)
590 xmlOut.addTextElementToData(
"ContextMember", member);
592 else if(requestType ==
"getBackboneMemberNames")
594 std::set<std::string> members = cfgMgr->getBackboneMemberNames();
596 for(
auto& member : members)
597 xmlOut.addTextElementToData(
"BackboneMember", member);
599 else if(requestType ==
"getIterateMemberNames")
601 std::set<std::string> members = cfgMgr->getIterateMemberNames();
603 for(
auto& member : members)
604 xmlOut.addTextElementToData(
"IterateMember", member);
606 else if(requestType ==
"getSpecificTableGroup")
608 std::string groupName =
612 __SUP_COUT__ <<
"groupName: " << groupName << __E__;
613 __SUP_COUT__ <<
"groupKey: " << groupKey << __E__;
618 else if(requestType ==
"saveNewTableGroup")
620 std::string groupName =
622 bool ignoreWarnings =
623 CgiDataUtilities::getDataAsInt(cgiIn,
"ignoreWarnings");
624 bool allowDuplicates =
625 CgiDataUtilities::getDataAsInt(cgiIn,
"allowDuplicates");
626 bool lookForEquivalent =
627 CgiDataUtilities::getDataAsInt(cgiIn,
"lookForEquivalent");
628 std::string tableList =
630 std::string comment =
633 __SUP_COUT__ <<
"saveNewTableGroup: " << groupName << __E__;
634 __SUP_COUT__ <<
"tableList: " << tableList << __E__;
635 __SUP_COUT__ <<
"ignoreWarnings: " << ignoreWarnings << __E__;
636 __SUP_COUT__ <<
"allowDuplicates: " << allowDuplicates << __E__;
637 __SUP_COUT__ <<
"lookForEquivalent: " << lookForEquivalent << __E__;
638 __SUP_COUT__ <<
"comment: " << comment << __E__;
649 else if(requestType ==
"getSpecificTable")
651 std::string tableName =
654 int dataOffset = CgiDataUtilities::getDataAsInt(cgiIn,
"dataOffset");
655 int chunkSize = CgiDataUtilities::getDataAsInt(
658 bool descriptionOnly = CgiDataUtilities::getDataAsInt(
659 cgiIn,
"descriptionOnly");
660 bool allowIllegalColumns =
661 CgiDataUtilities::getDataAsInt(cgiIn,
"allowIllegalColumns");
662 bool rawData = CgiDataUtilities::getDataAsInt(cgiIn,
"rawData");
664 __SUP_COUT__ <<
"getSpecificTable: " << tableName <<
" versionStr: " << versionStr
665 <<
" chunkSize: " << chunkSize <<
" dataOffset: " << dataOffset
666 <<
" descriptionOnly: " << descriptionOnly
667 <<
" allowIllegalColumns: " << allowIllegalColumns
668 <<
" rawData: " << rawData << __E__;
671 const std::map<std::string, TableInfo>& allTableInfo = cfgMgr->
getAllTableInfo();
673 if(allTableInfo.find(tableName) != allTableInfo.end())
675 if(versionStr ==
"" &&
676 allTableInfo.at(tableName).versions_.size())
679 auto it = allTableInfo.at(tableName).versions_.rbegin();
680 if(it->isScratchVersion())
684 else if(versionStr.find(ConfigurationManager::ALIAS_VERSION_PREAMBLE) == 0)
687 std::map<std::string ,
691 std::string versionAlias;
692 versionAlias = versionStr.substr(
693 ConfigurationManager::ALIAS_VERSION_PREAMBLE.size());
704 if(versionAliases.find(tableName) != versionAliases.end() &&
705 versionAliases[tableName].find(versionAlias) !=
706 versionAliases[tableName].end())
708 version = versionAliases[tableName][versionAlias];
709 __SUP_COUT__ <<
"version alias translated to: " << version << __E__;
714 << versionStr.substr(
715 ConfigurationManager::ALIAS_VERSION_PREAMBLE.size())
716 <<
"'was not found in active version aliases!" << __E__;
719 version = atoi(versionStr.c_str());
722 __SUP_COUT__ <<
"version: " << version << __E__;
724 handleGetTableXML(xmlOut,
732 xmlOut.addTextElementToData(
"DefaultRowValue", userInfo.username_);
734 else if(requestType ==
"saveSpecificTable")
736 std::string tableName =
738 int version = CgiDataUtilities::getDataAsInt(cgiIn,
"version");
739 int dataOffset = CgiDataUtilities::getDataAsInt(cgiIn,
"dataOffset");
740 bool sourceTableAsIs =
741 CgiDataUtilities::getDataAsInt(cgiIn,
"sourceTableAsIs");
742 bool lookForEquivalent =
743 CgiDataUtilities::getDataAsInt(cgiIn,
"lookForEquivalent");
744 int temporary = CgiDataUtilities::getDataAsInt(cgiIn,
"temporary");
745 std::string comment =
752 __SUP_COUT__ <<
"tableName: " << tableName <<
" version: " << version
753 <<
" temporary: " << temporary <<
" dataOffset: " << dataOffset
755 __SUP_COUT__ <<
"comment: " << comment << __E__;
756 __SUP_COUT__ <<
"data: " << data << __E__;
757 __SUP_COUT__ <<
"sourceTableAsIs: " << sourceTableAsIs << __E__;
758 __SUP_COUT__ <<
"lookForEquivalent: " << lookForEquivalent << __E__;
772 else if(requestType ==
"clearTableTemporaryVersions")
774 std::string tableName =
776 __SUP_COUT__ <<
"tableName: " << tableName << __E__;
782 catch(std::runtime_error& e)
784 __SUP_COUT__ <<
"Error detected!\n\n " << e.what() << __E__;
785 xmlOut.addTextElementToData(
786 "Error",
"Error clearing temporary views!\n " + std::string(e.what()));
790 __SUP_COUT__ <<
"Error detected!\n\n " << __E__;
791 xmlOut.addTextElementToData(
"Error",
"Error clearing temporary views! ");
794 else if(requestType ==
"clearTableCachedVersions")
796 std::string tableName =
798 __SUP_COUT__ <<
"tableName: " << tableName << __E__;
809 catch(std::runtime_error& e)
811 __SUP_COUT__ <<
"Error detected!\n\n " << e.what() << __E__;
812 xmlOut.addTextElementToData(
813 "Error",
"Error clearing cached views!\n " + std::string(e.what()));
817 __SUP_COUT__ <<
"Error detected!\n\n " << __E__;
818 xmlOut.addTextElementToData(
"Error",
"Error clearing cached views! ");
821 else if(requestType ==
"getGroupHistory")
828 __SUP_COUTV__(groupAction);
829 __SUP_COUTV__(groupType);
831 std::vector<std::map<std::string ,
834 groupAction, groupType,
true );
836 for(
const auto& group : groups)
838 auto parentEl = xmlOut.addTextElementToData(
839 "GroupHistoryEntry",
"");
840 for(
const auto& field : group)
844 else if(requestType ==
"getTreeView")
851 int depth = CgiDataUtilities::getDataAsInt(cgiIn,
"depth");
852 bool hideStatusFalse = CgiDataUtilities::getDataAsInt(cgiIn,
"hideStatusFalse");
856 __SUP_COUTT__ <<
"tableGroup: " << tableGroup << __E__;
857 __SUP_COUTT__ <<
"tableGroupKey: " << tableGroupKey << __E__;
858 __SUP_COUTT__ <<
"startPath: " << startPath << __E__;
859 __SUP_COUTT__ <<
"depth: " << depth << __E__;
860 __SUP_COUTT__ <<
"hideStatusFalse: " << hideStatusFalse << __E__;
861 __SUP_COUTT__ <<
"modifiedTables: " << modifiedTables << __E__;
862 __SUP_COUTT__ <<
"filterList: " << filterList << __E__;
864 handleFillTreeViewXML(xmlOut,
876 else if(requestType ==
"getTreeNodeCommonFields")
884 int depth = CgiDataUtilities::getDataAsInt(cgiIn,
"depth");
886 __SUP_COUT__ <<
"tableGroup: " << tableGroup << __E__;
887 __SUP_COUT__ <<
"tableGroupKey: " << tableGroupKey << __E__;
888 __SUP_COUT__ <<
"startPath: " << startPath << __E__;
889 __SUP_COUT__ <<
"depth: " << depth << __E__;
892 __SUP_COUT__ <<
"fieldList: " << fieldList << __E__;
893 __SUP_COUT__ <<
"recordList: " << recordList << __E__;
894 __SUP_COUT__ <<
"modifiedTables: " << modifiedTables << __E__;
896 handleFillTreeNodeCommonFieldsXML(xmlOut,
906 else if(requestType ==
"getUniqueFieldValuesForRecords")
915 __SUP_COUT__ <<
"tableGroup: " << tableGroup << __E__;
916 __SUP_COUT__ <<
"tableGroupKey: " << tableGroupKey << __E__;
917 __SUP_COUT__ <<
"startPath: " << startPath << __E__;
918 __SUP_COUT__ <<
"fieldList: " << fieldList << __E__;
919 __SUP_COUT__ <<
"recordList: " << recordList << __E__;
920 __SUP_COUT__ <<
"modifiedTables: " << modifiedTables << __E__;
922 handleFillUniqueFieldValuesForRecordsXML(xmlOut,
931 else if(requestType ==
"getTreeNodeFieldValues")
940 __SUP_COUT__ <<
"tableGroup: " << tableGroup << __E__;
941 __SUP_COUT__ <<
"tableGroupKey: " << tableGroupKey << __E__;
942 __SUP_COUT__ <<
"startPath: " << startPath << __E__;
943 __SUP_COUT__ <<
"fieldList: " << fieldList << __E__;
944 __SUP_COUT__ <<
"recordList: " << recordList << __E__;
945 __SUP_COUT__ <<
"modifiedTables: " << modifiedTables << __E__;
947 handleFillGetTreeNodeFieldValuesXML(xmlOut,
956 else if(requestType ==
"setTreeNodeFieldValues")
966 __SUP_COUT__ <<
"tableGroup: " << tableGroup << __E__;
967 __SUP_COUT__ <<
"tableGroupKey: " << tableGroupKey << __E__;
968 __SUP_COUT__ <<
"startPath: " << startPath << __E__;
969 __SUP_COUT__ <<
"fieldList: " << fieldList << __E__;
970 __SUP_COUT__ <<
"valueList: " << valueList << __E__;
971 __SUP_COUT__ <<
"recordList: " << recordList << __E__;
972 __SUP_COUT__ <<
"modifiedTables: " << modifiedTables << __E__;
974 handleFillSetTreeNodeFieldValuesXML(xmlOut,
985 else if(requestType ==
"addTreeNodeRecords")
993 __SUP_COUT__ <<
"tableGroup: " << tableGroup << __E__;
994 __SUP_COUT__ <<
"tableGroupKey: " << tableGroupKey << __E__;
995 __SUP_COUT__ <<
"startPath: " << startPath << __E__;
996 __SUP_COUT__ <<
"recordList: " << recordList << __E__;
997 __SUP_COUT__ <<
"modifiedTables: " << modifiedTables << __E__;
999 handleFillCreateTreeNodeRecordsXML(xmlOut,
1006 userInfo.username_);
1008 else if(requestType ==
"deleteTreeNodeRecords")
1016 __SUP_COUT__ <<
"tableGroup: " << tableGroup << __E__;
1017 __SUP_COUT__ <<
"tableGroupKey: " << tableGroupKey << __E__;
1018 __SUP_COUT__ <<
"startPath: " << startPath << __E__;
1019 __SUP_COUT__ <<
"recordList: " << recordList << __E__;
1020 __SUP_COUT__ <<
"modifiedTables: " << modifiedTables << __E__;
1022 handleFillDeleteTreeNodeRecordsXML(xmlOut,
1030 else if(requestType ==
"renameTreeNodeRecords")
1039 __SUP_COUT__ <<
"tableGroup: " << tableGroup << __E__;
1040 __SUP_COUT__ <<
"tableGroupKey: " << tableGroupKey << __E__;
1041 __SUP_COUT__ <<
"startPath: " << startPath << __E__;
1042 __SUP_COUT__ <<
"recordList: " << recordList << __E__;
1043 __SUP_COUT__ <<
"modifiedTables: " << modifiedTables << __E__;
1044 __SUP_COUTV__(newRecordList);
1046 handleFillRenameTreeNodeRecordsXML(xmlOut,
1055 else if(requestType ==
"copyTreeNodeRecords")
1062 unsigned int numberOfCopies =
1063 CgiDataUtilities::getDataAsInt(cgiIn,
"numberOfCopies");
1067 __SUP_COUT__ <<
"tableGroup: " << tableGroup << __E__;
1068 __SUP_COUT__ <<
"tableGroupKey: " << tableGroupKey << __E__;
1069 __SUP_COUT__ <<
"startPath: " << startPath << __E__;
1070 __SUP_COUT__ <<
"recordList: " << recordList << __E__;
1071 __SUP_COUT__ <<
"modifiedTables: " << modifiedTables << __E__;
1072 __SUP_COUTV__(numberOfCopies);
1074 handleFillCopyTreeNodeRecordsXML(xmlOut,
1083 else if(requestType ==
"getTableStructureStatusAsJSON")
1090 __SUP_COUT__ <<
"tableGroup: " << tableGroup << __E__;
1091 __SUP_COUT__ <<
"tableGroupKey: " << tableGroupKey << __E__;
1092 __SUP_COUT__ <<
"tableName: " << tableName << __E__;
1093 __SUP_COUT__ <<
"modifiedTables: " << modifiedTables << __E__;
1096 setupActiveTablesXML(xmlOut,
1105 xmlOut.addTextElementToData(
1106 "StructureStatusAsJSON",
1109 catch(
const std::runtime_error& e)
1111 __SUP_SS__ <<
"The table plugin feature getStructureStatusAsJSON(), does not "
1112 "seem to be supported for the table '"
1114 <<
".' Make sure you have the expected table plugin in your path, "
1115 "or contact system admins."
1117 ss <<
"Here is the error: " << e.what() << __E__;
1121 else if(requestType ==
"getArtdaqNodes")
1125 __SUP_COUTV__(modifiedTables);
1127 handleGetArtdaqNodeRecordsXML(xmlOut, cfgMgr, modifiedTables);
1129 else if(requestType ==
"saveArtdaqNodes")
1133 std::string subsystemString =
1136 __SUP_COUTV__(modifiedTables);
1137 __SUP_COUTV__(nodeString);
1138 __SUP_COUTV__(subsystemString);
1140 handleSaveArtdaqNodeRecordsXML(
1141 nodeString, subsystemString, xmlOut, cfgMgr, modifiedTables);
1143 else if(requestType ==
"getArtdaqNodeLayout")
1145 std::string contextGroupName =
1149 __SUP_COUTV__(contextGroupName);
1150 __SUP_COUTV__(contextGroupKey);
1152 handleLoadArtdaqNodeLayoutXML(
1153 xmlOut, cfgMgr, contextGroupName,
TableGroupKey(contextGroupKey));
1155 else if(requestType ==
"saveArtdaqNodeLayout")
1158 std::string contextGroupName =
1162 __SUP_COUTV__(layout);
1163 __SUP_COUTV__(contextGroupName);
1164 __SUP_COUTV__(contextGroupKey);
1166 handleSaveArtdaqNodeLayoutXML(
1167 xmlOut, cfgMgr, layout, contextGroupName,
TableGroupKey(contextGroupKey));
1169 else if(requestType ==
"checkAffectedActiveGroups")
1174 __SUP_COUT__ <<
"modifiedTables: " << modifiedTables << __E__;
1175 __SUP_COUT__ <<
"groupName: " << groupName << __E__;
1176 __SUP_COUT__ <<
"groupKey: " << groupKey << __E__;
1178 handleGetAffectedGroupsXML(
1179 xmlOut, cfgMgr, groupName,
TableGroupKey(groupKey), modifiedTables);
1181 else if(requestType ==
"SearchFieldInGroup")
1195 __SUP_COUT__ <<
"searchText: " << searchText << __E__;
1196 __SUP_COUT__ <<
"filterValue: " << filterValue << __E__;
1197 __SUP_COUT__ <<
"groupType: " << groupType << __E__;
1198 __SUP_COUT__ <<
"optionGroups: " << optionGroups << __E__;
1199 __SUP_COUT__ <<
"versionsToCheck: " << versionsToCheck << __E__;
1201 handleSearchFieldInGroupXML(xmlOut,
1204 (filterValue ==
"true"),
1209 else if(requestType ==
"SearchFieldInTableVersions")
1213 std::string searchVersionToCheck =
1222 __SUP_COUT__ <<
"searchText: " << searchText << __E__;
1223 __SUP_COUT__ <<
"tableName: " << tableName << __E__;
1224 __SUP_COUT__ <<
"searchVersionToCheck: " << searchVersionToCheck << __E__;
1225 __SUP_COUT__ <<
"activeTablesOnly: " << activeTablesOnly << __E__;
1227 handleSearchFieldInTableXML(xmlOut,
1231 searchVersionToCheck,
1232 (activeTablesOnly ==
"true"));
1234 else if(requestType ==
"saveTreeNodeEdit")
1238 std::string targetTableVersion =
1244 __SUP_COUT__ <<
"editNodeType: " << editNodeType << __E__;
1245 __SUP_COUT__ <<
"targetTable: " << targetTable << __E__;
1246 __SUP_COUT__ <<
"targetTableVersion: " << targetTableVersion << __E__;
1247 __SUP_COUT__ <<
"targetUID: " << targetUID << __E__;
1248 __SUP_COUT__ <<
"targetColumn: " << targetColumn << __E__;
1249 __SUP_COUT__ <<
"newValue: " << newValue << __E__;
1251 handleSaveTreeNodeEditXML(xmlOut,
1259 userInfo.username_);
1261 else if(requestType ==
"getLinkToChoices")
1264 std::string linkToTableVersion =
1271 __SUP_COUT__ <<
"linkToTableName: " << linkToTableName << __E__;
1272 __SUP_COUT__ <<
"linkToTableVersion: " << linkToTableVersion << __E__;
1273 __SUP_COUT__ <<
"linkIdType: " << linkIdType << __E__;
1274 __SUP_COUT__ <<
"linkIndex: " << linkIndex << __E__;
1275 __SUP_COUT__ <<
"linkInitId: " << linkInitId << __E__;
1277 handleGetLinkToChoicesXML(xmlOut,
1285 else if(requestType ==
"activateTableGroup")
1289 bool ignoreWarnings = CgiDataUtilities::getDataAsInt(cgiIn,
"ignoreWarnings");
1291 __SUP_COUT__ <<
"Activating group: " << groupName <<
"(" << groupKey <<
")"
1293 __SUP_COUTV__(ignoreWarnings);
1296 xmlOut.addTextElementToData(
"AttemptedGroupActivation",
"1");
1297 xmlOut.addTextElementToData(
"AttemptedGroupActivationName", groupName);
1298 xmlOut.addTextElementToData(
"AttemptedGroupActivationKey", groupKey);
1302 std::string accumulatedErrors, groupTypeString;
1310 groupName,
TableGroupKey(groupKey), &accumulatedErrors, &groupTypeString);
1312 if(accumulatedErrors !=
"")
1316 __SS__ <<
"Throwing exception on accumulated errors: "
1317 << accumulatedErrors << __E__;
1321 __COUT_WARN__ <<
"Ignoring warnings so ignoring this error:"
1322 << accumulatedErrors << __E__;
1323 __COUT_WARN__ <<
"Done ignoring the above error(s)." << __E__;
1325 xmlOut.addTextElementToData(
"AttemptedGroupActivationType", groupTypeString);
1327 catch(std::runtime_error& e)
1332 __SUP_COUT__ <<
"Error detected!\n\n " << e.what() << __E__;
1333 xmlOut.addTextElementToData(
1335 "Error activating table group '" + groupName +
"(" + groupKey +
")" +
1336 ".' Please see details below:\n\n" + std::string(e.what()));
1337 __SUP_COUT_ERR__ <<
"Errors detected so de-activating group: " << groupName
1338 <<
" (" << groupKey <<
")" << __E__;
1347 catch(cet::exception& e)
1353 __SUP_COUT__ <<
"Error detected!\n\n " << e.what() << __E__;
1354 xmlOut.addTextElementToData(
"Error",
1355 "Error activating table group '" + groupName +
1356 "(" + groupKey +
")" +
"!'\n\n" +
1357 std::string(e.what()));
1358 __SUP_COUT_ERR__ <<
"Errors detected so de-activating group: " << groupName
1359 <<
" (" << groupKey <<
")" << __E__;
1370 __SUP_COUT__ <<
"Unknown error detected!" << __E__;
1382 else if(requestType ==
"getActiveTableGroups")
1384 else if(requestType ==
"copyViewToCurrentColumns")
1386 std::string tableName =
1390 __SUP_COUT__ <<
"tableName: " << tableName << __E__;
1391 __SUP_COUT__ <<
"sourceVersion: " << sourceVersion << __E__;
1392 __SUP_COUT__ <<
"userInfo.username_: " << userInfo.username_ << __E__;
1398 newTemporaryVersion =
1401 __SUP_COUT__ <<
"New temporary version = " << newTemporaryVersion << __E__;
1403 catch(std::runtime_error& e)
1405 __SUP_COUT__ <<
"Error detected!\n\n " << e.what() << __E__;
1406 xmlOut.addTextElementToData(
"Error",
1407 "Error copying view from '" + tableName +
"_v" +
1408 sourceVersion +
"'! " +
1409 std::string(e.what()));
1413 __SUP_COUT__ <<
"Error detected!\n\n " << __E__;
1414 xmlOut.addTextElementToData(
1416 "Error copying view from '" + tableName +
"_v" + sourceVersion +
"'! ");
1419 handleGetTableXML(xmlOut, cfgMgr, tableName, newTemporaryVersion);
1421 else if(requestType ==
"getLastTableGroups")
1424 std::map<std::string ,
1425 std::tuple<std::string ,
1430 theRemoteWebUsers_.getLastTableGroups(theGroups);
1432 for(
const auto& theGroup : theGroups)
1434 xmlOut.addTextElementToData(
"Last" + theGroup.first +
"GroupName",
1435 std::get<0>(theGroup.second));
1436 xmlOut.addTextElementToData(
"Last" + theGroup.first +
"GroupKey",
1437 std::get<1>(theGroup.second).toString());
1438 xmlOut.addTextElementToData(
"Last" + theGroup.first +
"GroupTime",
1439 std::get<2>(theGroup.second));
1472 handleOtherSubsystemActiveGroups(xmlOut, cfgMgr,
false );
1474 else if(requestType ==
"getSubsytemTableGroups")
1476 std::string subsystem =
1478 __SUP_COUTV__(subsystem);
1479 handleOtherSubsystemActiveGroups(
1480 xmlOut, cfgMgr,
true , subsystem);
1482 else if(requestType ==
"diffWithActiveGroup")
1484 std::string groupName =
1487 __SUP_COUTV__(groupName);
1488 __SUP_COUTV__(groupKey);
1493 else if(requestType ==
"diffWithGroupKey")
1495 std::string groupName =
1499 std::string diffGroupName =
1501 __SUP_COUTV__(groupName);
1502 __SUP_COUTV__(groupKey);
1503 __SUP_COUTV__(diffKey);
1504 __SUP_COUTV__(diffGroupName);
1506 handleGroupDiff(xmlOut,
1513 else if(requestType ==
"diffTableVersions")
1515 std::string tableName =
1519 __SUP_COUTV__(tableName);
1524 const std::map<std::string, TableInfo>& allTableInfo = cfgMgr->
getAllTableInfo();
1527 if(allTableInfo.find(tableName) != allTableInfo.end())
1529 if(vA.find(ConfigurationManager::ALIAS_VERSION_PREAMBLE) == 0)
1532 std::map<std::string ,
1536 std::string versionAlias;
1538 vA.substr(ConfigurationManager::ALIAS_VERSION_PREAMBLE.size());
1540 if(versionAliases.find(tableName) != versionAliases.end() &&
1541 versionAliases[tableName].find(versionAlias) !=
1542 versionAliases[tableName].end())
1544 versionA = versionAliases[tableName][versionAlias];
1545 __SUP_COUT__ <<
"version alias translated to: " << versionA << __E__;
1548 __SUP_COUT_WARN__ <<
"version alias '" << versionAlias
1549 <<
"'was not found in active version aliases!"
1553 versionA = atoi(vA.c_str());
1555 if(vB.find(ConfigurationManager::ALIAS_VERSION_PREAMBLE) == 0)
1558 std::map<std::string ,
1562 std::string versionAlias;
1564 vB.substr(ConfigurationManager::ALIAS_VERSION_PREAMBLE.size());
1566 if(versionAliases.find(tableName) != versionAliases.end() &&
1567 versionAliases[tableName].find(versionAlias) !=
1568 versionAliases[tableName].end())
1570 versionB = versionAliases[tableName][versionAlias];
1571 __SUP_COUT__ <<
"version alias translated to: " << versionB << __E__;
1574 __SUP_COUT_WARN__ <<
"version alias '" << versionAlias
1575 <<
"'was not found in active version aliases!"
1579 versionB = atoi(vB.c_str());
1583 versionA = atoi(vA.c_str());
1584 versionB = atoi(vB.c_str());
1587 __SUP_COUTV__(versionA);
1588 __SUP_COUTV__(versionB);
1590 handleTableDiff(xmlOut, cfgMgr, tableName, versionA, versionB);
1592 else if(requestType ==
"findGroupsWithTable")
1594 std::string tableName =
1596 std::string tableVersion =
1599 __SUP_COUTV__(tableName);
1600 __SUP_COUTV__(tableVersion);
1602 std::set<std::string> groupsContainingTable =
1603 cfgMgr->getConfigurationInterface()->findGroupsWithTable(
1605 __SUP_COUT__ <<
"Groups containing " << tableName <<
"-v" << tableVersion
1606 <<
" count: " << groupsContainingTable.size() << __E__;
1607 std::string groupsContainingTableString =
1609 __SUP_COUTTV__(groupsContainingTableString);
1611 xmlOut.addNumberElementToData(
"GroupsContainingCount",
1612 groupsContainingTable.size());
1613 xmlOut.addTextElementToData(
"GroupsContainingCSV", groupsContainingTableString);
1616 else if(requestType ==
"savePlanCommandSequence")
1619 std::string commands =
1625 __SUP_COUTV__(modifiedTables);
1626 __SUP_COUTV__(planName);
1627 __SUP_COUTV__(commands);
1628 __SUP_COUTV__(groupName);
1629 __SUP_COUTV__(groupKey);
1631 handleSavePlanCommandSequenceXML(xmlOut,
1640 else if(requestType ==
"mergeGroups")
1642 std::string groupANameContext =
1644 std::string groupAKeyContext =
1646 std::string groupBNameContext =
1648 std::string groupBKeyContext =
1650 std::string groupANameConfig =
1653 std::string groupBNameConfig =
1658 __SUP_COUTV__(groupANameContext);
1659 __SUP_COUTV__(groupAKeyContext);
1660 __SUP_COUTV__(groupBNameContext);
1661 __SUP_COUTV__(groupBKeyContext);
1662 __SUP_COUTV__(groupANameConfig);
1663 __SUP_COUTV__(groupAKeyConfig);
1664 __SUP_COUTV__(groupBNameConfig);
1665 __SUP_COUTV__(groupBKeyConfig);
1666 __SUP_COUTV__(mergeApproach);
1668 handleMergeGroupsXML(xmlOut,
1683 __SUP_SS__ <<
"requestType Request, " << requestType
1684 <<
", not recognized by the Configuration GUI Supervisor (was it "
1685 "intended for another Supervisor?)."
1687 __SUP_COUT__ <<
"\n" << ss.str();
1688 xmlOut.addTextElementToData(
"Error", ss.str());
1691 __SUP_COUTT__ <<
"cfgMgr runtime=" << cfgMgr->runTimeSeconds() << __E__;
1694 xmlOut, cfgMgr, userInfo.username_);
1695 __SUP_COUTT__ <<
"cfgMgr runtime=" << cfgMgr->runTimeSeconds() << __E__;
1698 catch(
const std::runtime_error& e)
1700 __SS__ <<
"A fatal error occurred while handling the request '" << requestType
1701 <<
".' Error: " << e.what() << __E__;
1702 __COUT_ERR__ <<
"\n" << ss.str();
1703 xmlOut.addTextElementToData(
"Error", ss.str());
1708 xmlOut.addTextElementToData(
1710 ConfigurationInterface::isVersionTrackingEnabled() ?
"ON" :
"OFF");
1714 __COUT_ERR__ <<
"Error getting version tracking status!" << __E__;
1719 __SS__ <<
"An unknown fatal error occurred while handling the request '"
1720 << requestType <<
".'" << __E__;
1725 catch(
const std::exception& e)
1727 ss <<
"Exception message: " << e.what();
1732 __COUT_ERR__ <<
"\n" << ss.str();
1733 xmlOut.addTextElementToData(
"Error", ss.str());
1738 xmlOut.addTextElementToData(
1740 ConfigurationInterface::isVersionTrackingEnabled() ?
"ON" :
"OFF");
1744 __COUT_ERR__ <<
"Error getting version tracking status!" << __E__;
1764 void ConfigurationGUISupervisor::handleGetAffectedGroupsXML(
1767 const std::string& rootGroupName,
1769 const std::string& modifiedTables)
1772 __SUP_COUT__ <<
"rootGroupName " << rootGroupName <<
"(" << rootGroupKey
1773 <<
"). modifiedTables = " << modifiedTables << __E__;
1775 std::map<std::string, std::pair<std::string, TableGroupKey>> consideredGroups =
1780 if(consideredGroups[ConfigurationManager::GROUP_TYPE_NAME_CONTEXT].second.isInvalid())
1782 __SUP_COUT__ <<
"Finding a context group to consider..." << __E__;
1783 if(cfgMgr->getFailedTableGroups().find(
1784 ConfigurationManager::GROUP_TYPE_NAME_CONTEXT) !=
1785 cfgMgr->getFailedTableGroups().end())
1787 consideredGroups[ConfigurationManager::GROUP_TYPE_NAME_CONTEXT] =
1788 cfgMgr->getFailedTableGroups().at(
1789 ConfigurationManager::GROUP_TYPE_NAME_CONTEXT);
1791 else if(cfgMgr->getFailedTableGroups().find(
1792 ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN) !=
1793 cfgMgr->getFailedTableGroups().end())
1795 consideredGroups[ConfigurationManager::GROUP_TYPE_NAME_CONTEXT] =
1796 cfgMgr->getFailedTableGroups().at(
1797 ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN);
1800 if(consideredGroups[ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION]
1801 .second.isInvalid())
1803 __SUP_COUT__ <<
"Finding a table group to consider..." << __E__;
1804 if(cfgMgr->getFailedTableGroups().find(
1805 ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION) !=
1806 cfgMgr->getFailedTableGroups().end())
1808 consideredGroups[ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION] =
1809 cfgMgr->getFailedTableGroups().at(
1810 ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION);
1812 else if(cfgMgr->getFailedTableGroups().find(
1813 ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN) !=
1814 cfgMgr->getFailedTableGroups().end())
1816 consideredGroups[ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION] =
1817 cfgMgr->getFailedTableGroups().at(
1818 ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN);
1827 std::map<std::string ,
TableVersion > rootGroupMemberMap;
1832 &rootGroupMemberMap,
1842 consideredGroups[groupType] =
1843 std::pair<std::string, TableGroupKey>(rootGroupName, rootGroupKey);
1845 catch(
const std::runtime_error& e)
1848 if(rootGroupName.size())
1850 __SUP_SS__ <<
"Failed to determine type of table group for " << rootGroupName
1851 <<
"(" << rootGroupKey <<
")! " << e.what() << __E__;
1852 __SUP_COUT_ERR__ <<
"\n" << ss.str();
1857 __SUP_COUT__ <<
"Did not modify considered active groups due to empty root group "
1858 "name - assuming this was intentional."
1864 if(rootGroupName.size())
1866 __SUP_COUT_ERR__ <<
"Failed to determine type of table group for "
1867 << rootGroupName <<
"(" << rootGroupKey <<
")!" << __E__;
1872 __SUP_COUT__ <<
"Did not modify considered active groups due to empty root group "
1873 "name - assuming this was intentional."
1877 std::map<std::string ,
1880 std::map<std::string ,
1882 modifiedTablesMapIt;
1884 std::istringstream f(modifiedTables);
1885 std::string table, version;
1886 while(getline(f, table,
','))
1888 getline(f, version,
',');
1889 modifiedTablesMap.insert(
1892 std::pair<bool /*foundAffectedGroup*/, TableVersion /*version*/>>(
1896 __SUP_COUT__ << modifiedTables << __E__;
1897 for(
auto& pair : modifiedTablesMap)
1898 __SUP_COUT__ <<
"modified table " << pair.first <<
":" << pair.second.second
1903 xercesc::DOMElement* parentEl =
nullptr;
1904 std::string groupComment;
1905 std::vector<std::string> orderedGroupTypes(
1906 {ConfigurationManager::GROUP_TYPE_NAME_CONTEXT,
1907 ConfigurationManager::GROUP_TYPE_NAME_BACKBONE,
1908 ConfigurationManager::GROUP_TYPE_NAME_ITERATE,
1909 ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION});
1910 for(
auto groupType : orderedGroupTypes)
1912 if(consideredGroups.find(groupType) == consideredGroups.end())
1915 const std::pair<std::string, TableGroupKey>& group = consideredGroups[groupType];
1917 if(group.second.isInvalid())
1920 __SUP_COUT__ <<
"Considering " << groupType <<
" group " << group.first <<
" ("
1921 << group.second <<
")" << __E__;
1939 __SUP_COUT__ <<
"groupComment = " << groupComment << __E__;
1941 for(
auto& table : memberMap)
1943 if((modifiedTablesMapIt = modifiedTablesMap.find(table.first)) !=
1946 table.second != (*modifiedTablesMapIt).second.second)
1948 __SUP_COUT__ <<
"Affected by " << (*modifiedTablesMapIt).first <<
":"
1949 << (*modifiedTablesMapIt).second.second << __E__;
1951 memberMap[table.first] = (*modifiedTablesMapIt).second.second;
1952 (*modifiedTablesMapIt).second.first =
true;
1956 parentEl = xmlOut.addTextElementToData(
"AffectedActiveGroup",
"");
1960 if(groupType == ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
1962 __SUP_COUT__ <<
"Considering mockup tables for Configuration Group..."
1964 for(
auto& table : modifiedTablesMap)
1966 if(table.second.first)
1969 if(table.second.second.isMockupVersion() &&
1970 memberMap.find(table.first) == memberMap.end())
1972 __SUP_COUT__ <<
"Found mockup table '" << table.first
1973 <<
"' for Configuration Group." << __E__;
1974 memberMap[table.first] = table.second.second;
1977 parentEl = xmlOut.addTextElementToData(
"AffectedActiveGroup",
"");
1981 "AddMemberVersion", table.second.second.toString(), parentEl);
1988 __SUP_COUTV__(affected);
1992 parentEl = xmlOut.addTextElementToData(
"AffectedActiveGroup",
"");
1997 for(
auto& table : memberMap)
2001 "MemberVersion", table.second.toString(), parentEl);
2006 catch(std::runtime_error& e)
2008 __SUP_COUT__ <<
"Error detected!\n\n " << e.what() << __E__;
2009 xmlOut.addTextElementToData(
2010 "Error",
"Error getting affected groups! " + std::string(e.what()));
2014 __SUP_COUT__ <<
"Error detected!\n\n " << __E__;
2015 xmlOut.addTextElementToData(
"Error",
"Error getting affected groups! ");
2026 void ConfigurationGUISupervisor::setupActiveTablesXML(
2029 const std::string& groupName,
2031 const std::string& modifiedTables,
2033 bool doGetGroupInfo,
2034 std::map<std::string /*name*/, TableVersion /*version*/>* returnMemberMap,
2035 bool outputActiveTables,
2036 std::string* accumulatedErrors)
2039 xmlOut.addTextElementToData(
"tableGroup", groupName);
2040 xmlOut.addTextElementToData(
"tableGroupKey", groupKey.
toString());
2042 bool usingActiveGroups = (groupName ==
"" || groupKey.
isInvalid());
2050 __SUP_COUT__ <<
"Refreshing all table info, ignoring warnings..." << __E__;
2051 std::string accumulatedWarnings =
"";
2053 &accumulatedWarnings,
2067 __SUP_COUT__ <<
"Restoring active table group tables..." << __E__;
2069 for(
const auto& activeGroup : activeGroups)
2071 if(activeGroup.second.first == groupName &&
2072 activeGroup.second.second == groupKey)
2074 __SUP_COUTT__ <<
"Skipping target active group." << __E__;
2077 __SUP_COUTT__ <<
"Loading " << activeGroup.first <<
" "
2078 << activeGroup.second.first <<
"(" << activeGroup.second.second
2083 activeGroup.second.second,
2089 __SUP_COUT__ <<
"Ignoring errors while setting up active tables for "
2090 << activeGroup.second.first <<
"("
2091 << activeGroup.second.second <<
")..." << __E__;
2097 const std::map<std::string, TableInfo>& allTableInfo = cfgMgr->
getAllTableInfo();
2099 std::map<std::string ,
TableVersion > modifiedTablesMap;
2101 modifiedTablesMapIt;
2103 if(usingActiveGroups)
2106 __SUP_COUT__ <<
"Using active groups." << __E__;
2110 __SUP_COUT__ <<
"Loading group '" << groupName <<
"(" << groupKey <<
")'"
2113 std::string groupComment, groupAuthor, tableGroupCreationTime, groupType;
2122 doGetGroupInfo ? &groupComment : 0,
2123 doGetGroupInfo ? &groupAuthor : 0,
2124 doGetGroupInfo ? &tableGroupCreationTime : 0,
2126 doGetGroupInfo ? &groupType : 0);
2130 xmlOut.addTextElementToData(
"tableGroupComment", groupComment);
2131 xmlOut.addTextElementToData(
"tableGroupAuthor", groupAuthor);
2132 xmlOut.addTextElementToData(
"tableGroupCreationTime", tableGroupCreationTime);
2133 xmlOut.addTextElementToData(
"tableGroupType", groupType);
2136 if(accumulatedErrors && *accumulatedErrors !=
"")
2137 __SUP_COUTV__(*accumulatedErrors);
2143 std::istringstream f(modifiedTables);
2144 std::string table, version;
2145 while(getline(f, table,
','))
2147 getline(f, version,
',');
2148 modifiedTablesMap.insert(
2149 std::pair<std::string /*name*/, TableVersion /*version*/>(
2153 for(
auto& pair : modifiedTablesMap)
2154 __SUP_COUT__ <<
"modified table " << pair.first <<
":" << pair.second
2159 std::map<std::string, TableVersion> allActivePairs = cfgMgr->
getActiveVersions();
2160 xmlOut.addTextElementToData(
"DefaultNoLink",
2161 TableViewColumnInfo::DATATYPE_LINK_DEFAULT);
2164 std::set<std::string, StringMacros::IgnoreCaseCompareStruct> orderedTableSet;
2165 for(
const auto& tablePair : allActivePairs)
2166 orderedTableSet.emplace(tablePair.first);
2168 std::map<std::string, TableInfo>::const_iterator tableInfoIt;
2169 for(
auto& orderedTableName : orderedTableSet)
2171 tableInfoIt = allTableInfo.find(orderedTableName);
2172 if(tableInfoIt == allTableInfo.end())
2174 __SS__ <<
"Impossible missing table in map '" << orderedTableName <<
"'"
2179 if(outputActiveTables)
2180 xmlOut.addTextElementToData(
"ActiveTableName", orderedTableName);
2184 if((modifiedTablesMapIt = modifiedTablesMap.find(orderedTableName)) !=
2185 modifiedTablesMap.end())
2187 __SUP_COUT__ <<
"Found modified table " << (*modifiedTablesMapIt).first
2188 <<
": trying... " << (*modifiedTablesMapIt).second << __E__;
2192 tableInfoIt->second.tablePtr_->setActiveView(
2193 (*modifiedTablesMapIt).second);
2197 __SUP_SS__ <<
"Modified table version v" << (*modifiedTablesMapIt).second
2198 <<
" failed. Reverting to v"
2199 << tableInfoIt->second.tablePtr_->getView().getVersion() <<
"."
2201 __SUP_COUT_WARN__ <<
"Warning detected!\n\n " << ss.str() << __E__;
2202 xmlOut.addTextElementToData(
2204 "Error setting up active tables!\n\n" + std::string(ss.str()));
2208 if(outputActiveTables)
2210 xmlOut.addTextElementToData(
2211 "ActiveTableVersion",
2212 tableInfoIt->second.tablePtr_->getView().getVersion().toString());
2213 xmlOut.addTextElementToData(
2214 "ActiveTableComment",
2215 tableInfoIt->second.tablePtr_->getView().getAuthor() +
": " +
2216 tableInfoIt->second.tablePtr_->getView().getComment());
2224 catch(std::runtime_error& e)
2226 __SUP_SS__ << (
"Error setting up active tables!\n\n" + std::string(e.what()))
2228 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2229 xmlOut.addTextElementToData(
"Error", ss.str());
2234 __SUP_SS__ << (
"Error setting up active tables!\n\n") << __E__;
2239 catch(
const std::exception& e)
2241 ss <<
"Exception message: " << e.what();
2246 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2247 xmlOut.addTextElementToData(
"Error", ss.str());
2266 void ConfigurationGUISupervisor::handleFillCreateTreeNodeRecordsXML(
2269 const std::string& groupName,
2271 const std::string& startPath,
2272 const std::string& modifiedTables,
2273 const std::string& recordList,
2274 const std::string& author)
2277 setupActiveTablesXML(xmlOut,
2292 __SUP_COUT__ << table->getTableName() << __E__;
2302 bool firstSave =
true;
2309 std::istringstream f(recordList);
2310 std::string recordUID;
2312 while(getline(f, recordUID,
','))
2316 __SUP_COUT__ <<
"recordUID " << recordUID << __E__;
2321 .isTemporaryVersion())
2323 __SUP_COUT__ <<
"Start version " << temporaryVersion << __E__;
2325 temporaryVersion = table->createTemporaryView(temporaryVersion);
2331 __SUP_COUT__ <<
"Created temporary version " << temporaryVersion
2335 __SUP_COUT__ <<
"Using temporary version " << temporaryVersion
2341 backupView.copy(table->getView(), temporaryVersion, author);
2350 unsigned int row = table->getViewP()->addRow(
2357 unsigned int col = table->getViewP()->getColStatus();
2358 table->getViewP()->setURIEncodedValue(
"1", row, col);
2365 table->getViewP()->setURIEncodedValue(
2366 recordUID, row, table->getViewP()->getColUID());
2374 table->getViewP()->init();
2378 __SUP_COUT_INFO__ <<
"Reverting to original view." << __E__;
2379 __SUP_COUT__ <<
"Before:" << __E__;
2380 table->getViewP()->print();
2381 table->getViewP()->copy(backupView, temporaryVersion, author);
2382 __SUP_COUT__ <<
"After:" << __E__;
2383 table->getViewP()->print();
2389 handleFillModifiedTablesXML(xmlOut, cfgMgr);
2391 catch(std::runtime_error& e)
2393 __SUP_SS__ << (
"Error creating new record(s)!\n\n" + std::string(e.what()))
2395 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2396 xmlOut.addTextElementToData(
"Error", ss.str());
2400 __SUP_SS__ << (
"Error creating new record(s)!\n\n") << __E__;
2405 catch(
const std::exception& e)
2407 ss <<
"Exception message: " << e.what();
2412 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2413 xmlOut.addTextElementToData(
"Error", ss.str());
2420 void ConfigurationGUISupervisor::handleFillModifiedTablesXML(
2425 const std::map<std::string, TableInfo>& allTableInfo = cfgMgr->
getAllTableInfo();
2426 std::map<std::string, TableVersion> allActivePairs = cfgMgr->
getActiveVersions();
2427 for(
auto& activePair : allActivePairs)
2429 xmlOut.addTextElementToData(
"NewActiveTableName", activePair.first);
2430 xmlOut.addTextElementToData(
"NewActiveTableVersion",
2431 allTableInfo.at(activePair.first)
2432 .tablePtr_->getView()
2435 xmlOut.addTextElementToData(
2436 "NewActiveTableComment",
2437 allTableInfo.at(activePair.first).tablePtr_->getView().getAuthor() +
": " +
2438 allTableInfo.at(activePair.first).tablePtr_->getView().getComment());
2441 catch(std::runtime_error& e)
2443 __SUP_SS__ << (
"Error!\n\n" + std::string(e.what())) << __E__;
2444 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2445 xmlOut.addTextElementToData(
"Error", ss.str());
2449 __SUP_SS__ << (
"Error!\n\n") << __E__;
2454 catch(
const std::exception& e)
2456 ss <<
"Exception message: " << e.what();
2461 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2462 xmlOut.addTextElementToData(
"Error", ss.str());
2480 void ConfigurationGUISupervisor::handleFillDeleteTreeNodeRecordsXML(
2483 const std::string& groupName,
2485 const std::string& startPath,
2486 const std::string& modifiedTables,
2487 const std::string& recordList)
2490 setupActiveTablesXML(xmlOut,
2505 __SUP_COUT__ << table->getTableName() << __E__;
2515 bool firstSave =
true;
2519 std::istringstream f(recordList);
2520 std::string recordUID;
2523 while(getline(f, recordUID,
','))
2527 __SUP_COUT__ <<
"recordUID " << recordUID << __E__;
2532 .isTemporaryVersion())
2534 __SUP_COUT__ <<
"Start version " << temporaryVersion << __E__;
2536 temporaryVersion = table->createTemporaryView(temporaryVersion);
2542 __SUP_COUT__ <<
"Created temporary version " << temporaryVersion
2546 __SUP_COUT__ <<
"Using temporary version " << temporaryVersion
2557 table->getViewP()->findRow(table->getViewP()->getColUID(), recordUID);
2558 table->getViewP()->deleteRow(row);
2563 table->getViewP()->init();
2565 handleFillModifiedTablesXML(xmlOut, cfgMgr);
2567 catch(std::runtime_error& e)
2569 __SUP_SS__ << (
"Error removing record(s)!\n\n" + std::string(e.what())) << __E__;
2570 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2571 xmlOut.addTextElementToData(
"Error", ss.str());
2575 __SUP_SS__ << (
"Error removing record(s)!\n\n") << __E__;
2580 catch(
const std::exception& e)
2582 ss <<
"Exception message: " << e.what();
2587 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2588 xmlOut.addTextElementToData(
"Error", ss.str());
2608 void ConfigurationGUISupervisor::handleFillRenameTreeNodeRecordsXML(
2611 const std::string& groupName,
2613 const std::string& startPath,
2614 const std::string& modifiedTables,
2615 const std::string& recordList,
2616 const std::string& newRecordList)
2619 setupActiveTablesXML(xmlOut,
2634 __SUP_COUT__ << table->getTableName() << __E__;
2645 std::vector<std::string> recordArray =
2647 std::vector<std::string> newRecordArray =
2653 if(recordArray.size() == 0 || recordArray.size() != newRecordArray.size())
2656 <<
"Invalid record size vs new record name size, they must be the same: "
2657 << recordArray.size() <<
" vs " << newRecordArray.size() << __E__;
2663 if(!(temporaryVersion = targetNode.
getTableVersion()).isTemporaryVersion())
2665 __SUP_COUT__ <<
"Start version " << temporaryVersion << __E__;
2667 temporaryVersion = table->createTemporaryView(temporaryVersion);
2673 __SUP_COUT__ <<
"Created temporary version " << temporaryVersion << __E__;
2676 __SUP_COUT__ <<
"Using temporary version " << temporaryVersion << __E__;
2683 for(
unsigned int i = 0; i < recordArray.size(); ++i)
2685 row = table->getViewP()->findRow(
2686 table->getViewP()->getColUID(),
2689 table->getViewP()->setValueAsString(
2690 newRecordArray[i], row, table->getViewP()->getColUID());
2693 table->getViewP()->init();
2695 handleFillModifiedTablesXML(xmlOut, cfgMgr);
2697 catch(std::runtime_error& e)
2699 __SUP_SS__ << (
"Error renaming record(s)!\n\n" + std::string(e.what())) << __E__;
2700 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2701 xmlOut.addTextElementToData(
"Error", ss.str());
2705 __SUP_SS__ << (
"Error renaming record(s)!\n\n") << __E__;
2710 catch(
const std::exception& e)
2712 ss <<
"Exception message: " << e.what();
2717 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2718 xmlOut.addTextElementToData(
"Error", ss.str());
2739 void ConfigurationGUISupervisor::handleFillCopyTreeNodeRecordsXML(
2742 const std::string& groupName,
2744 const std::string& startPath,
2745 const std::string& modifiedTables,
2746 const std::string& recordList,
2747 unsigned int numberOfCopies )
2753 setupActiveTablesXML(xmlOut,
2768 __SUP_COUT__ << table->getTableName() << __E__;
2779 std::vector<std::string> recordArray =
2785 if(!(temporaryVersion = targetNode.
getTableVersion()).isTemporaryVersion())
2787 __SUP_COUT__ <<
"Start version " << temporaryVersion << __E__;
2789 temporaryVersion = table->createTemporaryView(temporaryVersion);
2795 __SUP_COUT__ <<
"Created temporary version " << temporaryVersion << __E__;
2798 __SUP_COUT__ <<
"Using temporary version " << temporaryVersion << __E__;
2805 for(
const auto& recordUID : recordArray)
2807 row = table->getViewP()->findRow(table->getViewP()->getColUID(),
2809 for(
unsigned int i = 0; i < numberOfCopies; ++i)
2810 table->getViewP()->copyRows(
2820 table->getViewP()->init();
2822 handleFillModifiedTablesXML(xmlOut, cfgMgr);
2824 catch(std::runtime_error& e)
2826 __SUP_SS__ << (
"Error copying record(s)!\n\n" + std::string(e.what())) << __E__;
2827 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2828 xmlOut.addTextElementToData(
"Error", ss.str());
2832 __SUP_SS__ << (
"Error copying record(s)!\n\n") << __E__;
2837 catch(
const std::exception& e)
2839 ss <<
"Exception message: " << e.what();
2844 __SUP_COUT_ERR__ <<
"\n" << ss.str();
2845 xmlOut.addTextElementToData(
"Error", ss.str());
2866 void ConfigurationGUISupervisor::handleFillSetTreeNodeFieldValuesXML(
2869 const std::string& groupName,
2871 const std::string& startPath,
2872 const std::string& modifiedTables,
2873 const std::string& recordList,
2874 const std::string& fieldList,
2875 const std::string& valueList,
2876 const std::string& author)
2879 setupActiveTablesXML(xmlOut,
2894 std::vector<std::string > fieldPaths;
2897 std::istringstream f(fieldList);
2898 std::string fieldPath;
2899 while(getline(f, fieldPath,
','))
2903 __SUP_COUT__ << fieldList << __E__;
2904 for(
const auto& field : fieldPaths)
2905 __SUP_COUT__ <<
"fieldPath " << field << __E__;
2908 std::vector<std::string > fieldValues;
2911 std::istringstream f(valueList);
2912 std::string fieldValue;
2913 while(getline(f, fieldValue,
','))
2915 fieldValues.push_back(fieldValue);
2920 if(valueList.size() && valueList[valueList.size() - 1] ==
',')
2921 fieldValues.push_back(
"");
2923 __SUP_COUT__ << valueList << __E__;
2924 for(
const auto& value : fieldValues)
2925 __SUP_COUT__ <<
"fieldValue " << value << __E__;
2928 if(fieldPaths.size() != fieldValues.size())
2931 __THROW__(ss.str() +
"Mismatch in fields and values array size!");
2938 std::istringstream f(recordList);
2939 std::string recordUID;
2942 while(getline(f, recordUID,
','))
2947 xmlOut.addTextElementToData(
"fieldValues", recordUID);
2950 for(i = 0; i < fieldPaths.size(); ++i)
2952 __SUP_COUT__ <<
"fieldPath " << fieldPaths[i] << __E__;
2953 __SUP_COUT__ <<
"fieldValue " << fieldValues[i] << __E__;
2958 cfgMgr->
getNode(startPath +
"/" + recordUID +
"/" + fieldPaths[i],
2999 if(!(temporaryVersion = table->getViewP()->getVersion())
3000 .isTemporaryVersion())
3004 table->createTemporaryView(table->getViewP()->getVersion());
3010 __SUP_COUT__ <<
"Created temporary version "
3011 << table->getTableName() <<
"-v" << temporaryVersion
3015 __SUP_COUT__ <<
"Using temporary version " << table->getTableName()
3016 <<
"-v" << temporaryVersion << __E__;
3020 table->getViewP()->setURIEncodedValue(fieldValues[i],
3031 handleFillModifiedTablesXML(xmlOut, cfgMgr);
3033 catch(std::runtime_error& e)
3035 __SUP_SS__ << (
"Error setting field values!\n\n" + std::string(e.what()))
3037 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3038 xmlOut.addTextElementToData(
"Error", ss.str());
3042 __SUP_SS__ << (
"Error setting field values!\n\n") << __E__;
3047 catch(
const std::exception& e)
3049 ss <<
"Exception message: " << e.what();
3054 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3055 xmlOut.addTextElementToData(
"Error", ss.str());
3074 void ConfigurationGUISupervisor::handleFillGetTreeNodeFieldValuesXML(
3077 const std::string& groupName,
3079 const std::string& startPath,
3080 const std::string& modifiedTables,
3081 const std::string& recordList,
3082 const std::string& fieldList)
3085 setupActiveTablesXML(
3086 xmlOut, cfgMgr, groupName, groupKey, modifiedTables,
false );
3093 std::vector<std::string > fieldPaths;
3096 std::istringstream f(fieldList);
3097 std::string fieldPath;
3098 while(getline(f, fieldPath,
','))
3102 __SUP_COUT__ << fieldList << __E__;
3107 std::istringstream f(recordList);
3108 std::string recordUID;
3109 while(getline(f, recordUID,
','))
3113 __SUP_COUT__ <<
"recordUID " << recordUID << __E__;
3115 xercesc::DOMElement* parentEl =
3116 xmlOut.addTextElementToData(
"fieldValues", recordUID);
3119 for(
const auto& fieldPath : fieldPaths)
3125 cfgMgr->
getNode(startPath +
"/" + recordUID +
"/" + fieldPath);
3137 catch(std::runtime_error& e)
3139 __SUP_SS__ << (
"Error getting field values!\n\n" + std::string(e.what()))
3141 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3142 xmlOut.addTextElementToData(
"Error", ss.str());
3146 __SUP_SS__ << (
"Error getting field values!\n\n") << __E__;
3151 catch(
const std::exception& e)
3153 ss <<
"Exception message: " << e.what();
3158 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3159 xmlOut.addTextElementToData(
"Error", ss.str());
3182 void ConfigurationGUISupervisor::handleFillTreeNodeCommonFieldsXML(
3185 const std::string& groupName,
3187 const std::string& startPath,
3189 const std::string& modifiedTables,
3190 const std::string& recordList,
3191 const std::string& fieldList)
3194 setupActiveTablesXML(
3195 xmlOut, cfgMgr, groupName, groupKey, modifiedTables,
false );
3199 xercesc::DOMElement* parentEl = xmlOut.addTextElementToData(
"fields", startPath);
3203 __SUP_SS__ <<
"Depth of search must be greater than 0." << __E__;
3204 __SUP_COUT__ << ss.str();
3213 std::vector<ConfigurationTree::RecordField> retFieldList;
3219 __SUP_SS__ <<
"Start path was a disconnected link node!" << __E__;
3225 std::vector<std::string > fieldAcceptList, fieldRejectList;
3230 std::istringstream f(fieldList);
3231 std::string fieldPath, decodedFieldPath;
3232 while(getline(f, fieldPath,
','))
3236 if(decodedFieldPath[0] ==
'!')
3237 fieldRejectList.push_back(decodedFieldPath.substr(1));
3239 fieldAcceptList.push_back(decodedFieldPath);
3241 __SUP_COUT__ << fieldList << __E__;
3242 for(
auto& field : fieldAcceptList)
3243 __SUP_COUT__ <<
"fieldAcceptList " << field << __E__;
3244 for(
auto& field : fieldRejectList)
3245 __SUP_COUT__ <<
"fieldRejectList " << field << __E__;
3249 std::vector<std::string > records;
3250 if(recordList ==
"*")
3254 __SUP_COUT__ <<
"Translating wildcard..." << __E__;
3255 for(
auto& record : records)
3256 __SUP_COUT__ <<
"recordList " << record << __E__;
3258 else if(recordList !=
"")
3262 std::istringstream f(recordList);
3263 std::string recordStr;
3264 while(getline(f, recordStr,
','))
3268 __SUP_COUT__ << recordList << __E__;
3269 for(
auto& record : records)
3270 __SUP_COUT__ <<
"recordList " << record << __E__;
3276 records, fieldAcceptList, fieldRejectList, depth);
3280 xercesc::DOMElement* parentTypeEl;
3281 for(
const auto& fieldInfo : retFieldList)
3284 "FieldTableName", fieldInfo.tableName_, parentEl);
3286 "FieldColumnName", fieldInfo.columnName_, parentEl);
3288 "FieldRelativePath", fieldInfo.relativePath_, parentEl);
3290 "FieldColumnType", fieldInfo.columnInfo_->getType(), parentEl);
3292 "FieldColumnDataType", fieldInfo.columnInfo_->getDataType(), parentEl);
3294 fieldInfo.columnInfo_->getDefaultValue(),
3301 auto dataChoices = fieldInfo.columnInfo_->getDataChoices();
3303 "FieldColumnDataChoice",
3304 fieldInfo.columnInfo_->getDefaultValue(),
3306 for(
const auto& dataChoice : dataChoices)
3308 "FieldColumnDataChoice", dataChoice, parentTypeEl);
3311 catch(std::runtime_error& e)
3313 __SUP_SS__ << (
"Error getting common fields!\n\n" + std::string(e.what()))
3315 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3316 xmlOut.addTextElementToData(
"Error", ss.str());
3320 __SUP_SS__ << (
"Error getting common fields!\n\n") << __E__;
3325 catch(
const std::exception& e)
3327 ss <<
"Exception message: " << e.what();
3332 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3333 xmlOut.addTextElementToData(
"Error", ss.str());
3365 void ConfigurationGUISupervisor::handleFillUniqueFieldValuesForRecordsXML(
3368 const std::string& groupName,
3370 const std::string& startPath,
3371 const std::string& modifiedTables,
3372 const std::string& recordList,
3373 const std::string& fieldList)
3376 setupActiveTablesXML(
3377 xmlOut, cfgMgr, groupName, groupKey, modifiedTables,
false );
3383 if(startPath ==
"/")
3389 __SUP_SS__ <<
"Start path was a disconnected link node!" << __E__;
3390 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3395 std::vector<std::string > records;
3396 if(recordList ==
"*")
3400 __SUP_COUT__ <<
"Translating wildcard..." << __E__;
3401 for(
auto& record : records)
3402 __SUP_COUT__ <<
"recordList " << record << __E__;
3404 else if(recordList !=
"")
3408 std::istringstream f(recordList);
3409 std::string recordStr;
3410 while(getline(f, recordStr,
','))
3414 __SUP_COUT__ << recordList << __E__;
3415 for(
auto& record : records)
3416 __SUP_COUT__ <<
"recordList " << record << __E__;
3421 std::vector<std::string > fieldsToGet;
3426 if(fieldList ==
"AUTO")
3431 __SUP_COUT__ <<
"Getting AUTO filter fields!" << __E__;
3433 std::vector<ConfigurationTree::RecordField> retFieldList;
3434 std::vector<std::string > fieldAcceptList,
3436 fieldRejectList.push_back(
"*" + TableViewColumnInfo::COL_NAME_COMMENT);
3438 records, fieldAcceptList, fieldRejectList, 5,
true );
3440 for(
const auto& retField : retFieldList)
3441 fieldsToGet.push_back(retField.relativePath_ + retField.columnName_);
3445 std::istringstream f(fieldList);
3446 std::string fieldPath;
3447 while(getline(f, fieldPath,
','))
3451 __SUP_COUTV__(fieldList);
3460 std::string fieldGroupIDChildLinkIndex;
3461 for(
auto& field : fieldsToGet)
3463 __SUP_COUTV__(field);
3465 xercesc::DOMElement* parentEl =
3466 xmlOut.addTextElementToData(
"field", field);
3472 std::set<std::string > uniqueValues =
3474 records, field, &fieldGroupIDChildLinkIndex);
3476 if(fieldGroupIDChildLinkIndex !=
"")
3478 "childLinkIndex", fieldGroupIDChildLinkIndex, parentEl);
3480 for(
auto& uniqueValue : uniqueValues)
3482 __SUP_COUT__ <<
"uniqueValue " << uniqueValue << __E__;
3489 catch(std::runtime_error& e)
3491 __SUP_SS__ <<
"Error getting unique field values from path '" << startPath
3492 <<
"' and field list '" << fieldList <<
"!'\n\n"
3493 << e.what() << __E__;
3494 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3495 xmlOut.addTextElementToData(
"Error", ss.str());
3499 __SUP_SS__ <<
"Error getting unique field values from path '" << startPath
3500 <<
"' and field list '" << fieldList <<
"!'\n\n"
3506 catch(
const std::exception& e)
3508 ss <<
"Exception message: " << e.what();
3513 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3514 xmlOut.addTextElementToData(
"Error", ss.str());
3538 void ConfigurationGUISupervisor::handleFillTreeViewXML(
3541 const std::string& groupName,
3543 const std::string& startPath,
3545 bool hideStatusFalse,
3546 const std::string& modifiedTables,
3547 const std::string& filterList,
3548 const std::string& diffGroupName ,
3551 __SUP_COUTT__ <<
"get Tree View: " << groupName <<
"(" << groupKey <<
")" << __E__;
3583 bool doDiff = (diffGroupName !=
"" && !diffGroupKey.
isInvalid());
3588 std::string diffAccumulateErrors;
3596 __SUP_COUT__ <<
"cfgMgr " << activeTable.first <<
"-v" << activeTable.second
3613 __SUP_COUT__ <<
"cfgMgr " << activeTable.first <<
"-v" << activeTable.second
3616 __SUP_COUTT__ <<
"Diff Group tables loaded." << __E__;
3618 *cfgMgr, diffMemberMap, diffGroupName, diffGroupKey);
3619 __SUP_COUTT__ <<
"Diff Group tables copied to local diff config manager."
3623 for(
auto& memberPair : diffMemberMap)
3625 ->setActiveView(memberPair.second);
3627 for(
const auto& lastGroupLoaded : cfgMgr->getLastTableGroups())
3628 __SUP_COUT__ <<
"cfgMgr Last loaded " << lastGroupLoaded.first <<
": "
3629 << lastGroupLoaded.second.first.first <<
"("
3630 << lastGroupLoaded.second.first.second <<
")";
3632 for(
const auto& lastGroupLoaded : diffCfgMgr->getLastTableGroups())
3633 __SUP_COUT__ <<
"diffCfgMgr Last loaded " << lastGroupLoaded.first <<
": "
3634 << lastGroupLoaded.second.first.first <<
"("
3635 << lastGroupLoaded.second.first.second <<
")";
3638 if(diffCfgMgr->getLastTableGroups().size() == 1)
3640 __SUP_COUT__ <<
"Type already loaded to diff = "
3641 << diffCfgMgr->getLastTableGroups().begin()->first << __E__;
3644 auto groupTypeToLoad = ConfigurationManager::GROUP_TYPE_NAME_CONTEXT;
3645 if(diffCfgMgr->getLastTableGroups().begin()->first ==
3646 ConfigurationManager::GROUP_TYPE_NAME_CONTEXT)
3647 groupTypeToLoad = ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION;
3648 else if(diffCfgMgr->getLastTableGroups().begin()->first ==
3649 ConfigurationManager::GROUP_TYPE_NAME_CONFIGURATION)
3650 groupTypeToLoad = ConfigurationManager::GROUP_TYPE_NAME_CONTEXT;
3653 <<
"Loading " << groupTypeToLoad
3654 << cfgMgr->getLastTableGroups().at(groupTypeToLoad).first.first <<
"("
3655 << cfgMgr->getLastTableGroups().at(groupTypeToLoad).first.second
3660 cfgMgr->getLastTableGroups().at(groupTypeToLoad).second,
3661 cfgMgr->getLastTableGroups().at(groupTypeToLoad).first.first,
3662 cfgMgr->getLastTableGroups().at(groupTypeToLoad).first.second);
3665 for(
auto& memberPair :
3666 cfgMgr->getLastTableGroups().at(groupTypeToLoad).second)
3668 ->setActiveView(memberPair.second);
3676 __SUP_COUTT__ <<
"cfgMgr " << activeTable.first <<
"-v" << activeTable.second
3679 __SUP_COUTT__ <<
"diffCfgMgr " << activeTable.first <<
"-v"
3680 << activeTable.second << __E__;
3682 __SUP_COUTT__ <<
"Diff Group tables are setup: " << diffAccumulateErrors << __E__;
3687 bool usingActiveGroups = (groupName ==
"" || groupKey.
isInvalid());
3690 std::string accumulatedErrors =
"";
3691 setupActiveTablesXML(
3704 if(memberMap.size() > ConfigurationManager::getFixedContextMemberNames().size() +
3706 && startPath ==
"/")
3708 __COUTT__ <<
"Checking for orphaned tables..." << __E__;
3711 std::set<std::string > linkingTables;
3716 __COUTS__(30) <<
"Table " << tableInfo.first << __E__;
3717 if(!tableInfo.second.tablePtr_->isActive())
3720 __COUTS__(30) <<
"Table active " << tableInfo.first << __E__;
3722 const TableView& view = tableInfo.second.tablePtr_->getView();
3724 bool addedThisTable =
false;
3725 for(
unsigned int col = 0; col < view.getNumberOfColumns(); ++col)
3727 if(!view.getColumnInfo(col).isChildLink())
3730 __COUTS__(30) <<
"Table " << tableInfo.first
3731 <<
" col: " << view.getColumnInfo(col).getName() << __E__;
3733 for(
unsigned int r = 0; r < view.getNumberOfRows(); ++r)
3735 if(view.getDataView()[r][col] ==
"" ||
3736 view.getDataView()[r][col] ==
3737 TableViewColumnInfo::DATATYPE_STRING_DEFAULT ||
3738 view.getDataView()[r][col] ==
3739 TableViewColumnInfo::DATATYPE_STRING_ALT_DEFAULT)
3744 linkingTables.emplace(tableInfo.first);
3745 addedThisTable =
true;
3747 linkingTables.emplace(
3748 view.getDataView()[r][col]);
3754 std::string missingTables =
"";
3755 for(
const auto& member : memberMap)
3758 if(linkingTables.find(member.first) != linkingTables.end())
3761 if(missingTables.size())
3762 missingTables +=
", ";
3763 missingTables += member.first;
3766 if(missingTables.size())
3768 __COUTV__(missingTables);
3769 std::stringstream ss;
3770 ss <<
"The following member tables of table group '" << groupName <<
"("
3772 <<
")' were identified as possibly orphaned (i.e. no active tables link "
3773 "to these tables, and these tables have no links to other tables):\n\n"
3774 << missingTables <<
".\n"
3776 xmlOut.addTextElementToData(
"NoTreeLinkWarning", ss.str());
3780 if(accumulatedErrors !=
"")
3782 xmlOut.addTextElementToData(
"Warning", accumulatedErrors);
3784 __SUP_COUT__ <<
"Active tables are setup. Warning string: '" << accumulatedErrors
3787 __SUP_COUT__ <<
"Active table versions: "
3792 __SUP_COUTT__ <<
"Active tables are setup. No issues found." << __E__;
3793 __SUP_COUTT__ <<
"Active table versions: "
3799 xercesc::DOMElement* parentEl = xmlOut.addTextElementToData(
"tree", startPath);
3804 std::vector<std::pair<std::string, ConfigurationTree>> rootMap;
3805 std::map<std::string, ConfigurationTree> diffRootMap;
3807 if(startPath ==
"/")
3811 std::string accumulateTreeErrs;
3813 if(usingActiveGroups)
3814 rootMap = cfgMgr->
getChildren(0, &accumulateTreeErrs);
3816 rootMap = cfgMgr->
getChildren(&memberMap, &accumulateTreeErrs);
3821 diffCfgMgr->
getChildrenMap(&diffMemberMap, &diffAccumulateErrors);
3822 __SUP_COUTV__(diffRootMap.size());
3823 for(
auto& diffChild : diffRootMap)
3824 __SUP_COUTV__(diffChild.first);
3827 __SUP_COUTV__(accumulateTreeErrs);
3829 if(accumulateTreeErrs !=
"")
3830 xmlOut.addTextElementToData(
"TreeErrors", accumulateTreeErrs);
3835 cfgMgr->
getNode(startPath,
true );
3838 xmlOut.addTextElementToData(
"DisconnectedStartNode",
"1");
3843 std::map<std::string , std::string > filterMap;
3847 std::set<char>({
';'}) ,
3848 std::set<char>({
'='}) );
3862 __SUP_COUTT__ <<
"Diff Group disconnected node." << __E__;
3867 catch(
const std::runtime_error& e)
3870 __SUP_COUTT__ <<
"Diff Group node does not exist." << __E__;
3877 for(
auto& treePair : rootMap)
3879 treePair.second, depth - 1, xmlOut, parentEl, hideStatusFalse);
3883 __SUP_COUTT__ <<
"Diff Tree recursive handling." << __E__;
3886 std::set<std::string > rootMapToSearch;
3887 for(
const auto& rootMember : rootMap)
3888 rootMapToSearch.emplace(rootMember.first);
3890 std::stringstream rootSs;
3891 for(
const auto& rootMember : rootMap)
3892 rootSs <<
", " << rootMember.first;
3895 std::stringstream diffRootSs;
3896 for(
const auto& diffMember : diffRootMap)
3898 diffRootSs <<
", " << diffMember.first <<
":"
3899 << diffMember.second.getNodeType();
3900 if(rootMapToSearch.find(diffMember.first) ==
3904 std::stringstream missingSs;
3905 missingSs << diffMember.first <<
3907 " <<< Only in " << diffGroupName <<
"(" << diffGroupKey
3910 "diffNodeMissing", missingSs.str(), parentEl);
3913 if(diffMember.second.getNodeType() ==
"UIDLinkNode")
3924 __SUP_COUTT__ <<
"diff map " << diffRootSs.str() << __E__;
3925 __SUP_COUTT__ <<
"root map " << rootSs.str() << __E__;
3927 __SUP_COUTT__ <<
"\t\t" << diffMember.second.getValueName() <<
": "
3928 << diffMember.second.getValueAsString() << __E__;
3930 __SUP_COUTT__ << diffMember.second.nodeDump();
3934 __SUP_COUTT__ <<
"diff map " << diffRootSs.str() << __E__;
3935 __SUP_COUTT__ <<
"root map " << rootSs.str() << __E__;
3938 for(
auto& treePair : rootMap)
3940 if(diffRootMap.find(treePair.first) == diffRootMap.end())
3942 __SUP_COUTT__ <<
"Diff Tree recursive handling... " << treePair.first
3955 __SUP_COUTT__ <<
"Diff Tree recursive handling... " << treePair.first
3957 recursiveTreeToXML(treePair.second,
3962 diffRootMap.at(treePair.first));
3967 catch(std::runtime_error& e)
3969 __SUP_SS__ <<
"Error detected generating XML tree!\n\n " << e.what() << __E__;
3970 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3971 xmlOut.addTextElementToData(
"Error", ss.str());
3975 __SUP_SS__ <<
"Error detected generating XML tree!" << __E__;
3980 catch(
const std::exception& e)
3982 ss <<
"Exception message: " << e.what();
3987 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3988 xmlOut.addTextElementToData(
"Error", ss.str());
3998 void ConfigurationGUISupervisor::recursiveTreeToXML(
4002 xercesc::DOMElement* parentEl,
4003 bool hideStatusFalse,
4004 std::optional<std::reference_wrapper<const ConfigurationTree>> diffTree)
4014 if(diffTree.has_value() &&
4015 t.
getValueName() != TableViewColumnInfo::COL_NAME_COMMENT &&
4016 t.
getValueName() != TableViewColumnInfo::COL_NAME_AUTHOR &&
4017 t.
getValueName() != TableViewColumnInfo::COL_NAME_CREATION)
4019 __COUTS__(30) <<
"\t\t diff type " << diffTree->get().getNodeType() << __E__;
4021 if(diffTree->get().isValueNode())
4023 __COUTS__(30) <<
"\t" << diffTree->get().getValueAsString() <<
" ? "
4025 __COUTS__(30) <<
"\t" << diffTree->get().getTableName() <<
"-v"
4026 << diffTree->get().getTableVersion() <<
" ? "
4031 std::stringstream missingSs;
4032 auto diffGroupPair =
4033 diffTree->get().getConfigurationManager()->getGroupOfLoadedTable(
4034 diffTree->get().getTableName());
4035 missingSs <<
"<<< '" << diffTree->get().getValueAsString() <<
"' in "
4036 << diffGroupPair.first <<
"(" << diffGroupPair.second
4043 std::stringstream missingSs;
4045 auto diffGroupPair =
4046 diffTree->get().getConfigurationManager()->getGroupOfLoadedTable(
4048 missingSs <<
"<<< Path not found in " << diffGroupPair.first <<
"("
4049 << diffGroupPair.second <<
") >>>";
4063 if(t.
getValueType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA ||
4064 t.
getValueType() == TableViewColumnInfo::TYPE_BITMAP_DATA)
4069 for(
const auto& choice : choices)
4086 if(diffTree.has_value())
4088 __COUTS__(30) <<
"\t\t diff type " << diffTree->get().getNodeType()
4095 std::stringstream missingSs;
4097 auto diffGroupPair =
4098 diffTree->get().getConfigurationManager()->getGroupOfLoadedTable(
4100 missingSs <<
"<<< Path not found in " << diffGroupPair.first <<
"("
4101 << diffGroupPair.second <<
") >>>";
4106 __COUTS__(30) <<
"\t\t diff isDisconnected "
4107 << diffTree->get().isDisconnected() << __E__;
4109 std::stringstream missingSs;
4111 auto diffGroupPair =
4112 diffTree->get().getConfigurationManager()->getGroupOfLoadedTable(
4114 missingSs <<
"<<< Link is "
4115 << (diffTree->get().isDisconnected() ?
"DISCONNECTED"
4117 <<
" in " << diffGroupPair.first <<
"("
4118 << diffGroupPair.second <<
") >>>";
4125 std::stringstream missingSs;
4127 auto diffGroupPair =
4128 diffTree->get().getConfigurationManager()->getGroupOfLoadedTable(
4130 missingSs <<
"<<< Link is "
4131 << (diffTree->get().isUIDLinkNode() ?
"a UID Link"
4133 <<
" in " << diffGroupPair.first <<
"("
4134 << diffGroupPair.second <<
") >>>";
4139 diffTree->get().getValueAsString())
4142 std::stringstream missingSs;
4144 auto diffGroupPair =
4145 diffTree->get().getConfigurationManager()->getGroupOfLoadedTable(
4147 missingSs <<
"<<< Link to '" << diffTree->get().getValueAsString()
4148 <<
"' in " << diffGroupPair.first <<
"("
4149 << diffGroupPair.second <<
") >>>";
4155 std::stringstream missingSs;
4158 auto dtchildren = diffTree->get().getChildrenMap();
4159 missingSs <<
"<<< Group link";
4160 if(tchildren.size() != dtchildren.size())
4161 missingSs <<
" has " << tchildren.size() <<
" vs "
4162 << dtchildren.size() <<
" children..";
4163 for(
auto& tchild : tchildren)
4164 if(dtchildren.find(tchild.first) == dtchildren.end())
4165 missingSs <<
" '" << tchild.first <<
"' missing..";
4166 for(
auto& dtchild : dtchildren)
4167 if(tchildren.find(dtchild.first) == tchildren.end())
4168 missingSs <<
" '" << dtchild.first <<
"' present...";
4171 if(missingSs.str().length() > std::string(
"<<< Group link").length())
4173 auto diffGroupPair =
4175 .getConfigurationManager()
4176 ->getGroupOfLoadedTable(diffTree->get().getTableName());
4177 missingSs <<
" in " << diffGroupPair.first <<
"("
4178 << diffGroupPair.second <<
") >>>";
4180 "nodeDiff", missingSs.str(), parentEl);
4208 xercesc::DOMElement* choicesParentEl =
4214 __COUTS__(30) <<
"choices.size() " << choices.size() << __E__;
4216 for(
const auto& choice : choices)
4238 xercesc::DOMElement* choicesParentEl =
4242 for(
const auto& choice : choices)
4249 bool returnNode =
true;
4263 "nodeStatus", t.
isEnabled() ?
"1" :
"0", parentEl);
4266 if(diffTree.has_value())
4269 <<
"\t\t diff type " << diffTree->get().getNodeType() << __E__;
4278 auto diffGroupPair =
4280 .getConfigurationManager()
4282 missingSs <<
"<<< Not in " << diffGroupPair.first <<
"("
4283 << diffGroupPair.second <<
") >>>";
4285 "nodeDiff", missingSs.str(), parentEl);
4319 void ConfigurationGUISupervisor::handleGetLinkToChoicesXML(
4322 const std::string& linkToTableName,
4324 const std::string& linkIdType,
4325 const std::string& linkIndex,
4326 const std::string& linkInitId)
4339 const std::string& tableName = linkToTableName;
4344 table->setActiveView(version);
4348 __SUP_COUT__ <<
"Failed to find stored version, so attempting to load version: "
4349 << version << __E__;
4353 if(version != table->getViewVersion())
4355 __SUP_SS__ <<
"Target table version (" << version
4356 <<
") is not the currently active version (" << table->getViewVersion()
4357 <<
". Try refreshing the tree." << __E__;
4358 __SUP_COUT_WARN__ << ss.str();
4362 __SUP_COUT__ <<
"Active version is " << table->getViewVersion() << __E__;
4364 if(linkIdType ==
"UID")
4367 unsigned int col = table->getView().getColUID();
4368 for(
unsigned int row = 0; row < table->getView().getNumberOfRows(); ++row)
4369 xmlOut.addTextElementToData(
"linkToChoice",
4370 table->getView().getDataView()[row][col]);
4372 else if(linkIdType ==
"GroupID")
4378 __SUP_COUTV__(linkIndex);
4379 __SUP_COUTV__(linkInitId);
4381 std::set<std::string> setOfGroupIDs =
4382 table->getView().getSetOfGroupIDs(linkIndex);
4387 bool foundInitId =
false;
4388 for(
const auto& groupID : setOfGroupIDs)
4390 if(!foundInitId && linkInitId == groupID)
4393 xmlOut.addTextElementToData(
"linkToChoice", groupID);
4397 xmlOut.addTextElementToData(
"linkToChoice", linkInitId);
4400 unsigned int col = table->getView().getColUID();
4401 for(
unsigned int row = 0; row < table->getView().getNumberOfRows(); ++row)
4403 xmlOut.addTextElementToData(
"groupChoice",
4404 table->getView().getDataView()[row][col]);
4405 if(table->getView().isEntryInGroup(row, linkIndex, linkInitId))
4406 xmlOut.addTextElementToData(
"groupMember",
4407 table->getView().getDataView()[row][col]);
4412 __SUP_SS__ <<
"Unrecognized linkIdType '" << linkIdType <<
".'" << __E__;
4416 catch(std::runtime_error& e)
4418 __SUP_SS__ <<
"Error detected saving tree node!\n\n " << e.what() << __E__;
4419 __SUP_COUT_ERR__ <<
"\n" << ss.str() << __E__;
4420 xmlOut.addTextElementToData(
"Error", ss.str());
4424 __SUP_SS__ <<
"Error detected saving tree node!\n\n " << __E__;
4429 catch(
const std::exception& e)
4431 ss <<
"Exception message: " << e.what();
4436 __SUP_COUT_ERR__ <<
"\n" << ss.str() << __E__;
4437 xmlOut.addTextElementToData(
"Error", ss.str());
4442 void ConfigurationGUISupervisor::handleMergeGroupsXML(
4445 const std::string& groupANameContext,
4447 const std::string& groupBNameContext,
4449 const std::string& groupANameConfig,
4451 const std::string& groupBNameConfig,
4453 const std::string& author,
4454 const std::string& mergeApproach)
4457 __SUP_COUT__ <<
"Merging context group pair " << groupANameContext <<
" ("
4458 << groupAKeyContext <<
") & " << groupBNameContext <<
" ("
4459 << groupBKeyContext <<
") and table group pair " << groupANameConfig
4460 <<
" (" << groupAKeyConfig <<
") & " << groupBNameConfig <<
" ("
4461 << groupBKeyConfig <<
") with approach '" << mergeApproach << __E__;
4477 if(!(mergeApproach ==
"Rename" || mergeApproach ==
"Replace" ||
4478 mergeApproach ==
"Skip"))
4480 __SS__ <<
"Error! Invalid merge approach '" << mergeApproach <<
".'" << __E__;
4484 std::map<std::string ,
TableVersion > memberMapAContext,
4485 memberMapBContext, memberMapAConfig, memberMapBConfig;
4488 bool skippingContextPair =
false;
4489 bool skippingConfigPair =
false;
4490 if(groupANameContext.size() == 0 || groupANameContext[0] ==
' ' ||
4491 groupBNameContext.size() == 0 || groupBNameContext[0] ==
' ')
4493 skippingContextPair =
true;
4494 __SUP_COUTV__(skippingContextPair);
4496 if(groupANameConfig.size() == 0 || groupANameConfig[0] ==
' ' ||
4497 groupBNameConfig.size() == 0 || groupBNameConfig[0] ==
' ')
4499 skippingConfigPair =
true;
4500 __SUP_COUTV__(skippingConfigPair);
4504 if(!skippingContextPair)
4537 if(!skippingConfigPair)
4574 std::map<std::pair<std::string , std::string >,
4578 std::pair<std::string ,
4579 std::pair<std::string , std::string >>,
4581 groupidConversionMap;
4583 std::stringstream mergeReport;
4584 mergeReport <<
"======================================" << __E__;
4586 mergeReport <<
"Merging context group pair " << groupANameContext <<
" ("
4587 << groupAKeyContext <<
") & " << groupBNameContext <<
" ("
4588 << groupBKeyContext <<
") and table group pair " << groupANameConfig
4589 <<
" (" << groupAKeyConfig <<
") & " << groupBNameConfig <<
" ("
4590 << groupBKeyConfig <<
") with approach '" << mergeApproach << __E__;
4591 mergeReport <<
"======================================" << __E__;
4595 for(
unsigned int i = 0; i < 2; ++i)
4597 if(i == 0 && mergeApproach !=
"Rename")
4601 for(
unsigned int j = 0; j < 2; ++j)
4603 if(j == 0 && skippingContextPair)
4605 __COUT__ <<
"Skipping context pair..." << __E__;
4608 else if(j == 1 && skippingConfigPair)
4610 __COUT__ <<
"Skipping table pair..." << __E__;
4615 j == 0 ? memberMapAContext : memberMapAConfig;
4618 j == 0 ? memberMapBContext : memberMapBConfig;
4621 __COUT__ <<
"Context pair..." << __E__;
4623 __COUT__ <<
"Table pair..." << __E__;
4625 __COUT__ <<
"Starting member map B scan." << __E__;
4626 for(
const auto& bkey : memberMapBref)
4628 __SUP_COUTV__(bkey.first);
4630 if(memberMapAref.find(bkey.first) == memberMapAref.end())
4632 mergeReport <<
"\n'" << mergeApproach <<
"'-Missing table '"
4633 << bkey.first <<
"' A=v" << -1 <<
", adding B=v"
4634 << bkey.second << __E__;
4637 memberMapAref[bkey.first] = bkey.second;
4639 else if(memberMapAref[bkey.first] != bkey.second)
4642 __SUP_COUTV__(memberMapAref[bkey.first]);
4643 __SUP_COUTV__(bkey.second);
4648 __SUP_COUT__ <<
"Got table." << __E__;
4652 ->getVersionedTableByName(bkey.first,
4653 memberMapAref[bkey.first])
4659 mergeApproach ==
"Rename"
4660 ? TableBase::MergeApproach::RENAME
4661 : (mergeApproach ==
"Replace"
4662 ? TableBase::MergeApproach::REPLACE
4663 : TableBase::MergeApproach::SKIP),
4665 groupidConversionMap,
4668 table->getTableName() ==
4669 ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME
4675 __SUP_COUTV__(newVersion);
4693 catch(std::runtime_error& e)
4696 <<
"There was an error saving the '"
4697 << table->getTableName()
4698 <<
"' merge result to a persistent table version. "
4699 <<
"Perhaps you can modify this table in one of the "
4700 "groups to resolve this issue, and then re-merge."
4701 << __E__ << e.what();
4705 __SUP_COUTV__(newVersion);
4707 memberMapAref[bkey.first] = newVersion;
4716 if(!skippingContextPair)
4718 __SUP_COUT__ <<
"New context member map complete." << __E__;
4725 "Merger of group " + groupANameContext +
" (" + groupAKeyContext.
toString() +
4726 ") and " + groupBNameContext +
" (" + groupBKeyContext.
toString() +
").");
4729 xmlOut.addTextElementToData(
"ContextGroupName", groupANameContext);
4730 xmlOut.addTextElementToData(
"ContextGroupKey", newKeyContext.
toString());
4732 if(!skippingConfigPair)
4734 __SUP_COUT__ <<
"New table member map complete." << __E__;
4741 "Merger of group " + groupANameConfig +
" (" + groupAKeyConfig.
toString() +
4742 ") and " + groupBNameConfig +
" (" + groupBKeyConfig.
toString() +
").");
4745 xmlOut.addTextElementToData(
"ConfigGroupName", groupANameConfig);
4746 xmlOut.addTextElementToData(
"ConfigGroupKey", newKeyConfig.
toString());
4751 std::string mergeReportBasePath = std::string(__ENV__(
"USER_DATA"));
4752 std::string mergeReportPath =
"/ServiceData/";
4754 mkdir((mergeReportBasePath + mergeReportPath).c_str(), 0755);
4755 mergeReportPath +=
"ConfigurationGUI_mergeReports/";
4757 mkdir((mergeReportBasePath + mergeReportPath).c_str(), 0755);
4760 "merge_" + std::to_string(time(0)) +
"_" + std::to_string(clock()) +
".txt";
4761 __SUP_COUTV__(mergeReportPath);
4763 FILE* fp = fopen((mergeReportBasePath + mergeReportPath).c_str(),
"w");
4766 fprintf(fp,
"%s", mergeReport.str().c_str());
4768 xmlOut.addTextElementToData(
"MergeReportFile",
4769 "/$USER_DATA/" + mergeReportPath);
4772 xmlOut.addTextElementToData(
"MergeReportFile",
"FILE FAILURE");
4776 catch(std::runtime_error& e)
4778 __SUP_SS__ <<
"Error merging context group pair " << groupANameContext <<
" ("
4779 << groupAKeyContext <<
") & " << groupBNameContext <<
" ("
4780 << groupBKeyContext <<
") and table group pair " << groupANameConfig
4781 <<
" (" << groupAKeyConfig <<
") & " << groupBNameConfig <<
" ("
4782 << groupBKeyConfig <<
") with approach '" << mergeApproach <<
"': \n\n"
4783 << e.what() << __E__;
4784 __SUP_COUT_ERR__ <<
"\n" << ss.str() << __E__;
4785 xmlOut.addTextElementToData(
"Error", ss.str());
4789 __SUP_SS__ <<
"Unknown error merging context group pair " << groupANameContext <<
" ("
4790 << groupAKeyContext <<
") & " << groupBNameContext <<
" ("
4791 << groupBKeyContext <<
") and table group pair " << groupANameConfig
4792 <<
" (" << groupAKeyConfig <<
") & " << groupBNameConfig <<
" ("
4793 << groupBKeyConfig <<
") with approach '" << mergeApproach <<
".' \n\n";
4798 catch(
const std::exception& e)
4800 ss <<
"Exception message: " << e.what();
4805 __SUP_COUT_ERR__ <<
"\n" << ss.
str() << __E__;
4806 xmlOut.addTextElementToData(
"Error", ss.str());
4811 void ConfigurationGUISupervisor::handleSavePlanCommandSequenceXML(
4814 const std::string& groupName,
4816 const std::string& modifiedTables,
4817 const std::string& author,
4818 const std::string& planName,
4819 const std::string& commandString)
4822 __COUT__ <<
"handleSavePlanCommandSequenceXML " << planName << __E__;
4825 setupActiveTablesXML(xmlOut,
4844 for(
const auto& commandPair : IterateTable::commandToTableMap_)
4845 if(commandPair.second !=
"")
4846 commandTableToEditMap.emplace(std::pair<std::string, TableEditStruct>(
4863 std::string groupName = planName +
"-Plan";
4864 __SUP_COUT__ <<
"Handling commands for group " << groupName << __E__;
4866 unsigned int groupIdCol =
4867 planTable.tableView_->findCol(IterateTable::planTableCols_.GroupID_);
4868 unsigned int cmdTypeCol =
4869 planTable.tableView_->findCol(IterateTable::planTableCols_.CommandType_);
4871 unsigned int targetGroupIdCol =
4872 targetTable.tableView_->findCol(IterateTable::targetCols_.GroupID_);
4873 unsigned int targetTableCol =
4874 targetTable.tableView_->findCol(IterateTable::targetCols_.TargetLink_);
4875 unsigned int targetUIDCol =
4876 targetTable.tableView_->findCol(IterateTable::targetCols_.TargetLinkUID_);
4878 std::string groupLinkIndex =
4879 planTable.tableView_->getColumnInfo(groupIdCol).getChildLinkIndex();
4880 __SUP_COUT__ <<
"groupLinkIndex: " << groupLinkIndex << __E__;
4882 std::pair<
unsigned int ,
unsigned int > commandUidLink;
4885 planTable.tableView_->getChildLink(
4886 planTable.tableView_->findCol(IterateTable::planTableCols_.CommandLink_),
4891 unsigned int cmdRow, cmdCol;
4892 std::string targetGroupName;
4896 std::string targetUID, cmdType;
4898 for(
unsigned int row = 0; row < planTable.tableView_->getNumberOfRows();
4901 targetUID = planTable.tableView_
4902 ->getDataView()[row][planTable.tableView_->getColUID()];
4903 __SUP_COUT__ <<
"targetUID: " << targetUID << __E__;
4906 if(planTable.tableView_->isEntryInGroup(row, groupLinkIndex, groupName))
4908 __SUP_COUT__ <<
"Removing." << __E__;
4912 cmdType = planTable.tableView_->getDataView()[row][cmdTypeCol];
4913 auto cmdTypeTableIt = IterateTable::commandToTableMap_.find(cmdType);
4914 if(cmdTypeTableIt != IterateTable::commandToTableMap_.end() &&
4915 cmdTypeTableIt->second !=
4919 commandTableToEditMap.at(cmdTypeTableIt->second);
4920 cmdRow = cmdTypeTableEdit.tableView_->findRow(
4921 cmdTypeTableEdit.tableView_->getColUID(),
4922 planTable.tableView_
4923 ->getDataView()[row][commandUidLink.second]);
4930 cmdCol = cmdTypeTableEdit.tableView_->findCol(
4931 IterateTable::commandTargetCols_.TargetsLinkGroupID_);
4932 targetGroupName = cmdTypeTableEdit.tableView_
4933 ->getDataView()[cmdRow][cmdCol];
4935 for(
unsigned int trow = 0;
4936 trow < targetTable.tableView_->getNumberOfRows();
4940 if(targetTable.tableView_->isEntryInGroup(
4942 cmdTypeTableEdit.tableView_->getColumnInfo(cmdCol)
4943 .getChildLinkIndex(),
4946 __SUP_COUT__ <<
"Removing target." << __E__;
4948 if(targetTable.tableView_->removeRowFromGroup(
4959 __SUP_COUT__ <<
"No targets." << __E__;
4964 cmdTypeTableEdit.tableView_->deleteRow(cmdRow);
4970 if(planTable.tableView_->removeRowFromGroup(
4971 row, groupIdCol, groupName,
true ))
4980 std::vector<IterateTable::Command> commands;
4985 std::istringstream f(commandString);
4986 std::string commandSubString, paramSubString, paramValue;
4988 while(getline(f, commandSubString,
';'))
4990 __SUP_COUTT__ <<
"commandSubString " << commandSubString << __E__;
4991 std::istringstream g(commandSubString);
4994 while(getline(g, paramSubString,
','))
4996 __SUP_COUTT__ <<
"paramSubString " << paramSubString << __E__;
4999 if(paramSubString !=
"type")
5001 __SUP_SS__ <<
"Invalid command sequence" << __E__;
5005 commands.push_back(IterateTable::Command());
5007 getline(g, paramValue,
',');
5009 __SUP_COUTT__ <<
"paramValue " << paramValue << __E__;
5010 commands.back().type_ = paramValue;
5014 getline(g, paramValue,
',');
5016 __SUP_COUTT__ <<
"paramValue " << paramValue << __E__;
5018 commands.back().params_.emplace(
5019 std::pair<std::string ,
5031 __SUP_COUT__ <<
"commands size " << commands.size() << __E__;
5038 unsigned int row, tgtRow;
5039 unsigned int targetIndex;
5040 std::string targetStr, cmdUID;
5042 for(
auto& command : commands)
5044 __SUP_COUT__ <<
"command " << command.type_ << __E__;
5045 __SUP_COUT__ <<
"table " << IterateTable::commandToTableMap_.at(command.type_)
5049 row = planTable.tableView_->addRow(
5050 author,
true ,
"planCommand");
5051 planTable.tableView_->addRowToGroup(row, groupIdCol, groupName);
5054 planTable.tableView_->setURIEncodedValue(command.type_, row, cmdTypeCol);
5057 planTable.tableView_->setValueAsString(
5058 "1", row, planTable.tableView_->getColStatus());
5061 auto cmdTypeTableIt = IterateTable::commandToTableMap_.find(command.type_);
5062 if(cmdTypeTableIt != IterateTable::commandToTableMap_.end() &&
5063 cmdTypeTableIt->second !=
5067 commandTableToEditMap.at(cmdTypeTableIt->second);
5068 __SUP_COUT__ <<
"table " << cmdTypeTableEdit.tableName_ << __E__;
5073 cmdRow = cmdTypeTableEdit.tableView_->addRow(
5074 author,
true , command.type_ +
"_COMMAND_");
5080 for(
auto& param : command.params_)
5082 __SUP_COUT__ <<
"\t param " << param.first <<
" : " << param.second
5085 if(param.first == IterateTable::targetParams_.Tables_)
5087 __SUP_COUT__ <<
"\t\t found target tables" << __E__;
5088 std::istringstream f(param.second);
5091 while(getline(f, targetStr,
'='))
5093 __SUP_COUT__ <<
"\t\t targetStr = " << targetStr << __E__;
5094 if(!command.targets_.size() ||
5095 command.targets_.back().table_ !=
"")
5097 __SUP_COUT__ <<
"\t\t make targetStr = " << targetStr
5100 command.addTarget();
5101 command.targets_.back().table_ = targetStr;
5104 command.targets_[targetIndex++].table_ = targetStr;
5110 if(param.first == IterateTable::targetParams_.UIDs_)
5112 __SUP_COUT__ <<
"\t\t found target UIDs" << __E__;
5113 std::istringstream f(param.second);
5116 while(getline(f, targetStr,
'='))
5118 __SUP_COUT__ <<
"\t\t targetStr = " << targetStr << __E__;
5119 if(!command.targets_.size() ||
5120 command.targets_.back().UID_ !=
"")
5122 __SUP_COUT__ <<
"\t\t make targetStr = " << targetStr
5125 command.addTarget();
5126 command.targets_.back().UID_ = targetStr;
5129 command.targets_[targetIndex++].UID_ = targetStr;
5134 cmdCol = cmdTypeTableEdit.tableView_->findCol(param.first);
5136 __SUP_COUT__ <<
"param col " << cmdCol << __E__;
5138 cmdTypeTableEdit.tableView_->setURIEncodedValue(
5139 param.second, cmdRow, cmdCol);
5143 cmdTypeTableEdit.tableView_
5144 ->getDataView()[cmdRow][cmdTypeTableEdit.tableView_->getColUID()];
5146 if(command.targets_.size())
5150 __SUP_COUT__ <<
"targets found for command UID=" << cmdUID << __E__;
5153 cmdCol = cmdTypeTableEdit.tableView_->findCol(
5154 IterateTable::commandTargetCols_.TargetsLink_);
5155 cmdTypeTableEdit.tableView_->setValueAsString(
5156 IterateTable::TARGET_TABLE, cmdRow, cmdCol);
5158 cmdCol = cmdTypeTableEdit.tableView_->findCol(
5159 IterateTable::commandTargetCols_.TargetsLinkGroupID_);
5160 cmdTypeTableEdit.tableView_->setValueAsString(
5161 cmdUID +
"_Targets", cmdRow, cmdCol);
5165 for(
const auto& target : command.targets_)
5167 __SUP_COUT__ << target.
table_ <<
" " << target.UID_ << __E__;
5170 tgtRow = targetTable.tableView_->addRow(
5171 author,
true ,
"commandTarget");
5172 targetTable.tableView_->addRowToGroup(
5173 tgtRow, targetGroupIdCol, cmdUID +
"_Targets");
5176 targetTable.tableView_->setValueAsString(
5177 target.table_, tgtRow, targetTableCol);
5180 targetTable.tableView_->setValueAsString(
5181 target.UID_, tgtRow, targetUIDCol);
5186 planTable.tableView_->setValueAsString(
5187 cmdTypeTableEdit.tableName_, row, commandUidLink.first);
5188 planTable.tableView_->setValueAsString(
5189 cmdUID, row, commandUidLink.second);
5191 __SUP_COUT__ <<
"linked to uid = " << cmdUID << __E__;
5201 planTable.tableView_->print();
5202 planTable.tableView_->init();
5204 __SUP_COUT__ <<
"requestType tables:" << __E__;
5206 for(
auto& modifiedConfig : commandTableToEditMap)
5208 __SUP_COUTV__(modifiedConfig.second.modified_);
5209 modifiedConfig.second.tableView_->print();
5210 modifiedConfig.second.tableView_->init();
5213 targetTable.tableView_->print();
5214 targetTable.tableView_->init();
5219 __SUP_COUT__ <<
"Handling command table errors while saving. Erasing all newly "
5225 if(planTable.createdTemporaryVersion_)
5227 __SUP_COUT__ <<
"Erasing temporary version " << planTable.tableName_ <<
"-v"
5228 << planTable.temporaryVersion_ << __E__;
5231 planTable.temporaryVersion_);
5234 if(targetTable.createdTemporaryVersion_)
5236 __SUP_COUT__ <<
"Erasing temporary version " << targetTable.tableName_ <<
"-v"
5237 << targetTable.temporaryVersion_ << __E__;
5240 targetTable.temporaryVersion_);
5243 for(
auto& modifiedConfig : commandTableToEditMap)
5245 if(modifiedConfig.second
5246 .createdTemporaryVersion_)
5248 __SUP_COUT__ <<
"Erasing temporary version "
5249 << modifiedConfig.second.tableName_ <<
"-v"
5250 << modifiedConfig.second.temporaryVersion_ << __E__;
5253 modifiedConfig.second.temporaryVersion_);
5267 planTable.tableName_,
5268 planTable.originalVersion_,
5271 planTable.temporaryVersion_,
5274 __SUP_COUT__ <<
"Final plan version is " << planTable.tableName_ <<
"-v"
5275 << finalVersion << __E__;
5280 targetTable.tableName_,
5281 targetTable.originalVersion_,
5284 targetTable.temporaryVersion_,
5287 __SUP_COUT__ <<
"Final target version is " << targetTable.tableName_ <<
"-v"
5288 << finalVersion << __E__;
5290 for(
auto& modifiedConfig : commandTableToEditMap)
5292 if(!modifiedConfig.second.modified_)
5294 if(modifiedConfig.second
5295 .createdTemporaryVersion_)
5297 __SUP_COUT__ <<
"Erasing unmodified temporary version "
5298 << modifiedConfig.second.tableName_ <<
"-v"
5299 << modifiedConfig.second.temporaryVersion_ << __E__;
5302 modifiedConfig.second.temporaryVersion_);
5310 modifiedConfig.second.tableName_,
5311 modifiedConfig.second.originalVersion_,
5313 modifiedConfig.second.table_,
5314 modifiedConfig.second.temporaryVersion_,
5317 __SUP_COUT__ <<
"Final version is " << modifiedConfig.second.tableName_ <<
"-v"
5318 << finalVersion << __E__;
5321 handleFillModifiedTablesXML(xmlOut, cfgMgr);
5323 catch(std::runtime_error& e)
5325 __SUP_SS__ <<
"Error detected saving Iteration Plan!\n\n " << e.what() << __E__;
5326 __SUP_COUT_ERR__ <<
"\n" << ss.str() << __E__;
5327 xmlOut.addTextElementToData(
"Error", ss.str());
5331 __SUP_SS__ <<
"Error detected saving Iteration Plan!\n\n " << __E__;
5336 catch(
const std::exception& e)
5338 ss <<
"Exception message: " << e.what();
5343 __SUP_COUT_ERR__ <<
"\n" << ss.str() << __E__;
5344 xmlOut.addTextElementToData(
"Error", ss.str());
5357 void ConfigurationGUISupervisor::handleSaveTreeNodeEditXML(
HttpXmlDocument& xmlOut,
5359 const std::string& tableName,
5361 const std::string& type,
5362 const std::string& uid,
5363 const std::string& colName,
5364 const std::string& newValue,
5365 const std::string& author)
5368 __SUP_COUT__ <<
"Editing table " << tableName <<
"(" << version <<
") uid=" << uid
5369 <<
" type=" << type << __E__;
5379 table->setActiveView(version);
5383 if(version.isTemporaryVersion())
5386 __SUP_COUT__ <<
"Failed to find stored version, so attempting to load version: "
5387 << version << __E__;
5391 __SUP_COUT__ <<
"Active version is " << table->getViewVersion() << __E__;
5392 __SUP_COUTTV__(table->getView().getComment());
5394 if(version != table->getViewVersion())
5396 __SUP_SS__ <<
"Target table version (" << version
5397 <<
") is not the currently active version (" << table->getViewVersion()
5398 <<
"). Try refreshing the tree." << __E__;
5402 unsigned int col = -1;
5403 if(type ==
"uid" || type ==
"delete-uid" || type ==
"tree-copy")
5404 col = table->getView().getColUID();
5405 else if(type ==
"node-comment")
5406 col = table->getView().findCol(TableViewColumnInfo::COL_NAME_COMMENT);
5407 else if(type ==
"link-UID" || type ==
"link-GroupID" || type ==
"value" ||
5408 type ==
"value-groupid" || type ==
"value-bool" || type ==
"value-bitmap")
5409 col = table->getView().findCol(colName);
5410 else if(type ==
"table" || type ==
"link-comment" || type ==
"table-newGroupRow" ||
5411 type ==
"table-newUIDRow" || type ==
"table-newRow")
5415 __SUP_SS__ <<
"Impossible! Unrecognized edit type: " << type << __E__;
5420 if(type ==
"table" || type ==
"link-comment")
5423 if(table->getView().isURIEncodedCommentTheSame(newValue))
5426 <<
"' is the same as the current comment. No need to save change."
5442 TableVersion temporaryVersion = table->createTemporaryView(version);
5444 __SUP_COUT__ <<
"Created temporary version " << temporaryVersion << __E__;
5446 TableView* cfgView = table->getTemporaryView(temporaryVersion);
5449 __SUP_COUTTV__(table->getView().getComment());
5455 if(type ==
"table" || type ==
"link-comment")
5460 else if(type ==
"table-newRow" || type ==
"table-newUIDRow")
5463 unsigned int row = cfgView->
addRow(
5464 author,
true , newValue );
5479 else if(type ==
"table-newGroupRow")
5482 unsigned int csvIndex = newValue.find(
',');
5484 std::string linkIndex = newValue.substr(0, csvIndex);
5485 std::string groupId = newValue.substr(csvIndex + 1);
5488 csvIndex = groupId.find(
',');
5489 std::string newRowUID = groupId.substr(csvIndex + 1);
5490 groupId = groupId.substr(0, csvIndex);
5492 __SUP_COUT__ <<
"newValue " << linkIndex <<
"," << groupId <<
"," << newRowUID
5496 unsigned int row = cfgView->
addRow(author,
5522 else if(type ==
"delete-uid")
5525 unsigned int row = cfgView->
findRow(col, uid);
5528 else if(type ==
"tree-copy")
5531 __COUTV__(newValue);
5532 std::vector<std::string> paramArray =
5538 if(paramArray.size() < 2 || paramArray.size() > 3)
5540 __SS__ <<
"Illegal parameters for tree copy request: must be number of "
5541 "copy instances & depth of copy (optionally followed by a "
5542 "custom UID for the new record)."
5547 unsigned int row = cfgView->
findRow(col, uid);
5550 unsigned int numberOfInstances = atoi(paramArray[0].c_str());
5551 unsigned int depth = atoi(paramArray[1].c_str());
5552 std::string customUID = paramArray.size() == 3
5556 __COUTV__(numberOfInstances);
5557 __COUTV__(customUID);
5558 if(numberOfInstances > 1000)
5560 __SS__ <<
"Illegal parameters - the maximum number of copy instances is "
5561 "1000. Number of instances provided was "
5562 << numberOfInstances << __E__;
5565 if(!customUID.empty() && numberOfInstances != 1)
5567 __SS__ <<
"A custom UID can only be supplied when copying a single "
5568 "instance. Requested instances: "
5569 << numberOfInstances << __E__;
5577 unsigned int rowsBeforeCopy = cfgView->getNumberOfRows();
5578 ConfigurationSupervisorBase::recursiveCopyTreeUIDNode(xmlOut,
5588 if(!customUID.empty() && cfgView->getNumberOfRows() > rowsBeforeCopy)
5590 unsigned int uidCol = cfgView->
getColUID();
5591 unsigned int newRow = cfgView->getNumberOfRows() - 1;
5593 xmlOut.addTextElementToData(
"CopiedRecordUID", customUID);
5596 else if(type ==
"uid" || type ==
"value" || type ==
"value-groupid" ||
5597 type ==
"value-bool" || type ==
"value-bitmap" || type ==
"node-comment")
5603 __SUP_SS__ <<
"Value '" << newValue
5604 <<
"' is the same as the current value. No need to save "
5605 "change to tree node."
5610 else if(type ==
"link-UID" || type ==
"link-GroupID")
5613 std::pair<
unsigned int ,
unsigned int > linkPair;
5617 __SUP_SS__ <<
"Col '" << colName <<
"' is not a link column." << __E__;
5621 __SUP_COUT__ <<
"linkPair " << linkPair.first <<
"," << linkPair.second
5624 std::string linkIndex = cfgView->getColumnInfo(col).getChildLinkIndex();
5626 __SUP_COUT__ <<
"linkIndex " << linkIndex << __E__;
5629 unsigned int csvIndexStart = 0, csvIndex = newValue.find(
',');
5631 std::string newTable = newValue.substr(csvIndexStart, csvIndex);
5632 csvIndexStart = csvIndex + 1;
5633 csvIndex = newValue.find(
',', csvIndexStart);
5634 std::string newLinkId = newValue.substr(
5639 __SUP_COUT__ <<
"newValue " << newTable <<
"," << newLinkId << __E__;
5643 bool changed =
false;
5644 bool needSecondaryChange = (type ==
"link-GroupID");
5649 __SUP_COUT__ <<
"Value '" << newTable
5650 <<
"' is the same as the current value." << __E__;
5658 std::string originalValue = cfgView->
getValueAsString(row, linkPair.second);
5662 __SUP_COUT__ <<
"Value '" << newLinkId
5663 <<
"' is the same as the current value." << __E__;
5668 needSecondaryChange =
5674 if(needSecondaryChange)
5676 bool secondaryChanged =
false;
5677 bool defaultIsInGroup =
5683 __SUP_COUT__ <<
"No changes to primary view. Erasing temporary table."
5685 table->eraseView(temporaryVersion);
5706 catch(std::runtime_error&
5709 __SUP_COUT__ <<
"Caught error while editing main table. Erasing "
5710 "temporary version."
5712 table->eraseView(temporaryVersion);
5716 xmlOut.addTextElementToData(
5718 "Error saving primary tree node! " + std::string(e.what()));
5728 __SUP_COUTV__(newValue);
5729 csvIndexStart = csvIndex + 1;
5730 csvIndex = newValue.find(
',', csvIndexStart);
5732 csvIndexStart, csvIndex - csvIndexStart));
5735 if(newTable == TableViewColumnInfo::DATATYPE_LINK_DEFAULT)
5746 table->setActiveView(version);
5750 if(version.isTemporaryVersion())
5753 __SUP_COUT__ <<
"Failed to find stored version, so attempting to "
5755 << newTable <<
" v" << version << __E__;
5759 __SUP_COUT__ << newTable <<
" active version is "
5760 << table->getViewVersion() << __E__;
5762 if(version != table->getViewVersion())
5765 if(version.isMockupVersion())
5766 ss <<
"Target table '" << newTable
5767 <<
"' is likely not a member of the current table group "
5768 <<
"since the mock-up version was not successfully loaded. "
5773 "To add a table to a group, click the group name to go to "
5775 "group view, then click 'Add/Remove/Modify Member Tables.' "
5777 "can then add or remove tables and save the new group." +
5779 "OR!!! Click the following button to add the table '" +
5781 "' to the currently active Configuration Group: " +
5782 "<input type='button' style='color:black !important;' " +
5783 "title='Click to add table to the active Configuration "
5785 "onclick='addTableToConfigurationGroup(\"" + newTable +
5786 "\"); Debug.closeErrorPop();event.stopPropagation();' "
5787 "value='Add Table'>" +
5791 ss <<
"Target table version (" << version
5792 <<
") is not the currently active version ("
5793 << table->getViewVersion() <<
"). Try refreshing the tree."
5799 temporaryVersion = table->createTemporaryView(version);
5801 __SUP_COUT__ <<
"Created temporary version " << temporaryVersion << __E__;
5803 cfgView = table->getTemporaryView(temporaryVersion);
5807 if(type ==
"link-UID")
5817 __SUP_COUT__ <<
"target col " << col << __E__;
5819 unsigned int row = -1;
5822 row = cfgView->
findRow(col, newLinkId);
5827 if(row == (
unsigned int)-1)
5829 __SUP_COUT__ <<
"New link UID '" << newLinkId
5830 <<
"' was not found, so attempting to change UID of "
5832 << originalValue <<
"'" << __E__;
5835 row = cfgView->
findRow(col, originalValue);
5838 secondaryChanged =
true;
5839 __SUP_COUT__ <<
"Original target record '"
5840 << originalValue <<
"' was changed to '"
5841 << newLinkId <<
"'" << __E__;
5846 __SUP_COUT__ <<
"Original target record '" << originalValue
5847 <<
"' not found." << __E__;
5851 else if(type ==
"link-GroupID")
5859 __SUP_COUT__ <<
"target col " << col << __E__;
5862 std::vector<std::string> memberUIDs;
5865 csvIndexStart = csvIndex + 1;
5866 csvIndex = newValue.find(
',', csvIndexStart);
5867 memberUIDs.push_back(
5868 newValue.substr(csvIndexStart, csvIndex - csvIndexStart));
5869 __SUP_COUT__ <<
"memberUIDs: " << memberUIDs.back() << __E__;
5871 (
unsigned int)std::string::npos);
5881 std::string targetUID;
5882 bool shouldBeInGroup;
5885 for(
unsigned int row = 0; row < cfgView->getNumberOfRows(); ++row)
5887 targetUID = cfgView->getDataView()[row][cfgView->
getColUID()];
5888 __SUP_COUT__ <<
"targetUID: " << targetUID << __E__;
5890 shouldBeInGroup =
false;
5891 for(
unsigned int i = 0; i < memberUIDs.size(); ++i)
5892 if(targetUID == memberUIDs[i])
5895 shouldBeInGroup =
true;
5902 if(shouldBeInGroup && !isInGroup)
5904 __SUP_COUT__ <<
"Changed to YES: " << row << __E__;
5905 secondaryChanged =
true;
5910 else if(!shouldBeInGroup && isInGroup)
5912 __SUP_COUT__ <<
"Changed to NO: " << row << __E__;
5913 secondaryChanged =
true;
5917 else if(targetUID ==
5919 ->getDefaultRowValues()[cfgView->
getColUID()] &&
5923 defaultIsInGroup =
true;
5929 if(!secondaryChanged)
5932 <<
"No changes to secondary view. Erasing temporary table."
5934 table->eraseView(temporaryVersion);
5955 catch(std::runtime_error&
5958 __SUP_COUT__ <<
"Caught error while editing secondary table. "
5959 "Erasing temporary version."
5961 table->eraseView(temporaryVersion);
5962 secondaryChanged =
false;
5965 xmlOut.addTextElementToData(
5967 "Error saving secondary tree node! " + std::string(e.what()));
5975 if(0 && !changed && !secondaryChanged && !defaultIsInGroup)
5977 __SUP_SS__ <<
"Link to table '" << newTable <<
"', linkID '"
5979 <<
"', and selected group members are the same as the "
5981 <<
"No need to save changes to tree." << __E__;
5987 else if(0 && !changed)
5992 __SUP_SS__ <<
"Link to table '" << newTable <<
"' and linkID '"
5994 <<
"' are the same as the current values. No need to save "
5995 "change to tree node."
6005 __SUP_COUT__ <<
"Caught error while editing. Erasing temporary version." << __E__;
6006 table->eraseView(temporaryVersion);
6020 catch(std::runtime_error& e)
6022 __SUP_SS__ <<
"Error saving tree node! " << e.what() << __E__;
6023 __SUP_COUT_ERR__ <<
"\n" << ss.str() << __E__;
6024 xmlOut.addTextElementToData(
"Error", ss.str());
6028 __SUP_SS__ <<
"Unknown Error saving tree node! " << __E__;
6033 catch(
const std::exception& e)
6035 ss <<
"Exception message: " << e.what();
6040 __SUP_COUT_ERR__ <<
"\n" << ss.str() << __E__;
6041 xmlOut.addTextElementToData(
"Error", ss.str());
6085 void ConfigurationGUISupervisor::handleGetTableXML(
HttpXmlDocument& xmlOut,
6087 const std::string& tableName,
6089 bool allowIllegalColumns ,
6091 bool descriptionOnly )
6094 xercesc::DOMElement *parentEl, *subparentEl;
6096 std::string accumulatedErrors =
"";
6098 if(allowIllegalColumns)
6099 xmlOut.addTextElementToData(
"allowIllegalColumns",
"1");
6101 const std::map<std::string, TableInfo>& allTableInfo = cfgMgr->
getAllTableInfo(
6102 allowIllegalColumns ,
6103 allowIllegalColumns ? &accumulatedErrors : 0,
6112 xmlOut.addTextElementToData(
"ExistingTableNames",
6113 TableViewColumnInfo::DATATYPE_LINK_DEFAULT);
6114 for(
auto& configPair : allTableInfo)
6116 xmlOut.addTextElementToData(
"ExistingTableNames", configPair.first);
6117 if(configPair.first == tableName &&
6118 configPair.second.versions_.find(version) ==
6119 configPair.second.versions_.end())
6121 __SUP_COUT__ <<
"Version not found, so using mockup." << __E__;
6127 xmlOut.addTextElementToData(
"TableName", tableName);
6128 xmlOut.addTextElementToData(
"TableDescription",
6129 table->getTableDescription());
6146 for(
const auto& aliases : versionAliases)
6147 for(
const auto& alias : aliases.second)
6148 __SUP_COUTT__ <<
"ALIAS: " << aliases.first <<
" " << alias.first
6149 <<
" ==> " << alias.second << __E__;
6151 catch(
const std::runtime_error& e)
6153 __SUP_COUT__ <<
"Could not get backbone information for version aliases: "
6154 << e.what() << __E__;
6157 auto tableIterator = versionAliases.find(tableName);
6159 parentEl = xmlOut.addTextElementToData(
"TableVersions",
"");
6162 for(
const TableVersion& v : allTableInfo.at(tableName).versions_)
6168 std::vector<std::string> aliases;
6169 if(tableIterator != versionAliases.end())
6172 for(
const auto& aliasPair : tableIterator->second)
6174 if(v == aliasPair.second)
6176 __SUP_COUT__ <<
"Found Alias " << aliasPair.second <<
" --> "
6177 << aliasPair.first << __E__;
6178 aliases.push_back(aliasPair.first);
6186 __SUP_COUT__ <<
"Handling version w/aliases" << __E__;
6189 TableVersion::INVALID)
6194 else if(hi.
version() + 1 == v.version())
6201 if(lo.
version() != TableVersion::INVALID)
6211 if(versionAliases.size())
6215 for(
const auto& alias : aliases)
6217 hi = lo = TableVersion::INVALID;
6222 if(lo.
version() != TableVersion::INVALID)
6236 if(version.isInvalid())
6238 tableViewPtr = table->getMockupViewP();
6246 std::string localAccumulatedErrors =
"";
6251 allowIllegalColumns ,
6252 &localAccumulatedErrors,
6258 xmlOut.addTextElementToData(
"TableRawData",
6259 tableViewPtr->getSourceRawData());
6261 const std::set<std::string>& srcColNames =
6262 tableViewPtr->getSourceColumnNames();
6263 for(
auto& srcColName : srcColNames)
6264 xmlOut.addTextElementToData(
"ColumnHeader", srcColName);
6266 if(!version.isTemporaryVersion())
6271 tableViewPtr = cfgMgr
6275 allowIllegalColumns ,
6276 &localAccumulatedErrors,
6282 if(localAccumulatedErrors !=
"")
6283 xmlOut.addTextElementToData(
"Error", localAccumulatedErrors);
6285 catch(std::runtime_error& e)
6287 __SUP_SS__ <<
"Failed to get table " << tableName <<
" version " << version
6288 <<
"... defaulting to mock-up! " << __E__;
6289 ss <<
"\n\n...Here is why it failed:\n\n" << e.what() << __E__;
6291 __SUP_COUT_ERR__ <<
"\n" << ss.str();
6293 tableViewPtr = table->getMockupViewP();
6295 xmlOut.addTextElementToData(
"Error",
"Error getting view! " + ss.str());
6299 __SUP_SS__ <<
"Failed to get table " << tableName <<
" version: " << version
6300 <<
"... defaulting to mock-up! "
6301 <<
"(You may want to try again to see what was partially loaded "
6302 "into cache before failure. "
6303 <<
"If you think, the failure is due to a column name change, "
6304 <<
"you can also try to Copy the failing view to the new column "
6306 <<
"'Copy and Move' functionality.)" << __E__;
6311 catch(
const std::exception& e)
6313 ss <<
"Exception message: " << e.what();
6319 __SUP_COUT_ERR__ <<
"\n" << ss.str();
6321 tableViewPtr = table->getMockupViewP();
6323 xmlOut.addTextElementToData(
"Error",
"Error getting view! " + ss.str());
6326 xmlOut.addTextElementToData(
"TableVersion", version.toString());
6332 xercesc::DOMElement* choicesParentEl;
6333 parentEl = xmlOut.addTextElementToData(
"CurrentVersionColumnHeaders",
"");
6335 std::vector<TableViewColumnInfo> colInfo = tableViewPtr->getColumnsInfo();
6337 for(
int i = 0; i < (int)colInfo.size(); ++i)
6342 "ColumnDataType", colInfo[i].getDataType(), parentEl);
6347 "ColumnDefaultValue", colInfo[i].getDefaultValue(), parentEl);
6351 if(colInfo[i].getType() == TableViewColumnInfo::TYPE_FIXED_CHOICE_DATA ||
6352 colInfo[i].getType() == TableViewColumnInfo::TYPE_BITMAP_DATA ||
6353 colInfo[i].isChildLink())
6355 for(
auto& choice : colInfo[i].getDataChoices())
6360 "ColumnMinValue", colInfo[i].getMinValue(), parentEl);
6362 "ColumnMaxValue", colInfo[i].getMaxValue(), parentEl);
6368 if(version.isInvalid())
6369 tableViewPtr->
init();
6371 catch(std::runtime_error& e)
6374 __THROW__(e.what() + std::string(
"\n\n") + accumulatedErrors);
6381 parentEl = xmlOut.addTextElementToData(
"CurrentVersionRows",
"");
6383 int numRows = (int)tableViewPtr->getNumberOfRows();
6384 int numCols = (int)tableViewPtr->getNumberOfColumns();
6386 for(
int c = 0; c < numCols; ++c)
6389 csvStr.reserve(numRows * 20);
6390 for(
int r = 0; r < numRows; ++r)
6394 if(colInfo[c].getDataType() == TableViewColumnInfo::DATATYPE_TIME)
6396 std::string timeAsString;
6397 tableViewPtr->
getValue(timeAsString, r, c);
6398 csvStr += StringMacros::encodeURIComponent(timeAsString);
6402 StringMacros::encodeURIComponent(tableViewPtr->getDataView()[r][c]);
6408 xmlOut.addTextElementToData(
"TableComment", tableViewPtr->getComment());
6409 xmlOut.addTextElementToData(
"TableAuthor", tableViewPtr->getAuthor());
6410 xmlOut.addTextElementToData(
"TableCreationTime",
6411 std::to_string(tableViewPtr->getCreationTime()));
6412 xmlOut.addTextElementToData(
"TableLastAccessTime",
6413 std::to_string(tableViewPtr->getLastAccessTime()));
6418 std::vector<std::string> defaultRowValues =
6419 table->getMockupViewP()->getDefaultRowValues();
6421 for(
unsigned int c = 0; c < defaultRowValues.size() - 2; ++c)
6423 xmlOut.addTextElementToData(
"DefaultRowValue", defaultRowValues[c]);
6426 const std::set<std::string> srcColNames = tableViewPtr->getSourceColumnNames();
6428 if(accumulatedErrors !=
"")
6430 __SUP_SS__ << (std::string(
"Column errors were allowed for this request, so "
6431 "perhaps you can ignore this, ") +
6432 "but please note the following warnings:\n" + accumulatedErrors)
6434 __SUP_COUT_ERR__ << ss.str();
6435 xmlOut.addTextElementToData(
"TableWarnings", ss.str());
6437 else if(!version.isTemporaryVersion() &&
6439 (srcColNames.size() != tableViewPtr->getNumberOfColumns() ||
6440 tableViewPtr->getSourceColumnMismatch() !=
6443 __SUP_SS__ <<
"\n\nThere were warnings found when loading the table " << tableName
6444 <<
":v" << version <<
". Please see the details below:\n\n"
6445 << tableViewPtr->getMismatchColumnInfo();
6447 __SUP_COUT__ <<
"\n" << ss.str();
6448 xmlOut.addTextElementToData(
"TableWarnings", ss.str());
6452 catch(std::runtime_error& e)
6454 __SUP_SS__ <<
"Error getting table view!\n\n " << e.what() << __E__;
6455 __SUP_COUT_ERR__ << ss.str();
6456 xmlOut.addTextElementToData(
"Error", ss.str());
6460 __SUP_SS__ <<
"Error getting table view!\n\n " << __E__;
6465 catch(
const std::exception& e)
6467 ss <<
"Exception message: " << e.what();
6472 __SUP_COUT_ERR__ << ss.str();
6473 xmlOut.addTextElementToData(
"Error", ss.str());
6484 std::string username,
bool refresh)
6486 uint64_t sessionIndex =
6489 std::stringstream ssMapKey;
6490 ssMapKey << username <<
":" << sessionIndex;
6491 std::string mapKey = ssMapKey.str();
6492 __SUP_COUTT__ <<
"Using Config Session " << mapKey
6493 <<
" ... Total Session Count: " << userConfigurationManagers_.size()
6494 <<
" refresh=" << refresh << __E__;
6496 time_t now = time(0);
6502 for(
auto& pair : userConfigurationManagers_)
6503 __SUP_COUTTV__(pair.first);
6506 const std::string preLoadCfgMgrName =
":0";
6507 if(userConfigurationManagers_.size() == 1 &&
6508 userConfigurationManagers_.find(preLoadCfgMgrName) !=
6509 userConfigurationManagers_.end())
6511 __SUP_COUT__ <<
"Using pre-loaded Configuration Manager. time=" << time(0) <<
" "
6512 << clock() <<
" Setting author from "
6513 << userConfigurationManagers_.at(preLoadCfgMgrName)->getUsername()
6514 <<
" to " << username << __E__;
6515 userConfigurationManagers_[mapKey] =
6516 userConfigurationManagers_.at(preLoadCfgMgrName);
6517 userLastUseTime_[mapKey] = userLastUseTime_.at(preLoadCfgMgrName);
6519 userConfigurationManagers_.at(mapKey)->setUsername(username);
6522 if(userConfigurationManagers_.find(mapKey) == userConfigurationManagers_.end())
6524 __SUP_COUT__ <<
"Creating new Configuration Manager. time=" << time(0) <<
" "
6525 << clock() << __E__;
6531 userConfigurationManagers_[mapKey]->getAllTableInfo(
6539 else if(userLastUseTime_.find(mapKey) == userLastUseTime_.end())
6541 __SUP_SS__ <<
"Fatal error managing user sessions! Check the logs for "
6542 "Configuration Interface failure."
6544 __SUP_COUT_ERR__ <<
"\n" << ss.str();
6549 (now - userLastUseTime_[mapKey]) >
6550 CONFIGURATION_MANAGER_REFRESH_THRESHOLD)
6552 __SUP_COUT__ <<
"Refreshing all table info." << __E__;
6553 userConfigurationManagers_[mapKey]->getAllTableInfo(
6561 __SUP_COUTT__ <<
"Configuration Manager for author="
6562 << userConfigurationManagers_[mapKey]->getUsername()
6563 <<
" ready. time=" << time(0) <<
" " << clock() <<
" runTimeSeconds()="
6564 << userConfigurationManagers_[mapKey]->runTimeSeconds() << __E__;
6567 userLastUseTime_[mapKey] = now;
6570 for(std::map<std::string, time_t>::iterator it = userLastUseTime_.begin();
6571 it != userLastUseTime_.end();
6573 if(now - it->second > CONFIGURATION_MANAGER_EXPIRATION_TIME)
6575 __SUP_COUT__ << now <<
":" << it->second <<
" = " << now - it->second
6577 delete userConfigurationManagers_[it->first];
6578 if(!(userConfigurationManagers_.erase(it->first)))
6580 __SUP_SS__ <<
"Fatal error erasing configuration manager by key!"
6582 __SUP_COUT_ERR__ <<
"\n" << ss.str();
6585 userLastUseTime_.erase(it);
6592 return userConfigurationManagers_[mapKey];
6600 void ConfigurationGUISupervisor::handleDeleteTableInfoXML(
HttpXmlDocument& xmlOut,
6602 std::string& tableName)
6604 if(0 == rename((TABLE_INFO_PATH + tableName + TABLE_INFO_EXT).c_str(),
6605 (TABLE_INFO_PATH + tableName + TABLE_INFO_EXT +
".unused").c_str()))
6606 __SUP_COUT_INFO__ << (
"Table Info File successfully renamed: " +
6607 (TABLE_INFO_PATH + tableName + TABLE_INFO_EXT +
".unused"))
6611 __SUP_COUT_ERR__ << (
"Error renaming file to " +
6612 (TABLE_INFO_PATH + tableName + TABLE_INFO_EXT +
".unused"))
6615 xmlOut.addTextElementToData(
6617 (
"Error renaming Table Info File to " +
6618 (TABLE_INFO_PATH + tableName + TABLE_INFO_EXT +
".unused")));
6633 void ConfigurationGUISupervisor::handleSaveTableInfoXML(
6636 std::string& tableName,
6637 const std::string& data,
6638 const std::string& tableDescription,
6639 const std::string& columnChoicesCSV,
6640 bool allowOverwrite)
6644 std::string capsName;
6649 catch(std::runtime_error& e)
6651 xmlOut.addTextElementToData(
"Error", e.what());
6657 FILE* fp = fopen((TABLE_INFO_PATH + tableName + TABLE_INFO_EXT).c_str(),
"r");
6661 xmlOut.addTextElementToData(
"TableName", tableName);
6662 xmlOut.addTextElementToData(
"OverwriteError",
"1");
6663 xmlOut.addTextElementToData(
6665 "File already exists! ('" +
6666 (TABLE_INFO_PATH + tableName + TABLE_INFO_EXT) +
"')");
6671 __SUP_COUT__ <<
"capsName=" << capsName << __E__;
6672 __SUP_COUT__ <<
"tableName=" << tableName << __E__;
6673 __SUP_COUT__ <<
"tableDescription=" << tableDescription << __E__;
6674 __SUP_COUT__ <<
"columnChoicesCSV=" << columnChoicesCSV << __E__;
6677 std::stringstream outss;
6679 outss <<
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n";
6680 outss <<
"\t<ROOT xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
6681 "xsi:noNamespaceSchemaLocation=\"TableInfo.xsd\">\n";
6682 outss <<
"\t\t<TABLE Name=\"" << tableName <<
"\">\n";
6683 outss <<
"\t\t\t<VIEW Name=\"" << capsName
6684 <<
"\" Type=\"File,Database,DatabaseTest\" Description=\"" << tableDescription
6690 std::istringstream columnChoicesISS(columnChoicesCSV);
6691 std::string columnChoicesString;
6692 std::string columnDefaultValue, columnMinValue, columnMaxValue;
6693 std::vector<std::string> columnParameters;
6694 std::vector<std::string> columnData =
6697 std::set<std::string> childLinkIndices, childLinkUIDIndices, childLinkGroupIDIndices;
6699 for(
unsigned int c = 0; c < columnData.size() - 1; ++c)
6703 __COUT__ <<
"Column #" << c <<
": "
6705 for(
unsigned int p = 0; p < columnParameters.size(); ++p)
6707 __COUT__ <<
"\t Parameter #" << p <<
": " << columnParameters[p] << __E__;
6709 __COUT__ <<
"\t creating the new xml" << __E__;
6711 std::string& columnType = columnParameters[0];
6712 std::string& columnName = columnParameters[1];
6713 std::string& columnDataType = columnParameters[2];
6714 const std::string columnStorageName =
6717 outss <<
"\t\t\t\t<COLUMN Type=\"";
6718 outss << columnType;
6719 outss <<
"\" \t Name=\"";
6720 outss << columnName;
6721 outss <<
"\" \t StorageName=\"";
6724 outss << columnStorageName;
6726 catch(std::runtime_error& e)
6728 xmlOut.addTextElementToData(
6730 std::string(
"For column name '") + columnName +
"' - " + e.what());
6733 outss <<
"\" \t DataType=\"";
6734 outss << columnDataType;
6738 std::string* columnDefaultValuePtr =
nullptr;
6739 if(columnDefaultValue !=
6742 __SUP_COUT__ <<
"FOUND user spec'd default value '" << columnDefaultValue
6744 outss <<
"\" \t DefaultValue=\"";
6745 outss << columnParameters[3];
6746 columnDefaultValuePtr = &columnParameters[3];
6748 getline(columnChoicesISS, columnChoicesString,
';');
6749 outss <<
"\" \t DataChoices=\"";
6750 outss << columnChoicesString;
6752 std::string* columnMinValuePtr =
nullptr;
6753 std::string* columnMaxValuePtr =
nullptr;
6755 if(columnParameters.size() > 4 &&
6759 if(columnMinValue !=
"")
6761 if(columnMinValue !=
6764 __SUP_COUT__ <<
"FOUND user spec'd min value '" << columnParameters[4]
6769 __SS__ <<
"Inavlid user spec'd min value '" << columnParameters[4]
6770 <<
"' which evaluates to '" << columnMinValue
6771 <<
"' and is not a valid number. The minimum value must "
6772 "be a number (environment variables and math "
6773 "operations are allowed)."
6777 outss <<
"\" \t MinValue=\"" << columnParameters[4];
6778 columnMinValuePtr = &columnParameters[4];
6783 if(columnMaxValue !=
"")
6785 if(columnMaxValue !=
6788 __SUP_COUT__ <<
"FOUND user spec'd max value = " << columnMaxValue
6793 __SS__ <<
"Inavlid user spec'd max value '" << columnParameters[5]
6794 <<
"' which evaluates to '" << columnMaxValue
6795 <<
"' and is not a valid number. The maximum value must "
6796 "be a number (environment variables and math "
6797 "operations are allowed)."
6801 outss <<
"\" \t MaxValue=\"" << columnParameters[5];
6802 columnMaxValuePtr = &columnParameters[5];
6814 columnDefaultValuePtr,
6815 columnChoicesString,
6821 catch(
const std::runtime_error& e)
6823 __SS__ <<
"Error identified with Column #" << c <<
": \n" << e.what();
6828 childLinkIndices.insert(columnType.substr(
sizeof(
"ChildLink-") - 1));
6829 else if(columnType.find(
"ChildLinkUID-") == 0)
6830 childLinkUIDIndices.insert(columnType.substr(
sizeof(
"ChildLinkUID-") - 1));
6831 else if(columnType.find(
"ChildLinkGroupID-") == 0)
6832 childLinkGroupIDIndices.insert(
6833 columnType.substr(
sizeof(
"ChildLinkGroupID-") - 1));
6840 for(
const auto& idx : childLinkUIDIndices)
6841 if(childLinkIndices.find(idx) == childLinkIndices.end())
6843 __SS__ <<
"Column type 'ChildLinkUID-" << idx
6844 <<
"' has no matching 'ChildLink-" << idx
6845 <<
"' column. A ChildLinkUID column must be paired with a "
6846 "ChildLink column using the same link index."
6850 for(
const auto& idx : childLinkGroupIDIndices)
6851 if(childLinkIndices.find(idx) == childLinkIndices.end())
6853 __SS__ <<
"Column type 'ChildLinkGroupID-" << idx
6854 <<
"' has no matching 'ChildLink-" << idx
6855 <<
"' column. A ChildLinkGroupID column must be paired with a "
6856 "ChildLink column using the same link index. "
6857 "Did you intend to make a target of a Group Link? "
6858 "If so, use the 'GroupID' column type instead."
6862 for(
const auto& idx : childLinkIndices)
6863 if(childLinkUIDIndices.find(idx) == childLinkUIDIndices.end() &&
6864 childLinkGroupIDIndices.find(idx) == childLinkGroupIDIndices.end())
6866 __SS__ <<
"Column type 'ChildLink-" << idx
6867 <<
"' has no matching 'ChildLinkUID-" << idx
6868 <<
"' or 'ChildLinkGroupID-" << idx
6869 <<
"' column. A ChildLink column must be paired with either a "
6870 "ChildLinkUID or ChildLinkGroupID column using the same link index."
6875 outss <<
"\t\t\t</VIEW>\n";
6876 outss <<
"\t\t</TABLE>\n";
6877 outss <<
"\t</ROOT>\n";
6879 __SUP_COUT__ << outss.str() << __E__;
6881 FILE* fp = fopen((TABLE_INFO_PATH + tableName + TABLE_INFO_EXT).c_str(),
"w");
6884 xmlOut.addTextElementToData(
"Error",
6885 "Failed to open destination Table Info file:" +
6886 (TABLE_INFO_PATH + tableName + TABLE_INFO_EXT));
6890 fprintf(fp,
"%s", outss.str().c_str());
6893 __SUP_COUT_INFO__ <<
"Finished saving Table Info for '" << tableName
6894 <<
".' Looking for errors in all table column info..." << __E__;
6898 std::string accumulatedErrors =
"";
6902 if(accumulatedErrors !=
"")
6904 __SUP_SS__ << (
"The new version of the '" + tableName +
6905 "' table column info was saved, however errors were detected "
6906 "reading back the table '" +
6907 tableName +
"' after the save attempt:\n\n" + accumulatedErrors)
6910 __SUP_COUT_ERR__ << ss.str() << __E__;
6911 xmlOut.addTextElementToData(
"Error", ss.str());
6917 handleGetTableXML(xmlOut, cfgMgr, tableName,
TableVersion());
6920 const std::map<std::string, TableInfo>& allTableInfo = cfgMgr->
getAllTableInfo();
6923 for(
const auto& cfgInfo : allTableInfo)
6929 catch(std::runtime_error& e)
6931 __SUP_COUT_WARN__ <<
"\n\n##############################################\n"
6932 <<
"Error identified in column info of table '"
6933 << cfgInfo.first <<
"':\n\n"
6934 << e.what() <<
"\n\n"
6948 void ConfigurationGUISupervisor::handleSetGroupAliasInBackboneXML(
6951 const std::string& groupAliasCSV,
6952 const std::string& groupNameCSV,
6953 const std::string& groupKeyCSV,
6954 const std::string& author)
6958 std::map<std::string, TableVersion> activeVersions = cfgMgr->
getActiveVersions();
6960 const std::string groupAliasesTableName =
6961 ConfigurationManager::GROUP_ALIASES_TABLE_NAME;
6962 if(activeVersions.find(groupAliasesTableName) == activeVersions.end())
6964 __SUP_SS__ <<
"Active version of " << groupAliasesTableName <<
" missing!"
6966 xmlOut.addTextElementToData(
"Error", ss.str());
6971 const std::set<std::string> backboneMembers = cfgMgr->getBackboneMemberNames();
6972 for(
auto& memberName : backboneMembers)
6974 __SUP_COUT__ <<
"activeVersions[\"" << memberName
6975 <<
"\"]=" << activeVersions[memberName] << __E__;
6977 xmlOut.addTextElementToData(
"oldBackboneName", memberName);
6978 xmlOut.addTextElementToData(
"oldBackboneVersion",
6979 activeVersions[memberName].toString());
6987 TableVersion originalVersion = activeVersions[groupAliasesTableName];
6988 TableVersion temporaryVersion = table->createTemporaryView(originalVersion);
6990 __SUP_COUT__ <<
"\t\t temporaryVersion: " << temporaryVersion << __E__;
6991 bool isDifferent =
false;
6995 TableView* configView = table->getTemporaryView(temporaryVersion);
6997 unsigned int col = configView->
findCol(
"GroupKeyAlias");
6998 unsigned int ccol = configView->
findCol(TableViewColumnInfo::COL_NAME_COMMENT);
6999 unsigned int ncol = configView->
findCol(
"GroupName");
7000 unsigned int kcol = configView->
findCol(
"GroupKey");
7003 std::vector<std::string> groupAliases =
7005 std::vector<std::string> groupNames =
7007 std::vector<std::string> groupKeys =
7014 for(
const auto& groupAlias : groupAliases)
7016 if(groupAlias ==
"" || groupNames[i] ==
"" || groupKeys[i] ==
"")
7019 __SUP_COUT_WARN__ <<
"Empty alias parameter found [" << i <<
"] = {"
7020 << groupAlias <<
", " << groupNames[i] <<
"("
7021 << groupKeys[i] <<
")}" << __E__;
7026 bool localIsDifferent =
false;
7027 const std::string& groupName = groupNames[i];
7031 unsigned int row = -1;
7035 row = configView->
findRow(col, groupAlias);
7041 if(row == (
unsigned int)-1)
7043 localIsDifferent =
true;
7044 row = configView->
addRow();
7048 "This Group Alias was automatically setup by the server.", row, ccol);
7049 configView->
setValue(groupAlias, row, col);
7052 __SUP_COUT__ <<
"\t\t row: " << row << __E__;
7054 __SUP_COUT__ <<
"\t\t groupName: " << groupName <<
" vs "
7055 << configView->getDataView()[row][ncol] << __E__;
7056 if(groupName != configView->getDataView()[row][ncol])
7058 configView->
setValue(groupName, row, ncol);
7059 localIsDifferent =
true;
7062 __SUP_COUT__ <<
"\t\t groupKey: " << groupKey <<
" vs "
7063 << configView->getDataView()[row][kcol] << __E__;
7064 if(groupKey.
toString() != configView->getDataView()[row][kcol])
7067 localIsDifferent =
true;
7070 if(localIsDifferent)
7075 configView->
findCol(TableViewColumnInfo::COL_NAME_AUTHOR));
7079 configView->
findCol(TableViewColumnInfo::COL_NAME_CREATION));
7086 __SUP_COUT_ERR__ <<
"Error editing Group Alias view!" << __E__;
7089 table->eraseView(temporaryVersion);
7096 __SUP_COUT__ <<
"\t\t**************************** Save as new table version"
7103 table->getTableName(),
7114 <<
"\t\t**************************** Using the existing table version"
7118 table->eraseView(temporaryVersion);
7119 newAssignedVersion = activeVersions[groupAliasesTableName];
7121 xmlOut.addTextElementToData(
"savedName", groupAliasesTableName);
7122 xmlOut.addTextElementToData(
"savedVersion", newAssignedVersion.
toString());
7125 __SUP_COUT__ <<
"\t\t newAssignedVersion: " << newAssignedVersion << __E__;
7127 catch(std::runtime_error& e)
7129 __SUP_SS__ <<
"Error saving new Group Alias view!\n\n " << e.what() << __E__;
7130 __SUP_COUT_ERR__ << ss.str();
7131 xmlOut.addTextElementToData(
"Error", ss.str());
7135 __SUP_SS__ <<
"Error saving new Group Alias view!\n\n " << __E__;
7140 catch(
const std::exception& e)
7142 ss <<
"Exception message: " << e.what();
7147 __SUP_COUT_ERR__ << ss.str();
7148 xmlOut.addTextElementToData(
"Error", ss.str());
7159 void ConfigurationGUISupervisor::handleSetTableAliasInBackboneXML(
7162 const std::string& tableAlias,
7163 const std::string& tableName,
7165 const std::string& author)
7169 std::map<std::string, TableVersion> activeVersions = cfgMgr->
getActiveVersions();
7171 const std::string versionAliasesTableName =
7172 ConfigurationManager::VERSION_ALIASES_TABLE_NAME;
7173 if(activeVersions.find(versionAliasesTableName) == activeVersions.end())
7175 __SUP_SS__ <<
"Active version of " << versionAliasesTableName <<
" missing!"
7177 xmlOut.addTextElementToData(
"Error", ss.str());
7182 const std::set<std::string> backboneMembers = cfgMgr->getBackboneMemberNames();
7183 for(
auto& memberName : backboneMembers)
7185 __SUP_COUT__ <<
"activeVersions[\"" << memberName
7186 <<
"\"]=" << activeVersions[memberName] << __E__;
7188 xmlOut.addTextElementToData(
"oldBackboneName", memberName);
7189 xmlOut.addTextElementToData(
"oldBackboneVersion",
7190 activeVersions[memberName].toString());
7198 TableVersion originalVersion = activeVersions[versionAliasesTableName];
7199 TableVersion temporaryVersion = table->createTemporaryView(originalVersion);
7201 __SUP_COUT__ <<
"\t\t temporaryVersion: " << temporaryVersion << __E__;
7203 bool isDifferent =
false;
7207 TableView* configView = table->getTemporaryView(temporaryVersion);
7210 unsigned int col2 = configView->
findCol(
"VersionAlias");
7211 unsigned int col3 = configView->
findCol(
"TableName");
7215 unsigned int row = -1;
7220 unsigned int tmpRow = -1;
7223 tmpRow = configView->
findRow(col3, tableName, tmpRow + 1);
7224 }
while(configView->getDataView()[tmpRow][col2] != tableAlias);
7231 if(row == (
unsigned int)-1)
7234 row = configView->
addRow();
7237 col = configView->
findCol(TableViewColumnInfo::COL_NAME_COMMENT);
7239 std::string(
"Entry was added by server in ") +
7240 "ConfigurationGUISupervisor::setTableAliasInActiveBackbone().",
7244 col = configView->
findCol(
"VersionAliasUID");
7246 tableName.substr(0, tableName.rfind(
"Table")) + tableAlias, row, col);
7248 configView->
setValue(tableAlias, row, col2);
7249 configView->
setValue(tableName, row, col3);
7252 __SUP_COUT__ <<
"\t\t row: " << row << __E__;
7254 col = configView->
findCol(
"Version");
7255 __SUP_COUT__ <<
"\t\t version: " << version <<
" vs "
7256 << configView->getDataView()[row][col] << __E__;
7257 if(version.toString() != configView->getDataView()[row][col])
7259 configView->
setValue(version.toString(), row, col);
7266 author, row, configView->
findCol(TableViewColumnInfo::COL_NAME_AUTHOR));
7270 configView->
findCol(TableViewColumnInfo::COL_NAME_CREATION));
7275 __SUP_COUT_ERR__ <<
"Error editing Version Alias view!" << __E__;
7278 table->eraseView(temporaryVersion);
7285 __SUP_COUT__ <<
"\t\t**************************** Save as new table version"
7291 table->getTableName(),
7301 __SUP_COUT__ <<
"\t\t**************************** Using existing table version"
7305 table->eraseView(temporaryVersion);
7306 newAssignedVersion = activeVersions[versionAliasesTableName];
7308 xmlOut.addTextElementToData(
"savedName", versionAliasesTableName);
7309 xmlOut.addTextElementToData(
"savedVersion", newAssignedVersion.
toString());
7312 __SUP_COUT__ <<
"\t\t newAssignedVersion: " << newAssignedVersion << __E__;
7314 catch(std::runtime_error& e)
7316 __SUP_SS__ <<
"Error saving new Version Alias view!\n\n " << e.what() << __E__;
7317 __SUP_COUT_ERR__ << ss.str();
7318 xmlOut.addTextElementToData(
"Error", ss.str());
7322 __SUP_SS__ <<
"Error saving new Version Alias view!\n\n " << __E__;
7327 catch(
const std::exception& e)
7329 ss <<
"Exception message: " << e.what();
7334 __SUP_COUT_ERR__ << ss.str();
7335 xmlOut.addTextElementToData(
"Error", ss.str());
7344 void ConfigurationGUISupervisor::handleAliasGroupMembersInBackboneXML(
7347 const std::string& versionAlias,
7348 const std::string& groupName,
7350 const std::string& author)
7354 std::map<std::string, TableVersion> activeVersions = cfgMgr->
getActiveVersions();
7356 const std::string versionAliasesTableName =
7357 ConfigurationManager::VERSION_ALIASES_TABLE_NAME;
7358 if(activeVersions.find(versionAliasesTableName) == activeVersions.end())
7360 __SUP_SS__ <<
"Active version of " << versionAliasesTableName <<
" missing!"
7362 xmlOut.addTextElementToData(
"Error", ss.str());
7367 const std::set<std::string> backboneMembers = cfgMgr->getBackboneMemberNames();
7368 for(
auto& memberName : backboneMembers)
7370 __SUP_COUT__ <<
"activeVersions[\"" << memberName
7371 <<
"\"]=" << activeVersions[memberName] << __E__;
7373 xmlOut.addTextElementToData(
"oldBackboneName", memberName);
7374 xmlOut.addTextElementToData(
"oldBackboneVersion",
7375 activeVersions[memberName].toString());
7384 table->createTemporaryView(activeVersions[versionAliasesTableName]);
7386 __SUP_COUT__ <<
"\t\t temporaryVersion: " << temporaryVersion << __E__;
7388 TableView* configView = table->getTemporaryView(temporaryVersion);
7391 bool isDifferent =
false;
7410 xmlOut.addTextElementToData(
7413 "\" can not be retrieved!");
7418 unsigned int col2 = configView->
findCol(
"VersionAlias");
7419 unsigned int col3 = configView->
findCol(
"TableName");
7421 for(
auto& memberPair : memberMap)
7423 bool thisMemberIsDifferent =
false;
7424 unsigned int row = -1;
7426 __SUP_COUT__ <<
"Adding alias for " << memberPair.first <<
"_v"
7427 << memberPair.second <<
" to " << versionAlias << __E__;
7433 unsigned int tmpRow = -1;
7436 tmpRow = configView->
findRow(col3, memberPair.first, tmpRow + 1);
7437 }
while(configView->getDataView()[tmpRow][col2] != versionAlias);
7444 if(row == (
unsigned int)-1)
7446 thisMemberIsDifferent =
true;
7447 row = configView->
addRow();
7450 col = configView->
findCol(TableViewColumnInfo::COL_NAME_COMMENT);
7452 std::string(
"Entry was added by server in ") +
7453 "ConfigurationGUISupervisor::setTableAliasInActiveBackbone().",
7459 memberPair.first.substr(0, memberPair.first.rfind(
"Table")) +
7464 configView->
setValue(versionAlias, row, col2);
7465 configView->
setValue(memberPair.first, row, col3);
7468 col = configView->
findCol(
"Version");
7470 if(memberPair.second.toString() != configView->getDataView()[row][col])
7472 configView->
setValue(memberPair.second.toString(), row, col);
7473 thisMemberIsDifferent =
true;
7476 if(thisMemberIsDifferent)
7479 author, row, configView->
findCol(TableViewColumnInfo::COL_NAME_AUTHOR));
7483 configView->
findCol(TableViewColumnInfo::COL_NAME_CREATION));
7486 if(thisMemberIsDifferent)
7495 __SUP_COUT__ <<
"\t\t**************************** Save v" << temporaryVersion
7496 <<
" as new table version" << __E__;
7498 newAssignedVersion =
7499 cfgMgr->
saveNewTable(versionAliasesTableName, temporaryVersion);
7503 __SUP_COUT__ <<
"\t\t**************************** Using existing table version"
7507 table->eraseView(temporaryVersion);
7508 newAssignedVersion = activeVersions[versionAliasesTableName];
7511 xmlOut.addTextElementToData(
"savedName", versionAliasesTableName);
7512 xmlOut.addTextElementToData(
"savedVersion", newAssignedVersion.
toString());
7513 __SUP_COUT__ <<
"\t\t Resulting Version: " << newAssignedVersion << __E__;
7515 catch(std::runtime_error& e)
7517 __SUP_SS__ <<
"Error saving new Version Alias view!\n\n " << e.what() << __E__;
7518 __SUP_COUT_ERR__ << ss.str();
7519 xmlOut.addTextElementToData(
"Error", ss.str());
7523 __SUP_SS__ <<
"Error saving new Version Alias view!\n\n " << __E__;
7528 catch(
const std::exception& e)
7530 ss <<
"Exception message: " << e.what();
7535 __SUP_COUT_ERR__ << ss.str();
7536 xmlOut.addTextElementToData(
"Error", ss.str());
7550 void ConfigurationGUISupervisor::handleGroupAliasesXML(
HttpXmlDocument& xmlOut,
7554 std::map<std::string, TableVersion> activeVersions = cfgMgr->
getActiveVersions();
7556 std::string groupAliasesTableName = ConfigurationManager::GROUP_ALIASES_TABLE_NAME;
7557 if(activeVersions.find(groupAliasesTableName) == activeVersions.end())
7559 __SUP_SS__ <<
"\nActive version of " << groupAliasesTableName <<
" missing! "
7560 << groupAliasesTableName
7561 <<
" is a required member of the Backbone table group."
7562 <<
"\n\nLikely you need to activate a valid Backbone table group."
7564 __SUP_COUT__ << ss.str();
7569 __SUP_COUT__ <<
"activeVersions[\"" << groupAliasesTableName
7570 <<
"\"]=" << activeVersions[groupAliasesTableName] << __E__;
7571 xmlOut.addTextElementToData(
"GroupAliasesTableName", groupAliasesTableName);
7572 xmlOut.addTextElementToData(
"GroupAliasesTableVersion",
7573 activeVersions[groupAliasesTableName].toString());
7575 std::vector<std::pair<std::string, ConfigurationTree>> aliasNodePairs =
7578 const int numOfThreads = StringMacros::getConcurrencyCount() / 2;
7579 __SUP_COUT__ <<
" getConcurrencyCount " << StringMacros::getConcurrencyCount()
7580 <<
" ==> " << numOfThreads <<
" threads for alias group loads." << __E__;
7582 if(numOfThreads < 2)
7584 std::string groupName, groupKey, groupComment, groupAuthor, groupCreateTime,
7586 for(
auto& aliasNodePair : aliasNodePairs)
7588 groupName = aliasNodePair.second.getNode(
"GroupName").getValueAsString();
7589 groupKey = aliasNodePair.second.getNode(
"GroupKey").getValueAsString();
7591 xmlOut.addTextElementToData(
"GroupAlias", aliasNodePair.first);
7592 xmlOut.addTextElementToData(
"GroupName", groupName);
7593 xmlOut.addTextElementToData(
"GroupKey", groupKey);
7594 xmlOut.addTextElementToData(
7596 aliasNodePair.second.getNode(TableViewColumnInfo::COL_NAME_COMMENT)
7597 .getValueAsString());
7601 ConfigurationManager::UNKNOWN_INFO;
7602 groupType = ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN;
7619 __SUP_COUT_WARN__ <<
"Failed to load group '" << groupName <<
"("
7620 << groupKey <<
")' to extract group comment and type."
7623 xmlOut.addTextElementToData(
"GroupComment", groupComment);
7624 xmlOut.addTextElementToData(
"GroupType", groupType);
7629 int threadsLaunched = 0;
7630 int foundThreadIndex = 0;
7631 std::vector<std::shared_ptr<std::atomic<bool>>> threadDone;
7632 for(
int i = 0; i < numOfThreads; ++i)
7633 threadDone.push_back(std::make_shared<std::atomic<bool>>(
true));
7635 std::vector<std::shared_ptr<ots::GroupInfo>> sharedGroupInfoPtrs;
7636 std::string groupName, groupKey;
7638 for(
auto& aliasNodePair : aliasNodePairs)
7641 sharedGroupInfoPtrs.push_back(std::make_shared<ots::GroupInfo>());
7643 groupName = aliasNodePair.second.getNode(
"GroupName").getValueAsString();
7644 groupKey = aliasNodePair.second.getNode(
"GroupKey").getValueAsString();
7646 if(threadsLaunched >= numOfThreads)
7649 foundThreadIndex = -1;
7650 while(foundThreadIndex == -1)
7652 for(
int i = 0; i < numOfThreads; ++i)
7653 if(*(threadDone[i]))
7655 foundThreadIndex = i;
7658 if(foundThreadIndex == -1)
7660 __SUP_COUTT__ <<
"Waiting for available thread..." << __E__;
7664 threadsLaunched = numOfThreads - 1;
7666 __SUP_COUTT__ <<
"Starting load group thread... " << groupName <<
"("
7667 << groupKey <<
")" << __E__;
7668 *(threadDone[foundThreadIndex]) =
false;
7672 std::string theGroupName,
7674 std::shared_ptr<ots::GroupInfo> theGroupInfo,
7675 std::shared_ptr<std::atomic<bool>> theThreadDone) {
7685 sharedGroupInfoPtrs.back(),
7686 threadDone[foundThreadIndex])
7697 foundThreadIndex = -1;
7698 for(
int i = 0; i < numOfThreads; ++i)
7699 if(!*(threadDone[i]))
7701 foundThreadIndex = i;
7704 if(foundThreadIndex != -1)
7706 __SUP_COUTT__ <<
"Waiting for thread to finish... " << foundThreadIndex
7710 }
while(foundThreadIndex != -1);
7714 for(
auto& aliasNodePair : aliasNodePairs)
7716 groupName = aliasNodePair.second.getNode(
"GroupName").getValueAsString();
7717 groupKey = aliasNodePair.second.getNode(
"GroupKey").getValueAsString();
7719 if(groupKey != sharedGroupInfoPtrs[i]->getLatestKey().toString())
7721 __SUP_SS__ <<
"Error loading group information for the group alias '"
7722 << aliasNodePair.first <<
"' mapping to group '" << groupName
7723 <<
"(" << groupKey <<
")" << __E__;
7727 xmlOut.addTextElementToData(
"GroupAlias", aliasNodePair.first);
7728 xmlOut.addTextElementToData(
"GroupName", groupName);
7729 xmlOut.addTextElementToData(
7730 "GroupKey", sharedGroupInfoPtrs[i]->getLatestKey().toString());
7731 xmlOut.addTextElementToData(
7733 aliasNodePair.second.getNode(TableViewColumnInfo::COL_NAME_COMMENT)
7734 .getValueAsString());
7736 xmlOut.addTextElementToData(
7737 "GroupComment", sharedGroupInfoPtrs[i]->getLatestKeyGroupComment());
7738 xmlOut.addTextElementToData(
7739 "GroupAuthor", sharedGroupInfoPtrs[i]->getLatestKeyGroupAuthor());
7740 xmlOut.addTextElementToData(
7741 "GroupCreationTime",
7742 sharedGroupInfoPtrs[i]->getLatestKeyGroupCreationTime());
7743 xmlOut.addTextElementToData(
7744 "GroupType", sharedGroupInfoPtrs[i]->getLatestKeyGroupTypeString());
7763 void ConfigurationGUISupervisor::handleVersionAliasesXML(
HttpXmlDocument& xmlOut,
7767 std::map<std::string, TableVersion> activeVersions = cfgMgr->
getActiveVersions();
7769 std::string versionAliasesTableName =
7770 ConfigurationManager::VERSION_ALIASES_TABLE_NAME;
7771 if(activeVersions.find(versionAliasesTableName) == activeVersions.end())
7773 __SUP_SS__ <<
"Active version of VersionAliases missing!"
7774 <<
"Make sure you have a valid active Backbone Group." << __E__;
7775 xmlOut.addTextElementToData(
"Error", ss.str());
7778 __SUP_COUT__ <<
"activeVersions[\"" << versionAliasesTableName
7779 <<
"\"]=" << activeVersions[versionAliasesTableName] << __E__;
7780 xmlOut.addTextElementToData(
"VersionAliasesVersion",
7781 activeVersions[versionAliasesTableName].toString());
7783 std::vector<std::pair<std::string, ConfigurationTree>> aliasNodePairs =
7786 for(
auto& aliasNodePair : aliasNodePairs)
7790 xmlOut.addTextElementToData(
7792 aliasNodePair.second.getNode(
"VersionAlias").getValueAsString());
7793 xmlOut.addTextElementToData(
7794 "TableName", aliasNodePair.second.getNode(
"TableName").getValueAsString());
7795 xmlOut.addTextElementToData(
7796 "Version", aliasNodePair.second.getNode(
"Version").getValueAsString());
7797 xmlOut.addTextElementToData(
7799 aliasNodePair.second.getNode(TableViewColumnInfo::COL_NAME_COMMENT)
7800 .getValueAsString());
7810 void ConfigurationGUISupervisor::handleGetTableGroupTypeXML(
7814 std::string name, versionStr;
7815 auto c = tableList.find(
',', 0);
7818 while(c < tableList.length())
7821 name = tableList.substr(i, c - i);
7823 c = tableList.find(
',', i);
7824 if(c == std::string::npos)
7826 __SUP_SS__ <<
"Incomplete Table Name-Version pair!" << __E__;
7827 __SUP_COUT_ERR__ <<
"\n" << ss.str();
7828 xmlOut.addTextElementToData(
"Error", ss.str());
7832 versionStr = tableList.substr(i, c - i);
7834 c = tableList.find(
',', i);
7839 std::string groupTypeString =
"";
7845 xmlOut.addTextElementToData(
"TableGroupType", groupTypeString);
7847 catch(std::runtime_error& e)
7849 __SUP_SS__ <<
"Table group has invalid type! " << e.what() << __E__;
7850 __SUP_COUT__ <<
"\n" << ss.str();
7851 groupTypeString = ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN;
7852 xmlOut.addTextElementToData(
"TableGroupType", groupTypeString);
7856 __SUP_SS__ <<
"Table group has invalid type! " << __E__;
7861 catch(
const std::exception& e)
7863 ss <<
"Exception message: " << e.what();
7868 __SUP_COUT__ <<
"\n" << ss.str();
7869 groupTypeString = ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN;
7870 xmlOut.addTextElementToData(
"TableGroupType", groupTypeString);
7890 void ConfigurationGUISupervisor::handleTableGroupsXML(
HttpXmlDocument& xmlOut,
7894 __SUP_COUTT__ <<
"cfgMgr runtime=" << cfgMgr->runTimeSeconds() << __E__;
7900 if(!cfgMgr->getAllGroupInfo().size() ||
7901 cfgMgr->getAllGroupInfo().begin()->second.getLatestKeyGroupTypeString() ==
"" ||
7902 cfgMgr->getAllGroupInfo().begin()->second.getLatestKeyGroupTypeString() ==
7903 ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN ||
7905 cfgMgr->getActiveGroupKey(ConfigurationManager::GroupType::CONTEXT_TYPE) !=
7906 TableGroupKey::INVALID &&
7907 cfgMgr->getAllGroupInfo().find(cfgMgr->getActiveGroupName(
7908 ConfigurationManager::GroupType::CONTEXT_TYPE)) !=
7909 cfgMgr->getAllGroupInfo().end() &&
7910 (cfgMgr->getAllGroupInfo()
7911 .at(cfgMgr->getActiveGroupName(
7912 ConfigurationManager::GroupType::CONTEXT_TYPE))
7913 .getLatestKeyGroupTypeString() ==
"" ||
7914 cfgMgr->getAllGroupInfo()
7915 .at(cfgMgr->getActiveGroupName(
7916 ConfigurationManager::GroupType::CONTEXT_TYPE))
7917 .getLatestKeyGroupTypeString() ==
7918 ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN)) ||
7920 cfgMgr->getActiveGroupKey(
7921 ConfigurationManager::GroupType::CONFIGURATION_TYPE) !=
7922 TableGroupKey::INVALID &&
7923 cfgMgr->getAllGroupInfo().find(cfgMgr->getActiveGroupName(
7924 ConfigurationManager::GroupType::CONFIGURATION_TYPE)) !=
7925 cfgMgr->getAllGroupInfo().end() &&
7926 (cfgMgr->getAllGroupInfo()
7927 .at(cfgMgr->getActiveGroupName(
7928 ConfigurationManager::GroupType::CONFIGURATION_TYPE))
7929 .getLatestKeyGroupTypeString() ==
"" ||
7930 cfgMgr->getAllGroupInfo()
7931 .at(cfgMgr->getActiveGroupName(
7932 ConfigurationManager::GroupType::CONFIGURATION_TYPE))
7933 .getLatestKeyGroupTypeString() ==
7934 ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN)))
7937 <<
"Group Info cache appears empty or stale. Attempting to regenerate..."
7947 const std::map<std::string, GroupInfo>& allGroupInfo = cfgMgr->getAllGroupInfo();
7949 __SUP_COUTT__ <<
"cfgMgr runtime=" << cfgMgr->runTimeSeconds() << __E__;
7951 std::string groupName;
7952 std::string groupString, groupTypeString, groupComment, groupCreationTime,
7954 for(
auto& groupInfo : allGroupInfo)
7956 groupName = groupInfo.first;
7961 if(groupInfo.second.getKeys().size() == 0)
7963 __SUP_COUT__ <<
"Group name '" << groupName
7964 <<
"' found, but no keys so ignoring." << __E__;
7968 xmlOut.dataSs_ <<
"<TableGroupName value='" << groupName <<
"'/>" << __E__;
7969 xmlOut.dataSs_ <<
"<TableGroupKey value='" << groupInfo.second.getLatestKey()
7973 xmlOut.dataSs_ <<
"<TableGroupType value='"
7974 << groupInfo.second.getLatestKeyGroupTypeString() <<
"'/>"
7976 xmlOut.dataSs_ <<
"<TableGroupComment value='"
7978 groupInfo.second.getLatestKeyGroupComment(),
7981 xmlOut.dataSs_ <<
"<TableGroupAuthor value='"
7982 << groupInfo.second.getLatestKeyGroupAuthor() <<
"'/>" << __E__;
7983 xmlOut.dataSs_ <<
"<TableGroupCreationTime value='"
7984 << groupInfo.second.getLatestKeyGroupCreationTime() <<
"'/>"
7990 xmlOut.dataSs_ <<
"<TableGroupMembers value=''>" << __E__;
7992 for(
auto& memberPair : groupInfo.second.getLatestKeyMemberMap())
7994 xmlOut.dataSs_ <<
"\t<MemberName value='" << memberPair.first <<
"'/>"
7996 xmlOut.dataSs_ <<
"\t<MemberVersion value='" << memberPair.second <<
"'/>"
8003 xmlOut.dataSs_ <<
"</TableGroupMembers>" << __E__;
8008 for(
auto& keyInSet : groupInfo.second.getKeys())
8010 if(keyInSet == groupInfo.second.getLatestKey())
8013 xmlOut.dataSs_ <<
"<TableGroupName value='" << groupName <<
"'/>" << __E__;
8014 xmlOut.dataSs_ <<
"<TableGroupKey value='" << keyInSet <<
"'/>" << __E__;
8019 bool loadingHistoricalInfo =
false;
8020 if(loadingHistoricalInfo)
8039 groupTypeString = ConfigurationManager::GROUP_TYPE_NAME_UNKNOWN;
8040 __SUP_COUT_WARN__ <<
"Failed to load group '" << groupName <<
"("
8042 <<
")' to extract group comment and type." << __E__;
8045 xmlOut.dataSs_ <<
"<TableGroupType value='" << groupTypeString <<
"'/>"
8047 xmlOut.dataSs_ <<
"<TableGroupComment value='"
8051 xmlOut.dataSs_ <<
"<TableGroupAuthor value='" << groupAuthor <<
"'/>"
8053 xmlOut.dataSs_ <<
"<TableGroupCreationTime value='" << groupCreationTime
8063 xmlOut.dataSs_ <<
"<TableGroupType value='"
8064 << groupInfo.second.getLatestKeyGroupTypeString() <<
"'/>"
8067 xmlOut.dataSs_ <<
"<TableGroupComment value='"
8070 xmlOut.dataSs_ <<
"<TableGroupAuthor value='"
8073 xmlOut.dataSs_ <<
"<TableGroupCreationTime value='"
8081 xmlOut.dataSs_ <<
"<TableGroupMembers/>" << __E__;
8086 __SUP_COUTT__ << groupName <<
" runtime=" << cfgMgr->runTimeSeconds() << __E__;
8088 __SUP_COUTT__ <<
"cfgMgr runtime=" << cfgMgr->runTimeSeconds() << __E__;
8110 void ConfigurationGUISupervisor::handleTablesXML(
HttpXmlDocument& xmlOut,
8112 const std::string& filterStartTimeStr,
8113 const std::string& filterEndTimeStr,
8114 const std::string& filterMode)
8116 time_t filterStartTime = 0;
8117 time_t filterEndTime = 0;
8118 if(filterStartTimeStr !=
"")
8122 filterStartTime =
static_cast<time_t
>(std::stoll(filterStartTimeStr));
8124 catch(
const std::exception& e)
8126 __SUP_SS__ <<
"Error parsing startTime parameter: " << e.what() << __E__;
8127 __SUP_COUT_ERR__ <<
"\n" << ss.str();
8128 xmlOut.addTextElementToData(
"Error", ss.str());
8132 if(filterEndTimeStr !=
"")
8136 filterEndTime =
static_cast<time_t
>(std::stoll(filterEndTimeStr));
8138 catch(
const std::exception& e)
8140 __SUP_SS__ <<
"Error parsing endTime parameter: " << e.what() << __E__;
8141 __SUP_COUT_ERR__ <<
"\n" << ss.str();
8142 xmlOut.addTextElementToData(
"Error", ss.str());
8146 if(filterStartTime != 0 && filterEndTime != 0 && filterStartTime > filterEndTime)
8148 __SUP_SS__ <<
"Invalid time range: startTime (" << filterStartTime
8149 <<
") must be <= endTime (" << filterEndTime <<
")." << __E__;
8152 if(filterMode !=
"created" && filterMode !=
"loaded")
8154 __SUP_SS__ <<
"Invalid filterMode parameter '" << filterMode
8155 <<
".' Expected 'created' or 'loaded.'" << __E__;
8156 __SUP_COUT_ERR__ <<
"\n" << ss.str();
8157 xmlOut.addTextElementToData(
"Error", ss.str());
8161 const auto diagStartTime = std::chrono::steady_clock::now();
8162 auto diagElapsedSec = [](
const std::chrono::steady_clock::time_point& start) {
8163 return std::chrono::duration<double>(std::chrono::steady_clock::now() - start)
8167 if(cfgMgr->getAllGroupInfo().size() == 0 || cfgMgr->
getActiveVersions().size() == 0)
8169 __SUP_COUT__ <<
"Table Info cache appears empty. Attempting to regenerate."
8177 __SUP_COUT__ <<
"getAllTableInfo() regenerate took "
8178 << diagElapsedSec(diagStartTime) <<
" s" << __E__;
8181 xercesc::DOMElement* parentEl;
8182 const std::map<std::string, TableInfo>& allTableInfo = cfgMgr->
getAllTableInfo();
8185 std::set<std::string, StringMacros::IgnoreCaseCompareStruct> orderedTableSet;
8186 for(
const auto& tablePair : allTableInfo)
8187 orderedTableSet.emplace(tablePair.first);
8191 __SUP_COUT__ <<
"# of tables to consider: " << allTableInfo.size() << __E__;
8193 const auto diagAliasStartTime = std::chrono::steady_clock::now();
8194 std::map<std::string, std::map<std::string, TableVersion>> versionAliases =
8197 __SUP_COUT__ <<
"# of tables w/aliases: " << versionAliases.size() <<
" (took "
8198 << diagElapsedSec(diagAliasStartTime) <<
" s)" << __E__;
8200 if(filterStartTime != 0 && filterEndTime != 0 && filterMode ==
"created")
8205 const auto diagPreloadStartTime = std::chrono::steady_clock::now();
8207 __SUP_COUT__ <<
"Version creation time cache pre-warm took "
8208 << diagElapsedSec(diagPreloadStartTime) <<
" s" << __E__;
8212 size_t diagNumTablesFound = 0;
8213 size_t diagNumVersionsConsidered = 0;
8214 size_t diagNumVersionsMatched = 0;
8215 size_t diagNumTimeLookups = 0;
8216 double diagTimeLookupSec = 0;
8217 double diagSlowestTableSec = 0;
8218 std::string diagSlowestTableName =
"";
8219 size_t diagTableCount = 0;
8221 for(
const auto& orderedTableName : orderedTableSet)
8224 std::map<std::string, TableInfo>::const_iterator it =
8225 allTableInfo.find(orderedTableName);
8226 if(it == allTableInfo.end())
8228 __SS__ <<
"Impossible missing table in map '" << orderedTableName <<
"'"
8237 xmlOut.addTextElementToData(
"TableName", it->first);
8238 parentEl = xmlOut.addTextElementToData(
"TableVersions",
"");
8241 if(versionAliases.find(it->first) != versionAliases.end())
8242 for(
auto& aliasVersion : versionAliases[it->first])
8243 if(it->second.versions_.find(aliasVersion.second) !=
8244 it->second.versions_
8248 ConfigurationManager::ALIAS_VERSION_PREAMBLE + aliasVersion.first,
8256 auto vSpanToXML = [&diagNumVersionsConsidered,
8257 &diagNumVersionsMatched,
8258 &diagNumTimeLookups,
8259 &diagTimeLookupSec](
auto const& sortedKeys,
8262 const std::string& tableName,
8264 const time_t filterStartTime,
8265 const time_t filterEndTime,
8266 const std::string& filterMode) {
8268 size_t lo = -1, hi = -1;
8269 bool allVersionsFiltered =
true;
8270 for(
auto& keyInOrder : sortedKeys)
8273 if(keyInOrder.isScratchVersion())
8276 ++diagNumVersionsConsidered;
8278 if(filterStartTime != 0 && filterEndTime != 0)
8280 const auto diagLookupStartTime = std::chrono::steady_clock::now();
8289 time_t tableVersionTime =
8290 filterMode ==
"loaded"
8291 ? cfgMgr->getVersionLastAccessTime(tableName, keyInOrder)
8292 : cfgMgr->getVersionCreationTime(tableName, keyInOrder);
8294 ++diagNumTimeLookups;
8295 diagTimeLookupSec +=
8296 std::chrono::duration<double>(
8297 std::chrono::steady_clock::now() - diagLookupStartTime)
8300 if(tableVersionTime < filterStartTime ||
8301 tableVersionTime > filterEndTime)
8305 __COUTT__ <<
"Table '" << tableName <<
"' version v"
8306 << keyInOrder <<
" " << filterMode
8307 <<
" time is outside the filter range, so "
8313 catch(
const std::runtime_error&)
8315 ++diagNumTimeLookups;
8316 diagTimeLookupSec +=
8317 std::chrono::duration<double>(
8318 std::chrono::steady_clock::now() - diagLookupStartTime)
8320 __COUT__ <<
"Failed to get " << filterMode <<
" time for table '"
8321 << tableName <<
"' version v" << keyInOrder
8322 <<
", so skipping." << __E__;
8327 allVersionsFiltered =
false;
8328 ++diagNumVersionsMatched;
8330 if(lo ==
size_t(-1))
8332 hi = lo = keyInOrder.
version();
8335 else if(hi + 1 == keyInOrder.version())
8343 xmlOut.addNumberElementToParent(
"Version", lo, configEl);
8345 xmlOut.addTextElementToParent(
8347 "_" + std::to_string(lo) +
"_" + std::to_string(hi),
8349 hi = lo = keyInOrder.
version();
8352 if(lo !=
size_t(-1))
8355 xmlOut.addNumberElementToParent(
"Version", lo, configEl);
8357 xmlOut.addTextElementToParent(
8359 "_" + std::to_string(lo) +
"_" + std::to_string(hi),
8362 return allVersionsFiltered;
8365 const auto diagTableStartTime = std::chrono::steady_clock::now();
8366 if(vSpanToXML(it->second.versions_,
8374 filterStartTime != 0 && filterEndTime != 0)
8380 unsigned int childCount = xmlOut.getChildrenCount();
8383 xmlOut.removeDataElement(childCount - 1);
8384 xmlOut.removeDataElement(childCount - 2);
8388 ++diagNumTablesFound;
8391 double diagTableSec = diagElapsedSec(diagTableStartTime);
8392 if(diagTableSec > diagSlowestTableSec)
8394 diagSlowestTableSec = diagTableSec;
8395 diagSlowestTableName = it->first;
8397 if(diagTableSec > 1.0)
8398 __SUP_COUT__ <<
"Slow table filter: '" << it->first <<
"' with "
8399 << it->second.versions_.size() <<
" versions took "
8400 << diagTableSec <<
" s" << __E__;
8402 if(diagTableCount % 50 == 0)
8403 __SUP_COUT__ <<
"getTables filter progress: " << diagTableCount <<
" of "
8404 << orderedTableSet.size() <<
" tables in "
8405 << diagElapsedSec(diagStartTime) <<
" s (" << diagNumTimeLookups
8406 <<
" version time lookups taking " << diagTimeLookupSec
8407 <<
" s so far)" << __E__;
8412 xmlOut.addTextElementToData(
"NumberOfTablesConsidered",
8413 std::to_string(allTableInfo.size()));
8414 xmlOut.addTextElementToData(
"NumberOfTablesFound",
8415 std::to_string(diagNumTablesFound));
8416 xmlOut.addTextElementToData(
"NumberOfVersionsConsidered",
8417 std::to_string(diagNumVersionsConsidered));
8418 xmlOut.addTextElementToData(
"NumberOfVersionsFound",
8419 std::to_string(diagNumVersionsMatched));
8421 __SUP_COUT__ <<
"getTables filter summary: mode=" << filterMode <<
" range=["
8422 << filterStartTime <<
"," << filterEndTime <<
"]"
8423 <<
" tables considered=" << allTableInfo.size()
8424 <<
" found=" << diagNumTablesFound
8425 <<
"; versions considered=" << diagNumVersionsConsidered
8426 <<
" matched=" << diagNumVersionsMatched <<
"; " << diagNumTimeLookups
8427 <<
" version time lookups took " << diagTimeLookupSec
8428 <<
" s; slowest table '" << diagSlowestTableName <<
"' took "
8429 << diagSlowestTableSec <<
" s; total " << diagElapsedSec(diagStartTime)
8441 void ConfigurationGUISupervisor::handleGetArtdaqNodeRecordsXML(
8444 const std::string& modifiedTables)
8446 __COUT__ <<
"Retrieving artdaq nodes..." << __E__;
8449 setupActiveTablesXML(
8450 xmlOut, cfgMgr,
"",
TableGroupKey(-1), modifiedTables,
false );
8452 std::map<std::string ,
8453 std::map<std::string , std::vector<std::string >>>
8454 nodeTypeToObjectMap;
8455 std::map<std::string , std::string >
8458 std::vector<std::string > artdaqSupervisorInfo;
8460 std::string artdaqSupervisorName;
8462 cfgMgr, nodeTypeToObjectMap, subsystemObjectMap, artdaqSupervisorInfo);
8464 if(artdaqSupervisorInfo.size() != 4 )
8466 __SUP_COUT__ <<
"No artdaq supervisor found." << __E__;
8470 __SUP_COUT__ <<
"========== "
8471 <<
"Found " << info.subsystems.size() <<
" subsystems." << __E__;
8473 unsigned int paramIndex = 0;
8475 auto parentEl = xmlOut.addTextElementToData(
"artdaqSupervisor",
8476 artdaqSupervisorInfo[paramIndex++]);
8478 std::string typeString =
"artdaqSupervisor";
8481 typeString +
"-status", artdaqSupervisorInfo[paramIndex++], parentEl);
8483 typeString +
"-contextAddress", artdaqSupervisorInfo[paramIndex++], parentEl);
8485 typeString +
"-contextPort", artdaqSupervisorInfo[paramIndex++], parentEl);
8487 for(
auto& subsystem : info.subsystems)
8489 typeString =
"subsystem";
8491 __SUP_COUT__ <<
"\t\t"
8492 <<
"Found " << typeString <<
" " << subsystem.first <<
" \t := '"
8493 << subsystem.second.label <<
"'" << __E__;
8497 typeString +
"-id", std::to_string(subsystem.first), parentEl);
8500 std::to_string(subsystem.second.sources.size()),
8505 std::to_string(subsystem.second.destination),
8510 __SUP_COUT__ <<
"========== "
8511 <<
"Found " << nodeTypeToObjectMap.size() <<
" process types." << __E__;
8513 for(
auto& nameTypePair : nodeTypeToObjectMap)
8515 typeString = nameTypePair.first;
8517 __SUP_COUT__ <<
"\t"
8518 <<
"Found " << nameTypePair.second.size() <<
" " << typeString
8521 for(
auto& artdaqNode : nameTypePair.second)
8523 __SUP_COUT__ <<
"\t\t"
8524 <<
"Found '" << artdaqNode.first <<
"' " << typeString << __E__;
8527 if(artdaqNode.second.size() < 2)
8529 __SUP_SS__ <<
"Impossible parameter size for node '" << artdaqNode.first
8530 <<
"' " << typeString <<
" - please notify admins!" << __E__;
8538 if(artdaqNode.second.size() > paramIndex)
8540 __SUP_COUTT__ <<
"\t\t\t"
8541 <<
"-multinode: " << artdaqNode.second[paramIndex] << __E__;
8543 typeString +
"-multinode", artdaqNode.second[paramIndex++], nodeEl);
8545 if(artdaqNode.second.size() > paramIndex)
8547 __SUP_COUTT__ <<
"\t\t\t"
8548 <<
"-nodefixedwidth: " << artdaqNode.second[paramIndex]
8551 artdaqNode.second[paramIndex++],
8554 if(artdaqNode.second.size() > paramIndex)
8556 __SUP_COUTT__ <<
"\t\t\t"
8557 <<
"-hostarray: " << artdaqNode.second[paramIndex] << __E__;
8559 typeString +
"-hostarray", artdaqNode.second[paramIndex++], nodeEl);
8561 if(artdaqNode.second.size() > paramIndex)
8563 __SUP_COUTT__ <<
"\t\t\t"
8564 <<
"-hostfixedwidth: " << artdaqNode.second[paramIndex]
8567 artdaqNode.second[paramIndex++],
8572 __SUP_COUTT__ <<
"\t\t\t"
8573 <<
"-status: " << artdaqNode.second[paramIndex] << __E__;
8575 typeString +
"-status", artdaqNode.second[paramIndex++], parentEl);
8576 __SUP_COUTT__ <<
"\t\t\t"
8577 <<
"-hostname: " << artdaqNode.second[paramIndex] << __E__;
8579 typeString +
"-hostname", artdaqNode.second[paramIndex++], parentEl);
8580 __SUP_COUTT__ <<
"\t\t\t"
8581 <<
"-subsystem: " << artdaqNode.second[paramIndex] << __E__;
8583 typeString +
"-subsystem", artdaqNode.second[paramIndex], parentEl);
8587 __SUP_COUT__ <<
"Done retrieving artdaq nodes." << __E__;
8598 void ConfigurationGUISupervisor::handleSaveArtdaqNodeRecordsXML(
8599 const std::string& nodeString,
8600 const std::string& subsystemString,
8603 const std::string& modifiedTables)
8605 __SUP_COUT__ <<
"Saving artdaq nodes..." << __E__;
8608 setupActiveTablesXML(
8609 xmlOut, cfgMgr,
"",
TableGroupKey(-1), modifiedTables,
false );
8612 std::map<std::string ,
8613 std::map<std::string , std::vector<std::string >>>
8614 nodeTypeToObjectMap;
8620 std::map<std::string , std::string >
8621 nodeTypeToStringMap;
8626 for(
auto& typePair : nodeTypeToStringMap)
8628 if(typePair.first ==
"")
8633 nodeTypeToObjectMap.emplace(
8635 std::map<std::string ,
8636 std::vector<std::string /*property*/>>()));
8638 std::map<std::string , std::string >
8639 nodeRecordToStringMap;
8642 typePair.second, nodeRecordToStringMap, {
';'}, {
'='});
8646 for(
auto& nodePair : nodeRecordToStringMap)
8648 if(nodePair.first ==
"")
8653 std::vector<std::string > nodePropertyVector;
8656 nodePair.second, nodePropertyVector, {
','});
8661 for(
unsigned int i = 0; i < nodePropertyVector.size(); ++i)
8666 nodePropertyVector[i] =
8670 nodeTypeToObjectMap[typePair.first].emplace(
8672 nodePropertyVector));
8678 std::map<std::string , std::string >
8685 std::map<std::string , std::string >
8686 tmpSubsystemObjectMap;
8688 subsystemString, tmpSubsystemObjectMap, {
';'}, {
':'});
8693 for(
auto& subsystemPair : tmpSubsystemObjectMap)
8698 subsystemObjectMap.emplace(
8705 cfgMgr, nodeTypeToObjectMap, subsystemObjectMap);
8707 __SUP_COUT__ <<
"Done saving artdaq nodes." << __E__;
8717 void ConfigurationGUISupervisor::handleLoadArtdaqNodeLayoutXML(
8721 const std::string& contextGroupName ,
8724 bool usingActiveGroups = (contextGroupName ==
"" || contextGroupKey.
isInvalid());
8727 const std::string& finalContextGroupName =
8729 ? cfgMgr->getActiveGroupName(ConfigurationManager::GroupType::CONTEXT_TYPE)
8733 ? cfgMgr->getActiveGroupKey(ConfigurationManager::GroupType::CONTEXT_TYPE)
8735 const std::string& finalConfigGroupName =
8736 cfgMgr->getActiveGroupName(ConfigurationManager::GroupType::CONFIGURATION_TYPE);
8738 cfgMgr->getActiveGroupKey(ConfigurationManager::GroupType::CONFIGURATION_TYPE);
8743 std::stringstream layoutPath;
8744 layoutPath << ARTDAQTableBase::ARTDAQ_CONFIG_LAYOUTS_PATH << finalContextGroupName
8745 <<
"_" << finalContextGroupKey <<
"." << finalConfigGroupName <<
"_"
8746 << finalConfigGroupKey <<
".dat";
8748 fp = fopen(layoutPath.str().c_str(),
"r");
8751 __SUP_COUT__ <<
"Layout file not found for '" << finalContextGroupName <<
"("
8752 << finalContextGroupKey <<
") + " << finalConfigGroupName <<
"("
8753 << finalConfigGroupKey <<
")': " << layoutPath.
str() << __E__;
8757 __SUP_COUTV__(layoutPath.str());
8762 std::stringstream layoutPath;
8763 layoutPath << ARTDAQTableBase::ARTDAQ_CONFIG_LAYOUTS_PATH << finalContextGroupName
8764 <<
"_" << finalContextGroupKey <<
".dat";
8765 __SUP_COUTV__(layoutPath.str());
8767 fp = fopen(layoutPath.str().c_str(),
"r");
8770 __SUP_COUT__ <<
"Layout file not found for '" << finalContextGroupName <<
"("
8771 << finalContextGroupKey <<
")': " << layoutPath.str() << __E__;
8775 __SUP_COUTV__(layoutPath.str());
8782 const size_t maxLineSz = 1000;
8783 char line[maxLineSz];
8784 if(!fgets(line, maxLineSz, fp))
8793 unsigned int rows, cols;
8795 sscanf(line,
"%u %u", &rows, &cols);
8797 __COUT__ <<
"Grid rows,cols = " << rows <<
"," << cols << __E__;
8799 xmlOut.addTextElementToData(
"grid-rows", std::to_string(rows));
8800 xmlOut.addTextElementToData(
"grid-cols", std::to_string(cols));
8803 char name[maxLineSz];
8804 char type[maxLineSz];
8806 while(fgets(line, maxLineSz, fp))
8809 sscanf(line,
"%s %s %u %u", type, name, &x, &y);
8811 xmlOut.addTextElementToData(
"node-type", type);
8812 xmlOut.addTextElementToData(
"node-name", name);
8813 xmlOut.addTextElementToData(
"node-x", std::to_string(x));
8814 xmlOut.addTextElementToData(
"node-y", std::to_string(y));
8828 void ConfigurationGUISupervisor::handleSaveArtdaqNodeLayoutXML(
8831 const std::string& layoutString,
8832 const std::string& contextGroupName,
8835 bool usingActiveGroups = (contextGroupName ==
"" || contextGroupKey.
isInvalid());
8837 const std::string& finalContextGroupName =
8839 ? cfgMgr->getActiveGroupName(ConfigurationManager::GroupType::CONTEXT_TYPE)
8843 ? cfgMgr->getActiveGroupKey(ConfigurationManager::GroupType::CONTEXT_TYPE)
8845 const std::string& finalConfigGroupName =
8846 cfgMgr->getActiveGroupName(ConfigurationManager::GroupType::CONFIGURATION_TYPE);
8848 cfgMgr->getActiveGroupKey(ConfigurationManager::GroupType::CONFIGURATION_TYPE);
8850 __SUP_COUTV__(layoutString);
8852 std::stringstream layoutPath;
8853 layoutPath << ARTDAQTableBase::ARTDAQ_CONFIG_LAYOUTS_PATH << finalContextGroupName
8854 <<
"_" << finalContextGroupKey <<
"." << finalConfigGroupName <<
"_"
8855 << finalConfigGroupKey <<
".dat";
8856 __SUP_COUTV__(layoutPath.str());
8861 if(fields.size() < 2 || (fields.size() - 2) % 4 != 0)
8863 __SUP_SS__ <<
"Invalid layout string fields size of " << fields.size() << __E__;
8867 FILE* fp = fopen(layoutPath.str().c_str(),
"w");
8870 __SUP_SS__ <<
"Could not open layout file for writing for '"
8871 << finalContextGroupName <<
"(" << finalContextGroupKey <<
") + "
8872 << finalConfigGroupName <<
"(" << finalConfigGroupKey
8873 <<
")': " << layoutPath.
str() << __E__;
8880 fprintf(fp,
"%s %s\n", fields[0].c_str(), fields[1].c_str());
8883 for(
unsigned int i = 2; i < fields.size(); i += 4)
8886 fields[i + 0].c_str(),
8887 fields[i + 1].c_str(),
8888 fields[i + 2].c_str(),
8889 fields[i + 3].c_str());
8897 void ConfigurationGUISupervisor::handleOtherSubsystemActiveGroups(
8901 std::string targetSubsystem )
8907 cfgMgr->
getNode(ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE);
8910 for(
auto subsystem : children)
8912 __SUP_COUTV__(subsystem.first);
8916 std::string userPath =
8917 subsystem.second.getNode(
"SubsystemUserDataPath").getValue();
8918 __SUP_COUTV__(userPath);
8921 catch(
const std::runtime_error& e)
8923 __SUP_COUT__ <<
"Ignoring errors in handling other subsystem active groups "
8924 "(assuming the subsystem information map is not setup in "
8925 << ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE
8926 <<
") -- here is the error: \n"
8927 << e.what() << __E__;
8934 cfgMgr->
getNode(ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE);
8936 for(
auto subsystem : children)
8938 if(targetSubsystem !=
"" && targetSubsystem != subsystem.first)
8941 xercesc::DOMElement* parent =
8942 xmlOut.addTextElementToData(
"SubsystemName", subsystem.first);
8947 std::string filename, userDataPath;
8948 std::string username, hostname;
8950 std::map<std::string ,
8952 retMap = cfgMgr->getOtherSubsystemActiveTableGroups(
8953 subsystem.first, &userDataPath, &hostname, &username);
8955 for(
const auto& retPair : retMap)
8958 retPair.second.first,
8961 retPair.second.second.toString(),
8965 std::vector<std::string> filenameTypes = {
"Configured",
8969 "ActivatedBackbone",
8970 "ActivatedIterator"};
8972 std::vector<std::string> filenames = {
8973 ConfigurationManager::LAST_CONFIGURED_CONFIG_GROUP_FILE,
8974 ConfigurationManager::LAST_STARTED_CONFIG_GROUP_FILE,
8975 ConfigurationManager::LAST_ACTIVATED_CONFIG_GROUP_FILE,
8976 ConfigurationManager::LAST_ACTIVATED_CONTEXT_GROUP_FILE,
8977 ConfigurationManager::LAST_ACTIVATED_BACKBONE_GROUP_FILE,
8978 ConfigurationManager::LAST_ACTIVATED_ITERATE_GROUP_FILE};
8980 std::string userPath =
8981 subsystem.second.getNode(
"SubsystemUserDataPath").getValue();
8983 std::string cmdResult;
8984 for(
unsigned int i = 0; i < filenames.size(); ++i)
8986 filename = userDataPath +
"/ServiceData/RunControlData/" + filenames[i];
8987 __SUP_COUTV__(filename);
8989 std::string tmpSubsystemFilename =
8990 ConfigurationManager::LAST_TABLE_GROUP_SAVE_PATH +
"/" + filenames[i] +
8991 "." + subsystem.first;
8992 __SUP_COUTV__(tmpSubsystemFilename);
8994 if(splitPath.size() == 2)
8998 (
"rm " + tmpSubsystemFilename +
" 2>/dev/null; scp " + username +
8999 "@" + hostname +
":" + filename +
" " + tmpSubsystemFilename +
9000 " 2>&1; cat " + tmpSubsystemFilename +
" 2>&1")
9004 (
"rm " + tmpSubsystemFilename +
" 2>/dev/null; scp " + hostname +
9005 ":" + filename +
" " + tmpSubsystemFilename +
" 2>&1; cat " +
9006 tmpSubsystemFilename +
" 2>&1")
9009 else if(splitPath.size() == 1)
9012 " 2>/dev/null; cp " + filename +
" " +
9013 tmpSubsystemFilename +
" 2>&1; cat " +
9014 tmpSubsystemFilename +
" 2>&1")
9018 __SUP_COUTV__(cmdResult);
9019 std::string timeString;
9022 filenames[i] +
"." + subsystem.first, timeString);
9026 "Last" + filenameTypes[i] +
"GroupName", theGroup.first, parent);
9028 theGroup.second.toString(),
9031 "Last" + filenameTypes[i] +
"GroupTime", timeString, parent);
9036 catch(
const std::runtime_error& e)
9039 <<
"An error occurred handling subsystem active groups (Please check the "
9040 "subsystem user data path information map setup in the Context group table "
9041 << ConfigurationManager::CONTEXT_SUBSYSTEM_OPTIONAL_TABLE
9042 <<
") -- here is the error: \n"
9043 << e.what() << __E__;
9049 void ConfigurationGUISupervisor::handleSearchFieldInGroupXML(
9052 const std::string& searchText,
9053 const bool activeGroupsOnly,
9054 const std::string& groupType,
9055 const std::string& optionGroups,
9056 const std::string& versionsToCheck)
9059 if(searchText.empty() || searchText.find_first_not_of(
" \t\r\n") == std::string::npos)
9061 __COUT_WARN__ <<
"searchText is empty or whitespace; aborting search." << __E__;
9062 xmlOut.addTextElementToData(
"Error",
"Search text must not be empty.");
9066 bool searchAllGroups =
false;
9067 if(optionGroups.size() == 0)
9069 __COUT__ <<
"No optionGroups specified, searching all groups of type "
9070 << groupType << __E__;
9071 searchAllGroups =
true;
9073 std::vector<std::string> optionGroupsList =
9076 const std::map<std::string, GroupInfo>& allGroupInfo = cfgMgr->getAllGroupInfo();
9078 int searchMinThreshold = 0;
9079 int searchMaxThreshold = 0;
9080 size_t dashPos = -1;
9083 if(versionsToCheck.empty())
9085 searchMaxThreshold = INT_MAX;
9087 else if(versionsToCheck.find(
'-') != std::string::npos)
9089 __COUT__ <<
"Parsing versionsToCheck for range: " << versionsToCheck << __E__;
9090 dashPos = versionsToCheck.find(
'-');
9095 std::string minStr = versionsToCheck.substr(0, dashPos);
9096 std::string maxStr = versionsToCheck.substr(dashPos + 1);
9098 searchMinThreshold = atoi(minStr.c_str());
9099 searchMaxThreshold = atoi(maxStr.c_str());
9102 else if(versionsToCheck !=
"")
9105 searchMinThreshold = atoi(versionsToCheck.c_str());
9106 searchMaxThreshold = INT_MAX;
9110 __COUT__ <<
"Unable to set min and max thresholds for versionsToCheck: "
9111 << versionsToCheck << __E__;
9112 xmlOut.addTextElementToData(
9114 "Unable to set min and max thresholds for versionsToCheck: " +
9117 __SUP_COUT__ <<
"versionsToCheck range: " << searchMinThreshold <<
" to "
9118 << searchMaxThreshold << __E__;
9120 auto parentEl = xmlOut.addTextElementToData(
"SearchResults",
"");
9122 for(
auto& groupInfo : allGroupInfo)
9124 __COUT__ <<
"Checking group: " << groupInfo.first
9125 <<
" group type : " << groupInfo.second.getLatestKeyGroupTypeString()
9128 if(groupInfo.second.getLatestKeyGroupTypeString() != groupType)
9132 if(!searchAllGroups &&
9133 std::find(optionGroupsList.begin(), optionGroupsList.end(), groupInfo.first) ==
9134 optionGroupsList.end())
9136 __COUT__ <<
"\tSkipping group not in optionGroups list." << __E__;
9140 std::set<
TableGroupKey > allGroupKeys = groupInfo.second.getKeys();
9142 std::vector<TableGroupKey> groupKeysVec(allGroupKeys.begin(), allGroupKeys.end());
9145 __COUT__ <<
"Group keys:" << groupKeysStr << __E__;
9150 std::string offsetStr = versionsToCheck.substr(1);
9152 atoi(offsetStr.c_str()) - 1;
9154 __SUP_COUT__ <<
"versionsToCheck offset from end: " << offset << __E__;
9157 if(groupKeysVec.size() > 0)
9160 groupKeysVec.size() - 1);
9161 int maxVersionNum = std::stoi(maxVersion.
toString());
9162 int minVersionNum = std::max(0, maxVersionNum - offset);
9164 searchMinThreshold = minVersionNum;
9165 searchMaxThreshold = maxVersionNum;
9167 __SUP_COUT__ <<
"Version range: " << searchMinThreshold <<
" to "
9168 << searchMaxThreshold << __E__;
9174 if(activeGroupsOnly)
9176 std::set<TableGroupKey> singleKeySet;
9177 singleKeySet.insert(groupInfo.second.getLatestKey());
9178 groupKeys = std::move(singleKeySet);
9181 groupKeys = std::move(allGroupKeys);
9183 for(
const auto& groupKey : groupKeys)
9185 __COUT__ <<
"\tProcessing group: " << groupInfo.first <<
" v" << groupKey
9188 if(!activeGroupsOnly &&
9189 (std::stoi(groupKey.toString()) < searchMinThreshold ||
9190 std::stoi(groupKey.toString()) > searchMaxThreshold))
9192 __COUT__ <<
"\tSkipping group version outside of versionsToCheck range."
9213 for(
auto& tablePair : memberMap)
9215 __COUT__ <<
"\t\tTable: " << tablePair.first <<
" v"
9216 << tablePair.second << __E__;
9222 tablePair.first, tablePair.second);
9225 const TableView& tableView = memberTable->getView();
9228 for(
unsigned int row = 0; row < tableView.getNumberOfRows();
9231 for(
unsigned int col = 0;
9232 col < tableView.getNumberOfColumns();
9235 const std::string& cellValue =
9236 tableView.getDataView()[row][col];
9239 if(cellValue.find(searchText) != std::string::npos)
9241 __COUT__ <<
"\t\t\tMatch found in " << tablePair.first
9242 <<
" v" << tablePair.second <<
" row " << row
9243 <<
" column " << col
9244 <<
" value: " << cellValue << __E__;
9248 groupInfo.first +
"/" + tablePair.first,
9251 "MatchRow", std::to_string(row), groupTableEl);
9254 tableView.getColumnInfo(col).getName(),
9257 groupKey.toString(),
9260 "MatchTableVersion",
9261 tablePair.second.toString(),
9267 catch(
const std::runtime_error& e)
9269 __COUT_WARN__ <<
"Failed to search table " << tablePair.first
9270 <<
" v" << tablePair.second <<
": " << e.what()
9275 catch(
const std::runtime_error& e)
9277 __COUT_WARN__ <<
"Failed to load group members for " << groupInfo.first
9278 <<
": " << e.what() << __E__;
9286 void ConfigurationGUISupervisor::handleSearchFieldInTableXML(
9289 const std::string& searchText,
9290 const std::string& tableName,
9291 const std::string& searchVersionToCheck,
9292 bool activeTablesOnly)
9295 if(searchText.empty() || searchText.find_first_not_of(
" \t\r\n") == std::string::npos)
9297 __COUT_WARN__ <<
"searchText is empty or whitespace; aborting search." << __E__;
9298 xmlOut.addTextElementToData(
"Error",
"Search text must not be empty.");
9302 const std::map<std::string, TableInfo>& allTableInfo = cfgMgr->
getAllTableInfo();
9303 std::map<std::string, TableVersion> allActivePairs = cfgMgr->
getActiveVersions();
9305 int searchMinThreshold = 0;
9306 int searchMaxThreshold = 0;
9309 if(searchVersionToCheck.empty())
9311 searchMaxThreshold = INT_MAX;
9313 else if(searchVersionToCheck.find(
'-') != std::string::npos)
9315 size_t dashPos = searchVersionToCheck.find(
'-');
9320 std::string offsetStr = searchVersionToCheck.substr(1);
9322 atoi(offsetStr.c_str()) - 1;
9324 __SUP_COUT__ <<
"searchVersionToCheck offset from end: " << offset << __E__;
9327 if(allTableInfo.find(tableName) != allTableInfo.end())
9329 const TableInfo& tableInfo = allTableInfo.at(tableName);
9330 if(tableInfo.versions_.size() > 0)
9332 auto maxVersionIter = tableInfo.versions_.rbegin();
9333 int maxVersionNum = maxVersionIter->version();
9334 int minVersionNum = std::max(0, maxVersionNum - offset);
9336 searchMinThreshold = minVersionNum;
9337 searchMaxThreshold = maxVersionNum;
9339 __SUP_COUT__ <<
"Version range: " << searchMinThreshold <<
" to "
9340 << searchMaxThreshold << __E__;
9347 std::string minStr = searchVersionToCheck.substr(0, dashPos);
9348 std::string maxStr = searchVersionToCheck.substr(dashPos + 1);
9350 searchMinThreshold = atoi(minStr.c_str());
9351 searchMaxThreshold = atoi(maxStr.c_str());
9354 else if(searchVersionToCheck !=
"")
9357 searchMinThreshold = atoi(searchVersionToCheck.c_str());
9358 searchMaxThreshold = INT_MAX;
9362 __COUT__ <<
"Unable to set min and max thresholds for searchVersionToCheck: "
9363 << searchVersionToCheck << __E__;
9364 xmlOut.addTextElementToData(
9366 "Unable to set min and max thresholds for searchVersionToCheck: " +
9367 searchVersionToCheck);
9369 __SUP_COUT__ <<
"searchVersionToCheck range: " << searchMinThreshold <<
" to "
9370 << searchMaxThreshold << __E__;
9374 if(allTableInfo.find(tableName) == allTableInfo.end())
9376 __SUP_SS__ <<
"Table '" << tableName <<
"' not found." << __E__;
9377 xmlOut.addTextElementToData(
"Error", ss.str());
9381 const TableInfo& tableInfo = allTableInfo.at(tableName);
9382 __COUT__ <<
"tableInfo versions length " << tableInfo.versions_.size() << __E__;
9384 unsigned int matchCount = 0;
9385 bool allowIllegalColumns =
true;
9387 auto parentEl = xmlOut.addTextElementToData(
"SearchResults",
"");
9390 for(
const auto& version : tableInfo.versions_)
9394 auto activeIt = allActivePairs.find(tableName);
9395 bool isActiveVersion =
9396 (activeIt != allActivePairs.end() && activeIt->second == version);
9397 __COUT__ <<
"Active check for " << tableName <<
" v" << version <<
" => "
9398 << (isActiveVersion ?
"active" :
"inactive") << __E__;
9399 if(!isActiveVersion && activeTablesOnly)
9402 if((std::stoi(version.toString()) < searchMinThreshold ||
9403 std::stoi(version.toString()) > searchMaxThreshold) &&
9404 activeTablesOnly ==
false )
9406 __COUT__ <<
"Skipping version " << version <<
" out of range "
9407 << searchMinThreshold <<
" to " << searchMaxThreshold
9415 if(version.isInvalid())
9417 __COUT__ <<
"Using mock-up for table " << tableName <<
" version "
9418 << version << __E__;
9419 tableViewPtr = table->getMockupViewP();
9427 std::string localAccumulatedErrors =
"";
9433 allowIllegalColumns ,
9434 &localAccumulatedErrors,
9438 if(localAccumulatedErrors !=
"")
9439 xmlOut.addTextElementToData(
"Error", localAccumulatedErrors);
9441 catch(
const std::runtime_error& e)
9443 __COUT__ <<
"Error loading version " << version <<
" for table "
9444 << tableName <<
": " << e.what() << __E__;
9445 __SUP_COUT_WARN__ <<
"Could not load version " << version
9446 <<
" for table " << tableName <<
": "
9447 << e.what() << __E__;
9449 tableViewPtr = table->getMockupViewP();
9453 __COUT__ <<
"Getting table " << tableName <<
" version " << version
9457 for(
unsigned int row = 0; row < tableViewPtr->getNumberOfRows(); ++row)
9459 for(
unsigned int col = 0; col < tableViewPtr->getNumberOfColumns();
9462 const std::string& cellValue =
9463 tableViewPtr->getDataView()[row][col];
9465 if(cellValue.find(searchText) != std::string::npos)
9467 __COUT__ <<
"Match found in row " << row <<
" column " << col
9468 <<
" value: " << cellValue << __E__;
9470 "Match", cellValue, parentEl);
9472 "MatchVersion", version.toString(), matchEl);
9474 "MatchRow", std::to_string(row), matchEl);
9477 tableViewPtr->getColumnInfo(col).getName(),
9485 catch(
const std::runtime_error& e)
9487 __COUT__ <<
"Error searching in version " << version <<
" for table "
9488 << tableName <<
": " << e.what() << __E__;
9489 __SUP_COUT_WARN__ <<
"Could not load version " << version <<
" for table "
9490 << tableName <<
": " << e.what() << __E__;
9494 xmlOut.addTextElementToData(
"MatchCount", std::to_string(matchCount));
9496 catch(std::runtime_error& e)
9498 __SUP_SS__ <<
"Error searching in table '" << tableName <<
"'!\n\n " << e.what()
9500 __SUP_COUT_ERR__ << ss.str();
9501 xmlOut.addTextElementToData(
"Error", ss.str());
9505 __SUP_SS__ <<
"Error searching in table '" << tableName <<
"'!\n\n " << __E__;
9510 catch(
const std::exception& e)
9512 ss <<
"Exception message: " << e.what();
9517 __SUP_COUT_ERR__ << ss.str();
9518 xmlOut.addTextElementToData(
"Error", ss.str());
9524 void ConfigurationGUISupervisor::handleGroupDiff(
9527 const std::string& groupName,
9530 const std::string& diffGroupNameInput )
9536 std::string diffGroupName;
9539 __SUP_COUT__ <<
"Differencing group " << groupName <<
"(" << groupKey
9540 <<
") with the active group." << __E__;
9543 if(diffGroupNameInput ==
"")
9544 diffGroupName = groupName;
9546 diffGroupName = diffGroupNameInput;
9548 __SUP_COUT__ <<
"Differencing group " << groupName <<
"(" << groupKey
9549 <<
") with group " << diffGroupName <<
"(" << diffKey <<
")"
9555 std::map<std::string ,
TableVersion > memberMap, diffMemberMap;
9556 std::string groupType, accumulateErrors;
9557 std::stringstream diffReport;
9558 bool noDifference =
true;
9577 std::map<std::string , std::pair<std::string, TableGroupKey>>
9584 __SUP_COUTV__(groupType);
9586 if(activeGroups.find(groupType) == activeGroups.end() ||
9587 activeGroups.at(groupType).first ==
"" ||
9588 activeGroups.at(groupType).second.isInvalid())
9590 __SUP_SS__ <<
"Could not find an active group of type '" << groupType
9591 <<
".' Please check the expected active configuration groups "
9592 "for errors (going to 'System View' of the Config App may "
9598 __SUP_COUT__ <<
"active " << groupType <<
" group is "
9599 << activeGroups.at(groupType).first <<
"("
9600 << activeGroups.at(groupType).second <<
")" << __E__;
9602 diffReport <<
"This difference report is between " << groupType
9603 <<
" group <b>'" << groupName <<
"(" << groupKey <<
")'</b>"
9604 <<
" and active group <b>'" << activeGroups.at(groupType).first
9605 <<
"(" << activeGroups.at(groupType).second <<
")'</b>." << __E__;
9608 activeGroups.at(groupType).second,
9618 diffReport <<
"\n\n"
9619 <<
"'" << groupName <<
"(" << groupKey <<
")' has <b>"
9620 << memberMap.size() <<
" member tables</b>, and "
9621 <<
"'" << activeGroups.at(groupType).first <<
"("
9622 << activeGroups.at(groupType).second <<
")' has <b>"
9623 << diffMemberMap.size() <<
" member tables</b>." << __E__;
9627 diffReport <<
"This difference report is between group <b>'" << groupName
9628 <<
"(" << groupKey <<
")'</b>"
9629 <<
" and group <b>'" << diffGroupName <<
"(" << diffKey
9630 <<
")'</b>." << __E__;
9643 diffReport <<
"\n\n"
9644 <<
"'" << groupName <<
"(" << groupKey <<
")' has <b>"
9645 << memberMap.size() <<
" member tables</b>, and "
9646 <<
"'" << diffGroupName <<
"(" << diffKey <<
")' has <b>"
9647 << diffMemberMap.size() <<
" member tables</b>." << __E__;
9652 diffReport <<
"<INDENT><ol>";
9654 unsigned int tableDifferences = 0;
9656 for(
auto& member : memberMap)
9658 if(diffMemberMap.find(member.first) == diffMemberMap.end())
9660 diffReport <<
"\n\n<li>"
9661 <<
"Table <b>" << member.first <<
"-v" << member.second
9662 <<
"</b> not found in active group."
9663 <<
"</li>" << __E__;
9664 noDifference =
false;
9669 __SUP_COUTT__ <<
"Comparing " << member.first <<
"-v" << member.second
9670 <<
" ... " << member.first <<
"-v"
9671 << diffMemberMap.at(member.first) << __E__;
9673 if(member.second == diffMemberMap.at(member.first))
9676 diffReport <<
"\n\n<li>"
9677 <<
"Table <b>" << member.first <<
" v" << member.second
9678 <<
"</b> in " << groupName <<
"(" << groupKey <<
")' ...vs... "
9679 <<
" <b>v" << diffMemberMap.at(member.first) <<
"</b> in "
9680 << diffGroupName <<
"(" << diffKey <<
")':" << __E__;
9684 diffReport <<
"<ul>";
9685 std::map<std::string , std::vector<std::string >>
9687 if(!table->diffTwoVersions(member.second,
9688 diffMemberMap.at(member.first),
9693 noDifference =
false;
9696 xmlOut.addTextElementToData(
"TableWithDiff", member.first);
9697 for(
auto& modifiedRecord : modifiedRecords)
9700 "RecordWithDiff", modifiedRecord.first, parentEl);
9701 for(
auto& modifiedColumn : modifiedRecord.second)
9703 "ColNameWithDiff", modifiedColumn, recordParentEl);
9706 diffReport <<
"</ul></li>";
9710 for(
auto& diffMember : diffMemberMap)
9712 if(memberMap.find(diffMember.first) == memberMap.end())
9715 diffReport <<
"\n\n<li>"
9716 <<
"Active Group Table <b>" << diffMember.first <<
"-v"
9717 << diffMember.second <<
"</b> not found in '" << groupName
9718 <<
"(" << groupKey <<
")'."
9719 <<
"</li>" << __E__;
9721 diffReport <<
"\n\n<li>" << diffGroupName <<
"(" << diffKey
9722 <<
") Table <b>" << diffMember.first <<
"-v"
9723 << diffMember.second <<
"</b> not found in '" << groupName
9724 <<
"(" << groupKey <<
")'."
9725 <<
"</li>" << __E__;
9727 noDifference =
false;
9732 diffReport <<
"\n</ol></INDENT>";
9737 diffReport <<
"\n\nNo difference found between "
9738 <<
"<b>'" << groupName <<
"(" << groupKey
9739 <<
")'</b> and active group "
9740 <<
"<b>'" << activeGroups.at(groupType).first <<
"("
9741 << activeGroups.at(groupType).second <<
")'</b>." << __E__;
9743 diffReport <<
"\n\n<b>" << tableDifferences
9744 <<
"</b> member table differences identified between "
9745 <<
"<b>'" << groupName <<
"(" << groupKey
9746 <<
")'</b> and active group "
9747 <<
"<b>'" << activeGroups.at(groupType).first <<
"("
9748 << activeGroups.at(groupType).second <<
")'</b>." << __E__;
9753 diffReport <<
"\n\nNo difference found between "
9754 <<
"<b>'" << groupName <<
"(" << groupKey
9755 <<
")'</b> and group "
9756 <<
"<b>'" << diffGroupName <<
"(" << diffKey <<
")'</b>."
9759 diffReport <<
"\n\n<b>" << tableDifferences
9760 <<
"</b> member table differences identified between "
9761 <<
"<b>'" << groupName <<
"(" << groupKey
9762 <<
")'</b> and group "
9763 <<
"<b>'" << diffGroupName <<
"(" << diffKey <<
")'</b>."
9767 xmlOut.addTextElementToData(
"NoDifference", noDifference ?
"1" :
"0");
9768 xmlOut.addTextElementToData(
"DiffReport", diffReport.str());
9770 catch(
const std::runtime_error& e)
9772 __SUP_COUT_ERR__ <<
"Caught error while differencing group " << groupName <<
"("
9773 << groupKey <<
") with group " << diffGroupName <<
"(" << diffKey
9774 <<
")" << __E__ << e.what() << __E__;
9781 void ConfigurationGUISupervisor::handleTableDiff(
HttpXmlDocument& xmlOut,
9783 const std::string& tableName,
9787 __SUP_COUT__ <<
"Differencing tableName " << tableName <<
" v" << vA <<
" with v"
9797 std::string localAccumulatedErrors =
"";
9801 &localAccumulatedErrors,
9804 if(localAccumulatedErrors !=
"")
9805 xmlOut.addTextElementToData(
"Error", localAccumulatedErrors);
9807 catch(std::runtime_error& e)
9809 __SUP_SS__ <<
"Failed to get table " << tableName <<
" version " << vA;
9810 ss <<
"\n\n...Here is why it failed:\n\n" << e.what() << __E__;
9811 __SUP_COUT_ERR__ <<
"\n" << ss.str();
9813 xmlOut.addTextElementToData(
"Error",
"Error getting view! " + ss.str());
9817 __SUP_SS__ <<
"Failed to get table " << tableName <<
" version: " << vA << __E__;
9822 catch(
const std::exception& e)
9824 ss <<
"Exception message: " << e.what();
9830 __SUP_COUT_ERR__ <<
"\n" << ss.str();
9831 xmlOut.addTextElementToData(
"Error",
"Error getting view! " + ss.str());
9837 std::string localAccumulatedErrors =
"";
9841 &localAccumulatedErrors,
9844 if(localAccumulatedErrors !=
"")
9845 xmlOut.addTextElementToData(
"Error", localAccumulatedErrors);
9847 catch(std::runtime_error& e)
9849 __SUP_SS__ <<
"Failed to get table " << tableName <<
" version " << vB;
9850 ss <<
"\n\n...Here is why it failed:\n\n" << e.what() << __E__;
9851 __SUP_COUT_ERR__ <<
"\n" << ss.str();
9853 xmlOut.addTextElementToData(
"Error",
"Error getting view! " + ss.str());
9857 __SUP_SS__ <<
"Failed to get table " << tableName <<
" version: " << vB << __E__;
9862 catch(
const std::exception& e)
9864 ss <<
"Exception message: " << e.what();
9870 __SUP_COUT_ERR__ <<
"\n" << ss.str();
9871 xmlOut.addTextElementToData(
"Error",
"Error getting view! " + ss.str());
9874 bool noDifference =
true;
9875 std::stringstream diffReport;
9877 diffReport <<
"This difference report is between table " << tableName <<
" v" << vA
9878 <<
" and v" << vB <<
"</b>." << __E__;
9880 diffReport <<
"<INDENT>";
9881 diffReport <<
"<ul>";
9882 std::map<std::string , std::vector<std::string >>
9884 if(!table->diffTwoVersions(vA, vB, &diffReport))
9885 noDifference =
false;
9886 diffReport <<
"</ul></INDENT>";
9888 xmlOut.addTextElementToData(
"NoDifference", noDifference ?
"1" :
"0");
9889 xmlOut.addTextElementToData(
"DiffReport", diffReport.str());
9895 void ConfigurationGUISupervisor::testXDAQContext()
9899 __COUT_INFO__ <<
"Hello0!";
9901 __COUT_INFO__ <<
"Hello1!";
9903 __COUT_INFO__ <<
"Hello2!";
9905 __COUT_INFO__ <<
"Hello3!";
9911 __SUP_COUT_INFO__ <<
"Attempting test activation of the context group." << __E__;
9915 catch(
const std::runtime_error& e)
9918 <<
"The test activation of the context group failed. Ignoring error: \n"
9919 << e.what() << __E__;
9924 __SUP_COUT_WARN__ <<
"The test activation of the context group failed. Ignoring."
9929 __SUP_COUT_INFO__ <<
"Completed test activation of the context group." << __E__;
static void setAndActivateARTDAQSystem(ConfigurationManagerRW *cfgMgr, const std::map< std::string, std::map< std::string, std::vector< std::string >>> &nodeTypeToObjectMap, const std::map< std::string, std::string > &subsystemObjectMap)
static const ARTDAQInfo & getARTDAQSystem(ConfigurationManagerRW *cfgMgr, std::map< std::string, std::map< std::string, std::vector< std::string >>> &nodeTypeToObjectMap, std::map< std::string, std::string > &subsystemObjectMap, std::vector< std::string > &artdaqSupervisoInfo)
static std::string postData(cgicc::Cgicc &cgi, const std::string &needle)
static std::string getData(cgicc::Cgicc &cgi, const std::string &needle)
virtual void forceSupervisorPropertyValues(void) override
override to force supervisor property values (and ignore user settings)
virtual void setSupervisorPropertyDefaults(void) override
ConfigurationGUISupervisor(xdaq::ApplicationStub *s)
static xdaq::Application * instantiate(xdaq::ApplicationStub *s)
TableVersion saveNewTable(const std::string &tableName, TableVersion temporaryVersion=TableVersion(), bool makeTemporary=false)
void testXDAQContext(void)
const GroupInfo & getGroupInfo(const std::string &groupName, bool attemptToReloadKeys=false)
void clearAllCachedVersions(void)
const std::map< std::string, TableInfo > & getAllTableInfo(bool refresh=false, std::string *accumulatedWarnings=0, const std::string &errorFilterName="", bool getGroupKeys=false, bool getGroupInfo=false, bool initializeActiveGroups=false)
void loadTableGroup(const std::string &tableGroupName, const TableGroupKey &tableGroupKey, bool doActivate=false, std::map< std::string, TableVersion > *groupMembers=0, ProgressBar *progressBar=0, std::string *accumulateWarnings=0, std::string *groupComment=0, std::string *groupAuthor=0, std::string *groupCreateTime=0, bool doNotLoadMember=false, std::string *groupTypeString=0, std::map< std::string, std::string > *groupAliases=0, ConfigurationManager::LoadGroupType groupTypeToLoad=ConfigurationManager::LoadGroupType::ALL_TYPES, bool ignoreVersionTracking=false)
TableVersion copyViewToCurrentColumns(const std::string &tableName, TableVersion sourceVersion)
TableGroupKey saveNewTableGroup(const std::string &groupName, std::map< std::string, TableVersion > &groupMembers, const std::string &groupComment=TableViewColumnInfo::DATATYPE_COMMENT_DEFAULT, std::map< std::string, std::string > *groupAliases=0)
void activateTableGroup(const std::string &tableGroupName, TableGroupKey tableGroupKey, std::string *accumulatedTreeErrors=0, std::string *groupTypeString=0)
void clearCachedVersions(const std::string &tableName)
const std::string & getUsername(void) const
std::map< std::string, std::map< std::string, TableVersion > > getVersionAliases(void) const
void eraseTemporaryVersion(const std::string &tableName, TableVersion targetVersion=TableVersion())
void preloadVersionCreationTimes(void)
static void loadTableGroupThread(ConfigurationManagerRW *cfgMgr, std::string groupName, ots::TableGroupKey groupKey, std::shared_ptr< ots::GroupInfo > theGroupInfo, std::shared_ptr< std::atomic< bool >> theThreadDone)
void restoreActiveTableGroups(bool throwErrors=false, const std::string &pathToActiveGroupsFile="", ConfigurationManager::LoadGroupType onlyLoadIfBackboneOrContext=ConfigurationManager::LoadGroupType::ALL_TYPES, std::string *accumulatedWarnings=0)
std::map< std::string, std::pair< std::string, TableGroupKey > > getActiveTableGroups(void) const
std::map< std::string, TableVersion > getActiveVersions(void) const
void copyTableGroupFromCache(const ConfigurationManager &cacheConfigMgr, const std::map< std::string, TableVersion > &groupMembers, const std::string &configGroupName="", const TableGroupKey &tableGroupKey=TableGroupKey(TableGroupKey::INVALID), bool doActivate=false, bool ignoreVersionTracking=false)
ConfigurationTree getNode(const std::string &nodeString, bool doNotThrowOnBrokenUIDLinks=false) const
TableBase * getVersionedTableByName(const std::string &tableName, TableVersion version, bool looseColumnMatching=false, std::string *accumulatedErrors=0, bool getRawData=false, bool touchLastAccessTime=true)
void init(std::string *accumulatedErrors=0, bool initForWriteAccess=false, std::string *accumulatedWarnings=0)
static const std::string & getTypeNameOfGroup(const std::map< std::string, TableVersion > &memberMap)
void destroyTableGroup(const std::string &theGroup="", bool onlyDeactivate=false)
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, TableVersion > *memberMap=0, std::string *accumulatedTreeErrors=0) const
std::map< std::string, ConfigurationTree > getChildrenMap(std::map< std::string, TableVersion > *memberMap=0, std::string *accumulatedTreeErrors=0) const
static std::vector< std::map< std::string, std::string > > loadGroupHistory(const std::string &groupAction, const std::string &groupType, bool formatTime=false)
TableGroupKey loadConfigurationBackbone(void)
const TableBase * getTableByName(const std::string &configurationName) const
static std::pair< std::string, TableGroupKey > loadGroupNameAndKey(const std::string &fileName, std::string &returnedTimeString)
static void getConfigurationStatusXML(HttpXmlDocument &xmlOut, ConfigurationManagerRW *cfgMgr, const std::string &username)
static void handleGetTableGroupXML(HttpXmlDocument &xmlOut, ConfigurationManagerRW *cfgMgr, const std::string &groupName, TableGroupKey groupKey, bool ignoreWarnings=false, bool cacheOnly=false)
static TableVersion saveModifiedVersionXML(HttpXmlDocument &xmlOut, ConfigurationManagerRW *cfgMgr, const std::string &tableName, TableVersion originalVersion, bool makeTemporary, TableBase *config, TableVersion temporaryModifiedVersion, bool ignoreDuplicates=false, bool lookForEquivalent=false)
static void handleCreateTableXML(HttpXmlDocument &xmlOut, ConfigurationManagerRW *cfgMgr, const std::string &tableName, TableVersion version, bool makeTemporary, const std::string &data, const int &dataOffset, const std::string &author, const std::string &comment, bool sourceTableAsIs, bool lookForEquivalent)
static void handleCreateTableGroupXML(HttpXmlDocument &xmlOut, ConfigurationManagerRW *cfgMgr, const std::string &groupName, const std::string &configList, bool allowDuplicates=false, bool ignoreWarnings=false, const std::string &groupComment="", bool lookForEquivalent=false)
bool isUIDNode(void) const
const TableVersion & getTableVersion(void) const
bool isDisconnected(void) const
const std::string & getAuthor(void) const
const std::string & getComment(void) const
std::vector< std::string > getChildrenNames(bool byPriority=false, bool onlyStatusTrue=false) const
bool isEnabled(void) const
const std::string & getTableName(void) const
const unsigned int & getFieldRow(void) const
std::map< std::string, ConfigurationTree > getChildrenMap(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool onlyStatusTrue=false) const
const std::string & getValueName(void) const
const std::string & getValueAsString(bool returnLinkTableValue=false) const
const std::string & getChildLinkIndex(void) const
const std::string & getDisconnectedTableName(void) const
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool byPriority=false, bool onlyStatusTrue=false) const
std::vector< std::string > getFixedChoices(void) const
bool isLinkNode(void) const
std::vector< ConfigurationTree::RecordField > getCommonFields(const std::vector< std::string > &recordList, const std::vector< std::string > &fieldAcceptList, const std::vector< std::string > &fieldRejectList, unsigned int depth=-1, bool autoSelectFilterFields=false) const
bool isValueNode(void) const
std::set< std::string > getUniqueValuesForField(const std::vector< std::string > &recordList, const std::string &fieldName, std::string *fieldGroupIDChildLinkIndex=0) const
const std::string & getValueType(void) const
bool isGroupLinkNode(void) const
const std::string & getFieldTableName(void) const
const std::string & getDisconnectedLinkID(void) const
const std::string & getParentTableName(void) const
bool isUIDLinkNode(void) const
const unsigned int & getFieldColumn(void) const
static std::string convertToCaps(std::string &str, bool isConfigName=false)
std::string toString(void) const
bool isInvalid(void) const
static std::string getFullGroupString(const std::string &groupName, const TableGroupKey &key, const std::string &preKey="_v", const std::string &postKey="")
std::string toString(void) const
unsigned int version(void) const
static const std::string DATATYPE_NUMBER
static std::map< std::pair< std::string, std::string >, std::string > getAllDefaultsForGUI(void)
bool isChildLink(void) const
static const std::string & getDefaultDefaultValue(const std::string &type, const std::string &dataType)
static const std::string & getMaxDefaultValue(const std::string &dataType)
static const std::string & getMinDefaultValue(const std::string &dataType)
unsigned int findRow(unsigned int col, const T &value, unsigned int offsetRow=0, bool doNotThrow=false) const
bool isEntryInGroup(const unsigned int &row, const std::string &childLinkIndex, const std::string &groupNeedle) const
void setValueAsString(const std::string &value, unsigned int row, unsigned int col)
unsigned int getColStatus(void) const
unsigned int getLinkGroupIDColumn(const std::string &childLinkIndex) const
bool removeRowFromGroup(const unsigned int &row, const unsigned int &col, const std::string &groupID, bool deleteRowIfNoGroupLeft=false)
bool getChildLink(const unsigned int &col, bool &isGroup, std::pair< unsigned int, unsigned int > &linkPair) const
void addRowToGroup(const unsigned int &row, const unsigned int &col, const std::string &groupID)
std::string getValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const
void getValue(T &value, unsigned int row, unsigned int col, bool doConvertEnvironmentVariables=true) const
unsigned int getColUID(void) const
bool setURIEncodedValue(const std::string &value, const unsigned int &row, const unsigned int &col, const std::string &author="")
unsigned int findCol(const std::string &name) const
void setValue(const T &value, unsigned int row, unsigned int col)
void setURIEncodedComment(const std::string &uriComment)
unsigned int addRow(const std::string &author="", unsigned char incrementUniqueData=false, const std::string &baseNameAutoUID="", unsigned int rowToAdd=(unsigned int) -1, std::string childLinkIndex="", std::string groupId="")
xercesc::DOMElement * addTextElementToParent(const std::string &childName, const std::string &childText, xercesc::DOMElement *parent)
void INIT_MF(const char *name)
static std::string getTimestampString(const std::string &linuxTimeInSeconds)
static void getVectorFromString(const std::string &inputString, std::vector< std::string > &listToReturn, const std::set< char > &delimiter={',', '|', '&'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'}, std::vector< char > *listOfDelimiters=0, bool decodeURIComponents=false)
static std::string exec(const char *cmd)
static std::string setToString(const std::set< T > &setToReturn, const std::string &delimeter=", ")
static std::string escapeString(std::string inString, bool allowWhiteSpace=false, bool forHtml=false)
static std::string vectorToString(const std::vector< T > &setToReturn, const std::string &delimeter=", ")
static std::string convertEnvironmentVariables(const std::string &data)
static bool isNumber(const std::string &stringToCheck)
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")
static void getMapFromString(const std::string &inputString, std::map< S, T > &mapToReturn, const std::set< char > &pairPairDelimiter={',', '|', '&'}, const std::set< char > &nameValueDelimiter={'=', ':'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'})
static std::string decodeURIComponent(const std::string &data)