Merged changes from 3.14 branch up to revno 12526

This commit is contained in:
Andrew Johnson
2015-02-27 18:11:37 -06:00
13 changed files with 153 additions and 81 deletions
+25
View File
@@ -14,6 +14,31 @@
<h2 align="center">Changes between 3.15.1 and 3.15.2</h2>
<!-- Insert new items immediately below here ... -->
<h3>Enhanced API for asTrapWrite listeners</h3>
<p>External software such as the CA Put Logging module that registers a listener
with the asTrapWrite subsystem was not previously given access to the actual
data being sent by the CA client. In most cases this was not a problem as the
listener can look at the field being modified both before and after the
operation, but if the put processes the record which immediately overwrites the
new value, the client's value cannot be observed.</p>
<p>This release adds three fields to the asTrapWriteMessage structure that is
passed to the listener routines. These new fields provide the CA data type, the
number of array elements, and a pointer to the source data buffer. This change
is completely backwards compatible with listener code written against the
original API. The new API can be detected at compile-time as follows:</p>
<blockquote><pre>
#include "asLib.h"
/* ... */
#ifdef asTrapWriteWithData
/* Enhanced API */
#endif
</pre></blockquote>
<h3>Use of PATH_FILTER in Makefiles deprecated</h3>
<p>The PATH_FILTER variable was being called to convert forward shashes
+1
View File
@@ -118,6 +118,7 @@ char *val2str (const void *v, unsigned type, int index)
strcpy (str, "*** invalid type");
return str;
}
strcpy (str, "!!!");
base_type = type % (LAST_TYPE+1);
+1
View File
@@ -588,6 +588,7 @@ void dbFreeBase(dbBase *pdbbase)
dbPvdFreeMem(pdbbase);
dbFreePath(pdbbase);
free((void *)pdbbase);
pdbbase = NULL;
return;
}
+10 -12
View File
@@ -284,21 +284,18 @@ static void log_header (
pciu = MPTOPCIU(mp);
if (pContext) {
epicsPrintf ("CAS: request from %s => \"%s\"\n",
epicsPrintf ("CAS: request from %s => %s\n",
hostName, pContext);
}
epicsPrintf (
"CAS: Request from %s => cmmd=%d cid=0x%x type=%d count=%d postsize=%u\n",
epicsPrintf ( "CAS: Request from %s => cmmd=%d cid=0x%x type=%d count=%d postsize=%u\n",
hostName, mp->m_cmmd, mp->m_cid, mp->m_dataType, mp->m_count, mp->m_postsize);
epicsPrintf (
"CAS: Request from %s => available=0x%x \tN=%u dbch=%p\n",
hostName, mp->m_available, mnum, (pciu?(void *)&pciu->dbch:NULL));
epicsPrintf ( "CAS: Request from %s => available=0x%x \tN=%u paddr=%p\n",
hostName, mp->m_available, mnum, (pciu ? (void *)&pciu->dbch : NULL));
if (mp->m_cmmd==CA_PROTO_WRITE && mp->m_dataType==DBF_STRING && pPayLoad ) {
epicsPrintf (
"CAS: Request from %s => \tThe string written: %s \n",
epicsPrintf ( "CAS: Request from %s => Wrote string \"%s\"\n",
hostName, (char *)pPayLoad );
}
}
@@ -854,10 +851,10 @@ static int write_action ( caHdrLargeArray *mp,
return RSRV_ERROR;
}
asWritePvt = asTrapWriteBefore ( pciu->asClientPVT,
asWritePvt = asTrapWriteWithData ( pciu->asClientPVT,
pciu->client->pUserName ? pciu->client->pUserName : "",
pciu->client->pHostName ? pciu->client->pHostName : "",
pciu->dbch );
pciu->dbch, mp->m_dataType, mp->m_count, pPayload );
dbStatus = dbChannel_put(
pciu->dbch,
@@ -1881,11 +1878,12 @@ static int write_notify_action ( caHdrLargeArray *mp, void *pPayload,
pciu->pPutNotify->dbrType = mp->m_dataType;
pciu->pPutNotify->asWritePvt = asTrapWriteBefore (
pciu->pPutNotify->asWritePvt = asTrapWriteWithData (
pciu->asClientPVT,
pciu->client->pUserName ? pciu->client->pUserName : "",
pciu->client->pHostName ? pciu->client->pHostName : "",
pciu->dbch );
pciu->dbch, mp->m_dataType, mp->m_count,
pciu->pPutNotify->pbuffer );
dbProcessNotify(&pciu->pPutNotify->dbPutNotify);
+13 -8
View File
@@ -68,9 +68,10 @@ void camsgtask ( void *pParm )
status = socket_ioctl (client->sock, FIONREAD, &nchars);
if (status < 0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf("CAS: io ctl err - %s\n",
errlogPrintf("CAS: ioctl error - %s\n",
sockErrBuf);
cas_send_bs_msg(client, TRUE);
}
@@ -99,9 +100,8 @@ void camsgtask ( void *pParm )
}
if ( anerrno == SOCK_ENOBUFS ) {
errlogPrintf (
"rsrv: system low on network buffers "
"- receive retry in 15 seconds\n" );
errlogPrintf (
"CAS: Out of network buffers, retring receive in 15 seconds\n" );
epicsThreadSleep ( 15.0 );
continue;
}
@@ -110,10 +110,15 @@ void camsgtask ( void *pParm )
* normal conn lost conditions
*/
if ( ( anerrno != SOCK_ECONNABORTED &&
anerrno != SOCK_ECONNRESET &&
anerrno != SOCK_ETIMEDOUT ) ||
CASDEBUG > 2 ) {
errlogPrintf ( "CAS: client disconnect(errno=%d)\n", anerrno );
anerrno != SOCK_ECONNRESET &&
anerrno != SOCK_ETIMEDOUT ) ||
CASDEBUG > 2 ) {
char sockErrBuf[64];
epicsSocketConvertErrorToString(
sockErrBuf, sizeof ( sockErrBuf ), anerrno);
errlogPrintf ( "CAS: Client disconnected - %s\n",
sockErrBuf );
}
break;
}
+7 -10
View File
@@ -90,7 +90,8 @@ void cas_send_bs_msg ( struct client *pclient, int lock_needed )
}
if ( anerrno == SOCK_ENOBUFS ) {
errlogPrintf ( "rsrv: system low on network buffers - send retry in 15 seconds\n" );
errlogPrintf (
"CAS: Out of network buffers, retrying send in 15 seconds\n" );
epicsThreadSleep ( 15.0 );
continue;
}
@@ -108,8 +109,7 @@ void cas_send_bs_msg ( struct client *pclient, int lock_needed )
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf (
"CAS: TCP send to \"%s\" failed because \"%s\"\n",
errlogPrintf ( "CAS: TCP send to %s failed - %s\n",
buf, sockErrBuf);
}
pclient->disconnect = TRUE;
@@ -135,7 +135,7 @@ void cas_send_bs_msg ( struct client *pclient, int lock_needed )
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf ("rsrv: socket shutdown error was %s\n",
errlogPrintf ("CAS: Socket shutdown error - %s\n",
sockErrBuf );
}
}
@@ -204,7 +204,7 @@ void cas_send_dg_msg ( struct client * pclient )
}
else {
errlogPrintf (
"cas: system failed to send entire udp frame?\n" );
"CAS: System failed to send entire udp frame?\n" );
}
}
else {
@@ -213,11 +213,8 @@ void cas_send_dg_msg ( struct client * pclient )
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
ipAddrToDottedIP ( &pclient->addr, buf, sizeof(buf) );
errlogPrintf(
"CAS: UDP send to \"%s\" "
"failed because \"%s\"\n",
buf,
sockErrBuf);
errlogPrintf( "CAS: UDP send to %s failed - %s\n",
buf, sockErrBuf);
}
pclient->send.stk = 0u;
+4 -4
View File
@@ -276,7 +276,7 @@ int rsrv_init (void)
status = envGetLongConfigParam ( &EPICS_CA_MAX_ARRAY_BYTES, &maxBytesAsALong );
if ( status || maxBytesAsALong < 0 ) {
errlogPrintf ( "cas: EPICS_CA_MAX_ARRAY_BYTES was not a positive integer\n" );
errlogPrintf ( "CAS: EPICS_CA_MAX_ARRAY_BYTES was not a positive integer\n" );
rsrvSizeofLargeBufTCP = MAX_TCP;
}
else {
@@ -290,7 +290,7 @@ int rsrv_init (void)
maxBytes = 0xffffffff;
}
if ( maxBytes < MAX_TCP ) {
errlogPrintf ( "cas: EPICS_CA_MAX_ARRAY_BYTES was rounded up to %u\n", MAX_TCP );
errlogPrintf ( "CAS: EPICS_CA_MAX_ARRAY_BYTES was rounded up to %u\n", MAX_TCP );
rsrvSizeofLargeBufTCP = MAX_TCP;
}
else {
@@ -571,7 +571,7 @@ void destroy_client ( struct client *client )
freeListFree ( rsrvLargeBufFreeListTCP, client->send.buf );
}
else {
errlogPrintf ( "cas: Corrupt send buffer free list type code=%u during client cleanup?\n",
errlogPrintf ( "CAS: Corrupt send buffer free list type code=%u during client cleanup?\n",
client->send.type );
}
}
@@ -583,7 +583,7 @@ void destroy_client ( struct client *client )
freeListFree ( rsrvLargeBufFreeListTCP, client->recv.buf );
}
else {
errlogPrintf ( "cas: Corrupt recv buffer free list type code=%u during client cleanup?\n",
errlogPrintf ( "CAS: Corrupt recv buffer free list type code=%u during client cleanup?\n",
client->send.type );
}
}
+30 -16
View File
@@ -30,25 +30,38 @@ typedef enum{
} asClientStatus;
typedef void (*ASCLIENTCALLBACK) (ASCLIENTPVT,asClientStatus);
/* The following routines are macros with the following syntax
long asCheckGet(ASCLIENTPVT asClientPvt);
long asCheckPut(ASCLIENTPVT asClientPvt);
*/
#define asCheckGet(asClientPvt)\
(asActive \
? ((asClientPvt)->access>=asREAD ? TRUE : FALSE)\
: TRUE)
#define asCheckPut(asClientPvt)\
(asActive \
? ((asClientPvt)->access>=asWRITE ? TRUE : FALSE)\
: TRUE)
#define asTrapWriteBefore(asClientPvt,user,host,addr) \
(((asActive) && (asClientPvt)->trapMask) \
? asTrapWriteBeforeWrite((user),(host),(addr)) \
: 0)
#define asCheckGet(asClientPvt) \
(!asActive || ((asClientPvt)->access >= asREAD))
#define asCheckPut(asClientPvt) \
(!asActive || ((asClientPvt)->access >= asWRITE))
/* More convenience macros
void *asTrapWriteWithData(ASCLIENTPVT asClientPvt,
const char *userid, const char *hostid, void *addr,
int dbrType, int no_elements, void *data);
void asTrapWriteAfter(ASCLIENTPVT asClientPvt);
*/
#define asTrapWriteWithData(asClientPvt, user, host, addr, type, count, data) \
((asActive && (asClientPvt)->trapMask) \
? asTrapWriteBeforeWithData((user), (host), (addr), (type), (count), (data)) \
: 0)
#define asTrapWriteAfter(pvt) \
if (pvt) asTrapWriteAfterWrite(pvt)
/* This macro is for backwards compatibility, upgrade any code
calling it to use asTrapWriteWithData() instead ASAP:
void *asTrapWriteBefore(ASCLIENTPVT asClientPvt,
const char *userid, const char *hostid, void *addr);
*/
#define asTrapWriteBefore(asClientPvt, user, host, addr) \
asTrapWriteWithData(asClientPvt, user, host, addr, 0, 0, NULL)
#define asTrapWriteAfter(pvt) if((pvt)) asTrapWriteAfterWrite((pvt))
epicsShareFunc long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction);
epicsShareFunc long epicsShareAPI asInitFile(
const char *filename,const char *substitutions);
@@ -100,8 +113,9 @@ epicsShareFunc int epicsShareAPI asDumpMemFP(FILE *fp,const char *asgname,
epicsShareFunc int epicsShareAPI asDumpHash(void);
epicsShareFunc int epicsShareAPI asDumpHashFP(FILE *fp);
epicsShareFunc void * epicsShareAPI asTrapWriteBeforeWrite(
const char *userid,const char *hostid,void *addr);
epicsShareFunc void * epicsShareAPI asTrapWriteBeforeWithData(
const char *userid, const char *hostid, void *addr,
int dbrType, int no_elements, void *data);
epicsShareFunc void epicsShareAPI asTrapWriteAfterWrite(void *pvt);
+31 -24
View File
@@ -3,8 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*asTrapWrite.c */
@@ -101,47 +100,53 @@ void epicsShareAPI asTrapWriteUnregisterListener(asTrapWriteId id)
= (listenerPvt *)ellNext(&plistenerPvt->node);
if(plistenerPvt->plistener == plistener) {
ellDelete(&pwriteMessage->listenerPvtList,&plistenerPvt->node);
freeListFree(pasTrapWritePvt->freeListListenerPvt,(void *)plistenerPvt);
freeListFree(pasTrapWritePvt->freeListListenerPvt, plistenerPvt);
}
plistenerPvt = pnext;
}
pwriteMessage = (writeMessage *)ellNext(&pwriteMessage->node);
}
ellDelete(&pasTrapWritePvt->listenerList,&plistener->node);
free((void *)plistener);
free(plistener);
epicsMutexUnlock(pasTrapWritePvt->lock);
}
void * epicsShareAPI asTrapWriteBeforeWrite(
const char *userid,const char *hostid,void *addr)
void * epicsShareAPI asTrapWriteBeforeWithData(
const char *userid, const char *hostid, void *addr,
int dbrType, int no_elements, void *data)
{
writeMessage *pwriteMessage;
listener *plistener;
listenerPvt *plistenerPvt;
if(pasTrapWritePvt==0) return(0);
if(ellCount(&pasTrapWritePvt->listenerList)<=0) return 0;
if (pasTrapWritePvt == 0 ||
ellCount(&pasTrapWritePvt->listenerList) <= 0) return 0;
pwriteMessage = (writeMessage *)freeListCalloc(
pasTrapWritePvt->freeListWriteMessage);
pwriteMessage->message.userid = userid;
pwriteMessage->message.hostid = hostid;
pwriteMessage->message.serverSpecific = addr;
pwriteMessage->message.dbrType = dbrType;
pwriteMessage->message.no_elements = no_elements;
pwriteMessage->message.data = data;
ellInit(&pwriteMessage->listenerPvtList);
epicsMutexMustLock(pasTrapWritePvt->lock);
ellAdd(&pasTrapWritePvt->writeMessageList,&pwriteMessage->node);
ellAdd(&pasTrapWritePvt->writeMessageList, &pwriteMessage->node);
plistener = (listener *)ellFirst(&pasTrapWritePvt->listenerList);
while(plistener) {
plistenerPvt = (listenerPvt *)freeListCalloc(
while (plistener) {
listenerPvt *plistenerPvt = (listenerPvt *)freeListCalloc(
pasTrapWritePvt->freeListListenerPvt);
plistenerPvt->plistener = plistener;
pwriteMessage->message.userPvt = 0;
(*plistener->func)(&pwriteMessage->message,0);
plistener->func(&pwriteMessage->message, 0);
plistenerPvt->userPvt = pwriteMessage->message.userPvt;
ellAdd(&pwriteMessage->listenerPvtList,&plistenerPvt->node);
ellAdd(&pwriteMessage->listenerPvtList, &plistenerPvt->node);
plistener = (listener *)ellNext(&plistener->node);
}
epicsMutexUnlock(pasTrapWritePvt->lock);
return((void *)pwriteMessage);
return pwriteMessage;
}
void epicsShareAPI asTrapWriteAfterWrite(void *pvt)
@@ -149,20 +154,22 @@ void epicsShareAPI asTrapWriteAfterWrite(void *pvt)
writeMessage *pwriteMessage = (writeMessage *)pvt;
listenerPvt *plistenerPvt;
if(pwriteMessage==0 || pasTrapWritePvt==0) return;
if (pwriteMessage == 0 ||
pasTrapWritePvt == 0) return;
epicsMutexMustLock(pasTrapWritePvt->lock);
plistenerPvt = (listenerPvt *)ellFirst(&pwriteMessage->listenerPvtList);
while(plistenerPvt) {
while (plistenerPvt) {
listenerPvt *pnext = (listenerPvt *)ellNext(&plistenerPvt->node);
listener *plistener;
plistener = plistenerPvt->plistener;
listener *plistener = plistenerPvt->plistener;
pwriteMessage->message.userPvt = plistenerPvt->userPvt;
(*plistener->func)(&pwriteMessage->message,1);
ellDelete(&pwriteMessage->listenerPvtList,&plistenerPvt->node);
freeListFree(pasTrapWritePvt->freeListListenerPvt,(void *)plistenerPvt);
plistener->func(&pwriteMessage->message, 1);
ellDelete(&pwriteMessage->listenerPvtList, &plistenerPvt->node);
freeListFree(pasTrapWritePvt->freeListListenerPvt, plistenerPvt);
plistenerPvt = pnext;
}
ellDelete(&pasTrapWritePvt->writeMessageList,&pwriteMessage->node);
freeListFree(pasTrapWritePvt->freeListWriteMessage,(void *)pwriteMessage);
ellDelete(&pasTrapWritePvt->writeMessageList, &pwriteMessage->node);
freeListFree(pasTrapWritePvt->freeListWriteMessage, pwriteMessage);
epicsMutexUnlock(pasTrapWritePvt->lock);
}
+5 -3
View File
@@ -3,9 +3,8 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*asTrapWrite.h*/
/* Author: Marty Kraimer Date: 07NOV2000 */
@@ -24,6 +23,9 @@ typedef struct asTrapWriteMessage {
const char *hostid;
void *serverSpecific;
void *userPvt;
int dbrType; /* Data type from ca/db_access.h, NOT dbFldTypes.h */
int no_elements;
void *data; /* Might be NULL if no data is available */
} asTrapWriteMessage;
+1 -1
View File
@@ -70,7 +70,7 @@ static void epicsExceptionTestPrivate ()
try {
char * p = new ( nothrow )
char [unsuccessfulNewSize];
testOk(p == 0, "new (nothrow)");
testOk(p == 0, "new (nothrow) returned %p", p);
}
catch( ... ) {
testFail("new (nothrow): threw");
+22
View File
@@ -31,11 +31,26 @@ MAIN(epicsMathTest)
testOk1(epicsINF == epicsINF);
testOk1(epicsINF > 0.0);
testOk1(epicsINF - epicsINF != 0.0);
#if defined(_WIN64) && defined(_MSC_VER)
testTodoBegin("Known failure on windows-x64");
#endif
testOk1(epicsINF + -epicsINF != 0.0);
testOk1(-epicsINF + epicsINF != 0.0);
#if defined(_WIN64) && defined(_MSC_VER)
testTodoEnd();
#endif
testOk1(isnan(epicsINF - epicsINF));
#if defined(_WIN64) && defined(_MSC_VER)
testTodoBegin("Known failure on windows-x64");
#endif
testOk1(isnan(epicsINF + -epicsINF));
testOk1(isnan(-epicsINF + epicsINF));
#if defined(_WIN64) && defined(_MSC_VER)
testTodoEnd();
#endif
testOk1(isnan(epicsNAN));
testOk1(!isinf(epicsNAN));
@@ -46,8 +61,15 @@ MAIN(epicsMathTest)
testOk1(!(epicsNAN >= epicsNAN));
testOk1(!(epicsNAN > epicsNAN));
testOk1(isnan(epicsNAN - epicsNAN));
#if defined(_WIN64) && defined(_MSC_VER)
testTodoBegin("Known failure on windows-x64");
#endif
testOk1(isnan(epicsNAN + -epicsNAN));
testOk1(isnan(-epicsNAN + epicsNAN));
#if defined(_WIN64) && defined(_MSC_VER)
testTodoEnd();
#endif
c = huge / tiny;
testOk(!isnan(c), "!isnan(1e300 / 1e-300)");
+3 -3
View File
@@ -10,8 +10,6 @@
* $Revision-Id$
*
* Author W. Eric Norum
* norume@aps.anl.gov
* 630 252 4793
*/
#include <stdio.h>
#include <stdlib.h>
@@ -109,7 +107,7 @@ receiver(void *arg)
testDiag("Sender %d -- %d messages", sender, expectmsg[sender-1]-1);
}
if (!testOk1(errors == 0))
testDiag("error count was %d", errors);
testDiag("Receiver finished, error count was %d", errors);
epicsEventSignal(finished);
}
@@ -127,6 +125,7 @@ sender(void *arg)
epicsThreadSleep(0.005 * (randBelow(5)));
epicsThreadSleep(0.005 * (randBelow(20)));
}
testDiag("%s exiting, sent %d messages", epicsThreadGetNameSelf(), i-1);
}
extern "C" void messageQueueTest(void *parm)
@@ -293,6 +292,7 @@ MAIN(epicsMessageQueueTest)
messageQueueTest, NULL);
(void) epicsEventWait(finished);
epicsThreadSleep(1.0);
return testDone();
}