Browse Source

Merge branch 'candidate-6.2.6' into candidate-6.4.0

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 8 years ago
parent
commit
ef461c6d76

+ 13 - 1
common/workunit/workunit.cpp

@@ -1668,6 +1668,10 @@ public:
     virtual IConstWUAssociatedFile * getAssociatedFile(WUFileType type, unsigned index) const;
     virtual IConstWUAssociatedFileIterator& getAssociatedFiles() const;
     virtual bool isArchive() const;
+    virtual bool hasArchive() const
+    {
+        return p->getPropBool("@hasArchive");
+    }
 
     virtual void        setQueryType(WUQueryType qt);
     virtual void        setQueryText(const char *pstr);
@@ -4391,12 +4395,13 @@ class CEnvironmentClusterInfo: implements IConstWUClusterInfo, public CInterface
     unsigned clusterWidth;
     unsigned roxieRedundancy;
     unsigned channelsPerNode;
+    unsigned numberOfSlaveLogs;
     int roxieReplicateOffset;
 
 public:
     IMPLEMENT_IINTERFACE;
     CEnvironmentClusterInfo(const char *_name, const char *_prefix, const char *_alias, IPropertyTree *agent, IArrayOf<IPropertyTree> &thors, IPropertyTree *roxie)
-        : name(_name), prefix(_prefix), alias(_alias), roxieRedundancy(0), channelsPerNode(0), roxieReplicateOffset(1)
+        : name(_name), prefix(_prefix), alias(_alias), roxieRedundancy(0), channelsPerNode(0), numberOfSlaveLogs(0), roxieReplicateOffset(1)
     {
         StringBuffer queue;
         if (thors.ordinality())
@@ -4423,6 +4428,7 @@ public:
                 unsigned slavesPerNode = thor.getPropInt("@slavesPerNode", 1);
                 unsigned channelsPerSlave = thor.getPropInt("@channelsPerSlave", 1);
                 unsigned ts = nodes * slavesPerNode * channelsPerSlave;
+                numberOfSlaveLogs = nodes * slavesPerNode;
                 if (clusterWidth && (ts!=clusterWidth)) 
                     throw MakeStringException(WUERR_MismatchClusterSize,"CEnvironmentClusterInfo: mismatched thor sizes in cluster");
                 clusterWidth = ts;
@@ -4511,6 +4517,10 @@ public:
     {
         return clusterWidth;
     }
+    unsigned getNumberOfSlaveLogs() const
+    {
+        return numberOfSlaveLogs;
+    }
     virtual ClusterType getPlatform() const
     {
         return platform;
@@ -7327,6 +7337,8 @@ void CLocalWUQuery::setQueryText(const char *text)
             p->setProp("ShortText", xml->queryProp("Query"));
     }
     p->setPropBool("@isArchive", isArchive);
+    if (isArchive)
+        p->setPropBool("@hasArchive", true); //preserved if setQueryText is called multiple times.  Should setting this be more explicit?
 }
 
 void CLocalWUQuery::setQueryName(const char *qname)

+ 2 - 0
common/workunit/workunit.hpp

@@ -415,6 +415,7 @@ interface IConstWUQuery : extends IInterface
     virtual IStringVal & getQueryShortText(IStringVal & str) const = 0;
     virtual IStringVal & getQueryMainDefinition(IStringVal & str) const = 0;
     virtual bool isArchive() const = 0;
+    virtual bool hasArchive() const = 0;
 };
 
 
@@ -540,6 +541,7 @@ interface IConstWUClusterInfo : extends IInterface
     virtual IStringVal & getScope(IStringVal & str) const = 0;
     virtual IStringVal & getThorQueue(IStringVal & str) const = 0;
     virtual unsigned getSize() const = 0;
+    virtual unsigned getNumberOfSlaveLogs() const = 0;
     virtual ClusterType getPlatform() const = 0;
     virtual IStringVal & getAgentQueue(IStringVal & str) const = 0;
     virtual IStringVal & getServerQueue(IStringVal & str) const = 0;

+ 14 - 0
common/wuwebview/wuwebview.cpp

@@ -337,6 +337,7 @@ public:
     void getResource(const char *name, StringBuffer &content, StringBuffer &abspath, const char *type);
     bool getResourceByPath(const char *path, MemoryBuffer &mb);
     StringBuffer &getManifest(StringBuffer &mf){return toXML(ensureManifest(), mf);}
+    IConstWUQuery* getEmbeddedQuery();
 
     void calculateResourceIncludePaths();
     virtual bool getInclude(const char *includename, MemoryBuffer &includebuf, bool &pathOnly);
@@ -921,6 +922,19 @@ void WuWebView::addInputsFromXml(const char *xml)
     addInputsFromPTree(pt.get());
 }
 
