Bladeren bron

Merge branch 'candidate-6.0.4'

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 9 jaren geleden
bovenliggende
commit
3c9b773820

+ 60 - 3
common/thorhelper/thorxmlwrite.hpp

@@ -42,10 +42,28 @@ interface IXmlWriterExt : extends IXmlWriter
     virtual IXmlWriterExt & clear() = 0;
     virtual size32_t length() const = 0;
     virtual const char *str() const = 0;
-    virtual void rewindTo(unsigned int prevlen) = 0;
+    virtual IInterface *saveLocation() const = 0;
+    virtual void rewindTo(IInterface *location) = 0;
     virtual void outputNumericString(const char *field, const char *fieldname) = 0;
 };
 
+class thorhelper_decl CommonXmlPosition : public CInterface, implements IInterface
+{
+public:
+    IMPLEMENT_IINTERFACE;
+
+    CommonXmlPosition(size32_t _pos, unsigned _indent, unsigned _nestLimit, bool _tagClosed, bool _needDelimiter) :
+        pos(_pos), indent(_indent), nestLimit(_nestLimit), tagClosed(_tagClosed), needDelimiter(_needDelimiter)
+    {}
+
+public:
+    size32_t pos = 0;
+    unsigned indent = 0;
+    unsigned nestLimit = 0;
+    bool tagClosed = false;
+    bool needDelimiter = false;
+};
+
 class thorhelper_decl CommonXmlWriter : public CInterface, implements IXmlWriterExt
 {
 public:
@@ -82,12 +100,28 @@ public:
     virtual IXmlWriterExt & clear();
     virtual unsigned length() const                                 { return out.length(); }
     virtual const char * str() const                                { return out.str(); }
-    virtual void rewindTo(unsigned int prevlen)
+    virtual IInterface *saveLocation() const
     {
         if (flusher)
             throwUnexpected();
 
-        if (prevlen < out.length()) out.setLength(prevlen);
+        return new CommonXmlPosition(length(), indent, nestLimit, tagClosed, false);
+    }
+    virtual void rewindTo(IInterface *saved)
+    {
+        if (flusher)
+            throwUnexpected();
+
+        CommonXmlPosition *position = dynamic_cast<CommonXmlPosition *>(saved);
+        if (!position)
+            return;
+        if (position->pos < out.length())
+        {
+            out.setLength(position->pos);
+            tagClosed = position->tagClosed;
+            indent = position->indent;
+            nestLimit = position->nestLimit;
+        }
     }
 
     virtual void outputNumericString(const char *field, const char *fieldname)
@@ -156,6 +190,29 @@ public:
     virtual unsigned length() const                                 { return out.length(); }
     virtual const char * str() const                                { return out.str(); }
     virtual void rewindTo(unsigned int prevlen)                     { if (prevlen < out.length()) out.setLength(prevlen); }
+    virtual IInterface *saveLocation() const
+    {
+        if (flusher)
+            throwUnexpected();
+
+        return new CommonXmlPosition(length(), indent, nestLimit, false, needDelimiter);
+    }
+    virtual void rewindTo(IInterface *saved)
+    {
+        if (flusher)
+            throwUnexpected();
+
+        CommonXmlPosition *position = dynamic_cast<CommonXmlPosition *>(saved);
+        if (!position)
+            return;
+        if (position->pos < out.length())
+        {
+            out.setLength(position->pos);
+            needDelimiter = position->needDelimiter;
+            indent = position->indent;
+            nestLimit = position->nestLimit;
+        }
+    }
 
     void outputBeginRoot(){out.append('{');}
     void outputEndRoot(){out.append('}');}

+ 1 - 1
dali/ft/filecopy.cpp

@@ -2661,7 +2661,7 @@ void FileSprayer::checkTargetPath(RemoteFilename & filename)
 
             Owned<IConstDropZoneInfo> targetDropZone = env->getDropZoneByAddressPath(netaddress.str(), ptargetFilePath);
             if (!targetDropZone)
-                    throwError1(DFTERR_NoMatchingDropzonePath, ptargetFilePath);
+                LOG(MCdebugInfo, unknownJob, "No matching drop zone path to target file path: '%s'", targetFilePath.str());
         }
     }
 }

