V4 Database Definition
EPICS: IOC Database Definition
April 29 2005
Goals
The following is a brief summary of the goals for the V4 Database Definition.
- Data Types
- Support "minimal" set of types, i.e. the minimum set that provides the functionality needed for V4 databases.
- Extensible: struct and array are DBD types
- Character Strings
- Arbitrary Length
- UTF-8
- Multidimensional Variable Length Arrays
- All supported types configurable by Database Configuration Tools
For example arrays and structs can be initialized via a DCT
- record and struct fields
- Arrays of most supported types
- metadata for database access
- Each field can have associated metadata
- Extensible set of properties
- remove artifical limits. For example allow arrays of link and menus.
- Links
Allow alternative implementations for soft links
- Device Support
Record type independent. Use interface for communication between record and device support..
struct can be the way time synchronous gets/puts can be handled. A client can request a get, put, or monitor on a struct and guaranteed that entire set of data is performed with the record containing the struct locked, i.e. no record processing can occur during the get/put. If this is the way time synchronous data is handled, then all the issues of trying to lock sets of record are avoided.
Overview
This chapter describes the Database Definition Syntax for V4 databases. It assumes that the reader is familiar with the EPICS Version 3 (V3) Database Definition Syntax as described in chapter 6 of the 3.14 Application Developer's Guide. The new Database Definition Syntax is meant to be used both by iocCore and by Database Configuration Tools (especially VDCT).
This document only describes the V4 Database Definition. Support libraries need to be created to support the V4 database. These will need their own documentation divided into something like the following:
- EPICS: iocTypes
- EPICS: IOC Database Access
- EPICS: IOC Record Support
Database Definitions
The following definitions are discussed:
- include - same as V3 include
- menu - like the V3 menu
- struct - New for V4.
- record - like the V3 recordtype
- link
- device - these replace V3 device plus much more
- registrar - same as V3 registrar
- variable - same as V3 variable
- record instances - like the V3 record
This document will not discuss the definitions that are the same as for V4.
Database Field Types
The V4 database field types are:
- bool
- A value that is (0,1) meaning (false,true)
- octet
- A 8 bit byte. Replaces DBF_CHAR and DBF_UCHAR.
- int16
- Same as V3 DBF_SHORT.
- uint16
- Same as V3 DBF_USHORT.
- int32
- Same as V3 DBF_LONG.
- uint32
- Same as V3 DBF_ULONG.
- int64
- New 64 bit integer.
- uint64
- New unsigned 64 bit integer.
- float32
- Same as V3 DBF_FLOAT.
- float64
- Same as V3 DBF_DOUBLE.
- string
- Replaces V3 DBF_STRING. Arbitrary length character string. It supports Unicode/UTF-8.
- menu
- Like V3 DBF_MENU but with string for choices.
- enum
- Like V3 DBF_ENUM but with string for choices.
- struct
- New for V4.
- link
- device
- link and device are new for V4. Extensible replacement for V3 DBF_XXXLINK and DTYP
- array
- Multidimensional arrays are now a field type
- private
- Like V3 DBF_NOACCESS but new syntax.
V3 features not in V4
V3 field types that do not exist in V4
The following V3 field types no longer exist:
- DBF_CHAR
- Replaced by octet but no arithmetic or conversions are supported.
- DBF_UCHAR
- Replaced by octet but no arithmetic or conversions are supported.
- DBF_DEVICE
- Replaced by device.
- DBF_INLINK
- Replaced by link and device
- DBF_OUTLINK
- Replaced by link and device
- DBF_FWDLINK
- Replaced by link and device
V3 Database Definitions not in V4
- path
- No longer needed.
- addpath
- No longer needed.
- driver
- Drivers must develop another way to configure and report. asynDrivers already has replacements.
- breaktable
- A replacement will be created. What!!!!
V3 field attributes not in V4
- pp
- Is this part of CA V4? It should be.
- base
- This was needed for 3.12 releases. It is no longer needed.
- size
- Not needed since string is arbitrary length string.
- extra
- New syntax replaces this.
- menu
- New syntax replaces this.
- interest
- Only used by dbpr. Find a better way!!!
- prompt and group
- Replaced by struct, arbitrary length field names, and nodct.
Summary of V4 Database Definition Syntax
include "filename" #comment menu(name) { choice("choice_value") ... } struct(name) { field(field_name,field_definition) {field_attributes} ... } record(name) extends iocRecord { include "filename" field(field_name,field_definition) {field_attributes} ... } #If field_definition is empty record instance determines type # must be one of bool,...,string #field_definition is one of the following: bool octet int16 uint16 int32 uint32 int64 uint64 float32 float64 string menu(name) enum # has associated # struct() { # field(index,iocInt16) # field(choice,array(string[])) # } struct(structName,interfaceName) link(direction) device(direction,interfaceName) #direction is null,in,out,fwd, or inout #interfaceName is the name of the record/device interface # an array field_definition has one of the following forms array(<type>[capacity]) #1dim array array(<type>[capacity,capacity,...]) #ndim array array(<type>) #arbitary dimensional array #<type> is not specified or one of bool,...,link # If not specified record instance determines type #capacity is optional. If not specified record instance determines capacity private("valid C type") #must NOT include field name #field_attributes is any combination of the following: asl(asl_level) default("default_value") nodct readonly special link #This field is a link to another record metadata(name,field,dynamic) #multiple properties can be specified interface(interfaceName,choiceName) link(dir,choiceName,configStruct) device(dir,interfaceName,choiceName,configStruct) #dir is null,in,out,fwd, or inout #interfaceName is name of interface record support understands #choiceName is name that is mapped to interface implementation #configStruct is struct containing configuration information registrar(function_name) variable(variable_name) #The Following defines a Record Instance recordType "recordName" = { include "filename" info name = {"info_value"}; fieldName = {fieldValue}; fieldName = type {fieldValue}; /*Only if type is not defined in record*/ fieldName = [capacities] {fieldValue}; /*Only if dim or capacities unknown*/ fieldName = type[capacities] {fieldValue};/*type and capacities unknown*/ fieldName = choiceName {configStructValue};/*for struct/link/device fields*/ ... } # type is one of bool,...,string # capacity is one of # capacity 1dim array # capacity,capacity,... ndim array # #fieldValue is scalar_value or struct_value or array_def or link_value #where #scalar_value is num_value or string_value # where # num_value is value # example: The following initializes a float64 field # outputRateOfChange = {1.0}; # string_value is "value" # example for menu field # scan = {".1 second"}; # example for string field # command = {"getValue\r\n"}; #struct_value is field_value or name = field_value , ... # assume struct(point) {field(x,float64) field(y,float64) field(z,float64)} # example: xxx = { y = 1.0, 2.0}; #array_def is row_value (1dim) or {row_value}, {row_value} ... (ndim) # row_value is field_value or [index]=field_value , ... # 1dim example: The following perform the same initialization # xxx = [4] {1.0,[2] = 3.0,4.0}; # xxx = [4] {1.0,0.0,3.0,4.0}; # 2dim example: The following all create a 3x3 identity matrix # xxx = [3,3]{{1, 0, 0} {0, 1, 0} {0, 0, 1}}; # xxx = [3,3]{{1}, {[1]=1}, {[2]=1}}; # xxx = [3,3]{[0]={1}, [1] = {0, 1}, {0, 0, 1}}; #examples of link/device fields # inp = constant {"stringValue"); # inp = dblink {pvname = "pvname",pp=1,ms=1}; # inp = SomeVMEdevice {card = 0,signal = 2,parm = "parm stuff"}
menu(name) { choice("choice_value") ... }
where
- name
- Must be a valid C identifier. Each menu must have a unique name.
- filename
- Must be a valid filename
- choice_value
- Can be any UTF-8 compatible string
Example:
menu(menuScan) { choice("Passive") choice("Event") choice("I/O Intr") choice("10 second") choice("5 second") choice("2 second") choice("1 second") choice(".5 second") choice(".2 second") choice(".1 second") }
struct and record
struct
A struct is defined as follows:
struct(name) { field(field_name,field_definition) {field_attributes} ... }
where
- name
- The structure name. It must be a valid C identifier. No two structures can have the same name.
- field_name
- Must be a valid C identifier
- field_definition
- See field_definition below.
- field_attributes
- See field_attributes below.
record
A record type is defined as follows:
include "dbCommon.dbd" record(name) extends iocRecord { field(field_name,field_definition) {field_attributes} ... }
- name
- The record type name. It must be a valid C identifier. No two record types can have the same name.
- field_name
- Must be a valid C identifier
- field_definition
- See field_definition below.
- field_attributes
- See field_attributes below.
field_definition
Both struct and record define a field as:
field(field_name,field_definition)
The syntax for field_definition depends of the field type.
- Numeric, Octet,and String Types
The following types have no arguments: bool, int16, uint16, int32, uint32,int64,uint54, float32, float64, octet,and string.
Example: field(description,string) field(value,float64)
- enum
An enum field also has no argument but has an implicit int32 and array(string[]).
struct() { field(index,int16) field(choice,array(string[]) }
- menu
A menu has the definition:
menu(name)
where
- name
- The name of the menu.
Example:
field(SCAN,menu(menuScan))
- struct
A struct has the definition:
struct(structName,interfaceName)
where
- structName
- The name of the struct, which must have been previously defined.
- interfaceName
- The name of an interface that provides code for the struct.
Example:
struct(point) { field(x,float64) field(y,float64) field(z,float64) } ... record(haspoint) extends iocRecord { ... field(point,struct(point)) }
- array
An array has one of the following definitions:
array(<type>[capacity]) #1dim array array(<type>[capacity,...]) #ndim array array(<type>) #arbitrary dimensional array
where
- <type>
- Any one of bool,...,link. In addition a null is acceptable. In this case the type is determined by record instance definitions.
- capacity
- The capacity for each dimension or null. If not specified then record instance determines capacity..
Examples:
field(VAL1D,array(float64[])) #1d array with arbitrary capacity field(VAL2D,array(float64[,])) #2d array with arbitrary capacities field(anyTypeAnyD,array()) #arbitrary type,number of dimensions, and capacities
- private
This is to allow "private" fields, i.e. fields not meant for use by database or channel access. The syntax is:
private("valid C definition")
where a valid C definition must be specified. Example:
field(asp,private("void *"))
The C definition must not include a field name since the field name in the generated include file is taken from the database definition.
- link device
This is for fields that can get or put data from/to a source outside the record. They replace the V3 DBF_XXXLINKs. A link field is similar to the non INP or OUT link fields from V3. A device field is similar to the INP or OUT together with the DTYP fields from V3. A link field obtains it's choices from link definitions. A device field obtains it's choices from device definitions. The main difference between link and device is that record support communicates with link support via a standard interface and with device support via specialized interfaces. The syntax is:
link(linkDirection) device(linkDirection,deviceInterface)
where
- linkDirection
- one of null, "in", "out", "fwd", or "inout". If null or inout, i.e. the
direction is determined by the link or device a record instance selects. Examples:
field(disableLink,link(in)) field(flnk,link(fwd)) field(inp,device(in,digitalIO))
field_attributes
field_attributes can be any combination of the following:
asl(asl_level) default("default_value") nodct readonly special link metadata(name,field,dynamic)
- asl
- access security level. Must be 0 or 1
- default
- Default value
- nodct
- Database Configuration Tool should not show
- readonly
- This field can not be modified via channel access or database links
- special
- Take special action if field is modified.
- link
- The field is a link to another record. This attribute is normally only defined for a field in a struct that is referenced in a link or device definition For example struct(pvlink) specifies the link attribute for field pvname.
- metadata
- Defines a metadata for the field. Multiple metadata attributes can be defined for a field.
- name
- The name of the metadata.
- field
- The name of a field in the same record.
- dynamic
- must be static or dynamic. The default is static. dynamic means that the value may change because of record processing. static means that the value does not change because of record processing. time is an example of a dynamic field and displayLimit is an example of a static field.
Example of metadata definitions
An analog output record can have fields like
record(ao) extends iocRecord { field(value,float64) { metadata("timeStamp",time,dynamic) metadata("displayLimit",displayLimit) metadata("controlLimit",controlLimit) ... } field(displayLimit,struct(displayLimit)) field(controlLimit,struct(controlLimit)) ... }
link and device
link describes choices for link fields and device describes choices for device fields.
the syntax:
link(dir,choiceName,configStruct) device(dir,interfaceName,choiceName,configStruct)
where
- choiceName
- UTF-8 string that describes the choice
- dir
- Must be one of null,in,out,fwd, or inout. Compatible checks are made to match the interface with a field. What are the rules?????
- configStruct
- The name of a struct for configuration information
- interfaceName
- The name of an interface via which record support communicates with device support.
record instance
A record instance has the following syntax
<recordType> "record_name" = { info name = {"info_value"}; fieldName = {fieldValue}; fieldName = type {fieldValue}; #Only if type is not defined in record fieldName = [capacities] {fieldValue}; #Only if dim or capacities unknown fieldName = type[capacities] {fieldValue}; #Only if type and capacities unknown fieldName = choiceName {configStructValue}; #for link/device fields ... }
where
- recordType
- The name of the record type
- record_name
- The name of the record instance. What restrictions will we place on record instance name? Can this contain non-ascii characters? That is will UTF-8 instance names be supported?
- info name
- Like V3 except new syntax
- fieldName
- The field name.
- type
- One of the types bool,...,string. This is only specified if the record definition did not specify a type.
- capacities
- The capacities for an array. This can only be specified if the record definition did not define the number of dimensions or the capacities. It has the format:
capacity,... The number of dimensions must agree with what record defined. For example if the record defined that array as array(<type>[]) then only one capacity can be specified. If a record defined array(<type>) than the record instance determines the number of dimensions and the capacities.
- choiceName
- This is the syntax for struct, link, and device fields. choiceName is a choice defined in a struct, link, or device definition.
- field_value
- The syntax depends on the field type. The details are described next..
The format for field_value depends of the field type.
- Single Item Field types
The following just have a single value: int16, uint16, int32, uint32, uint32, float32, float64, octet, string, enum, menu For example
value = {"1.0"} #Field Definition is float64 scan = {"1 second"} #Field Definition is menu description = {"This is a description"} #Field Definition is string junk = {"\x01\x02"} #Field Definition is array(octet[])
- Structure fields
The syntax follows the C99 syntax for initializing structures. Lets give some examples. assume that the following definitions have been made in a dbd file:
struct(point) { field(x,float64) field(y,float64) field(z,float64) } ... struct (pointdes) { field(des,string) field(point,struct(point)) } ... record(example) extends iocRecord { ... field(value,struct(pointdes)) ... }
Then the following are some of the valid ways to initialize the val field of an instance of an example record. They all do the same initialization.
value = {"this is the value for val.des",{0.0,1.0,2.0}} or value = {des = "this is the value for val.des", {x = 0.0, y =1.0, z = 2.0}} or value = {"this is the value for val.des", {y =1.0, z = 2.0}}
- Array fields
The syntax for array fields uses the C99 array initialization syntax. Some examples:
oneD = [3] {1.0,2.0,3.0} #The following creates a 3x3 identity matrix twoD = [3,3] { {1},{[1] = 1}, {[2] = 1}} #The following initializes an arbitrary type, arbitrary dim matrix anyDanyT = int16[3,3] { {1},{[1] = 1}, {[2] = 1}}
- link or device fields
The syntax is:
field = choiceName {struct_value}
For link choiceName is one of the choices from link definitions that have compatible directions. For device choiceName is one of the choices from link and device definitions that have compatible directions. struct_value is like the value for struct fields where the structure is the configStruct from the link or device definition which choiceName selected.
Process Variable Names
A process variable name (PV) follow C syntax for specifying fields and elements of arrays. A PV can select an elemenentary field, a structure, of an array.
For example if a pvname is:
recordname.f1.f2[ind].f3
Then:
- f1 is a field in recordname which is a structure
- f2 is a field of f1 that is an array of structures
- ind selects a structure from the array of structures
- f3 selects a field from the structure
Example: Assume that the following has been defined;
struct(s2) { ... field(f3,float64) ... } struct(s1) { ... field(f2,struct(s2) [] ) ... } record(sometype) extends iocRecord { ... field(f1,struct(s1)) ... } ... record(sometype,"xxx") { ... f1 = { f2 = [3] {[1] ={f3 = 2.0}}} ... }
Then:
xxx.f1.f2[1].f3
selects the float64 value 2.0
xxx.f1
selects the entire struct s1.
If a client accesses a struct it must know how to access the struct.
Standard Properties
The following is a list of standard metadata names.
- alarmStatus
The metadata must be defined as:
metadata("alarmStatus",alarmStatus,dynamic)
- alarmSeverity
The metadata must be defined as:
metadata("alarmSeverity",alarmSeverity,dynamic)
- timeStamp
The metadata must be defined as:
metadata("timeStamp",time,dynamic)
- displayLimit
The metadata must be defined as:
metadata("displayLimit",<field>) where field must be defined as: field(<field>,struct(displayLimit))
- controlLimit
The metadata must be defined as:
metadata("controlLimit",<field>) where field must be defined as: field(<field>,struct(controlLimit))
- alarmLimit
The metadata must be defined as:
metadata("alarmLimit",<field>) where field must be defined as: field(<field>,struct(alarmLimit))
- units
The metadata must be defined as:
metadata("units",<field>) where field must be defined as: field(<field>,string)
dbCommon
NOTE: dbCommon needs work. It should have more structure.
dbCommon.dbd defines the following:
# menu definitions for dbRecordCommon fields menu(menuPriority) { choice("LOW") choice("MEDIUM") choice("HIGH") } menu(menuScan) { choice("Passive") choice("Event") choice("I/O Intr") choice("10 second") choice("5 second") choice("2 second") choice("1 second") choice(".5 second") choice(".2 second") choice(".1 second") } menu(menuAlarmSevr) { choice("NO_ALARM") choice("MINOR") choice("MAJOR") choice("INVALID") } menu(menuConvert) { choice("NO CONVERSION") choice("SLOPE") choice("LINEAR") choice("Breakpoint Table") } #definition for constant links struct constantlink { field(value,string) } #definitions for ca, da, pv links #dblink must reference a pv in the same ioc. struct(dblink) { field(pvname,string) { link} field(pp,bool) field(ms,bool) } struct(dbfwdlink) {field(pvname,string){link}} #calink forces a link to be a channel access link struct(calink) { field(pvname,string) { link} field(pp,bool) field(ms,bool) } struct(cafwdlink) {field(pvname,string){link}} #pvlink becomes (dblink,calink) if pvname is (local,remote) struct(pvlink) { field(pvname,string) { link} field(pp,bool) field(ms,bool) } struct(pvfwdlink) {field(pvname,string){link}} link(inout,"constant",constantlink) link(inout,"dblink",dblink) link(inout,"calink",calink) link(inout,"pvlink",pvlink) link(fwd,"dblink",dbfwdlink) link(fwd,"calink",cafwdlink) link(fwd,"pvlink",pvfwdlink) #definitions for common properties struct(timeStamp) { field(secPastEpoch,uint64) field(nsec,uint32) }
iocRecord
iocRecord.dbd, which is part of every record, defines the following:
include "dbCommon.dbd" #The following are the fields that must be part of every recordtype #THIS SHOULD BE RESTRUCTURED record(iocRecord) { field(description,string) field(accessSecurityGroup,string) { special } field(scan,menu(menuScan)) { special } field(pini,bool) field(phase,int16) field(eventNumber,int16) { special } field(timeStampEvent,int16) field(timeStampLink,link(in)) field(disableValue,int16) { default("1") } field(disableInput,int16) field(disableLink,link(in)) field(disablePutField,bool) field(process,bool) { special } field(alarmStatus,string) { readonly default("UDF") } field(alarmSeverity,menu(menuAlarmSevr)) { readonly default("INVALID") } field(newAlarmStatus,string) { nodct readonly } field(newAlarmSeverity,menu(menuAlarmSevr)) { nodct readonly } field(alarmAckSeverity,menu(menuAlarmSevr)) { nodct readonly } field(alarmAckTransient,bool) { readonly default("YES") } field(disableAlarmSeverity,menu(menuAlarmSevr)) field(lockCount,int16) { nodct readonly } field(pact,bool) { nodct readonly } field(putFieldProcess,bool) { nodct readonly } field(reprocess,bool) { nodct readonly } field(priority,menu(menuPriority)) { special } field(udf,bool) { default("1") } field(time,struct(timeStamp)) { nodct readonly } field(flnk,link(fwd)) field(monitorLock,private("epicsMutexId")) field(monitorList,private("ELLLIST")) field(asp,private("void *")) field(ppn,private("struct putNotify *") field(ppnr,private("struct putNotifyRecord *")) field(spvt,private("struct scan_element *")) field(rset,private("struct rset *")) field(rdes,private(struct dbRecordType *")) field(lset,private("struct lockRecord *")) }
Comparison between V3 and V4
The following discusses the differences between the fields defined in V3 dbCommon.dbd and V4 iocRecord.dbd. The NOACCESS (now private) fields are not discussed.
- NAME
- Does not exist.
- DESC => description
- Name change and now arbitrary length UTF-8 string
- ASG => accessSecurityGroup
- Name change and now arbitrary length UTF-8 string
- SCAN => scan
- Case change
- PINI => pini
- Case change and type is now bool
- PHAS => phase
- Case change
- EVNT => eventNumber
- Name change
- TSE => timeStampEvent
- Name change
- TSEL => timeStampLink
- Name change
- DTYP
- No longer exists. Replaced by device
- DISV => disableValue
- Name change
- DISA => disableInput
- Name change
- SDIS => disableLink
- Name change
- DISP => disablePutField
- Name change and now bool
- PROC => process
- Name change and now bool
- STAT => alarmStatus
- Name change
- SEVR => alarmSeverity
- Name change
- NSTA => newAlarmStatus
- Name change
- NSEV => newAlarmSeverity
- Name change
- ACKS => alarmAckSeverity
- Name change
- ACKT => alarmAckTransient
- Name change and now bool
- DISS => disableAlarmSeverity
- Name change
- LCNT => lockCount
- Name change and now int16
- PACT => pact
- Case change and now bool
- PUTF => putFieldProcess
- Name change and now bool
- RPRO => reprocess
- Name change and now bool
- PRIO => priority
- Name change
- TPRO => reprocess
- No longer exists. Replaced by new tracing facility.
- UDF => udf
- Case change and now bool
- TIME => time
- Case change and now struct
- FLNK => flnk
- Case change and now link
aoRecord
aoRecord.dbd defines the following:
include "dbCommon.dbd" record(ao) extends iocRecord { field(value,float64) { asl(0) metadata("timeStamp",time,dynamic) metadata("alarmSeverity",alarmSeverity,dynamic) metadata("alarmStatus",alarmStatus,dynamic) metadata("displayLimit",displayLimit) metadata("controlLimit",controlLimit) metadata("alarmLimit",alarmLimit) metadata("units",units) } field(outValue,float64) { nodct metadata("timeStamp",time,dynamic) metadata("displayLimit",displayLimit) metadata("units",units) } field(out,device(out,analogOut)) field(outputRateOfChange,float64) field(desiredOutputLink,link(in)) field(closedLoop,bool) field(outputIncremental,bool) field(convert,menu(menuConvert)) { special } field(linearConvert,struct(linearConvert)) { special } field(units,string) field(displayLimit,struct(displayLimit)) field(controlLimit,struct(controlLimit)) field(alarmLimit,struct(alarmLimit)) field(alarmDeadband,float64) field(rawValue,int32) { nodct metadata("timeStamp",time) } field(prevRawValue,int32) { nodct readonly metadata("timeStamp",time) } field(readBackValue,int32) { nodct readonly metadata("timeStamp",time) } field(oldReadBackValue,int32) { nodct readonly metadata("timeStamp",time) } field(prevValue,float64) { nodct readonly } field(lastValueAlarmed,float64) { nodct readonly } field(pbrk,private("void *")) field(init,bool) { nodct readonly } field(lbrk,int16) { nodct readonly metadata("timeStamp",time) } field(simOutputLink,link(out)) field(simModeLink,link(in)) field(simMode,bool) field(simSevr,menu(menuAlarmSevr)) field(invalidAction,menu(menuIvoa)) field(invalidValue,float64) field(outValueModified,bool) { nodct readonly } }
Comparison between V3 and V4
The following discusses the differences between the fields defined in V3 and V4 aoRecord.dbd. The NOACCESS (now private) fields are not discussed.
- VAL => value
- Name change.
- OVAL => outValue
- Name change.
- OUT => out
- Case change and now device.
- OROC => outputRateOfChange
- Name change.
- DOL => desiredOutputLink
- Name change.
- OMSL => closedLoop
- Name change and now bool.
- OIF => outputIncremental
- Name change and now bool.
- PREC
- No longer supported
- LINR,EGUF,EGUL,ESLO,EOFF => linearConvert
- Handled via struct
- EGU => units
- Name change
- ROFF
- Obsolete
- HOPR,LOPR => displayLimit
- Now implemented via array
- DRVH,DRVL => controlLimit
- Now implemented via array
- AOFF,ASLO
- No longer supported.
- HIHI,LOLO,HIGH,LOW => alarmLimit
- Now implemented via struct
- HHSV,LLSV,HSV,LSV => alarmLimit
- Now implemented via struct
- HYST => alarmDeadband
- Name change
- ADEL,MDEL,ALST,MLST
- Replaced by new CA functionality. Is it???
- RVAL => rawValue
- Name change
- ORAW => prevRawValue
- Name change
- RBV => readBackValue
- Name change
- ORBV => oldReadBackValue
- Name change
- PVAL => prevValue
- Name change
- LALM => lastValueAlarmed
- Name change
- INIT => init
- Case change
- LBRK => lbrk
- Case change
- SIOL => simOutputLink
- Name change
- SIML => simModeLink
- Name change
- SIMM => simMode
- Name change
- SIMS => simSevr
- Name change
- IVOA => invalidAction
- Name change
- IVOV => invalidValue
- Name change
- OMOD => outValueModified
- Name change
calcRecord
calcRecord.dbd defines the following:
include "dbCommon.dbd" struct(calcInpLink) { field(link,link(in)) field(value,float64) field(prevValue,float64) } record(calc) extends iocRecord { field(value,float64) { asl(0) metadata("timeStamp",time,dynamic) metadata("alarmSeverity",alarmSeverity,dynamic) metadata("alarmStatus",alarmStatus,dynamic) metadata("displayLimit",displayLimit) metadata("alarmLimit",alarmLimit) metadata("units",units) } field(calc,string) { special } field(inp,array(struct(calcInpLink)[])) field(units,string) field(displayLimit,struct(displayLimit)) field(alarmLimit,struct(alarmLimit)) field(alarmDeadband,float64) field(lastValueAlarmed,float64) { nodct readonly } field(rpcl,private("char *")) }
Comparison between V3 and V4
The following discusses the differences between the fields defined in V3 and V4 calcRecord.dbd. The NOACCESS (now private) fields are not discussed.
- VAL => value
- Name change.
- CALC => calc
- Case change. What is new syntax?
- INPA,...INPL A,...L LA,...LL => inp
- Now implemented via array of structures. Record instances can create as many array elements as needed.
- EGU => units
- Name change.
- PREC
- No longer supported
- HOPR,LOPR => displayLimit
- Now implemented via struct
- HIHI,LOLO,HIGH,LOW => alarmLimit
- Now implemented via struct
- HHSV,LLSV,HSV,LSV => alarmLimit
- Now implemented via struct
- HYST => alarmDeadband
- Name change
- LALM => lastValueAlarmed
- Name change
- RPCL => rpcl
- Case change
mbbiRecord
mbbiRecord.dbd defines the following:
include "dbCommon.dbd" record(mbbi) extends iocRecord { field(value,enum) { asl(0) metadata("timeStamp",time,dynamic) metadata("alarmSeverity",alarmSeverity,dynamic) metadata("alarmStatus",alarmStatus,dynamic) } field(mask,array(uint32[])) { special } field(nbits,int16) { readonly } field(inp,device(in,digitalInput)) field(stateSeverity,array(menu(menuAlarmSevr)[])) field(unknownStateSeverity,menu(menuAlarmSevr)) field(changeStateSeverity,menu(menuAlarmSevr)) field(raw,uint32) { nodct readonly } field(oldRaw,uint32) { nodct readonly } field(hardwareMask,uint64 { readonly } field(lastValueAlarmed,int16) { nodct readonly } field(shift,uint16) { field(simInputLink,link(in)) field(simValue,uint64) field(simModeLink,link(in)) field(simMode,menu(menuYesNo)) field(simSevr,menu(menuAlarmSevr)) }
Comparison between V3 and V4
The following discusses the differences between the fields defined in V3 and V4 mbbiRecord.dbd. The NOACCESS (now private) fields are not discussed.
- VAL => value
- Name change. Now enum
- INP => inp
- Case change and now device.
- NOBT => nbits
- Name change.
- ZRVL,...,FFVL => mask
- Implemented via array. Record instances determine number of elements
- ONST,...,FFST => choice
- Implemented via array. Record instances determine number of elements
- ZRSV,...,FFSV => stateSeverity
- Implemented via array of menu(menuAlarmSevr). Record instances determine number of elements
- UNSV => unknownStateSeverity
- Name change and menu(menuAlarmSevr)
- COSV => changeStateSeverity
- Name change and menu(menuAlarmSevr).
- RVAL => raw
- Name change.
- ORAW => oldRaw
- Name change.
- MASK => hardwareMask
- Case change and now uint64
- MLST
- Handled by channel access???? Must discuss, i.e. to we want to post monitors every time record processes?
- SDEF
- Probably not needed.
- SHFT => shift
- Name change
- SIOL => simInputLink
- Name change
- SVAL => simValue
- Name change
- SIML => simModeLink
- Name change
- SIMM => simMode
- Name change
- SIMS => simSevr
- Name change
waveformRecord
waveformRecord.dbd defines the following:
include "dbCommon.dbd" record(waveform) extends iocRecord { field(value,array([])) { asl(0) special metadata("timeStamp",time,dynamic) metadata("alarmSeverity",alarmSeverity,dynamic) metadata("alarmStatus",alarmStatus,dynamic) metadata("displayLimit",displayLimit) metadata("units",units) } field(reArm,bool) field(inp,device(in,waveformIO)) field(units,string) field(displayLimit,struct(displayLimit)) field(busy,bool) { nodct readonly } field(simInputLink,link(in)) field(simModeLink,link(in)) field(simMode,menu(menuYesNo)) field(simSevr,menu(menuYesNo)) }
Comparison between V3 and V4
The following discusses the differences between the fields defined in V3 and V4 waveformRecord.dbd. The NOACCESS (now private) fields are not discussed.
- VAL => value
- Name change and is now a 1dim array field
- RARM => reArm
- Name change and is now an array field
- INP => inp
- Case change and now device.
- EGU => units
- Name change.
- HOPR,LOPR => displayLimit
- Now implemented via struct
- BUSY => busy
- Case change and now a bool
- SIOL => simInputLink
- Name change
- SIML => simModeLink
- Name change
- SIMM => simMode
- Name change
- SIMS => simSevr
- Name change
- PREC
- No longer supported
- NELM,FTVL,NORD,BPTR
- No longer needed because of new array support
Record Instance Examples
Initializing link and device fields
In order to support the database and channel access links the following struct definitions are in dbCommon.dbd: constantlink, dblink, dbfwdlink, calink, cafwdlink, pvlink, and pvfwdlink.
Assume that the recordtype definition has:
field(in,link(in))
The dbCommon.dbd definitions are automatically available for this field.
The following creates a record instance with a dblink
in = dblink {"pvname","pp","ms"}
Assume that the recordtype definition has:
field(in,device(in,analogIO))
The dbCommon.dbd definitions are automatically available for this field. Lets assume that the following has also been defined:
struct(vmeLink) { field(card,uint16) field(signal,uint16) field(parm,string) } device(in,analogIO,SomeVMEdevice,vmeLink)
The following creates a record instance connected to a vme device
in = SomeVMEdevice {0,2,"parm stuff"}
Initializing choices associated with an enum field
The following is a record instance that defines an mbbiRecord with three states and initializes the state to state0
mbbiRecord "xxx" = { ... value {0, {[3] {"state0","state1","state2"}}; mask [3] {0x1,0x2,0x4}; ... }
or
mbbiRecord "xxx" = { ... value {index=0, choice={[3] {"state0","state1","state2"}}; mask [3] {0x1,0x2,0x4}; ... }
Initializing an array of structures containing a link field
The calc record is defined as:
struct(calcInpLink) { field(link,link(in)) field(value,float64) field(prevValue,float64) }
record(calc) { ... field(inp,struct(calcInpLink)[]) ... }
The following calc record instance creates 32 input links but only initializes the third link.
calcRecord "xxx" = { ... inp = [32] {[2] = {link = pvlink {"pvname", "npp", "nms"}}} ... }
Initializing an array of arbitrary type
The waveform record is defined as:
record(waveform) { ... field(value,array([])) ... }
The following waveform record instance creates a 1024 element array of doubles. It initializes the 4th element of the array to 1.0. All other elements will be initialized to 0.0.
calcRecord "xxx" = { ... value = float64[1024] {[3] = 1.0} ... }
Unresolved Issues
attributes - nodct
Should this be dct(interestLevel)?
mbbi
Currently two fields define the states:
field(value,enum) field(mask,array(uint32[]))
Should there be a way to define these as one field?
- pro -
vdct can prompt for value and mask together
- con -
CA clients dont normally care about the mask values
dynamic metadata
Metadata can be dynamic meaning that the metadata might change as a result of record processing. Is this needed? The answer probably depends on how monitors are implemented. Can an efficient way be found to allow arbitrary metadata to be passed with a monitor or will it be necessary to limit the set of metadata, e.g. only timeStamp, status, and severity can be dynamic properties.
union and extend
Benjamin suggested that the DBD syntax should include union and extend. A limited form of extend is used for record. Is more needed?
prompt and group
This version only describes nodct for fields that DCTs should not show. Is this sufficient?
Scan Mechanism
Andrew gave a suggestion for a better way to define scan types and rates. This should be considered.
Implementation of special
Unlike V3 attribute special does not have an argument. For fields in iocRecord, iocCore implements special action when the field is modified.
For record type specific fields, the record support must implement a special method. It has a prototype something like:
iocStatus (*special)(iocDbAddr *piocDbAddr)
iocDbAddr will provide information that allows record support to determine the record instance, the field, and the new value to be written to the field. Record support is responsible for writing the new value. It can decide not to write a value. Details TBD.
Implementation of link
In V3 all links except INP,OUT were implemented by dbAccess. V4 provides an inplemention of link support that is similar to the V3 implementation but also allows other implementations. A link is defined as:
link(dir,choiceName,configStruct)
Record support communicates with the link support code via an interface something like the following:
typedef struct iocLinkSupport { epicsStatus (*connect)(iocDbAddr *piocDbAddr, const char *configName,void *pconfigStruct); epicsStatus (*disconnect)(iocDbAddr *piocDbAddr); epicsStatus (*get)(iocDbAddr *piocDbAddr); epicsStatus (*put)(iocDbAddr *piocDbAddr); }iocLinkConnect;
Implementation of device
In V3 all links INP,OUT together with field DTYP were implemented by device support modules. For V4 a device is defined as:
device(dir,interfaceName,choiceName,configStruct)
pinterface is the address of an implementation of interface iocDeviceConnect, which is something like the following:
typedef struct iocDeviceConnect { epicsStatus (*connect)(iocDbAddr *piocDbAddr, const char *configName,void *pconfigStruct); epicsStatus (*disconnect)(iocDbAddr *piocDbAddr); }iocDeviceConnect;