+IConstWUQuery* WuWebView::getEmbeddedQuery()
+{
+    if (!loadDll())
+        return NULL;
+
+    StringBuffer dllXML;
+    if (!getEmbeddedWorkUnitXML(dll, dllXML))
+        return NULL;
+
+    Owned<ILocalWorkUnit> embeddedWU = createLocalWorkUnit(dllXML.str());
+    return embeddedWU->getQuery();
+}
+
 extern WUWEBVIEW_API IWuWebView *createWuWebView(IConstWorkUnit &wu, const char *target, const char *queryname, const char *dir, bool mapEspDirectories)
 {
     try

+ 1 - 0
common/wuwebview/wuwebview.hpp

@@ -54,6 +54,7 @@ interface IWuWebView : extends IInterface
     virtual void createWuidResponse(StringBuffer &out, unsigned flags)=0;
     virtual bool getResourceByPath(const char *path, MemoryBuffer &mb)=0;
     virtual StringBuffer &getManifest(StringBuffer &mf)=0;
+    virtual IConstWUQuery* getEmbeddedQuery()=0;
 
 };
 

+ 1 - 1
dali/ft/filecopy.cpp

@@ -2705,7 +2705,7 @@ void FileSprayer::checkFilePath(RemoteFilename & filename)
             if (!dropZone)
             {
                 LOG(MCdebugInfo, unknownJob, "No matching drop zone path to file path: '%s'", pfilePath);
-                throwError1(DFTERR_NoMatchingDropzonePath, pfilePath);
+                // throwError1(DFTERR_NoMatchingDropzonePath, pfilePath);
             }
             else
             {

+ 19 - 6
ecl/hqlcpp/hqlhoist.cpp

@@ -102,6 +102,16 @@ void CHqlExprMultiGuard::combine(CHqlExprMultiGuard & other)
     }
 }
 
+
+static IHqlExpression * querySubset(IHqlExpression * newGuard, IHqlExpression * oldGuard)
+{
+    if (newGuard == oldGuard)
+        return newGuard;
+    if (newGuard->getOperator() == no_and)
+        return querySubset(newGuard->queryChild(0), oldGuard);
+    return nullptr;
+}
+
 void CHqlExprMultiGuard::combine(CHqlExprGuard & other)
 {
     ForEachItemIn(i, guarded)
@@ -109,12 +119,15 @@ void CHqlExprMultiGuard::combine(CHqlExprGuard & other)
         CHqlExprGuard & cur = guarded.item(i);
         if (cur.original == other.original)
         {
-            //condition is now (a || b)
-            OwnedHqlExpr newCond;
-            if (matchesBoolean(cur.guard, true) || matchesBoolean(other.guard, true))
-                newCond.set(queryBoolExpr(true));
-            else
-                newCond.setown(createBoolExpr(no_or, LINK(cur.guard), LINK(other.guard)));
+            LinkedHqlExpr newCond = querySubset(other.guard, cur.guard);
+            if (!newCond)
+            {
+                //condition is now (a || b)
+                if (matchesBoolean(cur.guard, true) || matchesBoolean(other.guard, true))
+                    newCond.set(queryBoolExpr(true));
+                else
+                    newCond.setown(createBoolExpr(no_or, LINK(cur.guard), LINK(other.guard)));
+            }
 
             //MORE: Could sometimes reuse the existing guard if this was created by this node
             Owned<CHqlExprGuard> newGuard = new CHqlExprGuard(newCond, cur.original, cur.guardContainsCandidate||other.guardContainsCandidate);

+ 1 - 1
esp/logging/loggingagent/espserverloggingagent/loggingagent.cpp

@@ -495,7 +495,7 @@ void CESPServerLoggingAgent::filterLogContent(IEspUpdateLogRequestWrap* req)
 
     StringBuffer updateLogRequestXML;
     toXML(updateLogRequestTree, updateLogRequestXML);
-    DBGLOG("filtered content and option: <%s>", updateLogRequestXML.str());
+    ESPLOG(LogMax, "filtered content and option: <%s>", updateLogRequestXML.str());
     req->clearOriginalContent();
     req->setUpdateLogRequest(updateLogRequestXML.str());
 }

+ 5 - 2
esp/logging/logginglib/loggingagentbase.cpp

@@ -91,6 +91,7 @@ bool CDBLogAgentBase::getTransactionSeed(IEspGetTransactionSeedRequest& req, IEs
 
 bool CDBLogAgentBase::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp)
 {
+    unsigned startTime = (getEspLogLevel()>=LogNormal) ? msTick() : 0;
     bool ret = false;
     try
     {
@@ -120,10 +121,11 @@ bool CDBLogAgentBase::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResp
             if(!buildUpdateLogStatement(logRequestTree, logDB.str(), table, logID, updateDBStatement))
                 throw MakeStringException(EspLoggingErrors::UpdateLogFailed, "Failed in creating SQL statement.");
 
-            if (getEspLogLevel() >= LogMax)
-                DBGLOG("UpdateLog: %s\n", updateDBStatement.str());
+            ESPLOG(LogNormal, "LAgent UpdateLog BuildStat %d done: %dms\n", i, msTick() -  startTime);
+            ESPLOG(LogMax, "UpdateLog: %s\n", updateDBStatement.str());
 
             executeUpdateLogStatement(updateDBStatement);
+            ESPLOG(LogNormal, "LAgent UpdateLog ExecStat %d done: %dms\n", i, msTick() -  startTime);
         }
         resp.setStatusCode(0);
         ret = true;
@@ -137,6 +139,7 @@ bool CDBLogAgentBase::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResp
         resp.setStatusCode(-1);
         resp.setStatusMessage(errorMessage.str());
     }
+    ESPLOG(LogNormal, "LAgent UpdateLog total=%dms\n", msTick() -  startTime);
     return ret;
 }
 

