Prechádzať zdrojové kódy

Merge remote-tracking branch 'origin/candidate-3.10.x'

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 12 rokov pred
rodič
commit
bfc3bfac9a
29 zmenil súbory, kde vykonal 533 pridanie a 92 odobranie
  1. 31 9
      common/workunit/workunit.cpp
  2. 5 0
      common/workunit/workunit.hpp
  3. 5 0
      dali/treeview/treeviewdlg.cpp
  4. 1 2
      docs/ECLLanguageReference/ECLR_mods/BltInFunc-PULL.xml
  5. 1 13
      docs/ECLLanguageReference/ECLR_mods/ExtrSvcs-ExternalServicesImpl.xml
  6. 7 7
      docs/ECLLanguageReference/ECLR_mods/Templ-FOR.xml
  7. 1 2
      docs/ECLLanguageReference/ECLR_mods/Templ-WORKUNIT.xml
  8. 1 1
      docs/ECLProgrammersGuide/PRG_Mods/PrG_Smart_Stepping.xml
  9. 5 5
      docs/ECLStandardLibraryReference/SLR-Mods/MonitorFile.xml
  10. 5 5
      docs/ECLStandardLibraryReference/SLR-Mods/MonitorLogicalFileName.xml
  11. 7 12
      docs/ECLStandardLibraryReference/SLR-Mods/Nodes.xml
  12. 2 2
      docs/ECLStandardLibraryReference/SLR-Mods/ToGregorianYMD.xml
  13. 28 0
      ecl/eclcmd/eclcmd_common.cpp
  14. 6 0
      ecl/eclcmd/eclcmd_common.hpp
  15. 27 0
      ecl/eclcmd/eclcmd_core.cpp
  16. 179 15
      ecl/eclcmd/queries/ecl-queries.cpp
  17. 35 3
      esp/scm/ws_workunits.ecm
  18. 162 2
      esp/services/ws_workunits/ws_workunitsQuerySets.cpp
  19. 1 0
      esp/services/ws_workunits/ws_workunitsService.hpp
  20. 4 2
      esp/xslt/ui_configmgr.xslt
  21. 2 2
      initfiles/bash/etc/init.d/hpcc_common.in
  22. 1 1
      initfiles/bash/etc/init.d/install-init.in
  23. 4 1
      initfiles/bin/init_dafilesrv.in
  24. 1 1
      initfiles/componentfiles/thor/run_thor
  25. 4 1
      initfiles/componentfiles/thor/start_slave
  26. 1 1
      initfiles/componentfiles/thor/start_slaves
  27. 4 3
      initfiles/componentfiles/thor/start_thor
  28. 2 1
      initfiles/sbin/add_conf_settings.sh.in
  29. 1 1
      system/jlib/jsocket.cpp

+ 31 - 9
common/workunit/workunit.cpp

@@ -8948,27 +8948,49 @@ void setQueryAlias(IPropertyTree * queryRegistry, const char * name, const char
     match->setProp("@id", value);
 }
 
-IPropertyTree * resolveQueryAlias(IPropertyTree * queryRegistry, const char * alias)
+extern WORKUNIT_API IPropertyTree * getQueryById(IPropertyTree * queryRegistry, const char *queryid)
 {
+    if (!queryRegistry || !queryid)
+        return NULL;
+    StringBuffer xpath;
+    xpath.append("Query[@id=\"").append(queryid).append("\"]");
+    return queryRegistry->getPropTree(xpath);
+}
+
+extern WORKUNIT_API IPropertyTree * getQueryById(const char *queryset, const char *queryid, bool readonly)
+{
+    Owned<IPropertyTree> queryRegistry = getQueryRegistry(queryset, readonly);
+    return getQueryById(queryRegistry, queryid);
+}
+
+extern WORKUNIT_API IPropertyTree * resolveQueryAlias(IPropertyTree * queryRegistry, const char * alias)
+{
+    if (!queryRegistry || !alias)
+        return NULL;
+
     StringBuffer xpath;
     unsigned cnt = 0;
-    StringBuffer lcAlias(alias);
-    lcAlias.toLowerCase();
-    const char * search = lcAlias.str();
+    StringBuffer lc(alias);
+    const char * search = lc.toLowerCase().str();
     loop
     {
-        xpath.clear().append("Alias[@name=\"").append(search).append("\"]/@id");
+        xpath.set("Alias[@name='").append(search).append("']/@id");
         const char * queryId = queryRegistry->queryProp(xpath);
         if (!queryId)
             break;
         //Check for too many alias indirections.
         if (cnt++ > 10)
             return NULL;
-        search = lcAlias.clear().append(queryId).toLowerCase().str();
+        search = lc.set(queryId).toLowerCase().str();
     }
 
-    xpath.clear().append("Query[@id=\"").append(search).append("\"]");
-    return queryRegistry->getPropTree(xpath);
+    return getQueryById(queryRegistry, search);
+}
+
+extern WORKUNIT_API IPropertyTree * resolveQueryAlias(const char *queryset, const char *alias, bool readonly)
+{
+    Owned<IPropertyTree> queryRegistry = getQueryRegistry(queryset, readonly);
+    return resolveQueryAlias(queryRegistry, alias);
 }
 
 void setQuerySuspendedState(IPropertyTree * queryRegistry, const char *id, bool suspend)
@@ -9273,4 +9295,4 @@ extern WORKUNIT_API void descheduleWorkunit(char const * wuid)
         workunit->deschedule();
     else
         doDescheduleWorkkunit(wuid);
-}
+}

+ 5 - 0
common/workunit/workunit.hpp

