176 lines
5.9 KiB
C
176 lines
5.9 KiB
C
/*************************************************************************\
|
||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||
* National Laboratory.
|
||
* Copyright (c) 2002 The Regents of the University of California, as
|
||
* Operator of Los Alamos National Laboratory.
|
||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||
* in file LICENSE that is included with this distribution.
|
||
\*************************************************************************/
|
||
/*asTrapWrite.c */
|
||
/* Author: Marty Kraimer Date: 07NOV2000 */
|
||
|
||
/* Matthias Clausen and Vladis Korobov at DESY
|
||
* implemented the first logging of Channel Access Puts
|
||
* This implementation uses many ideas from their implementation
|
||
*/
|
||
|
||
#include <stdlib.h>
|
||
#include <stddef.h>
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
|
||
#define epicsExportSharedSymbols
|
||
#include "ellLib.h"
|
||
#include "freeList.h"
|
||
#include "epicsStdio.h"
|
||
#include "cantProceed.h"
|
||
#include "epicsMutex.h"
|
||
#include "ellLib.h"
|
||
|
||
#include "asLib.h"
|
||
#include "asTrapWrite.h"
|
||
|
||
typedef struct listenerPvt {
|
||
ELLNODE node;
|
||
struct listener *plistener;
|
||
void *userPvt;
|
||
}listenerPvt;
|
||
|
||
typedef struct listener{
|
||
ELLNODE node;
|
||
asTrapWriteListener func;
|
||
}listener;
|
||
|
||
typedef struct writeMessage {
|
||
ELLNODE node;
|
||
asTrapWriteMessage message;
|
||
ELLLIST listenerPvtList;
|
||
}writeMessage;
|
||
|
||
|
||
typedef struct asTrapWritePvt
|
||
{
|
||
ELLLIST listenerList;
|
||
ELLLIST writeMessageList;
|
||
void *freeListWriteMessage;
|
||
void *freeListListenerPvt;
|
||
epicsMutexId lock;
|
||
}asTrapWritePvt;
|
||
|
||
static asTrapWritePvt *pasTrapWritePvt = 0;
|
||
|
||
static void asTrapWriteInit(void)
|
||
{
|
||
pasTrapWritePvt = callocMustSucceed(1,sizeof(asTrapWritePvt),"asTrapWriteInit");
|
||
ellInit(&pasTrapWritePvt->listenerList);
|
||
ellInit(&pasTrapWritePvt->writeMessageList);
|
||
freeListInitPvt(
|
||
&pasTrapWritePvt->freeListWriteMessage,sizeof(writeMessage),20);
|
||
freeListInitPvt(
|
||
&pasTrapWritePvt->freeListListenerPvt,sizeof(listenerPvt),20);
|
||
pasTrapWritePvt->lock = epicsMutexMustCreate();
|
||
}
|
||
|
||
asTrapWriteId epicsShareAPI asTrapWriteRegisterListener(
|
||
asTrapWriteListener func)
|
||
{
|
||
listener *plistener;
|
||
if(pasTrapWritePvt==0) asTrapWriteInit();
|
||
plistener = callocMustSucceed(1,sizeof(listener),"asTrapWriteRegisterListener");
|
||
plistener->func = func;
|
||
epicsMutexMustLock(pasTrapWritePvt->lock);
|
||
ellAdd(&pasTrapWritePvt->listenerList,&plistener->node);
|
||
epicsMutexUnlock(pasTrapWritePvt->lock);
|
||
return((asTrapWriteId)plistener);
|
||
}
|
||
|
||
void epicsShareAPI asTrapWriteUnregisterListener(asTrapWriteId id)
|
||
{
|
||
listener *plistener = (listener *)id;
|
||
writeMessage *pwriteMessage;
|
||
|
||
if(pasTrapWritePvt==0) return;
|
||
epicsMutexMustLock(pasTrapWritePvt->lock);
|
||
pwriteMessage = (writeMessage *)ellFirst(&pasTrapWritePvt->writeMessageList);
|
||
while(pwriteMessage) {
|
||
listenerPvt *plistenerPvt
|
||
= (listenerPvt *)ellFirst(&pwriteMessage->listenerPvtList);
|
||
while(plistenerPvt) {
|
||
listenerPvt *pnext
|
||
= (listenerPvt *)ellNext(&plistenerPvt->node);
|
||
if(plistenerPvt->plistener == plistener) {
|
||
ellDelete(&pwriteMessage->listenerPvtList,&plistenerPvt->node);
|
||
freeListFree(pasTrapWritePvt->freeListListenerPvt, plistenerPvt);
|
||
}
|
||
plistenerPvt = pnext;
|
||
}
|
||
pwriteMessage = (writeMessage *)ellNext(&pwriteMessage->node);
|
||
}
|
||
ellDelete(&pasTrapWritePvt->listenerList,&plistener->node);
|
||
free(plistener);
|
||
epicsMutexUnlock(pasTrapWritePvt->lock);
|
||
}
|
||
|
||
void * epicsShareAPI asTrapWriteBeforeWithData(
|
||
const char *userid, const char *hostid, void *addr,
|
||
int dbrType, int no_elements, void *data)
|
||
{
|
||
writeMessage *pwriteMessage;
|
||
listener *plistener;
|
||
|
||
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);
|
||
plistener = (listener *)ellFirst(&pasTrapWritePvt->listenerList);
|
||
while (plistener) {
|
||
listenerPvt *plistenerPvt = (listenerPvt *)freeListCalloc(
|
||
pasTrapWritePvt->freeListListenerPvt);
|
||
|
||
plistenerPvt->plistener = plistener;
|
||
pwriteMessage->message.userPvt = 0;
|
||
plistener->func(&pwriteMessage->message, 0);
|
||
plistenerPvt->userPvt = pwriteMessage->message.userPvt;
|
||
ellAdd(&pwriteMessage->listenerPvtList, &plistenerPvt->node);
|
||
plistener = (listener *)ellNext(&plistener->node);
|
||
}
|
||
epicsMutexUnlock(pasTrapWritePvt->lock);
|
||
return pwriteMessage;
|
||
}
|
||
|
||
void epicsShareAPI asTrapWriteAfterWrite(void *pvt)
|
||
{
|
||
writeMessage *pwriteMessage = (writeMessage *)pvt;
|
||
listenerPvt *plistenerPvt;
|
||
|
||
if (pwriteMessage == 0 ||
|
||
pasTrapWritePvt == 0) return;
|
||
|
||
epicsMutexMustLock(pasTrapWritePvt->lock);
|
||
plistenerPvt = (listenerPvt *)ellFirst(&pwriteMessage->listenerPvtList);
|
||
while (plistenerPvt) {
|
||
listenerPvt *pnext = (listenerPvt *)ellNext(&plistenerPvt->node);
|
||
listener *plistener = plistenerPvt->plistener;
|
||
|
||
pwriteMessage->message.userPvt = plistenerPvt->userPvt;
|
||
plistener->func(&pwriteMessage->message, 1);
|
||
ellDelete(&pwriteMessage->listenerPvtList, &plistenerPvt->node);
|
||
freeListFree(pasTrapWritePvt->freeListListenerPvt, plistenerPvt);
|
||
plistenerPvt = pnext;
|
||
}
|
||
ellDelete(&pasTrapWritePvt->writeMessageList, &pwriteMessage->node);
|
||
freeListFree(pasTrapWritePvt->freeListWriteMessage, pwriteMessage);
|
||
epicsMutexUnlock(pasTrapWritePvt->lock);
|
||
}
|