浏览代码

Merge remote-tracking branch 'origin/closedown-4.0.x' into candidate-4.0.0

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 12 年之前
父节点
当前提交
903200901c

+ 1 - 1
CMakeLists.txt

@@ -287,7 +287,7 @@ endif ( UNIX )
 if ( PLATFORM )
 else ( PLATFORM )
     if ( APPLE OR WIN32 )
-        set ( CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${CPACK_RPM_PACKAGE_VERSION}-${version}-${stagever}-${CPACK_SYSTEM_NAME}")
+        set ( CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${CPACK_RPM_PACKAGE_VERSION}-${version}-${stagever}${CPACK_SYSTEM_NAME}" )
     endif()
     set ( CPACK_MONOLITHIC_INSTALL TRUE )
     set ( CPACK_PACKAGE_VENDOR "HPCC Systems" )

+ 67 - 40
common/thorhelper/thorxmlwrite.cpp

@@ -330,19 +330,19 @@ CommonJsonWriter & CommonJsonWriter::clear()
 
 void CommonJsonWriter::checkFormat(bool doDelimit, bool delimitNext, int inc)
 {
-    if (doDelimit && needDelimiter)
+    if (doDelimit)
     {
-        if (!out.length()) //new block
-           out.append(',');
-        else
-            delimitJSON(out);
-    }
-    if (!nestLimit)
-    {
-        out.append('\n').pad(indent);
-        if (inc!=0)
-            indent+=inc;
+        if (needDelimiter)
+        {
+            if (!out.length()) //new block
+               out.append(',');
+            else
+                delimitJSON(out);
+        }
+        if (!nestLimit)
+            out.append('\n').pad(indent);
     }
+    indent+=inc;
     needDelimiter = delimitNext;
 }
 
@@ -351,6 +351,36 @@ void CommonJsonWriter::checkDelimit(int inc)
     checkFormat(true, true, inc);
 }
 
+const char *CommonJsonWriter::checkItemName(CJsonWriterItem *item, const char *name)
+{
+    if (item && item->depth==0 && strieq(item->name, name))
+        return NULL;
+    return name;
+}
+
+const char *CommonJsonWriter::checkItemName(const char *name)
+{
+    CJsonWriterItem *item = (arrays.length()) ? &arrays.tos() : NULL;
+    return checkItemName(item, name);
+}
+
+const char *CommonJsonWriter::checkItemNameBeginNested(const char *name)
+{
+    CJsonWriterItem *item = (arrays.length()) ? &arrays.tos() : NULL;
+    name = checkItemName(item, name);
+    if (item)
+        item->depth++;
+    return name;
+}
+
+const char *CommonJsonWriter::checkItemNameEndNested(const char *name)
+{
+    CJsonWriterItem *item = (arrays.length()) ? &arrays.tos() : NULL;
+    if (item)
+        item->depth--;
+    return checkItemName(item, name);
+}
+
 void CommonJsonWriter::outputQuoted(const char *text)
 {
     checkDelimit();
@@ -364,7 +394,7 @@ void CommonJsonWriter::outputString(unsigned len, const char *field, const char
     if ((flags & XWFopt) && (rtlTrimStrLen(len, field) == 0))
         return;
     checkDelimit();
-    appendJSONValue(out, fieldname, len, field);
+    appendJSONValue(out, checkItemName(fieldname), len, field);
 }
 
 void CommonJsonWriter::outputQString(unsigned len, const char *field, const char *fieldname)
@@ -382,43 +412,43 @@ void CommonJsonWriter::outputQString(unsigned len, const char *field, const char
 void CommonJsonWriter::outputBool(bool field, const char *fieldname)
 {
     checkDelimit();
-    appendJSONValue(out, fieldname, field);
+    appendJSONValue(out, checkItemName(fieldname), field);
 }
 
 void CommonJsonWriter::outputData(unsigned len, const void *field, const char *fieldname)
 {
     checkDelimit();
-    appendJSONValue(out, fieldname, len, field);
+    appendJSONValue(out, checkItemName(fieldname), len, field);
 }
 
 void CommonJsonWriter::outputInt(__int64 field, const char *fieldname)
 {
     checkDelimit();
-    appendJSONValue(out, fieldname, field);
+    appendJSONValue(out, checkItemName(fieldname), field);
 }
 
 void CommonJsonWriter::outputUInt(unsigned __int64 field, const char *fieldname)
 {
     checkDelimit();
-    appendJSONValue(out, fieldname, field);
+    appendJSONValue(out, checkItemName(fieldname), field);
 }
 
 void CommonJsonWriter::outputReal(double field, const char *fieldname)
 {
     checkDelimit();
-    appendJSONValue(out, fieldname, field);
+    appendJSONValue(out, checkItemName(fieldname), field);
 }
 
 void CommonJsonWriter::outputDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
 {
     checkDelimit();
-    outputJsonDecimal(field, size, precision, fieldname, out);
+    outputJsonDecimal(field, size, precision, checkItemName(fieldname), out);
 }
 
 void CommonJsonWriter::outputUDecimal(const void *field, unsigned size, unsigned precision, const char *fieldname)
 {
     checkDelimit();
-    outputJsonUDecimal(field, size, precision, fieldname, out);
+    outputJsonUDecimal(field, size, precision, checkItemName(fieldname), out);
 }
 
 void CommonJsonWriter::outputUnicode(unsigned len, const UChar *field, const char *fieldname)
@@ -428,7 +458,7 @@ void CommonJsonWriter::outputUnicode(unsigned len, const UChar *field, const cha
     if ((flags & XWFopt) && (rtlTrimUnicodeStrLen(len, field) == 0))
         return;
     checkDelimit();
-    outputJsonUnicode(len, field, fieldname, out);
+    outputJsonUnicode(len, field, checkItemName(fieldname), out);
 }
 
 void CommonJsonWriter::outputUtf8(unsigned len, const char *field, const char *fieldname)
@@ -438,12 +468,12 @@ void CommonJsonWriter::outputUtf8(unsigned len, const char *field, const char *f
     if ((flags & XWFopt) && (rtlTrimUtf8StrLen(len, field) == 0))
         return;
     checkDelimit();
-    appendJSONValue(out, fieldname, len, field);
+    appendJSONValue(out, checkItemName(fieldname), len, field);
 }
 
 void CommonJsonWriter::outputBeginArray(const char *fieldname)
 {
-    arrays.append(fieldname);
+    arrays.append(*new CJsonWriterItem(fieldname));
     const char * sep = strchr(fieldname, '/');
     while (sep)
     {
@@ -452,7 +482,7 @@ void CommonJsonWriter::outputBeginArray(const char *fieldname)
         fieldname = sep+1;
         sep = strchr(fieldname, '/');
     }
-    checkFormat(true, false, 1);
+    checkFormat(false, false, 1);
     appendJSONName(out, fieldname).append('[');
 }
 
@@ -471,24 +501,21 @@ void CommonJsonWriter::outputEndArray(const char *fieldname)
 
 void CommonJsonWriter::outputBeginNested(const char *fieldname, bool nestChildren)
 {
-    const char *parentArray = (arrays.length()) ? arrays.tos() : NULL;
-    if (parentArray && !streq(parentArray, fieldname))
-        parentArray = NULL;
     flush(false);
     checkFormat(true, false, 1);
-    const char * sep = (fieldname) ? strchr(fieldname, '/') : NULL;
-    while (sep)
+    fieldname = checkItemNameBeginNested(fieldname);
+    if (fieldname)
     {
-        if (!parentArray)
+        const char * sep = (fieldname) ? strchr(fieldname, '/') : NULL;
+        while (sep)
         {
             StringAttr leading(fieldname, sep-fieldname);
             appendJSONName(out, leading).append("{");
+            fieldname = sep+1;
+            sep = strchr(fieldname, '/');
         }
-        fieldname = sep+1;
-        sep = strchr(fieldname, '/');
-    }
-    if (!parentArray)
         appendJSONName(out, fieldname);
+    }
     out.append("{");
     if (!nestChildren && !nestLimit)
         nestLimit = indent;
@@ -496,17 +523,17 @@ void CommonJsonWriter::outputBeginNested(const char *fieldname, bool nestChildre
 
 void CommonJsonWriter::outputEndNested(const char *fieldname)
 {
-    const char *parentArray = (arrays.length()) ? arrays.tos() : NULL;
-    if (parentArray && !streq(parentArray, fieldname))
-        parentArray = NULL;
     flush(false);
     checkFormat(false, true, -1);
-    const char * sep = (fieldname) ? strchr(fieldname, '/') : NULL;
-    while (sep)
+    fieldname = checkItemNameEndNested(fieldname);
+    if (fieldname)
     {
-        if (!parentArray)
+        const char * sep = (fieldname) ? strchr(fieldname, '/') : NULL;
+        while (sep)
+        {
             out.append('}');
-        sep = strchr(sep+1, '/');
+            sep = strchr(sep+1, '/');
+        }
     }
     out.append("}");
     if (indent==nestLimit)

+ 15 - 2
common/thorhelper/thorxmlwrite.hpp

@@ -122,9 +122,22 @@ protected:
             flusher->flushXML(out, isClose);
     }
 
-protected:
+    class CJsonWriterItem : public CInterface
+    {
+    public:
+        CJsonWriterItem(const char *_name) : name(_name), depth(0){}
+
+        StringAttr name;
+        unsigned depth;
+    };
+
+    const char *checkItemName(CJsonWriterItem *item, const char *name);
+    const char *checkItemName(const char *name);
+    const char *checkItemNameBeginNested(const char *name);
+    const char *checkItemNameEndNested(const char *name);
+
     IXmlStreamFlusher *flusher;
-    StringArray arrays;
+    CIArrayOf<CJsonWriterItem> arrays;
     StringBuffer out;
     unsigned flags;
     unsigned indent;

+ 1 - 2
common/workunit/pkgimpl.hpp

@@ -85,6 +85,7 @@ protected:
 
     inline StringBuffer makeSuperFileXPath(StringBuffer &xpath, const char *superFileName) const
     {
+        superFileName = skipForeign(superFileName);
         return xpath.append("SuperFile[@id='").appendLower(strlen(superFileName), superFileName).append("']");
     }
 
@@ -244,8 +245,6 @@ public:
         if (!superFileName || !*superFileName || !TYPE::node)
             return false;
 
-        if (*superFileName=='~')
-            superFileName++;
         StringBuffer xpath;
         if (TYPE::hasProp(TYPE::makeSuperFileXPath(xpath, superFileName)))
             return true;

+ 1 - 1
common/workunit/referencedfilelist.cpp

@@ -35,7 +35,7 @@ bool getIsOpt(const IPropertyTree &graphNode)
         return graphNode.getPropBool("att[@name='_isIndexOpt']/@value", false);
 }
 
-const char *skipForeign(const char *name, StringBuffer *ip=NULL)
+const char *skipForeign(const char *name, StringBuffer *ip)
 {
     if (*name=='~')
         name++;

+ 2 - 0
common/workunit/referencedfilelist.hpp

@@ -59,6 +59,8 @@ interface IReferencedFileList : extends IInterface
     virtual void cloneRelationships()=0;
 };
 
+extern WORKUNIT_API const char *skipForeign(const char *name, StringBuffer *ip=NULL);
+
 extern WORKUNIT_API IReferencedFileList *createReferencedFileList(const char *user, const char *pw);
 
 #endif //REFFILE_LIST_HPP

+ 4 - 0
dali/base/dadfs.cpp

@@ -4127,6 +4127,8 @@ class CDistributedSuperFile: public CDistributedFileBase<IDistributedSuperFile>
                 try
                 {
                     sub.setown(transaction->lookupFile(subfile,SDS_SUB_LOCK_TIMEOUT));
+                    if (!sub)
+                        throw MakeStringException(-1,"cAddSubFileAction: sub file %s not found", subfile.sget());
                     // Must validate before locking for update below, to check sub is not already in parent (and therefore locked already)
                     CDistributedSuperFile *sf = dynamic_cast<CDistributedSuperFile *>(parent.get());;
                     sf->validateAddSubFile(sub);
@@ -4135,6 +4137,7 @@ class CDistributedSuperFile: public CDistributedFileBase<IDistributedSuperFile>
                 {
                     if (e->errorCode()!=DFSERR_LookupConnectionTimout)
                         throw;
+                    e->Release();
                     return false;
                 }
                 if (!sub.get())
@@ -4207,6 +4210,7 @@ class CDistributedSuperFile: public CDistributedFileBase<IDistributedSuperFile>
                 {
                     if (e->errorCode()!=DFSERR_LookupConnectionTimout)
                         throw;
+                    e->Release();
                     return false;
                 }
                 if (!parent->querySubFileNamed(subfile))

+ 1 - 1
dali/base/dautils.cpp

@@ -2682,12 +2682,12 @@ void safeChangeModeWrite(IRemoteConnection *conn,const char *name,bool &reload,
                     if (count==2)
                         PrintStackReport();
                 }
-                e->Release();
                 if (timeoutms!=INFINITE) {
                     timeoutms -= steptime;
                     if (timeoutms==0)
                         throw;
                 }
+                e->Release();
             }
             else
                 throw;

+ 2 - 1
dali/ft/filecopy.cpp

@@ -2575,9 +2575,10 @@ const char * FileSprayer::querySlaveExecutable(const IpAddress &ip, StringBuffer
         if (ret.length())
             return ret.str();
     }
-    catch (IException *) {
+    catch (IException * e) {
         if (!slave||!*slave)
             throw;
+        e->Release();
     }
     if (slave)
         ret.append(slave);

+ 5 - 1
docs/RDDERef/RDDE_Mods/Packages.xml

@@ -319,7 +319,11 @@
                 xpointer="eclpackageinfo"
                 xmlns:xi="http://www.w3.org/2001/XInclude" />
 
-    <sect2>
+    <xi:include href="../../HPCCClientTools/CT_Mods/CT_ECL_CLI.xml"
+                xpointer="eclpackagevalidate"
+                xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+    <sect2 role="brk">
       <title>Tips:</title>
 
       <itemizedlist mark="bullet">

+ 8 - 1
ecl/eclcc/eclcc.cpp

@@ -201,6 +201,7 @@ public:
         logVerbose = false;
         logTimings = false;
         optArchive = false;
+        optCheckEclVersion = true;
         optGenerateMeta = false;
         optGenerateDepend = false;
         optIncludeMeta = false;
@@ -292,6 +293,7 @@ protected:
     bool logVerbose;
     bool logTimings;
     bool optArchive;
+    bool optCheckEclVersion;
     bool optGenerateMeta;
     bool optGenerateDepend;
     bool optIncludeMeta;
@@ -1012,7 +1014,8 @@ void EclCC::processXmlFile(EclCompileInstance & instance, const char *archiveXML
     instance.ignoreUnknownImport = archiveTree->getPropBool("@ignoreUnknownImport", true);
 
     instance.eclVersion.set(archiveTree->queryProp("@eclVersion"));
-    checkEclVersionCompatible(instance.errs, instance.eclVersion);
+    if (optCheckEclVersion)
+        checkEclVersionCompatible(instance.errs, instance.eclVersion);
 
     Owned<IEclSourceCollection> archiveCollection;
     if (archiveTree->getPropBool("@testRemoteInterface", false))
@@ -1466,6 +1469,9 @@ bool EclCC::parseCommandLineOptions(int argc, const char* argv[])
         else if (iter.matchFlag(optOnlyCompile, "-c"))
         {
         }
+        else if (iter.matchFlag(optCheckEclVersion, "-checkVersion"))
+        {
+        }
         else if (iter.matchFlag(optArchive, "-E"))
         {
         }
@@ -1701,6 +1707,7 @@ const char * const helpText[] = {
     "Other options:",
     "!   -b            Batch mode.  Each source file is processed in turn.  Output",
     "!                 name depends on the input filename",
+    "!   -checkVersion Enable/disable ecl version checking from archives",
 #ifdef _WIN32
     "!   -brk <n>      Trigger a break point in eclcc after nth allocation",
 #endif

+ 1 - 1
ecl/regress/issue8857.eclxml

@@ -1,4 +1,4 @@
-<Archive build="community_3.8.6-1" eclVersion="3.6.1" legacyMode="0">
+<Archive build="community_3.8.6-1" legacyMode="0">
  <Query attributePath="_local_directory_.xyz"/>
  <Module key="_local_directory_" name="_local_directory_">
   <Attribute key="xyz" name="xyz" sourcePath="C:\xyz.ecl">

+ 4 - 1
ecl/regress/regress.sh

@@ -56,7 +56,7 @@ if [[ $1 = '' ]]; then
     exit -1
 fi
 if [[ $* != '' ]]; then
-    while getopts "t:c:I:e:d:f:q:l:" opt; do
+    while getopts "t:c:I:e:d:f:q:l:x:" opt; do
         case $opt in
             t)
                 target_dir=$OPTARG
@@ -82,6 +82,9 @@ if [[ $* != '' ]]; then
             l)
                 userflags="$userflags --logdetail 999 --logfile $OPTARG"
                 ;;
+            x)
+                userflags="$userflags $OPTARG"
+                ;;
             :)
                 echo $syntax
                 exit -1

+ 1 - 1
ecl/regress/version1.eclxml

@@ -1,4 +1,4 @@
-<Archive build="internal_3.0_beta0_Debug" eclVersion="3.0.0">
+<Archive build="internal_3.0_beta0_Debug" eclVersion="4.0.99">
 <!--
 
     HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.

+ 1 - 1
ecl/regress/version3.eclxml

@@ -1,4 +1,4 @@
-<Archive build="internal_3.0_beta0_Debug" eclVersion="3.99999.0">
+<Archive build="internal_3.0_beta0_Debug" eclVersion="4.99999.0">
 <!--
 
     HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.

+ 1 - 1
ecl/regress/version4.eclxml

@@ -1,4 +1,4 @@
-<Archive build="internal_3.0_beta0_Debug" eclVersion="3.0.9999">
+<Archive build="internal_3.0_beta0_Debug" eclVersion="4.0.9999">
 <!--
 
     HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.

+ 4 - 5
esp/files/scripts/DFUWUQueryWidget.js

@@ -37,7 +37,7 @@ define([
     "hpcc/LFDetailsWidget",
     "hpcc/SFDetailsWidget",
 
-    "dojo/text!../templates/DFUWUQueryWidget.html",
+    "dojo/text!../templates/DFUQueryWidget.html",
 
     "dijit/layout/BorderContainer",
     "dijit/layout/TabContainer",
@@ -60,9 +60,9 @@ define([
                 EnhancedGrid, Pagination, IndirectSelection,
                 _TabContainerWidget, WsDfu, ESPLogicalFile, LFDetailsWidget, SFDetailsWidget,
                 template) {
-    return declare("DFUWUQueryWidget", [_TabContainerWidget, _TemplatedMixin, _WidgetsInTemplateMixin], {
+    return declare("DFUQueryWidget", [_TabContainerWidget, _TemplatedMixin, _WidgetsInTemplateMixin], {
         templateString: template,
-        baseClass: "DFUWUQueryWidget",
+        baseClass: "DFUQueryWidget",
         workunitsTab: null,
         workunitsGrid: null,
 
@@ -256,8 +256,7 @@ define([
                 { name: "Modified (UTC/GMT)", field: "Modified", width: "12" }
             ]);
             var objStore = ESPLogicalFile.CreateLFQueryObjectStore();
-            this.workunitsGrid.setStore(objStore);
-            this.workunitsGrid.setQuery(this.getFilter());
+            this.workunitsGrid.setStore(objStore, this.getFilter());
 
             var context = this;
             this.workunitsGrid.on("RowDblClick", function (evt) {

+ 0 - 10
esp/files/scripts/DFUWUDetailsWidget.js

@@ -64,8 +64,6 @@ define([
         playgroundWidgetLoaded: false,
         xmlWidget: null,
         xmlWidgetLoaded: false,
-        legacyPane: null,
-        legacyPaneLoaded: false,
 
         wu: null,
         loaded: false,
@@ -78,10 +76,8 @@ define([
             this.inherited(arguments);
             this.borderContainer = registry.byId(this.id + "BorderContainer");
             this.tabContainer = registry.byId(this.id + "TabContainer");
-            this.legacyPane = registry.byId(this.id + "Legacy");
             this.xmlWidget = registry.byId(this.id + "XML");
 
-
             var context = this;
             this.tabContainer.watch("selectedChildWidget", function (name, oval, nval) {
                 if (nval.id == context.id + "Content" && !context.resultWidgetLoaded) {
@@ -123,12 +119,6 @@ define([
                     context.dfuWorkunitWidget.init({
                         Wuid: context.logicalFile.DFUInfoResponse.Wuid
                     });
-                } else if (nval.id == context.id + "Legacy" && !context.legacyPaneLoaded) {
-                    context.legacyPaneLoaded = true;
-                    context.legacyPane.set("content", dojo.create("iframe", {
-                        src: "/FileSpray/GetDFUWorkunit?wuid=" + context.wu.Wuid,
-                        style: "border: 0; width: 100%; height: 100%"
-                    }));
                 }
             });
         },

+ 10 - 0
esp/files/scripts/ESPWorkunit.js

@@ -558,6 +558,16 @@ define([
                 onGetResults: onFetchResults
             });
         },
+        fetchSourceFiles: function (onFetchSourceFiles) {
+            if (this.sourceFiles && this.sourceFiles.length) {
+                onFetchSourceFiles(this.sourceFiles);
+                return;
+            }
+
+            this.getInfo({
+                onGetSourceFiles: onFetchSourceFiles
+            });
+        },
         fetchTimers: function (onFetchTimers) {
             if (this.timers && this.timers.length) {
                 onFetchTimers(this.timers);

+ 8 - 16
esp/files/scripts/GetDFUWorkunitsWidget.js

@@ -55,8 +55,6 @@ define([
         borderContainer: null,
         tabContainer: null,
         workunitsGrid: null,
-        legacyPane: null,
-        legacyPaneLoaded: false,
 
         tabMap: [],
 
@@ -69,19 +67,10 @@ define([
             this.borderContainer = registry.byId(this.id + "BorderContainer");
             this.tabContainer = registry.byId(this.id + "TabContainer");
             this.workunitsGrid = registry.byId(this.id + "WorkunitsGrid");
-            this.legacyPane = registry.byId(this.id + "Legacy");
 
             var context = this;
             this.tabContainer.watch("selectedChildWidget", function (name, oval, nval) {
                 if (nval.id == context.id + "Workunits") {
-                } else if (nval.id == context.id + "Legacy") {
-                    if (!context.legacyPaneLoaded) {
-                        context.legacyPaneLoaded = true;
-                        context.legacyPane.set("content", dojo.create("iframe", {
-                            src: "/FileSpray/GetDFUWorkunits",
-                            style: "border: 0; width: 100%; height: 100%"
-                        }));
-                    }
                 } else {
                     if (!nval.initalized) {
                         nval.init(nval.params);
@@ -93,8 +82,6 @@ define([
 
         startup: function (args) {
             this.inherited(arguments);
-            this.refreshActionState();
-            this.initWorkunitsGrid();
         },
 
         resize: function (args) {
@@ -217,6 +204,12 @@ define([
             if (this.initalized)
                 return;
             this.initalized = true;
+
+            if (params.ClusterName) {
+                registry.byId(this.id + "Cluster").set("value", params.ClusterName);
+            }
+            this.initWorkunitsGrid();
+            this.refreshActionState();
         },
 
         initWorkunitsGrid: function() {
@@ -266,8 +259,7 @@ define([
             ]);
             var store = new FileSpray.GetDFUWorkunits();
             var objStore = new ObjectStore({ objectStore: store });
-            this.workunitsGrid.setStore(objStore);
-            this.workunitsGrid.setQuery(this.getFilter());
+            this.workunitsGrid.setStore(objStore, this.getFilter());
 
             var context = this;
             this.workunitsGrid.on("RowDblClick", function (evt) {
@@ -332,7 +324,7 @@ define([
                 retVal = new DFUWUDetailsWidget({
                     Wuid: id,
                     title: id,
-                    closable: true,
+                    closable: false,
                     onClose: function () {
                         delete context.tabMap[id];
                         return true;

+ 3 - 1
esp/files/scripts/GraphPageWidget.js

@@ -47,7 +47,9 @@ define([
     "dijit/PopupMenuItem",
     "dijit/Menu",
     "dijit/MenuItem",
-    "dijit/form/TextBox"
+    "dijit/MenuSeparator",
+    "dijit/form/TextBox",
+    "dijit/form/DropDownButton"
 ], function (declare, lang, sniff, arrayUtil, dom, domConstruct, on, has, Memory, ObjectStore,
             _LayoutWidget, _TemplatedMixin, _WidgetsInTemplateMixin, BorderContainer, TabContainer, ContentPane, registry, Dialog,
             DataGrid, entities,

+ 2 - 0
esp/files/scripts/GraphsWidget.js

@@ -37,6 +37,7 @@ define([
         templateString: template,
         baseClass: "GraphsWidget",
 
+        TabPosition: "bottom",
         tabMap: [],
 
         onErrorClick: function (line, col) {
@@ -63,6 +64,7 @@ define([
                 this.tabMap[id] = retVal;
                 this.addChild(retVal);
             }
+            return retVal;
         },
 
         init: function (params) {

+ 28 - 4
esp/files/scripts/ResultWidget.js

@@ -27,6 +27,8 @@ define([
     "dojox/grid/enhanced/plugins/Pagination",
 
     "hpcc/ESPBase",
+    "hpcc/ESPWorkunit",
+    "hpcc/ESPLogicalFile",
 
     "dojo/text!../templates/ResultWidget.html",
 
@@ -38,7 +40,7 @@ define([
 ], function (declare, lang, dom, iframe,
                 _LayoutWidget, _TemplatedMixin, _WidgetsInTemplateMixin, registry,
                 Pagination,
-                ESPBase,
+                ESPBase, ESPWorkunit, ESPLogicalFile,
                 template) {
     return declare("ResultWidget", [_LayoutWidget, _TemplatedMixin, _WidgetsInTemplateMixin], {
         templateString: template,
@@ -124,12 +126,34 @@ define([
             this.result = params.result;
             //TODO:  Encapsulate this IF into ESPResult.js
             if (params.result && params.result.canShowResults()) {
+                this.initResult(params.result);
+            } else if (params.Wuid && params.Sequence) {
+                var wu = ESPWorkunit.Get(params.Wuid);
                 var context = this;
-                params.result.fetchStructure(function (structure) {
+                wu.fetchResults(function (results) {
+                    context.initResult(results[params.Sequence]);
+                });
+            } else if (params.LogicalName) {
+                var logicalFile = ESPLogicalFile.Get(params.LogicalName);
+                var context = this;
+                logicalFile.getInfo({
+                    onGetAll: function(response) {
+                        context.initResult(logicalFile.result);
+                    }
+                });
+            } else {
+                this.initResult(null);
+            }
+        },
+
+        initResult: function (result) {
+            if (result) {
+                var context = this;
+                result.fetchStructure(function (structure) {
                     context.grid.setStructure(structure);
-                    context.grid.setStore(params.result.getObjectStore());
+                    context.grid.setStore(result.getObjectStore());
                     context.refresh();
-                })
+                });
             } else {
                 this.grid.setStructure([
                             {

+ 12 - 5
esp/files/scripts/WUQueryWidget.js

@@ -77,10 +77,8 @@ define([
 
         startup: function (args) {
             this.inherited(arguments);
-            this.initWorkunitsGrid();
             this.initFilter();
             this.initContextMenu();
-            this.refreshActionState();
         },
 
         resize: function (args) {
@@ -304,6 +302,12 @@ define([
                 return;
             this.initalized = true;
 
+            //TODO:  Should be easier generic way
+            if (params.Cluster) {
+                registry.byId(this.id + "Cluster").set("value", params.Cluster);
+            }
+            this.initWorkunitsGrid();
+            this.refreshActionState();
             this.selectChild(this.workunitsTab, true);
         },
 
@@ -434,8 +438,7 @@ define([
             ]);
 
             this.objectStore = ESPWorkunit.CreateWUQueryObjectStore();
-            this.workunitsGrid.setStore(this.objectStore);
-            this.workunitsGrid.setQuery(this.getFilter());
+            this.workunitsGrid.setStore(this.objectStore, this.getFilter());
             this.workunitsGrid.noDataMessage = "<span class='dojoxGridNoData'>Zero Workunits (check filter).</span>";
 
             this.workunitsGrid.on("RowDblClick", function (evt) {
@@ -493,7 +496,6 @@ define([
             var hasNotProtected = false;
             var hasFailed = false;
             var hasNotFailed = false;
-            var hasFilter = this.hasFilter();
             var hasCompleted = false;
             var hasNotCompleted = false;
             for (var i = 0; i < selection.length; ++i) {
@@ -531,6 +533,11 @@ define([
             this.menuProtect.set("disabled", !hasNotProtected);
             this.menuUnprotect.set("disabled", !hasProtected);
 
+            this.refreshFilterState();
+        },
+
+        refreshFilterState: function () {
+            var hasFilter = this.hasFilter();
             dom.byId(this.id + "IconFilter").src = hasFilter ? "img/filter.png" : "img/noFilter.png";
         },
 

+ 5 - 0
esp/files/stub.js

@@ -44,6 +44,11 @@ define([
                         TabPosition: params.TabPosition
                     });
                 }
+                if (params.ReadOnly) {
+                    lang.mixin(webParams, {
+                        readOnly: params.ReadOnly
+                    });
+                }
                 var widget = WidgetClass.fixCircularDependency ? new WidgetClass.fixCircularDependency(webParams) : new WidgetClass(webParams);
 
                 var standbyBackground = new Standby({

esp/files/templates/DFUWUQueryWidget.html → esp/files/templates/DFUQueryWidget.html


+ 0 - 2
esp/files/templates/DFUWUDetailsWidget.html

@@ -220,8 +220,6 @@
             </div>
             <div id="${id}XML" title="XML" data-dojo-props="WUXml: true" data-dojo-type="ECLSourceWidget">
             </div>
-            <div id="${id}Legacy" title="Legacy Web Page" data-dojo-type="dijit.layout.ContentPane">
-            </div>
         </div>
     </div>
 </div>

+ 0 - 2
esp/files/templates/GetDFUWorkunitsWidget.html

@@ -76,8 +76,6 @@
                 }" data-dojo-type="dojox.grid.EnhancedGrid">
                 </div>
             </div>
-            <div id="${id}Legacy" title="Legacy Web Page" data-dojo-type="dijit.layout.ContentPane">
-            </div>
         </div>
     </div>
 </div>

+ 1 - 1
esp/files/templates/GraphsWidget.html

@@ -1,4 +1,4 @@
 <div class="${baseClass}">
-    <div id="${id}TabContainer" style="width: 100%; height: 100%" data-dojo-props="tabPosition: 'bottom'" data-dojo-type="dijit.layout.TabContainer">
+    <div id="${id}TabContainer" style="width: 100%; height: 100%" data-dojo-props="tabPosition: '${TabPosition}'"  data-dojo-type="dijit.layout.TabContainer">
     </div>
 </div>

+ 1 - 1
esp/services/ws_fs/ws_fsBinding.hpp

@@ -69,7 +69,7 @@ public:
 
         IPropertyTree *folderTP = CEspBinding::ensureNavFolder(data, "Tech Preview", "Technical Preview");
         CEspBinding::ensureNavLink(*folderTP, "DFU Workunits", "/esp/files/stub.htm?Widget=GetDFUWorkunitsWidget", "DFU Workunits", NULL, NULL, 2);
-        CEspBinding::ensureNavLink(*folderTP, "Logical Files", "/esp/files/stub.htm?Widget=DFUWUQueryWidget", "Logical Files", NULL, NULL, 3);
+        CEspBinding::ensureNavLink(*folderTP, "Logical Files", "/esp/files/stub.htm?Widget=DFUQueryWidget", "Logical Files", NULL, NULL, 3);
     }
 
     int onGetInstantQuery(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method);

+ 10 - 1
roxie/ccd/ccdcontext.cpp

@@ -3005,11 +3005,12 @@ public:
         StringBuffer responseHead, responseTail;
         appendfJSONName(responseHead, "%sResponse", queryName.get()).append(" {");
         appendJSONValue(responseHead, "sequence", seqNo);
-        appendJSONName(responseHead, "Results").append(" {");
+        appendJSONName(responseHead, "Results").append(" {\n ");
 
         unsigned len = responseHead.length();
         client->write(responseHead.detach(), len, true);
 
+        bool needDelimiter = false;
         ForEachItemIn(seq, resultMap)
         {
             FlushingStringBuffer *result = resultMap.item(seq);
@@ -3022,8 +3023,16 @@ public:
                     void *payload = result->getPayload(length);
                     if (!length)
                         break;
+                    if (needDelimiter)
+                    {
+                        StringAttr s(",\n "); //write() will take ownership of buffer
+                        size32_t len = s.length();
+                        client->write((void *)s.detach(), len, true);
+                        needDelimiter=false;
+                    }
                     client->write(payload, length, true);
                 }
+                needDelimiter=true;
             }
         }
 

+ 1 - 1
rtl/eclrtl/eclrtl_imp.hpp

@@ -151,7 +151,7 @@ public:
     inline ~rtlUStrRegexFindInstance()          { rtlDestroyUStrRegExprFindInstance(instance); }
     inline IUStrRegExprFindInstance * operator -> () const { return instance; }
     
-    void find(rtlCompiledUStrRegex & regex, size32_t len, const UChar * str)
+    void find(const rtlCompiledUStrRegex & regex, size32_t len, const UChar * str)
     {
         IUStrRegExprFindInstance * search = regex->find(str, 0, len);
         if (instance)

+ 1 - 0
rtl/eclrtl/rtlds.cpp

@@ -1003,6 +1003,7 @@ public:
     {
         unsigned pos = offset;
         offset += sizeof(size32_t);
+        builder.ensureCapacity(offset, "");
         return pos;
     }
 

+ 1 - 0
system/hrpc/hrpc.cpp

@@ -424,6 +424,7 @@ bool HRPCmodule::TryConnect(int msecs,bool raiseex,bool leaveunlocked)
             sync->unlock();
             if (raiseex) 
                 throw e;
+            e->Release();
         }
         catch (...) {
             sync->unlock();

+ 1 - 0
thorlcr/activities/piperead/thprslave.cpp

@@ -221,6 +221,7 @@ public:
             {
                 StringBuffer s;
                 ActPrintLog("WARNING: input terminated for pipe with : %s", e->errorMessage(s).str());
+                e->Release();
             }
             else
                 throw;      

+ 12 - 0
thorlcr/graph/thgraphmaster.cpp

@@ -2081,7 +2081,10 @@ void CMasterGraph::abort(IException *e)
         {
             GraphPrintLog(e, "Aborting slave graph");
             if (abortException)
+            {
+                e->Release();
                 throw LINK(abortException);
+            }
             throw;
         }
     }
@@ -2199,7 +2202,10 @@ void CMasterGraph::create(size32_t parentExtractSz, const byte *parentExtract)
                 {
                     GraphPrintLog(e, "Aborting graph create(2)");
                     if (abortException)
+                    {
+                        e->Release();
                         throw LINK(abortException);
+                    }
                     throw;
                 }
             }
@@ -2378,7 +2384,10 @@ void CMasterGraph::sendGraph()
     {
         GraphPrintLog(e, "Aborting sendGraph");
         if (abortException)
+        {
+            e->Release();
             throw LINK(abortException);
+        }
         throw;
     }
     GraphPrintLog("sendGraph took %d ms", atimer.elapsed());
@@ -2401,7 +2410,10 @@ bool CMasterGraph::preStart(size32_t parentExtractSz, const byte *parentExtract)
         {
             GraphPrintLog(e, "Aborting preStart");
             if (abortException)
+            {
+                e->Release();
                 throw LINK(abortException);
+            }
             throw;
         }
     }