@@ -1213,9 +1213,14 @@ extern WORKUNIT_API void removeWuidFromNamedQueries(IPropertyTree * queryRegistr
 extern WORKUNIT_API void removeDllFromNamedQueries(IPropertyTree * queryRegistry, const char * dll);
 extern WORKUNIT_API void removeAliasesFromNamedQuery(IPropertyTree * queryRegistry, const char * id);
 extern WORKUNIT_API void setQueryAlias(IPropertyTree * queryRegistry, const char * name, const char * value);
+
+extern WORKUNIT_API IPropertyTree * getQueryById(IPropertyTree * queryRegistry, const char *queryid);
+extern WORKUNIT_API IPropertyTree * getQueryById(const char *queryset, const char *queryid, bool readonly);
 extern WORKUNIT_API IPropertyTree * resolveQueryAlias(IPropertyTree * queryRegistry, const char * alias);
+extern WORKUNIT_API IPropertyTree * resolveQueryAlias(const char *queryset, const char *alias, bool readonly);
 extern WORKUNIT_API IPropertyTree * getQueryRegistry(const char * wsEclId, bool readonly);
 extern WORKUNIT_API IPropertyTree * getQueryRegistryRoot();
+
 extern WORKUNIT_API void setQueryCommentForNamedQuery(IPropertyTree * queryRegistry, const char *id, const char *queryComment);
 
 extern WORKUNIT_API void setQuerySuspendedState(IPropertyTree * queryRegistry, const char * name, bool suspend);

+ 5 - 0
dali/treeview/treeviewdlg.cpp

@@ -191,6 +191,9 @@ CTreeviewDlg::CTreeviewDlg(LPCSTR fn, CWnd* pParent) : CDialog(CTreeviewDlg::IDD
         // NOTE: the ClassWizard will add member initialization here
     //}}AFX_DATA_INIT
     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
+    InitModuleObjects();
+    queryStderrLogMsgHandler()->setMessageFields(0);
+
     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
     tooltipCtrl = NULL;
     hAccel = NULL;
@@ -203,6 +206,8 @@ CTreeviewDlg::CTreeviewDlg(LPCSTR fn, CWnd* pParent) : CDialog(CTreeviewDlg::IDD
 
 CTreeviewDlg::~CTreeviewDlg()
 {
+    releaseAtoms();
+
     free(cmdfname);
     if(expander) delete expander;
     delete tooltipCtrl;

+ 1 - 2
docs/ECLLanguageReference/ECLR_mods/BltInFunc-PULL.xml

@@ -37,8 +37,7 @@
   <para>The <emphasis role="bold">PULL </emphasis>function is a meta-operation
   intended only to hint that the <emphasis>dataset</emphasis> should be fully
   loaded into the Data Refinery before continuing the operation in Data
-  Refinery. This allows the Data Refinery optimizer to ensure optimal
-  performance and frees up the Complex Analysis Engine sooner.</para>
+  Refinery. </para>
 
   <para>Example:</para>
 

+ 1 - 13
docs/ECLLanguageReference/ECLR_mods/ExtrSvcs-ExternalServicesImpl.xml

@@ -346,17 +346,6 @@
     a[][20].</para>
   </sect2>
 
-  <sect2 id="ECL_Plug-Ins">
-    <title>ECL Plug-Ins</title>
-
-    <para>In addition to external services, an ECL code module may be built as
-    an ECL plug-in. These need to be deployed to the ESP and ECL servers
-    through the ConfigEnv utility (see the <emphasis>Systems Operation
-    Manual</emphasis>). A plug-in is accessable to all users of the
-    environment, and appears in the ECL IDE in the same fashion as a service
-    library.</para>
-  </sect2>
-
   <sect2 id="Plug-In_Requirements">
     <title>Plug-In Requirements</title>
 
@@ -418,8 +407,7 @@
     called examplelib that contains one entry point (<emphasis
     role="bold">stringfind</emphasis>). This is a slightly modified version of
     the Find function found in the Str standard library. This version is
-    designed to work in both the Data Refinery and Complex Analysis Engine
-    supercomputers.</para>
+    designed to work in the Data Refinery supercomputer.</para>
   </sect2>
 
   <sect2 id="ECL_definitions">

+ 7 - 7
docs/ECLLanguageReference/ECLR_mods/Templ-FOR.xml

@@ -65,16 +65,16 @@
   XMLstuff :=
    '&lt;section&gt;'+
        '&lt;item&gt;'+
-           '&lt;dataset&gt;people&lt;/dataset&gt;'+
+           '&lt;dataset&gt;person&lt;/dataset&gt;'+
            '&lt;filter&gt;firstname = \'RICHARD\'&lt;/filter&gt;'+
        '&lt;/item&gt;'+
        '&lt;item&gt;'+
-           '&lt;dataset&gt;people&lt;/dataset&gt;'+
+           '&lt;dataset&gt;person&lt;/dataset&gt;'+
            '&lt;filter&gt;firstname = \'JOHN\'&lt;/filter&gt;'+
        '&lt;/item&gt;'+
        '&lt;item&gt;'+
-           '&lt;dataset&gt;people&lt;/dataset&gt;'+
-           '&lt;filter&gt;first_name = \'HENRY\'&lt;/filter&gt;'+
+           '&lt;dataset&gt;person&lt;/dataset&gt;'+
+           '&lt;filter&gt;firstname = \'HENRY\'&lt;/filter&gt;'+
        '&lt;/item&gt;'+
    '&lt;/section&gt;';
   
@@ -89,9 +89,9 @@
   %CountStr% // then execute the generated "COUNT" actions
   
   // Note that the "CountStr" will have 3 COUNT actions in it:
-  //   COUNT(person(person.per_first_name = 'RICHARD'));
-  //   COUNT(person(person.per_first_name = 'JOHN'));
-  //   COUNT(person(person.per_first_name = 'HENRY'));
+  //   COUNT(person(person.firstname = 'RICHARD'));
+  //   COUNT(person(person.firstname = 'JOHN'));
+  //   COUNT(person(person.firstname = 'HENRY'));
 </programlisting>
 
   <para>See Also: <link linkend="_LOOP-_BREAK">#LOOP</link>, <link

+ 1 - 2
docs/ECLLanguageReference/ECLR_mods/Templ-WORKUNIT.xml

@@ -83,8 +83,7 @@
             <entry>The value parameter is a string constant containing the
             scope value to use to override the workunit's default scope (the
             user ID of the submitting person). This is a Workunit Security
-            feature (see the supercomputer Operations Manual for a discussion
-            of this feature).</entry>
+            feature.</entry>
           </row>
         </tbody>
       </tgroup>

+ 1 - 1
docs/ECLProgrammersGuide/PRG_Mods/PrG_Smart_Stepping.xml

@@ -87,7 +87,7 @@ OUTPUT(STEPPED(IDX(Filter),FirstName),ALL); //Smart Stepping </programlisting>
     which those results are achieved is very different.</para>
 
     <para>Once you've successfully run this code and gotten your result, take
-    a look at the Graphs page:</para>
+    a look at the Graphs page.</para>
 
     <para>Notice that the first OUTPUT's sub-graph contains three activities:
     the index read, the sort, and the output. But the second OUTPUT's

+ 5 - 5
docs/ECLStandardLibraryReference/SLR-Mods/MonitorFile.xml

@@ -2,7 +2,7 @@
 <!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
 "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
 <sect1 id="MonitorFile">
-  <title>MonitorFile</title>
+  <title><emphasis role="bold">MonitorFile</emphasis></title>
 
   <para><emphasis role="bold">STD.File.MonitorFile<indexterm>
       <primary>STD.File.MonitorFile</primary>
@@ -114,10 +114,10 @@
   <para>The <emphasis role="bold">MonitorFile </emphasis>function creates a
   file monitor job in the DFU Server. Once the job is received it goes into a
   'monitoring' mode (which can be seen in the eclwatch DFU Workunit display),
-  which polls at a fixed interval (settable by configenv but default 15 mins).
-  If an appropriately named file arrives in this interval it will fire the
-  <emphasis>event</emphasis> with the name of the triggering object as the
-  event subtype (see the EVENT function).</para>
+  which polls at a fixed interval (default 15 mins). If an appropriately named
+  file arrives in this interval it will fire the <emphasis>event</emphasis>
+  with the name of the triggering object as the event subtype (see the EVENT
+  function).</para>
 
   <para>This process continues until either:</para>
 

+ 5 - 5
docs/ECLStandardLibraryReference/SLR-Mods/MonitorLogicalFileName.xml

@@ -2,7 +2,7 @@
 <!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
 "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
 <sect1 id="MonitorLogicalFileName">
-  <title>MonitorLogicalFileName</title>
+  <title><emphasis role="bold">MonitorLogicalFileName</emphasis></title>
 
   <para><emphasis role="bold">STD.File.MonitorLogicalFileName<indexterm>
       <primary>STD.File.MonitorLogicalFileName</primary>
@@ -93,10 +93,10 @@
   <para>The <emphasis role="bold">MonitorLogicalFileName </emphasis>function
   creates a file monitor job in the DFU Server. Once the job is received it
   goes into a 'monitoring' mode (which can be seen in the eclwatch DFU
-  Workunit display), which polls at a fixed interval (settable by configenv
-  but default 15 mins). If an appropriately named file arrives in this
-  interval it will fire the <emphasis>event</emphasis> with the name of the
-  triggering object as the event subtype (see the EVENT function).</para>
+  Workunit display), which polls at a fixed interval (default 15 mins). If an
+  appropriately named file arrives in this interval it will fire the
+  <emphasis>event</emphasis> with the name of the triggering object as the
+  event subtype (see the EVENT function).</para>
 
   <para>This process continues until either:</para>
 

+ 7 - 12
docs/ECLStandardLibraryReference/SLR-Mods/Nodes.xml

@@ -2,7 +2,7 @@
 <!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
 "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
 <sect1 id="Nodes">
-  <title>Nodes</title>
+  <title><emphasis role="bold">Nodes</emphasis></title>
 
   <para><emphasis role="bold">STD.System.Thorlib.Nodes<indexterm>
       <primary>STD.System.Thorlib.Nodes</primary>
@@ -23,24 +23,19 @@
 
       <tbody>
         <row>
-          
-
-
-  <entry>Return:<emphasis> </emphasis></entry><entry>Nodes returns an UNSIGNED INTEGER4
-  value.</entry>
-
+          <entry>Return:<emphasis> </emphasis></entry>
 
+          <entry>Nodes returns an UNSIGNED INTEGER4 value.</entry>
         </row>
       </tbody>
     </tgroup>
   </informaltable>
 
-
   <para>The <emphasis role="bold">Nodes </emphasis>function returns the number
-  of nodes in the cluster. This number is the same as the CLUSTERSIZE compile
-  time constant. The Nodes function is evaluated each time it is called, so
-  the choice to use the function versus the constant depends upon the
-  circumstances.</para>
+  of nodes in the Thor cluster (always returns 1 on hThor and Roxie). This
+  number is the same as the CLUSTERSIZE compile time constant. The Nodes
+  function is evaluated each time it is called, so the choice to use the
+  function versus the constant depends upon the circumstances.</para>
 
   <para>Example:</para>
 

+ 2 - 2
docs/ECLStandardLibraryReference/SLR-Mods/ToGregorianYMD.xml

@@ -2,13 +2,13 @@
 <!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
 "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
 <sect1 id="ToGregorianYMD">
-  <title>ToGregorianYMD</title>
+  <title><emphasis role="bold">ToGregorianYMD</emphasis></title>
 
   <para><emphasis role="bold">STD.Date.ToGregorianYMD<indexterm>
       <primary>STD.Date.ToGregorianYMD</primary>
     </indexterm><indexterm>
       <primary>Date.ToGregorianYMD</primary>
-    </indexterm>(</emphasis> <emphasis>year</emphasis> <emphasis
+    </indexterm>(</emphasis> <emphasis>days</emphasis> <emphasis
   role="bold">)</emphasis></para>
 
   <informaltable colsep="0" frame="none" rowsep="0">

+ 28 - 0
ecl/eclcmd/eclcmd_common.cpp

@@ -104,6 +104,34 @@ static bool looksLikeOnlyAWuid(const char * wuid)
     return true;
 }
 
+bool isValidMemoryValue(const char *value)
+{
+    if (!value || !*value || !isdigit(*value))
+        return false;
+    while (isdigit(*++value));
+
+    if (!*value)
+        return true;
+
+    switch (toupper(*value++))
+    {
+        case 'E':
+        case 'P':
+        case 'T':
+        case 'G':
+        case 'M':
+        case 'K':
+            if (!*value || strieq("B", value))
+                return true;
+            break;
+        case 'B':
+            if (!*value)
+                return true;
+            break;
+    }
+    return false;
+}
+
 //=========================================================================================
 
 #define PE_OFFSET_LOCATION_IN_DOS_SECTION 0x3C

+ 6 - 0
ecl/eclcmd/eclcmd_common.hpp

@@ -75,6 +75,10 @@ typedef IEclCommand *(*EclCommandFactory)(const char *cmdname);
 #define ECLOPT_WAIT_INI "waitTimeout"
 #define ECLOPT_WAIT_ENV "ECL_WAIT_TIMEOUT"
 
+#define ECLOPT_TIME_LIMIT "--timeLimit"
+#define ECLOPT_MEMORY_LIMIT "--memoryLimit"
+#define ECLOPT_WARN_TIME_LIMIT "--warnTimeLimit"
+
 #define ECLOPT_RESULT_LIMIT "--limit"
 #define ECLOPT_RESULT_LIMIT_INI "resultLimit"
 #define ECLOPT_RESULT_LIMIT_ENV "ECL_RESULT_LIMIT"
@@ -112,6 +116,8 @@ typedef IEclCommand *(*EclCommandFactory)(const char *cmdname);
 #define ECLOPT_VERBOSE "--verbose"
 #define ECLOPT_VERBOSE_S "-v"
 
+bool isValidMemoryValue(const char *value);
+
 bool extractEclCmdOption(StringBuffer & option, IProperties * globals, const char * envName, const char * propertyName, const char * defaultPrefix, const char * defaultSuffix);
 bool extractEclCmdOption(StringAttr & option, IProperties * globals, const char * envName, const char * propertyName, const char * defaultPrefix, const char * defaultSuffix);
 bool extractEclCmdOption(bool & option, IProperties * globals, const char * envName, const char * propertyName, bool defval);

+ 27 - 0
ecl/eclcmd/eclcmd_core.cpp

@@ -328,6 +328,8 @@ public:
     EclCmdPublish() : optNoActivate(false), activateSet(false), optNoReload(false), optMsToWait(10000)
     {
         optObj.accept = eclObjWuid | eclObjArchive | eclObjSharedObject;
+        optTimeLimit = (unsigned) -1;
+        optWarnTimeLimit = (unsigned) -1;
     }
     virtual bool parseCommandLineOptions(ArgvIterator &iter)
     {
@@ -349,6 +351,12 @@ public:
                 continue;
             if (iter.matchOption(optMsToWait, ECLOPT_WAIT))
                 continue;
+            if (iter.matchOption(optTimeLimit, ECLOPT_TIME_LIMIT))
+                continue;
+            if (iter.matchOption(optWarnTimeLimit, ECLOPT_WARN_TIME_LIMIT))
+                continue;
+            if (iter.matchOption(optMemoryLimit, ECLOPT_MEMORY_LIMIT))
+                continue;
             if (iter.matchFlag(optNoActivate, ECLOPT_NO_ACTIVATE))
             {
                 activateSet=true;
@@ -396,6 +404,11 @@ public:
                 return false;
             }
         }
+        if (optMemoryLimit.length() && !isValidMemoryValue(optMemoryLimit))
+        {
+            fprintf(stderr, "invalid --memoryLimit value of %s.\n\n", optMemoryLimit.get());
+            return false;
+        }
         return true;
     }
     virtual int processCMD()
@@ -426,6 +439,13 @@ public:
         req->setWait(optMsToWait);
         req->setNoReload(optNoReload);
 
+        if (optTimeLimit != (unsigned) -1)
+            req->setTimeLimit(optTimeLimit);
+        if (optWarnTimeLimit != (unsigned) -1)
+            req->setWarnTimeLimit(optWarnTimeLimit);
+        if (!optMemoryLimit.isEmpty())
+            req->setMemoryLimit(optMemoryLimit);
+
         Owned<IClientWUPublishWorkunitResponse> resp = client->WUPublishWorkunit(req);
         const char *id = resp->getQueryId();
         if (id && *id)
@@ -467,6 +487,10 @@ public:
             "   -A, --activate         Activate query when published (default)\n"
             "   -A-, --no-activate     Do not activate query when published\n"
             "   --no-reload            Do not request a reload of the (roxie) cluster\n"
+            "   --timeLimit=<ms>       Value to set for query timeLimit configuration\n"
+            "   --warnTimeLimit=<ms>   Value to set for query warnTimeLimit configuration\n"
+            "   --memoryLimit=<mem>    Value to set for query memoryLimit configuration\n"
+            "                          format <mem> as 500000B, 550K, 100M, 10G, 1T etc.\n"
             "   --wait=<ms>            Max time to wait in milliseconds\n",
             stdout);
         EclCmdWithEclTarget::usage();
