123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- /*##############################################################################
- HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ############################################################################## */
- /////////////////////////////////////////////////////////////////////////////
- //
- // ComputerPicker.cpp : implementation file
- //
- /////////////////////////////////////////////////////////////////////////////
- #include "computerpicker.hpp"
- #include "XMLTags.h"
- /*static*/MapStrToChar CComputerPicker::s_prefixMap;
- //---------------------------------------------------------------------------
- // CComputerPicker
- //---------------------------------------------------------------------------
- CComputerPicker::CComputerPicker()
- {
- if (s_prefixMap.empty())
- CreateComponentTypePrefixMap();
- }
- CComputerPicker::~CComputerPicker()
- {
- }
- //---------------------------------------------------------------------------
- // SetRootNode
- //---------------------------------------------------------------------------
- void CComputerPicker::SetRootNode(const IPropertyTree* pNode)
- {
- m_pRootNode = pNode;
- CreateComputerFilterTree();
- Refresh();
- }
- //generate a map containing unique prefix char based on component types, which can either
- //be process names, "Domain", "ComputerType" or "Subnet".
- //
- /*static*/
- void CComputerPicker::CreateComponentTypePrefixMap()
- {
- s_prefixMap["RoxieCluster" ] = 'C';
- s_prefixMap["DaliServerProcess"] = 'D';
- s_prefixMap["EspProcess" ] = 'E';
- s_prefixMap["HoleCluster" ] = 'H';
- s_prefixMap["LDAPServerProcess"] = 'L';
- s_prefixMap["PluginProcess" ] = 'P';
- s_prefixMap["SpareProcess" ] = 'S';
- s_prefixMap["ThorCluster" ] = 'T';
- s_prefixMap["DfuServerProcess" ] = 'U';
- s_prefixMap["SybaseProcess" ] = 'Y';
- s_prefixMap["EclAgentProcess" ] = 'a';
- s_prefixMap["EclServerProcess" ] = 'c';
- s_prefixMap["Domain" ] = 'd';
- s_prefixMap["ComputerType" ] = 'e';
- s_prefixMap["FTSlaveProcess" ] = 'f';
- s_prefixMap["EspService" ] = 's';
- s_prefixMap["Topology" ] = 't';
- s_prefixMap["Subnet" ] = 'u';
- }
- //returns a unique prefix char based on a component type, which can either
- //be a process name, "Domain", "ComputerType" or "Subnet".
- //
- /*static*/
- char CComputerPicker::GetPrefixForComponentType(const char* componType)
- {
- char prefix = ' ';
- MapStrToChar::const_iterator i = s_prefixMap.find(componType);
- if (i != s_prefixMap.end())
- prefix = (*i).second;
- return prefix;
- }
- const char* CComputerPicker::GetComponentTypeForPrefix(char chPrefix)
- {
- const char* szCompType = "";
- //this is inefficient and should be replaced by another map from prefix
- //to component type. However, this is only used for tooltip where time
- //is not an issue.
- MapStrToChar::const_iterator i = s_prefixMap.begin();
- MapStrToChar::const_iterator iEnd = s_prefixMap.end();
- for (; i != iEnd; i++)
- if ((*i).second == chPrefix)
- {
- szCompType = (*i).first.c_str();
- break;
- }
- return szCompType;
- }
- //---------------------------------------------------------------------------
- // ResetUsageMap
- //---------------------------------------------------------------------------
- void CComputerPicker::ResetUsageMap()
- {
- MapStrToStrArray::iterator i = m_usageMap.begin();
- MapStrToStrArray::iterator iEnd = m_usageMap.end();
- //empty all vectors keyed by all computers
- for (; i != iEnd; i++)
- {
- stringarray& usage = (*i).second;
- stringarray::iterator i2 = usage.begin();
- stringarray::iterator iEnd2 = usage.end();
- for (; i2 != iEnd2; i2++)
- {
- std::string& component = *i2;
- const char* szComponent = component.c_str();
- if (szComponent && *szComponent != '+')
- component[0] = '+';
- }
- }
- }
- bool CComputerPicker::GetUsage(const char* szComputer, StringBuffer& sUsage,
- bool bIncludeComponentType) const
- {
- MapStrToStrArray::const_iterator iUsage = m_usageMap.find(szComputer);
- bool bInclude = false;//computer isn't explicitly requested for by the user
- bool bExclude = false;//computer isn't explicitly excluded by the user
- if (iUsage != m_usageMap.end())
- {
- const stringarray& usage = (*iUsage).second;
- stringarray::const_iterator i2 = usage.begin();
- stringarray::const_iterator iEnd2 = usage.end();
- for (; i2 != iEnd2; i2++)
- {
- const std::string& component = *i2;
- const char* szComponent = component.c_str();
- if (szComponent)
- {
- char chStatus = *szComponent++;
- if (chStatus == 'I')
- bInclude = true;
- else
- if (chStatus == '-')
- bExclude = true;
- char chPrefix = *szComponent++;
- //gather usage anyway even for excluded components
- //since that needs to be shown in case another component
- //has explicitly asked this computer to be included
- //don't show usage info for domains, computer types and subnets
- if (chPrefix != 'd' && chPrefix != 'e' && chPrefix != 'u')
- {
- //if (!sUsage.IsEmpty())
- if (sUsage.length() > 0)
- sUsage.append(bIncludeComponentType ? '\n' : ' ');
- if (bIncludeComponentType)
- {
- StringBuffer sType = GetComponentTypeForPrefix(chPrefix);
- //if (!sType.IsEmpty())
- if (sUsage.length() > 0)
- {
- sUsage.append(sType);
- sUsage.append(" - ");
- }
- }
- sUsage.append(szComponent); //skip status and prefix characters
- }
- }
- }
- //if this computer has to be excluded because of some component and
- //then don't use it unless it is explicitly included by the user
- //for another
- if (bExclude && bInclude)
- bExclude = false;
- }
- return !bExclude;
- }
- //---------------------------------------------------------------------------
- // NoteUsage
- //---------------------------------------------------------------------------
- void CComputerPicker::NoteUsage(const char *computer, const char* componType,
- const char *name, char status/*='+'*/)
- {
- if (computer && *computer && componType && *componType && name && *name)
- {
- stringarray& usage = m_usageMap[computer];
- std::string sName;
- sName += status;
- sName += GetPrefixForComponentType(componType);
- sName += name;
- name = sName.c_str() + 1; //skip status
- //insert this entry in the array if not present already
- stringarray::iterator i = usage.begin();
- stringarray::iterator iEnd = usage.end();
- for (; i != iEnd; i++)
- {
- std::string& component = *i;
- const char* szCompName = component.c_str();
- if (szCompName && *szCompName && !strcmp(szCompName+1, name))
- {
- if (status != '-' || *szCompName != 'I')//don't mark unused if status is 'I'
- component[0] = status;
- break;
- }
- }
- if (i == iEnd)
- usage.push_back(sName);
- }
- }
- //---------------------------------------------------------------------------
- // CreateFilterTree
- //---------------------------------------------------------------------------
- void CComputerPicker::CreateComputerFilterTree()
- {
- m_pFilterTree.clear();
- m_pFilterTree.setown(createPTree("Filter"));
- IPropertyTree* pComponents= m_pFilterTree->addPropTree("Components", createPTree("Components"));
- IPropertyTree* pDomains = m_pFilterTree->addPropTree("Domains", createPTree("Domains"));
- IPropertyTree* pCompTypes = m_pFilterTree->addPropTree("ComputerTypes", createPTree("ComputerTypes"));
- IPropertyTree* pSubnets = m_pFilterTree->addPropTree("Subnets", createPTree("Subnets"));
- // Generate computer usage map
- if (m_pRootNode)
- {
- //collect all software components using any computers
- Owned<IPropertyTreeIterator> iter = m_pRootNode->getElements("Software/*");
- ForEach(*iter)
- {
- IPropertyTree &component = iter->query();
- const char* szProcessName = component.queryName();
- const char* szCompName = component.queryProp(XML_ATTR_NAME);
- const bool bThorCluster = strcmp(szProcessName, "ThorCluster")==0;
- if (bThorCluster || strcmp(szProcessName, "HoleCluster")==0 || strcmp(szProcessName, "RoxieCluster")==0)
- {
- Owned<IPropertyTreeIterator> instance = component.getElements("*[@computer]");
- ForEach(*instance)
- {
- const char* szComputer = instance->query().queryProp("@computer");
- NoteFilter(pComponents, szProcessName, szCompName, szComputer);
- NoteUsage(szComputer, szProcessName, szCompName);
- }
- }
- else
- {
- Owned<IPropertyTreeIterator> instance = component.getElements("Instance");
- ForEach(*instance)
- {
- const char* szComputer = instance->query().queryProp("@computer");
- NoteFilter(pComponents, szProcessName, szCompName, szComputer);
- NoteUsage(szComputer, szProcessName, szCompName);
- }
- const char* szComputer = component.queryProp("@computer");
- if (szComputer)
- {
- NoteFilter(pComponents, szProcessName, szCompName, szComputer);
- NoteUsage(szComputer, szProcessName, szCompName);
- }
- //if this is a dali server then get backup computer, if any
- if (strcmp(szProcessName, "DaliServerProcess")==0)
- {
- const char* szBackupComputer = component.queryProp("@backupComputer");
- NoteFilter(pComponents, szProcessName, szCompName, szBackupComputer);
- NoteUsage(szBackupComputer, szProcessName, szCompName);
- }
- }
- }
- iter.setown(m_pRootNode->getElements("Hardware/Domain"));
- ForEach(*iter)
- {
- const char* szDomain = iter->query().queryProp(XML_ATTR_NAME);
- StringBuffer xPath;
- xPath.appendf("Hardware/Computer[@domain='%s']", szDomain);
- //enumerate all computers in this domain
- Owned<IPropertyTreeIterator> icomputer = m_pRootNode->getElements(xPath);
- ForEach(*icomputer)
- {
- const char* szComputer = icomputer->query().queryProp("@name");
- NoteFilter(pDomains, "Domain", szDomain, szComputer);
- NoteUsage(szComputer, "Domain", szDomain);
- }
- }
- iter.setown(m_pRootNode->getElements("Hardware/ComputerType"));
- ForEach(*iter)
- {
- const char* szComputerType = iter->query().queryProp(XML_ATTR_NAME);
- StringBuffer xPath;
- xPath.appendf("Hardware/Computer[@computerType='%s']", szComputerType);
- //enumerate all computers with this computer type
- Owned<IPropertyTreeIterator> icomputer = m_pRootNode->getElements(xPath);
- ForEach(*icomputer)
- {
- const char* szComputer = icomputer->query().queryProp("@name");
- NoteFilter(pCompTypes, "ComputerType", szComputerType, szComputer);
- NoteUsage(szComputer, "ComputerType", szComputerType);
- }
- }
- //enumerate all computers and process their subnets
- Owned<IPropertyTreeIterator> icomputer = m_pRootNode->getElements("Hardware/Computer");
- ForEach(*icomputer)
- {
- IPropertyTree* pComputer = &icomputer->query();
- const char* szComputer = pComputer->queryProp("@name");
- const char* szNetAddress = pComputer->queryProp("@netAddress");
- if (szComputer && *szComputer && szNetAddress && *szNetAddress)
- {
- char szSubnet[128];
- strcpy(szSubnet, szNetAddress);
- char* pchDot = strrchr(szSubnet, '.');
- if (pchDot)
- {
- strcpy(pchDot+1, "0");
- //TRACE3("%s(%s)=> %s\n", szComputer, pComputer->queryProp("@netAddress"), szSubnet);
- NoteFilter(pSubnets, "Subnet", szSubnet, szComputer);
- NoteUsage(szComputer, "Subnet", szSubnet);
- }
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- // NoteFilter
- //---------------------------------------------------------------------------
- void CComputerPicker::NoteFilter(IPropertyTree* pFilter, const char *componentType,
- const char *component, const char* computer)
- {
- if (component && *component &&
- componentType && *componentType)
- {
- StringBuffer sComponentType(componentType);
- const char* psz = strstr(sComponentType.str(), "Process");
- if (psz)
- sComponentType.remove(psz - sComponentType.str(), strlen("Process"));
- StringBuffer xPath;
- xPath.appendf("%s[@name='%s']", sComponentType.str(), component);
- IPropertyTree* pComponentType = pFilter->queryPropTree(xPath);
- if (!pComponentType)
- {
- pComponentType = pFilter->addPropTree(sComponentType, createPTree(sComponentType));
- pComponentType->addProp("@name", component);
- }
- if (computer && *computer)
- {
- IPropertyTree* pComputer = pComponentType->addPropTree( "Computer", createPTree() );
- pComputer->addProp("@name", computer);
- pComputer->addPropBool("@__bHidden", true);
- }
- }
- }
- void CComputerPicker::Refresh()
- {
- // Passed all filters so add the computers left in the usage map
- int iItem = 0;
- m_pComputerTree.clear();
- m_pComputerTree.setown(createPTree("ComputerList"));
- Owned<IPropertyTreeIterator> iComputer = m_pRootNode->getElements(XML_TAG_HARDWARE "/" XML_TAG_COMPUTER);
- ForEach (*iComputer)
- {
- // Must have a valid name
- IPropertyTree* pNode = &iComputer->query();
- const char* szComputer = pNode->queryProp(XML_ATTR_NAME);
- StringBuffer sUsage;
- if (szComputer && *szComputer && GetUsage(szComputer, sUsage, false))
- {
- IPropertyTree* pComponentType = m_pComputerTree->addPropTree("Machine", createPTree("Machine"));
- pComponentType->addProp("@name", szComputer);
- pComponentType->addProp("@netAddress", pNode->queryProp(XML_ATTR_NETADDRESS));
- pComponentType->addProp("@usage", sUsage.str());
- }
- }
- }
- void CComputerPicker::ApplyFilter(const char* szSubTreeName,
- const char* szIncAttrib,
- char chStatus,
- StringBuffer& sFilterApplied)
- {
- StringBuffer xPath;
- xPath.appendf("%s/*[@%s]", szSubTreeName, szIncAttrib);
- Owned<IPropertyTreeIterator> iter = m_pFilterTree->getElements(xPath);
- ForEach(*iter)
- {
- IPropertyTree* pComponent = &iter->query();
- const char* szCompType = pComponent->queryName();
- const char* szCompName = pComponent->queryProp("@name");
- if (sFilterApplied.length() > 0)
- sFilterApplied.append(", ");
- sFilterApplied.append(szCompName);
- Owned<IPropertyTreeIterator> icomputer = pComponent->getElements("Computer[@name]");
- ForEach(*icomputer)
- {
- const char* szComputer = icomputer->query().queryProp("@name");
- if (szComputer)
- NoteUsage(szComputer, szCompType, szCompName, chStatus);
- }
- }
- }
|