+ 22 - 5
esp/logging/logginglib/logthread.cpp

@@ -83,8 +83,8 @@ CLogThread::CLogThread(IPropertyTree* _cfg , const char* _service, const char* _
     maxLogQueueLength = _cfg->getPropInt(PropMaxLogQueueLength, MaxLogQueueLength);
     signalGrowingQueueAt = _cfg->getPropInt(PropQueueSizeSignal, QueueSizeSignal);
     maxLogRetries = _cfg->getPropInt(PropMaxTriesRS, DefaultMaxTriesRS);
-    failSafeLogging = _cfg->getPropBool(PropFailSafe);
-    if(failSafeLogging)
+    ensureFailSafe = _cfg->getPropBool(PropFailSafe);
+    if(ensureFailSafe)
     {
         const char * logsDir = _cfg->queryProp(PropFailSafeLogsDir);
         if (!logsDir || !*logsDir)
@@ -155,7 +155,9 @@ bool CLogThread::queueLog(IEspUpdateLogRequest* logRequest)
 
 bool CLogThread::queueLog(IEspUpdateLogRequestWrap* logRequest)
 {
+    unsigned startTime = (getEspLogLevel()>=LogNormal) ? msTick() : 0;
     logAgent->filterLogContent(logRequest);
+    ESPLOG(LogNormal, "LThread:filterLog: %dms\n", msTick() -  startTime);
     return enqueue(logRequest);
 }
 
@@ -164,10 +166,12 @@ bool CLogThread::enqueue(IEspUpdateLogRequestWrap* logRequest)
     if (logFailSafe.get())
     {
         StringBuffer GUID, reqBuf;
+        unsigned startTime = (getEspLogLevel()>=LogNormal) ? msTick() : 0;
         logFailSafe->GenerateGUID(GUID, NULL);
         logRequest->setGUID(GUID.str());
         if (serializeLogRequestContent(logRequest, reqBuf))
             logFailSafe->Add(GUID, reqBuf.str());
+        ESPLOG(LogNormal, "LThread:addToFailSafe: %dms\n", msTick() -  startTime);
     }
 
     writeJobQueue(logRequest);
@@ -192,11 +196,12 @@ void CLogThread::sendLog()
                 break;
 
             const char* GUID= logRequest->getGUID();
-            if ((!GUID || !*GUID) && failSafeLogging && logFailSafe.get())
+            if ((!GUID || !*GUID) && ensureFailSafe && logFailSafe.get())
                 continue;
 
             try
             {
+                unsigned startTime = (getEspLogLevel()>=LogNormal) ? msTick() : 0;
                 Owned<IEspUpdateLogResponse> logResponse = createUpdateLogResponse();
                 logAgent->updateLog(*logRequest, *logResponse);
                 if (!logResponse)
@@ -209,9 +214,14 @@ void CLogThread::sendLog()
                     else
                         throw MakeStringException(EspLoggingErrors::UpdateLogFailed, "Unknown error");
                 }
+                ESPLOG(LogNormal, "LThread:updateLog: %dms\n", msTick() -  startTime);
 
-                if(failSafeLogging && logFailSafe.get())
+                if(ensureFailSafe && logFailSafe.get())
+                {
+                    unsigned startTime1 = (getEspLogLevel()>=LogNormal) ? msTick() : 0;
                     logFailSafe->AddACK(GUID);
+                    ESPLOG(LogNormal, "LThread:AddACK: %dms\n", msTick() -  startTime1);
+                }
                 logRequest->Release();//Make sure that no data (such as GUID) is needed before releasing the logRequest.
             }
             catch(IException* e)
@@ -235,7 +245,7 @@ void CLogThread::sendLog()
                 }
                 if (!willRetry)
                 {
-                    if(failSafeLogging && logFailSafe.get())
+                    if(ensureFailSafe && logFailSafe.get())
                         logFailSafe->AddACK(GUID);
                     logRequest->Release();
                 }
