Merge lp:~epics-core/epics-base/server-side-plugins into lp:~epics-core/epics-base/3.15

Proposed by mdavidsaver
Status: Merged
Merged at revision: 12295
Proposed branch: lp:~epics-core/epics-base/server-side-plugins
Merge into: lp:~epics-core/epics-base/3.15
Diff against target: 20253 lines (+11599/-2941) (has conflicts)
101 files modified
.bzrignore (+3/-0)
configure/RULES.Db (+2/-2)
src/Makefile (+4/-0)
src/ioc/as/asDbLib.c (+13/-21)
src/ioc/as/asDbLib.h (+6/-4)
src/ioc/db/Makefile (+11/-0)
src/ioc/db/chfPlugin.c (+649/-0)
src/ioc/db/chfPlugin.h (+280/-0)
src/ioc/db/dbAccess.c (+309/-705)
src/ioc/db/dbAccess.h (+2/-2)
src/ioc/db/dbAccessDefs.h (+8/-53)
src/ioc/db/dbAddr.h (+1/-4)
src/ioc/db/dbBkpt.c (+1/-0)
src/ioc/db/dbCAC.h (+34/-34)
src/ioc/db/dbCa.c (+8/-1)
src/ioc/db/dbCa.h (+1/-0)
src/ioc/db/dbChannel.c (+865/-0)
src/ioc/db/dbChannel.h (+181/-0)
src/ioc/db/dbChannelIO.cpp (+67/-59)
src/ioc/db/dbChannelIO.h (+33/-34)
src/ioc/db/dbContext.cpp (+72/-71)
src/ioc/db/dbContextReadNotifyCache.cpp (+19/-19)
src/ioc/db/dbEvent.c (+277/-235)
src/ioc/db/dbEvent.h (+18/-11)
src/ioc/db/dbExtractArray.c (+84/-0)
src/ioc/db/dbExtractArray.h (+34/-0)
src/ioc/db/dbIocRegister.c (+58/-0)
src/ioc/db/dbLink.c (+648/-0)
src/ioc/db/dbLink.h (+94/-0)
src/ioc/db/dbNotify.c (+197/-194)
src/ioc/db/dbNotify.h (+11/-11)
src/ioc/db/dbPutNotifyBlocker.cpp (+21/-21)
src/ioc/db/dbPutNotifyBlocker.h (+14/-14)
src/ioc/db/dbState.c (+108/-0)
src/ioc/db/dbState.h (+92/-0)
src/ioc/db/dbSubscriptionIO.cpp (+22/-22)
src/ioc/db/db_access.c (+131/-152)
src/ioc/db/db_access_routines.h (+11/-17)
src/ioc/db/db_field_log.h (+56/-13)
src/ioc/db/db_test.c (+191/-661)
src/ioc/db/recGbl.c (+9/-53)
src/ioc/db/test/Makefile (+24/-0)
src/ioc/db/test/arrShorthandTest.c (+139/-0)
src/ioc/db/test/chfPluginTest.c (+832/-0)
src/ioc/db/test/dbChannelTest.c (+261/-0)
src/ioc/db/test/dbChannelTest.db (+2/-0)
src/ioc/db/test/dbStateTest.c (+56/-0)
src/ioc/db/test/xRecord.dbd (+12/-0)
src/ioc/dbStatic/dbBase.h (+5/-4)
src/ioc/dbStatic/dbPvdLib.c (+1/-0)
src/ioc/dbStatic/dbStaticLib.c (+80/-79)
src/ioc/dbStatic/link.h (+23/-26)
src/ioc/misc/iocInit.c (+7/-36)
src/ioc/registry/registerRecordDeviceDriver.pl (+7/-1)
src/ioc/rsrv/camessage.c (+324/-280)
src/ioc/rsrv/caservertask.c (+66/-71)
src/ioc/rsrv/server.h (+15/-15)
src/libCom/Makefile (+1/-0)
src/libCom/ellLib/ellLib.c (+17/-2)
src/libCom/ellLib/ellLib.h (+6/-4)
src/libCom/gpHash/gpHash.h (+3/-1)
src/libCom/gpHash/gpHashLib.c (+15/-9)
src/libCom/yajl/Makefile (+26/-0)
src/libCom/yajl/yajl.c (+160/-0)
src/libCom/yajl/yajl_alloc.c (+67/-0)
src/libCom/yajl/yajl_alloc.h (+50/-0)
src/libCom/yajl/yajl_buf.c (+120/-0)
src/libCom/yajl/yajl_buf.h (+73/-0)
src/libCom/yajl/yajl_bytestack.h (+85/-0)
src/libCom/yajl/yajl_common.h (+76/-0)
src/libCom/yajl/yajl_encode.c (+189/-0)
src/libCom/yajl/yajl_encode.h (+50/-0)
src/libCom/yajl/yajl_gen.c (+317/-0)
src/libCom/yajl/yajl_gen.h (+159/-0)
src/libCom/yajl/yajl_lex.c (+738/-0)
src/libCom/yajl/yajl_lex.h (+133/-0)
src/libCom/yajl/yajl_parse.h (+193/-0)
src/libCom/yajl/yajl_parser.c (+449/-0)
src/libCom/yajl/yajl_parser.h (+82/-0)
src/std/Makefile (+1/-0)
src/std/dev/Makefile (+2/-0)
src/std/dev/devBiDbState.c (+92/-0)
src/std/dev/devBoDbState.c (+86/-0)
src/std/dev/devSoft.dbd (+3/-0)
src/std/filters/Makefile (+18/-0)
src/std/filters/arr.c (+207/-0)
src/std/filters/dbnd.c (+142/-0)
src/std/filters/filters.dbd (+4/-0)
src/std/filters/sync.c (+172/-0)
src/std/filters/test/Makefile (+45/-0)
src/std/filters/test/arrRecord.c (+135/-0)
src/std/filters/test/arrRecord.dbd (+33/-0)
src/std/filters/test/arrTest.cpp (+337/-0)
src/std/filters/test/arrTest.db (+15/-0)
src/std/filters/test/dbChannelTest.db (+2/-0)
src/std/filters/test/dbndTest.c (+235/-0)
src/std/filters/test/syncTest.c (+367/-0)
src/std/filters/test/tsTest.c (+113/-0)
src/std/filters/test/xRecord.dbd (+12/-0)
src/std/filters/ts.c (+67/-0)
src/std/softIoc/base.dbd (+3/-0)
Text conflict in src/ioc/db/db_test.c
To merge this branch: bzr merge lp:~epics-core/epics-base/server-side-plugins
Reviewer Review Type Date Requested Status
Ralph Lange Pending
EPICS Core Developers Pending
Review via email: mp+108028@code.launchpad.net

Description of the change

This branch takes the changes from

lp:~ralph-lange/epics-base/server-side-plugins

And updates them to the current 3.15 branch. So when reviewing the changes please check also for unintentionally reverted changes from the 3.15 branch.

To post a comment you must log in.
Revision history for this message
Andrew Johnson (anj) wrote :

I've moved the filter plugins to src/std, which build Ok now, and am making some changes to the filter tests. I've copied the xRecord.dbd file and dbChannelTest.db into the filter/test directory rather than try to use them from some remote directory. Successfully loading the .dbd and .db files should not be counted as tests, they are pre-conditions of the actual tests to be able to run, so if they fail the test code should call call testAbort().

Is chfPluginTest.t supposed to produce these warnings?
  chfPluginTest.t ..... 1/1755
  Plugin buggy: provided storage (2 bytes) for i is too small for long (4)
  Plugin buggy: provided storage (2 bytes) for d is too small for double (8)
  Plugin buggy: provided storage (2 bytes) for s is too small for string (>= 4)
  Plugin buggy: provided storage (2 bytes) for c is too small for enum (4)
  chfPluginTest.t ..... ok

All the tests pass on linux-x86, but when I run them on 64-bit Linux chfPluginTest.t fails lots of tests and then core-dumps. I also get the following warning from arrTest and a similar core-dump:
  Plugin arr: provided storage (4 bytes) for s is too small for long (8)
Looking more deeply, the code inside chfPlugin.c is using long data types when it should be using epicsInt32. I'm working on fixing this, but it might take some time.

12360. By Andrew Johnson

Moved filter plugins, fixed portability issues.

The filter plugins are now in src/std/filters
and their tests in the test subdirectory.

Various portability issues found and fixed:
 * Variable declarations after statements in a block
 * Code assuming that epicsInt32 = long
 * // comments in C files

Removed a number of tests that weren't really tests;
preconditions for future tests that don't actually check
the code being tested should call testAbort() if the
condition fails, which tells the test harness that you
meant to die at that point.

Split up lots of very long source lines.

