فهرست منبع

HPCC-11398 Spray file using NodeGroup and change related display

Read and display node group as spray target to thor cluster;
Rename related variables/methods from 'cluster' to 'NodeGroup';
Rename the variable 'DFUQRFcluster' to 'DFUQRFnodegroup' and rename
the variable 'DFUQRFgroup' to 'DFUQRFnodegroups';
Rename the 'Cluster' column to 'NodeGroup' on Browse Logical File
page.

Signed-off-by: Kevin Wang kevin.wang@lexisnexis.com
Kevin Wang 11 سال پیش
والد
کامیت
fa136d9f24

+ 26 - 26
dali/base/dadfs.cpp

@@ -11741,34 +11741,34 @@ IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, DFUQResultF
     class CFileAttrIterator: public CInterface, implements IPropertyTreeIterator
     {
         Owned<IPropertyTree> cur;
-        StringArray fileClusterGroups;
+        StringArray fileNodeGroups;
 
-        void setFileCluster(IPropertyTree *attr, const char* group, StringArray& clusterFilter)
+        void setFileNodeGroup(IPropertyTree *attr, const char* group, StringArray& nodeGroupFilter)
         {
             if (!group || !*group)
                 return;
 
             //The group may contain multiple clusters and some of them may match with the clusterFilter.
-            if (clusterFilter.length() == 1)
-                attr->setProp(getDFUQResultFieldName(DFUQRFcluster), clusterFilter.item(0));//Filter has been handled on server side.
+            if (nodeGroupFilter.length() == 1)
+                attr->setProp(getDFUQResultFieldName(DFUQRFnodegroup), nodeGroupFilter.item(0));//Filter has been handled on server side.
             else
             {
-                StringArray clusters;
-                clusters.appendListUniq(group, ",");
-                ForEachItemIn(i,clusters)
+                StringArray groups;
+                groups.appendListUniq(group, ",");
+                ForEachItemIn(i,groups)
                 {
                     //Add a cluster if no cluster filter or the cluster matchs with cluster filter
-                    const char* cluster = clusters.item(i);
-                    if (cluster && *cluster && ((!clusterFilter.length()) || (clusterFilter.find(cluster) != NotFound)))
-                        fileClusterGroups.append(cluster);
+                    const char* node = groups.item(i);
+                    if (node && *node && ((!nodeGroupFilter.length()) || (nodeGroupFilter.find(node) != NotFound)))
+                        fileNodeGroups.append(node);
                 }
-                if (fileClusterGroups.length())
+                if (fileNodeGroups.length())
                 {
                     //if this file exists on multiple clusters, set one of the clusters as the "@DFUSFcluster" prop for
-                    //this attr, leaving the rest inside the fileClusterGroups array. Those clusters will be used by the
+                    //this attr, leaving the rest inside the fileNodeGroups array. Those clusters will be used by the
                     //duplicateFileAttrOnOtherClusterGroup() to duplicate this file attr on other clusters.
-                    attr->setProp(getDFUQResultFieldName(DFUQRFcluster), fileClusterGroups.item(fileClusterGroups.length() -1));
-                    fileClusterGroups.pop();
+                    attr->setProp(getDFUQResultFieldName(DFUQRFnodegroup), fileNodeGroups.item(fileNodeGroups.length() -1));
+                    fileNodeGroups.pop();
                 }
             }
         }
@@ -11791,7 +11791,7 @@ IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, DFUQResultF
             return;
         }
 
-        IPropertyTree *deserializeFileAttr(MemoryBuffer &mb, StringArray& clusterFilter)
+        IPropertyTree *deserializeFileAttr(MemoryBuffer &mb, StringArray& nodeGroupFilter)
         {
             IPropertyTree *attr = getEmptyAttr();
             StringAttr val;
@@ -11823,22 +11823,22 @@ IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, DFUQResultF
                 mb.read(at);
                 mb.read(val);
                 attr->setProp(at.get(),val.get());
-                if (strieq(at.get(), getDFUQResultFieldName(DFUQRFgroup)))
-                    setFileCluster(attr, val.get(), clusterFilter);
+                if (strieq(at.get(), getDFUQResultFieldName(DFUQRFnodegroups)))
+                    setFileNodeGroup(attr, val.get(), nodeGroupFilter);
             }
             attr->setPropInt64(getDFUQResultFieldName(DFUQRFsize), attr->getPropInt64(getDFUQResultFieldName(DFUQRForigsize), -1));//Sort the files with empty size to front
             setRecordCount(attr);
             return attr;
         }
 
-        IPropertyTree *duplicateFileAttrOnOtherClusterGroup(IPropertyTree *previousAttr)
+        IPropertyTree *duplicateFileAttrOnOtherNodeGroup(IPropertyTree *previousAttr)
         {
             IPropertyTree *attr = getEmptyAttr();
             Owned<IAttributeIterator> ai = previousAttr->getAttributes();
             ForEach(*ai)
                 attr->setProp(ai->queryName(),ai->queryValue());
-            attr->setProp(getDFUQResultFieldName(DFUQRFcluster), fileClusterGroups.item(fileClusterGroups.length()-1));
-            fileClusterGroups.pop();
+            attr->setProp(getDFUQResultFieldName(DFUQRFnodegroup), fileNodeGroups.item(fileNodeGroups.length()-1));
+            fileNodeGroups.pop();
             return attr;
         }
 
@@ -11846,7 +11846,7 @@ IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, DFUQResultF
         IMPLEMENT_IINTERFACE;
         MemoryBuffer mb;
         unsigned numfiles;