@@ -474,7 +498,10 @@ public:
 private:
     StringAttr optTargetCluster;
     StringAttr optName;
+    StringAttr optMemoryLimit;
     unsigned optMsToWait;
+    unsigned optTimeLimit;
+    unsigned optWarnTimeLimit;
     bool optNoActivate;
     bool activateSet;
     bool optNoReload;

+ 179 - 15
ecl/eclcmd/queries/ecl-queries.cpp

@@ -180,20 +180,23 @@ public:
         line.append(query.getSuspended() ? 'S' : ' ');
         line.append(isActive ? 'A' : ' ');
         line.append(' ').append(queryid);
-        if (isActive)
+        if (!query.getTimeLimit_isNull())
         {
-            Owned<IPropertyTreeIterator> activeNames = queryMap.getActiveNames(queryid);
-            if (line.length() < 35)
-                line.appendN(35 - line.length(), ' ');
-            line.append("[");
-            activeNames->first();
-            while (activeNames->isValid())
-            {
-                line.append(activeNames->query().queryProp(NULL));
-                if (activeNames->next())
-                    line.append(',');
-            }
-            line.append("]");
+            if (line.length() < 34)
+                line.appendN(34 - line.length(), ' ');
+            line.append(' ').append(query.getTimeLimit());
+        }
+        if (!query.getWarnTimeLimit_isNull())
+        {
+            if (line.length() < 41)
+                line.appendN(41 - line.length(), ' ');
+            line.append(' ').append(query.getWarnTimeLimit());
+        }
+        if (query.getMemoryLimit())
+        {
+            if (line.length() < 48)
+                line.appendN(48 - line.length(), ' ');
+            line.append(' ').append(query.getMemoryLimit());
         }
         fputs(line.append('\n').str(), stdout);
     }
