diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index f95eb2e03..837b7e024 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -13,6 +13,31 @@ +
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.
+ +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:
+ +++#include "asLib.h" + +/* ... */ + +#ifdef asTrapWriteWithData + /* Enhanced API */ +#endif +
tapfilesbuild target from 3.15
This GNUmake target runs the same tests as the runtests
target, but
diff --git a/src/as/asLib.h b/src/as/asLib.h
index b3da2f836..2a420a23b 100644
--- a/src/as/asLib.h
+++ b/src/as/asLib.h
@@ -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);
diff --git a/src/as/asTrapWrite.c b/src/as/asTrapWrite.c
index 7c2536f93..65a77f09f 100644
--- a/src/as/asTrapWrite.c
+++ b/src/as/asTrapWrite.c
@@ -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 */
@@ -100,47 +99,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)
@@ -148,20 +153,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);
}
diff --git a/src/as/asTrapWrite.h b/src/as/asTrapWrite.h
index ec34c5312..b8033cb94 100644
--- a/src/as/asTrapWrite.h
+++ b/src/as/asTrapWrite.h
@@ -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;
diff --git a/src/rsrv/camessage.c b/src/rsrv/camessage.c
index e0521cf3a..e6c4330ab 100644
--- a/src/rsrv/camessage.c
+++ b/src/rsrv/camessage.c
@@ -811,10 +811,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 : "",
- (void *) &pciu->addr );
+ (void *) &pciu->addr, mp->m_dataType, mp->m_count, pPayload );
dbStatus = db_put_field(
&pciu->addr,
@@ -1816,11 +1816,12 @@ static int write_notify_action ( caHdrLargeArray *mp, void *pPayload,
return RSRV_OK;
}
- pciu->pPutNotify->asWritePvt = asTrapWriteBefore (
+ pciu->pPutNotify->asWritePvt = asTrapWriteWithData (
pciu->asClientPVT,
pciu->client->pUserName ? pciu->client->pUserName : "",
pciu->client->pHostName ? pciu->client->pHostName : "",
- (void *) &pciu->addr );
+ (void *) &pciu->addr, mp->m_dataType, mp->m_count,
+ pciu->pPutNotify->dbPutNotify.pbuffer );
dbPutNotify(&pciu->pPutNotify->dbPutNotify);