Преглед на файлове

Merge branch 'candidate-5.2.0'

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>

Conflicts:
	roxie/roxiemem/roxiemem.cpp
Richard Chapman преди 10 години
родител
ревизия
67eae993db

+ 13 - 0
deployment/configgen/main.cpp

@@ -19,6 +19,8 @@
 #include "configengcallback.hpp"
 #include "deploy.hpp"
 #include "build-config.h"
+#include "jutil.hpp"
+#include "jhash.ipp"
 
 #define STANDARD_INDIR COMPONENTFILES_DIR"/configxml"
 #define STANDARD_OUTDIR RUNTIME_DIR
@@ -581,12 +583,23 @@ int processRequest(const char* in_cfgname, const char* out_dirname, const char*
   }
   else if (listMachines)
   {
+    MapStringTo<bool> mapOfMachineIPs;
     StringBuffer out;
     Owned<IPropertyTreeIterator> computers = pEnv->getElements("Hardware/Computer");
     ForEach(*computers)
     {
       IPropertyTree* pComputer = &computers->query();
       const char *netAddress = pComputer->queryProp("@netAddress");
+
+      if (mapOfMachineIPs.getValue(netAddress) != NULL)
+      {
+          continue;
+      }
+      else
+      {
+          mapOfMachineIPs.setValue(netAddress, true);
+      }
+
       StringBuffer xpath;
       const char* name = pComputer->queryProp(XML_ATTR_NAME);
       bool isNonHPCCNode = true;

+ 12 - 1
deployment/deployutils/deployutils.cpp

@@ -2998,8 +2998,19 @@ IPropertyTree* getNewRange(const IPropertyTree* pEnv, const char* prefix, const
    while (count--)
    {
      range.getIpText(sIP.clear());
+
      unsigned x;
-       range.getNetAddress(sizeof(x),&x);
+     range.getNetAddress(sizeof(x),&x);
+
+     StringBuffer strCheckXPath;
+     strCheckXPath.setf("%s/%s[%s=\"%s\"][1]", XML_TAG_HARDWARE, XML_TAG_COMPUTER, XML_ATTR_NETADDRESS, sIP.str());
+
+     if (pEnv->hasProp(strCheckXPath.str()) == true)
+     {
+         range.ipincrement(1);
+         continue;
+     }
+
      sName.clear().appendf("%s%03d%03d", prefix, (x >> 16) & 0xFF, (x >> 24) & 0xFF);
      sNode.appendf("<"XML_TAG_COMPUTER" %s=\"%s\" %s=\"%s\" %s/>",
                       &XML_ATTR_NAME[1], getUniqueName(pEnv, sName, XML_TAG_COMPUTER, XML_TAG_HARDWARE),

+ 1 - 1
esp/eclwatch/ws_XSLT/services.xslt

@@ -696,7 +696,7 @@
                               <xsl:value-of select="Netaddress"/>
                               <xsl:text>%26FileType%3dcfg%26Directory%3d</xsl:text>
                               <xsl:value-of select="$absolutePath"/>
-                              <xsl:text>%26CompType%3dAgentExecProcess</xsl:text>
+                              <xsl:text>%26CompType%3dEclAgentProcess</xsl:text>
                               <xsl:text>%26OsType%3d</xsl:text>
                               <xsl:value-of select="OS"/>
                             </xsl:attribute>

+ 1 - 1
esp/eclwatch/ws_XSLT/targetclusters.xslt

@@ -797,7 +797,7 @@
                               <xsl:value-of select="Netaddress"/>
                               <xsl:text disable-output-escaping="yes">%26FileType%3dcfg%26Directory%3d</xsl:text>
                               <xsl:value-of select="$absolutePath"/>
-                              <xsl:text disable-output-escaping="yes">%26CompType%3dAgentExecProcess</xsl:text>
+                              <xsl:text disable-output-escaping="yes">%26CompType%3dEclAgentProcess</xsl:text>
                               <xsl:text disable-output-escaping="yes">%26OsType%3d</xsl:text>
                               <xsl:value-of select="OS"/>
                             </xsl:attribute>

+ 39 - 0
esp/logging/loggingmanager.h

@@ -0,0 +1,39 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2014 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#if !defined(__LOGGINGMANAGER_H__)
+#define __LOGGINGMANAGER_H__
+
+#include "jiface.hpp"
+#include "esp.hpp"
+#include "ws_loggingservice_esp.ipp"
+
+#define LOGGINGMANAGERLIB "loggingmanager"
+#define LOGGINGDBSINGLEINSERT "SingleInsert"
+
+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(IEspUpdateLogRequest& req, IEspUpdateLogResponse& resp) = 0;
+    virtual bool getTransactionSeed(StringBuffer& transactionSeed, StringBuffer& status) = 0;
+    virtual bool getTransactionSeed(IEspGetTransactionSeedRequest& req, IEspGetTransactionSeedResponse& resp) = 0;
+};
+
+typedef ILoggingManager* (*newLoggingManager_t_)();
+
+#endif // !defined(__LOGGINGMANAGER_H__)

+ 1 - 0
esp/scm/espscm.cmake

@@ -43,6 +43,7 @@ set ( ESPSCM_SRCS
       ws_workunits.ecm
       ws_packageprocess.ecm
       ws_esdlconfig.ecm
+      ws_loggingservice.ecm
     )
 
 foreach ( loop_var ${ESPSCM_SRCS} )

+ 62 - 0
esp/scm/ws_loggingservice.ecm

@@ -0,0 +1,62 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2014 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+ESPStruct LogItem
+{
+    string Name;
+    string Value;
+};
+
+ESPrequest [] GetTransactionSeedRequest
+{
+};
+
+ESPresponse [exceptions_inline] LoggingServiceResponse
+{
+    int StatusCode;
+    string StatusMessage;
+};
+
+ESPresponse [exceptions_inline] GetTransactionSeedResponse
+{
+    string SeedId;
+    int StatusCode;
+    string StatusMessage;
+};
+
+ESPrequest [nil_remove] UpdateLogRequest
+{
+    string Option;
+    string LogContent;
+};
+
+ESPresponse [exceptions_inline] UpdateLogResponse
+{
+    string Response;
+    int StatusCode;
+    string StatusMessage;
+};
+
+ESPService [version("1.0"), default_client_version("1.0"), noforms, use_method_name] WsLoggingService
+{
+    ESPmethod GetTransactionSeed(GetTransactionSeedRequest, GetTransactionSeedResponse);
+    ESPmethod UpdateLog(UpdateLogRequest, UpdateLogResponse);
+};
+
+SCMexportdef(WSLOGGING);
+
+SCMapi(WSLOGGING) IClientWsLoggingService *createWsLoggingServiceClient();

+ 1 - 3
esp/services/ws_topology/ws_topologyService.cpp

@@ -1445,14 +1445,12 @@ bool CWsTopologyEx::onTpGetComponentFile(IEspContext &context,
                 fileName = "eclccserver.xml";
             else if (!stricmp(compType, eqEclScheduler))
                 fileName = "eclscheduler.xml";
-            else if (!stricmp(compType, eqAgentExec))
+            else if (!stricmp(compType, eqEclAgent))
                 fileName = "agentexec.xml";
             else if (!stricmp(compType, eqEsp))
                 fileName = "esp.xml";
             else if (!stricmp(compType, eqSashaServer))
                 fileName = "sashaconf.xml";
-            else if (!stricmp(compType, eqEclAgent))
-                fileName = osType==OS_WINDOWS ? "setvars.bat" : NULL;
             else 
             {
                 const unsigned int len = strlen(compType);

+ 48 - 45
roxie/roxiemem/roxiemem.cpp

@@ -18,6 +18,7 @@
 #include "roxiemem.hpp"
 #include "roxierowbuff.hpp"
 #include "jlog.hpp"
+#include "jset.hpp"
 #include <new>
 
 #ifndef _WIN32
@@ -223,6 +224,7 @@ static void initializeHeap(bool allowHugePages, bool allowTransparentHugePages,
         }
 
         //If system supports transparent huge pages, use madvise to mark the memory as request huge pages
+#ifdef MADV_HUGEPAGE
         if (useTransparentHugePages)
         {
             if (madvise(heapBase,memsize,MADV_HUGEPAGE) == 0)
@@ -252,6 +254,9 @@ static void initializeHeap(bool allowHugePages, bool allowTransparentHugePages,
             else
                 DBGLOG("Transparent huge pages unsupported or disabled by system.");
         }
+#else
+        DBGLOG("Transparent huge pages are not supported on this kernel.  Requires kernel version > 2.6.38.");
+#endif
     }
 #endif
 
@@ -528,13 +533,10 @@ static void *suballoc_aligned(size32_t pages, bool returnNullWhenExhausted)
             unsigned hbi = heapBitmap[i];
             if (hbi)
             {
-                char *ret = heapBase + i*UNSIGNED_BITS*HEAP_ALIGNMENT_SIZE;
-                unsigned mask = 1;
-                while (!(hbi & mask))
-                {
-                    ret += HEAP_ALIGNMENT_SIZE;
-                    mask <<= 1;
-                }
+                const unsigned pos = countTrailingUnsetBits(hbi);
+                const unsigned mask = 1U << pos;
+                const unsigned match = i*UNSIGNED_BITS + pos;
+                char *ret = heapBase + match*HEAP_ALIGNMENT_SIZE;
                 heapBitmap[i] = (hbi & ~mask);
                 heapLWM = i;
                 heapAllocated++;
@@ -650,32 +652,30 @@ static void subfree_aligned(void *ptr, unsigned pages = 1)
 
         if (wordOffset < heapLWM)
             heapLWM = wordOffset;
+
         loop
         {
             unsigned prev = heapBitmap[wordOffset];
-            if ((prev & mask) == 0)
+            if ((prev & mask) != 0)
+                HEAPERROR("RoxieMemMgr: Page freed twice");
+
+            unsigned next = prev | mask;
+            heapBitmap[wordOffset] = next;
+            if ((next == UNSIGNED_ALLBITS) && heapNotifyUnusedEachBlock)
             {
-                unsigned next = prev | mask;
-                heapBitmap[wordOffset] = next;
-                if ((next == UNSIGNED_ALLBITS) && heapNotifyUnusedEachBlock)
-                {
-                    char * address = heapBase + wordOffset * heapBlockSize;
-                    if (!firstReleaseBlock)
-                        firstReleaseBlock = address;
-                    lastReleaseBlock = address;
-                }
+                char * address = heapBase + wordOffset * heapBlockSize;
+                if (!firstReleaseBlock)
+                    firstReleaseBlock = address;
+                lastReleaseBlock = address;
             }
-            else
-                HEAPERROR("RoxieMemMgr: Page freed twice");
             if (!--pages)
                 break;
-            if (mask==TOPBITMASK)
+            mask <<= 1;
+            if (mask==0)
             {
                 mask = 1;
                 wordOffset++;
             }
-            else
-                mask <<= 1;
         }
     }
 
@@ -700,21 +700,19 @@ static void clearBits(unsigned start, unsigned len)
         unsigned heapword = heapBitmap[wordOffset];
         while (len--)
         {
-            if (heapword & mask)
-                heapword &= ~mask;
-            else
+            if ((heapword & mask) == 0)
                 HEAPERROR("RoxieMemMgr: Page freed twice");
-            if (mask==TOPBITMASK)
+            heapword &= ~mask;
+            mask <<= 1;
+            if (mask==0)
             {
                 heapBitmap[wordOffset] = heapword;
-                mask = 1;
                 wordOffset++;
                 if (wordOffset==heapBitmapSize)
                     return;    // Avoid read off end of array
                 heapword = heapBitmap[wordOffset];
+                mask = 1;
             }
-            else
-                mask <<= 1;
         }
         heapBitmap[wordOffset] = heapword;
     }
@@ -4882,21 +4880,21 @@ protected:
     }
 
 #ifdef __64BIT__
-    enum { numBitmapThreads = 20, maxBitmapSize = (unsigned)(I64C(0xFFFFFFFFFF) / HEAP_ALIGNMENT_SIZE / UNSIGNED_BITS) };      // Test larger range - in case we ever reduce the granularity
+    enum { maxBitmapThreads = 20, maxBitmapSize = (unsigned)(I64C(0xFFFFFFFFFF) / HEAP_ALIGNMENT_SIZE / UNSIGNED_BITS) };      // Test larger range - in case we ever reduce the granularity
 #else
     // Restrict heap sizes on 32-bit systems
-    enum { numBitmapThreads = 20, maxBitmapSize = (unsigned)(I64C(0xFFFFFFFF) / HEAP_ALIGNMENT_SIZE / UNSIGNED_BITS) };      // 4Gb
+    enum { maxBitmapThreads = 20, maxBitmapSize = (unsigned)(I64C(0xFFFFFFFF) / HEAP_ALIGNMENT_SIZE / UNSIGNED_BITS) };      // 4Gb
 #endif
     class BitmapAllocatorThread : public Thread
     {
     public:
-        BitmapAllocatorThread(Semaphore & _sem, unsigned _size) : Thread("AllocatorThread"), sem(_sem), size(_size)
+        BitmapAllocatorThread(Semaphore & _sem, unsigned _size, unsigned _numThreads) : Thread("AllocatorThread"), sem(_sem), size(_size), numThreads(_numThreads)
         {
         }
 
         int run()
         {
-            unsigned numBitmapIter = (maxBitmapSize * 32 / size) / numBitmapThreads;
+            unsigned numBitmapIter = (maxBitmapSize * 32 / size) / numThreads;
             sem.wait();
             memsize_t total = 0;
             for (unsigned i=0; i < numBitmapIter; i++)
@@ -4915,9 +4913,10 @@ protected:
     protected:
         Semaphore & sem;
         const unsigned size;
+        const unsigned numThreads;
         volatile memsize_t final;
     };
-    void testBitmapThreading(unsigned size)
+    void testBitmapThreading(unsigned size, unsigned numThreads)
     {
         HeapPreserver preserver;
 
@@ -4926,19 +4925,19 @@ protected:
         heapNotifyUnusedEachBlock = false;
 
         Semaphore sem;
-        BitmapAllocatorThread * threads[numBitmapThreads];
-        for (unsigned i1 = 0; i1 < numBitmapThreads; i1++)
-            threads[i1] = new BitmapAllocatorThread(sem, size);
-        for (unsigned i2 = 0; i2 < numBitmapThreads; i2++)
+        BitmapAllocatorThread * threads[maxBitmapThreads];
+        for (unsigned i1 = 0; i1 < numThreads; i1++)
+            threads[i1] = new BitmapAllocatorThread(sem, size, numThreads);
+        for (unsigned i2 = 0; i2 < numThreads; i2++)
             threads[i2]->start();
 
         unsigned startTime = msTick();
-        sem.signal(numBitmapThreads);
-        for (unsigned i3 = 0; i3 < numBitmapThreads; i3++)
+        sem.signal(numThreads);
+        for (unsigned i3 = 0; i3 < numThreads; i3++)
             threads[i3]->join();
         unsigned endTime = msTick();
 
-        for (unsigned i4 = 0; i4 < numBitmapThreads; i4++)
+        for (unsigned i4 = 0; i4 < numThreads; i4++)
             threads[i4]->Release();
         DBGLOG("Time taken for bitmap threading(%d) = %d", size, endTime-startTime);
 
@@ -4947,16 +4946,20 @@ protected:
         unsigned maxBlock;
         memstats(totalPages, freePages, maxBlock);
         ASSERT(totalPages == maxBitmapSize * 32);
-        unsigned numAllocated = ((maxBitmapSize * 32 / size) / numBitmapThreads) * numBitmapThreads * size;
+        unsigned numAllocated = ((maxBitmapSize * 32 / size) / numThreads) * numThreads * size;
         ASSERT(freePages == maxBitmapSize * 32 - numAllocated);
 
         delete[] heapBitmap;
     }
     void testBitmapThreading()
     {
-        testBitmapThreading(1);
-        testBitmapThreading(3);
-        testBitmapThreading(11);
+        //Don't run this with NOTIFY_UNUSED_PAGES_ON_FREE enabled - I'm not sure what the calls to map out random memory are likely to do!
+        testBitmapThreading(1, 1);
+        testBitmapThreading(3, 1);
+        testBitmapThreading(11, 1);
+        testBitmapThreading(1, maxBitmapThreads);
+        testBitmapThreading(3, maxBitmapThreads);
+        testBitmapThreading(11, maxBitmapThreads);
     }
 
     void testCompressSize()

+ 64 - 11
system/jlib/jsocket.cpp

@@ -401,6 +401,7 @@ public:
     void        readtms(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read, unsigned timedelaysecs);
     void        read(void* buf, size32_t size);
     size32_t    write(void const* buf, size32_t size);
+    size32_t    writetms(void const* buf, size32_t size, unsigned timeoutms=WAIT_FOREVER);
     size32_t    write_multiple(unsigned num,void const**buf, size32_t *size);
     size32_t    udp_write_to(const SocketEndpoint &ep,void const* buf, size32_t size);
     void        close();
@@ -465,7 +466,7 @@ private:
             sock = INVALID_SOCKET;
             STATS.activesockets--;
     #ifdef SOCKTRACE
-            PROGLOG("SOCKTRACE: Closing socket %x %d (%x)", s, s, this);
+            PROGLOG("SOCKTRACE: Closing socket %x %d (%p)", s, s, this);
     #endif
     #ifdef _WIN32
             return ::closesocket(s);
@@ -834,7 +835,7 @@ int CSocket::pre_connect (bool block)
     } else
         atomic_set(&pre_conn_unreach_cnt, 0);
 #ifdef SOCKTRACE
-    PROGLOG("SOCKTRACE: pre-connected socket%s %x %d (%x) err=%d", block?"(block)":"", sock, sock, (int)this, err);
+    PROGLOG("SOCKTRACE: pre-connected socket%s %x %d (%p) err=%d", block?"(block)":"", sock, sock, this, err);
 #endif
     return err;
 }
@@ -870,7 +871,7 @@ void CSocket::open(int listen_queue_size,bool reuseports)
     STATS.activesockets++;
 
 #ifdef SOCKTRACE
-    PROGLOG("SOCKTRACE: opened socket %x %d (%x)", sock,sock,this);
+    PROGLOG("SOCKTRACE: opened socket %x %d (%p)", sock,sock,this);
 #endif
 
     if ((hostport==0)&&(sockmode==sm_udp)) {
@@ -962,7 +963,7 @@ ISocket* CSocket::accept(bool allowcancel)
         newsock = (sock!=INVALID_SOCKET)?::accept(sock, NULL, NULL):INVALID_SOCKET;
         in_accept = false;
     #ifdef SOCKTRACE
-        PROGLOG("SOCKTRACE: accept created socket %x %d (%x)", newsock,newsock,this);
+        PROGLOG("SOCKTRACE: accept created socket %x %d (%p)", newsock,newsock,this);
     #endif
 
         if (newsock!=INVALID_SOCKET) {
@@ -1128,7 +1129,7 @@ void CSocket::cancel_accept()
         THROWJSOCKEXCEPTION(JSOCKERR_connectionless_socket);
     }
 #ifdef SOCKTRACE
-    PROGLOG("SOCKTRACE: Cancel accept socket %x %d (%x)", sock, sock, this);
+    PROGLOG("SOCKTRACE: Cancel accept socket %x %d (%p)", sock, sock, this);
 #endif
     if (!in_accept) {
         accept_cancel_state = accept_cancelled;
@@ -1408,7 +1409,7 @@ void CSocket::udpconnect()
     socklen_t  ul = setSockAddr(u,targetip,hostport);
     sock = ::socket(u.sa.sa_family, SOCK_DGRAM, targetip.isIp4()?0:PF_INET6);
 #ifdef SOCKTRACE
-    PROGLOG("SOCKTRACE: udp connected socket %x %d (%x)", sock, sock, this);
+    PROGLOG("SOCKTRACE: udp connected socket %x %d (%p)", sock, sock, this);
 #endif
     STATS.activesockets++;
     if (sock == INVALID_SOCKET) {
@@ -1775,6 +1776,58 @@ EintrRetry:
     return res;
 }
 
+size32_t CSocket::writetms(void const* buf, size32_t size, unsigned timeoutms)
+{
+    if (size==0)
+        return 0;
+
+    if (state != ss_open)
+    {
+        THROWJSOCKEXCEPTION(JSOCKERR_not_opened);
+    }
+
+    if (timeoutms == WAIT_FOREVER)
+        return write(buf, size);
+
+    const char *p = (const char *)buf;
+    unsigned start, elapsed;
+    start = msTick();
+    elapsed = 0;
+    size32_t nwritten = 0;
+    size32_t nleft = size;
+    unsigned rollover = 0;
+
+    bool prevblock = set_nonblock(true);
+
+    while ( (nwritten < size) && (elapsed <= timeoutms) )
+    {
+        size32_t amnt = write(p,nleft);
+
+        if ( ((amnt == (size32_t)-1) || (amnt == 0)) && (++rollover >= 20) )
+        {
+            rollover = 0;
+            Sleep(20);
+        }
+        else
+        {
+            nwritten += amnt;
+            nleft -= amnt;
+            p += amnt;
+        }
+        elapsed = msTick() - start;
+    }
+
+    set_nonblock(prevblock);
+
+    if (nwritten < size)
+    {
+        ERRLOG("writetms timed out; timeout: %u, nwritten: %u, size: %u", timeoutms, nwritten, size);
+        THROWJSOCKEXCEPTION(JSOCKERR_timeout_expired);
+    }
+
+    return nwritten;
+}
+
 bool CSocket::check_connection()
 {
     if (state != ss_open) 
@@ -2196,7 +2249,7 @@ void CSocket::shutdown(unsigned mode)
     if (state == ss_open) {
         state = ss_shutdown;
 #ifdef SOCKTRACE
-        PROGLOG("SOCKTRACE: shutdown(%d) socket %x %d (%x)", mode, sock, sock, this);
+        PROGLOG("SOCKTRACE: shutdown(%d) socket %x %d (%p)", mode, sock, sock, this);
 #endif
         int rc = ::shutdown(sock, mode);
         if (rc != 0) {
@@ -2221,7 +2274,7 @@ void CSocket::errclose()
     if (state != ss_close) {
         state = ss_close;
 #ifdef SOCKTRACE
-        PROGLOG("SOCKTRACE: errclose socket %x %d (%x)", sock, sock, this);
+        PROGLOG("SOCKTRACE: errclose socket %x %d (%p)", sock, sock, this);
 #endif
         if (mcastreq)
             setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,(char*)mcastreq,sizeof(*mcastreq));
@@ -2240,7 +2293,7 @@ void CSocket::close()
 #endif
     if (state != ss_close) {
 #ifdef SOCKTRACE
-        PROGLOG("SOCKTRACE: close socket %x %d (%x)", sock, sock, this);
+        PROGLOG("SOCKTRACE: close socket %x %d (%p)", sock, sock, this);
 #endif
         state = ss_close;
         if (mcastreq)
@@ -3729,7 +3782,7 @@ class CSocketSelectThread: public CSocketBaseThread
         if (dummysockopen) { 
 #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
 #ifdef SOCKTRACE
-            PROGLOG("SOCKTRACE: Closing dummy sockets %x %d %x %d (%x)", dummysock[0], dummysock[0], dummysock[1], dummysock[1], this);
+            PROGLOG("SOCKTRACE: Closing dummy sockets %x %d %x %d (%p)", dummysock[0], dummysock[0], dummysock[1], dummysock[1], this);
 #endif
             ::close(dummysock[0]);
             ::close(dummysock[1]);
@@ -4302,7 +4355,7 @@ class CSocketEpollThread: public CSocketBaseThread
 #ifdef _USE_PIPE_FOR_SELECT_TRIGGER
             epoll_op(epfd, EPOLL_CTL_DEL, dummysock[0], 0);
 #ifdef SOCKTRACE
-            PROGLOG("SOCKTRACE: Closing dummy sockets %x %d %x %d (%x)", dummysock[0], dummysock[0], dummysock[1], dummysock[1], this);
+            PROGLOG("SOCKTRACE: Closing dummy sockets %x %d %x %d (%p)", dummysock[0], dummysock[0], dummysock[1], dummysock[1], this);
 #endif
             ::close(dummysock[0]);
             ::close(dummysock[1]);

+ 1 - 0
system/jlib/jsocket.hpp

@@ -267,6 +267,7 @@ public:
                            unsigned timeout) = 0;
     virtual void   read(void* buf, size32_t size) = 0;
     virtual size32_t write(void const* buf, size32_t size) = 0; // returns amount written normally same as in size (see set_nonblock)
+    virtual size32_t writetms(void const* buf, size32_t size, unsigned timeoutms=WAIT_FOREVER) = 0;
 
     virtual size32_t get_max_send_size() = 0;
 

+ 8 - 0
system/security/securesocket/securesocket.cpp

@@ -154,6 +154,7 @@ public:
     virtual void read(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read,unsigned timeoutsecs);
     virtual void readtms(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read, unsigned timeoutms);
     virtual size32_t write(void const* buf, size32_t size);
+    virtual size32_t writetms(void const* buf, size32_t size, unsigned timeoutms=WAIT_FOREVER);
 
     void readTimeout(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read, unsigned timeout, bool useSeconds);
 
@@ -734,6 +735,13 @@ size32_t CSecureSocket::write(void const* buf, size32_t size)
     return numwritten;
 }
 
+size32_t CSecureSocket::writetms(void const* buf, size32_t size, unsigned timeoutms)
+{
+    // timeoutms not implemented yet ...
+    int numwritten = SSL_write(m_ssl, buf, size);
+    return numwritten;
+}
+
 int verify_callback(int ok, X509_STORE_CTX *store)
 {
     if(!ok)

+ 4 - 3
testing/unittests/jlibtests.cpp

@@ -166,7 +166,8 @@ protected:
         bool setValue = !initial;
         bool clearValue = initial;
         const unsigned numBits = 400;
-        for (unsigned pass=0; pass < 10000; pass++)
+        const unsigned passes = 10000;
+        for (unsigned pass=0; pass < passes; pass++)
         {
             Owned<IBitSet> bs = createThreadSafeBitSet();
             testSet1(initial, bs, 0, numBits, setValue, clearValue);
@@ -174,7 +175,7 @@ protected:
         unsigned elapsed = msTick()-now;
         fprintf(stdout, "Bit test (%u) time taken = %dms\n", initial, elapsed);
         now = msTick();
-        for (unsigned pass=0; pass < 10000; pass++)
+        for (unsigned pass=0; pass < passes; pass++)
         {
             Owned<IBitSet> bs = createBitSet();
             testSet1(initial, bs, 0, numBits, setValue, clearValue);
@@ -185,7 +186,7 @@ protected:
         size32_t bitSetMemSz = getBitSetMemoryRequirement(numBits+5);
         MemoryBuffer mb;
         void *mem = mb.reserveTruncate(bitSetMemSz);
-        for (unsigned pass=0; pass < 10000; pass++)
+        for (unsigned pass=0; pass < passes; pass++)
         {
             Owned<IBitSet> bs = createBitSet(bitSetMemSz, mem);
             testSet1(initial, bs, 0, numBits, setValue, clearValue);

+ 1 - 1
tools/esdlcmd/esdlcmd_common.hpp

@@ -158,7 +158,7 @@ public:
             {
                 StringBuffer esxml;
                 EsdlCmdHelper::convertECMtoESXDL(sourceFileName, filename.str(), esxml, true, true, false);
-                esdlDef->addDefinitionFromXML(esxml, serviceName, version);
+                esdlDef->addDefinitionFromXML(esxml, serviceName, (int)version);
             }
             else
             {

+ 1 - 1
tools/esdlcomp/esdlcomp.h

@@ -1283,7 +1283,7 @@ public:
 };
 
 
-class esdl_decl ESDLcompiler
+class esdlcomp_decl ESDLcompiler
 {
 public:
     ESDLcompiler(const char * sourceFile, bool generatefile, const char * outDir, bool outputIncludes);

+ 3 - 3
tools/esdlcomp/esdldecl.hpp

@@ -20,12 +20,12 @@
 
 #ifdef _WIN32
  #ifdef ESDLCOMP_EXPORTS
-  #define esdl_decl __declspec(dllexport)
+  #define esdlcomp_decl __declspec(dllexport)
  #else
-  #define esdl_decl __declspec(dllimport)
+  #define esdlcomp_decl __declspec(dllimport)
  #endif
 #else
- #define esdl_decl
+ #define esdlcomp_decl
 #endif
 
 #endif