@@ -203,8 +206,10 @@ public:
         ActiveQueryMap queryMap(qs);
         if (qs.getQuerySetName())
             fprintf(stdout, "\nQuerySet: %s\n", qs.getQuerySetName());
-        fputs("\nFlags Query Id                     [Active Name(s)]\n", stdout);
-        fputs("----- ---------------------------- ----------------\n", stdout);
+        fputs("\n", stdout);
+        fputs("                                   Time   Warn   Memory\n", stdout);
+        fputs("Flags Query Id                     Limit  Limit  Limit\n", stdout);
+        fputs("----- ---------------------------- ------ ------ ----------\n", stdout);
 
         IArrayOf<IConstQuerySetQuery> &queries = qs.getQueries();
         ForEachItemIn(id, queries)
@@ -269,6 +274,8 @@ class EclCmdQueriesCopy : public EclCmdCommon
 public:
     EclCmdQueriesCopy() : optActivate(false), optNoReload(false), optMsToWait(10000), optDontCopyFiles(false), optOverwrite(false)
     {
+        optTimeLimit = (unsigned) -1;
+        optWarnTimeLimit = (unsigned) -1;
     }
     virtual bool parseCommandLineOptions(ArgvIterator &iter)
     {
@@ -308,6 +315,12 @@ public:
                 continue;
             if (iter.matchOption(optMsToWait, ECLOPT_WAIT))
                 continue;
+            if (iter.matchOption(optTimeLimit, ECLOPT_TIME_LIMIT))
+                continue;
+            if (iter.matchOption(optWarnTimeLimit, ECLOPT_WARN_TIME_LIMIT))
+                continue;
+            if (iter.matchOption(optMemoryLimit, ECLOPT_MEMORY_LIMIT))
+                continue;
             if (EclCmdCommon::matchCommandLineOption(iter, true)!=EclCmdOptionMatch)
                 return false;
         }
@@ -327,6 +340,12 @@ public:
             fputs("cluster must be specified for remote copies.\n\n", stderr);
             return false;
         }
+        if (optMemoryLimit.length() && !isValidMemoryValue(optMemoryLimit))
+        {
+            fprintf(stderr, "invalid --memoryLimit value of %s.\n\n", optMemoryLimit.get());
+            return false;
+        }
+
         return true;
     }
 
@@ -349,6 +368,13 @@ public:
         req->setWait(optMsToWait);
         req->setNoReload(optNoReload);
 