-        StringArray clusterFilter;
+        StringArray nodeGroupFilter;
 
         bool first()
         {
@@ -11858,9 +11858,9 @@ IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, DFUQResultF
 
         bool next()
         {
-            if (fileClusterGroups.length())
+            if (fileNodeGroups.length())
             {
-                IPropertyTree *attr = duplicateFileAttrOnOtherClusterGroup(cur);
+                IPropertyTree *attr = duplicateFileAttrOnOtherNodeGroup(cur);
                 cur.clear();
                 cur.setown(attr);
                 return true;
@@ -11868,7 +11868,7 @@ IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, DFUQResultF
             cur.clear();
             if (mb.getPos()>=mb.length())
                 return false;
-            cur.setown(deserializeFileAttr(mb, clusterFilter));
+            cur.setown(deserializeFileAttr(mb, nodeGroupFilter));
             return true;
         }
 
@@ -11892,8 +11892,8 @@ IPropertyTreeIterator *deserializeFileAttrIterator(MemoryBuffer& mb, DFUQResultF
             {
                 int fmt = localFilters[i];
                 int subfmt = (fmt&0xff);
-                if ((subfmt==DFUQRFcluster) && fv && *fv)
-                    clusterFilter.appendListUniq(fv, ",");
+                if ((subfmt==DFUQRFnodegroup) && fv && *fv)
+                    nodeGroupFilter.appendListUniq(fv, ",");
                 //Add more if needed
                 fv = fv + strlen(fv)+1;
             }

+ 2 - 2
dali/base/dadfs.hpp

@@ -240,7 +240,7 @@ enum DFUQResultField
 {
     DFUQRFname = 0,
     DFUQRFdescription = 1,
-    DFUQRFgroup = 2,
+    DFUQRFnodegroups = 2,
     DFUQRFkind = 3,
     DFUQRFtimemodified = 4,
     DFUQRFjob = 5,
@@ -251,7 +251,7 @@ enum DFUQResultField
     DFUQRFsize = 10,
     DFUQRForigsize = 11,
     DFUQRFworkunit = 12,
-    DFUQRFcluster = 13,
+    DFUQRFnodegroup = 13,
     DFUQRFnumsubfiles = 14,
     DFUQRFaccessed = 15,
     DFUQRFnumparts = 16,

+ 18 - 18
esp/eclwatch/ws_XSLT/dfu.xslt

@@ -20,7 +20,7 @@
     <xsl:output method="html"/>
     <xsl:variable name="owner" select="/DFUQueryResponse/Owner"/>
     <xsl:variable name="cluster" select="/DFUQueryResponse/Prefix"/>
-    <xsl:variable name="clustername" select="/DFUQueryResponse/ClusterName"/>
+    <xsl:variable name="nodegroup" select="/DFUQueryResponse/NodeGroup"/>
     
     <xsl:variable name="logicalname" select="/DFUQueryResponse/LogicalName"/>
     <xsl:variable name="descriptionfilter" select="/DFUQueryResponse/Description"/>
@@ -64,7 +64,7 @@
           <script language="JavaScript1.2" id="menuhandlers">
                     var owner = '<xsl:value-of select="$owner"/>';;
                     var cluster = '<xsl:value-of select="$cluster"/>';;
-                    var clusterName = '<xsl:value-of select="$clustername"/>';;
+                    var nodeGroup = '<xsl:value-of select="$nodegroup"/>';;
                     var logicalName = '<xsl:value-of select="$logicalname"/>';;
                     var descriptionFilter = '<xsl:value-of select="$descriptionfilter"/>';;
                     var startDate = '<xsl:value-of select="$startdate"/>';;
@@ -312,11 +312,11 @@
                                     }
                                     if (type != 3)
                                     {
-                                        if (clusterName)
+                                        if (nodeGroup)
                                         {
                                             if (numParam > 0)
                                                 url += '&';
-                                            url += 'ClusterName=' + clusterName;
+                                            url += 'NodeGroup=' + nodeGroup;
                                             numParam++;
                                         }
                                     }
@@ -324,7 +324,7 @@
                                     {
                                         if (numParam > 0)
                                             url += '&';
-                                        url += 'ClusterName=' + value;
+                                        url += 'NodeGroup=' + value;
                                         numParam++;
                                     }
                                     document.location.href=url;
@@ -570,14 +570,14 @@
                        </xsl:otherwise>
                    </xsl:choose>
                    <xsl:choose>
-                       <xsl:when test="$sortby='Cluster' and $descending &lt; 1">
-                          <th align="center" style="cursor:pointer" onmouseover="bgColor='#FFFFFF'" onmouseout="bgColor='#CCCCCC'" onclick="headerClicked('Cluster', 1)">Cluster<img src="/esp/files/img/upsimple.png" width="10" height="10"></img></th>
+                       <xsl:when test="$sortby='NodeGroup' and $descending &lt; 1">
+                          <th align="center" style="cursor:pointer" onmouseover="bgColor='#FFFFFF'" onmouseout="bgColor='#CCCCCC'" onclick="headerClicked('NodeGroup', 1)">NodeGroup<img src="/esp/files/img/upsimple.png" width="10" height="10"></img></th>
                        </xsl:when>
-                       <xsl:when test="$sortby='Cluster'">
-                          <th align="center" style="cursor:pointer" onmouseover="bgColor='#FFFFFF'" onmouseout="bgColor='#CCCCCC'" onclick="headerClicked('Cluster', 0)">Cluster<img src="/esp/files/img/downsimple.png" width="10" height="10"></img></th>
+                       <xsl:when test="$sortby='NodeGroup'">
+                          <th align="center" style="cursor:pointer" onmouseover="bgColor='#FFFFFF'" onmouseout="bgColor='#CCCCCC'" onclick="headerClicked('NodeGroup', 0)">NodeGroup<img src="/esp/files/img/downsimple.png" width="10" height="10"></img></th>
                        </xsl:when>
                        <xsl:otherwise>
-                          <th align="center" style="cursor:pointer" onmouseover="bgColor='#FFFFFF'" onmouseout="bgColor='#CCCCCC'" onclick="headerClicked('Cluster', 0)">Cluster</th>
+                          <th align="center" style="cursor:pointer" onmouseover="bgColor='#FFFFFF'" onmouseout="bgColor='#CCCCCC'" onclick="headerClicked('NodeGroup', 0)">NodeGroup</th>
                        </xsl:otherwise>
                    </xsl:choose>
                    <xsl:choose>
@@ -647,15 +647,15 @@
             <xsl:variable name="info_query">
                 <xsl:value-of select="Name"/>
                 <xsl:choose>
-                    <xsl:when test="string-length(ClusterName)">&amp;Cluster=<xsl:value-of select="ClusterName"/></xsl:when>
+                    <xsl:when test="string-length(NodeGroup)">&amp;NodeGroup=<xsl:value-of select="NodeGroup"/></xsl:when>
                 </xsl:choose>
             </xsl:variable>
       <td>
         <xsl:if test="FromRoxieCluster=1">
-          <input type="hidden" id="{Name}@{ClusterName}"/>
+          <input type="hidden" id="{Name}@{NodeGroup}"/>
         </xsl:if>
-        <input type="checkbox" name="LogicalFiles_i{position()}" value="{Name}@{ClusterName}" onclick="return clicked(this, event)"/>
-          <xsl:variable name="popup">return DFUFilePopup('<xsl:value-of select="$info_query"/>', '<xsl:value-of select="Name"/>', '<xsl:value-of select="ClusterName"/>', '<xsl:value-of select="Replicate"/>', '<xsl:value-of select="FromRoxieCluster"/>', '<xsl:value-of select="BrowseData"/>', '<xsl:value-of select="position()"/>')</xsl:variable>
+        <input type="checkbox" name="LogicalFiles_i{position()}" value="{Name}@{NodeGroup}" onclick="return clicked(this, event)"/>
+          <xsl:variable name="popup">return DFUFilePopup('<xsl:value-of select="$info_query"/>', '<xsl:value-of select="Name"/>', '<xsl:value-of select="NodeGroup"/>', '<xsl:value-of select="Replicate"/>', '<xsl:value-of select="FromRoxieCluster"/>', '<xsl:value-of select="BrowseData"/>', '<xsl:value-of select="position()"/>')</xsl:variable>
           <xsl:variable name="oncontextmenu">
             <xsl:value-of select="$popup"/>
           </xsl:variable>
@@ -731,13 +731,13 @@
             </td>
             <td>
                 <xsl:choose>
-                    <xsl:when test="string-length(ClusterName) and not(string-length($clustername))">
-                        <a href="javascript:doQuery(3, '{ClusterName}')">
-                            <xsl:value-of select="ClusterName"/>
+                    <xsl:when test="string-length(NodeGroup) and not(string-length($nodegroup))">
+                        <a href="javascript:doQuery(3, '{NodeGroup}')">
+                            <xsl:value-of select="NodeGroup"/>
                         </a>
                     </xsl:when>
                     <xsl:otherwise>
-                        <xsl:value-of select="ClusterName"/>
+                        <xsl:value-of select="NodeGroup"/>
                     </xsl:otherwise>
                 </xsl:choose>
             </td>

+ 7 - 4
esp/scm/ws_dfu.ecm

@@ -33,7 +33,8 @@ ESPStruct SpaceItem
 ESPStruct DFULogicalFile
 {
     string Prefix;      
-    string ClusterName; 
+    [depr_ver("1.26")] string ClusterName;
+    [min_ver("1.26")] string NodeGroup;
     string Directory;
     string Description;
     string Parts;
@@ -135,7 +136,8 @@ ESPStruct DFUSpaceItem
 ESPrequest [nil_remove] DFUQueryRequest
 {
     string Prefix;
-    string ClusterName;
+    [depr_ver("1.26")] string ClusterName;
+    [min_ver("1.26")] string NodeGroup;
     string LogicalName;
     string Description;
     string Owner;
@@ -166,7 +168,8 @@ DFUQueryResponse
     ESParray<ESPstruct DFULogicalFile> DFULogicalFiles;
 
     string Prefix;
-    string ClusterName;
+    [depr_ver("1.26")] string ClusterName;
+    [min_ver("1.26")] string NodeGroup;
     string LogicalName;
     string Description;
     string Owner;
@@ -638,7 +641,7 @@ ESPresponse [exceptions_inline, nil_remove, http_encode(0)] DFUSearchDataRespons
 
 //  ===========================================================================
 ESPservice [
-    version("1.25"), default_client_version("1.25"),
+    version("1.26"), default_client_version("1.26"),
     noforms, 
     exceptions_inline("./smc_xslt/exceptions.xslt")] WsDfu
 {

+ 77 - 94
esp/services/ws_dfu/ws_dfuService.cpp

@@ -2044,22 +2044,22 @@ void CWsDfuEx::getLogicalFileAndDirectory(IEspContext &context, IUserDescriptor*
                     pref.append(logicalName);
 
                 const char* owner=attr.queryProp("@owner");
-#if 0
-                char* clusterName=(char*)attr.queryProp("@group");   
-#else //Handling for multiple clusters
-                StringArray clusters;
-                if (getFileGroups(&attr,clusters)==0) 
+                StringArray groups;
+                if (getFileGroups(&attr,groups)==0)
                 {
-                    clusters.append("");
+                    groups.append("");
                 }
-#endif
-                ForEachItemIn(i, clusters)
+
+                ForEachItemIn(i, groups)
                 {
-                    const char* clusterName = clusters.item(i);
-                Owned<IEspDFULogicalFile> File = createDFULogicalFile("","");
+                    const char* groupName = groups.item(i);
+                    Owned<IEspDFULogicalFile> File = createDFULogicalFile("","");
 
                     File->setPrefix(pref);
-                    File->setClusterName(clusterName);
+                    if (version < 1.26)
+                        File->setClusterName(groupName);
+                    else
+                        File->setNodeGroup(groupName);
                     File->setName(logicalName);
                     File->setOwner(owner);
                     File->setReplicate(true);
@@ -2067,7 +2067,7 @@ void CWsDfuEx::getLogicalFileAndDirectory(IEspContext &context, IUserDescriptor*
                     ForEachItemIn(j, roxieClusterNames)
                     {
                         const char* roxieClusterName = roxieClusterNames.item(j);
-                        if (roxieClusterName && clusterName && !stricmp(roxieClusterName, clusterName))
+                        if (roxieClusterName && groupName && strieq(roxieClusterName, groupName))
                         {
                             File->setFromRoxieCluster(true);
                             break;
@@ -2292,9 +2292,9 @@ __int64 CWsDfuEx::findPositionByName(const char *name, bool descend, IArrayOf<IE
     return addToPos;
 }
 
-__int64 CWsDfuEx::findPositionByCluster(const char *cluster, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles)
+__int64 CWsDfuEx::findPositionByNodeGroup(double version, const char *node, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles)
 {
-    if (!cluster || (strlen(cluster) < 1))
+    if (!node || !*node)
     {
         if (descend)
             return -1;
@@ -2306,16 +2306,20 @@ __int64 CWsDfuEx::findPositionByCluster(const char *cluster, bool descend, IArra
     ForEachItemIn(i, LogicalFiles)
     {
         IEspDFULogicalFile& File = LogicalFiles.item(i);
-        const char *ClusterName = File.getClusterName();
-        if (!ClusterName)
+        const char *nodeGroup = NULL;
+        if (version < 1.26)
+            nodeGroup = File.getClusterName();
+        else
+            nodeGroup = File.getNodeGroup();
+        if (!nodeGroup)
             continue;
 
-        if (descend && strcmp(cluster, ClusterName)>0)
+        if (descend && strcmp(node, nodeGroup)>0)
         {
             addToPos = i;
             break;
         }
-        if (!descend && strcmp(cluster, ClusterName)<0)
+        if (!descend && strcmp(node, nodeGroup)<0)
         {
             addToPos = i;
             break;
@@ -2595,30 +2599,10 @@ void CWsDfuEx::getAPageOfSortedLogicalFile(IEspContext &context, IUserDescriptor
         roxieClusterNames.append(sName.str());
     }
 
-    StringArray clustersReq;
-    const char* clustersReq0 = req.getClusterName();
-    if (clustersReq0 && *clustersReq0)
-    {
-        char* pStr = (char*) clustersReq0;
-        while (pStr)
-        {
-            char clusterName[256];
-            char* ppStr = strchr(pStr, ',');
-            if (!ppStr)
-            {
-                strcpy(clusterName, pStr);
-                pStr = NULL;
-            }
-            else
-            {
-                strncpy(clusterName, pStr, ppStr - pStr );
-                clusterName[ppStr - pStr] = 0;
-                pStr = ppStr+1;
-            }
-
-            clustersReq.append(clusterName);
-        }
-    }
+    StringArray nodeGroupsReq;
+    const char* nodeGroupsReqString = req.getNodeGroup();
+    if (nodeGroupsReqString && *nodeGroupsReqString)
+        nodeGroupsReq.appendListUniq(nodeGroupsReqString, ",");
 
     StringBuffer size;
     __int64 totalFiles = 0;
@@ -2646,49 +2630,33 @@ void CWsDfuEx::getAPageOfSortedLogicalFile(IEspContext &context, IUserDescriptor
                 if (!owner || stricmp(owner, req.getOwner()))
                     continue;
             }
-            StringArray clusters;
-            StringArray clusters1;
-            if (getFileGroups(&attr,clusters1)==0)
+            StringArray nodeGroups;
+            StringArray fileNodeGroups;
+            if (getFileGroups(&attr,fileNodeGroups)==0)
             {
-                if (clustersReq.length() < 1)
-                {
-                    clusters.append("");
-                }
+                if (!nodeGroupsReq.length())
+                    nodeGroups.append("");
             }
-            else
+            else if (nodeGroupsReq.length() > 0) // check specified cluster name in list
             {
-                // check specified cluster name in list
-                if (clustersReq.length() > 0)
-                {
-                    ForEachItemIn(ii,clustersReq)
-                    {
-                        StringBuffer clusterFound;
-
-                        const char * cluster0 = clustersReq.item(ii);
-                        ForEachItemIn(i,clusters1)
-                        {
-                            if (!stricmp(clusters1.item(i), cluster0))
-                            {
-                                clusterFound.append(cluster0);
-                                break;
-                            }
-                        }
-                        if (clusterFound.length() > 0)
-                            clusters.append(clusterFound);
-                    }
-                }
-                else
+                ForEachItemIn(ii,nodeGroupsReq)
                 {
-                    if (clusters1.length() > 0)
+                    const char* nodeGroupReq = nodeGroupsReq.item(ii);
+                    ForEachItemIn(i,fileNodeGroups)
                     {
-                        ForEachItemIn(i,clusters1)
+                        if (strieq(fileNodeGroups.item(i), nodeGroupReq))
                         {
-                            const char * cluster0 = clusters1.item(i);
-                            clusters.append(cluster0);
+                            nodeGroups.append(nodeGroupReq);
+                            break;
                         }
                     }
                 }
             }
+            else if (fileNodeGroups.length())
+            {
+                ForEachItemIn(i,fileNodeGroups)
+                    nodeGroups.append(fileNodeGroups.item(i));
+            }
 
             const char* desc = attr.queryProp("@description");
             if(req.getDescription() && *req.getDescription())
@@ -2749,9 +2717,9 @@ void CWsDfuEx::getAPageOfSortedLogicalFile(IEspContext &context, IUserDescriptor
                 }
             }
 
-            ForEachItemIn(i, clusters)
+            ForEachItemIn(i, nodeGroups)
             {
-                const char* clusterName = clusters.item(i);
+                const char* nodeGroup = nodeGroups.item(i);
                 __int64 addToPos = -1; //Add to tail
                 if (stricmp(sortBy, "FileSize")==0)
                 {
@@ -2765,9 +2733,9 @@ void CWsDfuEx::getAPageOfSortedLogicalFile(IEspContext &context, IUserDescriptor
                 {
                     addToPos = findPositionByOwner(owner, descending, LogicalFileList);
                 }
-                else if (stricmp(sortBy, "Cluster")==0)
+                else if (stricmp(sortBy, "NodeGroup")==0)
                 {
-                    addToPos = findPositionByCluster(clusterName, descending, LogicalFileList);
+                    addToPos = findPositionByNodeGroup(version, nodeGroup, descending, LogicalFileList);
                 }
                 else if (stricmp(sortBy, "Records")==0)
                 {
@@ -2793,7 +2761,10 @@ void CWsDfuEx::getAPageOfSortedLogicalFile(IEspContext &context, IUserDescriptor
                 Owned<IEspDFULogicalFile> File = createDFULogicalFile("","");
 
                 File->setPrefix(pref);
-                File->setClusterName(clusterName);
+                if (version < 1.26)
+                    File->setClusterName(nodeGroup);
+                else
+                    File->setNodeGroup(nodeGroup);
                 File->setName(logicalName);
                 File->setOwner(owner);
                 File->setDescription(description);
@@ -2803,7 +2774,7 @@ void CWsDfuEx::getAPageOfSortedLogicalFile(IEspContext &context, IUserDescriptor
                 ForEachItemIn(j, roxieClusterNames)
                 {
                     const char* roxieClusterName = roxieClusterNames.item(j);
-                    if (roxieClusterName && clusterName && !stricmp(roxieClusterName, clusterName))
+                    if (roxieClusterName && nodeGroup && strieq(roxieClusterName, nodeGroup))
                     {
                         File->setFromRoxieCluster(true);
                         break;
@@ -2911,10 +2882,13 @@ void CWsDfuEx::getAPageOfSortedLogicalFile(IEspContext &context, IUserDescriptor
     }
 
     StringBuffer basicQuery;
-    if (req.getClusterName() && *req.getClusterName())
+    if (req.getNodeGroup() && *req.getNodeGroup())
     {
-        resp.setClusterName(req.getClusterName());
-        addToQueryString(basicQuery, "ClusterName", req.getClusterName());
+        if (version < 1.26)
+            resp.setClusterName(req.getNodeGroup());
+        else
+            resp.setNodeGroup(req.getNodeGroup());
+        addToQueryString(basicQuery, "NodeGroup", req.getNodeGroup());
     }
     if (req.getOwner() && *req.getOwner())
     {
@@ -3103,7 +3077,7 @@ void CWsDfuEx::setDFUQueryFilters(IEspDFUQueryRequest& req, StringBuffer& filter
     setFileTypeFilter(req.getFileType(), filterBuf);
     appendDFUQueryFilter(getDFUQFilterFieldName(DFUQFFdescription), DFUQFTwildcardMatch, req.getDescription(), filterBuf);
     appendDFUQueryFilter(getDFUQFilterFieldName(DFUQFFattrowner), DFUQFTwildcardMatch, req.getOwner(), filterBuf);
-    appendDFUQueryFilter(getDFUQFilterFieldName(DFUQFFgroup), DFUQFTcontainString, req.getClusterName(), ",", filterBuf);
+    appendDFUQueryFilter(getDFUQFilterFieldName(DFUQFFgroup), DFUQFTcontainString, req.getNodeGroup(), ",", filterBuf);
 
     __int64 sizeFrom = req.getFileSizeFrom();
     __int64 sizeTo = req.getFileSizeTo();
@@ -3164,8 +3138,8 @@ void CWsDfuEx::setDFUQuerySortOrder(IEspDFUQueryRequest& req, StringBuffer& sort
         sortOrder[0] = (DFUQResultField) (DFUQRFrecordcount | DFUQRFnumeric);
     else if (strieq(sortByPtr, "Owner"))
         sortOrder[0] = DFUQRFowner;
-    else if (strieq(sortByPtr, "Cluster"))
-        sortOrder[0] = DFUQRFcluster;
+    else if (strieq(sortByPtr, "NodeGroup"))
+        sortOrder[0] = DFUQRFnodegroup;
     else if (strieq(sortByPtr, "Modified"))
         sortOrder[0] = DFUQRFtimemodified;
     else if (strieq(sortByPtr, "Description"))
@@ -3224,9 +3198,14 @@ bool CWsDfuEx::addToLogicalFileList(IPropertyTree& file, double version, IArrayO
         lFile->setDescription(getShortDescription(file.queryProp(getDFUQResultFieldName(DFUQRFdescription)), buf.clear()));
         lFile->setTotalsize((buf.clear()<<comma(file.getPropInt64(getDFUQResultFieldName(DFUQRForigsize),-1))).str());
 
-        const char* clusterName = file.queryProp(getDFUQResultFieldName(DFUQRFcluster));
-        if (clusterName && *clusterName)
-            lFile->setClusterName(clusterName);
+        const char* nodeGroup = file.queryProp(getDFUQResultFieldName(DFUQRFnodegroup));
+        if (nodeGroup && *nodeGroup)
+        {
+            if (version < 1.26)
+                lFile->setClusterName(nodeGroup);
+            else
+                lFile->setNodeGroup(nodeGroup);
+        }
 
         int numSubFiles = file.hasProp(getDFUQResultFieldName(DFUQRFnumsubfiles));
         if(numSubFiles)
@@ -3287,6 +3266,7 @@ void CWsDfuEx::setDFUQueryResponse(IEspContext &context, unsigned totalFiles, St
                                    IEspDFUQueryRequest& req, IEspDFUQueryResponse& resp)
 {
     //for legacy
+    double version = context.getClientVersion();
     unsigned pageEnd = pageStart + pageSize;
     if (pageEnd > totalFiles)
         pageEnd = totalFiles;
@@ -3305,10 +3285,13 @@ void CWsDfuEx::setDFUQueryResponse(IEspContext &context, unsigned totalFiles, St
     }
 
     StringBuffer queryReq;
-    if (req.getClusterName() && *req.getClusterName())
+    if (req.getNodeGroup() && *req.getNodeGroup())
     {
-        resp.setClusterName(req.getClusterName());
-        addToQueryString(queryReq, "ClusterName", req.getClusterName());
+        if (version < 1.26)
+            resp.setClusterName(req.getNodeGroup());
+        else
+            resp.setNodeGroup(req.getNodeGroup());
+        addToQueryString(queryReq, "NodeGroup", req.getNodeGroup());
     }
     if (req.getOwner() && *req.getOwner())
     {
@@ -3403,7 +3386,7 @@ bool CWsDfuEx::doLogicalFileSearch(IEspContext &context, IUserDescriptor* udesc,
     unsigned short localFilterCount = 0;
     DFUQResultField localFilters[8];
     MemoryBuffer localFilterBuf;
-    addDFUQueryFilter(localFilters, localFilterCount, localFilterBuf, req.getClusterName(), DFUQRFcluster);
+    addDFUQueryFilter(localFilters, localFilterCount, localFilterBuf, req.getNodeGroup(), DFUQRFnodegroup);
     localFilters[localFilterCount] = DFUQRFterm;
 
     StringBuffer sortBy;

+ 1 - 1
esp/services/ws_dfu/ws_dfuService.hpp

@@ -100,7 +100,7 @@ private:
     __int64 findPositionByRecords(const __int64 records, bool decsend, IArrayOf<IEspDFULogicalFile>& LogicalFiles);
     __int64 findPositionByName(const char *name, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles);
     __int64 findPositionByOwner(const char *owner, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles);
-    __int64 findPositionByCluster(const char *Cluster, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles);
+    __int64 findPositionByNodeGroup(double version, const char *nodeGroup, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles);
     __int64 findPositionByDate(const char *datetime, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles);
     __int64 findPositionByDescription(const char *description, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles);
     bool checkDescription(const char *description, const char *descriptionFilter);

+ 15 - 1
esp/services/ws_fs/ws_fsBinding.cpp

@@ -303,9 +303,23 @@ IPropertyTree* CFileSpraySoapBindingEx::createPTreeForXslt(const char* method, c
             }
         }
 
+        //For Spray files on Thor Cluster, fetch all the group names for all the thor instances (and dedup them)
+        BoolHash uniqueThorClusterGroupNames;
         it.setown(pEnvSoftware->getElements("ThorCluster"));
         ForEach(*it)
-            pSoftware->addPropTree("ThorCluster", &it->get());
+        {
+            StringBuffer thorClusterGroupName;
+            IPropertyTree& cluster = it->query();
+            getClusterGroupName(cluster, thorClusterGroupName);
+            if (!thorClusterGroupName.length())
+                continue;
+            if (uniqueThorClusterGroupNames.getValue(thorClusterGroupName.str()))
+                continue;
+
+            uniqueThorClusterGroupNames.setValue(thorClusterGroupName.str(), true);
+            IPropertyTree* newClusterTree = pSoftware->addPropTree("ThorCluster", &it->get());
+            newClusterTree->setProp("@name", thorClusterGroupName.str()); //set group name into @name for spray target
+        }
 
         it.setown(pEnvSoftware->getElements("EclAgentProcess"));
         ForEach(*it)

+ 48 - 34
esp/services/ws_fs/ws_fsService.cpp

@@ -600,8 +600,12 @@ void setRoxieClusterPartDiskMapping(const char *clusterName, const char *default
     wuOptions->setReplicate(replicate);
 }
 
-void getClusterFromLFN(const char* lfn, StringBuffer& cluster, const char* username, const char* passwd)
+void getNodeGroupFromLFN(const char* lfn, StringBuffer& nodeGroup, const char* username, const char* passwd)
 {
+    Owned<IRemoteConnection> conn = querySDS().connect("Environment", myProcessSession(), RTM_LOCK_READ, SDS_LOCK_TIMEOUT);
+    if (!conn)
+        return;
+
     Owned<IUserDescriptor> udesc;
     if(username != NULL && *username != '\0')
     {
@@ -609,8 +613,21 @@ void getClusterFromLFN(const char* lfn, StringBuffer& cluster, const char* usern
         udesc->set(username, passwd);
     }
 
+    StringBuffer clusterName;
     LogicFileWrapper lfw;
-    lfw.FindClusterName(lfn, cluster, udesc);
+    lfw.FindClusterName(lfn, clusterName, udesc);
+
+    Owned<IPropertyTreeIterator> it = conn->queryRoot()->getElements("Software/ThorCluster");
+    ForEach(*it)
+    {
+        IPropertyTree& cluster = it->query();
+        const char* name = cluster.queryProp("@name");
+        if (name && strieq(name, clusterName.str()))
+        {
+            getClusterGroupName(cluster, nodeGroup);
+            break;
+        }
+    }
 }
 
 StringBuffer& constructFileMask(const char* filename, StringBuffer& filemask)
@@ -1825,9 +1842,9 @@ bool CFileSprayEx::onSprayFixed(IEspContext &context, IEspSprayFixed &req, IEspS
 
         StringBuffer destFolder, destTitle, defaultFolder, defaultReplicateFolder;
 
-        const char* destCluster = req.getDestGroup();
-        if(destCluster == NULL || *destCluster == '\0')
-            throw MakeStringException(ECLWATCH_INVALID_INPUT, "Destination cluster/group not specified.");
+        const char* destNodeGroup = req.getDestGroup();
+        if(destNodeGroup == NULL || *destNodeGroup == '\0')
+            throw MakeStringException(ECLWATCH_INVALID_INPUT, "Destination node group not specified.");
 
         MemoryBuffer& srcxml = (MemoryBuffer&)req.getSrcxml();
         const char* srcip = req.getSourceIP();
@@ -1849,19 +1866,19 @@ bool CFileSprayEx::onSprayFixed(IEspContext &context, IEspSprayFixed &req, IEspS
         destname = lfn.get();
 
         StringBuffer gName, ipAddr;
-        const char *pTr = strchr(destCluster, ' ');
+        const char *pTr = strchr(destNodeGroup, ' ');
         if (pTr)
         {
-            gName.append(pTr - destCluster, destCluster);
+            gName.append(pTr - destNodeGroup, destNodeGroup);
             ipAddr.append(pTr+1);
         }
         else
-            gName.append(destCluster);
+            gName.append(destNodeGroup);
 
         if (ipAddr.length() > 0)
             ParseLogicalPath(destname, ipAddr.str(), destFolder, destTitle, defaultFolder, defaultReplicateFolder);
         else
-            ParseLogicalPath(destname, destCluster, destFolder, destTitle, defaultFolder, defaultReplicateFolder);
+            ParseLogicalPath(destname, destNodeGroup, destFolder, destTitle, defaultFolder, defaultReplicateFolder);
 
         Owned<IDFUWorkUnitFactory> factory = getDFUWorkUnitFactory();
         Owned<IDFUWorkUnit> wu = factory->createWorkUnit();
@@ -1996,19 +2013,19 @@ bool CFileSprayEx::onSprayVariable(IEspContext &context, IEspSprayVariable &req,
 
         StringBuffer destFolder, destTitle, defaultFolder, defaultReplicateFolder;
 
-        const char* destCluster = req.getDestGroup();
-        if(destCluster == NULL || *destCluster == '\0')
-            throw MakeStringException(ECLWATCH_INVALID_INPUT, "Destination cluster/group not specified.");
+        const char* destNodeGroup = req.getDestGroup();
+        if(destNodeGroup == NULL || *destNodeGroup == '\0')
+            throw MakeStringException(ECLWATCH_INVALID_INPUT, "Destination node group not specified.");
 
         StringBuffer gName, ipAddr;
-        const char *pTr = strchr(destCluster, ' ');
+        const char *pTr = strchr(destNodeGroup, ' ');
         if (pTr)
         {
-            gName.append(pTr - destCluster, destCluster);
+            gName.append(pTr - destNodeGroup, destNodeGroup);
             ipAddr.append(pTr+1);
         }
         else
-            gName.append(destCluster);
+            gName.append(destNodeGroup);
 
         MemoryBuffer& srcxml = (MemoryBuffer&)req.getSrcxml();
         const char* srcip = req.getSourceIP();
@@ -2032,7 +2049,7 @@ bool CFileSprayEx::onSprayVariable(IEspContext &context, IEspSprayVariable &req,
         if (ipAddr.length() > 0)
             ParseLogicalPath(destname, ipAddr.str(), destFolder, destTitle, defaultFolder, defaultReplicateFolder);
         else
-            ParseLogicalPath(destname, destCluster, destFolder, destTitle, defaultFolder, defaultReplicateFolder);
+            ParseLogicalPath(destname, destNodeGroup, destFolder, destTitle, defaultFolder, defaultReplicateFolder);
 
         Owned<IDFUWorkUnitFactory> factory = getDFUWorkUnitFactory();
         Owned<IDFUWorkUnit> wu = factory->createWorkUnit();
@@ -2332,22 +2349,19 @@ bool CFileSprayEx::onCopy(IEspContext &context, IEspCopy &req, IEspCopyResponse
             throw MakeStringException(ECLWATCH_INVALID_INPUT, "Destination logical file not specified.");
 
         StringBuffer destFolder, destTitle, defaultFolder, defaultReplicateFolder;
-        StringBuffer srcCluster, destCluster, destClusterName;
+        StringBuffer srcNodeGroup, destNodeGroup;
         bool bRoxie = false;
-        const char* destCluster0 = req.getDestGroup();
-        if(destCluster0 == NULL || *destCluster0 == '\0')
+        const char* destNodeGroupReq = req.getDestGroup();
+        if(!destNodeGroupReq || !*destNodeGroupReq)
         {
-            getClusterFromLFN(srcname, srcCluster, context.queryUserId(), context.queryPassword());
-            DBGLOG("Destination cluster/group not specified, using source cluster %s", srcCluster.str());
-            destCluster = srcCluster.str();
-            destClusterName = srcCluster.str();
+            getNodeGroupFromLFN(srcname, destNodeGroup, context.queryUserId(), context.queryPassword());
+            DBGLOG("Destination node group not specified, using source node group %s", destNodeGroup.str());
         }
         else
         {
-            destCluster = destCluster0;
-            destClusterName = destCluster0;
-            const char* destClusterRoxie = req.getDestGroupRoxie();
-            if (destClusterRoxie && !stricmp(destClusterRoxie, "Yes"))
+            destNodeGroup = destNodeGroupReq;
+            const char* destRoxie = req.getDestGroupRoxie();
+            if (destRoxie && !stricmp(destRoxie, "Yes"))
             {
                 bRoxie = true;
             }
@@ -2361,7 +2375,7 @@ bool CFileSprayEx::onCopy(IEspContext &context, IEspCopy &req, IEspCopyResponse
             dstname = lfn.get();
         }
 
-        ParseLogicalPath(dstname, destCluster.str(), destFolder, destTitle, defaultFolder, defaultReplicateFolder);
+        ParseLogicalPath(dstname, destNodeGroup.str(), destFolder, destTitle, defaultFolder, defaultReplicateFolder);
 
         StringBuffer fileMask; 
         constructFileMask(destTitle.str(), fileMask);
@@ -2400,8 +2414,8 @@ bool CFileSprayEx::onCopy(IEspContext &context, IEspCopy &req, IEspCopyResponse
         StringBuffer user, passwd;
         wu->setUser(context.getUserID(user).str());
         wu->setPassword(context.getPassword(passwd).str());
-        if(destCluster.length() > 0)
-            wu->setClusterName(destCluster.str());
+        if(destNodeGroup.length() > 0)
+            wu->setClusterName(destNodeGroup.str());
         if (supercopy)
             wu->setCommand(DFUcmd_supercopy);
         else
@@ -2429,7 +2443,7 @@ bool CFileSprayEx::onCopy(IEspContext &context, IEspCopy &req, IEspCopyResponse
 
         if (bRoxie)
         {
-            setRoxieClusterPartDiskMapping(destCluster.str(), defaultFolder.str(), defaultReplicateFolder.str(), supercopy, wuFSpecDest, wuOptions);
+            setRoxieClusterPartDiskMapping(destNodeGroup.str(), defaultFolder.str(), defaultReplicateFolder.str(), supercopy, wuFSpecDest, wuOptions);
             wuFSpecDest->setWrap(true);                             // roxie always wraps
             if(req.getCompress())
                 wuFSpecDest->setCompressed(true);
@@ -2445,7 +2459,7 @@ bool CFileSprayEx::onCopy(IEspContext &context, IEspCopy &req, IEspCopyResponse
             if (destDiffKeyName&&*destDiffKeyName)
                 wuFSpecDest->setDiffKey(destDiffKeyName);
             wuFSpecDest->setDirectory(destFolder.str());
-            wuFSpecDest->setGroupName(destCluster.str());
+            wuFSpecDest->setGroupName(destNodeGroup.str());
             wuFSpecDest->setWrap(req.getWrap());
             const char * encryptkey = req.getEncrypt();
             if(req.getCompress()||(encryptkey&&*encryptkey))
@@ -2473,10 +2487,10 @@ bool CFileSprayEx::onCopy(IEspContext &context, IEspCopy &req, IEspCopyResponse
                 wuOptions->setIfNewer(true);
 
             ClusterPartDiskMapSpec mspec;
-            wuFSpecDest->getClusterPartDiskMapSpec(destCluster.str(), mspec);
+            wuFSpecDest->getClusterPartDiskMapSpec(destNodeGroup.str(), mspec);
             mspec.setDefaultBaseDir(defaultFolder.str());
             mspec.setDefaultReplicateDir(defaultReplicateFolder.str());
-            wuFSpecDest->setClusterPartDiskMapSpec(destCluster.str(), mspec);
+            wuFSpecDest->setClusterPartDiskMapSpec(destNodeGroup.str(), mspec);
         }
 
         resp.setResult(wu->queryId());