Переглянути джерело

HPCC-14367 Support target alias names for roxies behind a VIP

Roxies accessed from behind a vip usually use seperate target names to
represent the same set of queries.  Each roxie can also run more than
one target at the same time.  A way is needed to specify that any of the
targets representing the same set of queries can be used.

Allowing targets that represent the same set of queries to have a shared
alias will allow callers to select the right set of queries when calling
through a VIP.

Signed-off-by: Anthony Fishbeck <anthony.fishbeck@lexisnexis.com>
Anthony Fishbeck 9 роки тому
батько
коміт
2c72cac7ec

+ 9 - 3
common/workunit/workunit.cpp

@@ -4269,6 +4269,7 @@ void getRoxieProcessServers(const char *process, SocketEndpointArray &servers)
 class CEnvironmentClusterInfo: public CInterface, implements IConstWUClusterInfo
 {
     StringAttr name;
+    StringAttr alias;
     StringAttr serverQueue;
     StringAttr agentQueue;
     StringAttr roxieProcess;
@@ -4287,8 +4288,8 @@ class CEnvironmentClusterInfo: public CInterface, implements IConstWUClusterInfo
 
 public:
     IMPLEMENT_IINTERFACE;
-    CEnvironmentClusterInfo(const char *_name, const char *_prefix, IPropertyTree *agent, IArrayOf<IPropertyTree> &thors, IPropertyTree *roxie)
-        : name(_name), prefix(_prefix), roxieRedundancy(0), channelsPerNode(0), roxieReplicateOffset(1)
+    CEnvironmentClusterInfo(const char *_name, const char *_prefix, const char *_alias, IPropertyTree *agent, IArrayOf<IPropertyTree> &thors, IPropertyTree *roxie)
+        : name(_name), prefix(_prefix), alias(_alias), roxieRedundancy(0), channelsPerNode(0), roxieReplicateOffset(1)
     {
         StringBuffer queue;
         if (thors.ordinality())
@@ -4375,6 +4376,11 @@ public:
         str.set(name.get());
         return str;
     }
+    IStringVal & getAlias(IStringVal & str) const
+    {
+        str.set(alias.get());
+        return str;
+    }
     IStringVal & getScope(IStringVal & str) const
     {
         str.set(prefix.get());
@@ -4650,7 +4656,7 @@ IConstWUClusterInfo* getTargetClusterInfo(IPropertyTree *environment, IPropertyT
         }
     }
     const char *roxieName = cluster->queryProp("RoxieCluster/@process");
-    return new CEnvironmentClusterInfo(clustname, prefix, agent, thors, queryRoxieProcessTree(environment, roxieName));
+    return new CEnvironmentClusterInfo(clustname, prefix, cluster->queryProp("@alias"), agent, thors, queryRoxieProcessTree(environment, roxieName));
 }
 
 IPropertyTree* getTopologyCluster(Owned<IPropertyTree> &envRoot, const char *clustname)

+ 1 - 0
common/workunit/workunit.hpp

@@ -527,6 +527,7 @@ interface IConstWUClusterInfo : extends IInterface
     virtual unsigned getRoxieRedundancy() const = 0;
     virtual unsigned getChannelsPerNode() const = 0;
     virtual int getRoxieReplicateOffset() const = 0;
+    virtual IStringVal & getAlias(IStringVal & str) const = 0;
 };
 
 //! IWorkflowItem

+ 10 - 3
esp/services/ws_ecl/ws_ecl_service.cpp

