Difference between revisions of "V4 DBD Statement Syntax"

From EPICSWIKI
 
(41 intermediate revisions by 3 users not shown)
Line 1: Line 1:
DBD Statement Syntax November 02 2005
----
= Overview =
This document presents the syntax for V4 database definition files.
<b>NOTE</b> This version of the database definition and database instance
syntax does not provide:
# a direction for links
# a way to select a subset of the support definitions
Support can exist for either a link field or a struct field.
The support definition is just
    support(choiceName,supportStructName)
When a record instance is created any choiceName can be specified for
a link or struct field. If an invalid choice is made, an error will
be issued during initialization.
<center>
= General Statements =
= General Statements =
</center>


== include ==
== include ==
Line 10: Line 31:
: must be a valid filename
: must be a valid filename


The file system search path that will be used to look for the file is determined external to the DBD file itself.
The file system search path that will be used to look for the file is determined by the build system, and cannot be modified by the DBD file itself.
 
'''Question''': Where is this allowed?


Include statements can be used at the top level, or inside the braces of a <tt>menu</tt>, <tt>struct</tt> or <tt>record</tt> definition.


== # comment ==
== # comment ==
Line 36: Line 56:
: Must be a valid, unique C identifier.
: Must be a valid, unique C identifier.
; <tt>choiceName</tt>
; <tt>choiceName</tt>
: Must be a valid, unique C identifier. By convention, every choiceName should start with the menuName it belongs to.
: Must be a valid, unique C identifier. By convention, every choiceName should start with the menuName it belongs to. These names are only available to C/C++ source code using the header file generated from the menu definition; they are not stored in the IOC itself.
; <tt>choiceValue</tt>
; <tt>choiceValue</tt>
: Can be any UTF-8 compatible string
: Can be any UTF-8 compatible string, which should be unique within the context of this menu.
 
In general menus should only be definable once, in the DBD file (first definition seen wins in the event of duplicates, give a warning for duplicates and error if subsequent definition is different).  However we may want to include a syntax that allows specific menu definitions to be extended at database load time.


Example:
Example:
Line 55: Line 77:
  }
  }


 
<center>
= Structures, Record types, Fields and Views =
= Structures, Record types, Fields and Views =
</center>