+        if (optTimeLimit != (unsigned) -1)
+            req->setTimeLimit(optTimeLimit);
+        if (optWarnTimeLimit != (unsigned) -1)
+            req->setWarnTimeLimit(optWarnTimeLimit);
+        if (!optMemoryLimit.isEmpty())
+            req->setMemoryLimit(optMemoryLimit);
+
         Owned<IClientWUQuerySetCopyQueryResponse> resp = client->WUQuerysetCopyQuery(req);
         if (resp->getExceptions().ordinality())
             outputMultiExceptions(resp->getExceptions());
@@ -383,6 +409,10 @@ public:
             "   --no-reload            Do not request a reload of the (roxie) cluster\n"
             "   -O, --overwrite        Overwrite existing files\n"
             "   --wait=<ms>            Max time to wait in milliseconds\n"
+            "   --timeLimit=<sec>      Value to set for query timeLimit configuration\n"
+            "   --warnTimeLimit=<sec>  Value to set for query warnTimeLimit configuration\n"
+            "   --memoryLimit=<mem>    Value to set for query memoryLimit configuration\n"
+            "                          format <mem> as 500000B, 550K, 100M, 10G, 1T etc.\n"
             " Common Options:\n",
             stdout);
         EclCmdCommon::usage();
@@ -392,19 +422,152 @@ private:
     StringAttr optTargetQuerySet;
     StringAttr optTargetCluster;
     StringAttr optDaliIP;
+    StringAttr optMemoryLimit;
     unsigned optMsToWait;
+    unsigned optTimeLimit;
+    unsigned optWarnTimeLimit;
     bool optActivate;
     bool optNoReload;
     bool optOverwrite;
     bool optDontCopyFiles;
 };
 
+class EclCmdQueriesConfig : public EclCmdCommon
+{
+public:
+    EclCmdQueriesConfig() : optNoReload(false), optMsToWait(10000)
+    {
+        optTimeLimit = (unsigned) -1;
+        optWarnTimeLimit = (unsigned) -1;
+    }
+    virtual bool parseCommandLineOptions(ArgvIterator &iter)
+    {
+        if (iter.done())
+        {
+            usage();
+            return false;
+        }
+
+        for (; !iter.done(); iter.next())
+        {
+            const char *arg = iter.query();
+            if (*arg!='-')
+            {
+                if (optTargetCluster.isEmpty())
+                    optTargetCluster.set(arg);
+                else if (optQueryId.isEmpty())
+                    optQueryId.set(arg);
+                else
+                {
+                    fprintf(stderr, "\nunrecognized argument %s\n", arg);
+                    return false;
+                }
+                continue;
+            }
+            if (iter.matchFlag(optNoReload, ECLOPT_NORELOAD))
+                continue;
+            if (iter.matchOption(optMsToWait, ECLOPT_WAIT))
+                continue;
+            if (iter.matchOption(optTimeLimit, ECLOPT_TIME_LIMIT))
+                continue;
+            if (iter.matchOption(optWarnTimeLimit, ECLOPT_WARN_TIME_LIMIT))
+                continue;
+            if (iter.matchOption(optMemoryLimit, ECLOPT_MEMORY_LIMIT))
+                continue;
+            if (EclCmdCommon::matchCommandLineOption(iter, true)!=EclCmdOptionMatch)
+                return false;
+        }
+        return true;
+    }
+    virtual bool finalizeOptions(IProperties *globals)
+    {
+        if (!EclCmdCommon::finalizeOptions(globals))
+            return false;
+        if (optTargetCluster.isEmpty() || optQueryId.isEmpty())
+        {
+            fputs("Target and QueryId must both be specified.\n\n", stderr);
+            return false;
+        }
+        if (optMemoryLimit.length() && !isValidMemoryValue(optMemoryLimit))
+        {
+            fprintf(stderr, "invalid --memoryLimit value of %s.\n\n", optMemoryLimit.get());
+            return false;
+        }
+        return true;
+    }
+
+    virtual int processCMD()
+    {
+        Owned<IClientWsWorkunits> client = createWsWorkunitsClient();
+        VStringBuffer url("http://%s:%s/WsWorkunits", optServer.sget(), optPort.sget());
+        client->addServiceUrl(url.str());
+        if (optUsername.length())
+            client->setUsernameToken(optUsername.get(), optPassword.sget(), NULL);
+
+        Owned<IClientWUQueryConfigRequest> req = client->createWUQueryConfigRequest();
+        req->setTarget(optTargetCluster.get());
+        req->setQueryId(optQueryId.get());
+        req->setWait(optMsToWait);
+        req->setNoReload(optNoReload);
+
+        if (optTimeLimit != (unsigned) -1)
+            req->setTimeLimit(optTimeLimit);
+        if (optWarnTimeLimit != (unsigned) -1)
+            req->setWarnTimeLimit(optWarnTimeLimit);
+        if (!optMemoryLimit.isEmpty())
+            req->setMemoryLimit(optMemoryLimit);
+
+        Owned<IClientWUQueryConfigResponse> resp = client->WUQueryConfig(req);
+        if (resp->getExceptions().ordinality())
+            outputMultiExceptions(resp->getExceptions());
+        IArrayOf<IConstWUQueryConfigResult> &results = resp->getResults();
+        if (results.length())
+        {
+            fputs("configured:\n", stdout);
+            ForEachItemIn(i, results)
+                fprintf(stdout, "   %s\n", results.item(i).getQueryId());
+        }
+        return 0;
+    }
+    virtual void usage()
+    {
+        fputs("\nUsage:\n"
+            "\n"
+            "The 'queries config' command updates query configuration values.\n"
+            "\n"
+            "ecl queries config <target> <queryid> [options]\n"
+            "\n"
+            " Options:\n"
+            "   <target>               Name of target queryset containing query\n"
+            "   <queryid>              Id of the query to configure\n"
+            "   --no-reload            Do not request a reload of the (roxie) cluster\n"
+            "   --wait=<ms>            Max time to wait in milliseconds\n"
+            "   --timeLimit=<sec>      Value to set for query timeLimit configuration\n"
+            "   --warnTimeLimit=<sec>  Value to set for query warnTimeLimit configuration\n"
+            "   --memoryLimit=<mem>    Value to set for query memoryLimit configuration\n"
+            "                          format <mem> as 500000B, 550K, 100M, 10G, 1T etc.\n"
+            " Common Options:\n",
+            stdout);
+        EclCmdCommon::usage();
+    }
+private:
+    StringAttr optTargetCluster;
+    StringAttr optQueryId;
+    StringAttr optMemoryLimit;
+    unsigned optMsToWait;
+    unsigned optTimeLimit;
+    unsigned optWarnTimeLimit;
+    bool optNoReload;
+};
+
 IEclCommand *createEclQueriesCommand(const char *cmdname)
 {
     if (!cmdname || !*cmdname)
         return NULL;
     if (strieq(cmdname, "list"))
         return new EclCmdQueriesList();
+    if (strieq(cmdname, "config"))
+        return new EclCmdQueriesConfig();
     if (strieq(cmdname, "copy"))
         return new EclCmdQueriesCopy();
     return NULL;
@@ -426,6 +589,7 @@ public:
             "ecl queries <command> [command options]\n\n"
             "   Queries Commands:\n"
             "      list         list queries in queryset(s)\n"
+            "      config       update query settings\n"
             "      copy         copy a query from one queryset to another\n"
         );
     }