+ 8 - 1
esp/eclwatch/ws_XSLT/dfu.xslt

@@ -706,7 +706,14 @@
               </xsl:choose>
             </td>
             <td>
-                    <xsl:value-of select="Description"/>
+                <xsl:choose>
+                    <xsl:when test="string-length(Description) > 12">
+                        <xsl:value-of select="substring(Description, 1, 12)"/>...
+                    </xsl:when>
+                    <xsl:otherwise>
+                        <xsl:value-of select="Description"/>
+                    </xsl:otherwise>
+                </xsl:choose>
             </td>
             <td>
                     <xsl:value-of select="Totalsize"/>

+ 11 - 10
esp/esdllib/esdl_transformer2.cpp

@@ -703,7 +703,7 @@ void Esdl2Array::process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const
         const char *tagname = queryOutputName(ctx);
         if (pt->hasChildren())
         {
-            int prevlen = ctx.writer->length();
+            Owned<IInterface> prevLocation = ctx.writer->saveLocation();
 
             ctx.writer->outputBeginNested(tagname, true);
             ctx.writer->outputBeginArray(item_tag.get());
@@ -724,7 +724,7 @@ void Esdl2Array::process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const
             {
                 ctx.writer->outputEndArray(item_tag.get());
                 ctx.writer->outputEndNested(tagname); //we need to close out the nested area first
-                ctx.writer->rewindTo(prevlen); //rewind
+                ctx.writer->rewindTo(prevLocation); //rewind
             }
             else
             {
@@ -773,7 +773,7 @@ void Esdl2Array::process(Esdl2TransformerContext &ctx, const char *out_name, Esd
     }
     else
     {
-        int prevlen = ctx.writer->length();
+        Owned<IInterface> prevLocation = ctx.writer->saveLocation();
         ctx.writer->outputBeginNested(xml_tag.get(), true);
         ctx.writer->outputBeginArray(item_tag.get());
         int curlen = ctx.writer->length();
@@ -801,7 +801,7 @@ void Esdl2Array::process(Esdl2TransformerContext &ctx, const char *out_name, Esd
         {
             ctx.writer->outputEndArray(item_tag.get());
             ctx.writer->outputEndNested(xml_tag.get()); // we need to close out this section first
-            ctx.writer->rewindTo(prevlen); //rewind
+            ctx.writer->rewindTo(prevLocation); //rewind
         }
         else
         {
@@ -878,7 +878,7 @@ void Esdl2Struct::process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const
 
     if (checkVersion(ctx))
     {
-        unsigned prevlen = ctx.writer->length();
+        Owned<IInterface> prevLocation = ctx.writer->saveLocation();
         if (out_name && *out_name) {
             if (!might_skip_root || !ctx.skip_root)
                 ctx.writer->outputBeginNested(out_name, true);
@@ -907,7 +907,7 @@ void Esdl2Struct::process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const
                 if (ctx.writer->length() == curlen) //nothing was added, empty content, remove open tag
                 {
                     ctx.writer->outputEndNested(out_name); //we need to close out current section first
-                    ctx.writer->rewindTo(prevlen); //rewind
+                    ctx.writer->rewindTo(prevLocation); //rewind
                 }
                 else
                     ctx.writer->outputEndNested(out_name);
@@ -924,8 +924,8 @@ void Esdl2Struct::process(Esdl2TransformerContext &ctx, const char *out_name, Es
         ctx.xppp->skipSubTree();
     else
     {
-        unsigned prevlen = ctx.writer->length();
-        unsigned curlen = prevlen;
+        Owned<IInterface> prevLocation = ctx.writer->saveLocation();
+        unsigned curlen = ctx.writer->length();
 
         if (out_name && *out_name)
         {
@@ -1007,6 +1007,7 @@ void Esdl2Struct::process(Esdl2TransformerContext &ctx, const char *out_name, Es
                             Esdl2Base& chd = *child;
 
                             unsigned len = ctx.writer->length();
+                            Owned<IInterface> location = ctx.writer->saveLocation();
                             local.dataForProcessed = false;
 
                             chd.process(ctx, NULL, &local);
@@ -1019,7 +1020,7 @@ void Esdl2Struct::process(Esdl2TransformerContext &ctx, const char *out_name, Es
                                 {
                                     ESDL_DBG("Taking out data for DataFor '%s' from out buffer", chd.queryDataFor()->queryName());
                                     local.setDataFor(chd.queryDataFor()->queryName(), ctx.writer->str()+len);
-                                    ctx.writer->rewindTo(len);
+                                    ctx.writer->rewindTo(location);
                                 }
                             }
 
@@ -1055,7 +1056,7 @@ void Esdl2Struct::process(Esdl2TransformerContext &ctx, const char *out_name, Es
                 if (ctx.writer->length() == curlen) //nothing was added, empty content, remove open tag
                 {
                     ctx.writer->outputEndNested(out_name); //we need to close out current section first
-                    ctx.writer->rewindTo(prevlen); //rewind
+                    ctx.writer->rewindTo(prevLocation); //rewind
                 }
                 else
                 {

+ 3 - 34
esp/services/ws_dfu/ws_dfuService.cpp

@@ -74,7 +74,6 @@ static const char* FEATURE_URL="DfuAccess";
 
 const unsigned NODE_GROUP_CACHE_DEFAULT_TIMEOUT = 30*60*1000; //30 minutes
 
-const int DESCRIPTION_DISPLAY_LENGTH = 12;
 const unsigned MAX_VIEWKEYFILE_ROWS = 1000;
 const unsigned MAX_KEY_ROWS = 20;
 
@@ -2815,22 +2814,6 @@ void CWsDfuEx::getAPageOfSortedLogicalFile(IEspContext &context, IUserDescriptor
             else if(recordSize)
                 records = size/recordSize;
 
-            char description[DESCRIPTION_DISPLAY_LENGTH + 1];
-            description[0] = 0;
-            if (desc && *desc)
-            {
-                if (strlen(desc) <= DESCRIPTION_DISPLAY_LENGTH) //Only 12 characters is required for display
-                {
-                    strcpy(description, desc);
-                }
-                else
-                {
-                    strncpy(description, desc, DESCRIPTION_DISPLAY_LENGTH - 3);
-                    description[DESCRIPTION_DISPLAY_LENGTH - 3] = 0;
-                    strcat(description, "...");
-                }
-            }
-
             ForEachItemIn(i, nodeGroups)
             {
                 const char* nodeGroup = nodeGroups.item(i);
@@ -2861,7 +2844,7 @@ void CWsDfuEx::getAPageOfSortedLogicalFile(IEspContext &context, IUserDescriptor
                 }
                 else if (stricmp(sortBy, "Description")==0)
                 {
-                    addToPos = findPositionByDescription(description, descending, LogicalFileList);
+                    addToPos = findPositionByDescription(desc, descending, LogicalFileList);
                 }
                 else
                 {
@@ -2881,7 +2864,7 @@ void CWsDfuEx::getAPageOfSortedLogicalFile(IEspContext &context, IUserDescriptor
                     File->setNodeGroup(nodeGroup);
                 File->setName(logicalName);
                 File->setOwner(owner);
-                File->setDescription(description);
+                File->setDescription(desc);
                 File->setModified(modf.str());
                 File->setReplicate(true);
 
@@ -3292,20 +3275,6 @@ const char* CWsDfuEx::getPrefixFromLogicalName(const char* logicalName, StringBu
     return prefix.str();
 }
 
-const char* CWsDfuEx::getShortDescription(const char* description, StringBuffer& shortDesc)
-{
-    if (!description || !*description)
-        return NULL;
-
-    shortDesc.set(description);
-    if (shortDesc.length() > DESCRIPTION_DISPLAY_LENGTH) //Only DESCRIPTION_DISPLAY_LENGTH characters is required for display
-    {
-        shortDesc.setLength(DESCRIPTION_DISPLAY_LENGTH - 3);
-        shortDesc.append("...");
-    }
-    return shortDesc.str();
-}
-
 bool CWsDfuEx::addToLogicalFileList(IPropertyTree& file, const char* nodeGroup, double version, IArrayOf<IEspDFULogicalFile>& logicalFiles)
 {
     const char* logicalName = file.queryProp(getDFUQResultFieldName(DFUQRFname));
@@ -3321,7 +3290,7 @@ bool CWsDfuEx::addToLogicalFileList(IPropertyTree& file, const char* nodeGroup,
         StringBuffer buf(file.queryProp(getDFUQResultFieldName(DFUQRFtimemodified)));
         lFile->setModified(buf.replace('T', ' ').str());
         lFile->setPrefix(getPrefixFromLogicalName(logicalName, buf.clear()));
-        lFile->setDescription(getShortDescription(file.queryProp(getDFUQResultFieldName(DFUQRFdescription)), buf.clear()));
+        lFile->setDescription(file.queryProp(getDFUQResultFieldName(DFUQRFdescription)));
 
         if (!nodeGroup || !*nodeGroup)
                 nodeGroup = file.queryProp(getDFUQResultFieldName(DFUQRFnodegroup));

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

@@ -146,7 +146,6 @@ public:
 
 private:
     const char* getPrefixFromLogicalName(const char* logicalName, StringBuffer& prefix);
-    const char* getShortDescription(const char* description, StringBuffer& shortDesc);
     bool addDFUQueryFilter(DFUQResultField *filters, unsigned short &count, MemoryBuffer &buff, const char* value, DFUQResultField name);
     void appendDFUQueryFilter(const char *name, DFUQFilterType type, const char *value, StringBuffer& filterBuf);
     void appendDFUQueryFilter(const char *name, DFUQFilterType type, const char *value, const char *valueHigh, StringBuffer& filterBuf);

+ 3 - 2
plugins/javaembed/javaembed.cpp

@@ -2081,9 +2081,10 @@ public:
     {
         throwUnexpected();
     }
-    virtual void rewindTo(unsigned int prevlen)
+    virtual IInterface *saveLocation() const {return nullptr;}
+    virtual void rewindTo(IInterface *loc)
     {
-        //needs to be a no-op because it is used, but the way its used to trim empty xml sections I think we're fairly safe.
+        //needs to be a no-op because it is  used, but the way its used to trim empty xml sections I think we're fairly safe.
         //revisit cleaning up any empty objects later.
     }
     inline IEsdlDefStruct *queryCurrentEsdlStruct()

+ 80 - 62
testing/regress/ecl/despray.ecl

@@ -32,7 +32,7 @@ allPeople := DATASET([ {1,'Fred','Smith'},
                        {3,'Jane','Smith'}],Layout_Person);
 
 //  Outputs  ---
-output(allPeople, , '~persons', OVERWRITE);
+setup := output(allPeople, , '~persons', OVERWRITE);
 
 import * from lib_fileservices;
 
@@ -70,9 +70,9 @@ end;
 
 // This should be fine based on valid target file path and SrcAddIp
 DestFile1 := '/var/lib/HPCCSystems/mydropzone/' + File;
-dst0 := NOFOLD(DATASET([{SourceFile, DestFile1, SrcAddrIp, True, '', ''}], rec));
-p0 := PROJECT(NOFOLD(dst0), t(LEFT));
-c0 := CATCH(NOFOLD(p0), ONFAIL(TRANSFORM(rec,
+dst2 := NOFOLD(DATASET([{SourceFile, DestFile1, SrcAddrIp, True, '', ''}], rec));
+p2 := PROJECT(NOFOLD(dst2), t(LEFT));
+c2 := CATCH(NOFOLD(p2), ONFAIL(TRANSFORM(rec,
                                  SELF.sourceFile := SourceFile,
                                  SELF.destFile := DestFile1,
                                  SELF.ip := SrcAddrIp,
@@ -81,16 +81,16 @@ c0 := CATCH(NOFOLD(p0), ONFAIL(TRANSFORM(rec,
                                  SELF.msg := FAILMESSAGE
                                 )));
 #if (VERBOSE = 1)
-    output(c0);
+    o2 := output(c2);
 #else
-    output(c0, {result});
+    o2 := output(c2, {result});
 #end
 
 
 // This should fail based on 'localhost' used as source address
-dst1 := NOFOLD(DATASET([{SourceFile, DestFile1, SrcAddrLocalhost, True, '', ''}], rec));
-p1 := PROJECT(NOFOLD(dst1), t(LEFT));
-c1 := CATCH(NOFOLD(p1), ONFAIL(TRANSFORM(rec,
+dst3 := NOFOLD(DATASET([{SourceFile, DestFile1, SrcAddrLocalhost, True, '', ''}], rec));
+p3 := PROJECT(NOFOLD(dst3), t(LEFT));
+c3 := CATCH(NOFOLD(p3), ONFAIL(TRANSFORM(rec,
                                  SELF.result := 'Fail',
                                  SELF.destFile := DestFile1,
                                  SELF.sourceFile := SourceFile,
@@ -99,123 +99,126 @@ c1 := CATCH(NOFOLD(p1), ONFAIL(TRANSFORM(rec,
                                  SELF.msg := FAILMESSAGE
                                 )));
 #if (VERBOSE = 1)
-    output(c1);
+    o3 := output(c3);
 #else
-    output(c1, {result});
+    o3 := output(c3, {result});
 #end
 
 
 // This should fail based on '/./' used in target path
-DestFile2 := '/var/lib/HPCCSystems/mydropzone/./' + File;
-dst2 := NOFOLD(DATASET([{SourceFile, DestFile2, SrcAddrIp, True, '', ''}], rec));
-p2 := PROJECT(NOFOLD(dst2), t(LEFT));
-c2 := CATCH(NOFOLD(p2), ONFAIL(TRANSFORM(rec,
+DestFile4 := '/var/lib/HPCCSystems/mydropzone/./' + File;
+dst4 := NOFOLD(DATASET([{SourceFile, DestFile4, SrcAddrIp, True, '', ''}], rec));
+p4 := PROJECT(NOFOLD(dst4), t(LEFT));
+c4 := CATCH(NOFOLD(p4), ONFAIL(TRANSFORM(rec,
                                  SELF.result := 'Fail',
-                                 SELF.destFile := DestFile2,
+                                 SELF.destFile := DestFile4,
                                  SELF.sourceFile := SourceFile,
                                  SELF.ip := SrcAddrIp,
                                  SELF.allowOverwrite := True,
                                  SELF.msg := FAILMESSAGE
                                 )));
 #if (VERBOSE = 1)
-    output(c2);
+    o4 := output(c4);
 #else
-    output(c2, {result});
+    o4 := output(c4, {result});
 #end
 
 
 // This should fail based on '/../' used in target path
-DestFile3 := '/var/lib/HPCCSystems/mydropzone/../' + File;
-dst3 := NOFOLD(DATASET([{SourceFile, DestFile3, SrcAddrIp, True, '', ''}], rec));
-p3 := PROJECT(NOFOLD(dst3), t(LEFT));
-c3 := CATCH(NOFOLD(p3), ONFAIL(TRANSFORM(rec,
+DestFile5 := '/var/lib/HPCCSystems/mydropzone/../' + File;
+dst5 := NOFOLD(DATASET([{SourceFile, DestFile5, SrcAddrIp, True, '', ''}], rec));
+p5 := PROJECT(NOFOLD(dst5), t(LEFT));
+c5 := CATCH(NOFOLD(p5), ONFAIL(TRANSFORM(rec,
                                  SELF.result := 'Fail',
-                                 SELF.destFile := DestFile3,
+                                 SELF.destFile := DestFile5,
                                  SELF.sourceFile := SourceFile,
                                  SELF.ip := SrcAddrIp,
                                  SELF.allowOverwrite := True,
                                  SELF.msg := FAILMESSAGE
                                 )));
 #if (VERBOSE = 1)
-    output(c3);
+    o5 := output(c5);
 #else
-    output(c3, {result});
+    o5 := output(c5, {result});
 #end
 
 
-// This should fail based on not an existing dropzone path used in target file path
-DestFile4 := '/var/lib/HPCCSystems/mydropzona/' + File;
-dst4 := NOFOLD(DATASET([{SourceFile, DestFile4, SrcAddrIp, True, '', ''}], rec));
-p4 := PROJECT(NOFOLD(dst4), t(LEFT));
-c4 := CATCH(NOFOLD(p4), ONFAIL(TRANSFORM(rec,
+// This should pass based on HPCC-15787 write log entry instead of thow an exception if
+// not an existing dropzone path used in target file path
+DestFile6 := '/var/lib/HPCCSystems/mydropzona/' + File;
+dst6 := NOFOLD(DATASET([{SourceFile, DestFile6, SrcAddrIp, True, '', ''}], rec));
+p6 := PROJECT(NOFOLD(dst6), t(LEFT));
+c6 := CATCH(NOFOLD(p6), ONFAIL(TRANSFORM(rec,
                                  SELF.result := 'Fail',
-                                 SELF.destFile := DestFile4,
+                                 SELF.destFile := DestFile6,
                                  SELF.sourceFile := SourceFile,
                                  SELF.ip := SrcAddrIp,
                                  SELF.allowOverwrite := True,
                                  SELF.msg := FAILMESSAGE
                                 )));
 #if (VERBOSE = 1)
-    output(c4);
+    o6 := output(c6);
 #else
-    output(c4, {result});
+    o6 := output(c6, {result});
 #end
 
 
-// This should fail based on try to despray out of a drop zone
-DestFile5 := '/var/lib/HPCCSystems/' + File;
-dst5 := NOFOLD(DATASET([{SourceFile, DestFile5, SrcAddrIp, True, '', ''}], rec));
-p5 := PROJECT(NOFOLD(dst5), t(LEFT));
-c5 := CATCH(NOFOLD(p5), ONFAIL(TRANSFORM(rec,
+// This should pass based on HPCC15787 write log entry instead of thow an exception if
+// try to despray out of a drop zone
+DestFile7 := '/var/lib/HPCCSystems/' + File;
+dst7 := NOFOLD(DATASET([{SourceFile, DestFile7, SrcAddrIp, True, '', ''}], rec));
+p7 := PROJECT(NOFOLD(dst7), t(LEFT));
+c7 := CATCH(NOFOLD(p7), ONFAIL(TRANSFORM(rec,
                                  SELF.result := 'Fail',
-                                 SELF.destFile := DestFile5,
+                                 SELF.destFile := DestFile7,
                                  SELF.sourceFile := SourceFile,
                                  SELF.ip := SrcAddrIp,
                                  SELF.allowOverwrite := True,
                                  SELF.msg := FAILMESSAGE
                                 )));
 #if (VERBOSE = 1)
-    output(c5);
+    o7 := output(c7);
 #else
-    output(c5, {result});
+    o7 := output(c7, {result});
 #end
 
 
-// This should fail based on not an existing dropzone path used in target file path
-DestFile6 := '/var/lib/HPCCSystems/mydropzone../' + File;
-dst6 := NOFOLD(DATASET([{SourceFile, DestFile6, SrcAddrIp, True, '', ''}], rec));
-p6 := PROJECT(NOFOLD(dst6), t(LEFT));
-c6 := CATCH(NOFOLD(p6), ONFAIL(TRANSFORM(rec,
+// This should passbased on HPCC15787 write log entry instead of thow an exception if
+// not an existing dropzone path used in target file path
+DestFile8 := '/var/lib/HPCCSystems/mydropzone../' + File;
+dst8 := NOFOLD(DATASET([{SourceFile, DestFile8, SrcAddrIp, True, '', ''}], rec));
+p8 := PROJECT(NOFOLD(dst8), t(LEFT));
+c8 := CATCH(NOFOLD(p8), ONFAIL(TRANSFORM(rec,
                                  SELF.result := 'Fail',
-                                 SELF.destFile := DestFile6,
+                                 SELF.destFile := DestFile8,
                                  SELF.sourceFile := SourceFile,
                                  SELF.ip := SrcAddrIp,
                                  SELF.allowOverwrite := True,
                                  SELF.msg := FAILMESSAGE
                                 )));
 #if (VERBOSE = 1)
-    output(c6);
+    o8 := output(c8);
 #else
-    output(c6, {result});
+    o8 := output(c8, {result});
 #end
 
 
 // This should pass based on valid target file path and valid source address used
-DestFile7 := '/var/lib/HPCCSystems/mydropzone/test/' + File;
-dst7 := NOFOLD(DATASET([{SourceFile, DestFile7, SrcAddrIp, True, '', ''}], rec));
-p7 := PROJECT(NOFOLD(dst7), t(LEFT));
-c7 := CATCH(NOFOLD(p7), ONFAIL(TRANSFORM(rec,
+DestFile9 := '/var/lib/HPCCSystems/mydropzone/test/' + File;
+dst9 := NOFOLD(DATASET([{SourceFile, DestFile9, SrcAddrIp, True, '', ''}], rec));
+p9 := PROJECT(NOFOLD(dst9), t(LEFT));
+c9 := CATCH(NOFOLD(p9), ONFAIL(TRANSFORM(rec,
                                  SELF.result := 'Fail',
-                                 SELF.destFile := DestFile7,
+                                 SELF.destFile := DestFile9,
                                  SELF.sourceFile := SourceFile,
                                  SELF.ip := SrcAddrIp,
                                  SELF.allowOverwrite := True,
                                  SELF.msg := FAILMESSAGE
                                 )));
 #if (VERBOSE = 1)
-    output(c7);
+    o9 := output(c9);
 #else
-    output(c7, {result});
+    o9 := output(c9, {result});
 #end
 
 
@@ -223,18 +226,33 @@ c7 := CATCH(NOFOLD(p7), ONFAIL(TRANSFORM(rec,
 
 // This shoud fail based on the previous despray already created a file on the target path
 // and overwrite not allowed.
-dst8 := NOFOLD(DATASET([{SourceFile, DestFile7, SrcAddrIp, False, '', ''}], rec));
-p8 := PROJECT(NOFOLD(dst8), t(LEFT));
-c8 := CATCH(NOFOLD(p8), ONFAIL(TRANSFORM(rec,
+dst10 := NOFOLD(DATASET([{SourceFile, DestFile9, SrcAddrIp, False, '', ''}], rec));
+p10 := PROJECT(NOFOLD(dst10), t(LEFT));
+c10 := CATCH(NOFOLD(p10), ONFAIL(TRANSFORM(rec,
                                  SELF.result := 'Fail',
-                                 SELF.destFile := DestFile7,
+                                 SELF.destFile := DestFile9,
                                  SELF.sourceFile := SourceFile,
                                  SELF.ip := SrcAddrIp,
                                  SELF.allowOverwrite := False,
                                  SELF.msg := FAILMESSAGE
                                 )));
 #if (VERBOSE = 1)
-    output(c8);
+    o10 := output(c10);
 #else
-    output(c8, {result});
+    o10 := output(c10, {result});
 #end
+
+SEQUENTIAL(
+  setup,
+  PARALLEL(
+    o2,
+    o3,
+    o4,
+    o5,
+    o6,
+    o7,
+    o8,
+    o9,
+    o10
+  )
+);

+ 3 - 3
testing/regress/ecl/key/despray.xml

@@ -13,13 +13,13 @@
  <Row><result>Fail</result></Row>
 </Dataset>
 <Dataset name='Result 6'>
- <Row><result>Fail</result></Row>
+ <Row><result>Pass</result></Row>
 </Dataset>
 <Dataset name='Result 7'>
- <Row><result>Fail</result></Row>
+ <Row><result>Pass</result></Row>
 </Dataset>
 <Dataset name='Result 8'>
- <Row><result>Fail</result></Row>
+ <Row><result>Pass</result></Row>
 </Dataset>
 <Dataset name='Result 9'>
  <Row><result>Pass</result></Row>

+ 2 - 1
thorlcr/activities/keyedjoin/thkeyedjoinslave.cpp

@@ -1572,7 +1572,8 @@ public:
         groupsPendsNoted = fetchReadBack = groupPendsEnded = doneGroupsDeQueued = wroteToFetchPipe = groupsComplete = 0;
 #endif
         inputHelper = NULL;
-        preserveGroups = preserveOrder = eos = false;
+        preserveGroups = preserveOrder = false;
+        eos = true; // keep as true until started.
         resultDistStream = NULL;
         tlkKeySet.setown(createKeyIndexSet());
         partKeySet.setown(createKeyIndexSet());