1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408 |
- /*##############################################################################
- Copyright (C) 2011 HPCC Systems.
- All rights reserved. This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- ############################################################################## */
- #include "jliball.hpp"
- #include "environment.hpp"
- #include "XMLTags.h"
- #include "configenvhelper.hpp"
- #include "deployutils.hpp"
- #include "build-config.h"
- bool CConfigEnvHelper::handleRoxieOperation(const char* cmd, const char* xmlStr)
- {
- bool retVal = false;
- if (!strcmp(cmd, "AddRoxieFarm"))
- retVal = this->addRoxieServers(xmlStr);
- else if (!strcmp(cmd, "DeleteRoxieFarm"))
- retVal = this->deleteRoxieServers(xmlStr);
- else if (!strcmp(cmd, "RoxieSlaveConfig"))
- retVal = this->handleRoxieSlaveConfig(xmlStr);
- else if (!strcmp(cmd, "ReplaceRoxieServer"))
- retVal = this->handleReplaceRoxieServer(xmlStr);
- return retVal;
- }
- bool CConfigEnvHelper::handleThorTopologyOp(const char* cmd, const char* xmlArg, StringBuffer& sMsg)
- {
- bool retVal = false;
- StringBuffer xpath;
- Owned<IPropertyTree> pParams = createPTreeFromXMLString(xmlArg && *xmlArg ? xmlArg : "<ThorData/>", false);
- const char* thorName = pParams->queryProp(XML_ATTR_NAME);
- const char* newType = pParams->queryProp(XML_ATTR_TYPE);
- const char* validate = pParams->queryProp("@validateComputers");
- const char* skip = pParams->queryProp("@skipExisting");
- const char* slavesPerNode = pParams->queryProp("@slavesPerNode");
- bool checkComps = validate && !strcmp(validate, "true");
- bool skipExisting = skip && !strcmp(skip, "true");
- IPropertyTree* pThor = getSoftwareNode(XML_TAG_THORCLUSTER, thorName);
- StringBuffer usageList;
- if (!strcmp(cmd, "Add"))
- {
- Owned<IPropertyTreeIterator> iterComputers = pParams->getElements("Computer");
- IPropertyTreePtrArray computers;
- ForEach (*iterComputers)
- {
- IPropertyTree* pComp = &iterComputers->query();
- const char* pszCompName = pComp->queryProp(XML_ATTR_NAME);
- xpath.clear().appendf(XML_TAG_HARDWARE"/"XML_TAG_COMPUTER"/["XML_ATTR_NAME"='%s']", pszCompName);
- IPropertyTree* pComputer = m_pRoot->queryPropTree(xpath.str());
- if (pComputer)
- computers.push_back(pComputer);
- }
- int numNodes = 1;
- if (slavesPerNode && *slavesPerNode)
- numNodes = atoi(slavesPerNode);
- if (numNodes < 1)
- numNodes = 1;
- if (!strcmp(newType, "Master"))
- retVal = this->AddNewNodes(pThor, XML_TAG_THORMASTERPROCESS, 0, computers, checkComps, skipExisting, usageList);
- else if (!strcmp(newType, "Slave"))
- retVal = this->AddNewNodes(pThor, XML_TAG_THORSLAVEPROCESS, 0, computers, checkComps, skipExisting, usageList, numNodes);
- else if (!strcmp(newType, "Spare"))
- retVal = this->AddNewNodes(pThor, XML_TAG_THORSPAREPROCESS, 0, computers, checkComps, skipExisting, usageList);
- if (usageList.length() > 0)
- {
- sMsg.append("The following computers are already being used.\nDo you want to add/replace them anyway?");
- sMsg.append(usageList);
- }
- }
- else if (!strcmp(cmd, "Delete"))
- {
- Owned<IPropertyTreeIterator> iterComputers = pParams->getElements("Node");
- ForEach (*iterComputers)
- {
- IPropertyTree* pComp = &iterComputers->query();
- const char* process = pComp->queryProp(XML_ATTR_PROCESS_NAME);
- const char* type = pComp->queryProp(XML_ATTR_TYPE);
- // Delete process node
- IPropertyTree* pProcessNode = GetProcessNode(pThor, process);
- if (pProcessNode)
- pThor->removeTree(pProcessNode);
- // Delete from topology node
- IPropertyTree* pTopoNode = pThor->queryPropTree(XML_TAG_TOPOLOGY);
- if (!strcmp(type, "Slave"))
- {
- Owned<IPropertyTreeIterator> iter = pThor->getElements(XML_TAG_TOPOLOGY"//"XML_TAG_NODE);
- ForEach(*iter)
- {
- // Get macthing process node
- const char* szProcess = iter->query().queryProp(XML_ATTR_PROCESS);
- IPropertyTree* pProcessNode = GetProcessNode(pThor, szProcess);
- if (!strcmp(pProcessNode->queryName(), XML_TAG_THORMASTERPROCESS))
- {
- xpath.clear().appendf(XML_TAG_NODE"/["XML_ATTR_PROCESS"='%s']", process);
- IPropertyTree* pNode = iter->query().queryPropTree(xpath.str());
- if (pNode)
- iter->query().removeTree(pNode);
- break;
- }
- }
- }
- else
- {
- xpath.clear().appendf(XML_TAG_NODE"/["XML_ATTR_PROCESS"='%s']", process);
- IPropertyTree* pNode = pTopoNode->queryPropTree(xpath.str());
- //Remove all slaves from thor
- if (pNode && !strcmp(type, "Master"))
- {
- Owned<IPropertyTreeIterator> iter = pThor->getElements(XML_TAG_TOPOLOGY"//"XML_TAG_NODE);
- ForEach(*iter)
- {
- // Get macthing process node
- const char* szProcess = iter->query().queryProp(XML_ATTR_PROCESS);
- IPropertyTree* pProcessNode = GetProcessNode(pThor, szProcess);
- if (pProcessNode && !strcmp(pProcessNode->queryName(), XML_TAG_THORSLAVEPROCESS))
- pThor->removeTree(pProcessNode);
- }
- }
- if (pNode)
- pTopoNode->removeTree(pNode);
- }
- }
- RenameThorInstances(pThor);
- UpdateThorAttributes(pThor);
- retVal = true;
- }
- return retVal;
- }
- IPropertyTree* CConfigEnvHelper::getSoftwareNode(const char* compType, const char* compName)
- {
- StringBuffer xpath;
- xpath.appendf("Software/%s[@name='%s']", compType, compName);
- return m_pRoot->queryPropTree(xpath.str());
- }
- bool CConfigEnvHelper::addRoxieServers(const char* xmlArg)
- {
- Owned<IPropertyTree> pSrcTree = createPTreeFromXMLString(xmlArg && *xmlArg ? xmlArg : "<RoxieData/>", false);
- const char* pszFarm = pSrcTree->queryProp("@parentName");
- const char* pszRoxieCluster = pSrcTree->queryProp("@roxieName");
- unsigned int nComputers = 0;//computers.size();
- IPropertyTree* pParent = m_pRoot->queryPropTree("Software");
- IPropertyTree* pFarm;
- bool bNewFarm;
- StringBuffer sFarmName;
- StringBuffer xpath;
- if (strlen(pszFarm))
- {
- xpath.clear().appendf("RoxieCluster[@name='%s']/"XML_TAG_ROXIE_FARM, pszRoxieCluster);
- pFarm = getSoftwareNode(xpath.str(), pszFarm);
- sFarmName = pFarm->queryProp(XML_ATTR_NAME);
- bNewFarm = false;
- if (!pFarm->hasProp("@port"))
- pFarm->addPropInt("@port", 9876);
- if (!pFarm->hasProp("@listenQueue"))
- pFarm->addPropInt("@listenQueue", 200);
- if (!pFarm->hasProp("@numThreads"))
- pFarm->getPropInt("@numThreads", 30);
- if (!pFarm->hasProp("@requestArrayThreads"))
- pFarm->addPropInt("@requestArrayThreads", 5);
- if (!pFarm->hasProp("@aclName"))
- pFarm->addProp("@aclName", "");
- StringBuffer dataDir = pFarm->queryProp(XML_ATTR_DATADIRECTORY);
- if (dataDir.length()==0)
- dataDir.append(RUNTIME_DIR"/roxiedata");
- if (!pFarm->queryPropTree(XML_TAG_ROXIE_SERVER"[1]")) //no servers in farm
- {
- //if (nComputers > 0)
- //g_pDocument->makePlatformSpecificAbsolutePath(computers[0]->queryProp(XML_ATTR_NAME), dataDir);
- Owned<IPropertyTreeIterator> iter = pSrcTree->getElements(XML_TAG_COMPONENT);
-
- ForEach (*iter)
- {
- IPropertyTree* pFolder = &iter->query();
- makePlatformSpecificAbsolutePath(pFolder->queryProp(XML_ATTR_NAME), dataDir);
- break;
- }
- pFarm->setProp(XML_ATTR_DATADIRECTORY, dataDir.str());
- }
- }
- else
- {
- xpath.clear().appendf("RoxieCluster[@name='%s']/"XML_TAG_ROXIE_FARM, pszRoxieCluster);
- createUniqueName("farm", xpath.str(), sFarmName);
- bNewFarm = true;
- StringBuffer sDataDir;
- sDataDir.append(RUNTIME_DIR"/roxiedata");
- //get datadir from existing farm if any
- xpath.clear().appendf("Software/RoxieCluster[@name='%s']/"XML_TAG_ROXIE_FARM"[1]", pszRoxieCluster);
- IPropertyTree* pFarm1 = m_pRoot->queryPropTree(xpath.str());
- if (pFarm1)
- sDataDir.clear().append(pFarm1->queryProp(XML_ATTR_DATADIRECTORY));
- //if (nComputers > 0)
- //g_pDocument->makePlatformSpecificAbsolutePath(computers[0]->queryProp(XML_ATTR_NAME), sDataDir);
- Owned<IPropertyTreeIterator> iter = pSrcTree->getElements(XML_TAG_COMPONENT);
-
- ForEach (*iter)
- {
- IPropertyTree* pFolder = &iter->query();
- makePlatformSpecificAbsolutePath(pFolder->queryProp(XML_ATTR_NAME), sDataDir);
- break;
- }
- xpath.clear().appendf("RoxieCluster[@name='%s']/"XML_TAG_ROXIE_FARM, pszRoxieCluster);
- pFarm = pParent->addPropTree(xpath.str(), createPTree(false));
- pFarm->addProp (XML_ATTR_NAME, sFarmName.str());
- pFarm->addPropInt("@port", 9876);
- pFarm->addProp (XML_ATTR_DATADIRECTORY, sDataDir.str());
- pFarm->addPropInt("@listenQueue", 200);
- pFarm->addPropInt("@numThreads", 30);
- pFarm->addPropInt("@requestArrayThreads", 5);
- pFarm->addProp("@aclName", "");
- }
- Owned<IPropertyTreeIterator> iter = pSrcTree->getElements(XML_TAG_COMPONENT);
- StringBuffer sNotAdded;
- xpath.clear().appendf("RoxieCluster[@name='%s']/"XML_TAG_ROXIE_FARM"[@name='%s']/"XML_TAG_ROXIE_SERVER, pszRoxieCluster, sFarmName.str());
- ForEach (*iter)
- {
- IPropertyTree* pFolder = &iter->query();
- const char* pszName = pFolder->queryProp(XML_ATTR_NAME);
- // Check if we can add this computer
- if (checkComputerUse(pszName, pFarm))
- {
- StringBuffer sServerName( sFarmName), sbUniqueName;
- sServerName.append("_s");
- createUniqueName(sServerName.str(), xpath.str(), sbUniqueName);
- // Add process node
- IPropertyTree* pServer = createPTree( XML_TAG_ROXIE_SERVER, false );
- pServer->setProp(XML_ATTR_NAME, sbUniqueName.str());
- pServer->addProp(XML_ATTR_COMPUTER, pszName);
- addNode(pServer, pFarm);
- IPropertyTree* pLegacyServer = addLegacyServer(sbUniqueName, pServer, pFarm, pszRoxieCluster);
- }
- else
- {
- sNotAdded.append('\n');
- sNotAdded.append(pszName);
- sNotAdded.append(" ( ");
- sNotAdded.append( pFolder->queryProp(XML_ATTR_NETADDRESS) );
- sNotAdded.append(" )");
- }
- }
- xpath.clear().appendf("Software/RoxieCluster[@name='%s']", pszRoxieCluster);
- IPropertyTree* pRoxieCluster = m_pRoot->queryPropTree(xpath.str());
- renameInstances(pRoxieCluster);
- if (sNotAdded.length())
- {
- StringBuffer sMsg("The following servers were already allocated to the farm and could not be added:\n");
- sMsg.append(sNotAdded.str());
- }
- return true;
- }
- bool CConfigEnvHelper::handleReplaceRoxieServer(const char* xmlArg)
- {
- Owned<IPropertyTree> pSrcTree = createPTreeFromXMLString(xmlArg && *xmlArg ? xmlArg : "<RoxieData/>", false);
- const char* pszRoxieCluster = pSrcTree->queryProp("@roxieName");
- IPropertyTree* pParent = m_pRoot->queryPropTree("Software");
- StringBuffer xpath;
- if (pszRoxieCluster && *pszRoxieCluster)
- {
- xpath.clear().appendf(XML_TAG_ROXIECLUSTER"[@name='%s']/"XML_TAG_ROXIE_FARM, pszRoxieCluster);
- IPropertyTree* pFarm = pParent->queryPropTree(xpath.str());
- if (!pFarm)
- throw MakeStringException(-1, "Could not find a RoxieCluster with name '%s'", pszRoxieCluster);
- Owned<IPropertyTreeIterator> iter = pSrcTree->getElements("Nodes/Node");
-
- ForEach (*iter)
- {
- IPropertyTree* pNode = &iter->query();
- const char* pszFarm = pNode->queryProp("@farm");
- const char* pszName = pNode->queryProp(XML_ATTR_NAME);
- const char* pszNewComputer = pNode->queryProp("@newComputer");
- xpath.clear().appendf(XML_TAG_ROXIE_SERVER"[@computer='%s']", pszNewComputer);
- if (pFarm->queryPropTree(xpath.str()))
- return false;
- xpath.clear().appendf(XML_TAG_ROXIE_SERVER"[@name='%s']", pszName);
-
- IPropertyTree* pServer = pFarm->queryPropTree(xpath.str());
- if (pServer && pszNewComputer && *pszNewComputer)
- {
- pServer->setProp(XML_ATTR_COMPUTER, pszNewComputer);
- xpath.clear().appendf(XML_TAG_ROXIECLUSTER"[@name='%s']/"XML_TAG_ROXIE_SERVER"[@name='%s']", pszRoxieCluster, pszName);
- IPropertyTree* pOldVerRoxieServer = pParent->queryPropTree(xpath.str());
- if (pOldVerRoxieServer)
- {
- pOldVerRoxieServer->setProp(XML_ATTR_COMPUTER, pszNewComputer);
- xpath.clear().appendf("Hardware/"XML_TAG_COMPUTER"["XML_ATTR_NAME"='%s']", pszNewComputer);
- IPropertyTree* pComputer = m_pRoot->queryPropTree(xpath.str());
- if (pComputer)
- pOldVerRoxieServer->setProp(XML_ATTR_NETADDRESS, pComputer->queryProp(XML_ATTR_NETADDRESS));
- }
- }
- }
- }
- return true;
- }
- //---------------------------------------------------------------------------
- // CheckComputerUse - will only prompt once for each element type
- //---------------------------------------------------------------------------
- bool CConfigEnvHelper::checkComputerUse(/*IPropertyTree* pComputerNode*/ const char* szComputer, IPropertyTree* pParentNode) const
- {
- StringBuffer xpath;
- xpath.append(XML_TAG_ROXIE_SERVER "[@computer='").append( szComputer ).append("']");
- Owned<IPropertyTreeIterator> iter = pParentNode->getElements(xpath.str());
- return !(iter->first() && iter->isValid());
- }
- bool CConfigEnvHelper::makePlatformSpecificAbsolutePath(const char* computer, StringBuffer& path)
- {
- bool rc = false;
- if (computer && *computer && path.length())
- {
- IPropertyTree* pComputer = lookupComputerByName(computer);
- const char* computerType = pComputer ? pComputer->queryProp(XML_ATTR_COMPUTERTYPE) : NULL;
- if (computerType && *computerType)
- {
- StringBuffer xpath;
- xpath.appendf("Hardware/ComputerType[@name='%s']", computerType);
- Owned<IPropertyTreeIterator> iter = m_pRoot->getElements(xpath.str());
- if (iter->first() && iter->isValid())
- {
- const char* os = iter->query().queryProp("@opSys");
- if (os && *os)
- {
- const bool bLinux = 0 != stricmp(os, "W2K");
- if (bLinux)
- {
- path.replace('\\', '/');
- path.replace(':', '$');
- if (*path.str() != '/')
- path.insert(0, '/');
- }
- else
- {
- path.replace('/', '\\');
- path.replace('$', ':');
- if (*path.str() == '\\')
- path.remove(0, 1);
- }
- rc = true;
- }
- }
- }
- }
- return rc;
- }
- IPropertyTree* CConfigEnvHelper::addLegacyServer(const char* name, IPropertyTree* pServer,
- IPropertyTree* pFarm, const char* roxieClusterName)
- {
- IPropertyTree* pLegacyServer;
- StringBuffer xpath;
- xpath.clear().appendf("Software/RoxieCluster[@name='%s']", roxieClusterName);
- IPropertyTree* pParentNode = m_pRoot->queryPropTree(xpath.str());
- if (pParentNode)
- {
- const char* szComputer = pServer->queryProp(XML_ATTR_COMPUTER);
- xpath.clear().appendf("Hardware/Computer/[@name='%s']", szComputer);
- IPropertyTree* pComputer= m_pRoot->queryPropTree(xpath.str());
- const char* netAddress = pComputer->queryProp(XML_ATTR_NETADDRESS);
- //derive the new server from pFarm since it has most of the attributes
- pLegacyServer = addNode(XML_TAG_ROXIE_SERVER, pParentNode);
- pLegacyServer->setProp( XML_ATTR_NAME, name);
- pLegacyServer->setProp( XML_ATTR_COMPUTER, szComputer );
- pLegacyServer->setProp( XML_ATTR_NETADDRESS, netAddress);
- Owned<IAttributeIterator> iAttr = pFarm->getAttributes();
- ForEach(*iAttr)
- {
- const char* attrName = iAttr->queryName();
- if (0 != strcmp(attrName, XML_ATTR_COMPUTER) && //skip
- 0 != strcmp(attrName, XML_ATTR_NETADDRESS) &&
- 0 != strcmp(attrName, XML_ATTR_NAME))
- {
- pLegacyServer->addProp(attrName, iAttr->queryValue());
- }
- }
- }
- else
- pLegacyServer = NULL;
- return pLegacyServer;
- }
- //---------------------------------------------------------------------------
- // setComputerState
- //---------------------------------------------------------------------------
- void CConfigEnvHelper::setComputerState(IPropertyTree* pNode, COMPUTER_STATE state)
- {
- setAttribute(pNode, XML_ATTR_STATE, g_szComputerState[state]);
- }
- //---------------------------------------------------------------------------
- // setAttribute
- //---------------------------------------------------------------------------
- void CConfigEnvHelper::setAttribute(IPropertyTree* pNode, const char* szName, const char* szValue)
- {
- // Check attribute already has specified value
- const char* szValueOld = pNode->queryProp(szName);
- if (!szValueOld || strcmp(szValueOld, szValue))
- {
- //UpdateComputerMap(pNode, false);
- // ptree does not like missing intermediates...
- const char *finger = szName;
- StringBuffer subpath;
- while (strchr(finger, '/'))
- {
- while (*finger!='/')
- subpath.append(*finger++);
- if (!pNode->hasProp(subpath.str()))
- pNode->addProp(subpath.str(), "");
- subpath.append(*finger++);
- }
- if (!strcmp(szName, XML_ATTR_BUILD) && !strcmp(pNode->queryName(), XML_TAG_ESPSERVICE))
- {
- //remove previous Properties, if any, that this component inherited from its
- //previous build
- IPropertyTree* pProperties = pNode->queryPropTree("Properties");
- IPropertyTree* pNewProperties;
- //if the new build has any properties then let the node inherit them
- const char* buildSet = pNode->queryProp(XML_ATTR_BUILDSET);
- if (buildSet)
- {
- StringBuffer sPath;
- sPath.append("Programs/Build[@name='").append(szValue).append("']/BuildSet[@name='")
- .append(buildSet).append("']/Properties");
- pNewProperties = m_pRoot->queryPropTree(sPath.str());
- }
- else
- pNewProperties = NULL;
- //if we just changed build for an ESP service then enumerate all bindings for all
- //ESP server processes and if any binding uses this service then replace its
- //Authenticate and AuthenticateFeature nodes with those from the properties of
- //this service from the new build. However, we only remove the nodes that are
- //not in the new build preserving the others (so their attributes are preserved -
- //in case they have been changed by the user). We also add new nodes that did
- //not exist before. In essence, a merge is needed.
- //
- if (pProperties || pNewProperties)
- {
- StringBuffer xpath;
- xpath.appendf("Software/EspProcess/EspBinding[@service='%s']", pNode->queryProp(XML_ATTR_NAME));
- Owned<IPropertyTreeIterator> iBinding = m_pRoot->getElements(xpath.str());
- ForEach(*iBinding)
- {
- IPropertyTree* pBinding = &iBinding->query();
- //remove existing Authenticate and AuthenticateFeature nodes that are not in the new buildset's properties
- //
- mergeServiceAuthenticationWithBinding(pBinding, pProperties, pNewProperties, "Authenticate");
- mergeServiceAuthenticationWithBinding(pBinding, pProperties, pNewProperties, "AuthenticateFeature");
- mergeServiceAuthenticationWithBinding(pBinding, pProperties, pNewProperties, "AuthenticateSetting");
- }
- pNode->removeTree(pProperties);
- }
- if (pNewProperties)
- pNode->addPropTree("Properties", createPTree(pNewProperties));
- }
- pNode->setProp(szName, szValue);
- }
- }
- void CConfigEnvHelper::mergeServiceAuthenticationWithBinding(IPropertyTree* pBinding,
- IPropertyTree* pProperties,
- IPropertyTree* pNewProperties,
- const char* NodeName)
- {
- StringBuffer xpath;
- //remove existing Authenticate and AuthenticateFeature nodes that are not in the new buildset's properties
- //
- Owned<IPropertyTreeIterator> iDest = pBinding->getElements(NodeName);
- for (iDest->first(); iDest->isValid(); )
- {
- IPropertyTree* pDest = &iDest->query();
- iDest->next();
- const char* path = pDest->queryProp("@path");
- xpath.clear().appendf("%s[@path='%s']", NodeName, path);
- IPropertyTree* pNewPropChild = pNewProperties->queryPropTree(xpath.str());
- if (pNewPropChild)
- {
- IPropertyTree* pPropChild = pProperties->queryPropTree(xpath.str());
- if (pPropChild)
- {
- //same path so merge individual attributes, retaining any that may have been changed by user
- //but replacing ones that are different in newer build but not changed by user
- Owned<IAttributeIterator> iAttr = pDest->getAttributes();
- ForEach(*iAttr)
- {
- const char* attrName = iAttr->queryName();
- if (0 != strcmp(attrName, "@path"))
- {
- const char* attrDest = iAttr->queryValue();
- const char* attrProp = pPropChild->queryProp(attrName);
- const char* attrNewProp = pNewPropChild->queryProp(attrName);
- if (attrProp && attrNewProp && !strcmp(attrDest, attrProp))
- pDest->setProp(attrName, attrNewProp);
- }
- }
- }
- }
- else
- pBinding->removeTree(pDest);
- }
- //add nodes from buildset properties that are missing in binding
- //
- bool bAuthenticateFeature = !strcmp(NodeName, "AuthenticateFeature");
- Owned<IPropertyTreeIterator> iSrc = pNewProperties->getElements(NodeName);
- ForEach(*iSrc)
- {
- IPropertyTree* pNode = &iSrc->query();
- const char* path = pNode->queryProp("@path");
- xpath.clear().appendf("%s[@path='%s']", NodeName, path);
- if (!pBinding->queryPropTree(xpath.str()))
- {
- pNode = pBinding->addPropTree(NodeName, createPTree(pNode));
- if (bAuthenticateFeature)
- pNode->addProp("@authenticate", "Yes");
- }
- }
- }
- //---------------------------------------------------------------------------
- // lookupComputerByName
- //---------------------------------------------------------------------------
- IPropertyTree* CConfigEnvHelper::lookupComputerByName(const char* szName) const
- {
- if (!szName || !*szName) return NULL;
- Owned<IPropertyTreeIterator> iter = m_pRoot->getElements(XML_TAG_HARDWARE"/"XML_TAG_COMPUTER);
- for (iter->first(); iter->isValid(); iter->next())
- {
- const char* szValue = iter->query().queryProp(XML_ATTR_NAME);
- if (szValue && strcmp(szValue, szName) == 0)
- return &iter->query();
- }
- return NULL;
- }
- void CConfigEnvHelper::createUniqueName(const char* szPrefix, const char* parent, StringBuffer& sbName)
- {
- sbName.clear().append(szPrefix).append("1");
- if (getSoftwareNode(parent, sbName.str()))
- {
- int iIdx = 2;
- do
- {
- sbName.clear().append(szPrefix).append(iIdx++);
- }
- while (getSoftwareNode(parent, sbName.str()));
- }
- }
- //---------------------------------------------------------------------------
- // addNode
- //---------------------------------------------------------------------------
- IPropertyTree* CConfigEnvHelper::addNode(const char* szTag, IPropertyTree* pParentNode, IPropertyTree* pInsertAfterNode)
- {
- IPropertyTree* pNode = createPTree(szTag, false);
- if (pNode)
- {
- addNode(pNode, pParentNode, pInsertAfterNode);
- }
- return pNode;
- }
- //---------------------------------------------------------------------------
- // addNode
- //---------------------------------------------------------------------------
- IPropertyTree* CConfigEnvHelper::addNode(IPropertyTree*& pNode, IPropertyTree* pParentNode, IPropertyTree* pInsertAfterNode)
- {
- StringBuffer sTag(pNode->queryName()); // need to pass in a copy of the name
- // Check is node is to be added at specific location relative to nodes with same name
- if (pInsertAfterNode)
- {
- int idx = 1; // this will insert into first position
- if (strcmp(pInsertAfterNode->queryName(), pNode->queryName()) == 0)
- {
- idx = pParentNode->queryChildIndex(pInsertAfterNode) + 2;
- }
- // Only append qualifier is not inserting at end position
- if (pParentNode->queryPropTree(StringBuffer(sTag).appendf("[%d]", idx).str()))
- sTag.appendf("[%d]", idx);
- }
- pNode = pParentNode->addPropTree(sTag.str(), pNode);
- return pNode;
- }
- //---------------------------------------------------------------------------
- // renameInstances
- //---------------------------------------------------------------------------
- void CConfigEnvHelper::renameInstances(IPropertyTree* pRoxieCluster)
- {
- // Iterate through farms
- int nFarm = 0;
- StringBuffer xpath;
- Owned<IPropertyTreeIterator> iFarm = pRoxieCluster->getElements(XML_TAG_ROXIE_FARM);
- ForEach(*iFarm)
- {
- IPropertyTree* pFarm = &iFarm->query();
- int nServer = 0;
- StringBuffer sFarmName("farm");
- sFarmName.append(++nFarm);
- setAttribute(pFarm, XML_ATTR_NAME, sFarmName.str());
- Owned<IPropertyTreeIterator> iServer = pFarm->getElements(XML_TAG_ROXIE_SERVER);
- ForEach(*iServer)
- {
- IPropertyTree* pServer = &iServer->query();
- StringBuffer sServerName( sFarmName );
- sServerName.append("_s");
- sServerName.append(++nServer);
- const char* prevName = pServer->queryProp(XML_ATTR_NAME);
- if (prevName && *prevName)
- {
- IPropertyTree* pLegacyServer = findLegacyServer(pRoxieCluster, prevName);
- if (pLegacyServer)
- setAttribute(pLegacyServer, "@_name", sServerName.str());
- }
- setAttribute(pServer, XML_ATTR_NAME, sServerName.str());
- }
- }
- Owned<IPropertyTreeIterator> iServer = pRoxieCluster->getElements(XML_TAG_ROXIE_SERVER);
- ForEach(*iServer)
- {
- IPropertyTree* pServer = &iServer->query();
- const char* newName = pServer->queryProp("@_name");
- if (newName)
- {
- pServer->setProp(XML_ATTR_NAME, newName);
- pServer->removeProp("@_name");
- }
- }
- }
- IPropertyTree* CConfigEnvHelper::findLegacyServer(IPropertyTree* pRoxieCluster, const char* pszServer)
- {
- StringBuffer xpath;
- xpath.appendf(XML_TAG_ROXIE_SERVER"[@name='%s']", pszServer);
- return pRoxieCluster->queryPropTree( xpath.str() );
- }
- bool CConfigEnvHelper::deleteRoxieServers(const char* xmlArg)
- {
- Owned<IPropertyTree> pSrcTree = createPTreeFromXMLString(xmlArg && *xmlArg ? xmlArg : "<RoxieData/>", false);
- const char* pszRoxieCluster = pSrcTree->queryProp("@roxieName");
- unsigned int nComputers = 0;//computers.size();
- StringBuffer xpath;
- xpath.clear().appendf("Software/RoxieCluster[@name='%s']", pszRoxieCluster);
- IPropertyTree* pRoxieCluster = m_pRoot->queryPropTree(xpath.str());
- StringBuffer sFarmName;
- Owned<IPropertyTreeIterator> iterFarm = pSrcTree->getElements(XML_TAG_ROXIE_FARM);
- ForEach (*iterFarm)
- {
- IPropertyTree* pFarm = &iterFarm->query();
- const char* pszFarm = pFarm->queryProp(XML_ATTR_NAME);
- deleteFarm(pRoxieCluster, pszFarm);
- }
- Owned<IPropertyTreeIterator> iterServer = pSrcTree->getElements(XML_TAG_ROXIE_SERVER);
- ForEach (*iterServer)
- {
- IPropertyTree* pServer = &iterServer->query();
- const char* pszName = pServer->queryProp(XML_ATTR_NAME);
- const char* pszFarm = pServer->queryProp("@parent");
- deleteServer(pRoxieCluster, pszFarm, pszName);
- }
- Owned<IPropertyTreeIterator> iterSlaves = pSrcTree->getElements(XML_TAG_ROXIE_ONLY_SLAVE);
- ForEach (*iterSlaves)
- {
- IPropertyTree* pChild;
- //if atleast one slave, delete all slaves
- while (pChild = pRoxieCluster->queryPropTree( "RoxieSlave[1]" ))
- pRoxieCluster->removeTree( pChild );
- while (pChild = pRoxieCluster->queryPropTree( XML_TAG_ROXIE_SLAVE "[1]" ))
- pRoxieCluster->removeTree( pChild );
- break;
- }
- renameInstances(pRoxieCluster);
- return true;
- }
- void CConfigEnvHelper::deleteFarm(IPropertyTree* pRoxieCluster, const char* pszFarm)
- {
- StringBuffer xpath;
- xpath.clear().appendf(XML_TAG_ROXIE_FARM"[@name='%s']", pszFarm);
- IPropertyTree* pFarm = pRoxieCluster->queryPropTree(xpath.str());
- Owned<IPropertyTreeIterator> it = pFarm->getElements(XML_TAG_ROXIE_SERVER);
- ForEach(*it)
- {
- IPropertyTree* pServer = &it->query();
- const char* pszServer = pServer->queryProp(XML_ATTR_NAME);
- IPropertyTree* pLegacyServer = findLegacyServer(pRoxieCluster, pszServer);
- if (pLegacyServer)
- pRoxieCluster->removeTree(pLegacyServer);
- }
- pRoxieCluster->removeTree(pFarm);
- }
- void CConfigEnvHelper::deleteServer(IPropertyTree* pRoxieCluster, const char* pszFarm, const char* pszServer)
- {
- StringBuffer xpath;
- IPropertyTree* pLegacyServer = findLegacyServer(pRoxieCluster, pszServer);
- if (pLegacyServer)
- pRoxieCluster->removeTree(pLegacyServer);
- xpath.clear().appendf(XML_TAG_ROXIE_FARM"[@name='%s']", pszFarm);
- IPropertyTree* pFarm = pRoxieCluster->queryPropTree(xpath.str());
- if (pFarm)
- {
- xpath.clear().appendf(XML_TAG_ROXIE_SERVER"[@name='%s']", pszServer);
- IPropertyTree* pServer = pFarm->queryPropTree(xpath.str());
- if (pServer)
- pFarm->removeTree(pServer);
- }
- }
- void CConfigEnvHelper::addComponent(const char* pszBuildSet, StringBuffer& sbNewName, IPropertyTree* pCompTree)
- {
- try
- {
- // NOTE - we are assuming buildSet is unique in a build.
- StringBuffer xPath, value;
- xPath.appendf("./Programs/Build/BuildSet[@name=\"%s\"]", pszBuildSet);
- Owned<IPropertyTreeIterator> buildSet = m_pRoot->getElements(xPath.str());
- buildSet->first();
- IPropertyTree* pBuildSet = &buildSet->query();
- const char* buildSetName = pBuildSet->queryProp(XML_ATTR_NAME);
- const char* processName = pBuildSet->queryProp(XML_ATTR_PROCESS_NAME);
- const char* buildName = m_pRoot->queryPropTree("./Programs/Build[1]")->queryProp(XML_ATTR_NAME);
- if (!processName) //support non-generic components as well
- processName = buildSetName;
- {
- // Use lower case version of type for name prefix
- StringBuffer sName(buildSetName);
- sName.toLowerCase();
- sName.replaceString("process","");
- if(sbNewName.length())
- value.append(sbNewName.str()).append(getUniqueName(m_pRoot.get(), sName, processName, "Software"));
- else
- value.append(getUniqueName(m_pRoot.get(), sName, processName, "Software"));
- pCompTree->setProp(XML_ATTR_NAME,value);
- sbNewName.clear().append(sName);
- pCompTree->setProp(XML_ATTR_BUILD, buildName);
- pCompTree->setProp(XML_ATTR_BUILDSET,pszBuildSet);
- Owned<IPropertyTree> pProperties = pBuildSet->getPropTree("Properties");
- if (pProperties)
- pCompTree->addPropTree("Properties", createPTree(pProperties));
- addNode(pCompTree, m_pRoot->queryPropTree("Software"));
- }
- }
- catch (IException* e)
- {
- throw e;
- }
- }
- bool CConfigEnvHelper::EnsureInRange(const char* psz, UINT low, UINT high, const char* caption)
- {
- bool rc = false;
- StringBuffer msg;
- const UINT x = atoi( psz );
- if ( ((low < high) && (x < low || x > high)) || (low == high && x != low) )
- {
- msg.append(caption).append(" must be ");
- if (low == high)
- msg.append(low);
- else
- {
- msg.append("between ");
- msg.append(low).append(" and ");
- msg.append( high );
- }
- }
- else
- if (high == 0 && x < low)
- msg.append(caption).append(" must be at least ").append(low);
- else
- rc = true;
- if (!rc)
- {
- msg.append('.');
- throw MakeStringException(-1, msg.str());
- }
- return rc;
- }
- bool CConfigEnvHelper::handleRoxieSlaveConfig(const char* xmlArg)
- {
- try
- {
- Owned<IPropertyTree> pSrcTree = createPTreeFromXMLString(xmlArg && *xmlArg ? xmlArg : "<RoxieData/>", false);
- const char* type = pSrcTree->queryProp(XML_ATTR_TYPE);
- const char* pszRoxie = pSrcTree->queryProp("@roxieName");
- const char* val1 = pSrcTree->queryProp("@val1");
- const char* sOffset = pSrcTree->queryProp("@val2");
- StringBuffer dir1, dir2, dir3;
- getCommonDir(m_pRoot.get(), "data", "roxie", pszRoxie, dir1);
- getCommonDir(m_pRoot.get(), "data2", "roxie", pszRoxie, dir2);
- getCommonDir(m_pRoot.get(), "data3", "roxie", pszRoxie, dir3);
- StringBuffer xpath;
- xpath.clear().appendf("Software/RoxieCluster[@name='%s']", pszRoxie);
- IPropertyTree* pRoxie = m_pRoot->queryPropTree(xpath.str());
- if (!pRoxie)
- throw MakeStringException(-1, "Cannot find roxie with name %s", pszRoxie);
- Owned<IPropertyTreeIterator> iterComputers = pSrcTree->getElements("Computer");
- IPropertyTreePtrArray computers;
- ForEach (*iterComputers)
- {
- IPropertyTree* pComp = &iterComputers->query();
- const char* pszCompName = pComp->queryProp(XML_ATTR_NAME);
- xpath.clear().appendf(XML_TAG_HARDWARE"/"XML_TAG_COMPUTER"/["XML_ATTR_NAME"='%s']", pszCompName);
- IPropertyTree* pComputer = m_pRoot->queryPropTree(xpath.str());
-
- if (pComputer)
- computers.push_back(pComputer);
- }
- m_numChannels = atoi(val1);
- m_numDataCopies = 0;
- const char* confType;
- char chDrive;
- if (!strcmp(type, "Circular"))
- {
- if (!GenerateCyclicRedConfig(pRoxie, computers, val1, sOffset, dir1.str(), dir2.str(), dir3.str()))
- return false;
- confType = "cyclic redundancy";
- chDrive = 'c';
- pRoxie->setProp("@cyclicOffset", sOffset);
- }
- else
- {
- if (!strcmp(type, "Overloaded"))
- {
- if (!GenerateOverloadedConfig(pRoxie, computers, val1, dir1.str(), dir2.str(), dir3.str()))
- return false;
- confType = "overloaded";
- chDrive = 'c';
- }
- else
- {
- if (!strcmp(type, "Full"))
- {
- m_numDataCopies = atoi( val1 );
- confType = "full redundancy";
- }
- else //no redundancy
- {
- m_numDataCopies = 1;
- confType = "simple";
- }
- if (!GenerateFullRedConfig(pRoxie, m_numDataCopies, computers, dir1.str()))
- return false;
- }
- if (pRoxie->hasProp("@cyclicOffset"))
- pRoxie->removeProp("@cyclicOffset");
- }
- StringBuffer sDataDir;
- sDataDir.appendf("%s", dir1.str());
- //give legacy slaves unique names
- UINT i = 1;
- Owned<IPropertyTreeIterator> it = pRoxie->getElements(XML_TAG_ROXIE_SLAVE);
- ForEach( *it)
- {
- StringBuffer name;
- name.append('s').append(i);
- IPropertyTree* pLegacySlave = &it->query();
- pLegacySlave->setProp(XML_ATTR_NAME, name.str() );
- if (i++==1)
- makePlatformSpecificAbsolutePath( pLegacySlave->queryProp(XML_ATTR_COMPUTER), sDataDir);
- }
- pRoxie->setProp("@slaveConfig", confType);
- pRoxie->setPropInt("@clusterWidth", computers.size());
- pRoxie->setPropInt("@numChannels", m_numChannels);
- pRoxie->setPropInt("@numDataCopies", m_numDataCopies);
- pRoxie->setProp("@baseDataDir", sDataDir.str());
- pRoxie->setProp("@localSlave", computers.size() > 1 ? "false" : "true");
- //update Roxie data directories for all farms and all legacy servers
- //change all farms
- Owned<IPropertyTreeIterator> iterFarms = pRoxie->getElements(XML_TAG_ROXIE_FARM);
- ForEach (*iterFarms)
- {
- IPropertyTree* pTmpComp = &iterFarms->query();
- if (strcmp(pTmpComp->queryProp(XML_ATTR_DATADIRECTORY), sDataDir.str()))
- pTmpComp->setProp(XML_ATTR_DATADIRECTORY, sDataDir.str());
- }
- //change all legacy servers
- Owned<IPropertyTreeIterator> iterServers = pRoxie->getElements(XML_TAG_ROXIE_SERVER);
- ForEach (*iterServers)
- {
- IPropertyTree* pTmpComp = &iterServers->query();
- if (strcmp(pTmpComp->queryProp(XML_ATTR_DATADIRECTORY), sDataDir.str()))
- pTmpComp->setProp(XML_ATTR_DATADIRECTORY, sDataDir.str());
- }
- }
- catch (IException *e)
- {
- StringBuffer msg;
- throw MakeStringException(-1, e->errorMessage(msg).str());
- }
- catch (...)
- {
- throw MakeStringException(-1, "Unknown exception in generating slave configuration!" );
- }
- return true;
- }
- void CConfigEnvHelper::addReplicateConfig(IPropertyTree* pSlaveNode, int channel, const char* dir,
- const char* netAddress, IPropertyTree* pRoxie)
- {
- StringBuffer directory;
- directory.appendf("%s", dir);
- makePlatformSpecificAbsolutePath( pSlaveNode->queryProp(XML_ATTR_COMPUTER), directory);
- IPropertyTree* pInstance = pSlaveNode->addPropTree(XML_TAG_ROXIE_CHANNEL, createPTree(false));
- pInstance->setPropInt("@number", channel);
- pInstance->addProp(XML_ATTR_DATADIRECTORY, directory.str());
-
- //maintain a copy as an old style slave procss
- IPropertyTree* pSlaveProcess = pRoxie->addPropTree(XML_TAG_ROXIE_SLAVE, createPTree(false));
- pSlaveProcess->addProp(XML_ATTR_COMPUTER, pSlaveNode->queryProp(XML_ATTR_COMPUTER));
- pSlaveProcess->addPropInt("@channel", channel);
- pSlaveProcess->addProp(XML_ATTR_DATADIRECTORY, directory.str());
- pSlaveProcess->addProp(XML_ATTR_NETADDRESS, netAddress);
- }
- bool CConfigEnvHelper::GenerateCyclicRedConfig(IPropertyTree* pRoxie, IPropertyTreePtrArray& computers,
- const char* copies, const char* pszOffset,
- const char* dir1, const char* dir2, const char* dir3)
- {
- const int nComputers = computers.size();
- if (!nComputers)
- return false;
- if (!EnsureInRange(copies, min(2, nComputers), max(nComputers, 1), "Channel redundancy") ||
- !EnsureInRange(pszOffset, min(1, nComputers-1), nComputers-1, "Channel offset"))
- {
- return false;
- }
- const int offset = atoi( pszOffset );
- m_numDataCopies = atoi( copies );
-
- const int minOffset = min(1, nComputers-1);
- if( offset < minOffset )
- throw MakeStringException(-1, "Offset cannot be less than %d", minOffset);
- if ( offset > nComputers )
- throw MakeStringException(-1, "Offset cannot be greater than %d", nComputers);
- RemoveSlaves(pRoxie, true);
- RemoveSlaves(pRoxie, false);
- for (int i=0; i<nComputers; i++)
- {
- IPropertyTree* pComputer = computers[i];
- const char* szComputer = pComputer->queryProp(XML_ATTR_NAME);
- const char* netAddress = pComputer->queryProp(XML_ATTR_NETADDRESS);
- StringBuffer name;
- name.appendf("s%d", i+1);
- IPropertyTree* pSlave = pRoxie->addPropTree(XML_TAG_ROXIE_ONLY_SLAVE, createPTree(false));
- pSlave->addProp(XML_ATTR_NAME, name.str());
- pSlave->addProp(XML_ATTR_COMPUTER, szComputer);
- const int baseChannel = i; //channel for first copy of slave (0 based)
- int channel;
- for (int c=0; c<m_numDataCopies; c++)
- {
- const char drive = 'c' + c;
- channel = 1 + ((baseChannel + c*(nComputers-offset)) % nComputers);
- addReplicateConfig(pSlave, channel, c==0? dir1: (c==1?dir2:dir3), netAddress, pRoxie);
- }
- }
- m_numChannels = nComputers;
- return true;
- }
- bool CConfigEnvHelper::GenerateOverloadedConfig(IPropertyTree* pRoxie, IPropertyTreePtrArray& computers, const char* copies,
- const char* dir1, const char* dir2, const char* dir3)
- {
- const UINT nComputers = computers.size();
- if (!nComputers)
- return false;
- if (!EnsureInRange(copies, 1, 0, "Channels per host"))
- return false;
- m_numDataCopies = atoi( copies );
-
- RemoveSlaves(pRoxie, true);
- RemoveSlaves(pRoxie, false);
- int channel = 1;
- for (UINT i=0; i<nComputers; i++)
- {
- IPropertyTree* pComputer = computers[i];
- const char* szComputer = pComputer->queryProp(XML_ATTR_NAME);
- const char* netAddress = pComputer->queryProp(XML_ATTR_NETADDRESS);
- StringBuffer name;
- name.appendf("s%d", i+1);
- IPropertyTree* pSlave = pRoxie->addPropTree(XML_TAG_ROXIE_ONLY_SLAVE, createPTree(false));
- pSlave->addProp(XML_ATTR_NAME, name.str());
- pSlave->addProp(XML_ATTR_COMPUTER, szComputer);
- for (int c=0; c<m_numDataCopies; c++)
- {
- const char drive = 'c' + c;
- addReplicateConfig(pSlave, channel + c*nComputers, c==0?dir1:(c==1?dir2:dir3), netAddress, pRoxie);
- }
- channel++;
- }
- m_numChannels = m_numDataCopies*nComputers;
- return true;
- }
- bool CConfigEnvHelper::GenerateFullRedConfig(IPropertyTree* pRoxie, int copies, IPropertyTreePtrArray& computers, const char* dir1)
- {
- int nComputers = computers.size();
- if (!nComputers)
- return false;
- StringBuffer sbCopies;
- sbCopies.appendf("%d", copies);
- //if full redundancy is selected then check channel redundancy
- if (copies != 1 && !EnsureInRange(sbCopies.str(), min(2, nComputers), (nComputers+1)/2, "Channel redundancy"))
- return false;
- const int maxChannel = nComputers / copies;
- RemoveSlaves(pRoxie, true);
- RemoveSlaves(pRoxie, false);
- int channel = 0;
- nComputers = maxChannel * copies;
- for (int i=0; i<nComputers; i++)
- {
- IPropertyTree* pComputer = computers[i];
- const char* szComputer = pComputer->queryProp(XML_ATTR_NAME);
- const char* netAddress = pComputer->queryProp(XML_ATTR_NETADDRESS);
- StringBuffer name;
- name.appendf("s%d", i+1);
- IPropertyTree* pSlave = pRoxie->addPropTree(XML_TAG_ROXIE_ONLY_SLAVE, createPTree(false));
- pSlave->addProp(XML_ATTR_NAME, name.str());
- pSlave->addProp(XML_ATTR_COMPUTER, szComputer);
- addReplicateConfig(pSlave, 1 + (channel++ % maxChannel), dir1, netAddress, pRoxie);
- }
- m_numChannels = maxChannel;
- return true;
- }
- void CConfigEnvHelper::RemoveSlaves(IPropertyTree* pRoxie, bool bLegacySlaves/*=false*/)
- {
- IPropertyTree* pChild;
- while (pChild = pRoxie->queryPropTree( bLegacySlaves ? XML_TAG_ROXIE_SLAVE "[1]" : "RoxieSlave[1]"))
- pRoxie->removeTree( pChild );
- }
- void CConfigEnvHelper::RenameThorInstances(IPropertyTree* pThor)
- {
- // Iterate through topology nodes
- int nSlave = 1;
- int nSpare = 1;
- Owned<IPropertyTreeIterator> iter = pThor->getElements(XML_TAG_TOPOLOGY"//"XML_TAG_NODE);
- for (iter->first(); iter->isValid(); iter->next())
- {
- // Get macthing process node
- const char* szProcess = iter->query().queryProp(XML_ATTR_PROCESS);
- IPropertyTree* pProcessNode = GetProcessNode(pThor, szProcess);
- if (pProcessNode)
- {
- StringBuffer sName;
- const char* szTag = pProcessNode->queryName();
- if (strcmp(szTag, XML_TAG_THORSLAVEPROCESS) == 0)
- sName.appendf("s%d", nSlave++);
- else if (strcmp(szTag, XML_TAG_THORSPAREPROCESS) == 0)
- sName.appendf("spare%d", nSpare++);
- else if (strcmp(szTag, XML_TAG_THORMASTERPROCESS) == 0)
- sName = "m1";
- else continue;
- setAttribute(pProcessNode, XML_ATTR_NAME, sName);
- setAttribute(&iter->query(), XML_ATTR_PROCESS, sName);
- }
- }
- }
- //----------------------------------------------------------------------------
- // UpdateAttributes
- //----------------------------------------------------------------------------
- void CConfigEnvHelper::UpdateThorAttributes(IPropertyTree* pParentNode)
- {
- // Update computer attribute
- //IPropertyTree* pParentNode = GetParentNode();
- IPropertyTree* pNode = pParentNode->queryPropTree(XML_TAG_THORMASTERPROCESS);
- if (pNode)
- {
- const char* szName = pNode->queryProp(XML_ATTR_COMPUTER);
- setAttribute(pParentNode, XML_ATTR_COMPUTER, szName);
- }
- // Update slave count attribute
- int nSlaves = 0;
- bool multiSlaves = false;
- Owned<IPropertyTreeIterator> iter = pParentNode->getElements(XML_TAG_THORSLAVEPROCESS);
- StringArray sComputers;
- for (iter->first(); iter->isValid(); iter->next())
- {
- nSlaves++;
- if (!multiSlaves)
- {
- const char* computer = iter->query().queryProp(XML_ATTR_COMPUTER);
- if (sComputers.find(computer) == NotFound)
- sComputers.append(computer);
- else
- multiSlaves = true;
- }
- }
- setAttribute(pParentNode, XML_ATTR_MULTISLAVES, multiSlaves ? "true" : "false");
- setAttribute(pParentNode, "@localThor", nSlaves > 1 ? "false" : "true");
- StringBuffer sb;
- sb.appendf("%d", nSlaves);
- setAttribute(pParentNode, XML_ATTR_SLAVES, sb.str());
- }
- //---------------------------------------------------------------------------
- // AddNewNodes
- //---------------------------------------------------------------------------
- bool CConfigEnvHelper::AddNewNodes(IPropertyTree* pThor, const char* szType, int nPort, IPropertyTreePtrArray& computers, bool validate, bool skipExisting, StringBuffer& usageList, int slavesPerNode)
- {
- // Get parent node
- IPropertyTree* pParentNode = pThor;
- if (validate)
- {
- for (int i = 0; i < (int) computers.size(); i++)
- CheckTopologyComputerUse(computers[i], pThor, usageList);
- }
- if (usageList.length() > 0)
- return false;
- // Iterate through computer list
- for (int i = 0; i < (int) computers.size(); i++)
- {
- // Check if we can add this computer
- if (skipExisting && !CheckTopologyComputerUse(computers[i], pThor, usageList))
- continue;
- for (int j = 0; j < slavesPerNode; j++)
- {
- StringBuffer sName;
- sName.appendf("temp%d", i + j + 1);
- // Add process node
- IPropertyTree* pProcessNode = createPTree(szType, false);
- pProcessNode->addProp(XML_ATTR_NAME, sName);
- pProcessNode->addProp(XML_ATTR_COMPUTER, computers[i]->queryProp(XML_ATTR_NAME));
- if (nPort != 0) pProcessNode->addPropInt(XML_ATTR_PORT, nPort);
- addNode(pProcessNode, pThor);
- //some thor "Topology" have been known to have multiple (unused) "Node" children with the same name
- //so reuse any unused Topology/Node
- //
- Owned<IPropertyTreeIterator> iter = pThor->getElements(XML_TAG_TOPOLOGY"//"XML_TAG_NODE);
- IPropertyTree* pNode = NULL;
- ForEach(*iter)
- {
- // Get macthing process node
- const char* szProcess = iter->query().queryProp(XML_ATTR_PROCESS);
- IPropertyTree* pProcessNode = GetProcessNode(pThor, szProcess);
- if (!pProcessNode)
- {
- pNode = &iter->query();
- pNode->setProp(XML_ATTR_PROCESS, sName);
- break;
- }
- }
- if (!pNode)
- {
- // Add topology node
- pNode = createPTree(XML_TAG_NODE, false);
- pNode->addProp(XML_ATTR_PROCESS, sName);
- IPropertyTree* pTopoNode = pThor->queryPropTree(XML_TAG_TOPOLOGY);
- if (!pTopoNode)
- pTopoNode = pThor->addPropTree(XML_TAG_TOPOLOGY, createPTree(false));
- if (!strcmp(szType, XML_TAG_THORSLAVEPROCESS))
- {
- Owned<IPropertyTreeIterator> iter = pThor->getElements(XML_TAG_TOPOLOGY"//"XML_TAG_NODE);
- ForEach(*iter)
- {
- // Get macthing process node
- const char* szProcess = iter->query().queryProp(XML_ATTR_PROCESS);
- IPropertyTree* pProcessNode = GetProcessNode(pThor, szProcess);
- if (!strcmp(pProcessNode->queryName(), XML_TAG_THORMASTERPROCESS))
- {
- addNode(pNode, &iter->query());
- break;
- }
- }
- }
- else
- addNode(pNode, pTopoNode);
- }
- }
- }
- RenameThorInstances(pThor);
- UpdateThorAttributes(pThor);
- return true;
- }
- bool CConfigEnvHelper::CheckTopologyComputerUse(IPropertyTree* pComputerNode, IPropertyTree* pParentNode, StringBuffer& usageList) const
- {
- const char* szNetAddress = pComputerNode->queryProp(XML_ATTR_NETADDRESS);
- bool retVal = true;
- StringArray sElementTypes;
- StringBuffer xpath;
- Owned<IPropertyTreeIterator> iter = pParentNode->getElements("*");
- for (iter->first(); iter->isValid(); iter->next())
- {
- const char* szTag = iter->query().queryName();
- if (sElementTypes.find(szTag) == NotFound)
- {
- IPropertyTree* pTree = &iter->query();
- const char* pszComputer = pTree->queryProp(XML_ATTR_COMPUTER);
- xpath.clear().appendf(XML_TAG_HARDWARE"/"XML_TAG_COMPUTER"["XML_ATTR_NAME"='%s']", pszComputer);
- IPropertyTree* pComputer = m_pRoot->queryPropTree(xpath.str());
- const char* szNetAddress1 = pComputer?pComputer->queryProp(XML_ATTR_NETADDRESS):NULL;
- if (szNetAddress1 && strcmp(szNetAddress1, szNetAddress)==0)
- {
- usageList.appendf("\n%s:%s - %s",
- pComputerNode->queryProp(XML_ATTR_NAME),
- pComputerNode->queryProp(XML_ATTR_NETADDRESS),
- szTag);
- // Save the found type and suppress warnings for those types
- sElementTypes.append(szTag);
- retVal = false;
- }
- }
- }
- return retVal;
- }
- //---------------------------------------------------------------------------
- // GetProcessNode
- //---------------------------------------------------------------------------
- IPropertyTree* CConfigEnvHelper::GetProcessNode(IPropertyTree* pThor, const char* szProcess) const
- {
- if (szProcess && *szProcess)
- {
- Owned<IPropertyTreeIterator> iter = pThor->getElements("*");
- ForEach(*iter)
- {
- const char* szName = iter->query().queryProp(XML_ATTR_NAME);
- if (szName && strcmp(szName, szProcess) == 0)
- return &iter->query();
- }
- }
- return NULL;
- }
|