+ 35 - 3
esp/scm/ws_workunits.ecm

@@ -1053,7 +1053,7 @@ ESPresponse [exceptions_inline] WUCopyLogicalFilesResponse
 };
 
 
-ESPrequest WUPublishWorkunitRequest
+ESPrequest [nil_remove] WUPublishWorkunitRequest
 {
     string Wuid;
     string Cluster;
@@ -1063,6 +1063,9 @@ ESPrequest WUPublishWorkunitRequest
     int Wait(10000);
     bool NoReload(0);
     bool UpdateWorkUnitName(0);
+    string memoryLimit;
+    nonNegativeInteger TimeLimit(0);
+    nonNegativeInteger WarnTimeLimit(0);
 };
 
 ESPresponse [exceptions_inline] WUPublishWorkunitResponse
@@ -1076,6 +1079,28 @@ ESPresponse [exceptions_inline] WUPublishWorkunitResponse
     ESParray<ESPStruct WUCopyLogicalClusterFileSections, Cluster> ClusterFiles;
 };
 
+ESPrequest [nil_remove] WUQueryConfigRequest
+{
+    string Target;
+    string QueryId;
+    int Wait(10000);
+    bool NoReload(0);
+    string memoryLimit;
+    nonNegativeInteger TimeLimit(0);
+    nonNegativeInteger WarnTimeLimit(0);
+};
+
+ESPStruct WUQueryConfigResult
+{
+    string  QueryId;
+};
+
+ESPresponse [exceptions_inline] WUQueryConfigResponse
+{
+    bool ReloadFailed;
+    ESParray<ESPStruct WUQueryConfigResult, Result> Results;
+};
+
 
 ESPStruct QuerySet
 {
@@ -1098,7 +1123,7 @@ ESPStruct ClusterQueryState
     string State;
 };
 
-ESPStruct QuerySetQuery
+ESPStruct [nil_remove] QuerySetQuery
 {
     string Id;
     string Name;
@@ -1106,6 +1131,9 @@ ESPStruct QuerySetQuery
     string Dll;
     bool Suspended;
     ESParray<ESPstruct ClusterQueryState> Clusters;
+    string memoryLimit;
+    nonNegativeInteger timeLimit;
+    nonNegativeInteger warnTimeLimit;
 };
 
 ESPStruct QuerySetAlias
@@ -1241,7 +1269,7 @@ ESPresponse [exceptions_inline] WUQuerySetAliasActionResponse
     ESParray<ESPstruct QuerySetAliasActionResult, Result> Results;
 };
 
-ESPrequest WUQuerySetCopyQueryRequest
+ESPrequest [nil_remove] WUQuerySetCopyQueryRequest
 {
     string Source;
     string Target;
@@ -1252,6 +1280,9 @@ ESPrequest WUQuerySetCopyQueryRequest
     bool DontCopyFiles(false);
     int Wait(10000);
     bool NoReload(0);
+    string memoryLimit;
+    nonNegativeInteger TimeLimit(0);
+    nonNegativeInteger WarnTimeLimit(0);
 };
 
 ESPresponse [exceptions_inline] WUQuerySetCopyQueryResponse
@@ -1325,6 +1356,7 @@ ESPservice [
     ESPmethod WUQuerysetAliasAction(WUQuerySetAliasActionRequest, WUQuerySetAliasActionResponse);
     ESPmethod WUQuerysetCopyQuery(WUQuerySetCopyQueryRequest, WUQuerySetCopyQueryResponse);
     ESPmethod [resp_xsl_default("/esp/xslt/WUCopyLogicalFiles.xslt")] WUCopyLogicalFiles(WUCopyLogicalFilesRequest, WUCopyLogicalFilesResponse);
+    ESPmethod WUQueryConfig(WUQueryConfigRequest, WUQueryConfigResponse);
 };
 
 

+ 162 - 2
esp/services/ws_workunits/ws_workunitsQuerySets.cpp

@@ -298,6 +298,88 @@ bool reloadCluster(const char *cluster, unsigned wait)
     return (clusterInfo) ? reloadCluster(clusterInfo, wait) : true;
 }
 
