This is Unofficial EPICS BASE Doxygen Site
sync.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2010 Brookhaven National Laboratory.
3 * Copyright (c) 2010 Helmholtz-Zentrum Berlin
4 * fuer Materialien und Energie GmbH.
5 * EPICS BASE is distributed subject to a Software License Agreement found
6 * in file LICENSE that is included with this distribution.
7 \*************************************************************************/
8 
9 /*
10  * Author: Ralph Lange <Ralph.Lange@bessy.de>
11  */
12 
13 #include <stdio.h>
14 
15 #include "freeList.h"
16 #include "db_field_log.h"
17 #include "chfPlugin.h"
18 #include "dbState.h"
19 #include "epicsExit.h"
20 #include "epicsAssert.h"
21 #include "epicsExport.h"
22 
23 #define STATE_NAME_LENGTH 20
24 
25 typedef enum syncMode {
32 } syncMode;
33 
34 static const
35 chfPluginEnumType modeEnum[] = {
36  {"before", syncModeBefore},
37  {"first", syncModeFirst},
38  {"last", syncModeLast},
39  {"after", syncModeAfter},
40  {"while", syncModeWhile},
41  {"unless", syncModeUnless},
42  {NULL, 0}
43 };
44 
45 typedef struct myStruct {
48  dbStateId id;
49  db_field_log *lastfl;
50  int laststate:1;
51 } myStruct;
52 
53 static void *myStructFreeList;
54 
55 static const
56 chfPluginArgDef opts[] = {
57  chfEnum (myStruct, mode, "m", 1, 1, modeEnum),
58  chfString (myStruct, state, "s", 1, 0),
59  chfTagString (myStruct, state, "before", mode, 0, 1, 0),
60  chfTagString (myStruct, state, "first", mode, 1, 1, 0),
61  chfTagString (myStruct, state, "last", mode, 2, 1, 0),
62  chfTagString (myStruct, state, "after", mode, 3, 1, 0),
63  chfTagString (myStruct, state, "while", mode, 4, 1, 0),
64  chfTagString (myStruct, state, "unless", mode, 5, 1, 0),
65  chfPluginArgEnd
66 };
67 
68 static void * allocPvt(void)
69 {
70  myStruct *my = (myStruct*) freeListCalloc(myStructFreeList);
71  return (void *) my;
72 }
73 
74 static void freePvt(void *pvt)
75 {
76  myStruct *my = (myStruct*) pvt;
77  db_delete_field_log(my->lastfl);
78  freeListFree(myStructFreeList, pvt);
79 }
80 
81 static int parse_ok(void *pvt)
82 {
83  myStruct *my = (myStruct*) pvt;
84 
85  if (!(my->id = dbStateFind(my->state)))
86  return -1;
87 
88  return 0;
89 }
90 
91 static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl) {
92  db_field_log *passfl = NULL;
93  myStruct *my = (myStruct*) pvt;
94  int actstate;
95 
96  if (pfl->ctx == dbfl_context_read)
97  return pfl;
98 
99  actstate = dbStateGet(my->id);
100 
101  switch (my->mode) {
102  case syncModeBefore:
103  if (actstate && !my->laststate) {
104  passfl = my->lastfl;
105  my->lastfl = NULL;
106  }
107  break;
108  case syncModeFirst:
109  if (actstate && !my->laststate) {
110  passfl = pfl;
111  pfl = NULL;
112  }
113  else
114  db_delete_field_log(pfl);
115  goto save_state;
116  case syncModeLast:
117  if (!actstate && my->laststate) {
118  passfl = my->lastfl;
119  my->lastfl = NULL;
120  }
121  break;
122  case syncModeAfter:
123  if (!actstate && my->laststate) {
124  passfl = pfl;
125  pfl = NULL;
126  }
127  else
128  db_delete_field_log(pfl);
129  goto save_state;
130  case syncModeWhile:
131  if (actstate)
132  passfl = pfl;
133  else
134  db_delete_field_log(pfl);
135  goto no_shift;
136  case syncModeUnless:
137  if (!actstate)
138  passfl = pfl;
139  else
140  db_delete_field_log(pfl);
141  goto no_shift;
142  }
143 
144  if (my->lastfl)
145  db_delete_field_log(my->lastfl);
146  my->lastfl = pfl;
147 
148  /* since no copy is made we can't keep a reference to the returned fl */
149  assert(my->lastfl != passfl);
150 
151 save_state:
152  my->laststate = actstate;
153 
154 no_shift:
155  return passfl;
156 }
157 
158 static void channelRegisterPre(dbChannel *chan, void *pvt,
159  chPostEventFunc **cb_out, void **arg_out, db_field_log *probe)
160 {
161  *cb_out = filter;
162  *arg_out = pvt;
163 }
164 
165 static void channel_report(dbChannel *chan, void *pvt, int level, const unsigned short indent)
166 {
167  myStruct *my = (myStruct*) pvt;
168  printf("%*sSynchronize (sync): mode=%s, state=%s\n", indent, "",
169  chfPluginEnumString(modeEnum, my->mode, "n/a"), my->state);
170 }
171 
172 static chfPluginIf pif = {
173  allocPvt,
174  freePvt,
175 
176  NULL, /* parse_error, */
177  parse_ok,
178 
179  NULL, /* channel_open, */
180  channelRegisterPre,
181  NULL, /* channelRegisterPost, */
182  channel_report,
183  NULL /* channel_close */
184 };
185 
186 static void syncShutdown(void* ignore)
187 {
188  if(myStructFreeList)
189  freeListCleanup(myStructFreeList);
190  myStructFreeList = NULL;
191 }
192 
193 static void syncInitialize(void)
194 {
195  if (!myStructFreeList)
196  freeListInitPvt(&myStructFreeList, sizeof(myStruct), 64);
197 
198  chfPluginRegister("sync", &pif, opts);
199  epicsAtExit(syncShutdown, NULL);
200 }
201 
202 epicsExportRegistrar(syncInitialize);
LIBCOM_API void *epicsStdCall freeListCalloc(void *pvt)
Definition: freeListLib.c:60
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
Definition: arr.c:26
An EPICS-specific replacement for ANSI C&#39;s assert.
struct myStruct myStruct
epicsExportRegistrar(syncInitialize)
db_field_log * lastfl
Definition: sync.c:49
#define printf
Definition: epicsStdio.h:41
#define NULL
Definition: catime.c:38
LIBCOM_API void epicsStdCall freeListInitPvt(void **ppvt, int size, int nmalloc)
Definition: freeListLib.c:44
int mode
Definition: dbnd.c:26
syncMode
Definition: sync.c:25
LIBCOM_API void epicsStdCall freeListCleanup(void *pvt)
Definition: freeListLib.c:152
LIBCOM_API void epicsStdCall freeListFree(void *pvt, void *pmem)
Definition: freeListLib.c:131
Extended replacement for the Posix exit and atexit routines.
char state[STATE_NAME_LENGTH]
Definition: sync.c:47
dbStateId id
Definition: sync.c:48
#define epicsAtExit(F, A)
Convenience macro to register a function and context value to be run when the process exits...
Definition: epicsExit.h:70
int laststate
Definition: sync.c:50
syncMode mode
Definition: sync.c:46
#define STATE_NAME_LENGTH
Definition: sync.c:23
Exporting IOC objects.