V4 Database Definition

From EPICSWIKI
Revision as of 18:13, 2 May 2005 by AndrewJohnson (talk | contribs) (Converted from Marty's HTML page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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

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;