+static inline void updateQuerySetting(bool ignore, IPropertyTree *queryTree, const char *xpath, int value)
+{
+    if (ignore || !queryTree)
+        return;
+    if (value!=0)
+        queryTree->setPropInt(xpath, value);
+    else
+        queryTree->removeProp(xpath);
+}
+
+static inline unsigned __int64 memoryLimitUInt64FromString(const char *value)
+{
+    if (!value || !*value || !isdigit(*value))
+        return 0;
+    unsigned __int64 result = (*value - '0');
+    const char *s = value+1;
+    while (isdigit(*s))
+    {
+        result = 10 * result + ((*s) - '0');
+        s++;
+    }
+    if (*s)
+    {
+        const char unit = toupper(*s++);
+        if (*s && !strieq("B", s)) //more?
+            return 0;
+        switch (unit)
+        {
+            case 'E':
+                result <<=60;
+                break;
+            case 'P':
+                result <<=50;
+                break;
+            case 'T':
+                result <<=40;
+                break;
+            case 'G':
+                result <<=30;
+                break;
+            case 'M':
+                result <<=20;
+                break;
+            case 'K':
+                result <<=10;
+                break;
+            case 'B':
+                break;
+            default:
+                return 0;
+        }
+    }
+    return result;
+}
+
+const char memUnitAbbrev[] = {'B', 'K', 'M', 'G', 'T', 'P', 'E'};
+#define MAX_MEMUNIT_ABBREV 6
+
+static inline StringBuffer &memoryLimitStringFromUInt64(StringBuffer &s, unsigned __int64 in)
+{
+    if (!in)
+        return s;
+    unsigned __int64 value = in;
+    unsigned char unit = 0;
+    while (!(value & 0x3FF) && unit < MAX_MEMUNIT_ABBREV)
+    {
+        value >>= 10;
+        unit++;
+    }
+    return s.append(value).append(memUnitAbbrev[unit]);
+}
+
+static inline void updateMemoryLimitSetting(IPropertyTree *queryTree, const char *value)
+{
+    if (!value || !queryTree)
+        return;
+    unsigned __int64 limit = memoryLimitUInt64FromString(value);
+    if (0==limit)
+        queryTree->removeProp("@memoryLimit");
+    else
+        queryTree->setPropInt64("@memoryLimit", limit);
+}
 
 bool CWsWorkunitsEx::onWUPublishWorkunit(IEspContext &context, IEspWUPublishWorkunitRequest & req, IEspWUPublishWorkunitResponse & resp)
 {
@@ -343,7 +425,15 @@ bool CWsWorkunitsEx::onWUPublishWorkunit(IEspContext &context, IEspWUPublishWork
         wu->setJobName(req.getJobName());
 
     StringBuffer queryId;
-    addQueryToQuerySet(wu, target.str(), queryName.str(), NULL, (WUQueryActivationOptions)req.getActivate(), queryId);
+    WUQueryActivationOptions activate = (WUQueryActivationOptions)req.getActivate();
+    addQueryToQuerySet(wu, target.str(), queryName.str(), NULL, activate, queryId);
+    if (req.getMemoryLimit() || !req.getTimeLimit_isNull() || ! req.getWarnTimeLimit_isNull())
+    {
+        Owned<IPropertyTree> queryTree = getQueryById(target.str(), queryId, false);
+        updateMemoryLimitSetting(queryTree, req.getMemoryLimit());
+        updateQuerySetting(req.getTimeLimit_isNull(), queryTree, "@timeLimit", req.getTimeLimit());
+        updateQuerySetting(req.getWarnTimeLimit_isNull(), queryTree, "@warnTimeLimit", req.getWarnTimeLimit());
+    }
     wu->commit();
     wu.clear();
 
@@ -383,6 +473,16 @@ void gatherQuerySetQueryDetails(IPropertyTree *query, IEspQuerySetQuery *queryIn
     queryInfo->setDll(query->queryProp("@dll"));
     queryInfo->setWuid(query->queryProp("@wuid"));
     queryInfo->setSuspended(query->getPropBool("@suspended", false));
+    if (query->hasProp("@memoryLimit"))
+    {
+        StringBuffer s;
+        memoryLimitStringFromUInt64(s, query->getPropInt64("@memoryLimit"));
+        queryInfo->setMemoryLimit(s);
+    }
+    if (query->hasProp("@timeLimit"))
+        queryInfo->setTimeLimit(query->getPropInt("@timeLimit"));
+    if (query->hasProp("@warnTimeLimit"))
+        queryInfo->setWarnTimeLimit(query->getPropInt("@warnTimeLimit"));
     if (queriesOnCluster)
     {
         IArrayOf<IEspClusterQueryState> clusters;
@@ -675,6 +775,58 @@ void expandQueryActionTargetList(IProperties *queryIds, IPropertyTree *queryset,
     }
 }
 
+void expandQueryActionTargetList(IProperties *queryIds, IPropertyTree *queryset, const char *id, CQuerySetQueryActionTypes action)
+{
+    IArrayOf<IConstQuerySetQueryActionItem> items;
+    Owned<IEspQuerySetQueryActionItem> item = createQuerySetQueryActionItem();
+    item->setQueryId(id);
+    items.append(*(IConstQuerySetQueryActionItem*)item.getClear());
+    expandQueryActionTargetList(queryIds, queryset, items, action);
+}
+
+bool CWsWorkunitsEx::onWUQueryConfig(IEspContext &context, IEspWUQueryConfigRequest & req, IEspWUQueryConfigResponse & resp)
+{
+    StringAttr target(req.getTarget());
+    if (target.isEmpty())
+        throw MakeStringException(ECLWATCH_MISSING_PARAMS, "Target name required");
+    if (!isValidCluster(target))
+        throw MakeStringException(ECLWATCH_INVALID_CLUSTER_NAME, "Invalid target name: %s", target.get());
+
+    Owned<IPropertyTree> queryset = getQueryRegistry(target.get(), false);
+    if (!queryset)
+        throw MakeStringException(ECLWATCH_QUERYSET_NOT_FOUND, "Target Queryset %s not found", req.getTarget());
+
+    Owned<IProperties> queryIds = createProperties();
+    expandQueryActionTargetList(queryIds, queryset, req.getQueryId(), QuerySetQueryActionTypes_Undefined);
+
+    IArrayOf<IEspWUQueryConfigResult> results;
+    Owned<IPropertyIterator> it = queryIds->getIterator();
+    ForEach(*it)
+    {
+        Owned<IEspWUQueryConfigResult> result = createWUQueryConfigResult();
+        result->setQueryId(it->getPropKey());
+
+        VStringBuffer xpath("Query[@id='%s']", it->getPropKey());
+        IPropertyTree *queryTree = queryset->queryPropTree(xpath);
+        if (queryTree)
+        {
+            updateMemoryLimitSetting(queryTree, req.getMemoryLimit());
+            updateQuerySetting(req.getTimeLimit_isNull(), queryTree, "@timeLimit", req.getTimeLimit());
+            updateQuerySetting(req.getWarnTimeLimit_isNull(), queryTree, "@warnTimeLimit", req.getWarnTimeLimit());
+        }
+
+        results.append(*result.getClear());
+    }
+    resp.setResults(results);
+
+    bool reloadFailed = false;
+    if (0!=req.getWait() && !req.getNoReload())
+        reloadFailed = !reloadCluster(target.get(), (unsigned)req.getWait());
+    resp.setReloadFailed(reloadFailed);
+
+    return true;
+}
+
 bool CWsWorkunitsEx::onWUQuerysetQueryAction(IEspContext &context, IEspWUQuerySetQueryActionRequest & req, IEspWUQuerySetQueryActionResponse & resp)
 {
     resp.setQuerySetName(req.getQuerySetName());
@@ -898,7 +1050,15 @@ bool CWsWorkunitsEx::onWUQuerysetCopyQuery(IEspContext &context, IEspWUQuerySetC
         throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT, "Error opening wuid %s for query %s", wuid.str(), source);
 
     StringBuffer targetQueryId;
-    addQueryToQuerySet(wu, target, queryName.str(), NULL, (WUQueryActivationOptions)req.getActivate(), targetQueryId);
+    WUQueryActivationOptions activate = (WUQueryActivationOptions)req.getActivate();
+    addQueryToQuerySet(wu, target, queryName.str(), NULL, activate, targetQueryId);
+    if (req.getMemoryLimit() || !req.getTimeLimit_isNull() || ! req.getWarnTimeLimit_isNull())
+    {
+        Owned<IPropertyTree> queryTree = getQueryById(target, targetQueryId, false);
+        updateMemoryLimitSetting(queryTree, req.getMemoryLimit());
+        updateQuerySetting(req.getTimeLimit_isNull(), queryTree, "@timeLimit", req.getTimeLimit());
+        updateQuerySetting(req.getWarnTimeLimit_isNull(), queryTree, "@warnTimeLimit", req.getWarnTimeLimit());
+    }
     wu.clear();
 
     resp.setQueryId(targetQueryId.str());

+ 1 - 0
esp/services/ws_workunits/ws_workunitsService.hpp

@@ -49,6 +49,7 @@ public:
     bool onWUMultiQuerysetDetails(IEspContext &context, IEspWUMultiQuerySetDetailsRequest &req, IEspWUMultiQuerySetDetailsResponse &resp);
     bool onWUQuerysetQueryAction(IEspContext &context, IEspWUQuerySetQueryActionRequest & req, IEspWUQuerySetQueryActionResponse & resp);
     bool onWUQuerysetAliasAction(IEspContext &context, IEspWUQuerySetAliasActionRequest &req, IEspWUQuerySetAliasActionResponse &resp);
+    bool onWUQueryConfig(IEspContext &context, IEspWUQueryConfigRequest &req, IEspWUQueryConfigResponse &resp);
     bool onWUQuerysetCopyQuery(IEspContext &context, IEspWUQuerySetCopyQueryRequest &req, IEspWUQuerySetCopyQueryResponse &resp);
     bool onWUCopyLogicalFiles(IEspContext &context, IEspWUCopyLogicalFilesRequest &req, IEspWUCopyLogicalFilesResponse &resp);
 

+ 4 - 2
esp/xslt/ui_configmgr.xslt

@@ -218,8 +218,10 @@
               <i>
                 <h3>
                   <script type="text/javascript">
-                    <!--document.body.style.cursor='wait';-->
-                    document.write('<xsl:value-of select="$Component"/>');
+                    if (top.document.navDT.getRecordIndex(top.document.navDT.getSelectedRows()[0]) == 0)
+                      document.write("XML View");
+                    else
+                      document.write('<xsl:value-of select="$Component"/>');
                   </script>
                 </h3>
               </i>

+ 2 - 2
initfiles/bash/etc/init.d/hpcc_common.in

@@ -382,7 +382,7 @@ createRuntime() {
     chown -cR $user:$group "${dir_return}"  1> /dev/null 2>/dev/null
 
     # setting up ulimit for thor and other component which needs it.
-    ulimit -n 8192
+    ulimit -n 32768
     ulimit -c unlimited
 
 }
@@ -402,7 +402,7 @@ start_dafilesrv() {
 
       noStatusCheck=1
       /etc/init.d/dafilesrv setup 1>/dev/null 2>/dev/null
-      ulimit -n 8192
+      ulimit -n 32768
       ulimit -c unlimited
       startCmd ${compName} ${noStatusCheck}
       return $?

+ 1 - 1
initfiles/bash/etc/init.d/install-init.in

@@ -198,7 +198,7 @@ if [ -d ${INSTALL_DIR}/etc/bash_completion.d ] && [ -d /etc/bash_completion.d ];
 fi
 
 # Ubuntu Unity Launcher
-if [ -d ${INSTALL_DIR}/share/hpcc-systems.desktop ] && [ -d /usr/share/applications ]; then
+if [ -f ${INSTALL_DIR}/share/hpcc-systems.desktop ] && [ -d /usr/share/applications ]; then
     installFile ${INSTALL_DIR}/share/hpcc-systems.desktop /usr/share/applications 1 || exit 1
 fi
 

+ 4 - 1
initfiles/bin/init_dafilesrv.in

@@ -32,6 +32,9 @@ PID_NAME="$PID/`basename $PWD`.pid"
 INIT_PID_NAME="$PID/init_`basename $PWD`.pid"
 echo $$ > $INIT_PID_NAME
 
+# this must match jsocket hard limit
+export handlelimit=32768
+
 export SENTINEL="dafilesrv.sentinel"
 rm -f ${SENTINEL}
 
@@ -41,7 +44,7 @@ killed(){
     sleep 2
     exit 255
 }
-
+ulimit -n $handlelimit
 trap "killed" SIGINT SIGTERM SIGKILL
 dafilesrv -L $log &
 echo $! > $PID_NAME

+ 1 - 1
initfiles/componentfiles/thor/run_thor

@@ -18,7 +18,7 @@
 thorpid=0
 
 ulimit -c unlimited
-ulimit -n 8192
+ulimit -n $handlelimit
 
 RUN_THOR_PID_NAME="$PID/run_thor.`basename $PWD`.pid"
 # prevent two thors starting together

+ 4 - 1
initfiles/componentfiles/thor/start_slave

@@ -33,6 +33,9 @@ if [ $# -lt 9 ]; then
   exit 1
 fi
 
+# this must match jsocket hard limit
+export handlelimit=32768
+
 sudo /etc/init.d/hpcc-init -c dafilesrv setup
 mkdir -p $instancedir
 mkdir -p `dirname $logredirect`
@@ -61,7 +64,7 @@ trap "rm -f $lckfile" exit
 echo $$ > $lckfile
 
 ulimit -c unlimited
-ulimit -n 8192
+ulimit -n $handlelimit
 
 echo "slave starting `date`"
 

+ 1 - 1
initfiles/componentfiles/thor/start_slaves

@@ -20,7 +20,7 @@ echo starting thorslaves ...
 
 if [ "$localthor" = "true" ]; then
         ulimit -c unlimited
-        ulimit -n 8192
+        ulimit -n $handlelimit
         let "n = 1";
         for slave in $(cat $instancedir/thorgroup); do
             slaveport=${slave/*:/}

+ 4 - 3
initfiles/componentfiles/thor/start_thor

@@ -27,7 +27,8 @@ source ${PATH_PRE} ""
 export PID_NAME="$PID/`basename $PWD`_master.pid" ## this needed when we use bash_init_system
 export PID_NAME_BASE="$PID/`basename $PWD`.pid"
 
-
+# this must match jsocket hard limit
+export handlelimit=32768
 
 # deploydir = where binaries and scripts live
 if [ -z "$deploydir" ]; then
@@ -44,8 +45,8 @@ $deploydir/stop_thor $deploydir
 
 # ----------------------------
 
-ulimit -n 8192
-if [ `ulimit -n` -lt 8192 ]; then
+ulimit -n $handlelimit
+if [ `ulimit -n` -lt $handlelimit ]; then
     echo 'ulimit -n failed, aborting start_thor (perhaps you are not logged is as super user?)'
     exit 0
 fi

+ 2 - 1
initfiles/sbin/add_conf_settings.sh.in

@@ -34,7 +34,8 @@ Defaults:${USER_NAME} !requiretty
 %EOF
 
 alter_file /etc/security/limits.conf "^${USER_NAME}" << %EOF
-${USER_NAME}    hard    nofile  8192
+${USER_NAME}    soft    nofile  8192
+${USER_NAME}    hard    nofile  32768
 ${USER_NAME}    soft  core  unlimited
 ${USER_NAME}    hard  core  unlimited
 %EOF

+ 1 - 1
system/jlib/jsocket.cpp

@@ -311,7 +311,7 @@ struct MCASTREQ
 #define BADSOCKERR(err) ((err==EBADF)||(err==ENOTSOCK))
 #define CHECKSOCKRANGE(s)
 #else
-#define XFD_SETSIZE 8192
+#define XFD_SETSIZE 32768
 struct xfd_set { __fd_mask fds_bits[XFD_SETSIZE / __NFDBITS]; }; // define our own
 // linux 64 bit
 #ifdef __linux__