@@ -238,6 +238,7 @@ bool CWsEclService::init(const char * name, const char * type, IPropertyTree * c
 
     IPropertyTree *vips = serviceTree->queryPropTree("VIPS");
     Owned<IStringIterator> roxieTargets = getTargetClusters("RoxieCluster", NULL);
+
     ForEach(*roxieTargets)
     {
         SCMStringBuffer target;
@@ -260,6 +261,7 @@ bool CWsEclService::init(const char * name, const char * type, IPropertyTree * c
             {
                 vip = pc->queryProp("@vip");
                 includeTargetInURL = pc->getPropBool("@includeTargetInURL", true);
+
             }
         }
         StringBuffer list;
@@ -282,8 +284,12 @@ bool CWsEclService::init(const char * name, const char * type, IPropertyTree * c
         }
         if (list.length())
         {
-            Owned<ISmartSocketFactory> sf = new RoxieSocketFactory(list.str(), !loadBalanced, includeTargetInURL);
+            SCMStringBuffer alias;
+            clusterInfo->getAlias(alias);
+            Owned<ISmartSocketFactory> sf = new RoxieSocketFactory(list.str(), !loadBalanced, includeTargetInURL, loadBalanced ? alias.str() : NULL);
             connMap.setValue(target.str(), sf.get());
+            if (alias.length() && !connMap.getValue(alias.str())) //only need one vip per alias for routing purposes
+                connMap.setValue(alias.str(), sf.get());
         }
     }
 
@@ -1915,8 +1921,9 @@ void CWsEclBinding::sendRoxieRequest(const char *target, StringBuffer &req, Stri
         Owned<IHttpClientContext> httpctx = getHttpClientContext();
         StringBuffer url("http://");
         ep.getIpText(url).append(':').append(ep.port ? ep.port : 9876).append('/');
-        if (static_cast<RoxieSocketFactory*>(conn)->includeTargetInURL)
-            url.append(target);
+        RoxieSocketFactory *roxieConn = static_cast<RoxieSocketFactory*>(conn);
+        if (roxieConn->includeTargetInURL)
+            url.append(roxieConn->alias.isEmpty() ? target : roxieConn->alias.str());
         if (!trim)
             url.append("?.trim=0");
 

+ 5 - 2
esp/services/ws_ecl/ws_ecl_service.hpp

@@ -91,8 +91,9 @@ class RoxieSocketFactory : public CSmartSocketFactory
 {
 public:
     bool includeTargetInURL;
+    StringAttr alias;
 
-    RoxieSocketFactory(const char *_socklist, bool _retry, bool includeTarget) : CSmartSocketFactory(_socklist, _retry), includeTargetInURL(includeTarget)
+    RoxieSocketFactory(const char *_socklist, bool _retry, bool includeTarget, const char *_alias) : CSmartSocketFactory(_socklist, _retry), includeTargetInURL(includeTarget), alias(_alias)
     {
     }
 };
@@ -111,7 +112,9 @@ public:
 public:
     IMPLEMENT_IINTERFACE;
 
-    CWsEclService(){}
+    CWsEclService()
+    {
+    }
     ~CWsEclService();
 
     virtual const char * getServiceType(){return "ws_ecl";}

+ 14 - 0
initfiles/componentfiles/configxml/RoxieTopology.xsl

@@ -92,6 +92,11 @@
                     <xsl:with-param name="roxie" select="@name"/>
                 </xsl:call-template>
             </xsl:attribute>
+            <xsl:attribute name="targetAliases">
+                <xsl:call-template name="GetTargetAliases">
+                    <xsl:with-param name="roxie" select="@name"/>
+                </xsl:call-template>
+            </xsl:attribute>
             <xsl:attribute name="pluginDirectory">
                 <xsl:variable name="path" select="translate(@pluginsPath, '/$', '\:')"/>
                 <xsl:variable name="path2">
@@ -238,4 +243,13 @@
   </xsl:for-each>
 </xsl:template>
 
+<xsl:template name="GetTargetAliases">
+  <xsl:param name="roxie"/>
+  <xsl:for-each select="/Environment/Software/Topology/Cluster[@alias]/RoxieCluster[@process=$roxie]">
+   <xsl:value-of select="../@alias"/>=<xsl:value-of select="../@name"/>
+   <xsl:if test="position() != last()">,</xsl:if>
+  </xsl:for-each>
+</xsl:template>
+
+
 </xsl:stylesheet>

+ 1 - 0
roxie/ccd/ccd.hpp

@@ -325,6 +325,7 @@ extern IPropertyTree *ccdChannels;
 extern IPropertyTree *topology;
 extern MapStringTo<int> *preferredClusters;
 extern StringArray allQuerySetNames;
+extern IProperties *targetAliases;
 
 extern bool allFilesDynamic;
 extern bool lockSuperFiles;

+ 6 - 0
roxie/ccd/ccdlistener.cpp

@@ -1709,6 +1709,12 @@ readAnother:
                         {
                             client->setHttpMode(queryName, isRequestArray, httpHelper);
                             querySetName.set(httpHelper.queryTarget());
+                            if (querySetName.length())
+                            {
+                                const char *target = targetAliases->queryProp(querySetName.str());
+                                if (target)
+                                    querySetName.set(target);
+                            }
                         }
                         queryFactory.setown(globalPackageSetManager->getQuery(queryName, &querySetName, NULL, logctx));
                         if (queryFactory)

+ 15 - 0
roxie/ccd/ccdmain.cpp

@@ -92,6 +92,7 @@ StringBuffer topologyFile;
 CriticalSection ccdChannelsCrit;
 IPropertyTree* ccdChannels;
 StringArray allQuerySetNames;
+IProperties *targetAliases;
 
 bool allFilesDynamic;
 bool lockSuperFiles;
@@ -878,6 +879,20 @@ int STARTQUERY_API start_query(int argc, const char *argv[])
         topology->addPropBool("@linuxOS", true);
 #endif
         allQuerySetNames.appendListUniq(topology->queryProp("@querySets"), ",");
+        targetAliases = createProperties();
+        StringArray tempList;
+        tempList.appendListUniq(topology->queryProp("@targetAliases"), ",");
+        ForEachItemIn(i, tempList)
+        {
+            const char *alias = tempList.item(i);
+            const char *eq = strchr(alias, '=');
+            if (eq)
+            {
+                StringAttr name(alias, eq-alias);
+                if (!allQuerySetNames.contains(name))
+                    targetAliases->setProp(name.str(), ++eq);
+            }
+        }
 
         Owned<IPropertyTreeIterator> roxieServers = topology->getElements("./RoxieServerProcess");
         ForEach(*roxieServers)