Structures and record types have significant commonality in that they both define a data structure type containing fields.  The main difference is that you can't create or populate an instance of a structure outside of a record; only records can appear at the very top level.  Record types also define views of the record, which is not possible for a structure.
Structures and record types have significant commonality in that they both define a data structure type containing fields.  The main difference is that you can't create or populate an instance of a structure outside of a record; only records can appear at the very top level.  Record types also define views of the record, which is not possible for a structure.
Line 66: Line 89:
  struct(name) {
  struct(name) {
     field(fieldName, fieldType) {
     field(fieldName, fieldType) {
         fieldAttribute
         fieldAttribute(attributeValue)
         ...
         ...
     }
     }
Line 80: Line 103:
; <tt>fieldType</tt>
; <tt>fieldType</tt>
: See [[#fieldType|fieldType]] below.
: See [[#fieldType|fieldType]] below.
; <tt>fieldAttribute</tt>
; <tt>fieldAttribute</tt> and <tt>attributeValue</tt>
: See [[#fieldAttribute|fieldAttribute]] below.
: See [[#fieldAttribute|fieldAttribute]] below.


== record ==
== record ==
Line 89: Line 111:


  include "dbCommon.dbd"
  include "dbCommon.dbd"
  record(name) extends iocRecord {
  record(name) extends RecordCommon {
     field(fieldName, fieldType) {
     field(fieldName, fieldType) {
         fieldAttribute
         fieldAttribute(attributeValue)
         ...
         ...
     }
     }
     ...
     ...
     view(viewName) {
     view(viewName) {
         property(propName, fieldName)
         property(propName, fieldPath)
         ...
         ...
     }
     }
Line 104: Line 126:
; <tt>name</tt>
; <tt>name</tt>
: The record type name. It must be a valid, unique C identifier.
: The record type name. It must be a valid, unique C identifier.
; <tt>extends iocRecord</tt>
; <tt>extends RecordCommon</tt>
: This states that the record type extends the set of fields defined in [[V4 DBD dbCommon and iocRecord|iocRecord]]. It should be permissable to name other record types instead of iocRecord here, as long as the inheritance tree starts at iocRecordOnly single inheritance is supported.
: This states that the record type extends the set of fields defined in "V4 DB RecordCommon". It should be permissable to name other record types instead of RecordCommon here, as long as the inheritance tree starts at RecordCommonInheritance from multiple record types is not supported; you can only have one <tt>extends</tt> phrase.
; <tt>fieldName</tt>
; <tt>fieldName</tt>
: Must be a valid C identifier, unique within the context of this particular record type and its parents (extends ...).
: Must be a valid C identifier, unique within the context of this particular record type and its parents (extends ...).
; <tt>fieldType</tt>
; <tt>fieldType</tt>
: See [[#fieldType|fieldType]] below.
: See [[#fieldType|fieldType]] below.
; <tt>fieldAttribute</tt>
; <tt>fieldAttribute</tt> and <tt>attributeValue</tt>
: See [[#fieldAttribute|fieldAttribute]] below.
: See [[#fieldAttribute|fieldAttribute]] below.
; <tt>viewName</tt> and <tt>propName</tt>
; <tt>viewName</tt>, <tt>propName</tt> and <tt>fieldPath</tt>
: See [[#Views of a record|Views of a record]] below.
: See [[#Views of a record|Views of a record]] below.


Line 119: Line 141:
Both <tt>struct</tt> and <tt>record</tt> define a field as:
Both <tt>struct</tt> and <tt>record</tt> define a field as:
     field(fieldName, fieldType) {
     field(fieldName, fieldType) {
         fieldAttribute
         fieldAttribute(attributeValue)
         ...
         ...
     }
     }
Line 125: Line 147:
The syntax for <tt>fieldType</tt> depends of the field type.  For the more complex types the field definition needs additional information to be provided, which is given inside parentheses following the type name.
The syntax for <tt>fieldType</tt> depends of the field type.  For the more complex types the field definition needs additional information to be provided, which is given inside parentheses following the type name.


<blockquote>
=== Basic types: octet, boolean, numerics, and string ===
 
=== Numeric types, octet, and string ===


The following field types have no arguments: <tt>bool</tt>, <tt>int16</tt>, <tt>uint16</tt>, <tt>int32</tt>, <tt>uint32</tt>, <tt>int64</tt>, <tt>uint54</tt>, <tt>float32</tt>, <tt>float64</tt>, <tt>octet</tt>, and <tt>string</tt>.
The following field types have no arguments:
<tt>octet</tt>, <tt>bool</tt>, <tt>int16</tt>, <tt>int32</tt>, <tt>int64</tt>,
<tt>float32</tt>, <tt>float64</tt>, and <tt>string</tt>.


Examples:  
Examples:  
Line 137: Line 159:
=== enum ===
=== enum ===


An <tt>enum</tt> field needs no arguments after the type name, but internally it does have an implicit definition:
An <tt>enum</tt> field takes one argument after the type name:
     struct() {
 
        field(index,int16)
     enum(fieldName)
        field(choice,array(string[])
 
     }
where fieldName is the name of another field in the same record that must be of type <tt>array(string[])</tt>.  The values in this other field at runtime define the available choice strings for the enum field.
 
Examples:
 
    field(choices, array(string[])
     field(value, enum(choices))


=== menu ===
=== menu ===
Line 155: Line 182:
=== struct ===
=== struct ===


A <tt>struct</tt> field has the definition:
A <tt>struct</tt> field is declared using the type name
     struct(structName)
     struct(structName)


where <tt>structName</tt> is the name of a struct which must have been previously defined.
where <tt>structName</tt> is the name of a struct which must have been previously defined.


Example:
Example:
       struct(point) {
       struct(Point) {
           field(x, float64)
           field(x,float64)
           field(y, float64)
           field(y,float64)
           field(z, float64)
           field(z,float64)
       }
       }
       ...
       ...
       record(haspoint) extends iocRecord {
       record(haspoint) extends RecordCommon {
           ...
           ...
           field(point, struct(point))
           field(point, struct(point))
Line 174: Line 202:
=== array ===
=== array ===


An array has one of the following definitions:
An array field uses definitions like these:
; array(arrayType>[capacity])
: 1-dimensional array/vector
; array(arrayType[capacityX, capacityY, ...])
: multi-dimensional array
; array(arrayType)
: arbitrary dimensional array


* <tt>arrayType</tt> may be any fieldType except <tt>device</tt> or <tt>array</tt>, or may be omitted completely in which case the data type stored is determined by record instance.  '''Q: If the record instance defines the type, is it limited further in what types it can pick?'''
; 1-dimensional array
* <tt>capacity</tt> is the array's size in each dimension, and must be specified for all dimensions or for none.  If not specified by the record type, the record instance determines an array's dimensionality and capacities.
: <tt>array(arrayType[capacity])</tt>
; multi-dimensional array
: <tt>array(arrayType[capacityX, capacityY, ...])</tt>
; arbitrarily dimensioned array
: <tt>array(arrayType)</tt>


Examples:
; 1-dimensional array of unknown size
    field(VAL1D,array(float64[])) #1d array with arbitrary capacity
: <tt>array(arrayType[])</tt>
    field(VAL2D,array(float64[,])) #2d array with arbitrary capacities
; 3-dimensional array of unknown size
    field(anyTypeAnyD,array()) #arbitrary type,number of dimensions, and capacities
: <tt>array(arrayType[,,])</tt>


=== private ===
; 1-dimensional array of unknown type
: <tt>array([capacity])</tt>
; multi-dimensional array of unknown type
: <tt>array([capacityX, capacityY, ...])</tt>
; arbitrarily dimensioned array of unknown type
: <tt>array()</tt>


This is to allow "private" fields, i.e. fields not meant for use by database or channel access. The syntax is:
; 1-dimensional array of unknown type or size
    private("typename")
: <tt>array([])</tt>
where <tt>typename</tt> is a valid C typename.
; 2-dimensional array of unknown type or size
: <tt>array([,])</tt>


Example:
* <tt>arrayType</tt> may be any fieldType except <tt>array</tt>, or may be omitted completely in which case the data type stored is determined by record instance.  If the record instance defines the type, it can only be one of the types listed above under [[#Basic types: boolean, numerics, octet, and string|Basic types]]
    field(asp, private("void *"))
* <tt>capacity</tt> is the array's size in the relevent dimension, and must be specified for all dimensions or for none.  If not specified by the record type, the record instance determines an array's dimensionality and size.


The typename must ''not'' include a field name; the member name in the generated include file is taken from the field definition, and will be appended to the typename provided.  This may require that a typedef be added if a suitable one does not already exist.  '''WHERE DO WE FIND THE TYPE DEFINITION?'''
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


=== link and device ===
=== link ===


These field types that can get or put data from/to some source outside of the record. Link fields replace the DBF_INLINK and DBF_OUTLINK fields from EPICS V3, other than INP or OUT which were special.  A device field replaces the INP or OUT and DTYP fields from EPICS V3.
This field type can get or put data from/to some source outside of the record.
Link fields replace the DBF_INLINK, DBF_OUTLINK, and DTYP fields from EPICS 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, but with device support via an interface that can be different for different record types.
A link field's choices come from link definitions - see the [[#link]] section below for more details.
A link can be a link to another database record, to hardware device support,
or something else.


The syntax is:
The syntax is:
    link(linkDirection)
 
     device(linkDirection,deviceInterface)
     link
where
<tt>linkDirection</tt> is <tt>null</tt>, <tt>in</tt>, <tt>out</tt>, <tt>fwd</tt>, or <tt>inout</tt>. If <tt>null</tt> or <tt>inout</tt> the direction is determined by the <tt>link</tt> or <tt>device</tt> a record instance selects.


Examples:
Examples:
     field(disableLink,link(in))
     field(disableLink,link)
     field(flnk,link(fwd))
     field(process, link)
     field(inp,device(in,digitalIO))
     field(inp,link)
 
</blockquote>


== fieldAttribute ==
== fieldAttribute ==


Each field definition has various associated attributes, which look like this:
Each field definition has several associated attributes, the values of which are set like this:


     default("fieldValue")
     default("fieldValue")
    prompt("promptString")
    group("promptGroup")
     readonly(yesNo)
     readonly(yesNo)
     design(yesNo)
     design(yesNo)
     special(yesNo)
     special(yesNo)
    dynamic(yesNo)
     asl(securityLevel)
     asl(securityLevel)
    link(yesNo)
'''Marty thinks we should get rid of these two:'''
    prompt("promptString")
    group("promptGroup")
'''I am thinking about combining readonly and design into a single attribute called access, which takes one of four choices: design (the default), runtime, readonly, or none.'''


The attribute arguments have the following meanings:
The attribute parameter values have the following meanings:


; <tt>default("fieldValue")</tt>
; <tt>default("fieldValue")</tt>
: Default value for an instance of this field, using the [[V4 DBD Record Instance Syntax|record instance value syntax]].  If a default is not specified, the field will initialize to all zero bits.
: Default value for an instance of this field, using the [[V4 DB Record Instance Syntax|record instance value syntax]].  If a default is not specified, the field will initialize to all zero bits.
: If the field is itself a structure, the default value for the instance of the whole structure can override default values declared for individual fields inside that structure.  This can occur at multiple levels.
: If the field is itself a structure, the default value for the instance of the whole structure can override default values declared for individual fields inside that structure.  This can occur at multiple levels.
; <tt>prompt("promptString")</tt>
: A description of this field for the database designer, this string will be displayed by a Database Configuration Tool.  Empty if not specified.  Not used within the IOC.
; <tt>group("promptGroup")</tt>
: A name that can be used by a Database Configuration Tool to group similar or related fields together.  Empty if not specified.  Not used within the IOC.


; <tt>readonly(yesNo)</tt>
; <tt>readonly(yesNo)</tt>
: Can this field be modified via channel access or database links?  Takes the value No if not specified.
: Can this field be modified via channel access or database links?  Takes the value No if not specified.
: '''Q: Is this really an attribute of the view?'''  No, this controls all access to the field, but a view may declare some fields/properties to be readonly that are modifyable through other views.


; <tt>design(yesNo)</tt>
; <tt>design(yesNo)</tt>
Line 254: Line 285:
; <tt>special(yesNo)</tt>
; <tt>special(yesNo)</tt>
: Does the record have to take special action if the field is modified?  If this is Yes, the record types special processing will be invoked to actually change the field value, which will allow it to perform value checks or additional processing.  Takes the value No if not specified.
: Does the record have to take special action if the field is modified?  If this is Yes, the record types special processing will be invoked to actually change the field value, which will allow it to perform value checks or additional processing.  Takes the value No if not specified.
; <tt>dynamic(yesNo)</tt>
: Can the field change as a result of record processing?  If Yes, then changes will be posted to channel access automatically.  If No, only DB or CA puts can change the field, and these post monitors automatically.


; <tt>asl(securityLevel)</tt>
; <tt>asl(securityLevel)</tt>
: Channel Access security level for this field, 0 or 1.  Takes the value 1 if not specified.
: Channel Access security level for this field, 0 or 1.  Takes the value 1 if not specified.
: '''Q: Is this really an attribute of the view?'''  Not sure, it might be an attribute of both - this entry provides the ASL for the standard field view, other views may need to change it.


; <tt>link</tt>
: This is only valid for string fields. It signifies the the field is the name of an external record. This is for use by Database Configuration Tools.
''These attributes may disappear, see comment above:''
; <tt>prompt("promptString")</tt>
: A description of this field for the database designer, this string will be displayed by a Database Configuration Tool.  Empty if not specified.  Not used within the IOC.
; <tt>group("promptGroup")</tt>
: A name that can be used by a Database Configuration Tool to group similar or related fields together.  Empty if not specified.  Not used within the IOC.


== Views of a record ==
== view ==


There needs to be more than one way to look at a record remotely (via Channel Access).  Often we just want to get its value field and some metadata associated with that value, but there may be more than one value field which shares metadata with othersTherefore we can't do metadata using structures.
There needs to be more than one way to look at a record remotely (via Channel Access or some other similar network protocol).  Often we just want to get the contents of the value field and some metadata associated with that value, but there are often several fields which can share metadata - engineering units for exampleWe can't do metadata using structures because that would mean replicating this metadata, so we add a level of indirection to allow us to group fields together.


A view of a record provides a mapping between some of the record's fields and a Data Access property catalog that can be reached using Channel Access.  All records have a view named "field" that provides direct access to the individual public fields of the record, with no metadata.  Record types can declare additional views and define which fields appear under which property names.
A view of a record provides a hierarchical mapping of some of the record's fields from a named Data Access property catalog that can be reached using Channel Access.  Records automatically get a view named "field" that provides direct access to the individual public fields of the record, with no metadata.  Beyond that, record types can declare additional hierarchical views and define the fields that appear in them inside the DBD file.  The first view defined for a record type is used as its default view (if no views are defined, the field view will become the default view; view parameters may not be permitted).


A view looks like this:
A simple view looks like this:


  view(viewName) {
  view(viewName) {
     property(propName, fieldName)
     property(propName) {
        property(propName, fieldPath)
        ...
    }
    property(propName, fieldPath)
     ...
     ...
  }
  }
Line 280: Line 321:
; <tt>propName</tt>
; <tt>propName</tt>
: A Data Access property name, which must be a valid C identifier.
: A Data Access property name, which must be a valid C identifier.
; <tt>fieldName</tt>
; <tt>fieldPath</tt>
: The name of a field in this record type. To use a field inside a structure field, give the full path to that field: <tt>controlLimit.upper</tt> for example. If the field named is a structure, a property catalog containing the whole structure will be sent, with property names matching the structure field names.
: The path to a field in this record type. To use a field inside a structure field, give the full path to that field: <tt>controlLimit.upper</tt> for example.
: If <tt>fieldPath</tt> resolves to a structure, a property catalog containing the whole structure will be sent, with property names matching the structure's field names.
: The <tt>fieldPath</tt> may be omitted as long as there is a subordinate property catalog below this property.


Example:
Example:
  record(ao) extends iocRecord {
 
  record(ao) extends RecordCommon {
     field(value, float64) { ... }
     field(value, float64) { ... }
    field(outValue, float64) { ... }
    field(rawValue, int32) { ... }
     field(units, string) { ... }
     field(units, string) { ... }
     field(displayLimit, struct(displayLimit)) { ... }
     field(displayLimit, struct(displayLimit)) { ... }
     view(value) {
    ...
         property(value, value)
     view(value)
        property(timeStamp, time)
         property(value, value) {
        property(alarmSeverity, alarmSeverity)
            property(units, units)
        property(alarmStatus, alarmStatus)
            property(timeStamp, time)
        property(displayLimit, displayLimit)
            property(alarmSeverity, alarmSeverity)
         property(units, units)
            property(alarmStatus, alarmStatus)
            property(displayLimit, displayLimit)
        }
    }
    view(outValue)
         property(value, outValue) {
            property(units, units)
            property(timeStamp, time)
            property(alarmSeverity, alarmSeverity)
            property(alarmStatus, alarmStatus)
        }
     }
     }
     view(outValue) {
     view(rawValue)
         property(value, outValue)
         property(value, rawValue) {
        property(timeStamp, time)
            property(timeStamp, time)
         property(alarmSeverity, alarmSeverity)
         }
        property(alarmStatus, alarmStatus)
        property(units, units)
     }
     }
    ...
  }
  }
<center>
= support =
</center>
A <tt>support</tt> statement describes an implementation of support for a link
or struct field.
Link support can be any of the following:
* A link to another record either local or remote
* A link to hardware support
* Something else.
The syntax for these is:
support(choiceName)
or
support(choiceName,supportStructName)
where
; <tt>choiceName</tt>
: UTF-8 string that describes the choice
; <tt>supportStructName</tt>
: The name of a <tt>struct</tt> containing configuration information for the support. Record support normally does not access this structure. Database configuration tools do prompt the user to assign values to the structure.
When a record instance is created the choiceName
selects the support to attach to a record link.
Examples:
    link(processLink,ProcessLink)
    link(monitorLink,MonitorLink)

Latest revision as of 19:53, 2 November 2005

DBD Statement Syntax November 02 2005


Overview

This document presents the syntax for V4 database definition files.

NOTE This version of the database definition and database instance syntax does not provide:

  1. a direction for links
  2. a way to select a subset of the support definitions

Support can exist for either a link field or a struct field. The support definition is just

   support(choiceName,supportStructName)

When a record instance is created any choiceName can be specified for a link or struct field. If an invalid choice is made, an error will be issued during initialization.

General Statements

include

include "filename"

where

filename
must be a valid filename

The file system search path that will be used to look for the file is determined by the build system, and cannot be modified by the DBD file itself.

Include statements can be used at the top level, or inside the braces of a menu, struct or record definition.

# comment

# anything

Anything on a line after a # character is a comment, and will be ignored. Comments may appear on a line by themselves, or at the end of another statement. They may not appear inside the parentheses belonging to another statement, but they are permitted inside braces. Inside a single- or double- quoted string the # character has no special meaning.


menu

A menu is an enumerated type where the choice strings are defined once for each IOC. Menus are defined like this:

menu(menuName) {
    choice(choiceName, "choiceValue")
    ...
}

where

menuName
Must be a valid, unique C identifier.
choiceName
Must be a valid, unique C identifier. By convention, every choiceName should start with the menuName it belongs to. These names are only available to C/C++ source code using the header file generated from the menu definition; they are not stored in the IOC itself.
choiceValue
Can be any UTF-8 compatible string, which should be unique within the context of this menu.

In general menus should only be definable once, in the DBD file (first definition seen wins in the event of duplicates, give a warning for duplicates and error if subsequent definition is different). However we may want to include a syntax that allows specific menu definitions to be extended at database load time.

Example:

menu(menuScan) {
    choice(menuScanPassive, "Passive")
    choice(menuScanEvent, "Event")
    choice(menuScanInterrupt, "Interrupt")
    choice(menuScan10second, "10 second")
    choice(menuScan5second, "5 second")
    choice(menuScan2second, "2 second")
    choice(menuScan1second, "1 second")
    choice(menuScan_5second, ".5 second")
    choice(menuScan_2second, ".2 second")
    choice(menuScan_1second, ".1 second")
}

Structures, Record types, Fields and Views

Structures and record types have significant commonality in that they both define a data structure type containing fields. The main difference is that you can't create or populate an instance of a structure outside of a record; only records can appear at the very top level. Record types also define views of the record, which is not possible for a structure.

struct

A structure is defined as follows:

struct(name) {
    field(fieldName, fieldType) {
        fieldAttribute(attributeValue)
        ...
    }
    ...
}

where

name
The structure name must be a valid, unique C identifier.
fieldName
Must be a valid C identifier, unique within the context of this particular structure.
fieldType
See fieldType below.
fieldAttribute and attributeValue
See fieldAttribute below.

record

A record type is defined as follows:

include "dbCommon.dbd"
record(name) extends RecordCommon {
    field(fieldName, fieldType) {
        fieldAttribute(attributeValue)
        ...
    }
    ...
    view(viewName) {
        property(propName, fieldPath)
        ...
    }
    ...
}
name
The record type name. It must be a valid, unique C identifier.
extends RecordCommon
This states that the record type extends the set of fields defined in "V4 DB RecordCommon". It should be permissable to name other record types instead of RecordCommon here, as long as the inheritance tree starts at RecordCommon. Inheritance from multiple record types is not supported; you can only have one extends phrase.
fieldName
Must be a valid C identifier, unique within the context of this particular record type and its parents (extends ...).
fieldType
See fieldType below.
fieldAttribute and attributeValue
See fieldAttribute below.
viewName, propName and fieldPath
See Views of a record below.

fieldType

Both struct and record define a field as:

    field(fieldName, fieldType) {
        fieldAttribute(attributeValue)
        ...
    }

The syntax for fieldType depends of the field type. For the more complex types the field definition needs additional information to be provided, which is given inside parentheses following the type name.

Basic types: octet, boolean, numerics, and string

The following field types have no arguments: octet, bool, int16, int32, int64, float32, float64, and string.

Examples:

    field(description,string)
    field(value,float64)

enum

An enum field takes one argument after the type name:

    enum(fieldName)

where fieldName is the name of another field in the same record that must be of type array(string[]). The values in this other field at runtime define the available choice strings for the enum field.

Examples:

    field(choices, array(string[])
    field(value, enum(choices))

menu

A menu field is defined like this:

    menu(menuName)

where menuName is the name of the menu.

Example:

    field(scan, menu(menuScan))

struct

A struct field is declared using the type name

    struct(structName)

where structName is the name of a struct which must have been previously defined.


Example:

     struct(Point) {
         field(x,float64)
         field(y,float64)
         field(z,float64)
      }
      ...
      record(haspoint) extends RecordCommon {
          ...
          field(point, struct(point))
      }

array

An array field uses definitions like these:

1-dimensional array
array(arrayType[capacity])
multi-dimensional array
array(arrayType[capacityX, capacityY, ...])
arbitrarily dimensioned array
array(arrayType)
1-dimensional array of unknown size
array(arrayType[])
3-dimensional array of unknown size
array(arrayType[,,])
1-dimensional array of unknown type
array([capacity])
multi-dimensional array of unknown type
array([capacityX, capacityY, ...])
arbitrarily dimensioned array of unknown type
array()
1-dimensional array of unknown type or size
array([])
2-dimensional array of unknown type or size
array([,])
  • arrayType may be any fieldType except array, or may be omitted completely in which case the data type stored is determined by record instance. If the record instance defines the type, it can only be one of the types listed above under Basic types
  • capacity is the array's size in the relevent dimension, and must be specified for all dimensions or for none. If not specified by the record type, the record instance determines an array's dimensionality and size.

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

link

This field type can get or put data from/to some source outside of the record. Link fields replace the DBF_INLINK, DBF_OUTLINK, and DTYP fields from EPICS V3.

A link field's choices come from link definitions - see the #link section below for more details. A link can be a link to another database record, to hardware device support, or something else.

The syntax is:

    link

Examples:

    field(disableLink,link)
    field(process, link)
    field(inp,link)

fieldAttribute

Each field definition has several associated attributes, the values of which are set like this:

    default("fieldValue")
    readonly(yesNo)
    design(yesNo)
    special(yesNo)
    asl(securityLevel)
    link(yesNo)

Marty thinks we should get rid of these two:

    prompt("promptString")
    group("promptGroup")

I am thinking about combining readonly and design into a single attribute called access, which takes one of four choices: design (the default), runtime, readonly, or none.

The attribute parameter values have the following meanings:

default("fieldValue")
Default value for an instance of this field, using the record instance value syntax. If a default is not specified, the field will initialize to all zero bits.
If the field is itself a structure, the default value for the instance of the whole structure can override default values declared for individual fields inside that structure. This can occur at multiple levels.
readonly(yesNo)
Can this field be modified via channel access or database links? Takes the value No if not specified.
design(yesNo)
Should a Database Configuration Tool allow the field to be configured at design time? If No, values for the field cannot be set when loading record instance data at startup. Takes the value Yes if not specified.
special(yesNo)
Does the record have to take special action if the field is modified? If this is Yes, the record types special processing will be invoked to actually change the field value, which will allow it to perform value checks or additional processing. Takes the value No if not specified.
asl(securityLevel)
Channel Access security level for this field, 0 or 1. Takes the value 1 if not specified.
link
This is only valid for string fields. It signifies the the field is the name of an external record. This is for use by Database Configuration Tools.

These attributes may disappear, see comment above:

prompt("promptString")
A description of this field for the database designer, this string will be displayed by a Database Configuration Tool. Empty if not specified. Not used within the IOC.
group("promptGroup")
A name that can be used by a Database Configuration Tool to group similar or related fields together. Empty if not specified. Not used within the IOC.

view

There needs to be more than one way to look at a record remotely (via Channel Access or some other similar network protocol). Often we just want to get the contents of the value field and some metadata associated with that value, but there are often several fields which can share metadata - engineering units for example. We can't do metadata using structures because that would mean replicating this metadata, so we add a level of indirection to allow us to group fields together.

A view of a record provides a hierarchical mapping of some of the record's fields from a named Data Access property catalog that can be reached using Channel Access. Records automatically get a view named "field" that provides direct access to the individual public fields of the record, with no metadata. Beyond that, record types can declare additional hierarchical views and define the fields that appear in them inside the DBD file. The first view defined for a record type is used as its default view (if no views are defined, the field view will become the default view; view parameters may not be permitted).

A simple view looks like this:

view(viewName) {
    property(propName) {
        property(propName, fieldPath)
        ...
    }
    property(propName, fieldPath)
    ...
}
viewName
The view name must be a valid C identifier, which must be unique in the context of the particular record type.
propName
A Data Access property name, which must be a valid C identifier.
fieldPath
The path to a field in this record type. To use a field inside a structure field, give the full path to that field: controlLimit.upper for example.
If fieldPath resolves to a structure, a property catalog containing the whole structure will be sent, with property names matching the structure's field names.
The fieldPath may be omitted as long as there is a subordinate property catalog below this property.

Example:

record(ao) extends RecordCommon {
    field(value, float64) { ... }
    field(outValue, float64) { ... }
    field(rawValue, int32) { ... }
    field(units, string) { ... }
    field(displayLimit, struct(displayLimit)) { ... }
    ...
    view(value)
        property(value, value) {
            property(units, units)
            property(timeStamp, time)
            property(alarmSeverity, alarmSeverity)
            property(alarmStatus, alarmStatus)
            property(displayLimit, displayLimit)
        }
    }
    view(outValue)
        property(value, outValue) {
            property(units, units)
            property(timeStamp, time)
            property(alarmSeverity, alarmSeverity)
            property(alarmStatus, alarmStatus)
        }
    }
    view(rawValue)
        property(value, rawValue) {
            property(timeStamp, time)
        }
    }
    ...
}

support

A support statement describes an implementation of support for a link or struct field. Link support can be any of the following:

  • A link to another record either local or remote
  • A link to hardware support
  • Something else.

The syntax for these is:

support(choiceName)

or

support(choiceName,supportStructName)

where

choiceName
UTF-8 string that describes the choice
supportStructName
The name of a struct containing configuration information for the support. Record support normally does not access this structure. Database configuration tools do prompt the user to assign values to the structure.

When a record instance is created the choiceName selects the support to attach to a record link.

Examples:

    link(processLink,ProcessLink)
    link(monitorLink,MonitorLink)