@@ -288,6 +298,7 @@ void CLogThread::checkRollOver()
             return;
 
         ESPLOG(LogMax, "writing %d requests in the queue to the rolled over tank file.", numNewArrivals);
+        unsigned startTime = (getEspLogLevel()>=LogNormal) ? msTick() : 0;
         for(unsigned i = 0; i < numNewArrivals; i++)
         {
             IInterface* pRequest = logQueue.item(i);
@@ -303,6 +314,7 @@ void CLogThread::checkRollOver()
             if(GUID && *GUID && serializeLogRequestContent(pEspRequest, reqBuf))
                 logFailSafe->Add(GUID, reqBuf.str());
         }
+        ESPLOG(LogNormal, "LThread:AddFailSafe: %dms\n", msTick() -  startTime);
     }
     catch(IException* Ex)
     {
@@ -405,7 +417,10 @@ void CLogThread::writeJobQueue(IEspUpdateLogRequestWrap* jobToWrite)
 {
     if (jobToWrite)
     {
+        unsigned startTime = (getEspLogLevel()>=LogNormal) ? msTick() : 0;
         CriticalBlock b(logQueueCrit);
+        ESPLOG(LogNormal, "LThread:waitWQ: %dms\n", msTick() -  startTime);
+
         int QueueSize = logQueue.ordinality();
         if(QueueSize > maxLogQueueLength)
             ERRLOG("LOGGING QUEUE SIZE %d EXECEEDED MaxLogQueueLength %d, check the logging server.",QueueSize, maxLogQueueLength);
@@ -419,6 +434,8 @@ void CLogThread::writeJobQueue(IEspUpdateLogRequestWrap* jobToWrite)
 
 IEspUpdateLogRequestWrap* CLogThread::readJobQueue()
 {
+    unsigned startTime = (getEspLogLevel()>=LogNormal) ? msTick() : 0;
     CriticalBlock b(logQueueCrit);
+    ESPLOG(LogNormal, "LThread:waitRQ: %dms\n", msTick() -  startTime);
     return (IEspUpdateLogRequestWrap*)logQueue.dequeue();
 }

+ 1 - 1
esp/logging/logginglib/logthread.hpp

@@ -51,7 +51,7 @@ class CLogThread : public Thread , implements IUpdateLogThread
     CriticalSection logQueueCrit;
     Semaphore       m_sem;
 
-    bool failSafeLogging;
+    bool ensureFailSafe;
     Owned<ILogFailSafe> logFailSafe;
     struct tm         m_startTime;
 

+ 8 - 6
esp/logging/loggingmanager/loggingmanager.cpp

@@ -83,7 +83,7 @@ IEspLogAgent* CLoggingManager::loadLoggingAgent(const char* name, const char* dl
     return (IEspLogAgent*) xproc();
 }
 
-bool CLoggingManager::updateLog(const char* option, const char* logContent, StringBuffer& status)
+bool CLoggingManager::updateLog(IEspContext& espContext, const char* option, const char* logContent, StringBuffer& status)
 {
     if (!initialized)
         throw MakeStringException(-1,"LoggingManager not initialized");
@@ -93,7 +93,7 @@ bool CLoggingManager::updateLog(const char* option, const char* logContent, Stri
     {
         Owned<IEspUpdateLogRequestWrap> req =  new CUpdateLogRequestWrap(NULL, option, logContent);
         Owned<IEspUpdateLogResponse> resp =  createUpdateLogResponse();
-        bRet = updateLog(*req, *resp, status);
+        bRet = updateLog(espContext, *req, *resp, status);
     }
     catch (IException* e)
     {
@@ -129,7 +129,7 @@ bool CLoggingManager::updateLog(const char* option, IEspContext& espContext, IPr
         Owned<IEspUpdateLogRequestWrap> req =  new CUpdateLogRequestWrap(NULL, option, espContextTree.getClear(), LINK(userContext), LINK(userRequest),
             backEndResp, userResp, logDatasets);
         Owned<IEspUpdateLogResponse> resp =  createUpdateLogResponse();
-        bRet = updateLog(*req, *resp, status);
+        bRet = updateLog(espContext, *req, *resp, status);
     }
     catch (IException* e)
     {
@@ -141,9 +141,9 @@ bool CLoggingManager::updateLog(const char* option, IEspContext& espContext, IPr
     return bRet;
 }
 
-bool CLoggingManager::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp, StringBuffer& status)
+bool CLoggingManager::updateLog(IEspContext& espContext, IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp, StringBuffer& status)
 {
-    bool bRet = updateLog(req, resp);
+    bool bRet = updateLog(espContext, req, resp);
     if (bRet)
         status.set("Log request has been sent.");
     else
@@ -157,7 +157,7 @@ bool CLoggingManager::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResp
     return bRet;
 }
 
-bool CLoggingManager::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp)
+bool CLoggingManager::updateLog(IEspContext& espContext, IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp)
 {
     if (!initialized)
         throw MakeStringException(-1,"LoggingManager not initialized");
@@ -165,6 +165,7 @@ bool CLoggingManager::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResp
     bool bRet = false;
     try
     {
+        espContext.addTraceSummaryTimeStamp("LMgr:startQLog");
         for (unsigned int x = 0; x < loggingAgentThreads.size(); x++)
         {
             IUpdateLogThread* loggingThread = loggingAgentThreads[x];
@@ -174,6 +175,7 @@ bool CLoggingManager::updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResp
                 bRet = true;
             }
         }
+        espContext.addTraceSummaryTimeStamp("LMgr:endQLog");
     }
     catch (IException* e)
     {

+ 2 - 2
esp/logging/loggingmanager/loggingmanager.h

@@ -28,10 +28,10 @@
 interface ILoggingManager : implements IInterface
 {
     virtual bool init(IPropertyTree* loggingConfig, const char* service) = 0;
-    virtual bool updateLog(const char* option, const char* logContent, StringBuffer& status) = 0;
+    virtual bool updateLog(IEspContext& espContext, const char* option, const char* logContent, StringBuffer& status) = 0;
     virtual bool updateLog(const char* option, IEspContext& espContext, IPropertyTree* userContext, IPropertyTree* userRequest,
         const char* backEndResp, const char* userResp, const char* logDatasets, StringBuffer& status) = 0;
-    virtual bool updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp) = 0;
+    virtual bool updateLog(IEspContext& espContext, IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp) = 0;
     virtual bool getTransactionSeed(StringBuffer& transactionSeed, StringBuffer& status) = 0;
     virtual bool getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp) = 0;
     virtual bool getTransactionID(StringAttrMapping* transFields, StringBuffer& transactionID, StringBuffer& status) = 0;

+ 3 - 3
esp/logging/loggingmanager/loggingmanager.hpp

@@ -39,7 +39,7 @@ class CLoggingManager : implements ILoggingManager, public CInterface
     bool initialized;
 
     IEspLogAgent* loadLoggingAgent(const char* name, const char* dll, const char* type, IPropertyTree* cfg);
-    bool updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp, StringBuffer& status);
+    bool updateLog(IEspContext& espContext, IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp, StringBuffer& status);
 
 public:
     IMPLEMENT_IINTERFACE;
@@ -51,8 +51,8 @@ public:
 
     virtual bool updateLog(const char* option, IEspContext& espContext, IPropertyTree* userContext, IPropertyTree* userRequest,
         const char* backEndResp, const char* userResp, const char* logDatasets, StringBuffer& status);
-    virtual bool updateLog(const char* option, const char* logContent, StringBuffer& status);
-    virtual bool updateLog(IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp);
+    virtual bool updateLog(IEspContext& espContext, const char* option, const char* logContent, StringBuffer& status);
+    virtual bool updateLog(IEspContext& espContext, IEspUpdateLogRequestWrap& req, IEspUpdateLogResponse& resp);
     virtual bool getTransactionSeed(StringBuffer& transactionSeed, StringBuffer& status);
     virtual bool getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp);
     virtual bool getTransactionID(StringAttrMapping* transFields, StringBuffer& transactionID, StringBuffer& status);

+ 8 - 2
esp/logging/test/logging_test.cpp

@@ -136,7 +136,7 @@ void sendRequest()
         printf("userRespXML: <%s>.\n", userRespXML.str());
         printf("backEndResp: <%s>.\n", backEndResp);
 
-        //Sleep(5000); //Waiting for loggingManager to start
+        Sleep(5000); //Waiting for loggingManager to start
         loggingManager->updateLog(option.str(), *espContext, userContextTree, userRequestTree, backEndResp, userRespXML.str(), logDatasetsXML.str(), status);
     }
     else if (action.length() && strieq(action.str(), "UpdateLog1"))
@@ -151,7 +151,13 @@ void sendRequest()
         toXML(logContentTree, logContentXML);
         printf("log content: <%s>.\n", logContentXML.str());
         //Sleep(5000); //Waiting for loggingManager to start
-        loggingManager->updateLog(option.str(), logContentXML.str(), status);
+        Owned<IEspContext> espContext =  createEspContext();
+        const char* userName = logContentTree->queryProp("ESPContext/UserName");
+        const char* sourceIP = logContentTree->queryProp("ESPContext/SourceIP");
+        short servPort = logContentTree->getPropInt("ESPContext/Port");
+        espContext->setUserID(userName);
+        espContext->setServAddress(sourceIP, servPort);
+        loggingManager->updateLog(*espContext, option.str(), logContentXML.str(), status);
     }
     else
         printf("Invalid action.\n");

+ 20 - 7
esp/platform/espcontext.cpp

@@ -466,9 +466,6 @@ public:
     {
         if (m_txSummary)
         {
-            if (!m_hasException && (getEspLogLevel() <= LogNormal))
-                m_txSummary->clear();
-
             updateTraceSummaryHeader();
             m_txSummary->append("total", m_processingTime, "ms");
         }
@@ -586,12 +583,28 @@ void CEspContext::updateTraceSummaryHeader()
     if (m_txSummary)
     {
         m_txSummary->set("activeReqs", m_active);
-        m_txSummary->set("user", VStringBuffer("%s%s%s", (queryUserId() ? queryUserId() : ""), (m_peer.length() ? "@" : ""), m_peer.str()).str());
+        VStringBuffer user("%s%s%s", (queryUserId() ? queryUserId() : ""), (m_peer.length() ? "@" : ""), m_peer.str());
+        if (!user.isEmpty())
+            m_txSummary->set("user", user.str());
 
-        VStringBuffer reqSummury("%s %s.%s", httpMethod.get(), m_servName.str(), servMethod.get());
+        VStringBuffer reqSummary("%s", httpMethod.isEmpty() ? "" : httpMethod.get());
+        if (!m_servName.isEmpty() || !servMethod.isEmpty())
+        {
+            if (!reqSummary.isEmpty())
+                reqSummary.append(" ");
+            if (!m_servName.isEmpty())
+                reqSummary.append(m_servName.str());
+            if (!servMethod.isEmpty())
+                reqSummary.append(".").append(servMethod.str());
+        }
         if (m_clientVer > 0)
-            reqSummury.append(" v").append(m_clientVer);
-        m_txSummary->set("req", reqSummury.str());
+        {
+            if (!reqSummary.isEmpty())
+                reqSummary.append(" ");
+            reqSummary.append("v").append(m_clientVer);
+        }
+        if (!reqSummary.isEmpty())
+            m_txSummary->set("req", reqSummary.str());
 
         if (m_hasException)
             m_txSummary->set(VStringBuffer("exception@%ums", m_exceptionTime), m_exceptionCode);

+ 1 - 1
esp/platform/txsummary.cpp

@@ -143,7 +143,7 @@ void CTxSummary::serialize(StringBuffer& buffer) const
 
 void CTxSummary::log()
 {
-    if (size())
+    if (__contains("user") || __contains("req"))
     {
         StringBuffer summary;
         serialize(summary);

+ 6 - 6
esp/services/esdl_svc_engine/esdl_binding.cpp

@@ -34,6 +34,7 @@
 #include "workunit.hpp"
 #include "wuwebview.hpp"
 #include "build-config.h"
+#include "jsmartsock.ipp"
 
 #include "loggingagentbase.hpp"
 
@@ -432,6 +433,7 @@ void EsdlServiceImpl::configureUrlMethod(const char *method, IPropertyTree &entr
     entry.setProp("@path", path);
 
     Owned<ISmartSocketFactory> sf = createSmartSocketFactory(iplist, true);
+
     connMap.remove(method);
     connMap.setValue(method, sf.getClear());
 }
@@ -855,6 +857,7 @@ void EsdlServiceImpl::handleEchoTest(const char *mthName,
     else
         out.appendf("<%sResponse><ValueOut>%s</ValueOut></%sResponse>", mthName, valueIn && *valueIn ? valueIn : "", mthName);
 }
+
 void EsdlServiceImpl::generateTargetURL(IEspContext & context,
                                      IPropertyTree *srvinfo,
                                      StringBuffer & url,
@@ -866,8 +869,8 @@ void EsdlServiceImpl::generateTargetURL(IEspContext & context,
 
     StringBuffer name(srvinfo->queryProp("@name"));
 
-    ISmartSocketFactory *conn = connMap.getValue(name);
-    if (!conn)
+    ISmartSocketFactory *sconn = connMap.getValue(name);
+    if (!sconn)
         throw MakeStringException(-1, "Could not create smartsocket.");
 
     url.set(srvinfo->queryProp("@prot"));
@@ -875,10 +878,7 @@ void EsdlServiceImpl::generateTargetURL(IEspContext & context,
         url.append("HTTP");
     url.append("://");
 
-    SocketEndpoint ep;
-    ep = conn->nextEndpoint();
-
-    ep.getUrlStr(url);
+    sconn->getUrlStr(url, true);
 
     if(srvinfo->hasProp("@path"))  //Append the server path
     {

+ 2 - 0
esp/services/ws_loggingservice/loggingservice.cpp

@@ -85,6 +85,7 @@ bool CWsLoggingServiceEx::onUpdateLog(IEspContext& context, IEspUpdateLogRequest
         if (!context.validateFeatureAccess(WSLOGGING_ACCESS, SecAccess_Write, false))
             throw MakeStringException(EspLoggingErrors::WSLoggingAccessDenied, "Failed to update log. Permission denied.");
 
+        context.addTraceSummaryTimeStamp("startQLog");
         for (unsigned int x = 0; x < loggingAgentThreads.size(); x++)
         {
             IUpdateLogThread* loggingThread = loggingAgentThreads[x];
@@ -92,6 +93,7 @@ bool CWsLoggingServiceEx::onUpdateLog(IEspContext& context, IEspUpdateLogRequest
                 continue;
             loggingThread->queueLog(&req);
         }
+        context.addTraceSummaryTimeStamp("endQLog");
         resp.setStatusCode(0);
         resp.setStatusMessage("Log will be updated.");
     }

+ 24 - 4
esp/services/ws_workunits/ws_workunitsHelpers.cpp

@@ -514,7 +514,7 @@ void WsWuInfo::getHelpers(IEspECLWorkunit &info, unsigned flags)
 
             if (version > 1.30)
             {
-                info.setHasArchiveQuery(query->isArchive());
+                info.setHasArchiveQuery(query->hasArchive());
             }
 
             for (unsigned i = 0; i < FileTypeSize; i++)
@@ -1070,7 +1070,7 @@ unsigned WsWuInfo::getWorkunitThorLogInfo(IArrayOf<IEspECLHelpFile>& helpers, IE
             return countThorLog;
         }
 
-        unsigned numberOfSlaves = clusterInfo->getSize();
+        unsigned numberOfSlaveLogs = clusterInfo->getNumberOfSlaveLogs();
 
         BoolHash uniqueProcesses;
         Owned<IStringIterator> thorInstances = cw->getProcesses("Thor");
@@ -1136,7 +1136,7 @@ unsigned WsWuInfo::getWorkunitThorLogInfo(IArrayOf<IEspECLHelpFile>& helpers, IE
                 thorLog->setProcessName(processName.str());
                 thorLog->setClusterGroup(groupName.str());
                 thorLog->setLogDate(logDate.str());
-                thorLog->setNumberSlaves(numberOfSlaves);
+                thorLog->setNumberSlaves(numberOfSlaveLogs);
                 thorLogList.append(*thorLog.getLink());
             }
         }
@@ -2096,6 +2096,15 @@ void WsWuInfo::getWorkunitResTxt(MemoryBuffer& buf)
     queryDllServer().getDll(query->getQueryResTxtName(resname).str(), buf);
 }
 
+IConstWUQuery* WsWuInfo::getEmbeddedQuery()
+{
+    Owned<IWuWebView> wv = createWuWebView(*cw, NULL, NULL, NULL, false);
+    if (wv)
+        return wv->getEmbeddedQuery();
+
+    return NULL;
+}
+
 void WsWuInfo::getWorkunitArchiveQuery(MemoryBuffer& buf)
 {
     Owned<IConstWUQuery> query = cw->getQuery();
@@ -2105,7 +2114,18 @@ void WsWuInfo::getWorkunitArchiveQuery(MemoryBuffer& buf)
     SCMStringBuffer queryText;
     query->getQueryText(queryText);
     if ((queryText.length() < 1) || !isArchiveQuery(queryText.str()))
-        throw MakeStringException(ECLWATCH_CANNOT_GET_WORKUNIT, "Archive Query not found for workunit %s.", wuid.str());
+    {
+        if (!query->hasArchive())
+            throw MakeStringException(ECLWATCH_CANNOT_GET_WORKUNIT, "Archive query not found for workunit %s.", wuid.str());
+
+        Owned<IConstWUQuery> embeddedQuery = getEmbeddedQuery();
+        if (!embeddedQuery)
+            throw MakeStringException(ECLWATCH_CANNOT_GET_WORKUNIT, "Embedded query not found for workunit %s.", wuid.str());
+
+        embeddedQuery->getQueryText(queryText);
+        if ((queryText.length() < 1) || !isArchiveQuery(queryText.str()))
+            throw MakeStringException(ECLWATCH_CANNOT_GET_WORKUNIT, "Archive query not found for workunit %s.", wuid.str());
+    }
     buf.append(queryText.length(), queryText.str());
 }
 

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

@@ -203,6 +203,7 @@ public:
     void listArchiveFiles(IPropertyTree* archive, const char* path, IArrayOf<IEspWUArchiveModule>& modules, IArrayOf<IEspWUArchiveFile>& files);
     void getArchiveFile(IPropertyTree* archive, const char* moduleName, const char* attrName, const char* path, StringBuffer& file);
     void setWUAbortTime(IEspECLWorkunit &info, unsigned __int64 abortTS);
+    IConstWUQuery* getEmbeddedQuery();
 
 protected:
     void addTimerToList(SCMStringBuffer& name, const char * scope, IConstWUStatistic & stat, IArrayOf<IEspECLTimer>& timers);

+ 2 - 2
esp/services/ws_workunits/ws_workunitsService.cpp

@@ -4419,7 +4419,7 @@ void CWsWorkunitsEx::addThorSlaveLogfile(Owned<IConstWorkUnit>& cwu, WsWuInfo& w
         return;
     }
 
-    unsigned numberOfSlaves = clusterInfo->getSize();
+    unsigned numberOfSlaveLogs = clusterInfo->getNumberOfSlaveLogs();
     BoolHash uniqueProcesses;
     Owned<IStringIterator> thorInstances = cwu->getProcesses("Thor");
     ForEach (*thorInstances)
@@ -4456,7 +4456,7 @@ void CWsWorkunitsEx::addThorSlaveLogfile(Owned<IConstWorkUnit>& cwu, WsWuInfo& w
             StringBuffer logDate = ppStr;
             logDate.setLength(10);
 
-            for (unsigned i = 0; i < numberOfSlaves; i++)
+            for (unsigned i = 0; i < numberOfSlaveLogs; i++)
             {
                 MemoryBuffer mb;
                 winfo.getWorkunitThorSlaveLog(groupName.str(), NULL, logDate.str(), logDir.str(), i+1, mb, false);

+ 1 - 1
esp/src/eclwatch/Utility.js

@@ -184,7 +184,7 @@
             container.push(headerNames);
 
             arrayUtil.forEach(rows, function (cells, idx){
-                container.push(csvEncode(cells));
+                container.push(cells);
             });
 
             arrayUtil.forEach(container, function (header, idx) {

+ 22 - 0
system/jlib/jsmartsock.cpp

@@ -428,6 +428,28 @@ void CSmartSocketFactory::setStatus(SocketEndpoint &ep, bool status)
         ss->status=status;
 }
 
+StringBuffer & CSmartSocketFactory::getUrlStr(StringBuffer &url, bool useHostName)
+{
+	SmartSocketEndpoint * sep = nextSmartEndpoint();
+	if (sep)
+	{
+		SocketEndpoint ep;
+		if(useHostName && sep->name.length())
+		{
+			url.append(sep->name.str());
+			ep = sep->ep;
+			if (ep.port)
+				url.append(':').append((unsigned)ep.port);
+		}
+		else
+		{
+			sep->checkHost(dnsInterval);
+			SocketEndpoint ep = sep->ep;
+			ep.getUrlStr(url);
+		}
+	}
+	return url;
+}
 
 ISmartSocketFactory *createSmartSocketFactory(const char *_socklist, bool _retry, unsigned _retryInterval, unsigned _dnsInterval) {
     return new CSmartSocketFactory(_socklist, _retry, _retryInterval, _dnsInterval);

+ 2 - 0
system/jlib/jsmartsock.hpp

@@ -57,6 +57,8 @@ interface jlib_decl ISmartSocketFactory : extends IInterface
     virtual void stop() = 0;
 
     virtual void resolveHostnames() = 0;
+
+    virtual StringBuffer & getUrlStr(StringBuffer &str, bool useHostName) = 0;
 };
 
 

+ 2 - 0
system/jlib/jsmartsock.ipp

@@ -94,6 +94,8 @@ public:
     virtual void stop();
 
     virtual void resolveHostnames();
+
+    virtual StringBuffer & getUrlStr(StringBuffer &str, bool useHostName);
 };
 
 

+ 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>

+ 3 - 1
thorlcr/master/thgraphmanager.cpp

@@ -106,8 +106,10 @@ class CJobManager : public CSimpleInterface, implements IJobManager, implements
             }
 
             Linked<CJobMaster> job = mgr.getCurrentJob();
+            if (!job)
+                throw MakeStringException(5300, "Command not available when no job active");
             const char *graphId = job->queryGraphName();
-            if (!job || !graphId)
+            if (!graphId)
                 throw MakeStringException(5300, "Command not available when no graph active");
 
             const char *command = queryXml->queryName();