Probably made a few other changes that I forget about now.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.bzrignore'
--- .bzrignore 2009-12-23 21:06:44 +0000
+++ .bzrignore 2012-06-21 20:42:45 +0000
@@ -6,3 +6,6 @@
6./include6./include
7./templates7./templates
8**/O.*8**/O.*
9./.cproject
10./.project
11./.settings
912
=== modified file 'configure/RULES.Db'
--- configure/RULES.Db 2012-05-29 21:44:49 +0000
+++ configure/RULES.Db 2012-06-21 20:42:45 +0000
@@ -397,12 +397,12 @@
397397
398%_registerRecordDeviceDriver.cpp: $(COMMON_DIR)/%.dbd 398%_registerRecordDeviceDriver.cpp: $(COMMON_DIR)/%.dbd
399 @$(RM) $@ $*.tmp399 @$(RM) $@ $*.tmp
400 $(REGISTERRECORDDEVICEDRIVER) $< $(basename $@) $(IOC_INST_TOP) > $*.tmp400 $(REGISTERRECORDDEVICEDRIVER) $(DBDFLAGS) $< $(basename $@) $(IOC_INST_TOP) > $*.tmp
401 $(MV) $*.tmp $@401 $(MV) $*.tmp $@
402402
403%_registerRecordDeviceDriver.cpp: %.dbd 403%_registerRecordDeviceDriver.cpp: %.dbd
404 @$(RM) $@ $*.tmp404 @$(RM) $@ $*.tmp
405 $(REGISTERRECORDDEVICEDRIVER) $< $(basename $@) $(IOC_INST_TOP) > $*.tmp405 $(REGISTERRECORDDEVICEDRIVER) $(DBDFLAGS) $< $(basename $@) $(IOC_INST_TOP) > $*.tmp
406 $(MV) $*.tmp $@406 $(MV) $*.tmp $@
407407
408.PRECIOUS: %_registerRecordDeviceDriver.cpp408.PRECIOUS: %_registerRecordDeviceDriver.cpp
409409
=== modified file 'src/Makefile'
--- src/Makefile 2012-03-14 20:27:40 +0000
+++ src/Makefile 2012-06-21 20:42:45 +0000
@@ -69,6 +69,10 @@
69DIRS += std69DIRS += std
70std_DEPEND_DIRS = ioc libCom/RTEMS70std_DEPEND_DIRS = ioc libCom/RTEMS
7171
72DIRS += std/filters/test
73std/filters/test_DEPEND_DIRS = std
74
75
7276
73include $(TOP)/configure/RULES_DIRS77include $(TOP)/configure/RULES_DIRS
7478
7579
=== modified file 'src/ioc/as/asDbLib.c'
--- src/ioc/as/asDbLib.c 2012-05-03 17:19:34 +0000
+++ src/ioc/as/asDbLib.c 2012-06-21 20:42:45 +0000
@@ -6,7 +6,7 @@
6* Operator of Los Alamos National Laboratory.6* Operator of Los Alamos National Laboratory.
7* EPICS BASE Versions 3.13.77* EPICS BASE Versions 3.13.7
8* and higher are distributed subject to a Software License Agreement found8* and higher are distributed subject to a Software License Agreement found
9* in file LICENSE that is included with this distribution. 9* in file LICENSE that is included with this distribution.
10\*************************************************************************/10\*************************************************************************/
11/* Author: Marty Kraimer Date: 02-11-94*/11/* Author: Marty Kraimer Date: 02-11-94*/
1212
@@ -27,7 +27,7 @@
27#include "caeventmask.h"27#include "caeventmask.h"
28#include "callback.h"28#include "callback.h"
29#include "dbStaticLib.h"29#include "dbStaticLib.h"
30#include "dbAddr.h"30#include "dbChannel.h"
31#include "dbAccess.h"31#include "dbAccess.h"
32#include "db_field_log.h"32#include "db_field_log.h"
33#include "dbEvent.h"33#include "dbEvent.h"
@@ -40,7 +40,7 @@
40static char *psubstitutions=NULL;40static char *psubstitutions=NULL;
41static epicsThreadId asInitTheadId=0;41static epicsThreadId asInitTheadId=0;
42static int firstTime = TRUE;42static int firstTime = TRUE;
43
4443
44
45static long asDbAddRecords(void)45static long asDbAddRecords(void)
46{46{
47 DBENTRY dbentry;47 DBENTRY dbentry;
@@ -98,7 +98,7 @@
98 }98 }
99 return(0);99 return(0);
100}100}
101
102101
102
103static void asSpcAsCallback(struct dbCommon *precord)103static void asSpcAsCallback(struct dbCommon *precord)
104{104{
105 asChangeGroup(&precord->asp, precord->asg);105 asChangeGroup(&precord->asp, precord->asg);
@@ -109,7 +109,7 @@
109 int *firstTime = (int *)arg;109 int *firstTime = (int *)arg;
110 *firstTime = FALSE;110 *firstTime = FALSE;
111}111}
112 112
113static long asInitCommon(void)113static long asInitCommon(void)
114{114{
115 long status;115 long status;
@@ -117,7 +117,7 @@
117 int wasFirstTime = firstTime;117 int wasFirstTime = firstTime;
118 static epicsThreadOnceId asInitCommonOnceFlag = EPICS_THREAD_ONCE_INIT;118 static epicsThreadOnceId asInitCommonOnceFlag = EPICS_THREAD_ONCE_INIT;
119119
120 120
121 epicsThreadOnce(&asInitCommonOnceFlag,asInitCommonOnce,(void *)&firstTime);121 epicsThreadOnce(&asInitCommonOnceFlag,asInitCommonOnce,(void *)&firstTime);
122 if(wasFirstTime) {122 if(wasFirstTime) {
123 if(!pacf) return(0); /*access security will NEVER be turned on*/123 if(!pacf) return(0); /*access security will NEVER be turned on*/
@@ -148,7 +148,7 @@
148{148{
149 return(asInitCommon());149 return(asInitCommon());
150}150}
151
152151
152
153static void wdCallback(void *arg)153static void wdCallback(void *arg)
154{154{
155 ASDBCALLBACK *pcallback = (ASDBCALLBACK *)arg;155 ASDBCALLBACK *pcallback = (ASDBCALLBACK *)arg;
@@ -195,23 +195,15 @@
195 }195 }
196 return(0);196 return(0);
197}197}
198
199198
200int epicsShareAPI asDbGetAsl(void *paddress)199
200int epicsShareAPI asDbGetAsl(struct dbChannel *chan)
201{201{
202 DBADDR *paddr = paddress;202 return dbChannelFldDes(chan)->as_level;
203 dbFldDes *pflddes;
204
205 pflddes = paddr->pfldDes;
206 return((int)pflddes->as_level);
207}203}
208204
209void * epicsShareAPI asDbGetMemberPvt(void *paddress)205void * epicsShareAPI asDbGetMemberPvt(struct dbChannel *chan)
210{206{
211 DBADDR *paddr = paddress;207 return dbChannelRecord(chan)->asp;
212 dbCommon *precord;
213
214 precord = paddr->precord;
215 return((void *)precord->asp);
216}208}
217209
218static void astacCallback(ASCLIENTPVT clientPvt,asClientStatus status)210static void astacCallback(ASCLIENTPVT clientPvt,asClientStatus status)
@@ -259,7 +251,7 @@
259 }251 }
260 return(0);252 return(0);
261}253}
262
263254
255
264static void myMemberCallback(ASMEMBERPVT memPvt,FILE *fp)256static void myMemberCallback(ASMEMBERPVT memPvt,FILE *fp)
265{257{
266 dbCommon *precord;258 dbCommon *precord;
267259
=== modified file 'src/ioc/as/asDbLib.h'
--- src/ioc/as/asDbLib.h 2010-10-05 19:27:37 +0000
+++ src/ioc/as/asDbLib.h 2012-06-21 20:42:45 +0000
@@ -5,12 +5,12 @@
5* Operator of Los Alamos National Laboratory.5* Operator of Los Alamos National Laboratory.
6* EPICS BASE Versions 3.13.76* EPICS BASE Versions 3.13.7
7* and higher are distributed subject to a Software License Agreement found7* and higher are distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution. 8* in file LICENSE that is included with this distribution.
9\*************************************************************************/9\*************************************************************************/
10/* share/epicsH/dbAsLib.h */10/* share/epicsH/dbAsLib.h */
11/* $Revision-Id$ */11/* $Revision-Id$ */
12/* Author: Marty Kraimer Date: 02-23-94*/12/* Author: Marty Kraimer Date: 02-23-94*/
13
1413
14
15#ifndef INCdbAsLibh15#ifndef INCdbAsLibh
16#define INCdbAsLibh16#define INCdbAsLibh
1717
@@ -22,6 +22,8 @@
22 long status;22 long status;
23} ASDBCALLBACK;23} ASDBCALLBACK;
2424
25struct dbChannel;
26
25#ifdef __cplusplus27#ifdef __cplusplus
26extern "C" {28extern "C" {
27#endif29#endif
@@ -30,8 +32,8 @@
30epicsShareFunc int epicsShareAPI asSetSubstitutions(const char *substitutions);32epicsShareFunc int epicsShareAPI asSetSubstitutions(const char *substitutions);
31epicsShareFunc int epicsShareAPI asInit(void);33epicsShareFunc int epicsShareAPI asInit(void);
32epicsShareFunc int epicsShareAPI asInitAsyn(ASDBCALLBACK *pcallback);34epicsShareFunc int epicsShareAPI asInitAsyn(ASDBCALLBACK *pcallback);
33epicsShareFunc int epicsShareAPI asDbGetAsl( void *paddr);35epicsShareFunc int epicsShareAPI asDbGetAsl(struct dbChannel *chan);
34epicsShareFunc void * epicsShareAPI asDbGetMemberPvt( void *paddr);36epicsShareFunc void * epicsShareAPI asDbGetMemberPvt(struct dbChannel *chan);
35epicsShareFunc int epicsShareAPI asdbdump(void);37epicsShareFunc int epicsShareAPI asdbdump(void);
36epicsShareFunc int epicsShareAPI asdbdumpFP(FILE *fp);38epicsShareFunc int epicsShareAPI asdbdumpFP(FILE *fp);
37epicsShareFunc int epicsShareAPI aspuag(const char *uagname);39epicsShareFunc int epicsShareAPI aspuag(const char *uagname);
3840
=== modified file 'src/ioc/db/Makefile'
--- src/ioc/db/Makefile 2011-11-14 23:38:36 +0000
+++ src/ioc/db/Makefile 2012-06-21 20:42:45 +0000
@@ -17,9 +17,12 @@
17INC += dbCa.h17INC += dbCa.h
18INC += dbAddr.h18INC += dbAddr.h
19INC += dbBkpt.h19INC += dbBkpt.h
20INC += dbChannel.h
20INC += dbConvert.h21INC += dbConvert.h
21INC += dbConvertFast.h22INC += dbConvertFast.h
23INC += dbExtractArray.h
22INC += dbEvent.h24INC += dbEvent.h
25INC += dbLink.h
23INC += dbLock.h26INC += dbLock.h
24INC += dbNotify.h27INC += dbNotify.h
25INC += dbScan.h28INC += dbScan.h
@@ -30,6 +33,8 @@
30INC += initHooks.h33INC += initHooks.h
31INC += recGbl.h34INC += recGbl.h
32INC += dbIocRegister.h35INC += dbIocRegister.h
36INC += chfPlugin.h
37INC += dbState.h
33INC += db_access_routines.h38INC += db_access_routines.h
34INC += db_convert.h39INC += db_convert.h
3540
@@ -50,11 +55,15 @@
50DBDINC += $(basename $(menuGlobal_DBD))55DBDINC += $(basename $(menuGlobal_DBD))
51DBDINC += dbCommon56DBDINC += dbCommon
5257
58
53dbCore_SRCS += dbLock.c59dbCore_SRCS += dbLock.c
54dbCore_SRCS += dbAccess.c60dbCore_SRCS += dbAccess.c
55dbCore_SRCS += dbBkpt.c61dbCore_SRCS += dbBkpt.c
62dbCore_SRCS += dbChannel.c
56dbCore_SRCS += dbConvert.c63dbCore_SRCS += dbConvert.c
57dbCore_SRCS += dbFastLinkConv.c64dbCore_SRCS += dbFastLinkConv.c
65dbCore_SRCS += dbExtractArray.c
66dbCore_SRCS += dbLink.c
58dbCore_SRCS += dbNotify.c67dbCore_SRCS += dbNotify.c
59dbCore_SRCS += dbScan.c68dbCore_SRCS += dbScan.c
60dbCore_SRCS += dbEvent.c69dbCore_SRCS += dbEvent.c
@@ -74,4 +83,6 @@
74dbCore_SRCS += dbContextReadNotifyCache.cpp83dbCore_SRCS += dbContextReadNotifyCache.cpp
75dbCore_SRCS += templateInstances.cpp84dbCore_SRCS += templateInstances.cpp
76dbCore_SRCS += dbIocRegister.c85dbCore_SRCS += dbIocRegister.c
86dbCore_SRCS += chfPlugin.c
87dbCore_SRCS += dbState.c
7788
7889
=== added file 'src/ioc/db/chfPlugin.c'
--- src/ioc/db/chfPlugin.c 1970-01-01 00:00:00 +0000
+++ src/ioc/db/chfPlugin.c 2012-06-21 20:42:45 +0000
@@ -0,0 +1,649 @@
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/* Based on the linkoptions utility by Michael Davidsaver (BNL) */
14
15#include <stdlib.h>
16#include <errno.h>
17#include <string.h>
18#include <limits.h>
19#include <math.h>
20
21#include <dbDefs.h>
22#include <dbStaticLib.h>
23#include <epicsTypes.h>
24#include <epicsStdio.h>
25#include <epicsString.h>
26#include <errlog.h>
27#include <shareLib.h>
28
29#define epicsExportSharedSymbols
30#include "chfPlugin.h"
31
32#ifndef HUGE_VALF
33# define HUGE_VALF HUGE_VAL
34#endif
35#ifndef HUGE_VALL
36# define HUGE_VALL (-(HUGE_VAL))
37#endif
38
39/*
40 * Data for a chfPlugin
41 */
42typedef struct chfPlugin {
43 const chfPluginArgDef *opts;
44 size_t nopts;
45 epicsUInt32 *required;
46 const chfPluginIf *pif;
47} chfPlugin;
48
49/*
50 * Parser state data for a chfFilter (chfPlugin instance)
51 */
52typedef struct chfFilter {
53 const chfPlugin *plugin;
54 epicsUInt32 *found;
55 void *puser;
56 epicsInt16 nextParam;
57} chfFilter;
58
59/* Data types we get from the parser */
60typedef enum chfPluginType {
61 chfPluginTypeBool,
62 chfPluginTypeInt,
63 chfPluginTypeDouble,
64 chfPluginTypeString
65} chfPluginType;
66
67/*
68 * Convert the (long) integer value 'val' to the type named in 'opt->optType'
69 * and store the result at 'user + opt->offset'.
70 */
71static int store_integer_value(const chfPluginArgDef *opt, void *user, long val)
72{
73 epicsInt32 *ival;
74 int *eval;
75 const chfPluginEnumType *emap;
76 double *dval;
77 char *sval;
78 char buff[22]; /* 2^64 = 1.8e+19, so 20 digits plus sign max */
79
80/* printf("Got an integer for %s (type %d): %ld\n", opt->name, opt->optType, val); */
81
82 if (!opt->convert && opt->optType != chfPluginArgInt32) {
83 return -1;
84 }
85
86 switch (opt->optType) {
87 case chfPluginArgInt32:
88 ival = (epicsInt32 *) ((char *)user + opt->offset);
89 *ival = val;
90 break;
91 case chfPluginArgBoolean:
92 eval = (int*) ((char*)user + opt->offset);
93 *eval = !!val;
94 break;
95 case chfPluginArgDouble:
96 dval = (double*) ((char*)user + opt->offset);
97 *dval = (double) val;
98 break;
99 case chfPluginArgString:
100 sval = ((char*)user + opt->offset);
101 sprintf(buff, "%ld", val);
102 if (strlen(buff) > opt->size-1) {
103 return -1;
104 }
105 strncpy(sval, buff, opt->size-1);
106 sval[opt->size-1]='\0';
107 break;
108 case chfPluginArgEnum:
109 eval = (int*) ((char*)user + opt->offset);
110 for (emap = opt->enums; emap && emap->name; emap++) {
111 if (val == emap->value) {
112 *eval = val;
113 break;
114 }
115 }
116 if (!emap || !emap->name) {
117 return -1;
118 }
119 break;
120 case chfPluginArgInvalid:
121 return -1;
122 }
123 return 0;
124}
125
126/*
127 * Convert the (int) boolean value 'val' to the type named in 'opt->optType'
128 * and store the result at 'user + opt->offset'.
129 */
130static int store_boolean_value(const chfPluginArgDef *opt, void *user, int val)
131{
132 epicsInt32 *ival;
133 int *eval;
134 double *dval;
135 char *sval;
136
137/* printf("Got a boolean for %s (type %d): %d\n", opt->name, opt->optType, val); */
138
139 if (!opt->convert && opt->optType != chfPluginArgBoolean) {
140 return -1;
141 }
142
143 switch (opt->optType) {
144 case chfPluginArgInt32:
145 ival = (epicsInt32 *) ((char*)user + opt->offset);
146 *ival = val;
147 break;
148 case chfPluginArgBoolean:
149 eval = (int*) ((char*)user + opt->offset);
150 *eval = val;
151 break;
152 case chfPluginArgDouble:
153 dval = (double*) ((char*)user + opt->offset);
154 *dval = val ? 1. : 0.;
155 break;
156 case chfPluginArgString:
157 sval = ((char*)user + opt->offset);
158 if ((val ? 4 : 5) > opt->size-1) {
159 return -1;
160 }
161 strncpy(sval, (val ? "true" : "false"), opt->size-1);
162 sval[opt->size-1]='\0';
163 break;
164 case chfPluginArgEnum:
165 case chfPluginArgInvalid:
166 return -1;
167 }
168 return 0;
169}
170
171/*
172 * Convert the double value 'val' to the type named in 'opt->optType'
173 * and store the result at 'user + opt->offset'.
174 */
175static int store_double_value(const chfPluginArgDef *opt, void *user, double val)
176{
177 epicsInt32 *ival;
178 int *eval;
179 double *dval;
180 char *sval;
181 int i;
182
183/*
184 printf("Got a double for %s (type %d, convert: %s): %g\n",
185 opt->name, opt->optType, opt->convert?"yes":"no", val);
186*/
187 if (!opt->convert && opt->optType != chfPluginArgDouble) {
188 return -1;
189 }
190
191 switch (opt->optType) {
192 case chfPluginArgInt32:
193#if (LONG_MAX > 0x7fffffff)
194 if (val < -0x80000000L || val > 0x7fffffff) {
195 return -1;
196 }
197#endif
198 ival = (epicsInt32 *) ((char*)user + opt->offset);
199 *ival = val;
200 break;
201 case chfPluginArgBoolean:
202 eval = (int*) ((char*)user + opt->offset);
203 *eval = (val != 0.) ? 1 : 0;
204 break;
205 case chfPluginArgDouble:
206 dval = (double*) ((char*)user + opt->offset);
207 *dval = val;
208 break;
209 case chfPluginArgString:
210 sval = ((char*)user + opt->offset);
211 if (opt->size <= 8) { /* Play it safe: 3 exp + 2 sign + 'e' + '.' */
212 return -1;
213 }
214 i = epicsSnprintf(sval, opt->size, "%.*g", (int) opt->size - 7, val);
215 if (i >= opt->size) {
216 return -1;
217 }
218 break;
219 case chfPluginArgEnum:
220 case chfPluginArgInvalid:
221 return -1;
222 }
223 return 0;
224}
225
226/*
227 * Convert the (char*) string value 'val' to the type named in 'opt->optType'
228 * and store the result at 'user + opt->offset'.
229 */
230static int store_string_value(const chfPluginArgDef *opt, void *user, const char *val, size_t len)
231{
232 epicsInt32 *ival;
233 long lval;
234 int *eval;
235 const chfPluginEnumType *emap;
236 double *dval;
237 char *sval;
238 char *end;
239 int i;
240
241/* printf("Got a string for %s (type %d): %.*s\n", opt->name, opt->optType, len, val); */
242
243 if (!opt->convert && opt->optType != chfPluginArgString && opt->optType != chfPluginArgEnum) {
244 return -1;
245 }
246
247 switch (opt->optType) {
248 case chfPluginArgInt32:
249 lval = strtol(val, &end, 0);
250 /* test for the myriad error conditions which strtol may use */
251 if (lval == LONG_MAX || lval == LONG_MIN
252#if (LONG_MAX > 0x7fffffff)
253 || lval < -0x80000000L || lval > 0x7fffffff
254#endif
255 || end == val) {
256 return -1;
257 }
258 ival = (epicsInt32 *) ((char*)user + opt->offset);
259 *ival = lval;
260 break;
261 case chfPluginArgBoolean:
262 eval = (int*) ((char*)user + opt->offset);
263 if (epicsStrnCaseCmp(val, "true", len) == 0) {
264 *eval = 1;
265 } else if (epicsStrnCaseCmp(val, "false", len) == 0) {
266 *eval = 0;
267 } else {
268 i = strtol(val, &end, 0);
269 if (i > INT_MAX || i < INT_MIN || end == val) {
270 return -1;
271 }
272 *eval = !!i;
273 }
274 break;
275 case chfPluginArgDouble:
276 dval = (double*) ((char*)user + opt->offset);
277 *dval = strtod(val, &end);
278 /* Indicates errors in the same manner as strtol */
279 if (*dval==HUGE_VALF||*dval==HUGE_VALL||end==val )
280 {
281 return -1;
282 }
283 break;
284 case chfPluginArgString:
285 i = opt->size-1 < len ? opt->size-1 : len;
286 sval = ((char*)user + opt->offset);
287 strncpy(sval, val, i);
288 sval[i] = '\0';
289 break;
290 case chfPluginArgEnum:
291 eval = (int*) ((char*)user + opt->offset);
292 for (emap = opt->enums; emap && emap->name; emap++) {
293 if (strncmp(emap->name, val, len) == 0) {
294 *eval = emap->value;
295 break;
296 }
297 }
298 if( !emap || !emap->name ) {
299 return -1;
300 }
301 break;
302 case chfPluginArgInvalid:
303 return -1;
304 }
305 return 0;
306}
307
308static void freeInstanceData(chfFilter *f)
309{
310 free(f->found); /* FIXME: Use a free-list */
311 free(f); /* FIXME: Use a free-list */
312}
313
314/*
315 * chFilterIf callbacks
316 */
317
318/* First entry point when a new filter instance is created.
319 * All per-instance allocations happen here.
320 */
321static parse_result parse_start(chFilter *filter)
322{
323 chfPlugin *p = (chfPlugin*) filter->plug->puser;
324 chfFilter *f;
325
326 /* Filter context */
327 /* FIXME: Use a free-list */
328 f = calloc(1, sizeof(chfFilter));
329 if (!f) {
330 fprintf(stderr,"chfFilterCtx calloc failed\n");
331 goto errfctx;
332 }
333 f->nextParam = -1;
334
335 /* Bit array to find missing required keys */
336 /* FIXME: Use a free-list */
337 f->found = calloc( (p->nopts/32)+1, sizeof(epicsUInt32) );
338 if (!f->found) {
339 fprintf(stderr,"chfConfigParseStart: bit array calloc failed\n");
340 goto errbitarray;
341 }
342
343 /* Call the plugin to allocate its structure, it returns NULL on error */
344 if (p->pif->allocPvt) {
345 if ((f->puser = p->pif->allocPvt()) == NULL)
346 goto errplugin;
347 }
348
349 filter->puser = (void*) f;
350
351 return parse_continue;
352
353 errplugin:
354 free(f->found); /* FIXME: Use a free-list */
355 errbitarray:
356 free(f); /* FIXME: Use a free-list */
357 errfctx:
358 return parse_stop;
359}
360
361static void parse_abort(chFilter *filter) {
362 chfPlugin *p = (chfPlugin*) filter->plug->puser;
363 chfFilter *f = (chfFilter*) filter->puser;
364
365 /* Call the plugin to tell it we're aborting */
366 if (p->pif->parse_error) p->pif->parse_error(f->puser);
367 if (p->pif->freePvt) p->pif->freePvt(f->puser);
368 freeInstanceData(f);
369}
370
371static parse_result parse_end(chFilter *filter)
372{
373 chfPlugin *p = (chfPlugin*) filter->plug->puser;
374 chfFilter *f = (chfFilter*) filter->puser;
375 int i;
376
377 /* Check if all required arguments were supplied */
378 for(i = 0; i < (p->nopts/32)+1; i++) {
379 if ((f->found[i] & p->required[i]) != p->required[i]) {
380 if (p->pif->parse_error) p->pif->parse_error(f->puser);
381 if (p->pif->freePvt) p->pif->freePvt(f->puser);
382 freeInstanceData(f);
383 return parse_stop;
384 }
385 }
386
387 /* Call the plugin to tell it we're done */
388 if (p->pif->parse_ok) {
389 if (p->pif->parse_ok(f->puser)) {
390 if (p->pif->freePvt) p->pif->freePvt(f->puser);
391 freeInstanceData(f);
392 return parse_stop;
393 }
394 }
395
396 return parse_continue;
397}
398
399static parse_result parse_boolean(chFilter *filter, int boolVal)
400{
401 const chfPluginArgDef *opts = ((chfPlugin*)filter->plug->puser)->opts;
402 chfFilter *f = (chfFilter*)filter->puser;
403
404 if (f->nextParam < 0 || store_boolean_value(&opts[f->nextParam], f->puser, boolVal)) {
405 return parse_stop;
406 } else {
407 return parse_continue;
408 }
409}
410
411static parse_result parse_integer(chFilter *filter, long integerVal)
412{
413 const chfPluginArgDef *opts = ((chfPlugin*)filter->plug->puser)->opts;
414 chfFilter *f = (chfFilter*)filter->puser;
415
416 if (f->nextParam < 0 || store_integer_value(&opts[f->nextParam], f->puser, integerVal)) {
417 return parse_stop;
418 } else {
419 return parse_continue;
420 }
421}
422
423static parse_result parse_double(chFilter *filter, double doubleVal)
424{
425 const chfPluginArgDef *opts = ((chfPlugin*)filter->plug->puser)->opts;
426 chfFilter *f = (chfFilter*)filter->puser;
427
428 if (f->nextParam < 0 || store_double_value(&opts[f->nextParam], f->puser, doubleVal)) {
429 return parse_stop;
430 } else {
431 return parse_continue;
432 }
433}
434
435static parse_result parse_string(chFilter *filter, const char *stringVal, size_t stringLen)
436{
437 const chfPluginArgDef *opts = ((chfPlugin*)filter->plug->puser)->opts;
438 chfFilter *f = (chfFilter*)filter->puser;
439
440 if (f->nextParam < 0 || store_string_value(&opts[f->nextParam], f->puser, stringVal, stringLen)) {
441 return parse_stop;
442 } else {
443 return parse_continue;
444 }
445}
446
447static parse_result parse_start_map(chFilter *filter)
448{
449 return parse_continue;
450}
451
452static parse_result parse_map_key(chFilter *filter, const char *key, size_t stringLen)
453{
454 const chfPluginArgDef *cur;
455 const chfPluginArgDef *opts = ((chfPlugin*)filter->plug->puser)->opts;
456 chfFilter *f = (chfFilter*)filter->puser;
457 int i;
458
459 f->nextParam = -1;
460 for(cur = opts, i = 0; cur && cur->name; cur++, i++) {
461 if (strncmp(key, cur->name, stringLen) == 0) {
462 f->nextParam = i;
463 break;
464 }
465 }
466 if (f->nextParam == -1) {
467 return parse_stop;
468 }
469
470 f->found[i/32] |= 1<<(i%32);
471 return parse_continue;
472}
473
474static parse_result parse_end_map(chFilter *filter)
475{
476 return parse_continue;
477}
478
479static long channel_open(chFilter *filter)
480{
481 chfPlugin *p = (chfPlugin*) filter->plug->puser;
482 chfFilter *f = (chfFilter*) filter->puser;
483
484 if (p->pif->channel_open) return p->pif->channel_open(filter->chan, f->puser);
485 else return 0;
486}
487
488static void channel_register_pre(chFilter *filter,
489 chPostEventFunc **cb_out, void **arg_out, db_field_log *probe)
490{
491 chfPlugin *p = (chfPlugin*) filter->plug->puser;
492 chfFilter *f = (chfFilter*) filter->puser;
493
494 if (p->pif->channelRegisterPre)
495 p->pif->channelRegisterPre(filter->chan, f->puser, cb_out, arg_out, probe);
496}
497
498static void channel_register_post(chFilter *filter,
499 chPostEventFunc **cb_out, void **arg_out, db_field_log *probe)
500{
501 chfPlugin *p = (chfPlugin*) filter->plug->puser;
502 chfFilter *f = (chfFilter*) filter->puser;
503
504 if (p->pif->channelRegisterPost)
505 p->pif->channelRegisterPost(filter->chan, f->puser, cb_out, arg_out, probe);
506}
507
508static void channel_report(chFilter *filter, int level, const unsigned short indent)
509{
510 chfPlugin *p = (chfPlugin*) filter->plug->puser;
511 chfFilter *f = (chfFilter*) filter->puser;
512
513 if (p->pif->channel_report)
514 p->pif->channel_report(filter->chan, f->puser, level, indent);
515}
516
517static void channel_close(chFilter *filter)
518{
519 chfPlugin *p = (chfPlugin*) filter->plug->puser;
520 chfFilter *f = (chfFilter*) filter->puser;
521
522 if (p->pif->channel_close) p->pif->channel_close(filter->chan, f->puser);
523 if (p->pif->freePvt) p->pif->freePvt(f->puser);
524 free(f->found); /* FIXME: Use a free-list */
525 free(f); /* FIXME: Use a free-list */
526}
527
528/*
529 * chFilterIf for the wrapper
530 * we just support a simple one-level map, and no arrays
531 */
532static chFilterIf wrapper_fif = {
533 parse_start,
534 parse_abort,
535 parse_end,
536
537 NULL, /* parse_null, */
538 parse_boolean,
539 parse_integer,
540 parse_double,
541 parse_string,
542
543 parse_start_map,
544 parse_map_key,
545 parse_end_map,
546
547 NULL, /* parse_start_array, */
548 NULL, /* parse_end_array, */
549
550 channel_open,
551 channel_register_pre,
552 channel_register_post,
553 channel_report,
554 channel_close
555};
556
557const char* chfPluginEnumString(const chfPluginEnumType *emap, int i, const char* def)
558{
559 for(; emap && emap->name; emap++) {
560 if ( i == emap->value ) {
561 return emap->name;
562 }
563 }
564 return def;
565}
566
567int chfPluginRegister(const char* key, const chfPluginIf *pif, const chfPluginArgDef* opts)
568{
569 chfPlugin *p;
570 size_t i;
571 const chfPluginArgDef *cur;
572 epicsUInt32 *reqd;
573
574 /* Check and count options */
575 for (i = 0, cur = opts; cur && cur->name; i++, cur++) {
576 switch(cur->optType) {
577 case chfPluginArgInt32:
578 if (cur->size < sizeof(epicsInt32)) {
579 errlogPrintf("Plugin %s: provided storage (%d bytes) for %s is too small for epicsInt32 (%lu)\n",
580 key, cur->size, cur->name,
581 (unsigned long) sizeof(epicsInt32));
582 return -1;
583 }
584 break;
585 case chfPluginArgBoolean:
586 if (cur->size < 1) {
587 errlogPrintf("Plugin %s: provided storage (%d bytes) for %s is too small for boolean (%lu)\n",
588 key, cur->size, cur->name,
589 (unsigned long) sizeof(char));
590 return -1;
591 }
592 break;
593 case chfPluginArgDouble:
594 if (cur->size < sizeof(double)) {
595 errlogPrintf("Plugin %s: provided storage (%d bytes) for %s is too small for double (%lu)\n",
596 key, cur->size, cur->name,
597 (unsigned long) sizeof(double));
598 return -1;
599 }
600 break;
601 case chfPluginArgString:
602 if (cur->size < sizeof(char*)) {
603 /* Catch if someone has given us a char* instead of a char[]
604 * Also means that char buffers must be >=4.
605 */
606 errlogPrintf("Plugin %s: provided storage (%d bytes) for %s is too small for string (>= %lu)\n",
607 key, cur->size, cur->name,
608 (unsigned long) sizeof(char*));
609 return -1;
610 }
611 break;
612 case chfPluginArgEnum:
613 if (cur->size < sizeof(int)) {
614 errlogPrintf("Plugin %s: provided storage (%d bytes) for %s is too small for enum (%lu)\n",
615 key, cur->size, cur->name,
616 (unsigned long) sizeof(int));
617 return -1;
618 }
619 break;
620 case chfPluginArgInvalid:
621 errlogPrintf("Plugin %s: storage type for %s is not defined\n",
622 key, cur->name);
623 return -1;
624 break;
625 }
626 }
627
628 /* Bit array used to find missing required keys */
629 reqd = dbCalloc((i/32)+1, sizeof(epicsUInt32));
630 if (!reqd) {
631 fprintf(stderr,"Plugin %s: bit array calloc failed\n", key);
632 return -1;
633 }
634
635 for (i = 0, cur = opts; cur && cur->name; i++, cur++) {
636 if (cur->required) reqd[i/32] |= 1 << (i%32);
637 }
638
639 /* Plugin data */
640 p = dbCalloc(1, sizeof(chfPlugin));
641 p->pif = pif;
642 p->opts = opts;
643 p->nopts = i;
644 p->required = reqd;
645
646 dbRegisterFilter(key, &wrapper_fif, p);
647
648 return 0;
649}
0650
=== added file 'src/ioc/db/chfPlugin.h'
--- src/ioc/db/chfPlugin.h 1970-01-01 00:00:00 +0000
+++ src/ioc/db/chfPlugin.h 2012-06-21 20:42:45 +0000
@@ -0,0 +1,280 @@
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/* Based on the linkoptions utility by Michael Davidsaver (BNL) */
14
15#ifndef CHFPLUGIN_H
16#define CHFPLUGIN_H
17
18#include <shareLib.h>
19#include <dbDefs.h>
20#include <epicsTypes.h>
21#include <dbChannel.h>
22
23struct db_field_log;
24
25/** @file chfPlugin.h
26 * @brief Channel filter simplified plugins.
27 *
28 * Utility layer to allow an easier (reduced) interface for
29 * channel filter plugins.
30 *
31 * Parsing the configuration arguments of a channel filter plugin
32 * is done according to an argument description table provided by the plugin.
33 * The parser stores the results directly into a user supplied structure
34 * after appropriate type conversion.
35 *
36 * To specify the arguments, a chfPluginArgDef table must be defined
37 * for the user structure. This table has to be specified when the plugin registers.
38 *
39 * The plugin is responsible to register an init function using
40 * epicsExportRegistrar() and the accompanying registrar() directive in the dbd,
41 * and call chfPluginRegister() from within the init function.
42 *
43 * For example:
44 *
45 * typedef struct myStruct {
46 * ... other stuff
47 * epicsUInt32 ival;
48 * double dval;
49 * epicsUInt32 ival2;
50 * int enumval;
51 * char strval[20];
52 * } myStruct;
53 *
54 * static const
55 * chfPluginEnumType colorEnum[] = { {"Red",1}, {"Green",2}, {"Blue",3}, {NULL,0} };
56 *
57 * static const
58 * chfPluginDef myStructDef[] = {
59 * chfInt32 (myStruct, ival, "Integer" , 0, 0),
60 * chfInt32 (myStruct, ival2, "Second" , 1, 0),
61 * chfDouble(myStruct, dval, "Double" , 1, 0),
62 * chfString(myStruct, strval , "String" , 1, 0),
63 * chfEnum (myStruct, enumval, "Color" , 1, 0, colorEnum),
64 * chfPluginEnd
65 * };
66 *
67 * Note: The 4th argument specifies the parameter to be required (1) or optional (0),
68 * the 5th whether converting to the required type is allowed (1), or
69 * type mismatches are an error (0).
70 *
71 */
72
73#ifdef __cplusplus
74extern "C" {
75#endif
76
77/** @brief Channel filter simplified plugin interface.
78 *
79 * The routines in this structure must be implemented by each filter plugin.
80 */
81typedef struct chfPluginIf {
82
83 /* Memory management */
84 /** @brief Allocate private resources.
85 *
86 * <em>Called before parsing starts.</em>
87 * The plugin should allocate its per-instance structures,
88 * returning a pointer to them or NULL requesting an abort of the operation.
89 *
90 * allocPvt may be set to NULL, if no resource allocation is needed.
91 *
92 * @return Pointer to private structure, NULL if operation is to be aborted.
93 */
94 void * (* allocPvt) (void);
95
96 /** @brief Free private resources.
97 *
98 * <em>Called as part of abort or shutdown.</em>
99 * The plugin should release any resources allocated for this filter;
100 * no further calls through this interface will be made.
101 *
102 * freePvt may be set to NULL, if no resources need to be released.
103 *
104 * @param pvt Pointer to private structure.
105 */
106 void (* freePvt) (void *pvt);
107
108 /* Parameter parsing results */
109 /** @brief A parsing error occurred.
110 *
111 * <em>Called after parsing failed with an error.</em>
112 *
113 * @param pvt Pointer to private structure.
114 */
115 void (* parse_error) (void *pvt);
116
117 /** @brief Configuration has been parsed successfully.
118 *
119 * <em>Called after parsing has finished ok.</em>
120 * The plugin may check the validity of the parsed data,
121 * returning -1 to request an abort of the operation.
122 *
123 * @param pvt Pointer to private structure.
124 * @return 0 for success, -1 if operation is to be aborted.
125 */
126 int (* parse_ok) (void *pvt);
127
128 /* Channel operations */
129 /** @brief Open channel.
130 *
131 * <em>Called as part of the channel connection setup.</em>
132 *
133 * @param chan dbChannel for which the connection is being made.
134 * @param pvt Pointer to private structure.
135 * @return 0 for success, -1 if operation is to be aborted.
136 */
137 long (* channel_open) (dbChannel *chan, void *pvt);
138
139 /** @brief Register callbacks for pre-event-queue operation.
140 *
141 * <em>Called as part of the channel connection setup.</em>
142 *
143 * This function is called to establish the stack of plugins that an event
144 * is passed through between the database and the event queue.
145 *
146 * The plugin must set pe_out to point to its own post-event callback in order
147 * to be called when a data update is sent from the database towards the
148 * event queue.
149 *
150 * The plugin may find out the type of data it will receive by looking at 'probe'.
151 * If the plugin will change the data type and/or size, it must update 'probe'
152 * accordingly.
153 *
154 * @param chan dbChannel for which the connection is being made.
155 * @param pvt Pointer to private structure.
156 * @param cb_out Pointer to this plugin's post-event callback (NULL to bypass
157 * this plugin).
158 * @param arg_out Argument that must be supplied when calling
159 * this plugin's post-event callback.
160 */
161 void (* channelRegisterPre) (dbChannel *chan, void *pvt,
162 chPostEventFunc **cb_out, void **arg_out,
163 db_field_log *probe);
164
165 /** @brief Register callbacks for post-event-queue operation.
166 *
167 * <em>Called as part of the channel connection setup.</em>
168 *
169 * This function is called to establish the stack of plugins that an event
170 * is passed through between the event queue and the final user (CA server or
171 * database access).
172 *
173 * The plugin must set pe_out to point to its own post-event callback in order
174 * to be called when a data update is sent from the event queue towards the
175 * final user.
176 *
177 * The plugin may find out the type of data it will receive by looking at 'probe'.
178 * If the plugin will change the data type and/or size, it must update 'probe'
179 * accordingly.
180 *
181 * @param chan dbChannel for which the connection is being made.
182 * @param pvt Pointer to private structure.
183 * @param cb_out Pointer to this plugin's post-event callback (NULL to bypass
184 * this plugin).
185 * @param arg_out Argument that must be supplied when calling
186 * this plugin's post-event callback.
187 */
188 void (* channelRegisterPost) (dbChannel *chan, void *pvt,
189 chPostEventFunc **cb_out, void **arg_out,
190 db_field_log *probe);
191
192 /** @brief Channel report request.
193 *
194 * <em>Called as part of show... routines.</em>
195 *
196 * @param chan dbChannel for which the report is requested.
197 * @param pvt Pointer to private structure.
198 * @param level Interest level.
199 * @param indent Number of spaces to print before each output line.
200 */
201 void (* channel_report) (dbChannel *chan, void *pvt, int level, const unsigned short indent);
202
203 /* FIXME: More filter routines here ... */
204
205 /** @brief Channel close request.
206 *
207 * <em>Called as part of connection shutdown.</em>
208 * @param chan dbChannel for which the connection is being shut down.
209 * @param pvt Pointer to private structure.
210 */
211 void (* channel_close) (dbChannel *chan, void *pvt);
212
213} chfPluginIf;
214
215typedef enum chfPluginArg {
216 chfPluginArgInvalid=0,
217 chfPluginArgBoolean,
218 chfPluginArgInt32,
219 chfPluginArgDouble,
220 chfPluginArgString,
221 chfPluginArgEnum
222} chfPluginArg;
223
224typedef struct chfPluginEnumType {
225 const char *name;
226 const int value;
227} chfPluginEnumType;
228
229typedef struct chfPluginArgDef {
230 const char * name;
231 chfPluginArg optType;
232 unsigned int required:1;
233 unsigned int convert:1;
234 epicsUInt32 offset;
235 epicsUInt32 size;
236 const chfPluginEnumType *enums;
237} chfPluginArgDef;
238
239#define chfInt32(Struct, Member, Name, Req, Conv) \
240{Name, chfPluginArgInt32, Req, Conv, OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), NULL}
241
242#define chfBoolean(Struct, Member, Name, Req, Conv) \
243{Name, chfPluginArgBoolean, Req, Conv, OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), NULL}
244
245#define chfDouble(Struct, Member, Name, Req, Conv) \
246{Name, chfPluginArgDouble, Req, Conv, OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), NULL}
247
248#define chfString(Struct, Member, Name, Req, Conv) \
249{Name, chfPluginArgString, Req, Conv, OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), NULL}
250
251#define chfEnum(Struct, Member, Name, Req, Conv, Enums) \
252{Name, chfPluginArgEnum, Req, Conv, OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), Enums}
253
254#define chfPluginArgEnd {0}
255
256/* Extra output when parsing and converting */
257#define CHFPLUGINDEBUG 1
258
259/** @brief Return the string associated with Enum index 'i'.
260 *
261 * @param Enums A null-terminated array of string/integer pairs.
262 * @param i An Enum index.
263 * @param def String to be returned when 'i' isn't a valid Enum index.
264 * @return The string associated with 'i'.
265 */
266epicsShareFunc const char* chfPluginEnumString(const chfPluginEnumType *Enums, int i, const char* def);
267
268/** @brief Register a plugin.
269 *
270 * @param key The plugin name key that clients will use.
271 * @param pif Pointer to the plugin's interface.
272 * @param opts Pointer to the configuration argument description table.
273 */
274epicsShareFunc int chfPluginRegister(const char* key, const chfPluginIf *pif, const chfPluginArgDef* opts);
275
276#ifdef __cplusplus
277}
278#endif
279
280#endif // CHFPLUGIN_H
0281
=== modified file 'src/ioc/db/dbAccess.c'
--- src/ioc/db/dbAccess.c 2012-02-20 16:01:04 +0000
+++ src/ioc/db/dbAccess.c 2012-06-21 20:42:45 +0000
@@ -1,21 +1,22 @@
1/*************************************************************************\1/*************************************************************************\
2* Copyright (c) 2010 Brookhaven National Laboratory.
3* Copyright (c) 2010 Helmholtz-Zentrum Berlin
4* fuer Materialien und Energie GmbH.
2* Copyright (c) 2002 The University of Chicago, as Operator of Argonne5* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3* National Laboratory.6* National Laboratory.
4* Copyright (c) 2002 The Regents of the University of California, as7* Copyright (c) 2002 The Regents of the University of California, as
5* Operator of Los Alamos National Laboratory.8* Operator of Los Alamos National Laboratory.
6* EPICS BASE Versions 3.13.79* EPICS BASE is distributed subject to a Software License Agreement found
7* and higher are distributed subject to a Software License Agreement found10* in file LICENSE that is included with this distribution.
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/11\*************************************************************************/
10/* dbAccess.c */12
11/* $Revision-Id$ */
12/*13/*
13 * Original Author: Bob Dalesio14 * Original Author: Bob Dalesio
14 * Current Author: Marty Kraimer15 * Current Author: Marty Kraimer
15 * Date: 11-7-9016 * Andrew Johnson <anj@aps.anl.gov>
16*/17 * Ralph Lange <Ralph.Lange@bessy.de>
18 */
1719
18
1920
20#include <stddef.h>21#include <stddef.h>
21#include <stdlib.h>22#include <stdlib.h>
22#include <stdarg.h>23#include <stdarg.h>
@@ -46,6 +47,7 @@
46#include "dbAddr.h"47#include "dbAddr.h"
47#include "callback.h"48#include "callback.h"
48#include "dbScan.h"49#include "dbScan.h"
50#include "dbLink.h"
49#include "dbLock.h"51#include "dbLock.h"
50#include "dbEvent.h"52#include "dbEvent.h"
51#include "dbConvert.h"53#include "dbConvert.h"
@@ -89,17 +91,6 @@
8991
90/* The following is to handle SPC_AS */92/* The following is to handle SPC_AS */
91static SPC_ASCALLBACK spcAsCallback = 0;93static SPC_ASCALLBACK spcAsCallback = 0;
92
9394
94static void inherit_severity(const struct pv_link *ppv_link,
95 dbCommon *pdest, epicsEnum16 stat, epicsEnum16 sevr)
96{
97 switch(ppv_link->pvlMask&pvlOptMsMode) {
98 case pvlOptNMS: break;
99 case pvlOptMSI: if (sevr < INVALID_ALARM) break;
100 case pvlOptMS: recGblSetSevr(pdest,LINK_ALARM,sevr); break;
101 case pvlOptMSS: recGblSetSevr(pdest,stat,sevr); break;
102 }
103}
10495
105void epicsShareAPI dbSpcAsRegisterCallback(SPC_ASCALLBACK func)96void epicsShareAPI dbSpcAsRegisterCallback(SPC_ASCALLBACK func)
106{97{
@@ -113,7 +104,7 @@
113 dbCommon *precord = paddr->precord;104 dbCommon *precord = paddr->precord;
114 long status=0;105 long status=0;
115 long special=paddr->special;106 long special=paddr->special;
116 107
117 prset = dbGetRset(paddr);108 prset = dbGetRset(paddr);
118 if(special<100) { /*global processing*/109 if(special<100) { /*global processing*/
119 if((special==SPC_NOMOD) && (pass==0)) {110 if((special==SPC_NOMOD) && (pass==0)) {
@@ -139,7 +130,7 @@
139 }130 }
140 return(0);131 return(0);
141}132}
142
143133
134
144static void get_enum_strs(DBADDR *paddr, char **ppbuffer,135static void get_enum_strs(DBADDR *paddr, char **ppbuffer,
145 struct rset *prset,long *options)136 struct rset *prset,long *options)
146{137{
@@ -199,7 +190,7 @@
199 *ppbuffer = ((char *)*ppbuffer) + dbr_enumStrs_size;190 *ppbuffer = ((char *)*ppbuffer) + dbr_enumStrs_size;
200 return;191 return;
201}192}
202
203193
194
204static void get_graphics(DBADDR *paddr, char **ppbuffer,195static void get_graphics(DBADDR *paddr, char **ppbuffer,
205 struct rset *prset,long *options)196 struct rset *prset,long *options)
206{197{
@@ -239,7 +230,7 @@
239 }230 }
240 return;231 return;
241}232}
242
243233
234
244static void get_control(DBADDR *paddr, char **ppbuffer,235static void get_control(DBADDR *paddr, char **ppbuffer,
245 struct rset *prset,long *options)236 struct rset *prset,long *options)
246{237{
@@ -279,7 +270,7 @@
279 }270 }
280 return;271 return;
281}272}
282
283273
274
284static void get_alarm(DBADDR *paddr, char **ppbuffer,275static void get_alarm(DBADDR *paddr, char **ppbuffer,
285 struct rset *prset,long *options)276 struct rset *prset,long *options)
286{277{
@@ -324,35 +315,44 @@
324 }315 }
325 return;316 return;
326}317}
327
328318
329static void getOptions(DBADDR *paddr,char **poriginal,long *options,void *pflin)319
320/*
321 * This code relies on *poriginal being aligned and all increments done by the
322 * blocks only changing the buffer pointer in a way that does not break alignment.
323 */
324static void getOptions(DBADDR *paddr, char **poriginal, long *options,
325 void *pflin)
330{326{
331 db_field_log *pfl= (db_field_log *)pflin;327 db_field_log *pfl= (db_field_log *)pflin;
332 struct rset *prset;328 struct rset *prset;
333 short field_type=paddr->field_type;329 short field_type;
334 dbCommon *pcommon;330 dbCommon *pcommon;
335 char *pbuffer = *poriginal;331 char *pbuffer = *poriginal;
336332
333 if (!pfl || pfl->type == dbfl_type_rec)
334 field_type = paddr->field_type;
335 else
336 field_type = pfl->field_type;
337 prset=dbGetRset(paddr);337 prset=dbGetRset(paddr);
338 /* Process options */338 /* Process options */
339 pcommon = paddr->precord;339 pcommon = paddr->precord;
340 if( (*options) & DBR_STATUS ) {340 if( (*options) & DBR_STATUS ) {
341 unsigned short *pushort = (unsigned short *)pbuffer;341 unsigned short *pushort = (unsigned short *)pbuffer;
342342
343 if(pfl!=NULL) {343 if (!pfl || pfl->type == dbfl_type_rec) {
344 *pushort++ = pfl->stat;344 *pushort++ = pcommon->stat;
345 *pushort++ = pfl->sevr;345 *pushort++ = pcommon->sevr;
346 } else {346 } else {
347 *pushort++ = pcommon->stat;347 *pushort++ = pfl->stat;
348 *pushort++ = pcommon->sevr;348 *pushort++ = pfl->sevr;
349 }349 }
350 *pushort++ = pcommon->acks;350 *pushort++ = pcommon->acks;
351 *pushort++ = pcommon->ackt;351 *pushort++ = pcommon->ackt;
352 pbuffer = (char *)pushort;352 pbuffer = (char *)pushort;
353 }353 }
354 if( (*options) & DBR_UNITS ) {354 if( (*options) & DBR_UNITS ) {
355 memset(pbuffer,'\0',dbr_units_size);355 memset(pbuffer,'\0',dbr_units_size);
356 if( prset && prset->get_units ){ 356 if( prset && prset->get_units ){
357 (*prset->get_units)(paddr, pbuffer);357 (*prset->get_units)(paddr, pbuffer);
358 pbuffer[DB_UNITS_SIZE-1] = '\0';358 pbuffer[DB_UNITS_SIZE-1] = '\0';
359 } else {359 } else {
@@ -363,7 +363,7 @@
363 if( (*options) & DBR_PRECISION ) {363 if( (*options) & DBR_PRECISION ) {
364 memset(pbuffer, '\0', dbr_precision_size);364 memset(pbuffer, '\0', dbr_precision_size);
365 if((field_type==DBF_FLOAT || field_type==DBF_DOUBLE)365 if((field_type==DBF_FLOAT || field_type==DBF_DOUBLE)
366 && prset && prset->get_precision ){ 366 && prset && prset->get_precision ){
367 (*prset->get_precision)(paddr,pbuffer);367 (*prset->get_precision)(paddr,pbuffer);
368 } else {368 } else {
369 *options ^= DBR_PRECISION; /*Turn off DBR_PRECISION*/369 *options ^= DBR_PRECISION; /*Turn off DBR_PRECISION*/
@@ -373,12 +373,12 @@
373 if( (*options) & DBR_TIME ) {373 if( (*options) & DBR_TIME ) {
374 epicsUInt32 *ptime = (epicsUInt32 *)pbuffer;374 epicsUInt32 *ptime = (epicsUInt32 *)pbuffer;
375375
376 if(pfl!=NULL) {376 if (!pfl || pfl->type == dbfl_type_rec) {
377 *ptime++ = pfl->time.secPastEpoch;377 *ptime++ = pcommon->time.secPastEpoch;
378 *ptime++ = pfl->time.nsec;378 *ptime++ = pcommon->time.nsec;
379 } else {379 } else {
380 *ptime++ = pcommon->time.secPastEpoch;380 *ptime++ = pfl->time.secPastEpoch;
381 *ptime++ = pcommon->time.nsec;381 *ptime++ = pfl->time.nsec;
382 }382 }
383 pbuffer = (char *)ptime;383 pbuffer = (char *)ptime;
384 }384 }
@@ -392,7 +392,7 @@
392 get_alarm(paddr, &pbuffer, prset, options);392 get_alarm(paddr, &pbuffer, prset, options);
393 *poriginal = pbuffer;393 *poriginal = pbuffer;
394}394}
395
396395
396
397struct rset * epicsShareAPI dbGetRset(const struct dbAddr *paddr)397struct rset * epicsShareAPI dbGetRset(const struct dbAddr *paddr)
398{398{
399 struct dbFldDes *pfldDes = paddr->pfldDes;399 struct dbFldDes *pfldDes = paddr->pfldDes;
@@ -419,10 +419,10 @@
419419
420int epicsShareAPI dbIsValueField(const struct dbFldDes *pdbFldDes)420int epicsShareAPI dbIsValueField(const struct dbFldDes *pdbFldDes)
421{421{
422 if(pdbFldDes->pdbRecordType->indvalFlddes == pdbFldDes->indRecordType)422 if (pdbFldDes->pdbRecordType->indvalFlddes == pdbFldDes->indRecordType)
423 return(TRUE);423 return TRUE;
424 else424 else
425 return(FALSE);425 return FALSE;
426}426}
427427
428int epicsShareAPI dbGetFieldIndex(const struct dbAddr *paddr)428int epicsShareAPI dbGetFieldIndex(const struct dbAddr *paddr)
@@ -430,50 +430,6 @@
430 return paddr->pfldDes->indRecordType;430 return paddr->pfldDes->indRecordType;
431}431}
432432
433long epicsShareAPI dbGetNelements(const struct link *plink,long *nelements)
434{
435 switch(plink->type) {
436 case CONSTANT:
437 *nelements = 0;
438 return(0);
439 case DB_LINK: {
440 DBADDR *paddr = (DBADDR *)plink->value.pv_link.pvt;
441 *nelements = paddr->no_elements;
442 return(0);
443 }
444 case CA_LINK:
445 return(dbCaGetNelements(plink,nelements));
446 default:
447 break;
448 }
449 return(S_db_badField);
450}
451
452int epicsShareAPI dbIsLinkConnected(const struct link *plink)
453{
454 switch(plink->type) {
455 case DB_LINK: return(TRUE);
456 case CA_LINK: return(dbCaIsLinkConnected(plink));
457 default: break;
458 }
459 return(FALSE);
460}
461
462int epicsShareAPI dbGetLinkDBFtype(const struct link *plink)
463{
464 switch(plink->type) {
465 case DB_LINK:
466 {
467 DBADDR *paddr = (DBADDR *)plink->value.pv_link.pvt;
468
469 return((int)paddr->field_type);
470 }
471 case CA_LINK: return(dbCaGetLinkDBFtype(plink));
472 default: break;
473 }
474 return(-1);
475}
476
477433
478/*434/*
479 * Process a record if its scan field is passive.435 * Process a record if its scan field is passive.
480 * Will notify if processing is complete by callback.436 * Will notify if processing is complete by callback.
@@ -481,50 +437,15 @@
481 */437 */
482long epicsShareAPI dbScanPassive(dbCommon *pfrom, dbCommon *pto)438long epicsShareAPI dbScanPassive(dbCommon *pfrom, dbCommon *pto)
483{439{
484 long status;
485
486 /* if not passive just return success */440 /* if not passive just return success */
487 if(pto->scan != 0) return(0);
488
489 if(pfrom && pfrom->ppn) dbNotifyAdd(pfrom,pto);
490 status = dbProcess(pto);
491 return(status);
492}
493
494/*KLUDGE: Following needed so that dbPutLink to PROC field works correctly*/
495long epicsShareAPI dbScanLink(dbCommon *pfrom, dbCommon *pto)
496{
497 long status;
498 unsigned char pact;
499
500 if(pfrom && pfrom->ppn) dbNotifyAdd(pfrom,pto);
501 pact = pfrom->pact;
502 pfrom->pact = TRUE;
503 status = dbProcess(pto);
504 pfrom->pact = pact;
505 return(status);
506}
507
508void epicsShareAPI dbScanFwdLink(struct link *plink)
509{
510 dbCommon *precord;
511 struct pv_link *pvlink;
512 short fwdLinkValue;
513
514 if(plink->type!=DB_LINK && plink->type!=CA_LINK) return;
515 pvlink = &plink->value.pv_link;
516 precord = pvlink->precord;
517 if(plink->type==DB_LINK) {
518 dbAddr *paddr = (dbAddr *)plink->value.pv_link.pvt;
519 dbScanPassive(precord,paddr->precord);
520 return;
521 }
522 if(!(pvlink->pvlMask & pvlOptFWD)) return;
523 fwdLinkValue = 1;
524 dbCaPutLink(plink,DBR_SHORT,&fwdLinkValue,1);
525 return;
526}
527
528441
442 if (pto->scan != 0)
443 return 0;
444
445 if (pfrom && pfrom->ppn)
446 dbNotifyAdd(pfrom,pto);
447 return dbProcess(pto);
448}
449
529/*450/*
530 * Process the record.451 * Process the record.
531 * 1. Check for breakpoints.452 * 1. Check for breakpoints.
@@ -536,121 +457,127 @@
536 */457 */
537long epicsShareAPI dbProcess(dbCommon *precord)458long epicsShareAPI dbProcess(dbCommon *precord)
538{459{
539 struct rset *prset = precord->rset;460 struct rset *prset = precord->rset;
540 dbRecordType *pdbRecordType = precord->rdes;461 dbRecordType *pdbRecordType = precord->rdes;
541 unsigned char tpro=precord->tpro;462 unsigned char tpro = precord->tpro;
542 long status = 0;463 long status = 0;
543 int *ptrace;464 int *ptrace;
544 int set_trace=FALSE;465 int set_trace = FALSE;
545 dbFldDes *pdbFldDes;466 dbFldDes *pdbFldDes;
546 int callNotifyCompletion = FALSE;467 int callNotifyCompletion = FALSE;
547468
548 ptrace = dbLockSetAddrTrace(precord);469 ptrace = dbLockSetAddrTrace(precord);
470 /*
471 * Note that it is likely that if any changes are made
472 * to dbProcess() corresponding changes will have to
473 * be made in the breakpoint handler.
474 */
475
476 /* see if there are any stopped records or breakpoints */
477 if (lset_stack_count != 0) {
549 /*478 /*
550 * Note that it is likely that if any changes are made479 * Check to see if the record should be processed
551 * to dbProcess() corresponding changes will have to480 * and activate breakpoint accordingly. If this
552 * be made in the breakpoint handler.481 * function call returns non-zero, skip record
482 * support and fall out of dbProcess(). This is
483 * done so that a dbContTask() can be spawned to
484 * take over record processing for the lock set
485 * containing a breakpoint.
553 */486 */
554 487 if (dbBkpt(precord))
555 /* see if there are any stopped records or breakpoints */488 goto all_done;
556 if (lset_stack_count != 0) {489 }
557 /*490
558 * Check to see if the record should be processed491 /* check for trace processing*/
559 * and activate breakpoint accordingly. If this492 if (tpro) {
560 * function call returns non-zero, skip record493 if(*ptrace==0) {
561 * support and fall out of dbProcess(). This is494 *ptrace = 1;
562 * done so that a dbContTask() can be spawned to495 set_trace = TRUE;
563 * take over record processing for the lock set496 }
564 * containing a breakpoint.497 }
565 */498
566 if (dbBkpt(precord))499 /* If already active dont process */
567 goto all_done;500 if (precord->pact) {
568 }501 unsigned short monitor_mask;
569 502
570 /* check for trace processing*/503 if (*ptrace)
571 if (tpro) {504 printf("%s: Active %s\n",
572 if(*ptrace==0) {505 epicsThreadGetNameSelf(), precord->name);
573 *ptrace = 1;506 /* raise scan alarm after MAX_LOCK times */
574 set_trace = TRUE;507 if (precord->stat==SCAN_ALARM) goto all_done;
575 }508 if (precord->lcnt++ !=MAX_LOCK) goto all_done;
576 }509 if (precord->sevr>=INVALID_ALARM) goto all_done;
577510 recGblSetSevr(precord, SCAN_ALARM, INVALID_ALARM);
578 /* If already active dont process */511 monitor_mask = recGblResetAlarms(precord);
579 if (precord->pact) {512 monitor_mask |= DBE_VALUE|DBE_LOG;
580 unsigned short monitor_mask;513 pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];
581514 db_post_events(precord,
582 if (*ptrace) printf("%s: Active %s\n",515 (void *)(((char *)precord) + pdbFldDes->offset),
583 epicsThreadGetNameSelf(), precord->name);516 monitor_mask);
584 /* raise scan alarm after MAX_LOCK times */517 goto all_done;
585 if (precord->stat==SCAN_ALARM) goto all_done;518 }
586 if (precord->lcnt++ !=MAX_LOCK) goto all_done;519 else precord->lcnt = 0;
587 if (precord->sevr>=INVALID_ALARM) goto all_done;520
588 recGblSetSevr(precord, SCAN_ALARM, INVALID_ALARM);521 /*
589 monitor_mask = recGblResetAlarms(precord);522 * Check the record disable link. A record will not be
590 monitor_mask |= DBE_VALUE|DBE_LOG;523 * processed if the value retrieved through this link
591 pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];524 * is equal to constant set in the record's disv field.
592 db_post_events(precord,525 */
593 (void *)(((char *)precord) + pdbFldDes->offset),526 status = dbGetLink(&precord->sdis, DBR_SHORT, &precord->disa, 0, 0);
594 monitor_mask);527
595 goto all_done;528 /* if disabled check disable alarm severity and return success */
596 }529 if (precord->disa == precord->disv) {
597 else precord->lcnt = 0;530 if(*ptrace)
598531 printf("%s: Disabled %s\n",
599 /*532 epicsThreadGetNameSelf(), precord->name);
600 * Check the record disable link. A record will not be533
601 * processed if the value retrieved through this link534 /*take care of caching and notifyCompletion*/
602 * is equal to constant set in the record's disv field.535 precord->rpro = FALSE;
603 */536 precord->putf = FALSE;
604 status = dbGetLink(&(precord->sdis),DBR_SHORT,&(precord->disa),0,0);537 callNotifyCompletion = TRUE;
605538
606 /* if disabled check disable alarm severity and return success */539 /* raise disable alarm */
607 if (precord->disa == precord->disv) {540 if (precord->stat==DISABLE_ALARM) goto all_done;
608 if(*ptrace) printf("%s: Disabled %s\n",541 precord->sevr = precord->diss;
609 epicsThreadGetNameSelf(), precord->name);542 precord->stat = DISABLE_ALARM;
610 /*take care of caching and notifyCompletion*/543 precord->nsev = 0;
611 precord->rpro = FALSE;544 precord->nsta = 0;
612 precord->putf = FALSE;545 db_post_events(precord, &precord->stat, DBE_VALUE);
613 callNotifyCompletion = TRUE;546 db_post_events(precord, &precord->sevr, DBE_VALUE);
614 /* raise disable alarm */547 pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];
615 if (precord->stat==DISABLE_ALARM) goto all_done;548 db_post_events(precord,
616 precord->sevr = precord->diss;549 (void *)(((char *)precord) + pdbFldDes->offset),
617 precord->stat = DISABLE_ALARM;550 DBE_VALUE|DBE_ALARM);
618 precord->nsev = 0;551 goto all_done;
619 precord->nsta = 0;552 }
620 db_post_events(precord, &precord->stat, DBE_VALUE);553
621 db_post_events(precord, &precord->sevr, DBE_VALUE);554 /* locate record processing routine */
622 pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];555 /* FIXME: put this in iocInit() !!! */
623 db_post_events(precord,556 if (!(prset=precord->rset) || !(prset->process)) {
624 (void *)(((char *)precord) + pdbFldDes->offset),557 callNotifyCompletion = TRUE;
625 DBE_VALUE|DBE_ALARM);558 precord->pact=1;/*set pact TRUE so error is issued only once*/
626 goto all_done;559 recGblRecordError(S_db_noRSET, (void *)precord, "dbProcess");
627 }560 status = S_db_noRSET;
628561 if (*ptrace)
629 /* locate record processing routine */562 printf("%s: No RSET for %s\n",
630 /* put this in iocInit() !!! */563 epicsThreadGetNameSelf(), precord->name);
631 if (!(prset=precord->rset) || !(prset->process)) {564 goto all_done;
632 callNotifyCompletion = TRUE;565 }
633 precord->pact=1;/*set pact TRUE so error is issued only once*/566 if(*ptrace)
634 recGblRecordError(S_db_noRSET, (void *)precord, "dbProcess");567 printf("%s: Process %s\n",
635 status = S_db_noRSET;568 epicsThreadGetNameSelf(), precord->name);
636 if (*ptrace) printf("%s: No RSET for %s\n",569 /* process record */
637 epicsThreadGetNameSelf(), precord->name);570 status = (*prset->process)(precord);
638 goto all_done;571 /* Print record's fields if PRINT_MASK set in breakpoint field */
639 }572 if (lset_stack_count != 0) {
640 if(*ptrace) printf("%s: Process %s\n",573 dbPrint(precord);
641 epicsThreadGetNameSelf(), precord->name);574 }
642 /* process record */
643 status = (*prset->process)(precord);
644 /* Print record's fields if PRINT_MASK set in breakpoint field */
645 if (lset_stack_count != 0) {
646 dbPrint(precord);
647 }
648all_done:575all_done:
649 if (set_trace) *ptrace = 0;576 if (set_trace) *ptrace = 0;
650 if(callNotifyCompletion && precord->ppn) dbNotifyCompletion(precord);577 if(callNotifyCompletion && precord->ppn) dbNotifyCompletion(precord);
651 return(status);578 return(status);
652}579}
653
654580
581
655/*582/*
656 * Fill out a database structure (*paddr) for583 * Fill out a database structure (*paddr) for
657 * a record given by the name "pname."584 * a record given by the name "pname."
@@ -726,59 +653,7 @@
726 dbFinishEntry(&dbEntry);653 dbFinishEntry(&dbEntry);
727 return status;654 return status;
728}655}
729
730656
731/* JOH 10-19-04 */
732static char * dbCopyInNameComponentOfPV (
733 char * pBuf, unsigned bufLen, const char * pComponent )
734{
735 unsigned compLen = strlen ( pComponent );
736 if ( compLen < bufLen ) {
737 strcpy ( pBuf, pComponent );
738 return pBuf + compLen;
739 }
740 else {
741 unsigned reducedSize = bufLen - 1u;
742 strncpy ( pBuf, pComponent, reducedSize );
743 pBuf[reducedSize] = '\0';
744 return pBuf + reducedSize;
745 }
746}
747/*
748 * Copies PV name into pBuf of length bufLen
749 *
750 * Returns the number of bytes written to pBuf
751 * not including null termination.
752 * JOH 10-19-04
753 */
754unsigned dbNameOfPV (
755 const dbAddr * paddr, char * pBuf, unsigned bufLen )
756{
757 dbFldDes * pfldDes = paddr->pfldDes;
758 char * pBufTmp = pBuf;
759 if ( bufLen == 0u ) {
760 return 0u;
761 }
762 pBufTmp = dbCopyInNameComponentOfPV (
763 pBufTmp, bufLen, paddr->precord->name );
764 pBufTmp = dbCopyInNameComponentOfPV (
765 pBufTmp, bufLen - ( pBufTmp - pBuf ), "." );
766 pBufTmp = dbCopyInNameComponentOfPV (
767 pBufTmp, bufLen - ( pBufTmp - pBuf ), pfldDes->name );
768 return pBufTmp - pBuf;
769}
770/*
771 * Returns the number of bytes in the PV name
772 * not including null termination.
773 * JOH 10-19-04
774 */
775unsigned dbNameSizeOfPV ( const dbAddr * paddr )
776{
777 unsigned recNameLen = strlen ( paddr->precord->name );
778 dbFldDes * pfldDes = paddr->pfldDes;
779 unsigned fieldNameLen = strlen ( pfldDes->name );
780 return recNameLen + fieldNameLen + 1;
781}
782
783657
658
784long epicsShareAPI dbValueSize(short dbr_type)659long epicsShareAPI dbValueSize(short dbr_type)
785{660{
786 /* sizes for value associated with each DBR request type */661 /* sizes for value associated with each DBR request type */
@@ -826,222 +701,117 @@
826 return dbReadDatabase(&pdbbase, file, 0, subs);701 return dbReadDatabase(&pdbbase, file, 0, subs);
827}702}
828703
829
830704
831long epicsShareAPI dbGetLinkValue(struct link *plink, short dbrType,
832 void *pbuffer, long *poptions, long *pnRequest)
833{
834 long status = 0;
835
836 if (plink->type == CONSTANT) {
837 if (poptions) *poptions = 0;
838 if (pnRequest) *pnRequest = 0;
839 } else if (plink->type == DB_LINK) {
840 struct pv_link *ppv_link = &(plink->value.pv_link);
841 DBADDR *paddr = ppv_link->pvt;
842 dbCommon *precord = plink->value.pv_link.precord;
843
844 /* scan passive records with links that are process passive */
845 if (ppv_link->pvlMask&pvlOptPP) {
846 dbCommon *pfrom = paddr->precord;
847 unsigned char pact;
848
849 pact = precord->pact;
850 precord->pact = TRUE;
851 status = dbScanPassive(precord,pfrom);
852 precord->pact = pact;
853 if (status) return status;
854 }
855 if(precord!= paddr->precord) {
856 inherit_severity(ppv_link,precord,paddr->precord->stat,paddr->precord->sevr);
857 }
858
859 if (ppv_link->getCvt && ppv_link->lastGetdbrType == dbrType) {
860 status = ppv_link->getCvt(paddr->pfield, pbuffer, paddr);
861 } else {
862 unsigned short dbfType = paddr->field_type;
863 long no_elements = paddr->no_elements;
864
865 if (dbrType < 0 || dbrType > DBR_ENUM ||
866 dbfType > DBF_DEVICE) {
867 status = S_db_badDbrtype;
868 recGblRecordError(status, precord, "GetLinkValue Failed");
869 recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM);
870 return status;
871 }
872 /* attempt to make a fast link */
873 if ((!poptions || *poptions == 0) &&
874 no_elements == 1 &&
875 (!pnRequest || *pnRequest == 1) &&
876 paddr->special != SPC_ATTRIBUTE) {
877 ppv_link->getCvt = dbFastGetConvertRoutine[dbfType][dbrType];
878 status = ppv_link->getCvt(paddr->pfield, pbuffer, paddr);
879 } else {
880 ppv_link->getCvt = 0;
881 status = dbGet(paddr, dbrType, pbuffer, poptions, pnRequest, NULL);
882 }
883 }
884 ppv_link->lastGetdbrType = dbrType;
885 if (status) {
886 recGblRecordError(status, precord, "dbGetLinkValue");
887 recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM);
888 }
889 } else if (plink->type == CA_LINK) {
890 struct dbCommon *precord = plink->value.pv_link.precord;
891 const struct pv_link *pcalink = &plink->value.pv_link;
892 epicsEnum16 sevr, stat;
893
894 status=dbCaGetLink(plink,dbrType,pbuffer,&stat,&sevr,pnRequest);
895 if (status) {
896 recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM);
897 } else {
898 inherit_severity(pcalink,precord,stat,sevr);
899 }
900 if (poptions) *poptions = 0;
901 } else {
902 cantProceed("dbGetLinkValue: Illegal link type");
903 }
904 return status;
905}
906
907705
908long epicsShareAPI dbPutLinkValue(struct link *plink, short dbrType,
909 const void *pbuffer, long nRequest)
910{
911 long status = 0;
912
913 if (plink->type == DB_LINK) {
914 struct dbCommon *psource = plink->value.pv_link.precord;
915 struct pv_link *ppv_link = &plink->value.pv_link;
916 DBADDR *paddr = (DBADDR *)ppv_link->pvt;
917 dbCommon *pdest = paddr->precord;
918
919 status = dbPut(paddr, dbrType, pbuffer, nRequest);
920 inherit_severity(ppv_link,pdest,psource->nsta,psource->nsev);
921 if (status) return status;
922
923 if (paddr->pfield == (void *)&pdest->proc ||
924 (ppv_link->pvlMask & pvlOptPP && pdest->scan == 0)) {
925 /*if dbPutField caused asyn record to process */
926 /* ask for reprocessing*/
927 if (pdest->putf) {
928 pdest->rpro = TRUE;
929 } else { /* otherwise ask for the record to be processed*/
930 status = dbScanLink(psource, pdest);
931 }
932 }
933 if (status)
934 recGblSetSevr(psource, LINK_ALARM, INVALID_ALARM);
935 } else if (plink->type == CA_LINK) {
936 struct dbCommon *psource = plink->value.pv_link.precord;
937
938 status = dbCaPutLink(plink, dbrType, pbuffer, nRequest);
939 if (status < 0)
940 recGblSetSevr(psource, LINK_ALARM, INVALID_ALARM);
941 } else {
942 cantProceed("dbPutLinkValue: Illegal link type");
943 }
944 return status;
945}
946
947706
707
708static long getLinkValue(DBADDR *paddr, short dbrType,
709 char *pbuf, long *nRequest)
710{
711 dbCommon *precord = paddr->precord;
712 dbFldDes *pfldDes = paddr->pfldDes;
713 int maxlen;
714 DBENTRY dbEntry;
715 long status;
716
717 switch (dbrType) {
718 case DBR_STRING:
719 maxlen = MAX_STRING_SIZE - 1;
720 if (nRequest && *nRequest > 1) *nRequest = 1;
721 break;
722
723 case DBR_CHAR:
724 case DBR_UCHAR:
725 if (nRequest && *nRequest > 0) {
726 maxlen = *nRequest - 1;
727 break;
728 }
729 /* else fall through ... */
730 default:
731 return S_db_badDbrtype;
732 }
733
734 dbInitEntry(pdbbase, &dbEntry);
735 status = dbFindRecord(&dbEntry, precord->name);
736 if (!status) status = dbFindField(&dbEntry, pfldDes->name);
737 if (!status) {
738 char *rtnString = dbGetString(&dbEntry);
739
740 strncpy(pbuf, rtnString, --maxlen);
741 pbuf[maxlen] = 0;
742 }
743 dbFinishEntry(&dbEntry);
744 return status;
745}
746
747static long getAttrValue(DBADDR *paddr, short dbrType,
748 char *pbuf, long *nRequest)
749{
750 int maxlen;
751
752 if (!paddr->pfield) return S_db_badField;
753
754 switch (dbrType) {
755 case DBR_STRING:
756 maxlen = MAX_STRING_SIZE - 1;
757 if (nRequest && *nRequest > 1) *nRequest = 1;
758 break;
759
760 case DBR_CHAR:
761 case DBR_UCHAR:
762 if (nRequest && *nRequest > 0) {
763 maxlen = *nRequest - 1;
764 break;
765 }
766 /* else fall through ... */
767 default:
768 return S_db_badDbrtype;
769 }
770
771 strncpy(pbuf, paddr->pfield, --maxlen);
772 pbuf[maxlen] = 0;
773 return 0;
774}
775
948long epicsShareAPI dbGetField(DBADDR *paddr,short dbrType,776long epicsShareAPI dbGetField(DBADDR *paddr,short dbrType,
949 void *pbuffer, long *options, long *nRequest, void *pflin)777 void *pbuffer, long *options, long *nRequest, void *pflin)
950{778{
951 short dbfType = paddr->field_type;
952 dbCommon *precord = paddr->precord;779 dbCommon *precord = paddr->precord;
953 long status = 0;780 long status = 0;
954781
955 dbScanLock(precord);782 dbScanLock(precord);
956 if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) {783 status = dbGet(paddr, dbrType, pbuffer, options, nRequest, pflin);
957 DBENTRY dbEntry;
958 dbFldDes *pfldDes = paddr->pfldDes;
959 char *rtnString;
960 char *pbuf = (char *)pbuffer;
961 int maxlen;
962
963 if (options && (*options))
964 getOptions(paddr, &pbuf, options, pflin);
965 if (nRequest && *nRequest == 0) goto done;
966
967 switch (dbrType) {
968 case DBR_STRING:
969 maxlen = MAX_STRING_SIZE - 1;
970 if (nRequest && *nRequest > 1) *nRequest = 1;
971 break;
972
973 case DBR_CHAR:
974 case DBR_UCHAR:
975 if (nRequest && *nRequest > 0) {
976 maxlen = *nRequest - 1;
977 break;
978 }
979 /* else fall through ... */
980 default:
981 status = S_db_badDbrtype;
982 goto done;
983 }
984
985 dbInitEntry(pdbbase, &dbEntry);
986 status = dbFindRecord(&dbEntry, precord->name);
987 if (!status) status = dbFindField(&dbEntry, pfldDes->name);
988 if (!status) {
989 rtnString = dbGetString(&dbEntry);
990 strncpy(pbuf, rtnString, maxlen);
991 pbuf[maxlen] = 0;
992 }
993 dbFinishEntry(&dbEntry);
994 } else {
995 status = dbGet(paddr, dbrType, pbuffer, options, nRequest, pflin);
996 }
997done:
998 dbScanUnlock(precord);784 dbScanUnlock(precord);
999 return status;785 return status;
1000}786}
1001
1002787
788
1003long epicsShareAPI dbGet(DBADDR *paddr, short dbrType,789long epicsShareAPI dbGet(DBADDR *paddr, short dbrType,
1004 void *pbuffer, long *options, long *nRequest, void *pflin)790 void *pbuffer, long *options, long *nRequest, void *pflin)
1005{791{
792 char *pbuf = pbuffer;
1006 db_field_log *pfl = (db_field_log *)pflin;793 db_field_log *pfl = (db_field_log *)pflin;
1007 short field_type = paddr->field_type;794 short field_type;
1008 long no_elements = paddr->no_elements;795 long no_elements;
1009 long offset;796 long offset;
1010 struct rset *prset;797 struct rset *prset;
1011 long status = 0;798 long status = 0;
1012799
1013 if (options && *options) {800 if (options && *options)
1014 char *pbuf = pbuffer;
1015
1016 getOptions(paddr, &pbuf, options, pflin);801 getOptions(paddr, &pbuf, options, pflin);
1017 pbuffer = pbuf;802 if (nRequest && *nRequest == 0)
1018 }
1019 if (nRequest && *nRequest == 0) return 0;
1020
1021 if (paddr->special == SPC_ATTRIBUTE) {
1022 char *pbuf = pbuffer;
1023 int maxlen;
1024
1025 if (!paddr->pfield) return S_db_badField;
1026
1027 switch (dbrType) {
1028 case DBR_STRING:
1029 maxlen = MAX_STRING_SIZE - 1;
1030 if (nRequest && *nRequest > 1) *nRequest = 1;
1031 break;
1032
1033 case DBR_CHAR:
1034 case DBR_UCHAR:
1035 if (nRequest && *nRequest > 0) {
1036 maxlen = *nRequest - 1;
1037 break;
1038 }
1039 /* else fall through ... */
1040 default:
1041 return S_db_badDbrtype;
1042 }
1043
1044 strncpy(pbuf, (char *)paddr->pfield, maxlen);
1045 pbuf[maxlen] = 0;
1046 return 0;803 return 0;
804
805 if (!pfl || pfl->type == dbfl_type_rec) {
806 field_type = paddr->field_type;
807 no_elements = paddr->no_elements;
808 } else {
809 field_type = pfl->field_type;
810 no_elements = pfl->no_elements;
1047 }811 }
1048812
813 if (field_type >= DBF_INLINK && field_type <= DBF_FWDLINK)
814 return getLinkValue(paddr, dbrType, pbuf, nRequest);
815
816 if (paddr->special == SPC_ATTRIBUTE)
817 return getAttrValue(paddr, dbrType, pbuf, nRequest);
818
1049 /* Check for valid request */819 /* Check for valid request */
1050 if (INVALID_DB_REQ(dbrType) || field_type > DBF_DEVICE) {820 if (INVALID_DB_REQ(dbrType) || field_type > DBF_DEVICE) {
1051 char message[80];821 char message[80];
@@ -1052,7 +822,8 @@
1052 }822 }
1053823
1054 /* check for array */824 /* check for array */
1055 if (paddr->special == SPC_DBADDR &&825 if ((!pfl || pfl->type == dbfl_type_rec) &&
826 paddr->special == SPC_DBADDR &&
1056 no_elements > 1 &&827 no_elements > 1 &&
1057 (prset = dbGetRset(paddr)) &&828 (prset = dbGetRset(paddr)) &&
1058 prset->get_array_info) {829 prset->get_array_info) {
@@ -1062,15 +833,20 @@
1062833
1063 if (offset == 0 && (!nRequest || no_elements == 1)) {834 if (offset == 0 && (!nRequest || no_elements == 1)) {
1064 if (nRequest) *nRequest = 1;835 if (nRequest) *nRequest = 1;
1065 if (pfl != NULL) {836 if (!pfl || pfl->type == dbfl_type_rec) {
837 status = dbFastGetConvertRoutine[field_type][dbrType]
838 (paddr->pfield, pbuffer, paddr);
839 } else {
1066 DBADDR localAddr = *paddr; /* Structure copy */840 DBADDR localAddr = *paddr; /* Structure copy */
1067841 localAddr.field_type = pfl->field_type;
1068 localAddr.pfield = (char *)&pfl->field;842 localAddr.field_size = pfl->field_size;
843 localAddr.no_elements = pfl->no_elements;
844 if (pfl->type == dbfl_type_val)
845 localAddr.pfield = (char *) &pfl->u.v.field;
846 else
847 localAddr.pfield = (char *) pfl->u.r.field;
1069 status = dbFastGetConvertRoutine[field_type][dbrType]848 status = dbFastGetConvertRoutine[field_type][dbrType]
1070 (localAddr.pfield, pbuffer, &localAddr);849 (localAddr.pfield, pbuffer, &localAddr);
1071 } else {
1072 status = dbFastGetConvertRoutine[field_type][dbrType]
1073 (paddr->pfield, pbuffer, paddr);
1074 }850 }
1075 } else {851 } else {
1076 long n;852 long n;
@@ -1094,18 +870,23 @@
1094 /* convert database field and place it in the buffer */870 /* convert database field and place it in the buffer */
1095 if (n <= 0) {871 if (n <= 0) {
1096 ;/*do nothing*/872 ;/*do nothing*/
1097 } else if (pfl) {873 } else if (!pfl || pfl->type == dbfl_type_rec) {
874 status = convert(paddr, pbuffer, n, no_elements, offset);
875 } else {
1098 DBADDR localAddr = *paddr; /* Structure copy */876 DBADDR localAddr = *paddr; /* Structure copy */
1099877 localAddr.field_type = pfl->field_type;
1100 localAddr.pfield = (char *)&pfl->field;878 localAddr.field_size = pfl->field_size;
879 localAddr.no_elements = pfl->no_elements;
880 if (pfl->type == dbfl_type_val)
881 localAddr.pfield = (char *) &pfl->u.v.field;
882 else
883 localAddr.pfield = (char *) pfl->u.r.field;
1101 status = convert(&localAddr, pbuffer, n, no_elements, offset);884 status = convert(&localAddr, pbuffer, n, no_elements, offset);
1102 } else {
1103 status = convert(paddr, pbuffer, n, no_elements, offset);
1104 }885 }
1105 }886 }
1106 return status;887 return status;
1107}888}
1108
1109889
890
1110devSup* epicsShareAPI dbDTYPtoDevSup(dbRecordType *prdes, int dtyp) {891devSup* epicsShareAPI dbDTYPtoDevSup(dbRecordType *prdes, int dtyp) {
1111 return (devSup *)ellNth(&prdes->devList, dtyp+1);892 return (devSup *)ellNth(&prdes->devList, dtyp+1);
1112}893}
@@ -1125,10 +906,9 @@
1125 dbCommon *precord = paddr->precord;906 dbCommon *precord = paddr->precord;
1126 dbFldDes *pfldDes = paddr->pfldDes;907 dbFldDes *pfldDes = paddr->pfldDes;
1127 long special = paddr->special;908 long special = paddr->special;
1128 DBLINK *plink = (DBLINK *)paddr->pfield;909 struct link *plink = (struct link *)paddr->pfield;
1129 const char *pstring = (const char *)pbuffer;910 const char *pstring = (const char *)pbuffer;
1130 DBENTRY dbEntry;911 DBENTRY dbEntry;
1131 DBADDR dbaddr;
1132 struct dsxt *old_dsxt = NULL;912 struct dsxt *old_dsxt = NULL;
1133 struct dset *new_dset = NULL;913 struct dset *new_dset = NULL;
1134 struct dsxt *new_dsxt = NULL;914 struct dsxt *new_dsxt = NULL;
@@ -1199,21 +979,8 @@
1199979
1200 switch (plink->type) { /* Old link type */980 switch (plink->type) { /* Old link type */
1201 case DB_LINK:981 case DB_LINK:
1202 free(plink->value.pv_link.pvt);
1203 plink->value.pv_link.pvt = 0;
1204 plink->type = PV_LINK;
1205 plink->value.pv_link.getCvt = 0;
1206 plink->value.pv_link.pvlMask = 0;
1207 plink->value.pv_link.lastGetdbrType = 0;
1208 dbLockSetSplit(precord);
1209 break;
1210
1211 case CA_LINK:982 case CA_LINK:
1212 dbCaRemoveLink(plink);983 dbRemoveLink(plink);
1213 plink->type = PV_LINK;
1214 plink->value.pv_link.getCvt = 0;
1215 plink->value.pv_link.pvlMask = 0;
1216 plink->value.pv_link.lastGetdbrType = 0;
1217 break;984 break;
1218985
1219 case CONSTANT:986 case CONSTANT:
@@ -1260,35 +1027,7 @@
12601027
1261 switch (plink->type) { /* New link type */1028 switch (plink->type) { /* New link type */
1262 case PV_LINK:1029 case PV_LINK:
1263 if (plink == &precord->tsel)1030 dbAddLink(precord, plink, pfldDes->field_type);
1264 recGblTSELwasModified(plink);
1265 plink->value.pv_link.precord = precord;
1266
1267 if (!(plink->value.pv_link.pvlMask & (pvlOptCA|pvlOptCP|pvlOptCPP)) &&
1268 (dbNameToAddr(plink->value.pv_link.pvname, &dbaddr) == 0)) {
1269 /* It's a DB link */
1270 DBADDR *pdbAddr;
1271
1272 plink->type = DB_LINK;
1273 pdbAddr = dbMalloc(sizeof(struct dbAddr));
1274 *pdbAddr = dbaddr; /* NB: structure copy */;
1275 plink->value.pv_link.pvt = pdbAddr;
1276 dbLockSetRecordLock(pdbAddr->precord);
1277 dbLockSetMerge(precord, pdbAddr->precord);
1278 } else { /* Make it a CA link */
1279 char *pperiod;
1280
1281 plink->type = CA_LINK;
1282 if (pfldDes->field_type == DBF_INLINK) {
1283 plink->value.pv_link.pvlMask |= pvlOptInpNative;
1284 }
1285 dbCaAddLink(plink);
1286 if (pfldDes->field_type == DBF_FWDLINK) {
1287 pperiod = strrchr(plink->value.pv_link.pvname, '.');
1288 if (pperiod && strstr(pperiod, "PROC"))
1289 plink->value.pv_link.pvlMask |= pvlOptFWD;
1290 }
1291 }
1292 break;1031 break;
12931032
1294 case CONSTANT:1033 case CONSTANT:
@@ -1316,7 +1055,7 @@
1316 }1055 }
1317postScanEvent:1056postScanEvent:
1318 if (scan != precord->scan)1057 if (scan != precord->scan)
1319 db_post_events(precord, &precord->scan, DBE_VALUE|DBE_LOG);1058 db_post_events(precord, &precord->scan, DBE_VALUE | DBE_LOG);
1320unlock:1059unlock:
1321 dbLockSetGblUnlock();1060 dbLockSetGblUnlock();
1322finish:1061finish:
@@ -1337,8 +1076,7 @@
1337 return S_db_noMod;1076 return S_db_noMod;
13381077
1339 /*check for putField disabled*/1078 /*check for putField disabled*/
1340 if (precord->disp &&1079 if (precord->disp && paddr->pfield != &precord->disp)
1341 (void *)(&precord->disp) != paddr->pfield)
1342 return S_db_putDisabled;1080 return S_db_putDisabled;
13431081
1344 if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK)1082 if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK)
@@ -1347,7 +1085,7 @@
1347 dbScanLock(precord);1085 dbScanLock(precord);
1348 status = dbPut(paddr, dbrType, pbuffer, nRequest);1086 status = dbPut(paddr, dbrType, pbuffer, nRequest);
1349 if (status == 0) {1087 if (status == 0) {
1350 if (paddr->pfield == (void *)&precord->proc ||1088 if (paddr->pfield == &precord->proc ||
1351 (pfldDes->process_passive &&1089 (pfldDes->process_passive &&
1352 precord->scan == 0 &&1090 precord->scan == 0 &&
1353 dbrType < DBR_PUT_ACKT)) {1091 dbrType < DBR_PUT_ACKT)) {
@@ -1366,16 +1104,18 @@
1366 dbScanUnlock(precord);1104 dbScanUnlock(precord);
1367 return status;1105 return status;
1368}1106}
1369
13701107
1371static long putAckt(DBADDR *paddr, const unsigned short *pbuffer, long nRequest,1108
1109static long putAckt(DBADDR *paddr, const void *pbuffer, long nRequest,
1372 long no_elements, long offset)1110 long no_elements, long offset)
1373{1111{
1374 dbCommon *precord = paddr->precord;1112 dbCommon *precord = paddr->precord;
1113 const unsigned short *ptrans = pbuffer;
13751114
1376 if (*pbuffer == precord->ackt) return 0;1115 if (*ptrans == precord->ackt) return 0;
1377 precord->ackt = *pbuffer;1116 precord->ackt = *ptrans;
1378 db_post_events(precord, &precord->ackt, DBE_VALUE | DBE_ALARM);1117 db_post_events(precord, &precord->ackt, DBE_VALUE | DBE_ALARM);
1379 if (!precord->ackt && precord->acks > precord->sevr) {1118 if (!precord->ackt &&
1119 precord->acks > precord->sevr) {
1380 precord->acks = precord->sevr;1120 precord->acks = precord->sevr;
1381 db_post_events(precord, &precord->acks, DBE_VALUE | DBE_ALARM);1121 db_post_events(precord, &precord->acks, DBE_VALUE | DBE_ALARM);
1382 }1122 }
@@ -1383,19 +1123,20 @@
1383 return 0;1123 return 0;
1384}1124}
13851125
1386static long putAcks(DBADDR *paddr, const unsigned short *pbuffer, long nRequest,1126static long putAcks(DBADDR *paddr, const void *pbuffer, long nRequest,
1387 long no_elements, long offset)1127 long no_elements, long offset)
1388{1128{
1389 dbCommon *precord = paddr->precord;1129 dbCommon *precord = paddr->precord;
1130 const unsigned short *psev = pbuffer;
13901131
1391 if (*pbuffer >= precord->acks) {1132 if (*psev >= precord->acks) {
1392 precord->acks = 0;1133 precord->acks = 0;
1134 db_post_events(precord, &precord->acks, DBE_VALUE | DBE_ALARM);
1393 db_post_events(precord, NULL, DBE_ALARM);1135 db_post_events(precord, NULL, DBE_ALARM);
1394 db_post_events(precord, &precord->acks, DBE_VALUE | DBE_ALARM);
1395 }1136 }
1396 return 0;1137 return 0;
1397}1138}
1398
13991139
1140
1400long epicsShareAPI dbPut(DBADDR *paddr, short dbrType,1141long epicsShareAPI dbPut(DBADDR *paddr, short dbrType,
1401 const void *pbuffer, long nRequest)1142 const void *pbuffer, long nRequest)
1402{1143{
@@ -1403,17 +1144,17 @@
1403 short field_type = paddr->field_type;1144 short field_type = paddr->field_type;
1404 long no_elements = paddr->no_elements;1145 long no_elements = paddr->no_elements;
1405 long special = paddr->special;1146 long special = paddr->special;
1406 long offset;
1407 long status = 0;1147 long status = 0;
1408 dbFldDes *pfldDes;1148 dbFldDes *pfldDes;
1409 int isValueField;1149 int isValueField;
14101150
1411 if (special == SPC_ATTRIBUTE) return S_db_noMod;1151 if (special == SPC_ATTRIBUTE)
1152 return S_db_noMod;
14121153
1413 if (dbrType == DBR_PUT_ACKT && field_type <= DBF_DEVICE) {1154 if (dbrType == DBR_PUT_ACKT && field_type <= DBF_DEVICE) {
1414 return putAckt(paddr, (unsigned short *)pbuffer, 1, 1, 0);1155 return putAckt(paddr, pbuffer, 1, 1, 0);
1415 } else if (dbrType == DBR_PUT_ACKS && field_type <= DBF_DEVICE) {1156 } else if (dbrType == DBR_PUT_ACKS && field_type <= DBF_DEVICE) {
1416 return putAcks(paddr, (unsigned short *)pbuffer, 1, 1, 0);1157 return putAcks(paddr, pbuffer, 1, 1, 0);
1417 } else if (INVALID_DB_REQ(dbrType) || field_type > DBF_DEVICE) {1158 } else if (INVALID_DB_REQ(dbrType) || field_type > DBF_DEVICE) {
1418 char message[80];1159 char message[80];
14191160
@@ -1432,6 +1173,7 @@
1432 paddr->pfield, paddr);1173 paddr->pfield, paddr);
1433 } else {1174 } else {
1434 struct rset *prset = dbGetRset(paddr);1175 struct rset *prset = dbGetRset(paddr);
1176 long offset = 0;
14351177
1436 if (paddr->special == SPC_DBADDR &&1178 if (paddr->special == SPC_DBADDR &&
1437 prset && prset->get_array_info) {1179 prset && prset->get_array_info) {
@@ -1439,8 +1181,6 @@
14391181
1440 status = prset->get_array_info(paddr, &dummy, &offset);1182 status = prset->get_array_info(paddr, &dummy, &offset);
1441 }1183 }
1442 else
1443 offset = 0;
1444 if (no_elements < nRequest) nRequest = no_elements;1184 if (no_elements < nRequest) nRequest = no_elements;
1445 status = dbPutConvertRoutine[dbrType][field_type](paddr, pbuffer,1185 status = dbPutConvertRoutine[dbrType][field_type](paddr, pbuffer,
1446 nRequest, no_elements, offset);1186 nRequest, no_elements, offset);
@@ -1471,140 +1211,4 @@
14711211
1472 return status;1212 return status;
1473}1213}
1474
14751214
1476/* various utility routines */
1477long epicsShareAPI dbGetControlLimits(
1478 const struct link *plink,double *low, double *high)
1479{
1480 struct buffer {
1481 DBRctrlDouble
1482 double value;
1483 } buffer;
1484 DBADDR *paddr;
1485 long options = DBR_CTRL_DOUBLE;
1486 long number_elements = 0;
1487 long status;
1488
1489 if(plink->type == CA_LINK) return(dbCaGetControlLimits(plink,low,high));
1490 if(plink->type !=DB_LINK) return(S_db_notFound);
1491 paddr = (DBADDR *)plink->value.pv_link.pvt;
1492 status = dbGet(paddr,DBR_DOUBLE,&buffer,&options,&number_elements,0);
1493 if(status) return(status);
1494 *low = buffer.lower_ctrl_limit;
1495 *high = buffer.upper_ctrl_limit;
1496 return(0);
1497}
1498
1499long epicsShareAPI dbGetGraphicLimits(
1500 const struct link *plink,double *low, double *high)
1501{
1502 struct buffer {
1503 DBRgrDouble
1504 double value;
1505 } buffer;
1506 DBADDR *paddr;
1507 long options = DBR_GR_DOUBLE;
1508 long number_elements = 0;
1509 long status;
1510
1511 if(plink->type == CA_LINK) return(dbCaGetGraphicLimits(plink,low,high));
1512 if(plink->type !=DB_LINK) return(S_db_notFound);
1513 paddr = (DBADDR *)plink->value.pv_link.pvt;
1514 status = dbGet(paddr,DBR_DOUBLE,&buffer,&options,&number_elements,0);
1515 if(status) return(status);
1516 *low = buffer.lower_disp_limit;
1517 *high = buffer.upper_disp_limit;
1518 return(0);
1519}
1520
15211215
1522long epicsShareAPI dbGetAlarmLimits(const struct link *plink,
1523 double *lolo, double *low, double *high, double *hihi)
1524{
1525 struct buffer {
1526 DBRalDouble
1527 double value;
1528 } buffer;
1529 DBADDR *paddr;
1530 long options = DBR_AL_DOUBLE;
1531 long number_elements = 0;
1532 long status;
1533
1534 if(plink->type == CA_LINK)
1535 return(dbCaGetAlarmLimits(plink,lolo,low,high,hihi));
1536 if(plink->type !=DB_LINK) return(S_db_notFound);
1537 paddr = (DBADDR *)plink->value.pv_link.pvt;
1538 status = dbGet(paddr,DBR_DOUBLE,&buffer,&options,&number_elements,0);
1539 if(status) return(status);
1540 *lolo = buffer.lower_alarm_limit;
1541 *low = buffer.lower_warning_limit;
1542 *high = buffer.upper_warning_limit;
1543 *hihi = buffer.upper_alarm_limit;
1544 return(0);
1545}
1546
1547long epicsShareAPI dbGetPrecision(const struct link *plink,short *precision)
1548{
1549 struct buffer {
1550 DBRprecision
1551 double value;
1552 } buffer;
1553 DBADDR *paddr;
1554 long options = DBR_PRECISION;
1555 long number_elements = 0;
1556 long status;
1557
1558 if(plink->type == CA_LINK) return(dbCaGetPrecision(plink,precision));
1559 if(plink->type !=DB_LINK) return(S_db_notFound);
1560 paddr = (DBADDR *)plink->value.pv_link.pvt;
1561 status = dbGet(paddr,DBR_DOUBLE,&buffer,&options,&number_elements,0);
1562 if(status) return(status);
1563 *precision = buffer.precision.dp;
1564 return(0);
1565}
1566
15671216
1568long epicsShareAPI dbGetUnits(1217
1569 const struct link *plink,char *units,int unitsSize)
1570{
1571 struct buffer {
1572 DBRunits
1573 double value;
1574 } buffer;
1575 DBADDR *paddr;
1576 long options = DBR_UNITS;
1577 long number_elements = 0;
1578 long status;
1579
1580 if(plink->type == CA_LINK) return(dbCaGetUnits(plink,units,unitsSize));
1581 if(plink->type !=DB_LINK) return(S_db_notFound);
1582 paddr = (DBADDR *)plink->value.pv_link.pvt;
1583 status = dbGet(paddr,DBR_DOUBLE,&buffer,&options,&number_elements,0);
1584 if(status) return(status);
1585 strncpy(units,buffer.units,unitsSize);
1586 return(0);
1587}
1588
1589long epicsShareAPI dbGetAlarm(const struct link *plink,
1590 epicsEnum16 *status,epicsEnum16 *severity)
1591{
1592 DBADDR *paddr;
1593
1594 if(plink->type == CA_LINK) return(dbCaGetAlarm(plink,status,severity));
1595 if(plink->type !=DB_LINK) return(S_db_notFound);
1596 paddr = (DBADDR *)plink->value.pv_link.pvt;
1597 if (status) *status = paddr->precord->stat;
1598 if (severity) *severity = paddr->precord->sevr;
1599 return(0);
1600}
1601
1602long epicsShareAPI dbGetTimeStamp(const struct link *plink,epicsTimeStamp *pstamp)
1603{
1604 DBADDR *paddr;
1605
1606 if (plink->type == CA_LINK)
1607 return dbCaGetTimeStamp(plink,pstamp);
1608 if (plink->type != DB_LINK)
1609 return S_db_notFound;
1610 paddr = (DBADDR *)plink->value.pv_link.pvt;
1611 *pstamp = paddr->precord->time;
1612 return 0;
1613}
16141218
=== modified file 'src/ioc/db/dbAccess.h'
--- src/ioc/db/dbAccess.h 2002-07-12 21:35:43 +0000
+++ src/ioc/db/dbAccess.h 2012-06-21 20:42:45 +0000
@@ -3,8 +3,7 @@
3* National Laboratory.3* National Laboratory.
4* Copyright (c) 2002 The Regents of the University of California, as4* Copyright (c) 2002 The Regents of the University of California, as
5* Operator of Los Alamos National Laboratory.5* Operator of Los Alamos National Laboratory.
6* EPICS BASE Versions 3.13.76* EPICS BASE is distributed subject to a Software License Agreement found
7* and higher are distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution. 7* in file LICENSE that is included with this distribution.
9\*************************************************************************/8\*************************************************************************/
10/* dbAccess.h */9/* dbAccess.h */
@@ -22,6 +21,7 @@
22#include "dbAddr.h"21#include "dbAddr.h"
23#include "dbLock.h"22#include "dbLock.h"
24#include "dbAccessDefs.h"23#include "dbAccessDefs.h"
24#include "dbLink.h"
25#include "dbCa.h"25#include "dbCa.h"
26#include "dbCommon.h"26#include "dbCommon.h"
27#include "db_field_log.h"27#include "db_field_log.h"
2828
=== modified file 'src/ioc/db/dbAccessDefs.h'
--- src/ioc/db/dbAccessDefs.h 2010-10-05 19:27:37 +0000
+++ src/ioc/db/dbAccessDefs.h 2012-06-21 20:42:45 +0000
@@ -3,9 +3,8 @@
3* National Laboratory.3* National Laboratory.
4* Copyright (c) 2002 The Regents of the University of California, as4* Copyright (c) 2002 The Regents of the University of California, as
5* Operator of Los Alamos National Laboratory.5* Operator of Los Alamos National Laboratory.
6* EPICS BASE Versions 3.13.76* EPICS BASE is distributed subject to a Software License Agreement found
7* and higher are distributed subject to a Software License Agreement found7* in file LICENSE that is included with this distribution.
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/8\*************************************************************************/
10/* dbAccessDefs.h */9/* dbAccessDefs.h */
11/* $Revision-Id$ */10/* $Revision-Id$ */
@@ -20,6 +19,8 @@
2019
21#include "epicsTypes.h"20#include "epicsTypes.h"
22#include "epicsTime.h"21#include "epicsTime.h"
22#include "dbBase.h"
23#include "dbAddr.h"
2324
24#ifdef INCLdb_accessh_epicsExportSharedSymbols25#ifdef INCLdb_accessh_epicsExportSharedSymbols
25# define epicsExportSharedSymbols26# define epicsExportSharedSymbols
@@ -47,7 +48,7 @@
47#define DBR_CTRL_DOUBLE 0x0000010048#define DBR_CTRL_DOUBLE 0x00000100
48#define DBR_AL_LONG 0x0000020049#define DBR_AL_LONG 0x00000200
49#define DBR_AL_DOUBLE 0x0000040050#define DBR_AL_DOUBLE 0x00000400
50
5151
52
52/**********************************************************************53/**********************************************************************
53 * The next page contains macros for defining requests.54 * The next page contains macros for defining requests.
54 * As an example the following defines a buffer to accept an array55 * As an example the following defines a buffer to accept an array
@@ -69,7 +70,7 @@
69 * options = DBR_STATUS|DBR_TIME;70 * options = DBR_STATUS|DBR_TIME;
70 * number_elements = 10;71 * number_elements = 10;
71 * rtnval=dbGetField(paddr,DBR_FLOAT,&buffer,&options,&number_elements);72 * rtnval=dbGetField(paddr,DBR_FLOAT,&buffer,&options,&number_elements);
72 * 73 *
73 * When dbGetField returns:74 * When dbGetField returns:
74 * rtnval is error status (0 means success)75 * rtnval is error status (0 means success)
75 * options has a bit set for each option that was accepted76 * options has a bit set for each option that was accepted
@@ -97,7 +98,7 @@
97 * MYBUFFER *pbuf1;98 * MYBUFFER *pbuf1;
98 * MYBUFFER buf;99 * MYBUFFER buf;
99 *************************************************************************/100 *************************************************************************/
100
101101
102
102/* Macros for defining each option */103/* Macros for defining each option */
103#define DBRstatus \104#define DBRstatus \
104 epicsUInt16 status; /* alarm status */\105 epicsUInt16 status; /* alarm status */\
@@ -143,7 +144,7 @@
143 epicsFloat64 upper_warning_limit;\144 epicsFloat64 upper_warning_limit;\
144 epicsFloat64 lower_warning_limit;\145 epicsFloat64 lower_warning_limit;\
145 epicsFloat64 lower_alarm_limit;146 epicsFloat64 lower_alarm_limit;
146
147147
148
148/* structures for each option type */149/* structures for each option type */
149struct dbr_status {DBRstatus};150struct dbr_status {DBRstatus};
150struct dbr_units {DBRunits};151struct dbr_units {DBRunits};
@@ -198,25 +199,6 @@
198#define S_db_cntSpwn (M_dbAccess|63) /*Cannot spawn dbContTask*/199#define S_db_cntSpwn (M_dbAccess|63) /*Cannot spawn dbContTask*/
199#define S_db_cntCont (M_dbAccess|65) /*Cannot resume dbContTask*/200#define S_db_cntCont (M_dbAccess|65) /*Cannot resume dbContTask*/
200#define S_db_noMemory (M_dbAccess|66) /*unable to allocate data structure from pool*/201#define S_db_noMemory (M_dbAccess|66) /*unable to allocate data structure from pool*/
201
202202
203/* Global Database Access Routines*/
204#define dbGetLink(PLNK, DBRTYPE, PBUFFER, OPTIONS, NREQUEST) \
205 ( ( ( (PLNK)->type == CONSTANT ) && \
206 ( (NREQUEST) == 0) &&\
207 ( (OPTIONS) == 0) ) \
208 ? 0 \
209 : dbGetLinkValue((PLNK),(DBRTYPE), \
210 (void *)(PBUFFER), (OPTIONS), (NREQUEST) ) )
211#define dbPutLink(PLNK, DBRTYPE, PBUFFER, NREQUEST) \
212 ( ( (PLNK)->type == CONSTANT) \
213 ? 0 \
214 : dbPutLinkValue( (PLNK), (DBRTYPE), (void *)(PBUFFER), (NREQUEST) ) )
215#define dbGetPdbAddrFromLink(PLNK) \
216 ( ( (PLNK)->type != DB_LINK ) \
217 ? 0 \
218 : ( ( (struct dbAddr *)( (PLNK)->value.pv_link.pvt) ) ) )
219#define dbGetSevr(PLINK,PSEVERITY) \
220 dbGetAlarm((PLINK),NULL,(PSEVERITY))
221203
222epicsShareFunc long epicsShareAPI dbPutSpecial(struct dbAddr *paddr,int pass);204epicsShareFunc long epicsShareAPI dbPutSpecial(struct dbAddr *paddr,int pass);
223epicsShareFunc struct rset * epicsShareAPI dbGetRset(const struct dbAddr *paddr);205epicsShareFunc struct rset * epicsShareAPI dbGetRset(const struct dbAddr *paddr);
@@ -224,51 +206,24 @@
224 const char *recordTypename,const char *name,const char*value);206 const char *recordTypename,const char *name,const char*value);
225epicsShareFunc int epicsShareAPI dbIsValueField(const struct dbFldDes *pdbFldDes);207epicsShareFunc int epicsShareAPI dbIsValueField(const struct dbFldDes *pdbFldDes);
226epicsShareFunc int epicsShareAPI dbGetFieldIndex(const struct dbAddr *paddr);208epicsShareFunc int epicsShareAPI dbGetFieldIndex(const struct dbAddr *paddr);
227epicsShareFunc long epicsShareAPI dbGetNelements(
228 const struct link *plink,long *nelements);
229epicsShareFunc int epicsShareAPI dbIsLinkConnected(const struct link *plink);
230epicsShareFunc int epicsShareAPI dbGetLinkDBFtype(const struct link *plink);
231epicsShareFunc long epicsShareAPI dbScanLink(
232 struct dbCommon *pfrom, struct dbCommon *pto);
233epicsShareFunc long epicsShareAPI dbScanPassive(209epicsShareFunc long epicsShareAPI dbScanPassive(
234 struct dbCommon *pfrom,struct dbCommon *pto);210 struct dbCommon *pfrom,struct dbCommon *pto);
235epicsShareFunc void epicsShareAPI dbScanFwdLink(struct link *plink);
236epicsShareFunc long epicsShareAPI dbProcess(struct dbCommon *precord);211epicsShareFunc long epicsShareAPI dbProcess(struct dbCommon *precord);
237epicsShareFunc long epicsShareAPI dbNameToAddr(212epicsShareFunc long epicsShareAPI dbNameToAddr(
238 const char *pname,struct dbAddr *);213 const char *pname,struct dbAddr *);
239epicsShareFunc devSup* epicsShareAPI dbDTYPtoDevSup(dbRecordType *prdes, int dtyp);214epicsShareFunc devSup* epicsShareAPI dbDTYPtoDevSup(dbRecordType *prdes, int dtyp);
240epicsShareFunc devSup* epicsShareAPI dbDSETtoDevSup(dbRecordType *prdes, struct dset *pdset);215epicsShareFunc devSup* epicsShareAPI dbDSETtoDevSup(dbRecordType *prdes, struct dset *pdset);
241epicsShareFunc long epicsShareAPI dbGetLinkValue(
242 struct link *,short dbrType,void *pbuffer,long *options,long *nRequest);
243epicsShareFunc long epicsShareAPI dbGetField(216epicsShareFunc long epicsShareAPI dbGetField(
244 struct dbAddr *,short dbrType,void *pbuffer,long *options,217 struct dbAddr *,short dbrType,void *pbuffer,long *options,
245 long *nRequest,void *pfl);218 long *nRequest,void *pfl);
246epicsShareFunc long epicsShareAPI dbGet(219epicsShareFunc long epicsShareAPI dbGet(
247 struct dbAddr *,short dbrType,void *pbuffer,long *options,220 struct dbAddr *,short dbrType,void *pbuffer,long *options,
248 long *nRequest,void *pfl);221 long *nRequest,void *pfl);
249epicsShareFunc long epicsShareAPI dbPutLinkValue(
250 struct link *,short dbrType,const void *pbuffer,long nRequest);
251epicsShareFunc long epicsShareAPI dbPutField(222epicsShareFunc long epicsShareAPI dbPutField(
252 struct dbAddr *,short dbrType,const void *pbuffer,long nRequest);223 struct dbAddr *,short dbrType,const void *pbuffer,long nRequest);
253epicsShareFunc long epicsShareAPI dbPut(224epicsShareFunc long epicsShareAPI dbPut(
254 struct dbAddr *,short dbrType,const void *pbuffer,long nRequest);225 struct dbAddr *,short dbrType,const void *pbuffer,long nRequest);
255226
256/* various utility routines */
257epicsShareFunc long epicsShareAPI dbGetControlLimits(
258 const struct link *plink,double *low, double *high);
259epicsShareFunc long epicsShareAPI dbGetGraphicLimits(
260 const struct link *plink,double *low, double *high);
261epicsShareFunc long epicsShareAPI dbGetAlarmLimits(
262 const struct link *plink,double *lolo, double *low, double *high, double *hihi);
263epicsShareFunc long epicsShareAPI dbGetPrecision(
264 const struct link *plink,short *precision);
265epicsShareFunc long epicsShareAPI dbGetUnits(
266 const struct link *plink,char *units,int unitsSize);
267epicsShareFunc long epicsShareAPI dbGetAlarm(
268 const struct link *plink, epicsEnum16 *status,epicsEnum16 *severity);
269epicsShareFunc long epicsShareAPI dbGetTimeStamp(
270 const struct link *plink,epicsTimeStamp *pstamp);
271
272typedef void(*SPC_ASCALLBACK)(struct dbCommon *);227typedef void(*SPC_ASCALLBACK)(struct dbCommon *);
273/*dbSpcAsRegisterCallback called by access security */228/*dbSpcAsRegisterCallback called by access security */
274epicsShareFunc void epicsShareAPI dbSpcAsRegisterCallback(SPC_ASCALLBACK func);229epicsShareFunc void epicsShareAPI dbSpcAsRegisterCallback(SPC_ASCALLBACK func);
275230
=== modified file 'src/ioc/db/dbAddr.h'
--- src/ioc/db/dbAddr.h 2008-08-15 18:58:18 +0000
+++ src/ioc/db/dbAddr.h 2012-06-21 20:42:45 +0000
@@ -4,7 +4,7 @@
4* Copyright (c) 2002 The Regents of the University of California, as4* Copyright (c) 2002 The Regents of the University of California, as
5* Operator of Los Alamos National Laboratory.5* Operator of Los Alamos National Laboratory.
6* EPICS BASE is distributed subject to a Software License Agreement found6* EPICS BASE is distributed subject to a Software License Agreement found
7* in file LICENSE that is included with this distribution. 7* in file LICENSE that is included with this distribution.
8\*************************************************************************/8\*************************************************************************/
99
10#ifndef dbAddrh10#ifndef dbAddrh
@@ -27,7 +27,4 @@
2727
28typedef dbAddr DBADDR;28typedef dbAddr DBADDR;
2929
30unsigned dbNameOfPV (const dbAddr * paddr, char * pBuf, unsigned bufLen);
31unsigned dbNameSizeOfPV (const dbAddr * paddr);
32
33#endif /* dbAddrh */30#endif /* dbAddrh */
3431
=== modified file 'src/ioc/db/dbBkpt.c'
--- src/ioc/db/dbBkpt.c 2010-10-05 19:27:37 +0000
+++ src/ioc/db/dbBkpt.c 2012-06-21 20:42:45 +0000
@@ -65,6 +65,7 @@
65#include "dbAddr.h"65#include "dbAddr.h"
66#include "dbAccessDefs.h"66#include "dbAccessDefs.h"
67#include "dbScan.h"67#include "dbScan.h"
68#include "dbLink.h"
68#include "dbLock.h"69#include "dbLock.h"
69#include "recGbl.h"70#include "recGbl.h"
70#include "dbTest.h"71#include "dbTest.h"
7172
=== modified file 'src/ioc/db/dbCAC.h'
--- src/ioc/db/dbCAC.h 2011-06-01 22:22:12 +0000
+++ src/ioc/db/dbCAC.h 2012-06-21 20:42:45 +0000
@@ -5,7 +5,7 @@
5* Operator of Los Alamos National Laboratory.5* Operator of Los Alamos National Laboratory.
6* EPICS BASE Versions 3.13.76* EPICS BASE Versions 3.13.7
7* and higher are distributed subject to a Software License Agreement found7* and higher are distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution. 8* in file LICENSE that is included with this distribution.
9\*************************************************************************/9\*************************************************************************/
10/*10/*
11 * $Revision-Id$11 * $Revision-Id$
@@ -49,7 +49,7 @@
49#include "db_access.h"49#include "db_access.h"
50#include "dbNotify.h"50#include "dbNotify.h"
51#include "dbEvent.h"51#include "dbEvent.h"
52#include "dbAddr.h"52#include "dbChannel.h"
53#include "dbLock.h"53#include "dbLock.h"
54#include "dbCommon.h"54#include "dbCommon.h"
55#include "db_convert.h"55#include "db_convert.h"
@@ -75,25 +75,25 @@
75 virtual ~dbBaseIO() {}75 virtual ~dbBaseIO() {}
76};76};
7777
78extern "C" void dbSubscriptionEventCallback ( void *pPrivate, struct dbAddr *paddr,78extern "C" void dbSubscriptionEventCallback ( void *pPrivate, struct dbChannel *dbch,
79 int eventsRemaining, struct db_field_log *pfl );79 int eventsRemaining, struct db_field_log *pfl );
8080
81class dbSubscriptionIO : 81class dbSubscriptionIO :
82 public tsDLNode < dbSubscriptionIO >, 82 public tsDLNode < dbSubscriptionIO >,
83 public dbBaseIO {83 public dbBaseIO {
84public:84public:
85 dbSubscriptionIO ( 85 dbSubscriptionIO (
86 epicsGuard < epicsMutex > &, epicsMutex &,86 epicsGuard < epicsMutex > &, epicsMutex &,
87 dbContext &, dbChannelIO &, struct dbAddr &, cacStateNotify &, 87 dbContext &, dbChannelIO &, struct dbChannel *, cacStateNotify &,
88 unsigned type, unsigned long count, unsigned mask, dbEventCtx );88 unsigned type, unsigned long count, unsigned mask, dbEventCtx );
89 void destructor ( epicsGuard < epicsMutex > & );89 void destructor ( epicsGuard < epicsMutex > & );
90 void unsubscribe ( epicsGuard < epicsMutex > & );90 void unsubscribe ( epicsGuard < epicsMutex > & );
91 void channelDeleteException ( epicsGuard < epicsMutex > & );91 void channelDeleteException ( epicsGuard < epicsMutex > & );
92 void show ( epicsGuard < epicsMutex > &, unsigned level ) const;92 void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
93 void show ( unsigned level ) const;93 void show ( unsigned level ) const;
94 void * operator new ( size_t size, 94 void * operator new ( size_t size,
95 tsFreeList < dbSubscriptionIO, 256, epicsMutexNOOP > & );95 tsFreeList < dbSubscriptionIO, 256, epicsMutexNOOP > & );
96 epicsPlacementDeleteOperator (( void *, 96 epicsPlacementDeleteOperator (( void *,
97 tsFreeList < dbSubscriptionIO, 256, epicsMutexNOOP > & ))97 tsFreeList < dbSubscriptionIO, 256, epicsMutexNOOP > & ))
98private:98private:
99 epicsMutex & mutex;99 epicsMutex & mutex;
@@ -104,8 +104,8 @@
104 unsigned type;104 unsigned type;
105 unsigned id;105 unsigned id;
106 dbSubscriptionIO * isSubscription ();106 dbSubscriptionIO * isSubscription ();
107 friend void dbSubscriptionEventCallback ( 107 friend void dbSubscriptionEventCallback (
108 void * pPrivate, struct dbAddr * paddr,108 void * pPrivate, struct dbChannel * dbch,
109 int eventsRemaining, struct db_field_log * pfl );109 int eventsRemaining, struct db_field_log * pfl );
110 dbSubscriptionIO ( const dbSubscriptionIO & );110 dbSubscriptionIO ( const dbSubscriptionIO & );
111 dbSubscriptionIO & operator = ( const dbSubscriptionIO & );111 dbSubscriptionIO & operator = ( const dbSubscriptionIO & );
@@ -149,8 +149,8 @@
149class dbContextReadNotifyCache {149class dbContextReadNotifyCache {
150public:150public:
151 dbContextReadNotifyCache ( epicsMutex & );151 dbContextReadNotifyCache ( epicsMutex & );
152 void callReadNotify ( epicsGuard < epicsMutex > &, 152 void callReadNotify ( epicsGuard < epicsMutex > &,
153 struct dbAddr & addr, unsigned type, unsigned long count, 153 struct dbChannel * dbch, unsigned type, unsigned long count,
154 cacReadNotify & notify );154 cacReadNotify & notify );
155 void show ( epicsGuard < epicsMutex > &, unsigned level ) const;155 void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
156private:156private:
@@ -162,29 +162,29 @@
162162
163class dbContext : public cacContext {163class dbContext : public cacContext {
164public:164public:
165 dbContext ( epicsMutex & cbMutex, epicsMutex & mutex, 165 dbContext ( epicsMutex & cbMutex, epicsMutex & mutex,
166 cacContextNotify & notify );166 cacContextNotify & notify );
167 virtual ~dbContext ();167 virtual ~dbContext ();
168 void destroyChannel ( epicsGuard < epicsMutex > &, dbChannelIO & );168 void destroyChannel ( epicsGuard < epicsMutex > &, dbChannelIO & );
169 void callReadNotify ( epicsGuard < epicsMutex > &, 169 void callReadNotify ( epicsGuard < epicsMutex > &,
170 struct dbAddr & addr, unsigned type, unsigned long count, 170 struct dbChannel * dbch, unsigned type, unsigned long count,
171 cacReadNotify & notify );171 cacReadNotify & notify );
172 void callStateNotify ( struct dbAddr &addr, unsigned type, unsigned long count, 172 void callStateNotify ( struct dbChannel * dbch, unsigned type, unsigned long count,
173 const struct db_field_log * pfl, cacStateNotify & notify );173 const struct db_field_log * pfl, cacStateNotify & notify );
174 void subscribe ( 174 void subscribe (
175 epicsGuard < epicsMutex > &,175 epicsGuard < epicsMutex > &,
176 struct dbAddr & addr, dbChannelIO & chan,176 struct dbChannel * dbch, dbChannelIO & chan,
177 unsigned type, unsigned long count, unsigned mask, 177 unsigned type, unsigned long count, unsigned mask,
178 cacStateNotify & notify, cacChannel::ioid * pId );178 cacStateNotify & notify, cacChannel::ioid * pId );
179 void initiatePutNotify ( 179 void initiatePutNotify (
180 epicsGuard < epicsMutex > &, dbChannelIO &, struct dbAddr &, 180 epicsGuard < epicsMutex > &, dbChannelIO &, struct dbChannel *,
181 unsigned type, unsigned long count, const void * pValue, 181 unsigned type, unsigned long count, const void * pValue,
182 cacWriteNotify & notify, cacChannel::ioid * pId ); 182 cacWriteNotify & notify, cacChannel::ioid * pId );
183 void show ( unsigned level ) const;183 void show ( unsigned level ) const;
184 void showAllIO ( const dbChannelIO & chan, unsigned level ) const;184 void showAllIO ( const dbChannelIO & chan, unsigned level ) const;
185 void destroyAllIO ( 185 void destroyAllIO (
186 epicsGuard < epicsMutex > &, dbChannelIO & chan );186 epicsGuard < epicsMutex > &, dbChannelIO & chan );
187 void ioCancel ( epicsGuard < epicsMutex > &, 187 void ioCancel ( epicsGuard < epicsMutex > &,
188 dbChannelIO & chan, const cacChannel::ioid &id );188 dbChannelIO & chan, const cacChannel::ioid &id );
189 void ioShow ( epicsGuard < epicsMutex > &,189 void ioShow ( epicsGuard < epicsMutex > &,
190 const cacChannel::ioid & id, unsigned level ) const;190 const cacChannel::ioid & id, unsigned level ) const;
@@ -202,11 +202,11 @@
202 epics_auto_ptr < cacContext > pNetContext;202 epics_auto_ptr < cacContext > pNetContext;
203 char * pStateNotifyCache;203 char * pStateNotifyCache;
204204
205 cacChannel & createChannel ( 205 cacChannel & createChannel (
206 epicsGuard < epicsMutex > &,206 epicsGuard < epicsMutex > &,
207 const char * pChannelName, cacChannelNotify &, 207 const char * pChannelName, cacChannelNotify &,
208 cacChannel::priLev );208 cacChannel::priLev );
209 void flush ( 209 void flush (
210 epicsGuard < epicsMutex > & );210 epicsGuard < epicsMutex > & );
211 unsigned circuitCount (211 unsigned circuitCount (
212 epicsGuard < epicsMutex > & ) const;212 epicsGuard < epicsMutex > & ) const;
@@ -214,7 +214,7 @@
214 epicsGuard < epicsMutex > & ) const;214 epicsGuard < epicsMutex > & ) const;
215 unsigned beaconAnomaliesSinceProgramStart (215 unsigned beaconAnomaliesSinceProgramStart (
216 epicsGuard < epicsMutex > & ) const;216 epicsGuard < epicsMutex > & ) const;
217 void show ( 217 void show (
218 epicsGuard < epicsMutex > &, unsigned level ) const;218 epicsGuard < epicsMutex > &, unsigned level ) const;
219219
220 dbContext ( const dbContext & );220 dbContext ( const dbContext & );
@@ -226,17 +226,17 @@
226{226{
227}227}
228228
229inline dbContextPrivateListOfIO::~dbContextPrivateListOfIO () 229inline dbContextPrivateListOfIO::~dbContextPrivateListOfIO ()
230{230{
231 assert ( ! this->pBlocker );231 assert ( ! this->pBlocker );
232}232}
233233
234inline void dbContext::callReadNotify ( 234inline void dbContext::callReadNotify (
235 epicsGuard < epicsMutex > & guard, struct dbAddr &addr, 235 epicsGuard < epicsMutex > & guard, struct dbChannel * dbch,
236 unsigned type, unsigned long count, cacReadNotify & notifyIn )236 unsigned type, unsigned long count, cacReadNotify & notifyIn )
237{237{
238 guard.assertIdenticalMutex ( this-> mutex );238 guard.assertIdenticalMutex ( this-> mutex );
239 this->readNotifyCache.callReadNotify ( guard, addr, type, count, notifyIn );239 this->readNotifyCache.callReadNotify ( guard, dbch, type, count, notifyIn );
240}240}
241241
242#endif // dbCACh242#endif // dbCACh
243243
=== modified file 'src/ioc/db/dbCa.c'
--- src/ioc/db/dbCa.c 2012-05-04 18:38:59 +0000
+++ src/ioc/db/dbCa.c 2012-06-21 20:42:45 +0000
@@ -411,6 +411,13 @@
411 return pca->isConnected;411 return pca->isConnected;
412}412}
413413
414void dbCaScanFwdLink(struct link *plink) {
415 short fwdLinkValue = 1;
416
417 if (plink->value.pv_link.pvlMask & pvlOptFWD)
418 dbCaPutLink(plink, DBR_SHORT, &fwdLinkValue, 1);
419}
420
414#define pcaGetCheck \421#define pcaGetCheck \
415 assert(plink); \422 assert(plink); \
416 if (plink->type != CA_LINK) return -1; \423 if (plink->type != CA_LINK) return -1; \
@@ -639,7 +646,7 @@
639static void eventCallback(struct event_handler_args arg)646static void eventCallback(struct event_handler_args arg)
640{647{
641 caLink *pca = (caLink *)arg.usr;648 caLink *pca = (caLink *)arg.usr;
642 DBLINK *plink;649 struct link *plink;
643 size_t size;650 size_t size;
644 dbCommon *precord = 0;651 dbCommon *precord = 0;
645 struct dbr_time_double *pdbr_time_double;652 struct dbr_time_double *pdbr_time_double;
646653
=== modified file 'src/ioc/db/dbCa.h'
--- src/ioc/db/dbCa.h 2009-04-29 18:24:25 +0000
+++ src/ioc/db/dbCa.h 2012-06-21 20:42:45 +0000
@@ -40,6 +40,7 @@
40#define dbCaPutLink(plink, dbrType, pbuffer, nRequest) \40#define dbCaPutLink(plink, dbrType, pbuffer, nRequest) \
41 dbCaPutLinkCallback((plink), (dbrType), (pbuffer), (nRequest), 0, 0)41 dbCaPutLinkCallback((plink), (dbrType), (pbuffer), (nRequest), 0, 0)
42epicsShareFunc int dbCaIsLinkConnected(const struct link *plink);42epicsShareFunc int dbCaIsLinkConnected(const struct link *plink);
43epicsShareFunc void dbCaScanFwdLink(struct link *plink);
4344
44/* The following are available after the link is connected*/45/* The following are available after the link is connected*/
45epicsShareFunc long dbCaGetNelements(const struct link *plink,46epicsShareFunc long dbCaGetNelements(const struct link *plink,
4647
=== added file 'src/ioc/db/dbChannel.c'
--- src/ioc/db/dbChannel.c 1970-01-01 00:00:00 +0000
+++ src/ioc/db/dbChannel.c 2012-06-21 20:42:45 +0000
@@ -0,0 +1,865 @@
1/*************************************************************************\
2* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* Copyright (c) 2010 Brookhaven National Laboratory.
5* Copyright (c) 2010 Helmholtz-Zentrum Berlin
6* fuer Materialien und Energie GmbH.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author: Andrew Johnson <anj@aps.anl.gov>
13 * Ralph Lange <Ralph.Lange@bessy.de>
14 */
15
16#include <stdio.h>
17#include <string.h>
18
19#include "cantProceed.h"
20#include "dbChannel.h"
21#include "dbCommon.h"
22#include "dbBase.h"
23#include "dbEvent.h"
24#include "link.h"
25#include <freeList.h>
26#include "dbAccessDefs.h"
27#include "dbLock.h"
28#include "dbStaticLib.h"
29#include "epicsAssert.h"
30#include "epicsString.h"
31#include "errlog.h"
32#include "gpHash.h"
33#include "recSup.h"
34#include "special.h"
35#include "yajl_parse.h"
36
37/* The following is defined in db_convert.h */
38extern unsigned short dbDBRnewToDBRold[DBR_ENUM+1];
39
40typedef struct parseContext {
41 dbChannel *chan;
42 chFilter *filter;
43 int depth;
44} parseContext;
45
46#define CALLIF(rtn) !rtn ? parse_stop : rtn
47
48static void *dbchStringFreeList;
49
50void dbChannelInit (void)
51{
52 if (!dbchStringFreeList) {
53 freeListInitPvt(&dbchStringFreeList,
54 sizeof(epicsOldString), 128);
55 }
56}
57
58static void chf_value(parseContext *parser, parse_result *presult)
59{
60 chFilter *filter = parser->filter;
61
62 if (*presult == parse_stop || parser->depth > 0)
63 return;
64
65 parser->filter = NULL;
66 if (filter->plug->fif->parse_end(filter) == parse_continue) {
67 ellAdd(&parser->chan->filters, &filter->list_node);
68 } else {
69 free(filter); /* FIXME: Use free-list */
70 *presult = parse_stop;
71 }
72}
73
74static int chf_null(void * ctx)
75{
76 parseContext *parser = (parseContext *) ctx;
77 chFilter *filter = parser->filter;
78 parse_result result;
79
80 assert(filter);
81 result = CALLIF(filter->plug->fif->parse_null)(filter );
82 chf_value(parser, &result);
83 return result;
84}
85
86static int chf_boolean(void * ctx, int boolVal)
87{
88 parseContext *parser = (parseContext *) ctx;
89 chFilter *filter = parser->filter;
90 parse_result result;
91
92 assert(filter);
93 result = CALLIF(filter->plug->fif->parse_boolean)(filter , boolVal);
94 chf_value(parser, &result);
95 return result;
96}
97
98static int chf_integer(void * ctx, long integerVal)
99{
100 parseContext *parser = (parseContext *) ctx;
101 chFilter *filter = parser->filter;
102 parse_result result;
103
104 assert(filter);
105 result = CALLIF(filter->plug->fif->parse_integer)(filter , integerVal);
106 chf_value(parser, &result);
107 return result;
108}
109
110static int chf_double(void * ctx, double doubleVal)
111{
112 parseContext *parser = (parseContext *) ctx;
113 chFilter *filter = parser->filter;
114 parse_result result;
115
116 assert(filter);
117 result = CALLIF(filter->plug->fif->parse_double)(filter , doubleVal);
118 chf_value(parser, &result);
119 return result;
120}
121
122static int chf_string(void * ctx, const unsigned char * stringVal,
123 unsigned int stringLen)
124{
125 parseContext *parser = (parseContext *) ctx;
126 chFilter *filter = parser->filter;
127 parse_result result;
128
129 assert(filter);
130 result = CALLIF(filter->plug->fif->parse_string)(filter , (const char *) stringVal, stringLen);
131 chf_value(parser, &result);
132 return result;
133}
134
135static int chf_start_map(void * ctx)
136{
137 parseContext *parser = (parseContext *) ctx;
138 chFilter *filter = parser->filter;
139
140 if (!filter) {
141 assert(parser->depth == 0);
142 return parse_continue; /* Opening '{' */
143 }
144
145 ++parser->depth;
146 return CALLIF(filter->plug->fif->parse_start_map)(filter );
147}
148
149static int chf_map_key(void * ctx, const unsigned char * key,
150 unsigned int stringLen)
151{
152 parseContext *parser = (parseContext *) ctx;
153 chFilter *filter = parser->filter;
154 const chFilterPlugin *plug;
155 parse_result result;
156
157 if (filter) {
158 assert(parser->depth > 0);
159 return CALLIF(filter->plug->fif->parse_map_key)(filter , (const char *) key, stringLen);
160 }
161
162 assert(parser->depth == 0);
163 plug = dbFindFilter((const char *) key, stringLen);
164 if (!plug) {
165 printf("dbChannelCreate: Channel filter '%.*s' not found\n", (int) stringLen, key);
166 return parse_stop;
167 }
168
169 /* FIXME: Use a free-list */
170 filter = (chFilter *) callocMustSucceed(1, sizeof(*filter), "Creating dbChannel filter");
171 filter->chan = parser->chan;
172 filter->plug = plug;
173 filter->puser = NULL;
174
175 result = plug->fif->parse_start(filter);
176 if (result == parse_continue) {
177 parser->filter = filter;
178 } else {
179 free(filter); /* FIXME: Use free-list */
180 }
181 return result;
182}
183
184static int chf_end_map(void * ctx)
185{
186 parseContext *parser = (parseContext *) ctx;
187 chFilter *filter = parser->filter;
188 parse_result result;
189
190 if (!filter) {
191 assert(parser->depth == 0);
192 return parse_continue; /* Final closing '}' */
193 }
194
195 assert(parser->depth > 0);
196 result = CALLIF(filter->plug->fif->parse_end_map)(filter );
197
198 --parser->depth;
199 chf_value(parser, &result);
200 return result;
201}
202
203static int chf_start_array(void * ctx)
204{
205 parseContext *parser = (parseContext *) ctx;
206 chFilter *filter = parser->filter;
207
208 assert(filter);
209 ++parser->depth;
210 return CALLIF(filter->plug->fif->parse_start_array)(filter );
211}
212
213static int chf_end_array(void * ctx)
214{
215 parseContext *parser = (parseContext *) ctx;
216 chFilter *filter = parser->filter;
217 parse_result result;
218
219 assert(filter);
220 result = CALLIF(filter->plug->fif->parse_end_array)(filter );
221 --parser->depth;
222 chf_value(parser, &result);
223 return result;
224}
225
226static const yajl_callbacks chf_callbacks =
227 { chf_null, chf_boolean, chf_integer, chf_double, NULL, chf_string,
228 chf_start_map, chf_map_key, chf_end_map, chf_start_array, chf_end_array };
229
230static const yajl_parser_config chf_config =
231 { 0, 1 }; /* allowComments = NO , checkUTF8 = YES */
232
233static void * chf_malloc(void *ctx, unsigned int sz)
234{
235 return malloc(sz); /* FIXME: free-list */
236}
237
238static void * chf_realloc(void *ctx, void *ptr, unsigned int sz)
239{
240 return realloc(ptr, sz); /* FIXME: free-list */
241}
242
243static void chf_free(void *ctx, void *ptr)
244{
245 return free(ptr); /* FIXME: free-list */
246}
247
248static const yajl_alloc_funcs chf_alloc =
249 { chf_malloc, chf_realloc, chf_free };
250
251static long chf_parse(dbChannel *chan, const char **pjson)
252{
253 parseContext parser =
254 { chan, NULL, 0 };
255 yajl_handle yh = yajl_alloc(&chf_callbacks, &chf_config, &chf_alloc, &parser);
256 const char *json = *pjson;
257 size_t jlen = strlen(json);
258 yajl_status ys;
259 long status;
260
261 if (!yh)
262 return S_db_noMemory;
263
264 ys = yajl_parse(yh, (const unsigned char *) json, jlen);
265 if (ys == yajl_status_insufficient_data)
266 ys = yajl_parse_complete(yh);
267
268 switch (ys) {
269 case yajl_status_ok:
270 status = 0;
271 *pjson += yajl_get_bytes_consumed(yh);
272 break;
273
274 case yajl_status_error: {
275 unsigned char *err;
276
277 err = yajl_get_error(yh, 1, (const unsigned char *) json, jlen);
278 printf("dbChannelCreate: %s\n", err);
279 yajl_free_error(yh, err);
280 } /* fall through */
281 default:
282 status = S_db_notFound;
283 }
284
285 if (parser.filter) {
286 assert(status);
287 parser.filter->plug->fif->parse_abort(parser.filter);
288 free(parser.filter); /* FIXME: free-list */
289 }
290 yajl_free(yh);
291 return status;
292}
293
294static long pvNameLookup(DBENTRY *pdbe, const char **ppname)
295{
296 long status;
297
298 dbInitEntry(pdbbase, pdbe);
299
300 status = dbFindRecordPart(pdbe, ppname);
301 if (status)
302 return status;
303
304 if (**ppname == '.')
305 ++*ppname;
306
307 status = dbFindFieldPart(pdbe, ppname);
308 if (status == S_dbLib_fieldNotFound)
309 status = dbGetAttributePart(pdbe, ppname);
310
311 return status;
312}
313
314long dbChannelTest(const char *name)
315{
316 DBENTRY dbEntry;
317 long status;
318
319 if (!name || !*name || !pdbbase)
320 return S_db_notFound;
321
322 status = pvNameLookup(&dbEntry, &name);
323
324 dbFinishEntry(&dbEntry);
325 return status;
326}
327
328#define TRY(Func, Arg) \
329if (Func) { \
330 result = Func Arg; \
331 if (result != parse_continue) goto failure; \
332}
333
334static long parseArrayRange(dbChannel* chan, const char *pname, const char **ppnext) {
335 epicsInt32 start = 0;
336 epicsInt32 end = -1;
337 epicsInt32 incr = 1;
338 epicsInt32 l;
339 char *pnext;
340 short exist;
341 chFilter *filter;
342 const chFilterPlugin *plug;
343 parse_result result;
344 long status = 0;
345
346 /* If no number is present, strtol() returns 0 and sets pnext=pname,
347 else pnext points to the first char after the number */
348 pname++;
349 l = strtol(pname, &pnext, 0);
350 exist = pnext - pname;
351 if (exist) start = l;
352 pname = pnext;
353 if (*pname == ']' && exist) {
354 end = start;
355 goto insertplug;
356 }
357 if (*pname != ':') {
358 status = S_dbLib_fieldNotFound;
359 goto finish;
360 }
361 pname++;
362 l = strtol(pname, &pnext, 0);
363 exist = pnext - pname;
364 pname = pnext;
365 if (*pname == ']') {
366 if (exist) end = l;
367 goto insertplug;
368 }
369 if (exist) incr = l;
370 if (*pname != ':') {
371 status = S_dbLib_fieldNotFound;
372 goto finish;
373 }
374 pname++;
375 l = strtol(pname, &pnext, 0);
376 exist = pnext - pname;
377 if (exist) end = l;
378 pname = pnext;
379 if (*pname != ']') {
380 status = S_dbLib_fieldNotFound;
381 goto finish;
382 }
383
384 insertplug:
385 pname++;
386 *ppnext = pname;
387
388 plug = dbFindFilter("arr", 3);
389 if (!plug) {
390 status = S_dbLib_fieldNotFound;
391 goto finish;
392 }
393
394 /* FIXME: Use a free-list */
395 filter = (chFilter *) callocMustSucceed(1, sizeof(*filter), "Creating 'arr' dbChannel filter");
396 filter->chan = chan;
397 filter->plug = plug;
398 filter->puser = NULL;
399
400 TRY(filter->plug->fif->parse_start, (filter));
401 TRY(filter->plug->fif->parse_start_map, (filter));
402 if (start != 0) {
403 TRY(filter->plug->fif->parse_map_key, (filter, "s", 1));
404 TRY(filter->plug->fif->parse_integer, (filter, start));
405 }
406 if (incr != 1) {
407 TRY(filter->plug->fif->parse_map_key, (filter, "i", 1));
408 TRY(filter->plug->fif->parse_integer, (filter, incr));
409 }
410 if (end != -1) {
411 TRY(filter->plug->fif->parse_map_key, (filter, "e", 1));
412 TRY(filter->plug->fif->parse_integer, (filter, end));
413 }
414 TRY(filter->plug->fif->parse_end_map, (filter));
415 TRY(filter->plug->fif->parse_end, (filter));
416
417 ellAdd(&chan->filters, &filter->list_node);
418 return 0;
419
420 failure:
421 free(filter); /* FIXME: Use free-list */
422 status = S_dbLib_fieldNotFound;
423
424 finish:
425 return status;
426}
427
428/* Stolen from dbAccess.c: */
429static short mapDBFToDBR[DBF_NTYPES] =
430 {
431 /* DBF_STRING => */DBR_STRING,
432 /* DBF_CHAR => */DBR_CHAR,
433 /* DBF_UCHAR => */DBR_UCHAR,
434 /* DBF_SHORT => */DBR_SHORT,
435 /* DBF_USHORT => */DBR_USHORT,
436 /* DBF_LONG => */DBR_LONG,
437 /* DBF_ULONG => */DBR_ULONG,
438 /* DBF_FLOAT => */DBR_FLOAT,
439 /* DBF_DOUBLE => */DBR_DOUBLE,
440 /* DBF_ENUM, => */DBR_ENUM,
441 /* DBF_MENU, => */DBR_ENUM,
442 /* DBF_DEVICE => */DBR_ENUM,
443 /* DBF_INLINK => */DBR_STRING,
444 /* DBF_OUTLINK => */DBR_STRING,
445 /* DBF_FWDLINK => */DBR_STRING,
446 /* DBF_NOACCESS => */DBR_NOACCESS };
447
448dbChannel * dbChannelCreate(const char *name)
449{
450 const char *pname = name;
451 DBENTRY dbEntry;
452 dbChannel *chan = NULL;
453 dbAddr *paddr;
454 dbFldDes *pflddes;
455 long status;
456 short dbfType;
457
458 if (!name || !*name || !pdbbase)
459 return NULL;
460
461 status = pvNameLookup(&dbEntry, &pname);
462 if (status)
463 goto finish;
464
465 /* FIXME: Use free-list */
466 chan = (dbChannel *) callocMustSucceed(1, sizeof(*chan), "dbChannelCreate");
467 chan->name = epicsStrDup(name); /* FIXME: free-list */
468 ellInit(&chan->filters);
469 ellInit(&chan->pre_chain);
470 ellInit(&chan->post_chain);
471
472 paddr = &chan->addr;
473 pflddes = dbEntry.pflddes;
474 dbfType = pflddes->field_type;
475
476 paddr->precord = dbEntry.precnode->precord;
477 paddr->pfield = dbEntry.pfield;
478 paddr->pfldDes = pflddes;
479 paddr->no_elements = 1;
480 paddr->field_type = dbfType;
481 paddr->field_size = pflddes->size;
482 paddr->special = pflddes->special;
483 paddr->dbr_field_type = mapDBFToDBR[dbfType];
484
485 /* Handle field modifiers */
486 if (*pname) {
487 if (*pname == '$') {
488 /* Some field types can be accessed as char arrays */
489 if (dbfType == DBF_STRING) {
490 paddr->no_elements = pflddes->size;
491 paddr->field_type = DBF_CHAR;
492 paddr->field_size = 1;
493 paddr->dbr_field_type = DBR_CHAR;
494 } else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) {
495 /* Clients see a char array, but keep original dbfType */
496 paddr->no_elements = PVNAME_STRINGSZ + 12;
497 paddr->field_size = 1;
498 paddr->dbr_field_type = DBR_CHAR;
499 } else {
500 status = S_dbLib_fieldNotFound;
501 goto finish;
502 }
503 pname++;
504 }
505
506 if (*pname == '[') {
507 status = parseArrayRange(chan, pname, &pname);
508 if (status) goto finish;
509 }
510
511 /* JSON may follow */
512 if (*pname == '{') {
513 status = chf_parse(chan, &pname);
514 if (status) goto finish;
515 }
516
517 /* Make sure there's nothing else */
518 if (*pname) {
519 status = S_dbLib_fieldNotFound;
520 goto finish;
521 }
522 }
523
524 if (paddr->special == SPC_DBADDR) {
525 struct rset *prset = dbGetRset(paddr);
526
527 /* Let record type modify the dbAddr */
528 if (prset && prset->cvt_dbaddr) {
529 status = prset->cvt_dbaddr(paddr);
530 if (status) goto finish;
531 }
532 }
533
534finish:
535 if (status && chan) {
536 dbChannelDelete(chan);
537 chan = NULL;
538 }
539 dbFinishEntry(&dbEntry);
540 return chan;
541}
542
543db_field_log* dbChannelRunPreChain(dbChannel *chan, db_field_log *pLogIn) {
544 chFilter *filter;
545 ELLNODE *node;
546 db_field_log *pLog = pLogIn;
547
548 for (node = ellFirst(&chan->pre_chain); node && pLog; node = ellNext(node)) {
549 filter = CONTAINER(node, chFilter, pre_node);
550 pLog = filter->pre_func(filter->pre_arg, chan, pLog);
551 }
552 return pLog;
553}
554
555db_field_log* dbChannelRunPostChain(dbChannel *chan, db_field_log *pLogIn) {
556 chFilter *filter;
557 ELLNODE *node;
558 db_field_log *pLog = pLogIn;
559
560 for (node = ellFirst(&chan->post_chain); node && pLog; node = ellNext(node)) {
561 filter = CONTAINER(node, chFilter, post_node);
562 pLog = filter->post_func(filter->post_arg, chan, pLog);
563 }
564 return pLog;
565}
566
567long dbChannelOpen(dbChannel *chan)
568{
569 chFilter *filter;
570 chPostEventFunc *func;
571 void *arg;
572 long status;
573 ELLNODE *node;
574 db_field_log probe;
575 db_field_log p;
576
577 for (node = ellFirst(&chan->filters); node; node = ellNext(node)) {
578 filter = CONTAINER(node, chFilter, list_node);
579 /* Call channel_open */
580 status = 0;
581 if (filter->plug->fif->channel_open)
582 status = filter->plug->fif->channel_open(filter);
583 if (status) return status;
584 }
585
586 /* Set up type probe */
587 probe.field_type = dbChannelFieldType(chan);
588 probe.no_elements = dbChannelElements(chan);
589 probe.field_size = dbChannelFieldSize(chan);
590 p = probe;
591
592 /*
593 * Build up the pre- and post-event-queue filter chains
594 * Separate loops because the probe must reach the filters in the right order.
595 */
596 for (node = ellFirst(&chan->filters); node; node = ellNext(node)) {
597 filter = CONTAINER(node, chFilter, list_node);
598 func = NULL;
599 arg = NULL;
600 if (filter->plug->fif->channel_register_pre) {
601 filter->plug->fif->channel_register_pre(filter, &func, &arg, &p);
602 if (func) {
603 ellAdd(&chan->pre_chain, &filter->pre_node);
604 filter->pre_func = func;
605 filter->pre_arg = arg;
606 probe = p;
607 }
608 }
609 }
610 for (node = ellFirst(&chan->filters); node; node = ellNext(node)) {
611 filter = CONTAINER(node, chFilter, list_node);
612 func = NULL;
613 arg = NULL;
614 if (filter->plug->fif->channel_register_post) {
615 filter->plug->fif->channel_register_post(filter, &func, &arg, &p);
616 if (func) {
617 ellAdd(&chan->post_chain, &filter->post_node);
618 filter->post_func = func;
619 filter->post_arg = arg;
620 probe = p;
621 }
622 }
623 }
624
625 /* Save probe results */
626 chan->final_no_elements = probe.no_elements;
627 chan->final_field_size = probe.field_size;
628 chan->final_type = probe.field_type;
629 chan->dbr_final_type = dbDBRnewToDBRold[mapDBFToDBR[probe.field_type]];
630
631 return 0;
632}
633
634/* FIXME: For performance we should make these one-liners into macros,
635 * or try to make them inline if all our compilers can do that.
636 */
637const char * dbChannelName(dbChannel *chan)
638{
639 return chan->name;
640}
641
642struct dbCommon * dbChannelRecord(dbChannel *chan)
643{
644 return chan->addr.precord;
645}
646
647struct dbFldDes * dbChannelFldDes(dbChannel *chan)
648{
649 return chan->addr.pfldDes;
650}
651
652long dbChannelElements(dbChannel *chan)
653{
654 return chan->addr.no_elements;
655}
656
657short dbChannelFieldType(dbChannel *chan)
658{
659 return chan->addr.field_type;
660}
661
662short dbChannelExportType(dbChannel *chan)
663{
664 return chan->addr.dbr_field_type;
665}
666
667short dbChannelFieldSize(dbChannel *chan)
668{
669 return chan->addr.field_size;
670}
671
672long dbChannelFinalElements(dbChannel *chan)
673{
674 return chan->final_no_elements;
675}
676
677short dbChannelFinalFieldType(dbChannel *chan)
678{
679 return chan->final_type;
680}
681
682short dbChannelFinalExportType(dbChannel *chan)
683{
684 return chan->dbr_final_type;
685}
686
687short dbChannelFinalFieldSize(dbChannel *chan)
688{
689 return chan->final_field_size;
690}
691
692short dbChannelSpecial(dbChannel *chan)
693{
694 return chan->addr.special;
695}
696
697void * dbChannelField(dbChannel *chan)
698{
699 /* Channel filters do not get to interpose here since there are many
700 * places where the field pointer is compared with the address of a
701 * specific record field, so they can't modify the pointer value.
702 */
703 return chan->addr.pfield;
704}
705
706/* Only use dbChannelGet() if the record is already locked. */
707long dbChannelGet(dbChannel *chan, short type, void *pbuffer,
708 long *options, long *nRequest, void *pfl)
709{
710 /* FIXME: Vector through chan->get() ? */
711 return dbGet(&chan->addr, type, pbuffer, options, nRequest, pfl);
712}
713
714long dbChannelGetField(dbChannel *chan, short dbrType, void *pbuffer,
715 long *options, long *nRequest, void *pfl)
716{
717 dbCommon *precord = chan->addr.precord;
718 long status = 0;
719
720 dbScanLock(precord);
721 status = dbChannelGet(chan, dbrType, pbuffer, options, nRequest, pfl);
722 dbScanUnlock(precord);
723 return status;
724}
725
726/* Only use dbChannelPut() if the record is already locked.
727 * This routine doesn't work on link fields, ignores DISP, and
728 * doesn't trigger record processing on PROC or pp(TRUE).
729 */
730long dbChannelPut(dbChannel *chan, short type, const void *pbuffer,
731 long nRequest)
732{
733 /* FIXME: Vector through chan->put() ? */
734 return dbPut(&chan->addr, type, pbuffer, nRequest);
735}
736
737long dbChannelPutField(dbChannel *chan, short type, const void *pbuffer,
738 long nRequest)
739{
740 /* FIXME: Vector through chan->putField() ? */
741 return dbPutField(&chan->addr, type, pbuffer, nRequest);
742}
743
744void dbChannelShow(dbChannel *chan, int level, const unsigned short indent)
745{
746 long elems = chan->addr.no_elements;
747 long felems = chan->final_no_elements;
748 int count = ellCount(&chan->filters);
749 int pre = ellCount(&chan->pre_chain);
750 int post = ellCount(&chan->post_chain);
751
752 printf("%*schannel name: %s\n", indent, "", chan->name);
753 /* FIXME: show field_type as text */
754 printf("%*s field_type=%d (%dB), %ld element%s, %d filter%s", indent, "",
755 chan->addr.field_type, chan->addr.field_size, elems, elems == 1 ? "" : "s",
756 count, count == 1 ? "" : "s");
757 if (count)
758 printf(" (%d pre eventq, %d post eventq)\n", pre, post);
759 else
760 printf("\n");
761 if (level > 0)
762 dbChannelFilterShow(chan, level - 1, indent + 2);
763 if (count) {
764 /* FIXME: show field_type as text */
765 printf("%*s final field_type=%d (%dB), %ld element%s\n", indent, "",
766 chan->final_type, chan->final_field_size, felems, felems == 1 ? "" : "s");
767 }
768}
769
770void dbChannelFilterShow(dbChannel *chan, int level, const unsigned short indent)
771{
772 chFilter *filter = (chFilter *) ellFirst(&chan->filters);
773 while (filter) {
774 filter->plug->fif->channel_report(filter, level, indent);
775 filter = (chFilter *) ellNext(&filter->list_node);
776 }
777}
778
779void dbChannelDelete(dbChannel *chan)
780{
781 chFilter *filter;
782
783 /* Close filters in reverse order */
784 while ((filter = (chFilter *) ellPop(&chan->filters))) {
785 filter->plug->fif->channel_close(filter);
786 free(filter);
787 }
788 free((char *) chan->name); /* FIXME: Use free-list */
789 free(chan); /* FIXME: Use free-list */
790}
791
792static void freeArray(db_field_log *pfl) {
793 if (pfl->field_type == DBF_STRING && pfl->no_elements == 1) {
794 freeListFree(dbchStringFreeList, pfl->u.r.field);
795 } else {
796 free(pfl->u.r.field);
797 }
798}
799
800void dbChannelMakeArrayCopy(void *pvt, db_field_log *pfl, dbChannel *chan)
801{
802 void *p;
803 struct dbCommon *prec = dbChannelRecord(chan);
804
805 if (!pfl->type == dbfl_type_rec) return;
806
807 pfl->type = dbfl_type_ref;
808 pfl->stat = prec->stat;
809 pfl->sevr = prec->sevr;
810 pfl->time = prec->time;
811 pfl->field_type = chan->addr.field_type;
812 pfl->no_elements = chan->addr.no_elements;
813 pfl->field_size = chan->addr.field_size;
814 pfl->u.r.dtor = freeArray;
815 pfl->u.r.pvt = pvt;
816 if (pfl->field_type == DBF_STRING && pfl->no_elements == 1) {
817 p = freeListCalloc(dbchStringFreeList);
818 } else {
819 p = calloc(pfl->no_elements, pfl->field_size);
820 }
821 if (p) dbGet(&chan->addr, mapDBFToDBR[pfl->field_type], p, NULL, &pfl->no_elements, NULL);
822 pfl->u.r.field = p;
823}
824
825/* FIXME: Do these belong in a different file? */
826
827void dbRegisterFilter(const char *name, const chFilterIf *fif, void *puser)
828{
829 GPHENTRY *pgph;
830 chFilterPlugin *pfilt;
831
832 if (!pdbbase) {
833 printf("dbRegisterFilter: pdbbase not set!\n");
834 return;
835 }
836
837 pgph = gphFind(pdbbase->pgpHash, name, &pdbbase->filterList);
838 if (pgph)
839 return;
840
841 pfilt = dbCalloc(1, sizeof(chFilterPlugin));
842 pfilt->name = epicsStrDup(name);
843 pfilt->fif = fif;
844 pfilt->puser = puser;
845
846 ellAdd(&pdbbase->filterList, &pfilt->node);
847 pgph = gphAdd(pdbbase->pgpHash, pfilt->name, &pdbbase->filterList);
848 if (!pgph) {
849 free((void *) pfilt->name);
850 free(pfilt);
851 printf("dbRegisterFilter: gphAdd failed\n");
852 return;
853 }
854 pgph->userPvt = pfilt;
855}
856
857const chFilterPlugin * dbFindFilter(const char *name, size_t len)
858{
859 GPHENTRY *pgph = gphFindParse(pdbbase->pgpHash, name, len,
860 &pdbbase->filterList);
861
862 if (!pgph)
863 return NULL;
864 return (chFilterPlugin *) pgph->userPvt;
865}
0866
=== added file 'src/ioc/db/dbChannel.h'
--- src/ioc/db/dbChannel.h 1970-01-01 00:00:00 +0000
+++ src/ioc/db/dbChannel.h 2012-06-21 20:42:45 +0000
@@ -0,0 +1,181 @@
1/*************************************************************************\
2* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* Copyright (c) 2010 Brookhaven National Laboratory.
5* Copyright (c) 2010 Helmholtz-Zentrum Berlin
6* fuer Materialien und Energie GmbH.
7* EPICS BASE is distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/
10
11/*
12 * Author: Andrew Johnson <anj@aps.anl.gov>
13 * Ralph Lange <Ralph.Lange@bessy.de>
14 */
15
16#ifndef INC_dbChannel_H
17#define INC_dbChannel_H
18
19#include "dbDefs.h"
20#include "dbAddr.h"
21#include "ellLib.h"
22#include "epicsTypes.h"
23#include "errMdef.h"
24#include "shareLib.h"
25#include "db_field_log.h"
26#include "dbEvent.h"
27
28#ifdef __cplusplus
29extern "C" {
30#endif
31
32/*
33 * event subscription
34 */
35typedef struct evSubscrip {
36 ELLNODE node;
37 struct dbChannel *chan;
38 EVENTFUNC *user_sub;
39 void *user_arg;
40 struct event_que *ev_que;
41 db_field_log **pLastLog;
42 unsigned long npend; /* n times this event is on the queue */
43 unsigned long nreplace; /* n times replacing event on the queue */
44 unsigned char select;
45 char useValque;
46 char callBackInProgress;
47 char enabled;
48} evSubscrip;
49
50typedef struct chFilter chFilter;
51
52/* A dbChannel points to a record field, and can have multiple filters */
53typedef struct dbChannel {
54 const char *name;
55 dbAddr addr; /* address structure for record/field */
56 long final_no_elements; /* final number of elements (arrays) */
57 short final_field_size; /* final size of element */
58 short final_type; /* final type of database field */
59 short dbr_final_type; /* final field type as seen by database request */
60 ELLLIST filters; /* list of filters as created from JSON */
61 ELLLIST pre_chain; /* list of filters to be called pre-event-queue */
62 ELLLIST post_chain; /* list of filters to be called post-event-queue */
63} dbChannel;
64
65/* Prototype for the post event function that is called in filter stacks */
66typedef db_field_log* (chPostEventFunc)(void *pvt, dbChannel *chan, db_field_log *pLog);
67
68/* Return values from chFilterIf->parse_* routines: */
69typedef enum {
70 parse_stop, parse_continue
71} parse_result;
72
73/* These routines must be implemented by each filter plug-in */
74typedef struct chFilterIf {
75 /* Parsing event handlers: */
76 parse_result (* parse_start)(chFilter *filter);
77 /* If parse_start() returns parse_continue for a filter, one of
78 * parse_abort() or parse_end() will later be called for that same
79 * filter.
80 */
81 void (* parse_abort)(chFilter *filter);
82 /* If parse_abort() is called it should release any memory allocated
83 * for this filter; no further parse_...() calls will be made;
84 */
85 parse_result (* parse_end)(chFilter *filter);
86 /* If parse_end() returns parse_stop it should have released any
87 * memory allocated for this filter; no further parse_...() calls will
88 * be made in this case.
89 */
90
91 parse_result (* parse_null)(chFilter *filter);
92 parse_result (* parse_boolean)(chFilter *filter, int boolVal);
93 parse_result (* parse_integer)(chFilter *filter, long integerVal);
94 parse_result (* parse_double)(chFilter *filter, double doubleVal);
95 parse_result (* parse_string)(chFilter *filter, const char *stringVal,
96 size_t stringLen); /* NB: stringVal is not zero-terminated: */
97
98 parse_result (* parse_start_map)(chFilter *filter);
99 parse_result (* parse_map_key)(chFilter *filter, const char *key,
100 size_t stringLen); /* NB: key is not zero-terminated: */
101 parse_result (* parse_end_map)(chFilter *filter);
102
103 parse_result (* parse_start_array)(chFilter *filter);
104 parse_result (* parse_end_array)(chFilter *filter);
105
106 /* Channel operations: */
107 long (* channel_open)(chFilter *filter);
108 void (* channel_register_pre) (chFilter *filter, chPostEventFunc **cb_out, void **arg_out, db_field_log *probe);
109 void (* channel_register_post)(chFilter *filter, chPostEventFunc **cb_out, void **arg_out, db_field_log *probe);
110 void (* channel_report)(chFilter *filter, int level, const unsigned short indent);
111 /* FIXME: More filter routines here ... */
112 void (* channel_close)(chFilter *filter);
113} chFilterIf;
114
115/* A chFilterPlugin holds data for a filter plugin */
116typedef struct chFilterPlugin {
117 ELLNODE node;
118 const char *name;
119 const chFilterIf *fif;
120 void *puser;
121} chFilterPlugin;
122
123/* A chFilter holds data for a single filter instance */
124struct chFilter {
125 ELLNODE list_node;
126 ELLNODE pre_node;
127 ELLNODE post_node;
128 dbChannel *chan;
129 const chFilterPlugin *plug;
130 chPostEventFunc *pre_func;
131 void *pre_arg;
132 chPostEventFunc *post_func;
133 void *post_arg;
134 void *puser;
135};
136
137struct dbCommon;
138struct dbFldDes;
139
140epicsShareFunc void dbChannelInit (void);
141epicsShareFunc long dbChannelTest(const char *name);
142epicsShareFunc dbChannel * dbChannelCreate(const char *name);
143epicsShareFunc long dbChannelOpen(dbChannel *chan);
144epicsShareFunc const char * dbChannelName(dbChannel *chan);
145epicsShareFunc struct dbCommon * dbChannelRecord(dbChannel *chan);
146epicsShareFunc struct dbFldDes * dbChannelFldDes(dbChannel *chan);
147epicsShareFunc long dbChannelElements(dbChannel *chan);
148epicsShareFunc short dbChannelFieldType(dbChannel *chan);
149epicsShareFunc short dbChannelExportType(dbChannel *chan);
150epicsShareFunc short dbChannelFieldSize(dbChannel *chan);
151epicsShareFunc long dbChannelFinalElements(dbChannel *chan);
152epicsShareFunc short dbChannelFinalFieldType(dbChannel *chan);
153epicsShareFunc short dbChannelFinalExportType(dbChannel *chan);
154epicsShareFunc short dbChannelFinalElementSize(dbChannel *chan);
155epicsShareFunc short dbChannelSpecial(dbChannel *chan);
156epicsShareFunc void * dbChannelField(dbChannel *chan);
157epicsShareFunc long dbChannelGet(dbChannel *chan, short type,
158 void *pbuffer, long *options, long *nRequest, void *pfl);
159epicsShareFunc long dbChannelGetField(dbChannel *chan, short type,
160 void *pbuffer, long *options, long *nRequest, void *pfl);
161epicsShareFunc long dbChannelPut(dbChannel *chan, short type,
162 const void *pbuffer, long nRequest);
163epicsShareFunc long dbChannelPutField(dbChannel *chan, short type,
164 const void *pbuffer, long nRequest);
165epicsShareFunc void dbChannelShow(dbChannel *chan, int level,
166 const unsigned short indent);
167epicsShareFunc void dbChannelFilterShow(dbChannel *chan, int level,
168 const unsigned short indent);
169epicsShareFunc void dbChannelDelete(dbChannel *chan);
170
171epicsShareFunc void dbRegisterFilter(const char *key, const chFilterIf *fif, void *puser);
172epicsShareFunc db_field_log* dbChannelRunPreChain(dbChannel *chan, db_field_log *pLogIn);
173epicsShareFunc db_field_log* dbChannelRunPostChain(dbChannel *chan, db_field_log *pLogIn);
174epicsShareFunc const chFilterPlugin * dbFindFilter(const char *key, size_t len);
175epicsShareFunc void dbChannelMakeArrayCopy(void *pvt, db_field_log *pfl, dbChannel *chan);
176
177#ifdef __cplusplus
178}
179#endif
180
181#endif /* INC_dbChannel_H */
0182
=== modified file 'src/ioc/db/dbChannelIO.cpp'
--- src/ioc/db/dbChannelIO.cpp 2010-10-05 19:27:37 +0000
+++ src/ioc/db/dbChannelIO.cpp 2012-06-21 20:42:45 +0000
@@ -4,20 +4,20 @@
4* Copyright (c) 2002 The Regents of the University of California, as4* Copyright (c) 2002 The Regents of the University of California, as
5* Operator of Los Alamos National Laboratory.5* Operator of Los Alamos National Laboratory.
6* EPICS BASE is distributed subject to a Software License Agreement found6* EPICS BASE is distributed subject to a Software License Agreement found
7* in file LICENSE that is included with this distribution. 7* in file LICENSE that is included with this distribution.
8\*************************************************************************/8\*************************************************************************/
99
10/* 10/*
11 * $Revision-Id$11 * $Revision-Id$
12 *12 *
13 * 13 *
14 * L O S A L A M O S14 * L O S A L A M O S
15 * Los Alamos National Laboratory15 * Los Alamos National Laboratory
16 * Los Alamos, New Mexico 8754516 * Los Alamos, New Mexico 87545
17 * 17 *
18 * Copyright, 1986, The Regents of the University of California.18 * Copyright, 1986, The Regents of the University of California.
19 * 19 *
20 * 20 *
21 * Author Jeffrey O. Hill21 * Author Jeffrey O. Hill
22 * johill@lanl.gov22 * johill@lanl.gov
23 * 505 665 183123 * 505 665 1831
@@ -40,15 +40,12 @@
40#include "dbChannelIO.h"40#include "dbChannelIO.h"
41#include "dbPutNotifyBlocker.h"41#include "dbPutNotifyBlocker.h"
4242
43dbChannelIO::dbChannelIO ( 43dbChannelIO::dbChannelIO (
44 epicsMutex & mutexIn, cacChannelNotify & notify, 44 epicsMutex & mutexIn, cacChannelNotify & notify,
45 const dbAddr & addrIn, dbContext & serviceIO ) :45 dbChannel * dbchIn, dbContext & serviceIO ) :
46 cacChannel ( notify ), mutex ( mutexIn ), serviceIO ( serviceIO ), 46 cacChannel ( notify ), mutex ( mutexIn ), serviceIO ( serviceIO ),
47 addr ( addrIn )47 dbch ( dbchIn )
48{48{
49 unsigned bufLen = dbNameSizeOfPV ( & this->addr ) + 1;
50 this->pNameStr.reset ( new char [ bufLen ] );
51 dbNameOfPV ( & this->addr, this->pNameStr.get (), bufLen );
52}49}
5350
54void dbChannelIO::initiateConnect ( epicsGuard < epicsMutex > & guard )51void dbChannelIO::initiateConnect ( epicsGuard < epicsMutex > & guard )
@@ -57,7 +54,7 @@
57 this->notify().connectNotify ( guard );54 this->notify().connectNotify ( guard );
58}55}
5956
60dbChannelIO::~dbChannelIO () 57dbChannelIO::~dbChannelIO ()
61{58{
62}59}
6360
@@ -65,48 +62,49 @@
65{62{
66 guard.assertIdenticalMutex ( this->mutex );63 guard.assertIdenticalMutex ( this->mutex );
67 this->serviceIO.destroyAllIO ( guard, *this );64 this->serviceIO.destroyAllIO ( guard, *this );
65 dbChannelDelete ( this->dbch );
68 this->~dbChannelIO ();66 this->~dbChannelIO ();
69}67}
7068
71void dbChannelIO::destroy ( 69void dbChannelIO::destroy (
72 epicsGuard < epicsMutex > & guard )70 epicsGuard < epicsMutex > & guard )
73{71{
74 guard.assertIdenticalMutex ( this->mutex );72 guard.assertIdenticalMutex ( this->mutex );
75 this->serviceIO.destroyChannel ( guard, *this );73 this->serviceIO.destroyChannel ( guard, *this );
76 // dont access this pointer after above call because74 // don't access this pointer after above call because
77 // object nolonger exists75 // object no longer exists
78}76}
7977
80cacChannel::ioStatus dbChannelIO::read ( 78cacChannel::ioStatus dbChannelIO::read (
81 epicsGuard < epicsMutex > & guard, unsigned type, 79 epicsGuard < epicsMutex > & guard, unsigned type,
82 unsigned long count, cacReadNotify & notify, ioid * ) 80 unsigned long count, cacReadNotify & notify, ioid * )
83{81{
84 guard.assertIdenticalMutex ( this->mutex );82 guard.assertIdenticalMutex ( this->mutex );
85 this->serviceIO.callReadNotify ( guard, this->addr, 83 this->serviceIO.callReadNotify ( guard, this->dbch,
86 type, count, notify );84 type, count, notify );
87 return iosSynch;85 return iosSynch;
88}86}
8987
90void dbChannelIO::write ( 88void dbChannelIO::write (
91 epicsGuard < epicsMutex > & guard, unsigned type, 89 epicsGuard < epicsMutex > & guard, unsigned type,
92 unsigned long count, const void *pValue )90 unsigned long count, const void *pValue )
93{91{
94 epicsGuardRelease < epicsMutex > unguard ( guard );92 epicsGuardRelease < epicsMutex > unguard ( guard );
95 if ( count > LONG_MAX ) {93 if ( count > LONG_MAX ) {
96 throw outOfBounds();94 throw outOfBounds();
97 }95 }
98 int status = db_put_field ( &this->addr, type, pValue, 96 int status = dbChannel_put ( this->dbch, type, pValue,
99 static_cast <long> (count) );97 static_cast <long> (count) );
100 if ( status ) {98 if ( status ) {
101 throw std::logic_error ( 99 throw std::logic_error (
102 "db_put_field() completed unsuccessfully" );100 "db_put_field() completed unsuccessfully" );
103 }101 }
104}102}
105103
106cacChannel::ioStatus dbChannelIO::write ( 104cacChannel::ioStatus dbChannelIO::write (
107 epicsGuard < epicsMutex > & guard, unsigned type, 105 epicsGuard < epicsMutex > & guard, unsigned type,
108 unsigned long count, const void * pValue, 106 unsigned long count, const void * pValue,
109 cacWriteNotify & notify, ioid * pId ) 107 cacWriteNotify & notify, ioid * pId )
110{108{
111 guard.assertIdenticalMutex ( this->mutex );109 guard.assertIdenticalMutex ( this->mutex );
112110
@@ -114,24 +112,24 @@
114 throw outOfBounds();112 throw outOfBounds();
115 }113 }
116114
117 this->serviceIO.initiatePutNotify ( 115 this->serviceIO.initiatePutNotify (
118 guard, *this, this->addr, 116 guard, *this, this->dbch,
119 type, count, pValue, notify, pId );117 type, count, pValue, notify, pId );
120118
121 return iosAsynch;119 return iosAsynch;
122}120}
123121
124void dbChannelIO::subscribe ( 122void dbChannelIO::subscribe (
125 epicsGuard < epicsMutex > & guard, unsigned type, unsigned long count, 123 epicsGuard < epicsMutex > & guard, unsigned type, unsigned long count,
126 unsigned mask, cacStateNotify & notify, ioid * pId ) 124 unsigned mask, cacStateNotify & notify, ioid * pId )
127{ 125{
128 guard.assertIdenticalMutex ( this->mutex );126 guard.assertIdenticalMutex ( this->mutex );
129 this->serviceIO.subscribe ( 127 this->serviceIO.subscribe (
130 guard, this->addr, *this,128 guard, this->dbch, *this,
131 type, count, mask, notify, pId );129 type, count, mask, notify, pId );
132}130}
133131
134void dbChannelIO::ioCancel ( 132void dbChannelIO::ioCancel (
135 epicsGuard < epicsMutex > & mutualExclusionGuard,133 epicsGuard < epicsMutex > & mutualExclusionGuard,
136 const ioid & id )134 const ioid & id )
137{135{
@@ -139,7 +137,7 @@
139 this->serviceIO.ioCancel ( mutualExclusionGuard, *this, id );137 this->serviceIO.ioCancel ( mutualExclusionGuard, *this, id );
140}138}
141139
142void dbChannelIO::ioShow ( 140void dbChannelIO::ioShow (
143 epicsGuard < epicsMutex > & guard,141 epicsGuard < epicsMutex > & guard,
144 const ioid & id, unsigned level ) const142 const ioid & id, unsigned level ) const
145{143{
@@ -147,31 +145,35 @@
147 this->serviceIO.ioShow ( guard, id, level );145 this->serviceIO.ioShow ( guard, id, level );
148}146}
149147
150void dbChannelIO::show ( 148void dbChannelIO::show (
151 epicsGuard < epicsMutex > & guard, unsigned level ) const149 epicsGuard < epicsMutex > & guard, unsigned level ) const
152{150{
153 guard.assertIdenticalMutex ( this->mutex );151 guard.assertIdenticalMutex ( this->mutex );
154152
155 printf ("channel at %p attached to local database record %s\n", 153 printf ("channel at %p attached to local database record %s\n",
156 static_cast <const void *> ( this ), this->addr.precord->name );154 static_cast <const void *> ( this ),
155 dbChannelRecord ( this->dbch ) -> name );
157156
158 if ( level > 0u ) {157 if ( level > 0u ) {
159 printf ( "\ttype %s, element count %li, field at %p\n",158 printf ( " type %s, element count %li, field at %p\n",
160 dbf_type_to_text ( this->addr.dbr_field_type ), this->addr.no_elements,159 dbf_type_to_text ( dbChannelExportType ( this->dbch ) ),
161 this->addr.pfield );160 dbChannelElements ( this->dbch ),
162 }161 dbChannelField ( this->dbch ) );
163 if ( level > 1u ) {162 if ( level > 1u ) {
164 this->serviceIO.show ( level - 2u );163 dbChannelFilterShow ( this->dbch, level - 2u, 8 );
165 this->serviceIO.showAllIO ( *this, level - 2u );164 this->serviceIO.show ( level - 2u );
165 this->serviceIO.showAllIO ( *this, level - 2u );
166 }
166 }167 }
167}168}
168169
169unsigned long dbChannelIO::nativeElementCount (170unsigned long dbChannelIO::nativeElementCount (
170 epicsGuard < epicsMutex > & guard ) const 171 epicsGuard < epicsMutex > & guard ) const
171{172{
172 guard.assertIdenticalMutex ( this->mutex );173 guard.assertIdenticalMutex ( this->mutex );
173 if ( this->addr.no_elements >= 0u ) {174 long elements = dbChannelElements ( this->dbch );
174 return static_cast < unsigned long > ( this->addr.no_elements );175 if ( elements >= 0u ) {
176 return static_cast < unsigned long > ( elements );
175 }177 }
176 return 0u;178 return 0u;
177}179}
@@ -181,24 +183,30 @@
181 epicsGuard < epicsMutex > & guard ) const throw ()183 epicsGuard < epicsMutex > & guard ) const throw ()
182{184{
183 guard.assertIdenticalMutex ( this->mutex );185 guard.assertIdenticalMutex ( this->mutex );
184 return this->pNameStr.get ();186 return dbChannelName ( this->dbch );
185}187}
186188
187unsigned dbChannelIO::getName (189unsigned dbChannelIO::getName (
188 epicsGuard < epicsMutex > &,190 epicsGuard < epicsMutex > &,
189 char * pBuf, unsigned bufLen ) const throw ()191 char * pBuf, unsigned bufLen ) const throw ()
190{192{
191 return dbNameOfPV ( & this->addr, pBuf, bufLen );193 const char *name = dbChannelName ( this->dbch );
194 size_t len = strlen ( name );
195 strncpy ( pBuf, name, bufLen );
196 if (len < bufLen)
197 return len;
198 pBuf[--bufLen] = '\0';
199 return bufLen;
192}200}
193201
194short dbChannelIO::nativeType (202short dbChannelIO::nativeType (
195 epicsGuard < epicsMutex > & guard ) const 203 epicsGuard < epicsMutex > & guard ) const
196{204{
197 guard.assertIdenticalMutex ( this->mutex );205 guard.assertIdenticalMutex ( this->mutex );
198 return this->addr.dbr_field_type;206 return dbChannelExportType( this->dbch );
199}207}
200208
201void * dbChannelIO::operator new ( size_t size, 209void * dbChannelIO::operator new ( size_t size,
202 tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & freeList )210 tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & freeList )
203{211{
204 return freeList.allocate ( size );212 return freeList.allocate ( size );
@@ -212,7 +220,7 @@
212}220}
213221
214#ifdef CXX_PLACEMENT_DELETE222#ifdef CXX_PLACEMENT_DELETE
215void dbChannelIO::operator delete ( void *pCadaver, 223void dbChannelIO::operator delete ( void *pCadaver,
216 tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & freeList )224 tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & freeList )
217{225{
218 freeList.release ( pCadaver );226 freeList.release ( pCadaver );
219227
=== modified file 'src/ioc/db/dbChannelIO.h'
--- src/ioc/db/dbChannelIO.h 2010-10-05 19:27:37 +0000
+++ src/ioc/db/dbChannelIO.h 2012-06-21 20:42:45 +0000
@@ -5,7 +5,7 @@
5* Operator of Los Alamos National Laboratory.5* Operator of Los Alamos National Laboratory.
6* EPICS BASE Versions 3.13.76* EPICS BASE Versions 3.13.7
7* and higher are distributed subject to a Software License Agreement found7* and higher are distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution. 8* in file LICENSE that is included with this distribution.
9\*************************************************************************/9\*************************************************************************/
1010
11/*11/*
@@ -44,65 +44,64 @@
4444
45class dbChannelIO : public cacChannel, public dbContextPrivateListOfIO {45class dbChannelIO : public cacChannel, public dbContextPrivateListOfIO {
46public:46public:
47 dbChannelIO ( 47 dbChannelIO (
48 epicsMutex &, cacChannelNotify &, 48 epicsMutex &, cacChannelNotify &,
49 const dbAddr &, dbContext & );49 dbChannel *, dbContext & );
50 void destructor ( 50 void destructor (
51 epicsGuard < epicsMutex > & );51 epicsGuard < epicsMutex > & );
52 void destroy (52 void destroy (
53 epicsGuard < epicsMutex > & mutualExclusionGuard );53 epicsGuard < epicsMutex > & mutualExclusionGuard );
54 void callReadNotify ( 54 void callReadNotify (
55 epicsGuard < epicsMutex > &, 55 epicsGuard < epicsMutex > &,
56 unsigned type, unsigned long count, 56 unsigned type, unsigned long count,
57 cacReadNotify & notify );57 cacReadNotify & notify );
58 void callStateNotify ( 58 void callStateNotify (
59 unsigned type, unsigned long count, 59 unsigned type, unsigned long count,
60 const struct db_field_log * pfl, cacStateNotify & notify );60 const struct db_field_log * pfl, cacStateNotify & notify );
61 void show ( 61 void show (
62 epicsGuard < epicsMutex > &, unsigned level ) const;62 epicsGuard < epicsMutex > &, unsigned level ) const;
63 unsigned getName (63 unsigned getName (
64 epicsGuard < epicsMutex > &,64 epicsGuard < epicsMutex > &,
65 char * pBuf, unsigned bufLen ) const throw ();65 char * pBuf, unsigned bufLen ) const throw ();
66 const char * pName (66 const char * pName (
67 epicsGuard < epicsMutex > & ) const throw ();67 epicsGuard < epicsMutex > & ) const throw ();
68 void * operator new ( size_t size, 68 void * operator new ( size_t size,
69 tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & );69 tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & );
70 epicsPlacementDeleteOperator (( void *, 70 epicsPlacementDeleteOperator (( void *,
71 tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & ))71 tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & ))
72protected:72protected:
73 ~dbChannelIO ();73 ~dbChannelIO ();
74private:74private:
75 epicsMutex & mutex;75 epicsMutex & mutex;
76 dbContext & serviceIO;76 dbContext & serviceIO;
77 dbAddr addr;77 dbChannel * dbch;
78 epics_auto_ptr < char, eapt_array > pNameStr;
7978
80 void initiateConnect (79 void initiateConnect (
81 epicsGuard < epicsMutex > & );80 epicsGuard < epicsMutex > & );
82 unsigned requestMessageBytesPending ( 81 unsigned requestMessageBytesPending (
83 epicsGuard < epicsMutex > & );82 epicsGuard < epicsMutex > & );
84 void flush ( 83 void flush (
85 epicsGuard < epicsMutex > & );84 epicsGuard < epicsMutex > & );
86 ioStatus read ( 85 ioStatus read (
87 epicsGuard < epicsMutex > &,86 epicsGuard < epicsMutex > &,
88 unsigned type, unsigned long count, 87 unsigned type, unsigned long count,
89 cacReadNotify &, ioid * );88 cacReadNotify &, ioid * );
90 void write ( 89 void write (
91 epicsGuard < epicsMutex > &,90 epicsGuard < epicsMutex > &,
92 unsigned type, unsigned long count, 91 unsigned type, unsigned long count,
93 const void * pvalue );92 const void * pvalue );
94 ioStatus write ( 93 ioStatus write (
95 epicsGuard < epicsMutex > &,94 epicsGuard < epicsMutex > &,
96 unsigned type, unsigned long count, 95 unsigned type, unsigned long count,
97 const void * pvalue, cacWriteNotify &, ioid * );96 const void * pvalue, cacWriteNotify &, ioid * );
98 void subscribe ( 97 void subscribe (
99 epicsGuard < epicsMutex > &,98 epicsGuard < epicsMutex > &,
100 unsigned type, unsigned long count, 99 unsigned type, unsigned long count,
101 unsigned mask, cacStateNotify &notify, ioid * );100 unsigned mask, cacStateNotify &notify, ioid * );
102 void ioCancel ( 101 void ioCancel (
103 epicsGuard < epicsMutex > & mutualExclusionGuard,102 epicsGuard < epicsMutex > & mutualExclusionGuard,
104 const ioid & );103 const ioid & );
105 void ioShow ( 104 void ioShow (
106 epicsGuard < epicsMutex > &,105 epicsGuard < epicsMutex > &,
107 const ioid &, unsigned level ) const;106 const ioid &, unsigned level ) const;
108 short nativeType (107 short nativeType (
@@ -115,18 +114,18 @@
115 void operator delete ( void * );114 void operator delete ( void * );
116};115};
117116
118inline void dbChannelIO::callReadNotify ( 117inline void dbChannelIO::callReadNotify (
119 epicsGuard < epicsMutex > & guard, unsigned type, unsigned long count, 118 epicsGuard < epicsMutex > & guard, unsigned type, unsigned long count,
120 cacReadNotify & notify )119 cacReadNotify & notify )
121{120{
122 guard.assertIdenticalMutex ( this->mutex );121 guard.assertIdenticalMutex ( this->mutex );
123 this->serviceIO.callReadNotify ( guard, this->addr, type, count, notify );122 this->serviceIO.callReadNotify ( guard, this->dbch, type, count, notify );
124}123}
125124
126inline void dbChannelIO::callStateNotify ( unsigned type, unsigned long count, 125inline void dbChannelIO::callStateNotify ( unsigned type, unsigned long count,
127 const struct db_field_log *pfl, cacStateNotify &notify )126 const struct db_field_log *pfl, cacStateNotify &notify )
128{127{
129 this->serviceIO.callStateNotify ( this->addr, type, count, pfl, notify );128 this->serviceIO.callStateNotify ( this->dbch, type, count, pfl, notify );
130}129}
131130
132131
133132
=== modified file 'src/ioc/db/dbContext.cpp'
--- src/ioc/db/dbContext.cpp 2010-10-05 19:27:37 +0000
+++ src/ioc/db/dbContext.cpp 2012-06-21 20:42:45 +0000
@@ -4,19 +4,19 @@
4* Copyright (c) 2002 The Regents of the University of California, as4* Copyright (c) 2002 The Regents of the University of California, as
5* Operator of Los Alamos National Laboratory.5* Operator of Los Alamos National Laboratory.
6* EPICS BASE is distributed subject to a Software License Agreement found6* EPICS BASE is distributed subject to a Software License Agreement found
7* in file LICENSE that is included with this distribution. 7* in file LICENSE that is included with this distribution.
8\*************************************************************************/8\*************************************************************************/
9/* 9/*
10 * $Revision-Id$10 * $Revision-Id$
11 *11 *
12 * 12 *
13 * L O S A L A M O S13 * L O S A L A M O S
14 * Los Alamos National Laboratory14 * Los Alamos National Laboratory
15 * Los Alamos, New Mexico 8754515 * Los Alamos, New Mexico 87545
16 * 16 *
17 * Copyright, 1986, The Regents of the University of California.17 * Copyright, 1986, The Regents of the University of California.
18 * 18 *
19 * 19 *
20 * Author Jeffrey O. Hill20 * Author Jeffrey O. Hill
21 * johill@lanl.gov21 * johill@lanl.gov
22 * 505 665 183122 * 505 665 1831
@@ -33,6 +33,7 @@
33#include "epicsEvent.h"33#include "epicsEvent.h"
34#include "epicsThread.h"34#include "epicsThread.h"
35#include "errlog.h"35#include "errlog.h"
36#include "dbChannel.h"
3637
37#define epicsExportSharedSymbols38#define epicsExportSharedSymbols
38#include "db_access_routines.h"39#include "db_access_routines.h"
@@ -43,20 +44,20 @@
43class dbService : public cacService {44class dbService : public cacService {
44public:45public:
45 ~dbService () {}46 ~dbService () {}
46 cacContext & contextCreate ( 47 cacContext & contextCreate (
47 epicsMutex & mutualExclusion, 48 epicsMutex & mutualExclusion,
48 epicsMutex & callbackControl, 49 epicsMutex & callbackControl,
49 cacContextNotify & );50 cacContextNotify & );
50};51};
5152
52static dbService dbs;53static dbService dbs;
5354
54cacContext & dbService::contextCreate ( 55cacContext & dbService::contextCreate (
55 epicsMutex & mutualExclusion, 56 epicsMutex & mutualExclusion,
56 epicsMutex & callbackControl, 57 epicsMutex & callbackControl,
57 cacContextNotify & notify )58 cacContextNotify & notify )
58{59{
59 return * new dbContext ( callbackControl, 60 return * new dbContext ( callbackControl,
60 mutualExclusion, notify );61 mutualExclusion, notify );
61}62}
6263
@@ -67,9 +68,9 @@
6768
68dbBaseIO::dbBaseIO () {}69dbBaseIO::dbBaseIO () {}
6970
70dbContext::dbContext ( epicsMutex & cbMutexIn, 71dbContext::dbContext ( epicsMutex & cbMutexIn,
71 epicsMutex & mutexIn, cacContextNotify & notifyIn ) :72 epicsMutex & mutexIn, cacContextNotify & notifyIn ) :
72 readNotifyCache ( mutexIn ), ctx ( 0 ), 73 readNotifyCache ( mutexIn ), ctx ( 0 ),
73 stateNotifyCacheSize ( 0 ), mutex ( mutexIn ), cbMutex ( cbMutexIn ),74 stateNotifyCacheSize ( 0 ), mutex ( mutexIn ), cbMutex ( cbMutexIn ),
74 notify ( notifyIn ), pNetContext ( 0 ), pStateNotifyCache ( 0 )75 notify ( notifyIn ), pNetContext ( 0 ), pStateNotifyCache ( 0 )
75{76{
@@ -84,41 +85,41 @@
84}85}
8586
86cacChannel & dbContext::createChannel ( // X aCC 36187cacChannel & dbContext::createChannel ( // X aCC 361
87 epicsGuard < epicsMutex > & guard, const char * pName, 88 epicsGuard < epicsMutex > & guard, const char * pName,
88 cacChannelNotify & notifyIn, cacChannel::priLev priority )89 cacChannelNotify & notifyIn, cacChannel::priLev priority )
89{90{
90 guard.assertIdenticalMutex ( this->mutex );91 guard.assertIdenticalMutex ( this->mutex );
9192
92 struct dbAddr addr;93 dbChannel *dbch = dbChannel_create ( pName );
93 int status;94 if ( ! dbch ) {
94 {
95 // dont know if the database might call a put callback
96 // while holding its lock ...
97 epicsGuardRelease < epicsMutex > unguard ( guard );
98 status = db_name_to_addr ( pName, & addr );
99 }
100 if ( status ) {
101 if ( ! this->pNetContext.get() ) {95 if ( ! this->pNetContext.get() ) {
102 this->pNetContext.reset (96 this->pNetContext.reset (
103 & this->notify.createNetworkContext ( 97 & this->notify.createNetworkContext (
104 this->mutex, this->cbMutex ) );98 this->mutex, this->cbMutex ) );
105 }99 }
106 return this->pNetContext->createChannel (100 return this->pNetContext->createChannel (
107 guard, pName, notifyIn, priority );101 guard, pName, notifyIn, priority );
108 }102 }
109 else if ( ca_preemtive_callback_is_enabled () ) {103
110 return * new ( this->dbChannelIOFreeList )104 if ( ! ca_preemtive_callback_is_enabled () ) {
111 dbChannelIO ( this->mutex, notifyIn, addr, *this ); 105 dbChannelDelete ( dbch );
112 }106 errlogPrintf (
113 else {
114 errlogPrintf (
115 "dbContext: preemptive callback required for direct in\n"107 "dbContext: preemptive callback required for direct in\n"
116 "memory interfacing of CA channels to the DB.\n" );108 "memory interfacing of CA channels to the DB.\n" );
117 throw cacChannel::unsupportedByService ();109 throw cacChannel::unsupportedByService ();
118 }110 }
111
112 try {
113 return * new ( this->dbChannelIOFreeList )
114 dbChannelIO ( this->mutex, notifyIn, dbch, *this );
115 }
116 catch (...) {
117 dbChannelDelete ( dbch );
118 throw;
119 }
119}120}
120121
121void dbContext::destroyChannel ( 122void dbContext::destroyChannel (
122 epicsGuard < epicsMutex > & guard, dbChannelIO & chan )123 epicsGuard < epicsMutex > & guard, dbChannelIO & chan )
123{124{
124 guard.assertIdenticalMutex ( this->mutex );125 guard.assertIdenticalMutex ( this->mutex );
@@ -134,30 +135,30 @@
134 this->dbChannelIOFreeList.release ( & chan );135 this->dbChannelIOFreeList.release ( & chan );
135}136}
136137
137void dbContext::callStateNotify ( struct dbAddr & addr, 138void dbContext::callStateNotify ( struct dbChannel * dbch,
138 unsigned type, unsigned long count, 139 unsigned type, unsigned long count,
139 const struct db_field_log * pfl, 140 const struct db_field_log * pfl,
140 cacStateNotify & notifyIn )141 cacStateNotify & notifyIn )
141{142{
142 unsigned long size = dbr_size_n ( type, count );143 unsigned long size = dbr_size_n ( type, count );
143144
144 if ( type > INT_MAX ) {145 if ( type > INT_MAX ) {
145 epicsGuard < epicsMutex > guard ( this->mutex );146 epicsGuard < epicsMutex > guard ( this->mutex );
146 notifyIn.exception ( guard, ECA_BADTYPE, 147 notifyIn.exception ( guard, ECA_BADTYPE,
147 "type code out of range (high side)", 148 "type code out of range (high side)",
148 type, count );149 type, count );
149 return;150 return;
150 }151 }
151152
152 if ( count > INT_MAX ) {153 if ( count > INT_MAX ) {
153 epicsGuard < epicsMutex > guard ( this->mutex );154 epicsGuard < epicsMutex > guard ( this->mutex );
154 notifyIn.exception ( guard, ECA_BADCOUNT, 155 notifyIn.exception ( guard, ECA_BADCOUNT,
155 "element count out of range (high side)",156 "element count out of range (high side)",
156 type, count);157 type, count);
157 return;158 return;
158 }159 }
159160
160 // no need to lock this because state notify is 161 // no need to lock this because state notify is
161 // called from only one event queue consumer thread162 // called from only one event queue consumer thread
162 if ( this->stateNotifyCacheSize < size) {163 if ( this->stateNotifyCacheSize < size) {
163 char * pTmp = new char [size];164 char * pTmp = new char [size];
@@ -166,14 +167,14 @@
166 this->stateNotifyCacheSize = size;167 this->stateNotifyCacheSize = size;
167 }168 }
168 void *pvfl = (void *) pfl;169 void *pvfl = (void *) pfl;
169 int status = db_get_field ( &addr, static_cast <int> ( type ), 170 int status = dbChannel_get ( dbch, static_cast <int> ( type ),
170 this->pStateNotifyCache, static_cast <int> ( count ), pvfl );171 this->pStateNotifyCache, static_cast <int> ( count ), pvfl );
171 if ( status ) {172 if ( status ) {
172 epicsGuard < epicsMutex > guard ( this->mutex );173 epicsGuard < epicsMutex > guard ( this->mutex );
173 notifyIn.exception ( guard, ECA_GETFAIL, 174 notifyIn.exception ( guard, ECA_GETFAIL,
174 "db_get_field() completed unsuccessfuly", type, count );175 "dbChannel_get() completed unsuccessfully", type, count );
175 }176 }
176 else { 177 else {
177 epicsGuard < epicsMutex > guard ( this->mutex );178 epicsGuard < epicsMutex > guard ( this->mutex );
178 notifyIn.current ( guard, type, count, this->pStateNotifyCache );179 notifyIn.current ( guard, type, count, this->pStateNotifyCache );
179 }180 }
@@ -185,10 +186,10 @@
185 assert ( status == ECA_NORMAL );186 assert ( status == ECA_NORMAL );
186}187}
187188
188void dbContext::subscribe ( 189void dbContext::subscribe (
189 epicsGuard < epicsMutex > & guard,190 epicsGuard < epicsMutex > & guard,
190 struct dbAddr & addr, dbChannelIO & chan,191 struct dbChannel * dbch, dbChannelIO & chan,
191 unsigned type, unsigned long count, unsigned mask, 192 unsigned type, unsigned long count, unsigned mask,
192 cacStateNotify & notifyIn, cacChannel::ioid * pId )193 cacStateNotify & notifyIn, cacChannel::ioid * pId )
193{194{
194 guard.assertIdenticalMutex ( this->mutex );195 guard.assertIdenticalMutex ( this->mutex );
@@ -214,12 +215,12 @@
214215
215 unsigned selfPriority = epicsThreadGetPrioritySelf ();216 unsigned selfPriority = epicsThreadGetPrioritySelf ();
216 unsigned above;217 unsigned above;
217 epicsThreadBooleanStatus tbs = 218 epicsThreadBooleanStatus tbs =
218 epicsThreadLowestPriorityLevelAbove ( selfPriority, &above );219 epicsThreadLowestPriorityLevelAbove ( selfPriority, &above );
219 if ( tbs != epicsThreadBooleanStatusSuccess ) {220 if ( tbs != epicsThreadBooleanStatusSuccess ) {
220 above = selfPriority;221 above = selfPriority;
221 }222 }
222 int status = db_start_events ( tmpctx, "CAC-event", 223 int status = db_start_events ( tmpctx, "CAC-event",
223 cacAttachClientCtx, ca_current_context (), above );224 cacAttachClientCtx, ca_current_context (), above );
224 if ( status ) {225 if ( status ) {
225 db_close_events ( tmpctx );226 db_close_events ( tmpctx );
@@ -227,7 +228,7 @@
227 }228 }
228 }229 }
229 if ( this->ctx ) {230 if ( this->ctx ) {
230 // another thread tried to simultaneously setup 231 // another thread tried to simultaneously setup
231 // the event system232 // the event system
232 db_close_events ( tmpctx );233 db_close_events ( tmpctx );
233 }234 }
@@ -237,9 +238,9 @@
237 }238 }
238239
239 dbSubscriptionIO & subscr =240 dbSubscriptionIO & subscr =
240 * new ( this->dbSubscriptionIOFreeList ) 241 * new ( this->dbSubscriptionIOFreeList )
241 dbSubscriptionIO ( guard, this->mutex, *this, chan, 242 dbSubscriptionIO ( guard, this->mutex, *this, chan,
242 addr, notifyIn, type, count, mask, this->ctx );243 dbch, notifyIn, type, count, mask, this->ctx );
243 chan.dbContextPrivateListOfIO::eventq.add ( subscr );244 chan.dbContextPrivateListOfIO::eventq.add ( subscr );
244 this->ioTable.idAssignAdd ( subscr );245 this->ioTable.idAssignAdd ( subscr );
245246
@@ -248,27 +249,27 @@
248 }249 }
249}250}
250251
251void dbContext::initiatePutNotify ( 252void dbContext::initiatePutNotify (
252 epicsGuard < epicsMutex > & guard,253 epicsGuard < epicsMutex > & guard,
253 dbChannelIO & chan, struct dbAddr & addr, 254 dbChannelIO & chan, struct dbChannel * dbch,
254 unsigned type, unsigned long count, const void * pValue, 255 unsigned type, unsigned long count, const void * pValue,
255 cacWriteNotify & notifyIn, cacChannel::ioid * pId )256 cacWriteNotify & notifyIn, cacChannel::ioid * pId )
256{257{
257 guard.assertIdenticalMutex ( this->mutex );258 guard.assertIdenticalMutex ( this->mutex );
258 if ( ! chan.dbContextPrivateListOfIO::pBlocker ) {259 if ( ! chan.dbContextPrivateListOfIO::pBlocker ) {
259 chan.dbContextPrivateListOfIO::pBlocker = 260 chan.dbContextPrivateListOfIO::pBlocker =
260 new ( this->dbPutNotifyBlockerFreeList ) 261 new ( this->dbPutNotifyBlockerFreeList )
261 dbPutNotifyBlocker ( this->mutex );262 dbPutNotifyBlocker ( this->mutex );
262 this->ioTable.idAssignAdd ( *chan.dbContextPrivateListOfIO::pBlocker );263 this->ioTable.idAssignAdd ( *chan.dbContextPrivateListOfIO::pBlocker );
263 }264 }
264 chan.dbContextPrivateListOfIO::pBlocker->initiatePutNotify ( 265 chan.dbContextPrivateListOfIO::pBlocker->initiatePutNotify (
265 guard, notifyIn, addr, type, count, pValue );266 guard, notifyIn, dbch, type, count, pValue );
266 if ( pId ) {267 if ( pId ) {
267 *pId = chan.dbContextPrivateListOfIO::pBlocker->getId ();268 *pId = chan.dbContextPrivateListOfIO::pBlocker->getId ();
268 }269 }
269}270}
270271
271void dbContext::destroyAllIO ( 272void dbContext::destroyAllIO (
272 epicsGuard < epicsMutex > & guard, dbChannelIO & chan )273 epicsGuard < epicsMutex > & guard, dbChannelIO & chan )
273{274{
274 guard.assertIdenticalMutex ( this->mutex );275 guard.assertIdenticalMutex ( this->mutex );
@@ -284,7 +285,7 @@
284 }285 }
285286
286 while ( ( pIO = tmp.get() ) ) {287 while ( ( pIO = tmp.get() ) ) {
287 // This prevents a db event callback from coming 288 // This prevents a db event callback from coming
288 // through after the notify IO is deleted289 // through after the notify IO is deleted
289 pIO->unsubscribe ( guard );290 pIO->unsubscribe ( guard );
290 // If they call ioCancel() here it will be ignored291 // If they call ioCancel() here it will be ignored
@@ -301,8 +302,8 @@
301 }302 }
302}303}
303304
304void dbContext::ioCancel ( 305void dbContext::ioCancel (
305 epicsGuard < epicsMutex > & guard, dbChannelIO & chan, 306 epicsGuard < epicsMutex > & guard, dbChannelIO & chan,
306 const cacChannel::ioid &id )307 const cacChannel::ioid &id )
307{308{
308 guard.assertIdenticalMutex ( this->mutex );309 guard.assertIdenticalMutex ( this->mutex );
@@ -325,8 +326,8 @@
325 }326 }
326}327}
327328
328void dbContext::ioShow ( 329void dbContext::ioShow (
329 epicsGuard < epicsMutex > & guard, const cacChannel::ioid &id, 330 epicsGuard < epicsMutex > & guard, const cacChannel::ioid &id,
330 unsigned level ) const331 unsigned level ) const
331{332{
332 guard.assertIdenticalMutex ( this->mutex );333 guard.assertIdenticalMutex ( this->mutex );
@@ -339,7 +340,7 @@
339void dbContext::showAllIO ( const dbChannelIO & chan, unsigned level ) const340void dbContext::showAllIO ( const dbChannelIO & chan, unsigned level ) const
340{341{
341 epicsGuard < epicsMutex > guard ( this->mutex );342 epicsGuard < epicsMutex > guard ( this->mutex );
342 tsDLIterConst < dbSubscriptionIO > pItem = 343 tsDLIterConst < dbSubscriptionIO > pItem =
343 chan.dbContextPrivateListOfIO::eventq.firstIter ();344 chan.dbContextPrivateListOfIO::eventq.firstIter ();
344 while ( pItem.valid () ) {345 while ( pItem.valid () ) {
345 pItem->show ( guard, level );346 pItem->show ( guard, level );
@@ -356,14 +357,14 @@
356 this->show ( guard, level );357 this->show ( guard, level );
357}358}
358359
359void dbContext::show ( 360void dbContext::show (
360 epicsGuard < epicsMutex > & guard, unsigned level ) const361 epicsGuard < epicsMutex > & guard, unsigned level ) const
361{362{
362 guard.assertIdenticalMutex ( this->mutex );363 guard.assertIdenticalMutex ( this->mutex );
363 printf ( "dbContext at %p\n", 364 printf ( "dbContext at %p\n",
364 static_cast <const void *> ( this ) );365 static_cast <const void *> ( this ) );
365 if ( level > 0u ) {366 if ( level > 0u ) {
366 printf ( "\tevent call back cache location %p, and its size %lu\n", 367 printf ( "\tevent call back cache location %p, and its size %lu\n",
367 static_cast <void *> ( this->pStateNotifyCache ), this->stateNotifyCacheSize );368 static_cast <void *> ( this->pStateNotifyCache ), this->stateNotifyCacheSize );
368 this->readNotifyCache.show ( guard, level - 1 );369 this->readNotifyCache.show ( guard, level - 1 );
369 }370 }
@@ -375,7 +376,7 @@
375 }376 }
376}377}
377378
378void dbContext::flush ( 379void dbContext::flush (
379 epicsGuard < epicsMutex > & guard )380 epicsGuard < epicsMutex > & guard )
380{381{
381 guard.assertIdenticalMutex ( this->mutex );382 guard.assertIdenticalMutex ( this->mutex );
382383
=== modified file 'src/ioc/db/dbContextReadNotifyCache.cpp'
--- src/ioc/db/dbContextReadNotifyCache.cpp 2010-10-05 19:27:37 +0000
+++ src/ioc/db/dbContextReadNotifyCache.cpp 2012-06-21 20:42:45 +0000
@@ -5,7 +5,7 @@
5* Operator of Los Alamos National Laboratory.5* Operator of Los Alamos National Laboratory.
6* EPICS BASE Versions 3.13.76* EPICS BASE Versions 3.13.7
7* and higher are distributed subject to a Software License Agreement found7* and higher are distributed subject to a Software License Agreement found
8* in file LICENSE that is included with this distribution. 8* in file LICENSE that is included with this distribution.
9\*************************************************************************/9\*************************************************************************/
1010
11/*11/*
@@ -30,11 +30,11 @@
3030
31class privateAutoDestroyPtr {31class privateAutoDestroyPtr {
32public:32public:
33 privateAutoDestroyPtr ( 33 privateAutoDestroyPtr (
34 dbContextReadNotifyCacheAllocator & allocator, unsigned long size ) :34 dbContextReadNotifyCacheAllocator & allocator, unsigned long size ) :
35 _allocator ( allocator ), _p ( allocator.alloc ( size ) ) {}35 _allocator ( allocator ), _p ( allocator.alloc ( size ) ) {}
36 ~privateAutoDestroyPtr () { _allocator.free ( _p ); }36 ~privateAutoDestroyPtr () { _allocator.free ( _p ); }
37 char * get () const { return _p; } 37 char * get () const { return _p; }
38private:38private:
39 dbContextReadNotifyCacheAllocator & _allocator;39 dbContextReadNotifyCacheAllocator & _allocator;
40 char * _p;40 char * _p;
@@ -43,28 +43,28 @@
43};43};
4444
45// extra effort taken here to not hold the lock when calling the callback45// extra effort taken here to not hold the lock when calling the callback
46void dbContextReadNotifyCache::callReadNotify ( 46void dbContextReadNotifyCache::callReadNotify (
47 epicsGuard < epicsMutex > & guard, struct dbAddr & addr, 47 epicsGuard < epicsMutex > & guard, struct dbChannel * dbch,
48 unsigned type, unsigned long count, cacReadNotify & notify )48 unsigned type, unsigned long count, cacReadNotify & notify )
49{49{
50 guard.assertIdenticalMutex ( _mutex );50 guard.assertIdenticalMutex ( _mutex );
5151
52 if ( type > INT_MAX ) {52 if ( type > INT_MAX ) {
53 notify.exception ( guard, ECA_BADTYPE, 53 notify.exception ( guard, ECA_BADTYPE,
54 "type code out of range (high side)", 54 "type code out of range (high side)",
55 type, count );55 type, count );
56 return;56 return;
57 }57 }
5858
59 if ( addr.no_elements < 0 ) {59 if ( dbChannelElements(dbch) < 0 ) {
60 notify.exception ( guard, ECA_BADCOUNT, 60 notify.exception ( guard, ECA_BADCOUNT,
61 "database has negetive element count",61 "database has negetive element count",
62 type, count);62 type, count);
63 return;63 return;
64 }64 }
6565
66 if ( count > static_cast < unsigned > ( addr.no_elements ) ) {66 if ( count > static_cast < unsigned long > ( dbChannelElements(dbch) ) ) {
67 notify.exception ( guard, ECA_BADCOUNT, 67 notify.exception ( guard, ECA_BADCOUNT,
68 "element count out of range (high side)",68 "element count out of range (high side)",
69 type, count);69 type, count);
70 return;70 return;
@@ -75,21 +75,21 @@
75 int status;75 int status;
76 {76 {
77 epicsGuardRelease < epicsMutex > unguard ( guard );77 epicsGuardRelease < epicsMutex > unguard ( guard );
78 status = db_get_field ( &addr, static_cast <int> ( type ), 78 status = dbChannel_get ( dbch, static_cast <int> ( type ),
79 ptr.get (), static_cast <int> ( count ), 0 );79 ptr.get (), static_cast <long> ( count ), 0 );
80 }80 }
81 if ( status ) {81 if ( status ) {
82 notify.exception ( guard, ECA_GETFAIL, 82 notify.exception ( guard, ECA_GETFAIL,
83 "db_get_field() completed unsuccessfuly",83 "db_get_field() completed unsuccessfuly",
84 type, count );84 type, count );
85 }85 }
86 else { 86 else {
87 notify.completion ( 87 notify.completion (
88 guard, type, count, ptr.get () );88 guard, type, count, ptr.get () );
89 }89 }
90}90}
9191
92void dbContextReadNotifyCache::show ( 92void dbContextReadNotifyCache::show (
93 epicsGuard < epicsMutex > & guard, unsigned level ) const93 epicsGuard < epicsMutex > & guard, unsigned level ) const
94{94{
95 guard.assertIdenticalMutex ( _mutex );95 guard.assertIdenticalMutex ( _mutex );
@@ -155,8 +155,8 @@
155 pNext = _pReadNotifyCache->pNext;155 pNext = _pReadNotifyCache->pNext;
156 count++;156 count++;
157 }157 }
158 printf ( "\tcount %lu and size %lu\n", 158 printf ( "\tcount %lu and size %lu\n",
159 static_cast < unsigned long > ( count ), 159 static_cast < unsigned long > ( count ),
160 _readNotifyCacheSize );160 _readNotifyCacheSize );
161 }161 }
162}162}
163163
=== modified file 'src/ioc/db/dbEvent.c'
--- src/ioc/db/dbEvent.c 2011-10-19 18:07:00 +0000
+++ src/ioc/db/dbEvent.c 2012-06-21 20:42:45 +0000
@@ -1,19 +1,20 @@
1/*************************************************************************\1/*************************************************************************\
2* Copyright (c) 2010 Brookhaven National Laboratory.
3* Copyright (c) 2010 Helmholtz-Zentrum Berlin
4* fuer Materialien und Energie GmbH.
2* Copyright (c) 2002 The University of Chicago, as Operator of Argonne5* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3* National Laboratory.6* National Laboratory.
4* Copyright (c) 2002 The Regents of the University of California, as7* Copyright (c) 2002 The Regents of the University of California, as
5* Operator of Los Alamos National Laboratory.8* Operator of Los Alamos National Laboratory.
6* EPICS BASE Versions 3.13.79* EPICS BASE is distributed subject to a Software License Agreement found
7* and higher are distributed subject to a Software License Agreement found10* in file LICENSE that is included with this distribution.
8* in file LICENSE that is included with this distribution.
9\*************************************************************************/11\*************************************************************************/
10/* dbEvent.c */12
11/* $Revision-Id$ */
12/* routines for scheduling events to lower priority tasks via the RT kernel */
13/*13/*
14 * Author: Jeffrey O. Hill 14 * Author: Jeffrey O. Hill <johill@lanl.gov>
15 * Date: 4-1-8915 *
16*/16 * Ralph Lange <Ralph.Lange@bessy.de>
17 */
1718
18#include <stddef.h>19#include <stddef.h>
19#include <stdlib.h>20#include <stdlib.h>
@@ -39,6 +40,7 @@
39#include "db_field_log.h"40#include "db_field_log.h"
40#define epicsExportSharedSymbols41#define epicsExportSharedSymbols
41#include "dbAddr.h"42#include "dbAddr.h"
43#include "dbChannel.h"
42#include "dbLock.h"44#include "dbLock.h"
43#include "dbAccessDefs.h"45#include "dbAccessDefs.h"
44#include "dbEvent.h"46#include "dbEvent.h"
@@ -49,51 +51,33 @@
49#define EVENTQEMPTY ((struct evSubscrip *)NULL)51#define EVENTQEMPTY ((struct evSubscrip *)NULL)
5052
51/*53/*
52 * event subscruiption
53 */
54struct evSubscrip {
55 ELLNODE node;
56 struct dbAddr *paddr;
57 EVENTFUNC *user_sub;
58 void *user_arg;
59 struct event_que *ev_que;
60 db_field_log *pLastLog;
61 unsigned long npend; /* n times this event is on the queue */
62 unsigned long nreplace; /* n times replacing event on the queue */
63 unsigned char select;
64 char valque;
65 char callBackInProgress;
66 char enabled;
67};
68
69/*
70 * really a ring buffer54 * really a ring buffer
71 */55 */
72struct event_que {56struct event_que {
73 /* lock writers to the ring buffer only */57 /* lock writers to the ring buffer only */
74 /* readers must never slow up writers */58 /* readers must never slow up writers */
75 epicsMutexId writelock;59 epicsMutexId writelock;
76 db_field_log valque[EVENTQUESIZE];60 db_field_log *valque[EVENTQUESIZE];
77 struct evSubscrip *evque[EVENTQUESIZE];61 struct evSubscrip *evque[EVENTQUESIZE];
78 struct event_que *nextque; /* in case que quota exceeded */62 struct event_que *nextque; /* in case que quota exceeded */
79 struct event_user *evUser; /* event user parent struct */63 struct event_user *evUser; /* event user parent struct */
80 unsigned short putix;64 unsigned short putix;
81 unsigned short getix;65 unsigned short getix;
82 unsigned short quota; /* the number of assigned entries*/66 unsigned short quota; /* the number of assigned entries*/
83 unsigned short nDuplicates; /* N events duplicated on this q */ 67 unsigned short nDuplicates; /* N events duplicated on this q */
84 unsigned short nCanceled; /* the number of canceled entries */68 unsigned short nCanceled; /* the number of canceled entries */
85};69};
8670
87struct event_user {71struct event_user {
88 struct event_que firstque; /* the first event que */72 struct event_que firstque; /* the first event que */
89 73
90 epicsMutexId lock;74 epicsMutexId lock;
91 epicsEventId ppendsem; /* Wait while empty */75 epicsEventId ppendsem; /* Wait while empty */
92 epicsEventId pflush_sem; /* wait for flush */76 epicsEventId pflush_sem; /* wait for flush */
93 77
94 EXTRALABORFUNC *extralabor_sub;/* off load to event task */78 EXTRALABORFUNC *extralabor_sub;/* off load to event task */
95 void *extralabor_arg;/* parameter to above */79 void *extralabor_arg;/* parameter to above */
96 80
97 epicsThreadId taskid; /* event handler task id */81 epicsThreadId taskid; /* event handler task id */
98 struct evSubscrip *pSuicideEvent; /* event that is deleteing itself */82 struct evSubscrip *pSuicideEvent; /* event that is deleteing itself */
99 unsigned queovr; /* event que overflow count */83 unsigned queovr; /* event que overflow count */
@@ -114,34 +98,28 @@
114#define RNGINC(OLD)\98#define RNGINC(OLD)\
115( (unsigned short) ( (OLD) >= (EVENTQUESIZE-1) ? 0 : (OLD)+1 ) )99( (unsigned short) ( (OLD) >= (EVENTQUESIZE-1) ? 0 : (OLD)+1 ) )
116100
117#define LOCKEVQUE(EV_QUE)\101#define LOCKEVQUE(EV_QUE) epicsMutexMustLock((EV_QUE)->writelock)
118epicsMutexMustLock((EV_QUE)->writelock);102#define UNLOCKEVQUE(EV_QUE) epicsMutexUnlock((EV_QUE)->writelock)
119103#define LOCKREC(RECPTR) epicsMutexMustLock((RECPTR)->mlok)
120#define UNLOCKEVQUE(EV_QUE)\104#define UNLOCKREC(RECPTR) epicsMutexUnlock((RECPTR)->mlok)
121epicsMutexUnlock((EV_QUE)->writelock);
122
123#define LOCKREC(RECPTR)\
124epicsMutexMustLock((RECPTR)->mlok);
125
126#define UNLOCKREC(RECPTR)\
127epicsMutexUnlock((RECPTR)->mlok);
128105
129static void *dbevEventUserFreeList;106static void *dbevEventUserFreeList;
130static void *dbevEventQueueFreeList;107static void *dbevEventQueueFreeList;
131static void *dbevEventBlockFreeList;108static void *dbevEventSubscriptionFreeList;
109static void *dbevFieldLogFreeList;
132110
133static char *EVENT_PEND_NAME = "eventTask";111static char *EVENT_PEND_NAME = "eventTask";
134112
135static struct evSubscrip canceledEvent;113static struct evSubscrip canceledEvent;
136114
137static unsigned short ringSpace ( const struct event_que *pevq ) 115static unsigned short ringSpace ( const struct event_que *pevq )
138{116{
139 if ( pevq->evque[pevq->putix] == EVENTQEMPTY ) {117 if ( pevq->evque[pevq->putix] == EVENTQEMPTY ) {
140 if ( pevq->getix > pevq->putix ) {118 if ( pevq->getix > pevq->putix ) {
141 return ( unsigned short ) ( pevq->getix - pevq->putix );119 return ( unsigned short ) ( pevq->getix - pevq->putix );
142 }120 }
143 else {121 else {
144 return ( unsigned short ) ( ( EVENTQUESIZE + pevq->getix ) - pevq->putix ); 122 return ( unsigned short ) ( ( EVENTQUESIZE + pevq->getix ) - pevq->putix );
145 }123 }
146 }124 }
147 return 0;125 return 0;
@@ -163,7 +141,7 @@
163 DBADDR addr;141 DBADDR addr;
164 long status;142 long status;
165 struct evSubscrip *pevent;143 struct evSubscrip *pevent;
166 dbFldDes *pdbFldDes;144 dbFldDes *pdbFldDes;
167145
168 if ( ! pname ) return DB_EVENT_OK;146 if ( ! pname ) return DB_EVENT_OK;
169 status = dbNameToAddr ( pname, &addr );147 status = dbNameToAddr ( pname, &addr );
@@ -172,7 +150,7 @@
172 return DB_EVENT_ERROR;150 return DB_EVENT_ERROR;
173 }151 }
174152
175 LOCKREC ( addr.precord );153 LOCKREC (addr.precord);
176154
177 pevent = (struct evSubscrip *) ellFirst ( &addr.precord->mlis );155 pevent = (struct evSubscrip *) ellFirst ( &addr.precord->mlis );
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: