This is Unofficial EPICS BASE Doxygen Site
asTrapWrite.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /*asTrapWrite.c */
10 /* Author: Marty Kraimer Date: 07NOV2000 */
11 
12 /* Matthias Clausen and Vladis Korobov at DESY
13  * implemented the first logging of Channel Access Puts
14  * This implementation uses many ideas from their implementation
15 */
16 
17 #include <stdlib.h>
18 #include <stddef.h>
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include "ellLib.h"
23 #include "freeList.h"
24 #include "epicsStdio.h"
25 #include "cantProceed.h"
26 #include "epicsMutex.h"
27 #include "ellLib.h"
28 
29 #include "asLib.h"
30 #include "asTrapWrite.h"
31 
32 typedef struct listenerPvt {
35  void *userPvt;
37 
38 typedef struct listener{
41 }listener;
42 
43 typedef struct writeMessage {
48 
49 
50 typedef struct asTrapWritePvt
51 {
58 
59 static asTrapWritePvt *pasTrapWritePvt = 0;
60 
61 static void asTrapWriteInit(void)
62 {
63  pasTrapWritePvt = callocMustSucceed(1,sizeof(asTrapWritePvt),"asTrapWriteInit");
64  ellInit(&pasTrapWritePvt->listenerList);
65  ellInit(&pasTrapWritePvt->writeMessageList);
67  &pasTrapWritePvt->freeListWriteMessage,sizeof(writeMessage),20);
69  &pasTrapWritePvt->freeListListenerPvt,sizeof(listenerPvt),20);
70  pasTrapWritePvt->lock = epicsMutexMustCreate();
71 }
72 
75 {
77  if(pasTrapWritePvt==0) asTrapWriteInit();
78  plistener = callocMustSucceed(1,sizeof(listener),"asTrapWriteRegisterListener");
79  plistener->func = func;
80  epicsMutexMustLock(pasTrapWritePvt->lock);
81  ellAdd(&pasTrapWritePvt->listenerList,&plistener->node);
82  epicsMutexUnlock(pasTrapWritePvt->lock);
83  return((asTrapWriteId)plistener);
84 }
85 
87 {
88  listener *plistener = (listener *)id;
89  writeMessage *pwriteMessage;
90 
91  if(pasTrapWritePvt==0) return;
92  epicsMutexMustLock(pasTrapWritePvt->lock);
93  pwriteMessage = (writeMessage *)ellFirst(&pasTrapWritePvt->writeMessageList);
94  while(pwriteMessage) {
95  listenerPvt *plistenerPvt
96  = (listenerPvt *)ellFirst(&pwriteMessage->listenerPvtList);
97  while(plistenerPvt) {
98  listenerPvt *pnext
99  = (listenerPvt *)ellNext(&plistenerPvt->node);
100  if(plistenerPvt->plistener == plistener) {
101  ellDelete(&pwriteMessage->listenerPvtList,&plistenerPvt->node);
102  freeListFree(pasTrapWritePvt->freeListListenerPvt, plistenerPvt);
103  }
104  plistenerPvt = pnext;
105  }
106  pwriteMessage = (writeMessage *)ellNext(&pwriteMessage->node);
107  }
108  ellDelete(&pasTrapWritePvt->listenerList,&plistener->node);
109  free(plistener);
110  epicsMutexUnlock(pasTrapWritePvt->lock);
111 }
112 
113 void * epicsStdCall asTrapWriteBeforeWithData(
114  const char *userid, const char *hostid, void *addr,
115  int dbrType, int no_elements, void *data)
116 {
117  writeMessage *pwriteMessage;
119 
120  if (pasTrapWritePvt == 0 ||
121  ellCount(&pasTrapWritePvt->listenerList) <= 0) return 0;
122 
123  pwriteMessage = (writeMessage *)freeListCalloc(
124  pasTrapWritePvt->freeListWriteMessage);
125  pwriteMessage->message.userid = userid;
126  pwriteMessage->message.hostid = hostid;
127  pwriteMessage->message.serverSpecific = addr;
128  pwriteMessage->message.dbrType = dbrType;
129  pwriteMessage->message.no_elements = no_elements;
130  pwriteMessage->message.data = data;
131  ellInit(&pwriteMessage->listenerPvtList);
132 
133  epicsMutexMustLock(pasTrapWritePvt->lock);
134  ellAdd(&pasTrapWritePvt->writeMessageList, &pwriteMessage->node);
135  plistener = (listener *)ellFirst(&pasTrapWritePvt->listenerList);
136  while (plistener) {
137  listenerPvt *plistenerPvt = (listenerPvt *)freeListCalloc(
138  pasTrapWritePvt->freeListListenerPvt);
139 
140  plistenerPvt->plistener = plistener;
141  pwriteMessage->message.userPvt = 0;
142  plistener->func(&pwriteMessage->message, 0);
143  plistenerPvt->userPvt = pwriteMessage->message.userPvt;
144  ellAdd(&pwriteMessage->listenerPvtList, &plistenerPvt->node);
145  plistener = (listener *)ellNext(&plistener->node);
146  }
147  epicsMutexUnlock(pasTrapWritePvt->lock);
148  return pwriteMessage;
149 }
150 
151 void epicsStdCall asTrapWriteAfterWrite(void *pvt)
152 {
153  writeMessage *pwriteMessage = (writeMessage *)pvt;
154  listenerPvt *plistenerPvt;
155 
156  if (pwriteMessage == 0 ||
157  pasTrapWritePvt == 0) return;
158 
159  epicsMutexMustLock(pasTrapWritePvt->lock);
160  plistenerPvt = (listenerPvt *)ellFirst(&pwriteMessage->listenerPvtList);
161  while (plistenerPvt) {
162  listenerPvt *pnext = (listenerPvt *)ellNext(&plistenerPvt->node);
163  listener *plistener = plistenerPvt->plistener;
164 
165  pwriteMessage->message.userPvt = plistenerPvt->userPvt;
166  plistener->func(&pwriteMessage->message, 1);
167  ellDelete(&pwriteMessage->listenerPvtList, &plistenerPvt->node);
168  freeListFree(pasTrapWritePvt->freeListListenerPvt, plistenerPvt);
169  plistenerPvt = pnext;
170  }
171  ellDelete(&pasTrapWritePvt->writeMessageList, &pwriteMessage->node);
172  freeListFree(pasTrapWritePvt->freeListWriteMessage, pwriteMessage);
173  epicsMutexUnlock(pasTrapWritePvt->lock);
174 }
LIBCOM_API void *epicsStdCall freeListCalloc(void *pvt)
Definition: freeListLib.c:60
void * freeListWriteMessage
Definition: asTrapWrite.c:54
void * userPvt
Definition: asTrapWrite.c:35
struct asTrapWritePvt asTrapWritePvt
ELLNODE node
Definition: asTrapWrite.c:44
epicsMutexId lock
Definition: asTrapWrite.c:56
int dbrType
Data type from ca/db_access.h, NOT dbFldTypes.h.
Definition: asTrapWrite.h:50
#define ellCount(PLIST)
Report the number of nodes in a list.
Definition: ellLib.h:84
asTrapWriteListener func
Definition: asTrapWrite.c:40
void * serverSpecific
A field for use by the server.
Definition: asTrapWrite.h:41
ELLNODE node
Definition: asTrapWrite.c:33
void * data
Might be NULL if no data is available.
Definition: asTrapWrite.h:52
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
Definition: epicsMutex.h:179
void * asTrapWriteId
An identifier needed to unregister an listener.
Definition: asTrapWrite.h:58
LIBCOM_API void epicsStdCall freeListInitPvt(void **ppvt, int size, int nmalloc)
Definition: freeListLib.c:44
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
ELLLIST writeMessageList
Definition: asTrapWrite.c:53
void * userPvt
A field for use by the asTrapWriteListener.
Definition: asTrapWrite.h:49
const char * hostid
Hostid of whoever orginated the request.
Definition: asTrapWrite.h:33
struct listener listener
A doubly-linked list library.
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
void *epicsStdCall asTrapWriteBeforeWithData(const char *userid, const char *hostid, void *addr, int dbrType, int no_elements, void *data)
Definition: asTrapWrite.c:113
APIs for the epicsMutex mutual exclusion semaphore.
LIBCOM_API void epicsStdCall freeListFree(void *pvt, void *pmem)
Definition: freeListLib.c:131
ELLLIST listenerList
Definition: asTrapWrite.c:52
struct listener * plistener
Definition: asTrapWrite.c:34
struct writeMessage writeMessage
void epicsStdCall asTrapWriteAfterWrite(void *pvt)
Definition: asTrapWrite.c:151
asTrapWriteMessage message
Definition: asTrapWrite.c:45
LIBCOM_API void * callocMustSucceed(size_t count, size_t size, const char *msg)
A calloc() that never returns NULL.
Definition: cantProceed.c:22
ELLNODE node
Definition: asTrapWrite.c:39
The message passed to registered listeners.
Definition: asTrapWrite.h:31
List node type.
Definition: ellLib.h:45
void epicsStdCall asTrapWriteUnregisterListener(asTrapWriteId id)
Unregister asTrapWriteListener.
Definition: asTrapWrite.c:86
const char * userid
Userid of whoever orginated the request.
Definition: asTrapWrite.h:32
struct listenerPvt listenerPvt
#define ellInit(PLIST)
Initialize a list type.
Definition: ellLib.h:76
ELLLIST listenerPvtList
Definition: asTrapWrite.c:46
void(* asTrapWriteListener)(asTrapWriteMessage *pmessage, int after)
Pointer to a listener function.
Definition: asTrapWrite.h:74
void * freeListListenerPvt
Definition: asTrapWrite.c:55
Routines for code that can&#39;t continue or return after an error.
API for monitoring external put operations to an IOC.
List header type.
Definition: ellLib.h:56
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
Definition: epicsMutex.h:214
int no_elements
Array length.
Definition: asTrapWrite.h:51
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
Definition: ellLib.c:75
asTrapWriteId epicsStdCall asTrapWriteRegisterListener(asTrapWriteListener func)
Register function to be called on asTrapWriteListener.
Definition: asTrapWrite.c:73
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89