/*############################################################################## 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 . ############################################################################## */ #pragma warning (disable : 4786) #include #include "jfile.hpp" #include "wshelpers.hpp" #include "portlist.h" #include "jiface.hpp" #include "environment.hpp" #include "TpWrapper.hpp" #include "jstring.hpp" #include "dautils.hpp" #include "eclrtl.hpp" #include "fverror.hpp" #include "exception_util.hpp" #include "ws_roxiequeryservice.hpp" const unsigned int ROXIEQUERYID = 1; const unsigned int ROXIEQUERYWUID = 2; const unsigned int ROXIEQUERYCLUSTER = 3; const unsigned int ROXIEQUERYLABEL = 4; const unsigned int ROXIEQUERYSUSPENDED = 5; const unsigned int ROXIEQUERYHIGHPRIORITY = 6; const unsigned int ROXIEQUERYERROR = 7; const unsigned int ROXIEQUERYCOMMENT = 8; const unsigned int ROXIEQUERYASSOCIATEDNAME = 9; const unsigned int ROXIEQUERYHASALIASES = 10; const unsigned int ROXIEQUERYDEPLOYEDBY = 11; const unsigned int ROXIEQUERYUPDATEDBY = 12; static const char* FEATURE_URL="RoxieQueryAccess"; static const char* ROXIE_CLUSTER="RoxieCluster"; static const char* ROXIE_FARMERPROCESS1="RoxieServerProcess[1]"; __int64 findPositionInRoxieQueryList(int type, const char *value, bool descend, IArrayOf& queries) { if (!value || (strlen(value) < 1)) { if (descend) return -1; else return 0; } __int64 addToPos = -1; ForEachItemIn(i, queries) { IEspRoxieQuery& query = queries.item(i); char *Value = NULL; switch (type) { case ROXIEQUERYID: Value = (char *) query.getID(); break; case ROXIEQUERYDEPLOYEDBY: Value = (char *) query.getDeployedBy(); break; case ROXIEQUERYUPDATEDBY: Value = (char *) query.getUpdatedBy(); break; case ROXIEQUERYWUID: Value = (char *) query.getWUID(); break; case ROXIEQUERYSUSPENDED: Value = (char *) query.getSuspended(); break; case ROXIEQUERYHIGHPRIORITY: Value = (char *) query.getHighPriority(); break; case ROXIEQUERYERROR: Value = (char *) query.getError(); break; case ROXIEQUERYCOMMENT: Value = (char *) query.getComment(); break; case ROXIEQUERYHASALIASES: Value = (char *) query.getHasAliases(); break; } if (!Value) continue; if (type != ROXIEQUERYID) { if (descend && strcmp(value, Value)>0) { addToPos = i; break; } if (!descend && strcmp(value, Value)<0) { addToPos = i; break; } } else { if (descend && stricmp(value, Value)>0) { addToPos = i; break; } if (!descend && stricmp(value, Value)<0) { addToPos = i; break; } } } return addToPos; } void getUserInformation(IEspContext &context, StringBuffer &username, StringBuffer &password) { context.getUserID(username); context.getPassword(password); } void CWsRoxieQueryEx::init(IPropertyTree *cfg, const char *process, const char *service) { IPropertyTree* pStyleSheets = cfg->queryPropTree("StyleSheets"); const char* xslt = cfg->queryProp("xslt[@name='atts']"); m_attsXSLT.append(getCFD()).append( xslt && *xslt ? xslt : "smc_xslt/atts.xslt"); xslt = cfg->queryProp("xslt[@name='graphStats']"); m_graphStatsXSLT.append(getCFD()).append( xslt && *xslt ? xslt : "smc_xslt/graphStats.xslt"); } void CWsRoxieQueryEx::addToQueryString(StringBuffer &queryString, const char *name, const char *value) { if (queryString.length() > 0) { queryString.append("&"); } queryString.append(name); queryString.append("="); queryString.append(value); } void CWsRoxieQueryEx::addToQueryStringFromInt(StringBuffer &queryString, const char *name, int value) { if (queryString.length() > 0) { queryString.append("&"); } queryString.append(name); queryString.append("="); queryString.append(value); } void CWsRoxieQueryEx::getClusterConfig(char const * clusterType, char const * clusterName, char const * processName, StringBuffer& netAddress, int& port) { Owned factory = getEnvironmentFactory(); #if 0 Owned environment = factory->openEnvironment(); #else Owned environment = factory->openEnvironmentByFile(); #endif Owned pRoot = &environment->getPTree(); StringBuffer xpath; xpath.appendf("Software/%s[@name='%s']", clusterType, clusterName); IPropertyTree* pCluster = pRoot->queryPropTree( xpath.str() ); if (!pCluster) throw MakeStringException(ECLWATCH_CLUSTER_NOT_IN_ENV_INFO, "Failed to get environment information for the cluster '%s %s'.", clusterType, clusterName); xpath.clear().append(processName); xpath.append("@computer"); const char* computer = pCluster->queryProp(xpath.str()); if (!computer || strlen(computer) < 1) throw MakeStringException(ECLWATCH_CLUSTER_NOT_IN_ENV_INFO, "Failed to get the 'computer' information for the process '%s'. Please check environment settings for the cluster '%s %s'.", processName, clusterType, clusterName); xpath.clear().append(processName); xpath.append("@port"); const char* portStr = pCluster->queryProp(xpath.str()); port = ROXIE_SERVER_PORT; if (portStr && *portStr) { port = atoi(portStr); } Owned pMachine = environment->getMachine(computer); if (pMachine) { SCMStringBuffer scmNetAddress; pMachine->getNetAddress(scmNetAddress); netAddress = scmNetAddress.str(); #ifdef MACHINE_IP if (!strcmp(netAddress.str(), ".")) netAddress = MACHINE_IP; #endif } return; } bool CWsRoxieQueryEx::onRoxieQuerySearch(IEspContext &context, IEspRoxieQuerySearchRequest & req, IEspRoxieQuerySearchResponse & resp) { try { if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false)) throw MakeStringException(ECLWATCH_ROXIE_QUERY_ACCESS_DENIED, "Failed to Search Roxie Queries. Permission denied."); StringBuffer username; context.getUserID(username); DBGLOG("CWsRoxieQueryEx::onRoxieQuerySearch User=%s",username.str()); CTpWrapper dummy; IArrayOf clusters; dummy.getClusterProcessList(eqRoxieCluster, clusters); if (clusters.length() <= 0) throw MakeStringException(ECLWATCH_CLUSTER_NOT_IN_ENV_INFO, "Roxie cluster not found."); StringArray roxieclusters; ForEachItemIn(k, clusters) { IEspTpCluster& cluster = clusters.item(k); roxieclusters.append(cluster.getName()); } StringArray ftarray; ftarray.append("Suspended and Non-Suspended"); ftarray.append("Non-Suspended Only"); ftarray.append("Suspended Only"); resp.setClusterNames(roxieclusters); resp.setSuspendedSelections(ftarray); } catch(IException* e) { FORWARDEXCEPTION(e, ECLWATCH_INTERNAL_ERROR); } return true; } bool CWsRoxieQueryEx::getAllRoxieQueries(IEspContext &context, const char* cluster, const char* suspended, const char* sortBy, bool descending, __int64 displayEnd, IArrayOf& RoxieQueryList, __int64& totalFiles) { int port; StringBuffer netAddress; SocketEndpoint ep; getClusterConfig(ROXIE_CLUSTER, cluster, ROXIE_FARMERPROCESS1, netAddress, port); int suspendedFlag = 0; if (suspended && *suspended) { if (stricmp(suspended, "Suspended Only") == 0) { suspendedFlag = 2; } else if (stricmp(suspended, "Non-Suspended Only") == 0) { suspendedFlag = 1; } } ep.set(netAddress.str(), port); StringBuffer username, password; getUserInformation(context, username, password); StringBuffer currentDaliIp; const SocketEndpoint &ep1 = queryCoven().queryComm().queryGroup().queryNode(0).endpoint(); ep1.getUrlStr(currentDaliIp); LogLevel loglevel = getEspLogLevel(&context); Owned queryManager = createRoxieQueryManager(ep, cluster, currentDaliIp, 60000, username.str(), password.str(), loglevel); Owned result = queryManager->retrieveQueryList("*", false, false, false, false, 0); Owned queries = result->getElements("Query"); ForEach(*queries) { IPropertyTree &query = queries->query(); const char* id = query.queryProp("@id"); const char* wuid = query.queryProp("@wuid"); const char* deployedby = query.queryProp("@deployedBy"); const char* updatedby = query.queryProp("@suspendedBy"); const char* comment = query.queryProp("@comment"); const char* error = query.queryProp("@error"); bool bSuspended = query.getPropBool("@suspended", false); bool bHighPriority = query.getPropBool("@priority", false); bool bHasAliases = query.getPropBool("@hasAlias", false); if (suspendedFlag > 1) { if (!bSuspended) //Suspended Only continue; } else if (suspendedFlag > 0) { if (bSuspended) //Non-Suspended Only continue; } StringBuffer strSuspended, strHighPriority, strHasAliases; if (bSuspended) strSuspended.append("Yes"); else strSuspended.append("No"); if (bHighPriority) strHighPriority.append("Yes"); else strHighPriority.append("No"); if (bHasAliases) strHasAliases.append("Yes"); else strHasAliases.append("No"); Owned roxieQuery = createRoxieQuery("",""); if (id && *id) roxieQuery->setID(id); if (comment && *comment) roxieQuery->setComment(comment); if (error && *error) roxieQuery->setError("Yes"); else roxieQuery->setError("No"); roxieQuery->setHasAliases(strHasAliases.str()); roxieQuery->setSuspended(strSuspended.str()); roxieQuery->setHighPriority(strHighPriority.str()); double version = context.getClientVersion(); if (version > 1.00) { if (deployedby && *deployedby) roxieQuery->setDeployedBy(deployedby); if (updatedby && *updatedby) roxieQuery->setUpdatedBy(updatedby); } if (version > 1.01) { if (wuid && *wuid) roxieQuery->setWUID(wuid); } __int64 addToPos = -1; //Add to tail if (!sortBy) { addToPos = findPositionInRoxieQueryList(ROXIEQUERYID, id, false, RoxieQueryList); } else if (stricmp(sortBy, "ID")==0) { addToPos = findPositionInRoxieQueryList(ROXIEQUERYID, id, descending, RoxieQueryList); } else if (stricmp(sortBy, "DeployedBy")==0) { if (version > 1.00) { addToPos = findPositionInRoxieQueryList(ROXIEQUERYDEPLOYEDBY, deployedby, descending, RoxieQueryList); } } else if (stricmp(sortBy, "UpdatedBy")==0) { if (version > 1.00) { addToPos = findPositionInRoxieQueryList(ROXIEQUERYUPDATEDBY, updatedby, descending, RoxieQueryList); } } else if (stricmp(sortBy, "WUID")==0) { if (version > 1.01) { addToPos = findPositionInRoxieQueryList(ROXIEQUERYWUID, wuid, descending, RoxieQueryList); } } else if (stricmp(sortBy, "Suspended")==0) { addToPos = findPositionInRoxieQueryList(ROXIEQUERYSUSPENDED, strSuspended.str(), descending, RoxieQueryList); } else if (stricmp(sortBy, "HighPriority")==0) { addToPos = findPositionInRoxieQueryList(ROXIEQUERYHIGHPRIORITY, strHighPriority.str(), descending, RoxieQueryList); } else if (stricmp(sortBy, "Error")==0) { addToPos = findPositionInRoxieQueryList(ROXIEQUERYERROR, error, descending, RoxieQueryList); } else if (stricmp(sortBy, "Comment")==0) { addToPos = findPositionInRoxieQueryList(ROXIEQUERYCOMMENT, comment, descending, RoxieQueryList); } else if (stricmp(sortBy, "HasAliases")==0) { addToPos = findPositionInRoxieQueryList(ROXIEQUERYHASALIASES, strHighPriority.str(), descending, RoxieQueryList); } else { addToPos = findPositionInRoxieQueryList(ROXIEQUERYID, id, false, RoxieQueryList); } totalFiles++; if (addToPos < 0) RoxieQueryList.append(*roxieQuery.getClear()); else RoxieQueryList.add(*roxieQuery.getClear(), (int) addToPos); } return true; } bool CWsRoxieQueryEx::onRoxieQueryList(IEspContext &context, IEspRoxieQueryListRequest & req, IEspRoxieQueryListResponse & resp) { try { if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false)) throw MakeStringException(ECLWATCH_ROXIE_QUERY_ACCESS_DENIED, "Failed to List Roxie Queries. Permission denied."); StringBuffer username; context.getUserID(username); DBGLOG("CWsRoxieQueryEx::onRoxieQueryList User=%s",username.str()); const char* sortBy = req.getSortby(); bool descending = req.getDescending(); unsigned pagesize = req.getPageSize(); if (pagesize < 1) { pagesize = 100; } __int64 displayStartReq = 1; if (req.getPageStartFrom() > 0) displayStartReq = req.getPageStartFrom(); __int64 displayStart = displayStartReq - 1; __int64 displayEnd = displayStart + pagesize; StringBuffer size; __int64 totalFiles = 0; IArrayOf RoxieQueryList; const char* name = req.getLogicalName(); const char* cluster = req.getCluster(); if (!cluster || !*cluster) throw MakeStringException(ECLWATCH_INVALID_INPUT,"Cluster is not specified for retrieving Roxie queries."); getAllRoxieQueries(context, cluster, req.getSuspended(), sortBy, descending, displayEnd, RoxieQueryList, totalFiles); resp.setNumFiles(totalFiles); resp.setPageSize(pagesize); resp.setPageStartFrom(displayStart+1); resp.setPageEndAt(displayEnd); if (displayStart - pagesize > 0) resp.setPrevPageFrom(displayStart - pagesize + 1); else if(displayStart > 0) resp.setPrevPageFrom(1); if(displayEnd < totalFiles) { resp.setNextPageFrom(displayEnd+1); resp.setLastPageFrom(pagesize * (int) floor((double) totalFiles/pagesize) + 1); } StringBuffer ParametersForSorting; addToQueryString(ParametersForSorting, "Cluster", cluster); resp.setCluster(cluster); if (name && *name) { addToQueryString(ParametersForSorting, "LogicalName", name); resp.setLogicalName(name); } if (req.getSuspended() && *req.getSuspended()) addToQueryString(ParametersForSorting, "Suspended", req.getSuspended()); StringBuffer ParametersForPaging; addToQueryStringFromInt(ParametersForPaging, "PageSize", pagesize); descending = false; if (sortBy && *sortBy) { if (req.getDescending()) descending = req.getDescending(); resp.setSortby(sortBy); resp.setDescending(descending); addToQueryString(ParametersForPaging, "Sortby", sortBy); if (descending) { addToQueryString(ParametersForPaging, "Descending", "1"); } } if (ParametersForSorting.length() > 0) resp.setParametersForSorting(ParametersForSorting.str()); if (ParametersForPaging.length() > 0) resp.setParametersForPaging(ParametersForPaging.str()); resp.setRoxieQueries(RoxieQueryList); } catch(IException* e) { FORWARDEXCEPTION(e, ECLWATCH_INTERNAL_ERROR); } return true; } bool CWsRoxieQueryEx::onQueryDetails(IEspContext &context, IEspRoxieQueryDetailsRequest & req, IEspRoxieQueryDetailsResponse & resp) { try { if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false)) throw MakeStringException(ECLWATCH_ROXIE_QUERY_ACCESS_DENIED, "Failed to get Query Details. Permission denied."); StringBuffer username, password; getUserInformation(context, username, password); DBGLOG("CWsRoxieQueryEx::onQueryDetails User=%s",username.str()); const char* queryID = req.getQueryID(); const char* cluster = req.getCluster(); if (!queryID || !*queryID || !cluster || !*cluster) { throw MakeStringException(ECLWATCH_INVALID_INPUT,"Query ID or Cluster is not specified for retrieving query information."); } int port; StringBuffer netAddress; SocketEndpoint ep; getClusterConfig(ROXIE_CLUSTER, cluster, ROXIE_FARMERPROCESS1, netAddress, port); ep.set(netAddress.str(), port); StringBuffer currentDaliIp; const SocketEndpoint &ep1 = queryCoven().queryComm().queryGroup().queryNode(0).endpoint(); ep1.getUrlStr(currentDaliIp); LogLevel loglevel = getEspLogLevel(&context); Owned queryManager = createRoxieQueryManager(ep, cluster, currentDaliIp, 60000, username.str(), password.str(), loglevel); Owned result = queryManager->retrieveQueryList(queryID, false, false, false, false, 0); if (result) { Owned queries = result->getElements("Query"); ForEach(*queries) { IPropertyTree &query = queries->query(); const char* wuid = query.queryProp("@wuid"); const char* label = query.queryProp("@label"); const char* associatedName = query.queryProp("@associatedName"); const char* comment = query.queryProp("@comment"); const char* error = query.queryProp("@error"); const char* deployedby = query.queryProp("@deployedBy"); const char* updatedby = query.queryProp("@suspendedBy"); bool bSuspended = query.getPropBool("@suspended", false); bool bHighPriority = query.getPropBool("@priority", false); StringBuffer strSuspended, strHighPriority; if (bSuspended) resp.setSuspended("Yes"); else resp.setSuspended("No"); if (bHighPriority) resp.setHighPriority("Yes"); else resp.setHighPriority("No"); resp.setQueryID(queryID); resp.setCluster(cluster); if (wuid && *wuid) resp.setWUID(wuid); if (associatedName && *associatedName) resp.setAssociatedName(associatedName); if (label && *label) resp.setLabel(label); if (error && *error) resp.setError(error); if (comment && *comment) resp.setComment(comment); double version = context.getClientVersion(); if (version > 1.00) { if (deployedby && *deployedby) resp.setDeployedBy(deployedby); if (updatedby && *updatedby) resp.setUpdatedBy(updatedby); } break; } IArrayOf AliasList; Owned queries1 = result->getElements("Alias"); ForEach(*queries1) { IPropertyTree &query = queries1->query(); const char* id = query.queryProp("@id"); const char* original = query.queryProp("@original"); Owned alias = createRoxieQueryAlias("",""); if (id && *id) alias->setID(id); if (original && *original) alias->setOriginal(original); AliasList.append(*alias.getClear()); } resp.setAliases(AliasList); } } catch(IException* e) { FORWARDEXCEPTION(e, ECLWATCH_INTERNAL_ERROR); } return true; }