<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki-ext.aps.anl.gov/epics/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=MartyKraimer</id>
	<title>EPICSWIKI - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-ext.aps.anl.gov/epics/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=MartyKraimer"/>
	<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=Special:Contributions/MartyKraimer"/>
	<updated>2026-06-04T00:03:26Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.36.1</generator>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=Ancient_V4_Design&amp;diff=1482</id>
		<title>Ancient V4 Design</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=Ancient_V4_Design&amp;diff=1482"/>
		<updated>2006-02-07T11:48:45Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page links to various documents for discussion by the EPICS core developers.&lt;br /&gt;
&lt;br /&gt;
'''Code to implement this stuff doesn't exist yet, and the designs may change!'''&lt;br /&gt;
&lt;br /&gt;
''Note to authors: please use 'V4' at the start of page names for Version 4 documentation, as this makes it clear which wiki pages refer to the new designs just from the page name.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Overall Design ==&lt;br /&gt;
&lt;br /&gt;
* [[V4 Use Cases]] - Bob Dalesio, Kay Kasemir&lt;br /&gt;
&lt;br /&gt;
== Core and Database ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Marty Kraimer is currently working on a Java IOC. He is no longer updating any material in this section.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* [[V4 Modules and Interfaces]] - Andrew Johnson&lt;br /&gt;
&lt;br /&gt;
* [[V4 Requirements for Standard Types]] - Andrew Johnson&lt;br /&gt;
* [[V4 Standard Properties and Events]] - Andrew Johnson&lt;br /&gt;
&lt;br /&gt;
* V4 Database Definition - Marty Kraimer, Andrew Johnson&lt;br /&gt;
** [[V4 DBD Statement Syntax]] - Marty Kraimer, Andrew Johnson&lt;br /&gt;
** [[V4 DB Record Instance Syntax]] - Andrew Johnson&lt;br /&gt;
** [[V4 DB RecordCommon]] - Marty Kraimer&lt;br /&gt;
** [[V4 DBD Examples]] - Marty Kraimer, Andrew Johnson&lt;br /&gt;
** [[V4 Link Support Tutorial]] - Marty Kraimer&lt;br /&gt;
** [[V4 View Generated Code]] - Andrew Johnson&lt;br /&gt;
&lt;br /&gt;
* V4 Database Runtime&lt;br /&gt;
** [[V4 Design: Record Processing]] - Marty Kraimer&lt;br /&gt;
** [[V4 Design: dbdInterfaces]] - Marty Kraimer&lt;br /&gt;
** [[V4 Design: Runtime Interfaces]] - Marty Kraimer&lt;br /&gt;
** [[V4 Design: RecordCommon Support]] - Marty Kraimer&lt;br /&gt;
&lt;br /&gt;
* V4 Database Access:&lt;br /&gt;
** [[V4 Design: epicsTypes]] - Marty Kraimer, Andrew Johnson&lt;br /&gt;
** [[V4 Design: Assembling Record Support]] - Ben Franksen&lt;br /&gt;
** [[V4 Design: driverInterfaces]] - Marty Kraimer&lt;br /&gt;
&lt;br /&gt;
* [[V4 User-defined fields]] - Kay Kasemir&lt;br /&gt;
&lt;br /&gt;
* [[V4 Server Side Plugins]] - Ralph Lange, Benjamin Franksen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Network Communications ==&lt;br /&gt;
&lt;br /&gt;
* [[V4 CA Interfaces]] - Jeff Hill&lt;br /&gt;
* [[V4 CA Protocol Specification]] - Jeff Hill&lt;br /&gt;
&lt;br /&gt;
* [[V4 Name Server]] - Doug Murray, Kay Kasemir&lt;br /&gt;
* [[V4 CA Client User Interface]] - Doug Murray, Kay Kasemir&lt;br /&gt;
* [[V4 Data Interface]] - Kay Kasemir&lt;br /&gt;
* [[V4 CA example timeStamp, sevr, status, data]] - Marty Kraimer&lt;br /&gt;
&lt;br /&gt;
== Other Services ==&lt;br /&gt;
&lt;br /&gt;
* [[V4 Replacement for drvTS]] - Timo Korhonen&lt;br /&gt;
* [[V4 Replacement for SNL]] - Ben Franksen, Go&amp;quot;tz Pfeiffer&lt;br /&gt;
* [[V4 Data Store]] - Ralph Lange&lt;br /&gt;
&lt;br /&gt;
== Obselete pages ==&lt;br /&gt;
&lt;br /&gt;
* [[V4 July Meeting Agenda]]&lt;br /&gt;
&lt;br /&gt;
* [[V4 DBD dbCommon and iocRecord]] - Marty Kraimer&lt;br /&gt;
* [[V4 DBD Generated Code]] - Marty Kraimer&lt;br /&gt;
* [[V4 Design: dbdClass]] - Marty Kraimer&lt;br /&gt;
* [[V4 Design: dbdClass Examples]] - Marty Kraimer&lt;br /&gt;
* [[V4 Design: Database Initialization]] - Marty Kraimer&lt;br /&gt;
* [[V4 Design: Database Access Semantics]] - Marty Kraimer&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_dbdInterfaces&amp;diff=2736</id>
		<title>V4 Design: dbdInterfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_dbdInterfaces&amp;diff=2736"/>
		<updated>2005-11-04T15:25:13Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: dbdInterfaces - IOC Database Description November 04 2005 &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes  definitions for code that accessses&lt;br /&gt;
IOC records, i.e. the records created from Database Definitions:&lt;br /&gt;
menu, struct, record, link, device, and record instances.&lt;br /&gt;
&lt;br /&gt;
The interfaces support introspection of everything created from Database&lt;br /&gt;
Definitions. The interfaces can be used by tools such as VDCT or on&lt;br /&gt;
a running IOC database.&lt;br /&gt;
&lt;br /&gt;
The definitions can be used by support code, e.g. record support,&lt;br /&gt;
or by code that uses only introspection.&lt;br /&gt;
&lt;br /&gt;
Code is automatically generated from the following definitions:&lt;br /&gt;
* &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; - Used by record support.&lt;br /&gt;
* &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; - Used by code that understands the struct.&lt;br /&gt;
* &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt; - Used by code that understands the menu.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Syntax =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax is defined so that either C++ and Java implementations can be created.&lt;br /&gt;
&lt;br /&gt;
NOTE: Most of the code fragments use Java syntax.&lt;br /&gt;
&lt;br /&gt;
== Primitive Types ==&lt;br /&gt;
* octet - 8 bit byte&lt;br /&gt;
* boolean - a value that takes the values &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt;&lt;br /&gt;
* int16 - 16 bit signed integer&lt;br /&gt;
* int32 - 32 bit signed integer&lt;br /&gt;
* int64 - 64 bit signed integer&lt;br /&gt;
* float32 - 32 bit IEEE float&lt;br /&gt;
* float64 - 64 bit IEEE float&lt;br /&gt;
&lt;br /&gt;
In Java these types become:&lt;br /&gt;
&lt;br /&gt;
* octet =&amp;gt; byte  BUT no arithmetic is implied&lt;br /&gt;
* boolean =&amp;gt; boolean&lt;br /&gt;
* int16 =&amp;gt; short&lt;br /&gt;
* int32 =&amp;gt; int&lt;br /&gt;
* int64 =&amp;gt; long&lt;br /&gt;
* float32 =&amp;gt; float&lt;br /&gt;
* float64 =&amp;gt; double&lt;br /&gt;
&lt;br /&gt;
In C++ these types become:&lt;br /&gt;
&lt;br /&gt;
* octet =&amp;gt; char  BUT no arithmetic is implied&lt;br /&gt;
* boolean =&amp;gt; bool BUT no arithmetic or conversion to/from int is implied&lt;br /&gt;
* int16 =&amp;gt; int16_t&lt;br /&gt;
* int32 =&amp;gt; int32_t&lt;br /&gt;
* int64 =&amp;gt; int64_t&lt;br /&gt;
* float32 =&amp;gt; float&lt;br /&gt;
* float64 =&amp;gt; double&lt;br /&gt;
&lt;br /&gt;
NOTE:&lt;br /&gt;
* The C++ integer types are from C99 stdint.h&lt;br /&gt;
* Should exceptions be defined?&lt;br /&gt;
&lt;br /&gt;
== enum, struct, interface, class,  string, array ==&lt;br /&gt;
&lt;br /&gt;
In adition to the primitive types the syntax&lt;br /&gt;
uses the terms enum, struct, interface, and array.&lt;br /&gt;
&lt;br /&gt;
=== enum ===&lt;br /&gt;
&lt;br /&gt;
An example of an enum is:&lt;br /&gt;
&lt;br /&gt;
     enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The C++  definition is identical. In Java 5 the definition would be:&lt;br /&gt;
&lt;br /&gt;
     public enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
=== struct ===&lt;br /&gt;
An example of a struct definition is:&lt;br /&gt;
&lt;br /&gt;
     struct DisplayLimitData {&lt;br /&gt;
         float64 low;&lt;br /&gt;
         float64 high;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In C++ this would be:&lt;br /&gt;
&lt;br /&gt;
    class DisplayLimitData {&lt;br /&gt;
    public:&lt;br /&gt;
         double low;&lt;br /&gt;
         double high;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
In Java this would be:&lt;br /&gt;
&lt;br /&gt;
     class DisplayLimitData {&lt;br /&gt;
         public double low;&lt;br /&gt;
         public double high;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== interface ===&lt;br /&gt;
An example of an interface definition is:&lt;br /&gt;
&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void    put(boolean val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class DbfBoolean : public Dbf {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual bool get() = 0;&lt;br /&gt;
         virtual void put(bool val) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
In Java would be:&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void    put(boolean val)&lt;br /&gt;
     }&lt;br /&gt;
=== class ===&lt;br /&gt;
&lt;br /&gt;
Any class definitions are language specific.&lt;br /&gt;
&lt;br /&gt;
=== string ===&lt;br /&gt;
&lt;br /&gt;
For C++ a string will be a &amp;lt;tt&amp;gt;char *&amp;lt;/tt&amp;gt; array containing UTF-8&lt;br /&gt;
compatible characters not necessarily terminated with a null character.&lt;br /&gt;
Wherever a &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt; argument appears, the C++ definition&lt;br /&gt;
will have &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;char *&amp;lt;/tt&amp;gt; arguments.&lt;br /&gt;
&lt;br /&gt;
For Java string will just be a &amp;lt;tt&amp;gt;String&amp;lt;/tt&amp;gt;.&lt;br /&gt;
It is assumed that Java Strings will be converted to/from UTF-8 byte streams&lt;br /&gt;
when the data is transfered to/from the network.&lt;br /&gt;
&lt;br /&gt;
If a string is being passed to a method the syntax is:&lt;br /&gt;
     void put(string value);&lt;br /&gt;
In C++ this becomes&lt;br /&gt;
     void put(int valueLength, char *value);&lt;br /&gt;
In Java it becomes&lt;br /&gt;
     void put(String value);&lt;br /&gt;
&lt;br /&gt;
If a method is returning a string the syntax is&lt;br /&gt;
     string get();&lt;br /&gt;
In C++ this becomes&lt;br /&gt;
     int getValueLength();&lt;br /&gt;
     int get(int valueLength, char *value);&lt;br /&gt;
     // valueLength is number of octets in value&lt;br /&gt;
     // return value is the number of octets written&lt;br /&gt;
In Java it becomes&lt;br /&gt;
     String get();&lt;br /&gt;
=== array ===&lt;br /&gt;
&lt;br /&gt;
An example of a definition that includes an array is:&lt;br /&gt;
&lt;br /&gt;
     void get(float64[] data);&lt;br /&gt;
&lt;br /&gt;
In C++ this would become:&lt;br /&gt;
&lt;br /&gt;
     void get(int lenData, double data[]);&lt;br /&gt;
&lt;br /&gt;
In Java this would be:&lt;br /&gt;
&lt;br /&gt;
     void get(double[] data);&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= DbfTypes =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
The following naming conventions are used:&lt;br /&gt;
; Dbf&lt;br /&gt;
: any class starting with Dbf describes a field in a header file generated from a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definition. For example DbfArray describes a field generated from &amp;lt;tt&amp;gt;field(name,array(float64[])&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; Dbd&lt;br /&gt;
: A class name starting with Dbd describes something related to dbd definitions. For example DbdMenu describes a dbd menu definition.&lt;br /&gt;
&lt;br /&gt;
All Dbf and Dbd definitions are interfaces. Thus all access to data is via&lt;br /&gt;
interfaces.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbfTypes.h&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
The following &amp;lt;tt&amp;gt;enum&amp;lt;/tt&amp;gt; definitions describe &lt;br /&gt;
each field in the header files generated from DBD &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; and&lt;br /&gt;
&amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
&lt;br /&gt;
     enum BasicType {&lt;br /&gt;
         basicTypeOctet,    // DbfOctet&lt;br /&gt;
         basicTypeBoolean,  // DbfBoolean&lt;br /&gt;
         basicTypeInt16,    // DbfInt16&lt;br /&gt;
         basicTypeInt32,    // DbfInt32&lt;br /&gt;
         basicTypeInt64,    // DbfInt64&lt;br /&gt;
         basicTypeFloat32,  // DbfFloat32&lt;br /&gt;
         basicTypeFloat64,  // DbfFloat64&lt;br /&gt;
         basicTypeString,   // DbfString&lt;br /&gt;
         basicTypeArray,    // DbfArray&lt;br /&gt;
         basicTypeStruct,   // DbfStruct&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum DbfType {&lt;br /&gt;
         dbfTypeBasic,       // DbfOctet,...,DbfStruct&lt;br /&gt;
         dbfTypeMenu,        // DbfMenu&lt;br /&gt;
         dbfTypeEnum,        // DbfEnum&lt;br /&gt;
         dbfTypeLink,        // DbfLink&lt;br /&gt;
         dbfTypeMDArray,     // DbfMDArray&lt;br /&gt;
         dbfTypeTimeStamp    // DbfTimeStamp&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Database Fields =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each database field is accessed via an interface which all extend&lt;br /&gt;
the following interface:&lt;br /&gt;
&lt;br /&gt;
     interface Dbf{&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         boolean isPrimitive(); // BasicTypeBoolean,...,BasicTypeFloat64&lt;br /&gt;
         boolean isBasic();&lt;br /&gt;
         BasicType getBasicType();&lt;br /&gt;
         RecordInstance getRecord();&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The interfaces are designed so that a field can be accessded&lt;br /&gt;
without exposing the address of its data.&lt;br /&gt;
&lt;br /&gt;
== Primitive Types ==&lt;br /&gt;
&lt;br /&gt;
DbfOctet, ..., DbfFloat64 are all interfaces with methods get and put.&lt;br /&gt;
    &lt;br /&gt;
     interface DbfOctet extends Dbf {&lt;br /&gt;
         octet get();&lt;br /&gt;
         void put(octet val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void put(boolean val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt16 extends Dbf {&lt;br /&gt;
         int16 get();&lt;br /&gt;
         void put(int16 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt32 extends Dbf {&lt;br /&gt;
         int32 get();&lt;br /&gt;
         void put(int32 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt64 extends Dbf {&lt;br /&gt;
         int64 get();&lt;br /&gt;
         void put(int64 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfFloat32 extends Dbf {&lt;br /&gt;
         float32 get();&lt;br /&gt;
         void put(float32 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfFloat64 extends Dbf {&lt;br /&gt;
         float64 get();&lt;br /&gt;
         void put(float64 val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Record support code can access such fields via the generated header&lt;br /&gt;
file. Some examples are:&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     ...&lt;br /&gt;
     precord.ffloat.put(10.0);&lt;br /&gt;
     ...&lt;br /&gt;
     short myint = record.fint.get();&lt;br /&gt;
&lt;br /&gt;
Code that does not include the generated header file can access these fields&lt;br /&gt;
via the introspection interfaces described later in this document.&lt;br /&gt;
For example code that expects a float64 field can access it via&lt;br /&gt;
&lt;br /&gt;
     Dbf dbf =  RecordInstanceLocate.getField(&amp;quot;recordname.value&amp;quot;);&lt;br /&gt;
     if(dbf==null&lt;br /&gt;
     || !dbf.isPrimitive()&lt;br /&gt;
     || (dbf.getBasicType() != basicTypeFloat64) ) // do something&lt;br /&gt;
     DbfFloat64 dbfdouble = (DbfFloat64)dbf;&lt;br /&gt;
     dbfdouble.put(10.0);&lt;br /&gt;
&lt;br /&gt;
or more concisely (but exception may be thrown)&lt;br /&gt;
     DbfConvertPrimitive(RecordInstanceLocate.getField(&amp;quot;recordname.value&amp;quot;),10.0);&lt;br /&gt;
&lt;br /&gt;
== String fields ==&lt;br /&gt;
&lt;br /&gt;
The interface for a string field is:&lt;br /&gt;
&lt;br /&gt;
     interface DbfString extends Dbf {&lt;br /&gt;
        string get();&lt;br /&gt;
        void put(string value);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following code prints a string.&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     String string = record.fstring.get();&lt;br /&gt;
     printf(&amp;quot;%s\n&amp;quot;,string);&lt;br /&gt;
or more concisely&lt;br /&gt;
     printf(&amp;quot;%s\n&amp;quot;,record.fstring.get());&lt;br /&gt;
&lt;br /&gt;
Code that does not include the header file can use the introspection methods&lt;br /&gt;
to locate the DbfString that provides access to the field.&lt;br /&gt;
&lt;br /&gt;
== Structure Fields ==&lt;br /&gt;
&lt;br /&gt;
     interface DbfStruct extends Dbf {&lt;br /&gt;
         int16 getNfields();&lt;br /&gt;
         Dbf getInterface(int16 index);&lt;br /&gt;
         DbdField getDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following traverses the fields of a DbfStruct&lt;br /&gt;
&lt;br /&gt;
     DbfStruct dbfStruct;&lt;br /&gt;
     &lt;br /&gt;
     for(i=0; i &amp;lt; dbfStruct.getNfields(); i++) {&lt;br /&gt;
         DbdField dbdField = dbfStruct.getDescription[i];&lt;br /&gt;
         String name = dbdField.getName();&lt;br /&gt;
         printf(&amp;quot;field %s\n&amp;quot;,name);&lt;br /&gt;
         // or just&lt;br /&gt;
         printf(&amp;quot;field %s\n&amp;quot;,dbfStruct.getDescription[i].dbdField.getName());&lt;br /&gt;
&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Structure fields can only be accessed via introspection.&lt;br /&gt;
However, for each structure, code is generated that does the introspection.&lt;br /&gt;
For example DisplayLimitData can be obtained via the statements:&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     DisplayLimitData limit = new DisplayLimitData();&lt;br /&gt;
     &lt;br /&gt;
     ...&lt;br /&gt;
     DisplayLimitSupport.get(record.displayLimit,limit);&lt;br /&gt;
     printf(&amp;quot;low %f high %f\n&amp;quot;,limit.low,limit.high);&lt;br /&gt;
&lt;br /&gt;
== Array Fields ==&lt;br /&gt;
&lt;br /&gt;
The generated header file will have a type that extends &amp;lt;tt&amp;gt;DbfArray&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     interface DbfArray extends Dbf {&lt;br /&gt;
        DbfType getType();&lt;br /&gt;
        int32 getNelements();&lt;br /&gt;
        void setNelements(int32 len);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfBooleanArray extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, boolean[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, boolean[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfOctetArray extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, octet[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, octet[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt16Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int16[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int16[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt32Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int32[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int32[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt64Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int64[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int64[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfFloat32Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, float32[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, float32[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfFloat64Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, float64[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, float64[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfStringArray extends DbfArray {&lt;br /&gt;
         DbfString getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfArrayArray extends DbfArray {&lt;br /&gt;
         DbfArray getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfStructArray extends DbfArray {&lt;br /&gt;
         DbfStruct getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfMenuArray extends DbfArray {&lt;br /&gt;
         DbfMenu getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfEnumArray extends DbfArray {&lt;br /&gt;
         DbfEnum getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfLinkArray extends DbfArray {&lt;br /&gt;
         DbfLink getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following puts data into a float64 field.&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
&lt;br /&gt;
     double[] data = new double[] {1.0,2.0,3.0};;&lt;br /&gt;
     if(!record.ffloat.isPrimitive()&lt;br /&gt;
     || record.ffloat.getBasicType()!=basicTypeFloat64)  // DO SOMTHING!!!!&lt;br /&gt;
     ...&lt;br /&gt;
     array.put(0,nelements,precord-&amp;gt;data);&lt;br /&gt;
&lt;br /&gt;
or more concisely&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     ...&lt;br /&gt;
     DbfConvertPrimitive.put(precord.array,new double[] {1.0,2.0,3.0});&lt;br /&gt;
For the primitive data types both get and put return an int32,&lt;br /&gt;
which is the number of array elements transfered.&lt;br /&gt;
The caller &amp;lt;b&amp;gt;must&amp;lt;/b&amp;gt; be prepared to make multiple calls&lt;br /&gt;
in order to get or put an entire array.&lt;br /&gt;
&lt;br /&gt;
For example&lt;br /&gt;
     DbfDoubleArray dbfarray;&lt;br /&gt;
     ...&lt;br /&gt;
     double[] data = double [dbfArray.getNelements];&lt;br /&gt;
     int offset=0;&lt;br /&gt;
     int len = data.length;&lt;br /&gt;
     int n;&lt;br /&gt;
     while(offset &amp;lt; len) {&lt;br /&gt;
         n = dbfarray.get(offset,len);&lt;br /&gt;
         if(n==len) break;&lt;br /&gt;
         len -= n;&lt;br /&gt;
         offset += n;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfMDArray ==&lt;br /&gt;
NOT YET DEFINED&lt;br /&gt;
     &lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; is described as:&lt;br /&gt;
     interface DbfMenu extends Dbf {&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
         void putIndex(int16 val);&lt;br /&gt;
         DbdMenu getDbdMenu();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; allows the menu index to be set and retrieved&lt;br /&gt;
and also provides access to the DbdMenu.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; field can be accessed via the generated header file or via&lt;br /&gt;
the introspection methods.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfEnum ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfEnum&amp;lt;/tt&amp;gt; is described as:&lt;br /&gt;
     interface DbfEnum extends Dbf {&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
         void putIndex(int16 val);&lt;br /&gt;
         DbfStringArray getChoiceArray();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfEnum&amp;lt;/tt&amp;gt; allows the enum index to be set and retrieved&lt;br /&gt;
and also provides access to the The DbfArray field that contains the choices.&lt;br /&gt;
&lt;br /&gt;
== DbfLink ==&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;tt&amp;gt;DbfLink&amp;lt;/tt&amp;gt; is described as&lt;br /&gt;
 &lt;br /&gt;
     interface DbfLink extends Dbf {&lt;br /&gt;
         DbdLink getDbdLink();&lt;br /&gt;
         DbfStruct getSupportStruct();&lt;br /&gt;
     }&lt;br /&gt;
Where&lt;br /&gt;
* &amp;lt;tt&amp;gt;getDbdLink&amp;lt;/tt&amp;gt; gets the link definition for the field&lt;br /&gt;
* &amp;lt;tt&amp;gt;getSupportStruct&amp;lt;/tt&amp;gt; get a struct instance for the support structure. Thius is NOT a field in the record but appears like it is.&lt;br /&gt;
&lt;br /&gt;
== DbfTimeStamp ==&lt;br /&gt;
&lt;br /&gt;
     struct TimeStamp {&lt;br /&gt;
         int64 secondsSinceEpoch;&lt;br /&gt;
         int32 nanoSeconds;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfTimeStamp extends Dbf {&lt;br /&gt;
         void get(TimeStamp timeStamp);&lt;br /&gt;
         void put(TimeStamp timeStamp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= DbdStatements =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
These describe everything defined in database definition files.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdMenu&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdMenu {&lt;br /&gt;
         string getName();&lt;br /&gt;
         int16 getNchoices();&lt;br /&gt;
         string getChoice(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdSupport&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdSupport {&lt;br /&gt;
         string getChoiceName();&lt;br /&gt;
         string getSupportStructName(string name);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdStruct&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;DbdRecord&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdAttribute {&lt;br /&gt;
         string getDefault();&lt;br /&gt;
         boolean isReadonly();&lt;br /&gt;
         boolean isDesign();&lt;br /&gt;
         boolean isSpecial();&lt;br /&gt;
         int16 getAsl();&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbdDefaults {}&lt;br /&gt;
    &lt;br /&gt;
     interface DbdArrayDefaults extends DbdDefaults{&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         int32 getLength();&lt;br /&gt;
&lt;br /&gt;
     interface DbdStructDefaults extends DbdDefaults{&lt;br /&gt;
         DbdStruct getDescription();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdField {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         string getName();&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         DbdDefaults getDefaults();&lt;br /&gt;
         DbdAttribute getAttributes();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdStruct {&lt;br /&gt;
         string getName();&lt;br /&gt;
         int16 getNumberFields();&lt;br /&gt;
         DbdField getFieldDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdRecord {&lt;br /&gt;
         string getName();&lt;br /&gt;
         int16 getNumberFields();&lt;br /&gt;
         DbdField getFieldDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Record Instance ==&lt;br /&gt;
&lt;br /&gt;
     interface RecordInstance {&lt;br /&gt;
         string getName();&lt;br /&gt;
         DbdRecord getDescription();&lt;br /&gt;
         DbfStruct getInstance();&lt;br /&gt;
         Dbf getField(string fieldName);&lt;br /&gt;
         Dbf getField(int16 index)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;getName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the record name&lt;br /&gt;
; &amp;lt;tt&amp;gt;getDescription&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the description of the record specific portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getInstance&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get instance for the record specific portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getField&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get field instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Locate Interfaces =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Classes are available to find and traverse the various Dbd definitons&lt;br /&gt;
and record instances.&lt;br /&gt;
The implementation will be language specific. For Java they will be something&lt;br /&gt;
like the following:&lt;br /&gt;
&lt;br /&gt;
In addition the following is defined:&lt;br /&gt;
&lt;br /&gt;
     public class DbdLocate {&lt;br /&gt;
         public DbdMenu getMenu(String name);&lt;br /&gt;
         public DbdLink getLink(String name);&lt;br /&gt;
         public DbdStruct getStruct(String name);&lt;br /&gt;
         public DbdRecord getRecord(String name);&lt;br /&gt;
         public LinkedList&amp;lt;DbdMenu&amp;gt; menuList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdLink&amp;gt; linkList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdStruct&amp;gt; structList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdRecord&amp;gt; recordList;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public class RecordInstanceLocate {&lt;br /&gt;
         public RecordInstance getRecord(string name);&lt;br /&gt;
         public Dbf getField(string name);&lt;br /&gt;
         public Dbf getField(string recordName, string fieldName);&lt;br /&gt;
         public LinkedList&amp;lt;RecordInstance&amp;gt; instanceList;&lt;br /&gt;
         public LinkedList&amp;lt;RecordInstance&amp;gt; instanceList(string recordTypeName);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; Are the above methods static or should there be something like&lt;br /&gt;
     public class FindLocator {&lt;br /&gt;
         public static DbdLocate findDbdLocate();&lt;br /&gt;
         public static RecordInstance findRecordInstance();&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
The following locates a specific menu.&lt;br /&gt;
&lt;br /&gt;
     DbdMenu menu = DbdLocate.get(&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
     if(menu!=null) printf(&amp;quot;found menu %s\n&amp;quot;,&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
The following locates a field of a record instance.&lt;br /&gt;
&lt;br /&gt;
     Dbf field = RecordInstanceLocate.getField(&amp;quot;example.value&amp;quot;);&lt;br /&gt;
     if(addr!=null) printf(&amp;quot;found %s\n&amp;quot;,&amp;quot;example.value&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_dbdInterfaces&amp;diff=588</id>
		<title>V4 Design: dbdInterfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_dbdInterfaces&amp;diff=588"/>
		<updated>2005-11-03T19:49:27Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: dbdInterfaces - IOC Database Description November 03 2005 &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes  definitions for code that accessses&lt;br /&gt;
IOC records, i.e. the records created from Database Definitions:&lt;br /&gt;
menu, struct, record, link, device, and record instances.&lt;br /&gt;
&lt;br /&gt;
The interfaces support introspection of everything created from Database&lt;br /&gt;
Definitions. The interfaces can be used by tools such as VDCT or on&lt;br /&gt;
a running IOC database.&lt;br /&gt;
&lt;br /&gt;
The definitions can be used by code that use code automatically&lt;br /&gt;
generated from DBD files or by code that uses only introspection.&lt;br /&gt;
&lt;br /&gt;
Code is automatically generated from the following definitions:&lt;br /&gt;
* &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; - Used by record support.&lt;br /&gt;
* &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; - Used by code that understands the struct.&lt;br /&gt;
* &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt; - Used by code that understands the menu.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Syntax =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax is defined so that either C++ and Java implementations can be created.&lt;br /&gt;
&lt;br /&gt;
NOTE: Most of the code fragments use Java syntax.&lt;br /&gt;
&lt;br /&gt;
== Primitive Types ==&lt;br /&gt;
* octet - 8 bit byte&lt;br /&gt;
* boolean - a value that takes the values &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt;&lt;br /&gt;
* int16 - 16 bit signed integer&lt;br /&gt;
* int32 - 32 bit signed integer&lt;br /&gt;
* int64 - 64 bit signed integer&lt;br /&gt;
* float32 - 32 bit IEEE float&lt;br /&gt;
* float64 - 64 bit IEEE float&lt;br /&gt;
&lt;br /&gt;
In Java these types become:&lt;br /&gt;
&lt;br /&gt;
* octet =&amp;gt; byte  BUT no arithmetic is implied&lt;br /&gt;
* boolean =&amp;gt; boolean&lt;br /&gt;
* int16 =&amp;gt; short&lt;br /&gt;
* int32 =&amp;gt; int&lt;br /&gt;
* int64 =&amp;gt; long&lt;br /&gt;
* float32 =&amp;gt; float&lt;br /&gt;
* float64 =&amp;gt; double&lt;br /&gt;
&lt;br /&gt;
In C++ these types become:&lt;br /&gt;
&lt;br /&gt;
* octet =&amp;gt; char  BUT no arithmetic is implied&lt;br /&gt;
* boolean =&amp;gt; bool BUT no arithmetic or conversion to/from int is implied&lt;br /&gt;
* int16 =&amp;gt; int16_t&lt;br /&gt;
* int32 =&amp;gt; int32_t&lt;br /&gt;
* int64 =&amp;gt; int64_t&lt;br /&gt;
* float32 =&amp;gt; float&lt;br /&gt;
* float64 =&amp;gt; double&lt;br /&gt;
&lt;br /&gt;
NOTE:&lt;br /&gt;
* The C++ integer types are from C99 stdint.h&lt;br /&gt;
* Should exceptions be defined?&lt;br /&gt;
&lt;br /&gt;
== enum, struct, interface, class,  string, array ==&lt;br /&gt;
&lt;br /&gt;
In adition to the primitive types the syntax&lt;br /&gt;
uses the terms enum, struct, interface, and array.&lt;br /&gt;
&lt;br /&gt;
=== enum ===&lt;br /&gt;
&lt;br /&gt;
An example of an enum is:&lt;br /&gt;
&lt;br /&gt;
     enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The C++  definition is identical. In Java 5 the definition would be:&lt;br /&gt;
&lt;br /&gt;
     public enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
=== struct ===&lt;br /&gt;
An example of a struct definition is:&lt;br /&gt;
&lt;br /&gt;
     struct DisplayLimitData {&lt;br /&gt;
         float64 low;&lt;br /&gt;
         float64 high;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In C++ this would be:&lt;br /&gt;
&lt;br /&gt;
    class DisplayLimitData {&lt;br /&gt;
    public:&lt;br /&gt;
         double low;&lt;br /&gt;
         double high;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
In Java this would be:&lt;br /&gt;
&lt;br /&gt;
     class DisplayLimitData {&lt;br /&gt;
         public double low;&lt;br /&gt;
         public double high;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== interface ===&lt;br /&gt;
An example of an interface definition is:&lt;br /&gt;
&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void    put(boolean val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class DbfBoolean : public Dbf {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual bool get() = 0;&lt;br /&gt;
         virtual void put(bool val) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
In Java would be:&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void    put(boolean val)&lt;br /&gt;
     }&lt;br /&gt;
=== class ===&lt;br /&gt;
&lt;br /&gt;
Any class definitions are language specific.&lt;br /&gt;
&lt;br /&gt;
=== string ===&lt;br /&gt;
&lt;br /&gt;
For C++ a string will be a &amp;lt;tt&amp;gt;char *&amp;lt;/tt&amp;gt; array containing UTF-8&lt;br /&gt;
compatible characters not necessarily terminated with a null character.&lt;br /&gt;
Wherever a &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt; argument appears, the C++ definition&lt;br /&gt;
will have &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;char *&amp;lt;/tt&amp;gt; arguments.&lt;br /&gt;
&lt;br /&gt;
For Java string will just be a &amp;lt;tt&amp;gt;String&amp;lt;/tt&amp;gt;.&lt;br /&gt;
It is assumed that Java Strings will be converted to/from UTF-8 byte streams&lt;br /&gt;
when the data is transfered to/from the network.&lt;br /&gt;
&lt;br /&gt;
If a string is being passed to a method the syntax is:&lt;br /&gt;
     void put(string value);&lt;br /&gt;
In C++ this becomes&lt;br /&gt;
     void put(int valueLength, char *value);&lt;br /&gt;
In Java it becomes&lt;br /&gt;
     void put(String value);&lt;br /&gt;
&lt;br /&gt;
If a method is returning a string the syntax is&lt;br /&gt;
     string get();&lt;br /&gt;
In C++ this becomes&lt;br /&gt;
     int getValueLength();&lt;br /&gt;
     int get(int valueLength, char *value);&lt;br /&gt;
     // valueLength is number of octets in value&lt;br /&gt;
     // return value is the number of octets written&lt;br /&gt;
In Java it becomes&lt;br /&gt;
     String get();&lt;br /&gt;
=== array ===&lt;br /&gt;
&lt;br /&gt;
An example of a definition that includes an array is:&lt;br /&gt;
&lt;br /&gt;
     void get(float64[] data);&lt;br /&gt;
&lt;br /&gt;
In C++ this would become:&lt;br /&gt;
&lt;br /&gt;
     void get(int lenData, double data[]);&lt;br /&gt;
&lt;br /&gt;
In Java this would be:&lt;br /&gt;
&lt;br /&gt;
     void get(double[] data);&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= DbfTypes =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
The following naming conventions are used:&lt;br /&gt;
; Dbf&lt;br /&gt;
: any class starting with Dbf describes a field in a header file generated from a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definition. For example DbfArray describes a field generated from &amp;lt;tt&amp;gt;field(name,array(float64[])&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; Dbd&lt;br /&gt;
: A class name starting with Dbd describes something related to dbd definitions. For example DbdMenu describes a dbd menu definition.&lt;br /&gt;
&lt;br /&gt;
All Dbf and Dbd definitions are interfaces. Thus all access to data is via&lt;br /&gt;
interfaces.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbfTypes.h&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
The following &amp;lt;tt&amp;gt;enum&amp;lt;/tt&amp;gt; definitions describe &lt;br /&gt;
each field in the header files generated from DBD &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; and&lt;br /&gt;
&amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
&lt;br /&gt;
     enum BasicType {&lt;br /&gt;
         basicTypeOctet,    // DbfOctet&lt;br /&gt;
         basicTypeBoolean,  // DbfBoolean&lt;br /&gt;
         basicTypeInt16,    // DbfInt16&lt;br /&gt;
         basicTypeInt32,    // DbfInt32&lt;br /&gt;
         basicTypeInt64,    // DbfInt64&lt;br /&gt;
         basicTypeFloat32,  // DbfFloat32&lt;br /&gt;
         basicTypeFloat64,  // DbfFloat64&lt;br /&gt;
         basicTypeString,   // DbfString&lt;br /&gt;
         basicTypeArray,    // DbfArray&lt;br /&gt;
         basicTypeStruct,   // DbfStruct&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum DbfType {&lt;br /&gt;
         dbfTypeBasic,       // DbfOctet,...,DbfStruct&lt;br /&gt;
         dbfTypeMenu,        // DbfMenu&lt;br /&gt;
         dbfTypeEnum,        // DbfEnum&lt;br /&gt;
         dbfTypeLink,        // DbfLink&lt;br /&gt;
         dbfTypeMDArray,     // DbfMDArray&lt;br /&gt;
         dbfTypeTimeStamp    // DbfTimeStamp&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Database Fields =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each database field is accessed via an interface which all extend&lt;br /&gt;
the following interface:&lt;br /&gt;
&lt;br /&gt;
     interface Dbf{&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         boolean isPrimitive(); // BasicTypeBoolean,...,BasicTypeFloat64&lt;br /&gt;
         boolean isBasic();&lt;br /&gt;
         BasicType getBasicType();&lt;br /&gt;
         RecordInstance getRecord();&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The interfaces are designed so that a field can be accessded&lt;br /&gt;
without exposing the address of its data.&lt;br /&gt;
&lt;br /&gt;
== Primitive Types ==&lt;br /&gt;
&lt;br /&gt;
DbfOctet, ..., DbfFloat64 are all interfaces with methods get and put.&lt;br /&gt;
    &lt;br /&gt;
     interface DbfOctet extends Dbf {&lt;br /&gt;
         octet get();&lt;br /&gt;
         void put(octet val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void put(boolean val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt16 extends Dbf {&lt;br /&gt;
         int16 get();&lt;br /&gt;
         void put(int16 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt32 extends Dbf {&lt;br /&gt;
         int32 get();&lt;br /&gt;
         void put(int32 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt64 extends Dbf {&lt;br /&gt;
         int64 get();&lt;br /&gt;
         void put(int64 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfFloat32 extends Dbf {&lt;br /&gt;
         float32 get();&lt;br /&gt;
         void put(float32 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfFloat64 extends Dbf {&lt;br /&gt;
         float64 get();&lt;br /&gt;
         void put(float64 val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Record support code can access such fields via the generated header&lt;br /&gt;
file. Some examples are:&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     ...&lt;br /&gt;
     precord.ffloat.put(10.0);&lt;br /&gt;
     ...&lt;br /&gt;
     short myint = record.fint.get();&lt;br /&gt;
&lt;br /&gt;
Code that does not include the generated header file can access these fields&lt;br /&gt;
via the introspection interfaces described later in this document.&lt;br /&gt;
For example code that expects a float64 field can access it via&lt;br /&gt;
&lt;br /&gt;
     Dbf dbf =  RecordInstanceLocate.getField(&amp;quot;recordname.value&amp;quot;);&lt;br /&gt;
     if(dbf==null&lt;br /&gt;
     || !dbf.isPrimitive()&lt;br /&gt;
     || (dbf.getBasicType() != basicTypeFloat64) ) // do something&lt;br /&gt;
     DbfFloat64 dbfdouble = (DbfFloat64)dbf;&lt;br /&gt;
     dbfdouble.put(10.0);&lt;br /&gt;
&lt;br /&gt;
or more concisely (but exception may be thrown)&lt;br /&gt;
     DbfConvertPrimitive(RecordInstanceLocate.getField(&amp;quot;recordname.value&amp;quot;),10.0);&lt;br /&gt;
&lt;br /&gt;
== String fields ==&lt;br /&gt;
&lt;br /&gt;
The interface for a string field is:&lt;br /&gt;
&lt;br /&gt;
     interface DbfString extends Dbf {&lt;br /&gt;
        string get();&lt;br /&gt;
        void put(string value);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following code prints a string.&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     String string = record.fstring.get();&lt;br /&gt;
     printf(&amp;quot;%s\n&amp;quot;,string);&lt;br /&gt;
&lt;br /&gt;
Code that does not include the header file can use the introspection methods&lt;br /&gt;
to locate the DbfString that provides access to the field.&lt;br /&gt;
&lt;br /&gt;
== Structure Fields ==&lt;br /&gt;
&lt;br /&gt;
     interface DbfStruct extends Dbf {&lt;br /&gt;
         int16 getNfields();&lt;br /&gt;
         Dbf getInterface(int16 index);&lt;br /&gt;
         DbdField getDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following traverses the fields of a DbfStruct&lt;br /&gt;
&lt;br /&gt;
     DbfStruct dbfStruct;&lt;br /&gt;
     &lt;br /&gt;
     for(i=0; i &amp;lt; dbfStruct.getNfields(); i++) {&lt;br /&gt;
         DbdField dbdField = dbfStruct.getDescription[i];&lt;br /&gt;
         String name = dbdField.getName();&lt;br /&gt;
         printf(&amp;quot;field %s\n&amp;quot;,name);&lt;br /&gt;
         // or just&lt;br /&gt;
         printf(&amp;quot;field %s\n&amp;quot;,dbfStruct.getDescription[i].dbdField.getName());&lt;br /&gt;
&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Structure fields can only be accessed via introspection.&lt;br /&gt;
However, for each structure, code is generated that does the introspection.&lt;br /&gt;
For example DisplayLimitData can be obtained via the statements:&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     DisplayLimitData limit = new DisplayLimitData();&lt;br /&gt;
     &lt;br /&gt;
     ...&lt;br /&gt;
     DisplayLimitSupport.get(record.displayLimit,limit);&lt;br /&gt;
     printf(&amp;quot;low %f high %f\n&amp;quot;,limit.low,limit.high);&lt;br /&gt;
&lt;br /&gt;
== Array Fields ==&lt;br /&gt;
&lt;br /&gt;
The generated header file will have a type that extends &amp;lt;tt&amp;gt;DbfArray&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     interface DbfArray extends Dbf {&lt;br /&gt;
        DbfType getType();&lt;br /&gt;
        int32 getNelements();&lt;br /&gt;
        void setNelements(int32 len);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfBooleanArray extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, boolean[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, boolean[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfOctetArray extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, octet[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, octet[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt16Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int16[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int16[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt32Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int32[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int32[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt64Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int64[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int64[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfFloat32Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, float32[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, float32[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfFloat64Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, float64[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, float64[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfStringArray extends DbfArray {&lt;br /&gt;
         DbfString getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfArrayArray extends DbfArray {&lt;br /&gt;
         DbfArray getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfStructArray extends DbfArray {&lt;br /&gt;
         DbfStruct getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfMenuArray extends DbfArray {&lt;br /&gt;
         DbfMenu getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfEnumArray extends DbfArray {&lt;br /&gt;
         DbfEnum getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfLinkArray extends DbfArray {&lt;br /&gt;
         DbfLink getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following puts data into a float64 field.&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
&lt;br /&gt;
     double[] data = new double[] {1.0,2.0,3.0};;&lt;br /&gt;
     if(!record.ffloat.isPrimitive()&lt;br /&gt;
     || record.ffloat.getBasicType()!=basicTypeFloat64)  // DO SOMTHING!!!!&lt;br /&gt;
     ...&lt;br /&gt;
     array.put(0,nelements,precord-&amp;gt;data);&lt;br /&gt;
&lt;br /&gt;
or more concisely&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     ...&lt;br /&gt;
     DbfConvertPrimitive.put(precord.array,new double[] {1.0,2.0,3.0});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfMDArray ==&lt;br /&gt;
NOT YET DEFINED&lt;br /&gt;
     &lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; is described as:&lt;br /&gt;
     interface DbfMenu extends Dbf {&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
         void putIndex(int16 val);&lt;br /&gt;
         DbdMenu getDbdMenu();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; allows the menu index to be set and retrieved&lt;br /&gt;
and also provides access to the DbdMenu.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; field can be accessed via the generated header file or via&lt;br /&gt;
the introspection methods.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfEnum ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfEnum&amp;lt;/tt&amp;gt; is described as:&lt;br /&gt;
     interface DbfEnum extends Dbf {&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
         void putIndex(int16 val);&lt;br /&gt;
         DbfStringArray getChoiceArray();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfEnum&amp;lt;/tt&amp;gt; allows the enum index to be set and retrieved&lt;br /&gt;
and also provides access to the The DbfArray field that contains the choices.&lt;br /&gt;
&lt;br /&gt;
== DbfLink ==&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;tt&amp;gt;DbfLink&amp;lt;/tt&amp;gt; is described as&lt;br /&gt;
 &lt;br /&gt;
     interface DbfLink extends Dbf {&lt;br /&gt;
         DbdLink getDbdLink();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== DbfTimeStamp ==&lt;br /&gt;
&lt;br /&gt;
     struct TimeStamp {&lt;br /&gt;
         int64 secondsSinceEpoch;&lt;br /&gt;
         int32 nanoSeconds;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfTimeStamp extends Dbf {&lt;br /&gt;
         void get(TimeStamp timeStamp);&lt;br /&gt;
         void put(TimeStamp timeStamp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= DbdStatements =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
These describe everything defined in database definition files.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdMenu&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdMenu {&lt;br /&gt;
         string getName();&lt;br /&gt;
         int16 getNchoices();&lt;br /&gt;
         string getChoice(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdSupport&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdSupport {&lt;br /&gt;
         string getChoiceName();&lt;br /&gt;
         string getSupportStructName(string name);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdStruct&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;DbdRecord&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdAttribute {&lt;br /&gt;
         string getDefault();&lt;br /&gt;
         boolean isReadonly();&lt;br /&gt;
         boolean isDesign();&lt;br /&gt;
         boolean isSpecial();&lt;br /&gt;
         int16 getAsl();&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbdDefaults {}&lt;br /&gt;
    &lt;br /&gt;
     interface DbdArrayDefaults extends DbdDefaults{&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         int32 getLength();&lt;br /&gt;
&lt;br /&gt;
     interface DbdStructDefaults extends DbdDefaults{&lt;br /&gt;
         DbdStruct getDescription();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdField {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         string getName();&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         DbdDefaults getDefaults();&lt;br /&gt;
         DbdAttribute getAttributes();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdStruct {&lt;br /&gt;
         string getName();&lt;br /&gt;
         int16 getNumberFields();&lt;br /&gt;
         DbdField getFieldDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdRecord {&lt;br /&gt;
         string getName();&lt;br /&gt;
         int16 getNumberFields();&lt;br /&gt;
         DbdField getFieldDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Record Instance ==&lt;br /&gt;
&lt;br /&gt;
     interface RecordInstance {&lt;br /&gt;
         string getName();&lt;br /&gt;
         DbdRecord getDescription();&lt;br /&gt;
         DbfStruct getInstance();&lt;br /&gt;
         Dbf getField(string fieldName);&lt;br /&gt;
         Dbf getField(int16 index)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;getNameLength&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get length of record name&lt;br /&gt;
; &amp;lt;tt&amp;gt;getName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the record name&lt;br /&gt;
; &amp;lt;tt&amp;gt;getDescription&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the description of the record specific portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getRecordCommonDescription&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the description of RecordCommon&lt;br /&gt;
; &amp;lt;tt&amp;gt;getInstance&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get instance for the record specific portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getRecordCommonInstance&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get instance for for RecordCommon portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getField&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get field instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Locate Interfaces =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Classes are available to find and traverse the various Dbd definitons&lt;br /&gt;
and record instances.&lt;br /&gt;
The implementation will be language specific. For Java they will be something&lt;br /&gt;
like the following:&lt;br /&gt;
&lt;br /&gt;
In addition the following is defined:&lt;br /&gt;
&lt;br /&gt;
     public class DbdLocate {&lt;br /&gt;
         public DbdMenu getMenu(String name);&lt;br /&gt;
         public DbdLink getLink(String name);&lt;br /&gt;
         public DbdStruct getStruct(String name);&lt;br /&gt;
         public DbdRecord getRecord(String name);&lt;br /&gt;
         public LinkedList&amp;lt;DbdMenu&amp;gt; menuList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdLink&amp;gt; linkList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdStruct&amp;gt; structList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdRecord&amp;gt; recordList;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public class RecordInstanceLocate {&lt;br /&gt;
         public RecordInstance getRecord(string name);&lt;br /&gt;
         public Dbf getField(string name);&lt;br /&gt;
         public Dbf getField(string recordName, string fieldName);&lt;br /&gt;
         public LinkedList&amp;lt;RecordInstance&amp;gt; instanceList;&lt;br /&gt;
         public LinkedList&amp;lt;RecordInstance&amp;gt; instanceList(string recordTypeName);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; Are the above methods static or should there be something like&lt;br /&gt;
     public class FindLocator {&lt;br /&gt;
         public static DbdLocate findDbdLocate();&lt;br /&gt;
         public static RecordInstance findRecordInstance();&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
The following locates a specific menu.&lt;br /&gt;
&lt;br /&gt;
     DbdMenu menu = DbdLocate.get(&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
     if(menu!=null) printf(&amp;quot;found menu %s\n&amp;quot;,&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
The following locates a field of a record instance.&lt;br /&gt;
&lt;br /&gt;
     Dbf field = RecordInstanceLocate.getField(&amp;quot;example.value&amp;quot;);&lt;br /&gt;
     if(addr!=null) printf(&amp;quot;found %s\n&amp;quot;,&amp;quot;example.value&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Runtime_Interfaces&amp;diff=2770</id>
		<title>V4 Design: Runtime Interfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Runtime_Interfaces&amp;diff=2770"/>
		<updated>2005-11-03T19:47:28Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Runtime Interfaces November 03 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes  definitions for IOC runtime,&lt;br /&gt;
i.e. interfaces implemented or used by database access, record support,&lt;br /&gt;
link support, and device support.&lt;br /&gt;
&lt;br /&gt;
It assumes knowledge of the interfaces described in dbdInterfaces.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTES&amp;lt;/b&amp;gt;&lt;br /&gt;
* IOC runtime needs lots more work&lt;br /&gt;
* methods, arguments, and return values are likely to undergo many changes&lt;br /&gt;
&lt;br /&gt;
The example code presented in this document assume the following database&lt;br /&gt;
definitions:&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,double)&lt;br /&gt;
         field(high,double)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     record(Example) extends RecordCommon {&lt;br /&gt;
         field(common,struct(RecordCommon))&lt;br /&gt;
         field(fboolean,boolean)&lt;br /&gt;
         field(octet,octet)&lt;br /&gt;
         field(fint,int16)&lt;br /&gt;
         ...&lt;br /&gt;
         field(ffloat,float64)&lt;br /&gt;
         field(string,string)&lt;br /&gt;
         field(array,array(double[])&lt;br /&gt;
         field(mdarray,array(double[,])&lt;br /&gt;
         field(menu,menu(name))&lt;br /&gt;
         field(fenum,enum)&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(device,link(in,analogIO))&lt;br /&gt;
         field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     }&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Record Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     enum ProcessState {&lt;br /&gt;
         processCancel,&lt;br /&gt;
         processStart,&lt;br /&gt;
         processContinue,&lt;br /&gt;
         processFinish,&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum ProcessReturn {&lt;br /&gt;
         processDone,&lt;br /&gt;
         processAbort,&lt;br /&gt;
         processActive&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RecordSupport {&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize(int16 pass);&lt;br /&gt;
         ProcessReturn process(ProcessState state,Callback done);&lt;br /&gt;
         // if special returns false when after is false put fails&lt;br /&gt;
         boolean special(boolean after,Dbf[] field);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ProcessState&amp;lt;/tt&amp;gt; supports the following semantics:&lt;br /&gt;
* cancel - If the record is active terminate &lt;br /&gt;
* For all other states see the companion document &amp;quot;V4 Design: Record Processing&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The methods of &amp;lt;tt&amp;gt;RecordSupport&amp;lt;/tt&amp;gt; are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - Called when a record instance is deleted.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called twice (pass = 0,1) when a record is initialized.&lt;br /&gt;
** pass 0 - Can do all local initialization but can not attach to anything external&lt;br /&gt;
** pass 1 - Can attach to external things&lt;br /&gt;
* &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; - Called to process a record. See &amp;quot;V4 Design: Record Processing&amp;quot; for semantics.&lt;br /&gt;
* &amp;lt;tt&amp;gt;special&amp;lt;/tt&amp;gt; - Called when a field declared special in a DBD file is modified. &amp;lt;tt&amp;gt;field&amp;lt;/tt&amp;gt; is an array of Dbfs showing which field is being modified.&lt;br /&gt;
&lt;br /&gt;
== Discussion of special ==&lt;br /&gt;
&lt;br /&gt;
Special is passed a Dbf array that identifies the field being modified.&lt;br /&gt;
For example &amp;lt;tt&amp;gt;ExampleRecord.dbd&amp;lt;/tt&amp;gt; has a field:&lt;br /&gt;
     field(displayLimit,struct(displayLimit))&lt;br /&gt;
&amp;lt;tt&amp;gt;ExampleRecordSupport.java&amp;lt;/tt&amp;gt; might implement special as follows:&lt;br /&gt;
     boolean special(boolean after, Dbf[] field)&lt;br /&gt;
     {&lt;br /&gt;
         switch(field[0].getIndex()) {&lt;br /&gt;
         ...&lt;br /&gt;
         case ExampleRecord.displayLimitIndex:&lt;br /&gt;
             if(field.length==1) {&lt;br /&gt;
                 // displayLimits itself is being modified. Do something&lt;br /&gt;
             } else {&lt;br /&gt;
                // a field of displayLimits is being modified&lt;br /&gt;
                 switch(field[1].getIndex) {&lt;br /&gt;
                     case DisplayLimit.lowIndex:&lt;br /&gt;
                          // low being modified. do something&lt;br /&gt;
                     case DisplayLimit.highIndex:&lt;br /&gt;
                          // high being modified. do something&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         ...&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Support for link and struct fields =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Support can be provided for link and struct fields.&lt;br /&gt;
An arbitrary number of Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
Recall that the support DBD definition is:&lt;br /&gt;
&lt;br /&gt;
    support(choiceName, supportStructName)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; is the name that identifies the implementation.&lt;br /&gt;
&amp;lt;tt&amp;gt;supportStructName&amp;lt;/tt&amp;gt; is the name of a structure used by support for&lt;br /&gt;
configuration.&lt;br /&gt;
&lt;br /&gt;
The syntax for interface definitions is similar to Java syntax&lt;br /&gt;
since it is more concise than C++.&lt;br /&gt;
It can easily be translated to C++ syntax. For example the&lt;br /&gt;
definition:&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,int16 data);&lt;br /&gt;
         boolean getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class LinkInt16 {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual LinkResult get(Callback &amp;amp;callback, int16_t &amp;amp;data) = 0;&lt;br /&gt;
         virtual LinkResult put(Callback &amp;amp;callback, int16_t data) = 0;&lt;br /&gt;
         virtual bool getBounds(int16_t &amp;amp;low, int16_t &amp;amp;high) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE:&amp;lt;/b&amp;gt; Int16 becomes int16_t &amp;amp;data and int16 data becomes int16_t data.&lt;br /&gt;
&lt;br /&gt;
Support and SupportMonitor are interfaces that are common to&lt;br /&gt;
the support for both link and struct fields.&lt;br /&gt;
All support &amp;lt;b&amp;gt;must&amp;lt;/b&amp;gt; register interface &amp;lt;tt&amp;gt;Support&amp;lt;/tt&amp;gt;&lt;br /&gt;
and if it supports monitors interface &amp;lt;tt&amp;gt;SupportMonitor&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE: arguments and return types ignored for now&amp;lt;/b&amp;gt;&lt;br /&gt;
     interface Support {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize(int16 pass);&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
         void cancel();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface SupportMonitor {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Support&amp;lt;/tt&amp;gt; is an interface that must be implemented by every &lt;br /&gt;
support module.&lt;br /&gt;
An instance of this is connected to each DbfLink or DbfStruct field that is configured to use support.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Support&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;SupportMonitor&amp;lt;/tt&amp;gt; is an interface that is implemented by support that&lt;br /&gt;
supports monitors. An example is support for hardware interrupts.&lt;br /&gt;
The methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally recordSupport does not need to call any of the Support &lt;br /&gt;
or SupportMonitor methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call destroy before modifying the link&lt;br /&gt;
and initialize and connect after the link is modified.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This section describes the standard interfaces&lt;br /&gt;
used by the record types supplied with epics base.&lt;br /&gt;
These interfaces are appropriate for the soft support supplied with EPICS&lt;br /&gt;
base and should also be sufficient for a wide variety of hardware support.&lt;br /&gt;
In particular they sufficient for communication with asynDriver.&lt;br /&gt;
&lt;br /&gt;
Soft support should try to implement the same interfaces implemented by&lt;br /&gt;
the Channel/Database access support supplied with base. The support&lt;br /&gt;
can define support structures for it's own use.&lt;br /&gt;
Implementing these interfaces means that the support will work for&lt;br /&gt;
the same set of record links as the Channel/Database access support.&lt;br /&gt;
&lt;br /&gt;
Hardware support should, if possible, also implement the same interfaces&lt;br /&gt;
implemented by the Channel/Database access support.&lt;br /&gt;
Message based support may also have to implement the AsynOctet interface&lt;br /&gt;
but this interface is only used by a few record types.&lt;br /&gt;
&lt;br /&gt;
This section describes the interfaces implemented by all link support&lt;br /&gt;
and then the standard interfaces used by the records supplied with base.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
These are the definitions used by the Channel/Database access support&lt;br /&gt;
supplied with base.&lt;br /&gt;
&lt;br /&gt;
     enum LinkResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkNoop,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting for completion &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
&lt;br /&gt;
     interface LinkOctet {&lt;br /&gt;
         LinkResult get(Callback callback, Octet data);&lt;br /&gt;
         LinkResult put(Callback callback, octet data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkResult get(Callback callback, octet[] data);&lt;br /&gt;
         LinkResult put(Callback callback, octet[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== asynDigital Support ==&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkResult write(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          LinkResult read(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,Boolean data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,boolean[] data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,int16 data);&lt;br /&gt;
         boolean getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,int16[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int16[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,int32 data);&lt;br /&gt;
         boolean getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,int32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,Int64 data);&lt;br /&gt;
         LinkResult put(Callback callback,int64 data);&lt;br /&gt;
         boolean getBounds(Int64 low, Int64 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,int64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,Float32 data);&lt;br /&gt;
         LinkResult put(Callback callback,float32 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,float32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,Float64 data);&lt;br /&gt;
         LinkResult put(Callback callback,float64 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,float64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkResult get(Callback callback,string data);&lt;br /&gt;
         LinkResult put(Callback callback,string data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkResult get(Callback callback,string[] data);&lt;br /&gt;
         LinkResult put(Callback callback,string[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Struct Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
== support for RecordCommon ==&lt;br /&gt;
This implements an interface, not yet defined, that is similar to the&lt;br /&gt;
interface record support implements.&lt;br /&gt;
== support for LinearConvert ==&lt;br /&gt;
This implements the interface&lt;br /&gt;
     interface SupportLinearConvert{&lt;br /&gt;
          void convert(int32 raw,Float64 value) // from raw to eng&lt;br /&gt;
          void convert(float64 value,Int32 raw) // from eng to raw&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In addition it provides a factory&lt;br /&gt;
     interface FactoryLinearConvert{&lt;br /&gt;
         SupportLinearConvert create(string choiceName,&lt;br /&gt;
             DbfStruct linearConvert,DbfLink inlink)&lt;br /&gt;
     }&lt;br /&gt;
== support for simulation ==&lt;br /&gt;
This needs to be defined.&lt;br /&gt;
== support for breakpoint tables ==&lt;br /&gt;
This needs to be defined.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtime Database Access =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Database Access, with help from record, link, and device support&lt;br /&gt;
implements the dbdInterfaces.&lt;br /&gt;
Other than Database Access, fields of a record can only&lt;br /&gt;
be accessed via the interfaces described in dbdInterfaces.&lt;br /&gt;
This allows the database to handle&lt;br /&gt;
actions like posting database monitors without any help from&lt;br /&gt;
record, link, or device support.&lt;br /&gt;
&lt;br /&gt;
Database access by default allocates the actual storage for each field&lt;br /&gt;
but allows support code to register itself to manage storage for field&lt;br /&gt;
instances.&lt;br /&gt;
Two examples, both involving arrays, are:&lt;br /&gt;
* The compress record  registers to provide storage for the value.&lt;br /&gt;
** This allows it to implement a circular buffer.&lt;br /&gt;
** Code that accesses the value field may have to issue two get requests.&lt;br /&gt;
* Device support for a transient recorder registers to provide storage for the array&lt;br /&gt;
** This allows device support to read data from hardware in segments&lt;br /&gt;
** Code that accesses the array may have to issue many get requests.&lt;br /&gt;
&lt;br /&gt;
The fact that each field of a record instance is an object means that additional storage is required.&lt;br /&gt;
Database Access  will probably have something like the following:&lt;br /&gt;
&lt;br /&gt;
    class Field {&lt;br /&gt;
        DbRecord instance;&lt;br /&gt;
        short          index;&lt;br /&gt;
    };&lt;br /&gt;
    ...&lt;br /&gt;
    class IntField extends Field {&lt;br /&gt;
        int data;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
This each field has the overhead of&lt;br /&gt;
* instance - a reference to DbRecord, i.e. record instance&lt;br /&gt;
* index - a 16 bit integer&lt;br /&gt;
* vtbl - a reference to the object implementation&lt;br /&gt;
&lt;br /&gt;
Additional fields will be needed for things like monitors.&lt;br /&gt;
These fields can start out null and only allocate storage as needed.&lt;br /&gt;
&lt;br /&gt;
== Database Access ==&lt;br /&gt;
&lt;br /&gt;
     interface DbAccess {&lt;br /&gt;
         void lock(RecordInstance instance);&lt;br /&gt;
         void unlock(RecordInstance instance);&lt;br /&gt;
         void process(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processCancel(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processContinue(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processRequestAccept(Dbf field, boolean yesNo);&lt;br /&gt;
         void registerDbfSource(Dbf field, Dbf source);&lt;br /&gt;
         LinkSupport getLinkSupport(Dbf field);&lt;br /&gt;
         Support getSupport(Dbf field);&lt;br /&gt;
         RecordSupport getRecordSupport(RecordInstance instance);&lt;br /&gt;
         RecordSupport getRecordCommonSupport(RecordInstance instance);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;lock&amp;lt;/tt&amp;gt; - lock the record.&lt;br /&gt;
* &amp;lt;tt&amp;gt;unlock&amp;lt;/tt&amp;gt; - unlock the record.&lt;br /&gt;
* &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; - Request processing. Record must be idle or active or request fails.&lt;br /&gt;
** &amp;lt;tt&amp;gt;instance&amp;lt;/tt&amp;gt; - The record to process&lt;br /&gt;
** &amp;lt;tt&amp;gt;callback&amp;lt;/tt&amp;gt; - A callback to call when processing completes or for failure.&lt;br /&gt;
* &amp;lt;tt&amp;gt;processRequestAccept&amp;lt;/tt&amp;gt; - Should a process request from channel access be accepted,&lt;br /&gt;
* &amp;lt;tt&amp;gt;registerDbfSource&amp;lt;/tt&amp;gt; - Register code that will implement storage for the field.&lt;br /&gt;
* &amp;lt;tt&amp;gt;getLinkSupport&amp;lt;/tt&amp;gt; - Find the link support for a link field&lt;br /&gt;
* &amp;lt;tt&amp;gt;getSupport&amp;lt;/tt&amp;gt; - Get the device support for a device field&lt;br /&gt;
* &amp;lt;tt&amp;gt;getRecordSupport&amp;lt;/tt&amp;gt; - Get the record support for the record&lt;br /&gt;
* &amp;lt;tt&amp;gt;getRecordCommonSupport&amp;lt;/tt&amp;gt; - Get the RecordCommon support for the record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTES&amp;lt;/b&amp;gt; This is just the beginning of defining the methods in DbAccess&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code generated from Database Definition Files =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following shows the Java code generated from DBD files:&lt;br /&gt;
&lt;br /&gt;
== structure definitions ==&lt;br /&gt;
&lt;br /&gt;
Two files are generated from &amp;lt;tt&amp;gt;struct(name)&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
# &amp;lt;tt&amp;gt;name.java&amp;lt;/tt&amp;gt;&lt;br /&gt;
# &amp;lt;tt&amp;gt;nameSupport.java&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;name.java&amp;lt;/tt&amp;gt; implements:&lt;br /&gt;
     interface Struct {&lt;br /&gt;
         Dbf getField(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a structure is defined as:&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,double)&lt;br /&gt;
         field(high,double)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
A generated file &amp;lt;tt&amp;gt;DisplayLimit.java&amp;lt;/tt&amp;gt; contains:&lt;br /&gt;
&lt;br /&gt;
     public class DisplayLimit implements Struct{&lt;br /&gt;
         public DbfFloat64 low;&lt;br /&gt;
         public DbfFloat64 high;&lt;br /&gt;
         public static final short lowIndex = 1;&lt;br /&gt;
         public static final short highIndex = 2;&lt;br /&gt;
         public static final short lastIndex = indexHigh;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case lowIndex: return(low);&lt;br /&gt;
                 case highIndex: return(high);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
             return null;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
A generated file &amp;lt;tt&amp;gt;DisplayLimitAccess.java&amp;lt;/tt&amp;gt; contains:&lt;br /&gt;
&lt;br /&gt;
     public class DisplayLimitData {&lt;br /&gt;
         public double low;&lt;br /&gt;
         public double high;&lt;br /&gt;
     }&lt;br /&gt;
     public final class DisplayLimitAccess implements StructFactory{&lt;br /&gt;
         public Struct create() { return new DisplayLimit; }&lt;br /&gt;
         public static final void get(DbfStruct from,DisplayLimitData data) {&lt;br /&gt;
             DbfFloat64 dbf = from.getInterface(1);&lt;br /&gt;
             data.low = dbf.get();&lt;br /&gt;
             DbfFloat64 dbf = from.getInterface(2);&lt;br /&gt;
             data.high = dbf.get();&lt;br /&gt;
         }&lt;br /&gt;
         public static final void put(DbfStruct to, DisplayLimitData data) {&lt;br /&gt;
             DbfFloat64 dbf = to.getInterface(1);&lt;br /&gt;
             dbf.put(data.low);&lt;br /&gt;
             DbfFloat64 dbf = to.getInterface(2);&lt;br /&gt;
             dbf.put(data.high);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class DisplayLimitAccessRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             DisplayLimitAccess access = new DisplayLimitAccess;&lt;br /&gt;
             RegisterSupport.structure(access,&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTES&amp;lt;/b&amp;gt;&lt;br /&gt;
* The V4 replacement for registerRecordDeviceDriver must call DisplayLimitAccessRegister.createAndRegister.&lt;br /&gt;
* For non primitive fields the generated field is the Dbf type for the field.&lt;br /&gt;
&lt;br /&gt;
Similar files are generated for C++.&lt;br /&gt;
&lt;br /&gt;
== record definitions ==&lt;br /&gt;
If a record is defined as:&lt;br /&gt;
     record(Example) {&lt;br /&gt;
         field(common,struct(RecordCommon))&lt;br /&gt;
         ...&lt;br /&gt;
         field(fboolean,boolean)&lt;br /&gt;
         field(octet,octet)&lt;br /&gt;
         field(fint,int16)&lt;br /&gt;
         ...&lt;br /&gt;
         field(ffloat,float64)&lt;br /&gt;
         field(string,string)&lt;br /&gt;
         field(array,array(double[])&lt;br /&gt;
         field(mdarray,array(double[,])&lt;br /&gt;
         field(menu,menu(name))&lt;br /&gt;
         field(fenum,enum)&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(device,link(in,analogIO))&lt;br /&gt;
         field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The generated Java file is&lt;br /&gt;
&lt;br /&gt;
     public class ExampleRecord implements Struct {&lt;br /&gt;
         ... // all the fields from menuStructBase&lt;br /&gt;
         public DbfBoolean   fboolean;&lt;br /&gt;
         public DbfOctet     ctet;&lt;br /&gt;
         public DbfInt16     fint;&lt;br /&gt;
         ...&lt;br /&gt;
         public DbfFloat64   ffloat;&lt;br /&gt;
         public DbfString    string;&lt;br /&gt;
         public DbfArray     array;&lt;br /&gt;
         public DbfMDArray   mdarray;&lt;br /&gt;
         public DbfMenu      menu;&lt;br /&gt;
         public DbfEnum      fenum;&lt;br /&gt;
         public DbfLink      link;&lt;br /&gt;
         public DbfDevice    device;&lt;br /&gt;
         public DbfStruct    displayLimit;&lt;br /&gt;
         public static final int16 fbooleanIndex = 1;&lt;br /&gt;
         ...&lt;br /&gt;
         public static final int16 lastIndex = displayLimitIndex;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case fbooleanIndex : return(fboolean);&lt;br /&gt;
                 ...&lt;br /&gt;
                 case displayLimitIndex: return(displayLimit);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class ExampleRecordFactory implements StructFactory{&lt;br /&gt;
         public static final Struct create() { return new ExampleRecord; }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class ExampleRecordFactoryRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             ExampleRecordFactory  factory = new ExampleRecordFactory;&lt;br /&gt;
             RegisterSupport.record(factory,&amp;quot;ExampleRecord&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; The V4 replacement for registerRecordDeviceDriver must&lt;br /&gt;
call ExampleRecordFactoryRegister.createAndRegister&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar code is generated for C++.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Support Code =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section described interfaces for&lt;br /&gt;
strings, arrays, and conversions. &lt;br /&gt;
They are intended for use by Database Access, Record Support, etc.&lt;br /&gt;
&lt;br /&gt;
== C++ support for strings ==&lt;br /&gt;
&lt;br /&gt;
For most strings all the database  needs is a nonmutable string.&lt;br /&gt;
&lt;br /&gt;
Perhaps the only type of string connected with an IOC record&lt;br /&gt;
that changes frequently is a field in a record type&lt;br /&gt;
like stringin and stringout.&lt;br /&gt;
&lt;br /&gt;
This what to do for strings?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== array copy ==&lt;br /&gt;
&lt;br /&gt;
ArrayCopy copies arrays an array performing conversions if necessary.&lt;br /&gt;
&lt;br /&gt;
     interface ArrayCopy {&lt;br /&gt;
         void copy(DbfArray from,DbfArray to);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
This only supports primitive types, i.e. DbfBoolean,...,DbfFloat64.&lt;br /&gt;
It does NOT convert between&lt;br /&gt;
* DbfBoolean and another type.&lt;br /&gt;
* DbfOctet and another type.&lt;br /&gt;
Thus for DbfBoolean and DbfOctet it is willing to copy&lt;br /&gt;
but not convert to/from other types.&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Conversions ==&lt;br /&gt;
This is a static class that converts between primitie types and arrays of primitive types.&lt;br /&gt;
&lt;br /&gt;
     static class DbfConvertPrimitive {&lt;br /&gt;
     public:&lt;br /&gt;
          int16 get(Dbf from);&lt;br /&gt;
          int32 get(Dbf from);&lt;br /&gt;
          int64 get(Dbf from);&lt;br /&gt;
          float32 get(Dbf from);&lt;br /&gt;
          float64 get(Dbf from);&lt;br /&gt;
          get(Dbf from, String value);&lt;br /&gt;
          get(DbfOctet from, String value);&lt;br /&gt;
          get(DbfBoolean from, String value);&lt;br /&gt;
          put(Dbf to, int16 value);&lt;br /&gt;
          put(Dbf to, int32 value);&lt;br /&gt;
          put(Dbf to, int64 value);&lt;br /&gt;
          put(Dbf to, float32 value);&lt;br /&gt;
          put(Dbf to, float64 value);&lt;br /&gt;
          put(Dbf to,int32 String value);&lt;br /&gt;
          put(DbfOctet to, String value);&lt;br /&gt;
          put(DbfBoolean to, String value);&lt;br /&gt;
&lt;br /&gt;
          get(DbfArray from, int16[] value);&lt;br /&gt;
          get(DbfArray from, int32[] value);&lt;br /&gt;
          get(DbfArray from, int64[] value);&lt;br /&gt;
          get(DbfArray from, float32[] value);&lt;br /&gt;
          get(DbfArray from, float64[] value);&lt;br /&gt;
          put(DbfArray to, int16[] value);&lt;br /&gt;
          put(DbfArray to, int32[] value);&lt;br /&gt;
          put(DbfArray to, int64[] value);&lt;br /&gt;
          put(DbfArray to, float32[] value);&lt;br /&gt;
          put(DbfArray to, float64[] value);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* For Dbf &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; must be one of &amp;lt;tt&amp;gt;DbfInt16&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;DbfFloat64&amp;lt;/tt&amp;gt;&lt;br /&gt;
* The get to a string implements printf semantics&lt;br /&gt;
* The put from a string value just scanf semantics.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;DbfOctet&amp;lt;/tt&amp;gt; methods convert to/from a string of the form &amp;quot;0xXX&amp;quot;&lt;br /&gt;
* The &amp;lt;tt&amp;gt;DbfBoolean&amp;lt;/tt&amp;gt; get method supports all the choices specified in the DBD Record Instance Specification&lt;br /&gt;
* For DbfArray &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; must be an array of one of &amp;lt;tt&amp;gt;DbfInt16&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;DbfFloat64&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=2725</id>
		<title>V4 Link Support Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=2725"/>
		<updated>2005-11-03T19:46:11Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;V4 Link Support Tutorial - November 03 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
The V4 link/struct support is a replacement for V3 &lt;br /&gt;
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK&lt;br /&gt;
# device DBD definition and device support&lt;br /&gt;
# driver DBD definition and driver support&lt;br /&gt;
&lt;br /&gt;
Each link and struct field in a record can have associated support.&lt;br /&gt;
* record support communicates with support via interfaces&lt;br /&gt;
* link or struct support implements interfaces&lt;br /&gt;
** link or struct support registers the interfaces it implements&lt;br /&gt;
** record support looks for interfaces it uses&lt;br /&gt;
*** it uses only the interfaces it finds&lt;br /&gt;
*** if no interfaces are found it reports an error&lt;br /&gt;
&lt;br /&gt;
Support has no knowledge of what record types are using it.&lt;br /&gt;
Struct support may have knowledge of the struct field&lt;br /&gt;
but not of the record type.&lt;br /&gt;
recordSupport has no knowledge about support other than the&lt;br /&gt;
interface it is using.&lt;br /&gt;
&lt;br /&gt;
For the rest of this document recordSupport means record support and support,&lt;br /&gt;
unless qualified, means link or struct support.&lt;br /&gt;
&lt;br /&gt;
EPICS base defines a standard set of interfaces for support,&lt;br /&gt;
which includes enough functionality such that&lt;br /&gt;
most link support can be implemented via just these interfaces.&lt;br /&gt;
&lt;br /&gt;
Base provides struct support for the following:&lt;br /&gt;
* RecordCommon - used by all record types in base&lt;br /&gt;
* LinearConvert - can be used by any analog type record&lt;br /&gt;
* others TBD&lt;br /&gt;
&lt;br /&gt;
Base provides channel/database access link support for primitive,&lt;br /&gt;
string, and array fields.&lt;br /&gt;
The link interfaces provided by base are also used by asynDriver.&lt;br /&gt;
Since asynDriver is intended as a framework for interfacing to most hardware,&lt;br /&gt;
this means that the interfaces supplied and used by base allows support&lt;br /&gt;
for most hardware. The support can communicate with the hardware&lt;br /&gt;
anyway it wants but must implement some set of the interfaces defined&lt;br /&gt;
by base.&lt;br /&gt;
&lt;br /&gt;
This document gives a brief overview of the V4 link/struct support model.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Database Definitions For links and structures =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section first reviews the DBD syntax related to link definitions.&lt;br /&gt;
It then gives a brief description of link related definitions in dbCommon.dbd&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
A record link has the syntax:&lt;br /&gt;
     field(name,link)&lt;br /&gt;
A record struct has the syntax&lt;br /&gt;
     field(name,struct(structName))&lt;br /&gt;
Support for a struct or link has the syntax&lt;br /&gt;
     support(choiceName) // no SupportStruct&lt;br /&gt;
     support(choiceName,SupportStruct)&lt;br /&gt;
A record instance link has the syntax&lt;br /&gt;
    field = support(choiceName) SupportStruct{structAssignmentList}&lt;br /&gt;
A record instance struct has the the syntax&lt;br /&gt;
    field = StructName{structAssignmentList} // no support&lt;br /&gt;
    field = support(choiceName)&lt;br /&gt;
            StructName{structAssignmentList} // support has no SupportStruct&lt;br /&gt;
    field = support(choiceName) SupportStruct{structAssignmentList}&lt;br /&gt;
            StructName{structAssignmentList}&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;structName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice. Each support must have a unique name.&lt;br /&gt;
; &amp;lt;tt&amp;gt;StructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The same name that appears in the field definition of the record.&lt;br /&gt;
; &amp;lt;tt&amp;gt;SupportStruct&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the support. recordSupport normally does not access this structure. Database configuration tools prompt the user to assign values to the structure.&lt;br /&gt;
&lt;br /&gt;
Assume the following definitions:&lt;br /&gt;
     record(AiRecord) {&lt;br /&gt;
         ...&lt;br /&gt;
         field(in,link)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     struct(MonitorLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(InputLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     support(monitorLink,MonitorLink)&lt;br /&gt;
     support(inputLink,InputLink)&lt;br /&gt;
     struct VME{&lt;br /&gt;
         field(a16,int16) &lt;br /&gt;
         field(a32,int32)&lt;br /&gt;
         field(channel,int16)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     support(someVmeADC,VME)&lt;br /&gt;
&lt;br /&gt;
The first example instance definition selects a monitor link.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {&lt;br /&gt;
                   support(monitorLink) MonitorLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                        process = true;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The next example selects a channel access input link.&lt;br /&gt;
     AiRecord aiInputExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {&lt;br /&gt;
                   support(inputLink) InputLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                        process = true;&lt;br /&gt;
                        wait = true;&lt;br /&gt;
                        timeout = 1.0;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The last example selects support for a VME Analog to Digital device.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {support(someVmeADC) VME {a16 = 0xc000; channel = 1} }&lt;br /&gt;
&lt;br /&gt;
== Standard Definitions For Channel/Database Access ==&lt;br /&gt;
&lt;br /&gt;
menuStructBase.dbd defines definitions for Channel/Database Access Links.&lt;br /&gt;
The base supplied support registers each choiceName in the support definitions.&lt;br /&gt;
The complete set of data structure and support definitions are defined&lt;br /&gt;
in &amp;quot;V4 DB RecordCommon&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* process&lt;br /&gt;
* monitor&lt;br /&gt;
* input&lt;br /&gt;
* output&lt;br /&gt;
&lt;br /&gt;
For monitor, input, and output the following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
&lt;br /&gt;
These are definitions that are used by the standard EPICS device support&lt;br /&gt;
for asynDriver. Since asynDriver is a generic way of interfacing arbitrary&lt;br /&gt;
hardware support, this is a generic way of attaching links in records to&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLink) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== support definitions ===&lt;br /&gt;
&lt;br /&gt;
     support(asynInt32,AsynLink)&lt;br /&gt;
     support(asynInt32Average,AsynLink)&lt;br /&gt;
     support(asynInt32Monitor,AsynLink)&lt;br /&gt;
     support(asynFloat64,AsynLink)&lt;br /&gt;
     support(asynFloat64Average,AsynLink)&lt;br /&gt;
     support(asynFloat64Monitor,AsynLink)&lt;br /&gt;
     support(asynDigitalMonitor,AsynLink)&lt;br /&gt;
     support(asynDigital,AsynLink)&lt;br /&gt;
     support(asynInt32Array,AsynLink)&lt;br /&gt;
     support(asynFloat64Array,AsynLink)&lt;br /&gt;
     support(asynOctet,AsynLink)&lt;br /&gt;
&lt;br /&gt;
This is the set of definitions for the standard EPICS device support implemented&lt;br /&gt;
by asynDriver. At least for the first few V4 releases,&lt;br /&gt;
asynDriver will not be part of base.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  interfaces for link and struct support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Support can be provided for link and struct fields.&lt;br /&gt;
An arbitrary number of Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
The syntax for interface definitions is similar to Java syntax&lt;br /&gt;
since it is more concise than C++.&lt;br /&gt;
It can easily be translated to C++ syntax. For example the&lt;br /&gt;
definition:&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,int16 data);&lt;br /&gt;
         boolean getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class LinkInt16 {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual LinkResult get(Callback &amp;amp;callback, int16_t &amp;amp;data) = 0;&lt;br /&gt;
         virtual LinkResult put(Callback &amp;amp;callback, int16_t data) = 0;&lt;br /&gt;
         virtual bool getBounds(int16_t &amp;amp;low, int16_t &amp;amp;high) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE:&amp;lt;/b&amp;gt; Int16 becomes int16_t &amp;amp;data and int16 data becomes int16_t data.&lt;br /&gt;
&lt;br /&gt;
Support and SupportMonitor are interfaces that are common to&lt;br /&gt;
the support for both link and struct fields.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE: arguments and return types ignored for now&amp;lt;/b&amp;gt;&lt;br /&gt;
     interface Support {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize(int16 pass);&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
         void cancel();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface SupportMonitor {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Support&amp;lt;/tt&amp;gt; is an interface that must be implemented by every &lt;br /&gt;
support module.&lt;br /&gt;
&amp;lt;tt&amp;gt;SupportMonitor&amp;lt;/tt&amp;gt; is an interface that is implemented by support that&lt;br /&gt;
supports monitors. An example is support for hardware interrupts.&lt;br /&gt;
&lt;br /&gt;
Normally recordSupport does not need to call any of the Support &lt;br /&gt;
or SupportMonitor methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call destroy before modifying the link&lt;br /&gt;
and initialize and connect after the link is modified.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  interfaces for struct support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
== support for RecordCommon ==&lt;br /&gt;
This implements an interface, not yet defined, that is similar to the&lt;br /&gt;
interface record support implements.&lt;br /&gt;
== support for LinearConvert ==&lt;br /&gt;
This implements the interface&lt;br /&gt;
     interface SupportLinearConvert{&lt;br /&gt;
          convert(int32 raw,Float64 value) // from raw to eng&lt;br /&gt;
          convert(float64 value,Int32 raw) // from eng to raw&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In addition it provides a factory&lt;br /&gt;
     interface FactoryLinearConvert{&lt;br /&gt;
         SupportLinearConvert(string choiceName,&lt;br /&gt;
             DbfStruct linearConvert,DbfLink inlink)&lt;br /&gt;
     }&lt;br /&gt;
== support for simulation ==&lt;br /&gt;
This needs to be defined.&lt;br /&gt;
== support for breakpoint tables ==&lt;br /&gt;
This needs to be defined.&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  interfaces for link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
EPICS base defines a number of standard interfaces&lt;br /&gt;
that are used by the record types supplied with epics base.&lt;br /&gt;
These interfaces are appropriate for the soft support supplied with EPICS&lt;br /&gt;
base and should also be sufficient for a wide variety of hardware support.&lt;br /&gt;
In particular they sufficient for communication with asynDriver.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The standard interfaces use the following definitions:&lt;br /&gt;
&lt;br /&gt;
     enum LinkResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkNoop,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting for completion &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The complete set of interfaces are described in V4 Design: Runtime Interfaces.&lt;br /&gt;
Some examples are:&lt;br /&gt;
&lt;br /&gt;
     interface LinkProcess {&lt;br /&gt;
         LinkResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,int16 data);&lt;br /&gt;
         boolean getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;LinkProcess&amp;lt;/tt&amp;gt; is the interface for process link fields&lt;br /&gt;
and &amp;lt;tt&amp;gt;LinkInt16&amp;lt;/tt&amp;gt; is the interface for int16 fields.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Example - VME ADC support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
Assume the VME and support definitions given in the examples at the beginning&lt;br /&gt;
of this document.&lt;br /&gt;
&lt;br /&gt;
The following is presented with Java syntax.&lt;br /&gt;
It assumes that there is VME support of the form&lt;br /&gt;
&lt;br /&gt;
     public class vme {&lt;br /&gt;
         static public short getShort(long addr);&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The link support would be something like:&lt;br /&gt;
&lt;br /&gt;
     class AdcSupport implements Link LinkInt32 {&lt;br /&gt;
     AdcSupport(VME fromFactory)&lt;br /&gt;
     {&lt;br /&gt;
         addr = fromFactory;&lt;br /&gt;
         connected = false;&lt;br /&gt;
         //  from the VME initialize vmeaddr and channel&lt;br /&gt;
         // details left to your imagination&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Link methods&lt;br /&gt;
     void report(int16_t level)&lt;br /&gt;
     {&lt;br /&gt;
         printf(&amp;quot;AdcSupport a16 %x channel %d\n&amp;quot;,a16,channel);&lt;br /&gt;
     }&lt;br /&gt;
     void cancel() {} // nothing to do&lt;br /&gt;
     void destroy() {} //nothing to do&lt;br /&gt;
     void initialize()&lt;br /&gt;
     {&lt;br /&gt;
         // make sure we can access a16&lt;br /&gt;
     }&lt;br /&gt;
     void connect() {connected = true}&lt;br /&gt;
     void disconnect() {connected = false}&lt;br /&gt;
     &lt;br /&gt;
     // LinkInt32 methods&lt;br /&gt;
     LinkResult get(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         data = (Int)VME.getShort(vmeaddr);&lt;br /&gt;
         return linkNoop;&lt;br /&gt;
     }&lt;br /&gt;
     LinkResult put(Callback callback, int data)&lt;br /&gt;
     {&lt;br /&gt;
         throw CantWriteAdc;&lt;br /&gt;
     }&lt;br /&gt;
     void getBounds(Int low, Int high) &lt;br /&gt;
     {&lt;br /&gt;
         // assume 16 bit unipolor adc&lt;br /&gt;
         low = 0; high = 0xffff;&lt;br /&gt;
     }&lt;br /&gt;
     private:&lt;br /&gt;
         VME addr;&lt;br /&gt;
         int vmeaddr;&lt;br /&gt;
         int channel;&lt;br /&gt;
         boolean connected;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Additional requirements for link support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The following are two important requirements:&lt;br /&gt;
* analog I/O&lt;br /&gt;
** link support can return raw value. Support must convert to engineering units.&lt;br /&gt;
** link support can return engineering units&lt;br /&gt;
* output records&lt;br /&gt;
** If possible link support should provide initial value during initialization&lt;br /&gt;
** If output can be modified other than by record itself than the records balue should be modified without causing a new output&lt;br /&gt;
&lt;br /&gt;
Lets consider each of these separately.&lt;br /&gt;
== Analog I/O ==&lt;br /&gt;
In V3 the aiRecord and aoRecords are responsible for conversion between&lt;br /&gt;
raw values and engineering units. Raw values are 32 bit integers. Device&lt;br /&gt;
support is responsible for setting the slope and intercept fields of the record.&lt;br /&gt;
recordSupport takes care of the actual conversions.&lt;br /&gt;
Device support can tell recordSupport that it set the engineering units&lt;br /&gt;
rather than a raw value by a different return value.&lt;br /&gt;
&lt;br /&gt;
For V4 the following is done:&lt;br /&gt;
&lt;br /&gt;
aiRecord and aoRecord both have the following fields:&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;None&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(engUnitsHigh,float64)&lt;br /&gt;
         field(engUnitsLow,float64)&lt;br /&gt;
         field(slope,float64)&lt;br /&gt;
         field(intercept,float64)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     ...&lt;br /&gt;
     field(convert, menu(menuConvert))&lt;br /&gt;
     field(linearConvert, struct(LinearConvert))&lt;br /&gt;
     field(convertTable,string);&lt;br /&gt;
     field(units, string)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; This section is written as though record support itself does&lt;br /&gt;
the conversions. Most record support would call the standard support&lt;br /&gt;
for LinearConvert.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a record instance has convert set to None then recordSupport does the following.&lt;br /&gt;
* if link support implements LinkFloat64 it just calls this to obtain an engineering units value&lt;br /&gt;
* otherwise it gets a value via interface LinkInt32 and converts the value from in int32 to a float64.&lt;br /&gt;
&lt;br /&gt;
If a record instance has convert linear&lt;br /&gt;
* if link support implements LinkInt32 it uses LinkInt32 otherwise it uses LinkFloat64&lt;br /&gt;
* it uses slope and interccept to convert from raw to engineering units&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;LinkInt32&amp;lt;/tt&amp;gt; is defined as:&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         boolean getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
If convert is linear and getBounds returns true than recordSupport&lt;br /&gt;
uses the returned value to compute slope and intercept. In all&lt;br /&gt;
other cases recordSupport just uses whatever values they have.&lt;br /&gt;
&lt;br /&gt;
For example support for a 16 bit unipolar ADC would set low=0, high=65535,&lt;br /&gt;
and return true.&lt;br /&gt;
If link support can not determine the bounds then getBounds returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE:&amp;lt;/b&amp;gt;The interface implemented by breakpoint tables must be defined.&lt;br /&gt;
It will support the same semantics as the V3 breakpoint tables.&lt;br /&gt;
&lt;br /&gt;
== Output Records ==&lt;br /&gt;
&lt;br /&gt;
The following are two features that link support should implement&lt;br /&gt;
whenever possible:&lt;br /&gt;
# When a record is initalized provide the current value of the output&lt;br /&gt;
# If the actual output is changed by something other than the output record than the output record should also be modified to reflect the new output value.&lt;br /&gt;
&lt;br /&gt;
The first feature is especially desirable when an IOC is rebooted.&lt;br /&gt;
If a hardware output can survive a reboot this is a very desirable feature.&lt;br /&gt;
If the output is to a field bus, a PLC, or to a record in another IOC&lt;br /&gt;
it is often possible for the link support to determine the current value.&lt;br /&gt;
&lt;br /&gt;
The second feature is something that was often asked for in V3 but&lt;br /&gt;
only implemented&lt;br /&gt;
for some special cases. This is especially desirable when the output is&lt;br /&gt;
connected to a system that can have multiple sources of control.&lt;br /&gt;
Examples are GPIB devices with front pannel controls, PLC systems that&lt;br /&gt;
have manual controls or non-epics network access.&lt;br /&gt;
&lt;br /&gt;
For V3 some of the hardware , but none of the soft,&lt;br /&gt;
support implemented the first feature but by&lt;br /&gt;
modifying actual fields in the record. V3 did not implement the second&lt;br /&gt;
feature. Some special device support, not part of base, was implemented&lt;br /&gt;
to support this feature.&lt;br /&gt;
&lt;br /&gt;
For V4 these features are supported as follows:&lt;br /&gt;
&lt;br /&gt;
=== record initialization ===&lt;br /&gt;
&lt;br /&gt;
The link support implements an interface that has a put and a get method.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         boolean getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
If the link support can support readbacks then it implements get&lt;br /&gt;
and returns linkNoop. If it does not support readbacks&lt;br /&gt;
then it implements get by just returning linkNoop.&lt;br /&gt;
&lt;br /&gt;
=== monitors for outputs ===&lt;br /&gt;
&lt;br /&gt;
If output link support can detect when something besides the link support&lt;br /&gt;
itself modifies the output then it implements interface &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt;&lt;br /&gt;
     interface SupportMonitor {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
At initialization recordSupport looks for this interface and if found&lt;br /&gt;
it calls &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt;. The link support calls the callback whenever&lt;br /&gt;
it detects a change in the output that it did not cause. recordSupport&lt;br /&gt;
causes itself to be processed without making a new call to the&lt;br /&gt;
link support.&lt;br /&gt;
---&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_dbdInterfaces&amp;diff=587</id>
		<title>V4 Design: dbdInterfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_dbdInterfaces&amp;diff=587"/>
		<updated>2005-11-02T20:33:54Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: dbdInterfaces - IOC Database Description November 02 2005 &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes  definitions for code that accessses&lt;br /&gt;
IOC records, i.e. the records created from Database Definitions:&lt;br /&gt;
menu, struct, record, link, device, and record instances.&lt;br /&gt;
&lt;br /&gt;
The interfaces support introspection of everything created from Database&lt;br /&gt;
Definitions. The interfaces can be used by tools such as VDCT or on&lt;br /&gt;
a running IOC database.&lt;br /&gt;
&lt;br /&gt;
The definitions can be used by code that use code automatically&lt;br /&gt;
generated from DBD files or by code that uses only introspection.&lt;br /&gt;
&lt;br /&gt;
Code is automatically generated from the following definitions:&lt;br /&gt;
* &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; - Used by record support.&lt;br /&gt;
* &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; - Used by code that understands the struct.&lt;br /&gt;
* &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt; - Used by code that understands the menu.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Syntax =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax is defined so that either C++ and Java implementations can be created.&lt;br /&gt;
&lt;br /&gt;
NOTE: Most of the code fragments use Java syntax.&lt;br /&gt;
&lt;br /&gt;
== Primitive Types ==&lt;br /&gt;
* octet - 8 bit byte&lt;br /&gt;
* boolean - a value that takes the values &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt;&lt;br /&gt;
* int16 - 16 bit signed integer&lt;br /&gt;
* int32 - 32 bit signed integer&lt;br /&gt;
* int64 - 64 bit signed integer&lt;br /&gt;
* float32 - 32 bit IEEE float&lt;br /&gt;
* float64 - 64 bit IEEE float&lt;br /&gt;
&lt;br /&gt;
In Java these types become:&lt;br /&gt;
&lt;br /&gt;
* octet =&amp;gt; byte  BUT no arithmetic is implied&lt;br /&gt;
* boolean =&amp;gt; boolean&lt;br /&gt;
* int16 =&amp;gt; short&lt;br /&gt;
* int32 =&amp;gt; int&lt;br /&gt;
* int64 =&amp;gt; long&lt;br /&gt;
* float32 =&amp;gt; float&lt;br /&gt;
* float64 =&amp;gt; double&lt;br /&gt;
&lt;br /&gt;
In C++ these types become:&lt;br /&gt;
&lt;br /&gt;
* octet =&amp;gt; char  BUT no arithmetic is implied&lt;br /&gt;
* boolean =&amp;gt; bool BUT no arithmetic or conversion to/from int is implied&lt;br /&gt;
* int16 =&amp;gt; int16_t&lt;br /&gt;
* int32 =&amp;gt; int32_t&lt;br /&gt;
* int64 =&amp;gt; int64_t&lt;br /&gt;
* float32 =&amp;gt; float&lt;br /&gt;
* float64 =&amp;gt; double&lt;br /&gt;
&lt;br /&gt;
NOTE:&lt;br /&gt;
* The C++ integer types are from C99 stdint.h&lt;br /&gt;
* Should exceptions be defined?&lt;br /&gt;
&lt;br /&gt;
== enum, struct, interface, class,  string, array ==&lt;br /&gt;
&lt;br /&gt;
In adition to the primitive types the syntax&lt;br /&gt;
uses the terms enum, struct, interface, and array.&lt;br /&gt;
&lt;br /&gt;
=== enum ===&lt;br /&gt;
&lt;br /&gt;
An example of an enum is:&lt;br /&gt;
&lt;br /&gt;
     enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The C++  definition is identical. In Java 5 the definition would be:&lt;br /&gt;
&lt;br /&gt;
     public enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
=== struct ===&lt;br /&gt;
An example of a struct definition is:&lt;br /&gt;
&lt;br /&gt;
     struct DisplayLimitData {&lt;br /&gt;
         float64 low;&lt;br /&gt;
         float64 high;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In C++ this would be:&lt;br /&gt;
&lt;br /&gt;
    class DisplayLimitData {&lt;br /&gt;
    public:&lt;br /&gt;
         double low;&lt;br /&gt;
         double high;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
In Java this would be:&lt;br /&gt;
&lt;br /&gt;
     class DisplayLimitData {&lt;br /&gt;
         public double low;&lt;br /&gt;
         public double high;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== interface ===&lt;br /&gt;
An example of an interface definition is:&lt;br /&gt;
&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void    put(boolean val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class DbfBoolean : public Dbf {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual bool get() = 0;&lt;br /&gt;
         virtual void put(bool val) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
In Java would be:&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void    put(boolean val)&lt;br /&gt;
     }&lt;br /&gt;
=== class ===&lt;br /&gt;
&lt;br /&gt;
Any class definitions are language specific.&lt;br /&gt;
&lt;br /&gt;
=== string ===&lt;br /&gt;
&lt;br /&gt;
For C++ a string will be a &amp;lt;tt&amp;gt;char *&amp;lt;/tt&amp;gt; array containing UTF-8&lt;br /&gt;
compatible characters not necessarily terminated with a null character.&lt;br /&gt;
Wherever a &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt; argument appears, the C++ definition&lt;br /&gt;
will have &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;char *&amp;lt;/tt&amp;gt; arguments.&lt;br /&gt;
&lt;br /&gt;
For Java string will just be a &amp;lt;tt&amp;gt;String&amp;lt;/tt&amp;gt;.&lt;br /&gt;
It is assumed that Java Strings will be converted to/from UTF-8 byte streams&lt;br /&gt;
when the data is transfered to/from the network.&lt;br /&gt;
&lt;br /&gt;
An example of a definition that includes a string argument is&lt;br /&gt;
     void get(String name);&lt;br /&gt;
&lt;br /&gt;
In C++  this will become&lt;br /&gt;
     void get(int lenName, char *name);&lt;br /&gt;
In Java this will become&lt;br /&gt;
     void get(String name);&lt;br /&gt;
=== array ===&lt;br /&gt;
&lt;br /&gt;
An example of a definition that includes an array is:&lt;br /&gt;
&lt;br /&gt;
     void get(float64[] data);&lt;br /&gt;
&lt;br /&gt;
In C++ ,this would become:&lt;br /&gt;
&lt;br /&gt;
     void get(int lenData, double data[]);&lt;br /&gt;
&lt;br /&gt;
In Java this would be:&lt;br /&gt;
&lt;br /&gt;
     void get(double[] data);&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= DbfTypes =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
The following naming conventions are used:&lt;br /&gt;
; Dbf&lt;br /&gt;
: any class starting with Dbf describes a field in a header file generated from a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definition. For example DbfArray describes a field generated from &amp;lt;tt&amp;gt;field(name,array(float64[])&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; Dbd&lt;br /&gt;
: A class name starting with Dbd describes something related to dbd definitions. For example DbdMenu describes a dbd menu definition.&lt;br /&gt;
&lt;br /&gt;
All Dbf and Dbd definitions are interfaces. Thus all access to data is via&lt;br /&gt;
interfaces.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbfTypes.h&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
The following &amp;lt;tt&amp;gt;enum&amp;lt;/tt&amp;gt; definitions describe &lt;br /&gt;
each field in the header files generated from DBD &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; and&lt;br /&gt;
&amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
&lt;br /&gt;
     enum BasicType {&lt;br /&gt;
         basicTypeOctet,    // DbfOctet&lt;br /&gt;
         basicTypeBoolean,  // DbfBoolean&lt;br /&gt;
         basicTypeInt16,    // DbfInt16&lt;br /&gt;
         basicTypeInt32,    // DbfInt32&lt;br /&gt;
         basicTypeInt64,    // DbfInt64&lt;br /&gt;
         basicTypeFloat32,  // DbfFloat32&lt;br /&gt;
         basicTypeFloat64,  // DbfFloat64&lt;br /&gt;
         basicTypeString,   // DbfString&lt;br /&gt;
         basicTypeArray,    // DbfArray&lt;br /&gt;
         basicTypeStruct,   // DbfStruct&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum DbfType {&lt;br /&gt;
         dbfTypeBasic,       // DbfOctet,...,DbfStruct&lt;br /&gt;
         dbfTypeMenu,        // DbfMenu&lt;br /&gt;
         dbfTypeEnum,        // DbfEnum&lt;br /&gt;
         dbfTypeLink,        // DbfLink&lt;br /&gt;
         dbfTypeMDArray,     // DbfMDArray&lt;br /&gt;
         dbfTypeTimeStamp    // DbfTimeStamp&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Database Fields =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each database field is accessed via an interface which all extend&lt;br /&gt;
the following interface:&lt;br /&gt;
&lt;br /&gt;
     interface Dbf{&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         boolean isPrimitive(); // BasicTypeBoolean,...,BasicTypeFloat64&lt;br /&gt;
         boolean isBasic();&lt;br /&gt;
         BasicType getBasicType();&lt;br /&gt;
         RecordInstance getRecord();&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The interfaces are designed so that a field can be accessded&lt;br /&gt;
without exposing the address of its data.&lt;br /&gt;
&lt;br /&gt;
== Primitive Types ==&lt;br /&gt;
&lt;br /&gt;
DbfOctet, ..., DbfFloat64 are all interfaces with methods get and put.&lt;br /&gt;
    &lt;br /&gt;
     interface DbfOctet extends Dbf {&lt;br /&gt;
         octet get();&lt;br /&gt;
         void put(octet val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void put(boolean val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt16 extends Dbf {&lt;br /&gt;
         int16 get();&lt;br /&gt;
         void put(int16 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt32 extends Dbf {&lt;br /&gt;
         int32 get();&lt;br /&gt;
         void put(int32 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt64 extends Dbf {&lt;br /&gt;
         int64 get();&lt;br /&gt;
         void put(int64 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfFloat32 extends Dbf {&lt;br /&gt;
         float32 get();&lt;br /&gt;
         void put(float32 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfFloat64 extends Dbf {&lt;br /&gt;
         float64 get();&lt;br /&gt;
         void put(float64 val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Record support code can access such fields via the generated header&lt;br /&gt;
file. Some examples are:&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     ...&lt;br /&gt;
     precord.ffloat.put(10.0);&lt;br /&gt;
     ...&lt;br /&gt;
     short myint = record.fint.get();&lt;br /&gt;
&lt;br /&gt;
Code that does not include the generated header file can access these fields&lt;br /&gt;
via the introspection interfaces described later in this document.&lt;br /&gt;
For example code that expects a float64 field can access it via&lt;br /&gt;
&lt;br /&gt;
     Dbf dbf =  RecordInstanceLocate.getField(&amp;quot;recordname.value&amp;quot;);&lt;br /&gt;
     if(dbf==null&lt;br /&gt;
     || !dbf.isPrimitive()&lt;br /&gt;
     || (dbf.getBasicType() != basicTypeFloat64) ) // do something&lt;br /&gt;
     DbfFloat64 dbfdouble = (DbfFloat64)dbf;&lt;br /&gt;
     dbfdouble.put(10.0);&lt;br /&gt;
&lt;br /&gt;
or more concisely (but exception may be thrown)&lt;br /&gt;
     DbfConvertPrimitive(RecordInstanceLocate.getField(&amp;quot;recordname.value&amp;quot;),10.0);&lt;br /&gt;
&lt;br /&gt;
== String fields ==&lt;br /&gt;
&lt;br /&gt;
The interface for a string field is:&lt;br /&gt;
&lt;br /&gt;
     interface DbfString extends Dbf {&lt;br /&gt;
        int32 getLength();&lt;br /&gt;
        void get(string value);&lt;br /&gt;
        void setPutSize(int32 size);&lt;br /&gt;
        void put(string value);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following code prints a string.&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     String string;&lt;br /&gt;
     record.fstring.get(string);&lt;br /&gt;
     printf(&amp;quot;%s\n&amp;quot;,string);&lt;br /&gt;
&lt;br /&gt;
Code that does not include the header file can use the introspection methods&lt;br /&gt;
to locate the DbfString that provides access to the field.&lt;br /&gt;
&lt;br /&gt;
== Structure Fields ==&lt;br /&gt;
&lt;br /&gt;
     interface DbfStruct extends Dbf {&lt;br /&gt;
         int16 getNfields();&lt;br /&gt;
         Dbf getInterface(int16 index);&lt;br /&gt;
         DbdField getDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following traverses the fields of a DbfStruct&lt;br /&gt;
&lt;br /&gt;
     DbfStruct dbfStruct;&lt;br /&gt;
     &lt;br /&gt;
     for(i=0; i &amp;lt; dbfStruct.getNfields(); i++) {&lt;br /&gt;
         DbdField dbdField = dbfStruct.getDescription(i);&lt;br /&gt;
         String name;&lt;br /&gt;
         dbdField.getName(name);&lt;br /&gt;
         printf(&amp;quot;field %s\n&amp;quot;,name);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Structure fields can only be accessed via introspection.&lt;br /&gt;
However, for each structure, code is generated that does the introspection.&lt;br /&gt;
For example DisplayLimitData can be obtained via the statements:&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     DisplayLimitData limit = new DisplayLimitData();&lt;br /&gt;
     &lt;br /&gt;
     ...&lt;br /&gt;
     DisplayLimitSupport.get(record.displayLimit,limit);&lt;br /&gt;
     printf(&amp;quot;low %f high %f\n&amp;quot;,limit.low,limit.high);&lt;br /&gt;
&lt;br /&gt;
== Array Fields ==&lt;br /&gt;
&lt;br /&gt;
The generated header file will have a type that extends &amp;lt;tt&amp;gt;DbfArray&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     interface DbfArray extends Dbf {&lt;br /&gt;
        DbfType getType();&lt;br /&gt;
        int32 getNelements();&lt;br /&gt;
        void setNelements(int32 len);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfBooleanArray extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, boolean[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, boolean[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfOctetArray extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, octet[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, octet[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt16Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int16[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int16[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt32Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int32[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int32[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt64Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int64[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int64[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfFloat32Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, float32[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, float32[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfFloat64Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, float64[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, float64[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfStringArray extends DbfArray {&lt;br /&gt;
         DbfString getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfArrayArray extends DbfArray {&lt;br /&gt;
         DbfArray getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfStructArray extends DbfArray {&lt;br /&gt;
         DbfStruct getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfMenuArray extends DbfArray {&lt;br /&gt;
         DbfMenu getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfEnumArray extends DbfArray {&lt;br /&gt;
         DbfEnum getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfLinkArray extends DbfArray {&lt;br /&gt;
         DbfLink getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following puts data into a float64 field.&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
&lt;br /&gt;
     double[] data = new double[] {1.0,2.0,3.0};;&lt;br /&gt;
     if(!record.ffloat.isPrimitive()&lt;br /&gt;
     || record.ffloat.getBasicType()!=basicTypeFloat64)  // DO SOMTHING!!!!&lt;br /&gt;
     ...&lt;br /&gt;
     array.put(0,nelements,precord-&amp;gt;data);&lt;br /&gt;
&lt;br /&gt;
or more concisely&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     ...&lt;br /&gt;
     DbfConvertPrimitive.put(precord.array,new double[] {1.0,2.0,3.0});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfMDArray ==&lt;br /&gt;
NOT YET DEFINED&lt;br /&gt;
     &lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; is described as:&lt;br /&gt;
     interface DbfMenu extends Dbf {&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
         void putIndex(int16 val);&lt;br /&gt;
         DbdMenu getDbdMenu();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; allows the menu index to be set and retrieved&lt;br /&gt;
and also provides access to the DbdMenu.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; field can be accessed via the generated header file or via&lt;br /&gt;
the introspection methods.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfEnum ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfEnum&amp;lt;/tt&amp;gt; is described as:&lt;br /&gt;
     interface DbfEnum extends Dbf {&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
         void putIndex(int16 val);&lt;br /&gt;
         DbfStringArray getChoiceArray();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfEnum&amp;lt;/tt&amp;gt; allows the enum index to be set and retrieved&lt;br /&gt;
and also provides access to the The DbfArray field that contains the choices.&lt;br /&gt;
&lt;br /&gt;
== DbfLink ==&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;tt&amp;gt;DbfLink&amp;lt;/tt&amp;gt; is described as&lt;br /&gt;
 &lt;br /&gt;
     interface DbfLink extends Dbf {&lt;br /&gt;
         DbdLink getDbdLink();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== DbfTimeStamp ==&lt;br /&gt;
&lt;br /&gt;
     struct TimeStamp {&lt;br /&gt;
         int64 secondsSinceEpoch;&lt;br /&gt;
         int32 nanoSeconds;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfTimeStamp extends Dbf {&lt;br /&gt;
         void get(TimeStamp timeStamp);&lt;br /&gt;
         void put(TimeStamp timeStamp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= DbdStatements =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
These describe everything defined in database definition files.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdMenu&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdMenu {&lt;br /&gt;
         int32 getNameLength(&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         int16 getNchoices();&lt;br /&gt;
         int32 getChoiceNameLength(int16 index);&lt;br /&gt;
         void getChoice(int16 index,String choice);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdSupport&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdSupport {&lt;br /&gt;
         int32 getChoiceNameLength();&lt;br /&gt;
         void getChoiceName(String name);&lt;br /&gt;
         int32 getSupportStructNameLength();&lt;br /&gt;
         void getSupportStructName(String name);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdStruct&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;DbdRecord&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdAttribute {&lt;br /&gt;
         int32 getDefaultLength();&lt;br /&gt;
         void getDefault(String value);&lt;br /&gt;
         boolean isReadonly();&lt;br /&gt;
         boolean isDesign();&lt;br /&gt;
         boolean isSpecial();&lt;br /&gt;
         int16 getAsl();&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbdDefaults {}&lt;br /&gt;
    &lt;br /&gt;
     interface DbdArrayDefaults extends DbdDefaults{&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         int32 getLength();&lt;br /&gt;
&lt;br /&gt;
     interface DbdStructDefaults extends DbdDefaults{&lt;br /&gt;
         DbdStruct getDescription();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdField {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         DbdDefaults getDefaults();&lt;br /&gt;
         DbdAttribute getAttributes();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdStruct {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         int16 getNumberFields();&lt;br /&gt;
         DbdField getFieldDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdRecord {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         int16 getNumberFields();&lt;br /&gt;
         DbdField getFieldDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Record Instance ==&lt;br /&gt;
&lt;br /&gt;
     interface RecordInstance {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         DbdRecord getDescription();&lt;br /&gt;
         DbfStruct getInstance();&lt;br /&gt;
         Dbf getField(String fieldName);&lt;br /&gt;
         Dbf getField(int16 index)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;getNameLength&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get length of record name&lt;br /&gt;
; &amp;lt;tt&amp;gt;getName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the record name&lt;br /&gt;
; &amp;lt;tt&amp;gt;getDescription&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the description of the record specific portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getRecordCommonDescription&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the description of RecordCommon&lt;br /&gt;
; &amp;lt;tt&amp;gt;getInstance&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get instance for the record specific portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getRecordCommonInstance&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get instance for for RecordCommon portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getField&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get field instance.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Locate Interfaces =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Classes are available to find and traverse the various Dbd definitons&lt;br /&gt;
and record instances.&lt;br /&gt;
The implementation will be language specific. For Java they will be something&lt;br /&gt;
like the following:&lt;br /&gt;
&lt;br /&gt;
In addition the following is defined:&lt;br /&gt;
&lt;br /&gt;
     public class DbdLocate {&lt;br /&gt;
         public DbdMenu getMenu(String name);&lt;br /&gt;
         public DbdLink getLink(String name);&lt;br /&gt;
         public DbdStruct getStruct(String name);&lt;br /&gt;
         public DbdRecord getRecord(String name);&lt;br /&gt;
         public LinkedList&amp;lt;DbdMenu&amp;gt; menuList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdLink&amp;gt; linkList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdStruct&amp;gt; structList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdRecord&amp;gt; recordList;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public class RecordInstanceLocate {&lt;br /&gt;
         public RecordInstance getRecord(String name);&lt;br /&gt;
         public Dbf getField(String name);&lt;br /&gt;
         public Dbf getField(String recordName, String fieldName);&lt;br /&gt;
         public LinkedList&amp;lt;RecordInstance&amp;gt; instanceList;&lt;br /&gt;
         public LinkedList&amp;lt;RecordInstance&amp;gt; instanceList(String recordTypeName);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; Are the above methods static or should there be something like&lt;br /&gt;
     public class FindLocator {&lt;br /&gt;
         public static DbdLocate findDbdLocate();&lt;br /&gt;
         public static RecordInstance findRecordInstance();&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
The following locates a specific menu.&lt;br /&gt;
&lt;br /&gt;
     DbdMenu menu = DbdLocate.get(&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
     if(menu!=null) printf(&amp;quot;found menu %s\n&amp;quot;,&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
The following locates a field of a record instance.&lt;br /&gt;
&lt;br /&gt;
     Dbf field = RecordInstanceLocate.getField(&amp;quot;example.value&amp;quot;);&lt;br /&gt;
     if(addr!=null) printf(&amp;quot;found %s\n&amp;quot;,&amp;quot;example.value&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Generated Code =&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example code shown below uses Java syntax.&lt;br /&gt;
It assumes the following definitions:&lt;br /&gt;
&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,double)&lt;br /&gt;
         field(high,double)&lt;br /&gt;
     }&lt;br /&gt;
     record(Example) {&lt;br /&gt;
         ...&lt;br /&gt;
         field(octet,octet)&lt;br /&gt;
         field(fboolean,boolean)&lt;br /&gt;
         field(fint,int16)&lt;br /&gt;
         ...&lt;br /&gt;
         field(ffloat,float64)&lt;br /&gt;
         field(string,string)&lt;br /&gt;
         field(array,array(double[])&lt;br /&gt;
         field(mdarray,array(double[,])&lt;br /&gt;
         field(menu,menu(name))&lt;br /&gt;
         field(fenum,enum)&lt;br /&gt;
         field(link,link)&lt;br /&gt;
         field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
From this the following Java code is automatically generated.&lt;br /&gt;
     public class DisplayLimit implements Struct{&lt;br /&gt;
         public DbfFloat64 low;&lt;br /&gt;
         public DbfFloat64 high;&lt;br /&gt;
         ...&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case lowIndex: return(low);&lt;br /&gt;
                 case highIndex: return(high);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
             return null;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     public class ExampleRecord implements Struct {&lt;br /&gt;
         ...&lt;br /&gt;
         public DbfOctet     ctet;&lt;br /&gt;
         public DbfBoolean   fboolean;&lt;br /&gt;
         public DbfInt16     fint;&lt;br /&gt;
         ...&lt;br /&gt;
         public DbfFloat64   ffloat;&lt;br /&gt;
         public DbfString    string;&lt;br /&gt;
         public DbfArray     array;&lt;br /&gt;
         public DbfMDArray   mdarray;&lt;br /&gt;
         public DbfMenu      menu;&lt;br /&gt;
         public DbfEnum      fenum;&lt;br /&gt;
         public DbfLink      link;&lt;br /&gt;
         public DbfStruct    displayLimit;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case fbooleanIndex : return(fboolean);&lt;br /&gt;
                 ...&lt;br /&gt;
                 case displayLimitIndex: return(displayLimit);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Similar code is generated for C++.&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Examples&amp;diff=2730</id>
		<title>V4 DBD Examples</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Examples&amp;diff=2730"/>
		<updated>2005-11-02T19:54:24Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Example Record Types November 02 2005&lt;br /&gt;
= Overview =&lt;br /&gt;
This document present proposed V4 replacements for a few of the&lt;br /&gt;
V3 record types.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= aoRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
aoRecord.dbd might be defined as follows:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
 record(AoRecord) {&lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
     field(desiredValue, float64) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(currentValue, float64) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(out,link)&lt;br /&gt;
     field(outputRateOfChange, float64)&lt;br /&gt;
     field(desiredOutputLink,link)&lt;br /&gt;
     field(closedLoop, bool)&lt;br /&gt;
     field(outputIncremental, bool)&lt;br /&gt;
     field(convert, menu(menuConvert)) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(linearConvert, struct(LinearConvert)) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(convertTable,string);&lt;br /&gt;
     field(units, string)&lt;br /&gt;
     field(displayLimit, struct(DisplayLimit))&lt;br /&gt;
     field(controlLimit, struct(ControlLimit))&lt;br /&gt;
     field(alarmLimit, struct(AlarmLimit))&lt;br /&gt;
     field(rawValue, int32) {&lt;br /&gt;
         design(no)&lt;br /&gt;
     }&lt;br /&gt;
     field(readBackValue, int32) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(simulation,struct(SimulationFloat64))&lt;br /&gt;
     field(invalidAction, menu(menuIvoa))&lt;br /&gt;
     field(invalidValue, float64)&lt;br /&gt;
     view(value) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
             property(controlLimit, controlLimit)&lt;br /&gt;
             property(alarmLimit, alarmLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(output) {&lt;br /&gt;
         property(value, outValue) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(raw) {&lt;br /&gt;
         property(value, rawValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(readback) {&lt;br /&gt;
         property(value, readBackValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 } &lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= calcRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
calcRecord.dbd defines the following:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
 struct(CalcInpLink) {&lt;br /&gt;
     field(block,boolean)&lt;br /&gt;
     field(link,link)&lt;br /&gt;
     field(value,float64)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 record(CalcRecord){&lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
     field(value,float64) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(calc,string) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(input,array(struct(CalcInpLink)[])) &lt;br /&gt;
     field(units,string)&lt;br /&gt;
     field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     field(alarmLimit,struct(AlarmLimit))&lt;br /&gt;
     view(result) {&lt;br /&gt;
         property(value, result) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
             property(alarmLimit, alarmLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(expression) {&lt;br /&gt;
         property(value, calc)&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= mbbiRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
mbbiRecord.dbd could be:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
 struct(MbbiState) {&lt;br /&gt;
     field(name, string)&lt;br /&gt;
     field(value, array(octet[]))&lt;br /&gt;
     field(severity, menu(menuAlarmSevr))&lt;br /&gt;
 }&lt;br /&gt;
 record(MbbiRecord) {&lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
     field(state, array(struct(MbbiState)[])) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
#NOTE: stateName needed because enum must refer to array of string&lt;br /&gt;
     field(stateName,array(string[])) {&lt;br /&gt;
         design(no) readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(value, enum(stateName)) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(unknownStateSeverity, menu(menuAlarmSevr))&lt;br /&gt;
     field(changeStateSeverity, menu(menuAlarmSevr))&lt;br /&gt;
     field(inp, link)&lt;br /&gt;
     field(rawValue, array(octet[])) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(hardwareShift, int16) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(hardwareMask, array(octet[]) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     view(choice) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(raw) {&lt;br /&gt;
         property(value, raw) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= waveformRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
waveformRecord.dbd defines the following:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
 record(WaveformRecord) {&lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
     field(value, array([])) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(reArm,bool)&lt;br /&gt;
     field(io,link)&lt;br /&gt;
     field(units,string)&lt;br /&gt;
     field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     field(busy,bool) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     view(value) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=2723</id>
		<title>V4 DBD Statement Syntax</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=2723"/>
		<updated>2005-11-02T19:53:04Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DBD Statement Syntax November 02 2005&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
This document presents the syntax for V4 database definition files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; This version of the database definition and database instance&lt;br /&gt;
syntax does not provide:&lt;br /&gt;
# a direction for links&lt;br /&gt;
# a way to select a subset of the support definitions&lt;br /&gt;
&lt;br /&gt;
Support can exist for either a link field or a struct field.&lt;br /&gt;
The support definition is just&lt;br /&gt;
&lt;br /&gt;
    support(choiceName,supportStructName)&lt;br /&gt;
&lt;br /&gt;
When a record instance is created any choiceName can be specified for&lt;br /&gt;
a link or struct field. If an invalid choice is made, an error will&lt;br /&gt;
be issued during initialization.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= General Statements =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== include ==&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;filename&amp;quot;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;filename&amp;lt;/tt&amp;gt;&lt;br /&gt;
: must be a valid filename&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Include statements can be used at the top level, or inside the braces of a &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definition.&lt;br /&gt;
&lt;br /&gt;
== # comment ==&lt;br /&gt;
&lt;br /&gt;
 # anything&lt;br /&gt;
&lt;br /&gt;
Anything on a line after a &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; 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 &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; character has no special meaning.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== menu ==&lt;br /&gt;
&lt;br /&gt;
A menu is an enumerated type where the choice strings are defined once for each IOC.  Menus are defined like this:&lt;br /&gt;
&lt;br /&gt;
 menu(menuName) {&lt;br /&gt;
     choice(choiceName, &amp;quot;choiceValue&amp;quot;)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can be any UTF-8 compatible string, which should be unique within the context of this menu.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 menu(menuScan) {&lt;br /&gt;
     choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
     choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
     choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
     choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
     choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Structures, Record types, Fields and Views =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== struct ==&lt;br /&gt;
&lt;br /&gt;
A structure is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 struct(name) {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The structure name must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular structure.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
&lt;br /&gt;
== record ==&lt;br /&gt;
&lt;br /&gt;
A record type is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 record(name) extends RecordCommon {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     view(viewName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The record type name. It must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;extends RecordCommon&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This states that the record type extends the set of fields defined in &amp;quot;V4 DB RecordCommon&amp;quot;. 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 &amp;lt;tt&amp;gt;extends&amp;lt;/tt&amp;gt; phrase.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular record type and its parents (extends ...).&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#Views of a record|Views of a record]] below.&lt;br /&gt;
&lt;br /&gt;
== fieldType ==&lt;br /&gt;
&lt;br /&gt;
Both &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; define a field as:&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The syntax for &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
=== Basic types: octet, boolean, numerics, and string ===&lt;br /&gt;
&lt;br /&gt;
The following field types have no arguments:&lt;br /&gt;
&amp;lt;tt&amp;gt;octet&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int32&amp;lt;/tt&amp;gt;,  &amp;lt;tt&amp;gt;int64&amp;lt;/tt&amp;gt;,&lt;br /&gt;
&amp;lt;tt&amp;gt;float32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;float64&amp;lt;/tt&amp;gt;,  and &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Examples: &lt;br /&gt;
     field(description,string)&lt;br /&gt;
     field(value,float64)&lt;br /&gt;
&lt;br /&gt;
=== enum ===&lt;br /&gt;
&lt;br /&gt;
An &amp;lt;tt&amp;gt;enum&amp;lt;/tt&amp;gt; field takes one argument after the type name:&lt;br /&gt;
&lt;br /&gt;
     enum(fieldName)&lt;br /&gt;
&lt;br /&gt;
where fieldName is the name of another field in the same record that must be of type &amp;lt;tt&amp;gt;array(string[])&amp;lt;/tt&amp;gt;.  The values in this other field at runtime define the available choice strings for the enum field.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
     field(choices, array(string[])&lt;br /&gt;
     field(value, enum(choices))&lt;br /&gt;
&lt;br /&gt;
=== menu ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt; field is defined like this:&lt;br /&gt;
     menu(menuName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt; is the name of the menu.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     field(scan, menu(menuScan))&lt;br /&gt;
&lt;br /&gt;
=== struct ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; field is declared using the type name&lt;br /&gt;
     struct(structName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;structName&amp;lt;/tt&amp;gt; is the name of a struct which must have been previously defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
      struct(Point) {&lt;br /&gt;
          field(x,float64)&lt;br /&gt;
          field(y,float64)&lt;br /&gt;
          field(z,float64)&lt;br /&gt;
       }&lt;br /&gt;
       ...&lt;br /&gt;
       record(haspoint) extends RecordCommon {&lt;br /&gt;
           ...&lt;br /&gt;
           field(point, struct(point))&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
=== array ===&lt;br /&gt;
&lt;br /&gt;
An array field uses definitions like these:&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 3-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[,,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 2-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;arrayType&amp;lt;/tt&amp;gt; may be any fieldType except &amp;lt;tt&amp;gt;array&amp;lt;/tt&amp;gt;, 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]]&lt;br /&gt;
* &amp;lt;tt&amp;gt;capacity&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(VAL1D,array(float64[]))  #1d array with arbitrary capacity&lt;br /&gt;
     field(VAL2D,array(float64[,])) #2d array with arbitrary capacities&lt;br /&gt;
     field(anyTypeAnyD,array())     #arbitrary type,number of dimensions, and capacities&lt;br /&gt;
&lt;br /&gt;
=== link ===&lt;br /&gt;
&lt;br /&gt;
This field type can get or put data from/to some source outside of the record.&lt;br /&gt;
Link fields replace the DBF_INLINK, DBF_OUTLINK, and DTYP fields from EPICS V3.&lt;br /&gt;
&lt;br /&gt;
A link field's choices come from link definitions - see the [[#link]] section below for more details.&lt;br /&gt;
A link can be a link to another database record, to hardware device support,&lt;br /&gt;
or something else.&lt;br /&gt;
&lt;br /&gt;
The syntax is:&lt;br /&gt;
&lt;br /&gt;
     link&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(disableLink,link)&lt;br /&gt;
     field(process, link)&lt;br /&gt;
     field(inp,link)&lt;br /&gt;
&lt;br /&gt;
== fieldAttribute ==&lt;br /&gt;
&lt;br /&gt;
Each field definition has several associated attributes, the values of which are set like this:&lt;br /&gt;
&lt;br /&gt;
     default(&amp;quot;fieldValue&amp;quot;)&lt;br /&gt;
     readonly(yesNo)&lt;br /&gt;
     design(yesNo)&lt;br /&gt;
     special(yesNo)&lt;br /&gt;
     asl(securityLevel)&lt;br /&gt;
     link(yesNo)&lt;br /&gt;
&lt;br /&gt;
'''Marty thinks we should get rid of these two:'''&lt;br /&gt;
     prompt(&amp;quot;promptString&amp;quot;)&lt;br /&gt;
     group(&amp;quot;promptGroup&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
'''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.'''&lt;br /&gt;
&lt;br /&gt;
The attribute parameter values have the following meanings:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;default(&amp;quot;fieldValue&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;readonly(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can this field be modified via channel access or database links?  Takes the value No if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;design(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;special(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;asl(securityLevel)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Channel Access security level for this field, 0 or 1.  Takes the value 1 if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
''These attributes may disappear, see comment above:''&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;prompt(&amp;quot;promptString&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;group(&amp;quot;promptGroup&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
== view ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;field&amp;quot; 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).&lt;br /&gt;
&lt;br /&gt;
A simple view looks like this:&lt;br /&gt;
&lt;br /&gt;
 view(viewName) {&lt;br /&gt;
     property(propName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     property(propName, fieldPath)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The view name must be a valid C identifier, which must be unique in the context of the particular record type.&lt;br /&gt;
; &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: A Data Access property name, which must be a valid C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The path to a field in this record type. To use a field inside a structure field, give the full path to that field: &amp;lt;tt&amp;gt;controlLimit.upper&amp;lt;/tt&amp;gt; for example.&lt;br /&gt;
: If &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; resolves to a structure, a property catalog containing the whole structure will be sent, with property names matching the structure's field names.&lt;br /&gt;
: The &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; may be omitted as long as there is a subordinate property catalog below this property.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 record(ao) extends RecordCommon {&lt;br /&gt;
     field(value, float64) { ... }&lt;br /&gt;
     field(outValue, float64) { ... }&lt;br /&gt;
     field(rawValue, int32) { ... }&lt;br /&gt;
     field(units, string) { ... }&lt;br /&gt;
     field(displayLimit, struct(displayLimit)) { ... }&lt;br /&gt;
     ...&lt;br /&gt;
     view(value)&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(outValue)&lt;br /&gt;
         property(value, outValue) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(rawValue)&lt;br /&gt;
         property(value, rawValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;support&amp;lt;/tt&amp;gt; statement describes an implementation of support for a link&lt;br /&gt;
or struct field.&lt;br /&gt;
Link support can be any of the following:&lt;br /&gt;
* A link to another record either local or remote&lt;br /&gt;
* A link to hardware support&lt;br /&gt;
* Something else.&lt;br /&gt;
&lt;br /&gt;
The syntax for these is:&lt;br /&gt;
&lt;br /&gt;
 support(choiceName)&lt;br /&gt;
or&lt;br /&gt;
 support(choiceName,supportStructName)&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;supportStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
When a record instance is created the choiceName&lt;br /&gt;
selects the support to attach to a record link.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     link(processLink,ProcessLink)&lt;br /&gt;
     link(monitorLink,MonitorLink)&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Record_Processing&amp;diff=2746</id>
		<title>V4 Design: Record Processing</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Record_Processing&amp;diff=2746"/>
		<updated>2005-11-02T19:52:08Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Record Processing November 02 2005 &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;UNRESOLVED ISSUES&amp;lt;/b&amp;gt;&lt;br /&gt;
* This document is still evolving&lt;br /&gt;
* Monitors&lt;br /&gt;
** How will monitor data be managed?&lt;br /&gt;
** Big problem is how will array data be managed?&lt;br /&gt;
* Alarms&lt;br /&gt;
** How will V4 handle alarms?&lt;br /&gt;
* Events&lt;br /&gt;
** What is the V4 event model?&lt;br /&gt;
** What is required from the IOC database?&lt;br /&gt;
&lt;br /&gt;
This document described semantics for V4 record processing that are&lt;br /&gt;
different than for V3.&lt;br /&gt;
This includes the following:&lt;br /&gt;
* Semantics for record processing&lt;br /&gt;
* Semantics for Database and Channel Access Links.&lt;br /&gt;
* Record Locking&lt;br /&gt;
* Posting database monitors&lt;br /&gt;
* Status and Alarm Severity&lt;br /&gt;
* Access to array and structure fields.&lt;br /&gt;
&lt;br /&gt;
This version is based on feedback from the EPICS core developer's&lt;br /&gt;
meeting at ANL/APS on July 11th through July 14th.&lt;br /&gt;
In addition discussions with Andrew Johnson and Eric Norum have &lt;br /&gt;
led to many of the ideas described below.&lt;br /&gt;
This wiki is a companion to the wiki &amp;quot;V4 Design: dbdInterfaces&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
V3 record processing semantics do not work well for data&lt;br /&gt;
acquisition applications. An example of data acquisition is:&lt;br /&gt;
*  Move sample to new position.&lt;br /&gt;
** Several motors may be involved&lt;br /&gt;
** While moving post monitors to show current position, etc.&lt;br /&gt;
* Sample data&lt;br /&gt;
* Wait until CA client has fetched the data before next move.&lt;br /&gt;
&lt;br /&gt;
SynAPPS provides the Scan, motor, etc records which help with&lt;br /&gt;
data processing applications. These records process as follows:&lt;br /&gt;
&lt;br /&gt;
* Record does not complete processing until all inputs, outputs, etc done. Not completing means that they do not call recGblFwdLink until all proccessing is complete. Note that recGblFwdLink is what causes the V3 ioc to complete record processing.&lt;br /&gt;
* While waiting for asynchronous events these records have PACT=0 but keep state that shows it is still active&lt;br /&gt;
* Can be scanned and issue monitors while internal state is active&lt;br /&gt;
&lt;br /&gt;
Leaving PACT 0 but not calling recGblFwdLink was not anticipated when the V3 record processing semantics were created.&lt;br /&gt;
For V4 a record can be processed while it is waiting&lt;br /&gt;
for asynchronous processing to complete.&lt;br /&gt;
&lt;br /&gt;
In V3, if an input link is asynchronous, Process Passive does not wait&lt;br /&gt;
for asynchronous processing to complete before fetching data.&lt;br /&gt;
This also complicated data acquisition applications.&lt;br /&gt;
&lt;br /&gt;
V4 record processing is designed to make data acquisition easier.&lt;br /&gt;
Both input and output links can wait for record processing.&lt;br /&gt;
This is done, however, without record support blocking.&lt;br /&gt;
If blocking makes it easier to implement record support,&lt;br /&gt;
then the support can spawn a separate thread that does block.&lt;br /&gt;
Record support can communicate with the separate thread to decide when&lt;br /&gt;
to complete record processing.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Overview of V4 Record Processing =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
V4 will provide a replacement for dbProcess.&lt;br /&gt;
The name may be different but for now it will still be called dbProcess.&lt;br /&gt;
&lt;br /&gt;
In V4 database access and channel access appear the same to record and&lt;br /&gt;
link support.&lt;br /&gt;
Only the implementation knows the difference.&lt;br /&gt;
In this document the term channelAccess will mean access to a record.&lt;br /&gt;
Thus it can mean a workstation client or a field of&lt;br /&gt;
a record that is a link to a record.&lt;br /&gt;
&lt;br /&gt;
V4 also allows support for &amp;lt;b&amp;gt;struct&amp;lt;/b&amp;gt; fields.&lt;br /&gt;
For example base provides support for &lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
In the record types provided with base, this is the first field.&lt;br /&gt;
The fields in &amp;lt;tt&amp;gt;RecordCommon&amp;lt;/tt&amp;gt; are the V4 replacement for&lt;br /&gt;
the V3 dbCommon fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
V4 record processing has the following features.&lt;br /&gt;
&lt;br /&gt;
* database fields&lt;br /&gt;
** &amp;quot;owned&amp;quot; by database not record support&lt;br /&gt;
** fields can only be accessed via interfaces&lt;br /&gt;
** support can optionally provide storage for data associated with a field&lt;br /&gt;
** for channelAccess all fields appear as type primitive, string, struct, array or combination thereof&lt;br /&gt;
* dbProcess&lt;br /&gt;
** processes synchronous linked records by queuing requests rather than recursive calls to dbProcess&lt;br /&gt;
** can be called an arbitrary number of times while record is active&lt;br /&gt;
* link&lt;br /&gt;
** always has associated support&lt;br /&gt;
** can be record link or can be something else, e.g. a link to hardware&lt;br /&gt;
* record link&lt;br /&gt;
** can request process and/or wait for asynchronous completion&lt;br /&gt;
** local synchronous requests queued by dbProcess&lt;br /&gt;
** record is active and can be processed while asynchronous links active&lt;br /&gt;
* struct fields&lt;br /&gt;
** Can have associated support which can be synchronous or asynchronous&lt;br /&gt;
* block&lt;br /&gt;
** is requested via a separate field&lt;br /&gt;
** if true than support waits for all outstanding I/O to complete before further processing&lt;br /&gt;
** if false than asynchronous support can proceed in parallel&lt;br /&gt;
* lock&lt;br /&gt;
** record instances are locked&lt;br /&gt;
** dbProcess locks before calling support&lt;br /&gt;
** other code can also lock&lt;br /&gt;
** Two records can be locked without deadlock&lt;br /&gt;
* monitors&lt;br /&gt;
** dbProcess handles monitors&lt;br /&gt;
** support triggers monitors by writing to fields&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Database Fields =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
== Field Access by Support Code ==&lt;br /&gt;
Support code can access database fields only via interfaces implemented by&lt;br /&gt;
the IOC database.&lt;br /&gt;
Thus record fields are owned by the IOC database not by record support.&lt;br /&gt;
&lt;br /&gt;
Support code can register to provide storage for particular fields.&lt;br /&gt;
For example support code could implement a circular buffer for field &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
When some other code&lt;br /&gt;
request the array associated with &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, the IOC database&lt;br /&gt;
calls the support. The support returns the first portion of the circular&lt;br /&gt;
buffer and the caller must make an additional call to retrieve the rest of&lt;br /&gt;
the circular buffer.&lt;br /&gt;
&lt;br /&gt;
== Field Access by Channel Access ==&lt;br /&gt;
&lt;br /&gt;
For V4 database access and channel access appear the same to record&lt;br /&gt;
instances.&lt;br /&gt;
It is only the code that implements link support that knows the difference.&lt;br /&gt;
If a linked record is local, database access is used, and, if the record&lt;br /&gt;
is remote, channel access.&lt;br /&gt;
&lt;br /&gt;
V4 allows channel access to the following types of fields:&lt;br /&gt;
&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* one dimensional array of primitive or string or struct&lt;br /&gt;
* struct with fields of following types:&lt;br /&gt;
** primitive&lt;br /&gt;
** string&lt;br /&gt;
** struct&lt;br /&gt;
** array of primitive or string or struct&lt;br /&gt;
&lt;br /&gt;
For other database field types, i.e. links, the database will make the field&lt;br /&gt;
appear as one of the above types. For example a link field will appear&lt;br /&gt;
as a string with syntax that matches the information associated with the link.&lt;br /&gt;
For example a process link will have a string something like&lt;br /&gt;
    support(processLink) ProcessLink(pvname = 'pvname'; wait = true)&lt;br /&gt;
where&lt;br /&gt;
; &amp;lt;tt&amp;gt;processLink&amp;lt;/tt&amp;gt;&lt;br /&gt;
: selects the support for a process link&lt;br /&gt;
; &amp;lt;tt&amp;gt;ProcessLink&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Names the struct that the support uses for configuration information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Record Processing Semantics =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section describes the semantics implemented by dbProcess.&lt;br /&gt;
&lt;br /&gt;
The following are involved in record processing&lt;br /&gt;
* dbProcess&lt;br /&gt;
** implements a queue for local records that are processed because of record links&lt;br /&gt;
** posts monitors caused by field changes during record processing&lt;br /&gt;
* record support&lt;br /&gt;
** calls support code for RecordCommon fields&lt;br /&gt;
** is responsible for record instance fields&lt;br /&gt;
** calls link/struct support via interfaces implemented by the support&lt;br /&gt;
* link support&lt;br /&gt;
** can be links to other records, to driver support, etc&lt;br /&gt;
** implements interfaces called by record and/or other support&lt;br /&gt;
* struct support&lt;br /&gt;
** is responsible for the fields in the struct&lt;br /&gt;
** implements interfaces called by record and/or other support&lt;br /&gt;
&lt;br /&gt;
== Processing Life Cycle ==&lt;br /&gt;
Assume a record instance is idle, i.e. is ready to start processing.&lt;br /&gt;
*dbProcess calls record support with one of the following states&lt;br /&gt;
** processCancel - record support must terminate any outstanding processing&lt;br /&gt;
** processStart - start processing. record support returns one of&lt;br /&gt;
*** processDone - All done and successful&lt;br /&gt;
*** processQuit - dont do any more processing. Return to idle state&lt;br /&gt;
*** processActive - not done. Call again&lt;br /&gt;
** processContinue - another request to process while record is active. Record support again returns one of the above.&lt;br /&gt;
&lt;br /&gt;
Record support, with associated link/struct support does the following:&lt;br /&gt;
* When it is called for processStart&lt;br /&gt;
** calls the support for RecordCommon with state processStart. it returns&lt;br /&gt;
*** processDone - Record support starts processing record specific fields&lt;br /&gt;
*** processQuit - Record support just returns processQuit to dbProcess&lt;br /&gt;
*** processActive - Record returns processActive. It will be called again with state processContinue. It calls RecordCommon support with state processActive. This continues until Record Common returns processDone or processQuit&lt;br /&gt;
* When RecordCommon returns processDone record support starts processing record specific fields&lt;br /&gt;
** Associated link or struct support may be called&lt;br /&gt;
*** Record support implements any &amp;lt;tt&amp;gt;block&amp;lt;/tt&amp;gt; fields.&lt;br /&gt;
*** It detects when asynchronous support completes&lt;br /&gt;
*** as long as there is incomplete asynchronous support it returns processActive to dbProcess&lt;br /&gt;
** When all record specific fields have been processed it calls RecordCommon suport with state processQuit&lt;br /&gt;
*** RecordCommon support can return processActive. Until it returns processDone, record support just returns processActive to dbProcess&lt;br /&gt;
** When RecordCommon returns processDone, record support returns processDone to dbProcess.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
struct and link fields can have associated support&lt;br /&gt;
* associated support may be asynchronous&lt;br /&gt;
** support returns indicating that it is active&lt;br /&gt;
** support is required to detect when asynchronous support completes&lt;br /&gt;
** when processing is complete support returns indicating that it is done.&lt;br /&gt;
* whenever record support returns to dbProcess, dbProcess posts any fields that were modified.&lt;br /&gt;
** record may be active or done&lt;br /&gt;
* when record support returns processDone or processQuit record is again set idle.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== record common ==&lt;br /&gt;
&lt;br /&gt;
These fields are optional but it is expected that most record&lt;br /&gt;
types will include a standard set of fields.&lt;br /&gt;
&lt;br /&gt;
The support for RecordCommon processes the following fields:&lt;br /&gt;
&lt;br /&gt;
* at the beginning of record processing&lt;br /&gt;
** disabled - if true NO processing will be done, i.e. processQuit is returned&lt;br /&gt;
** scanDisable&lt;br /&gt;
*** has associated support&lt;br /&gt;
*** if record is scan disabled processQuit is returned&lt;br /&gt;
** alarm fields&lt;br /&gt;
*** alarm handling is described below&lt;br /&gt;
* after record support completes&lt;br /&gt;
** processLink array&lt;br /&gt;
*** has associated support&lt;br /&gt;
&lt;br /&gt;
== record support ==&lt;br /&gt;
&lt;br /&gt;
Record support is responsible for all its fields.&lt;br /&gt;
For link and struct fields there may be associated support which&lt;br /&gt;
may be synchronous or asynchronous.&lt;br /&gt;
Record support communicates with&lt;br /&gt;
the link/struct support via interfaces that are implemented by the support.&lt;br /&gt;
If the record includes a field for struct(RecordCommon) it should&lt;br /&gt;
use the associated support for its fields.&lt;br /&gt;
&lt;br /&gt;
Record support may be called multiple times by dbProcess while a record instance&lt;br /&gt;
is active.&lt;br /&gt;
One of the arguments to process is ProcessState which has the values:&lt;br /&gt;
* processCancel - Cancel any outstanding activity&lt;br /&gt;
* processStart - Start processing&lt;br /&gt;
* processContinue - Making additional call&lt;br /&gt;
&lt;br /&gt;
process returns ProcessReturn which is one of the following:&lt;br /&gt;
* processDone - Done and successful&lt;br /&gt;
* processQuit - Do not do any more processing&lt;br /&gt;
* processActive - Not done&lt;br /&gt;
&lt;br /&gt;
If record support returns processActive it must keep internal state so&lt;br /&gt;
that it knows how to handle processCancel and processContinue.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For record support the above rules allow:&lt;br /&gt;
* process can be called repeatedly. This will continue as long as it returns processActive&lt;br /&gt;
* Everytime process returns processActive DbProcess posts monitors.&lt;br /&gt;
&lt;br /&gt;
== Record Locking ==&lt;br /&gt;
&lt;br /&gt;
V3 implemented lock sets in order to prevent different threads&lt;br /&gt;
from simultaneously accessing linked records.&lt;br /&gt;
&lt;br /&gt;
Instead of lock sets V4:&lt;br /&gt;
* implements a per record instance lock.&lt;br /&gt;
* defines a rule that allows two records to be locked without deadlocks&lt;br /&gt;
&lt;br /&gt;
== Posting Monitors ==&lt;br /&gt;
&lt;br /&gt;
In V3 monitors are posted when code (record support, device support, database access, etc) calls db_post_event. In V4 database access will itself handle&lt;br /&gt;
the posting of monitors.&lt;br /&gt;
&lt;br /&gt;
Monitors are posted by DbProcess when&lt;br /&gt;
* record support returns processActive.&lt;br /&gt;
* at the end of record processing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= link/struct Semantics =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both link and struct fields can have associated support.&lt;br /&gt;
The support can be synchronous or asynchronous.&lt;br /&gt;
&lt;br /&gt;
Support code implements interfaces.&lt;br /&gt;
Code that is responsible for a field communicates with the support via&lt;br /&gt;
the interface. Lets call this code the client.&lt;br /&gt;
&lt;br /&gt;
Each link and struct field has a well defined client.&lt;br /&gt;
* The support for RecordCommon is the client for fields in dbCommon&lt;br /&gt;
* record support is the client for the other top level fields in a record&lt;br /&gt;
* the struct support is the client for any link or struct fields in the struct&lt;br /&gt;
&lt;br /&gt;
A link/struct may have an associated block. The client is responsible for&lt;br /&gt;
implementing block. If block is true then the support will not be called&lt;br /&gt;
until all outstanding record activity completes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= channelAccess links =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
channelAccess link means access to a record or field. The requester can be:&lt;br /&gt;
* A database link in a record&lt;br /&gt;
* A channel access link in a record&lt;br /&gt;
* A workstation channel access client&lt;br /&gt;
&lt;br /&gt;
A channelAccess link is one of the following types:&lt;br /&gt;
* Monitor Link&lt;br /&gt;
** Implemented via a monitor request on linked field&lt;br /&gt;
** Optionally process record containing the link when monitor value is returned.&lt;br /&gt;
* Input Link&lt;br /&gt;
** Optionally request that record be processed.&lt;br /&gt;
** Optionally wait for linked record to complete processing.&lt;br /&gt;
** Get value.&lt;br /&gt;
* Output Link: &lt;br /&gt;
** Put value&lt;br /&gt;
** Optionally request processing.&lt;br /&gt;
** Optionally wait until completion&lt;br /&gt;
* Process Link: Perform the following actions&lt;br /&gt;
** Request processing&lt;br /&gt;
** Optionally wait until linked record completes&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* processLink is the replacement for the V3 forwardLink&lt;br /&gt;
* wait does NOT mean to wait synchronously. It means to save state, return, and resume at the saved state when called again.&lt;br /&gt;
&lt;br /&gt;
Links are processed as follows:&lt;br /&gt;
&lt;br /&gt;
The following rules apply when a process request is made:&lt;br /&gt;
* If record is already being processed the request is just ignored&lt;br /&gt;
* record support can specify that links to particular fields not cause processing.&lt;br /&gt;
** Where should this be specified?  In the Database Definition, the record instance, or both.&lt;br /&gt;
** If a process request is allowed, should it be done regardless of the scan mechanism, i.e. the record does not have to be passive?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Mutual Exclusion =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
V3 implemented lock sets, i.e. when a record was being processed it and all records linked via database links were locked.&lt;br /&gt;
&lt;br /&gt;
Lock sets solved two Mutual Exclusion problems:&lt;br /&gt;
* V3 allowed dbProcess to be called recursively.&lt;br /&gt;
** process passive database links and forward links were implemented via recursive calls to DbProcess&lt;br /&gt;
** Lock sets prevented deadly embrace problems for circular links.&lt;br /&gt;
* No puts could be done to a record in a lock set while record processing is active.&lt;br /&gt;
** For synchronous records this guarantees that no fields are modified except by record processing itself.&lt;br /&gt;
** For asynchronous records this guarantee is not valid.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
V4 does not call dbProcess recursively. Instead a process request is queued.&lt;br /&gt;
The request fails if either of the following is true:&lt;br /&gt;
* The record is active.&lt;br /&gt;
* The record is already queued.&lt;br /&gt;
&lt;br /&gt;
dbProcess itself manages the queue , which is FIFO.&lt;br /&gt;
When record support returns the first entry in the queue is processed.&lt;br /&gt;
In addition if link or struct support completes before the queue&lt;br /&gt;
is empty, a request to process the record containing the link/struct will&lt;br /&gt;
be added to the same queue.&lt;br /&gt;
Thus if a set of synchronous records are processed they will complete processing&lt;br /&gt;
without any context switch.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; What about periodically scanned records? Needs thought.&lt;br /&gt;
&lt;br /&gt;
This leaves the question of what should be done about mutual exclusion.&lt;br /&gt;
&lt;br /&gt;
For V4 there will be two locks associated with the IOC database:&lt;br /&gt;
1) a global lock, and 2) A per record instance lock.&lt;br /&gt;
&lt;br /&gt;
The global lock must be taken&lt;br /&gt;
whenever the structure of the database is modified. Examples are&lt;br /&gt;
1) adding new record types, 2) adding new record instances, and 3) modifying&lt;br /&gt;
database links. Global locks are not discussed further in this document.&lt;br /&gt;
&lt;br /&gt;
Each record instance has an associated lock.&lt;br /&gt;
When dbProcess is called it takes the lock.&lt;br /&gt;
Before it returns it unlocks.&lt;br /&gt;
Thus record support does not need to lock or unlock.&lt;br /&gt;
&lt;br /&gt;
Other code that needs access to fields of a record instance must&lt;br /&gt;
lock before accessing any fields and unlock after all accesses are complete.&lt;br /&gt;
&lt;br /&gt;
This leaves the problem of how to access fields from two different record&lt;br /&gt;
instances simultaneously. For example code that implements database&lt;br /&gt;
access needs such access. Code that needs such access must call dbLockLink before accessing the linked record and dbUnlockLink after access.&lt;br /&gt;
&lt;br /&gt;
dbLockLink is implemented as follows:&lt;br /&gt;
* Each Record instances has a unique ordinal number&lt;br /&gt;
* Assume Record X has a link to record Y&lt;br /&gt;
* If the ordinal number of X is less than that of Y&lt;br /&gt;
** Just call dbLock for record Y&lt;br /&gt;
* If the ordinal numnber of X is greater than that of Y&lt;br /&gt;
** call dbUnlock for X&lt;br /&gt;
** call dbLock for Y&lt;br /&gt;
** call dbLock for X&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Posting Modifications =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The document &amp;quot;V4 Design: dbdIterfaces&amp;quot; provides a design that allows&lt;br /&gt;
database access to handle all posting on monitors without requiring&lt;br /&gt;
any help from the code that modifies database fields.&lt;br /&gt;
It can do this because fields can be modified only via an&lt;br /&gt;
interface implemented by database access.&lt;br /&gt;
&lt;br /&gt;
dbProcess posts monitors when:&lt;br /&gt;
* When record support returns processActive.&lt;br /&gt;
* When it finishes record processing.&lt;br /&gt;
&lt;br /&gt;
How to implement monitors must be decided.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Alarm Processing =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; Will V4 alarm handling be different than V3? If so this section&lt;br /&gt;
may be meaningless.&lt;br /&gt;
&lt;br /&gt;
The V4 semantics for status and severity have the following goals:&lt;br /&gt;
* alarmSeverity has the same values as for V3&lt;br /&gt;
* alarmStatus is a string&lt;br /&gt;
* a record starts processing with alarmSeverity = &amp;quot;NO_ALARM&amp;quot; and status empty.&lt;br /&gt;
* status will ONLY be posted if it has changed since the last time it was posted.&lt;br /&gt;
* alarmSeverity will ONLY be posted if it has changed since the last time it was posted&lt;br /&gt;
&lt;br /&gt;
The semantics, which are implemented by the support for RecordCommon, are:&lt;br /&gt;
&lt;br /&gt;
* When recordCommon is called with processStart&lt;br /&gt;
** A private variable newSeverity is set to NO_ALARM&lt;br /&gt;
** A private variable prevSeverity is set to alarmSeverity&lt;br /&gt;
* When recordCommon completes its part of record processing&lt;br /&gt;
** If newSeverity is NO_ALARM and prevSeverity has a different value&lt;br /&gt;
*** alarmSeverity is set to NO_ALARM&lt;br /&gt;
*** alarmStatus is set to empty&lt;br /&gt;
&lt;br /&gt;
* When the recordCommon.setSeverity(sevr,status) is called&lt;br /&gt;
** If sevr is less than or equal to newSeverity nothing is done&lt;br /&gt;
** else&lt;br /&gt;
*** alarmSeverity is set to sevr&lt;br /&gt;
*** alarmStatus is set to status&lt;br /&gt;
*** newSeverity is set to sevr&lt;br /&gt;
&lt;br /&gt;
NOTE: alarmStatus and alarmSeverity are written by the normal method.&lt;br /&gt;
This means that their values will be posted.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Channel Access/ Database Access field types =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This section discusses how IOC database fields are accessed by channel access&lt;br /&gt;
or via database links.&lt;br /&gt;
&lt;br /&gt;
For the initial V4 implementation only the following types of data&lt;br /&gt;
will be accessable.&lt;br /&gt;
&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* enum&lt;br /&gt;
* one dimensional array of primitive or string or struct&lt;br /&gt;
* struct with fields of following types:&lt;br /&gt;
** primitive&lt;br /&gt;
** string&lt;br /&gt;
** enum&lt;br /&gt;
** struct (use recursion for allowed types)&lt;br /&gt;
** one dimensional array of primitive or string or struct&lt;br /&gt;
&lt;br /&gt;
The dbdInterfaces document defines database field types.&lt;br /&gt;
It also defines a subset called basic types, which consists&lt;br /&gt;
of primitive types, string, array, and structure.&lt;br /&gt;
For external access only basic types can be accessed.&lt;br /&gt;
This means that structures and arrays that do not consist of basic types&lt;br /&gt;
are not accessablevia clannelAccess. For example a DbfLink is&lt;br /&gt;
not accessable via channel access as a DbfLink.&lt;br /&gt;
&lt;br /&gt;
Non basic fields will only be available via some combination of basic types.&lt;br /&gt;
&lt;br /&gt;
For example a DbfLink field will appear as a string.&lt;br /&gt;
If a Database Definition is&lt;br /&gt;
&lt;br /&gt;
     struct(calcInpLink) {&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(link,link)&lt;br /&gt;
         field(value,float64)&lt;br /&gt;
     };&lt;br /&gt;
     &lt;br /&gt;
     record(xxx) {&lt;br /&gt;
         field(link,link)&lt;br /&gt;
         field(value,float64)&lt;br /&gt;
     ...&lt;br /&gt;
         field(inp,array(struct(calcInpLink)[]))&lt;br /&gt;
     ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
If a client attaches to &lt;br /&gt;
     record.field(link)&lt;br /&gt;
The data will be appear in the form:&lt;br /&gt;
     choice(choiceName) SupportStruct(pvname= ...)&lt;br /&gt;
where &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; is the name of the link support, &amp;lt;tt&amp;gt;SupportStruct&amp;lt;/tt&amp;gt; is the name of the support struct asociated with the support, and the arguments are the values for the support structure.&lt;br /&gt;
&lt;br /&gt;
Then if a client specifies the process variable:&lt;br /&gt;
     record.field(inp[1].link)&lt;br /&gt;
Then it connects to the link field of the second calcInpLink of field inp.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== primitive types ==&lt;br /&gt;
&lt;br /&gt;
This includes DbfBool, DbfOctet, DbfInt16, ... , DbfFloat64.&lt;br /&gt;
These do not present any problems. The scalar value is transfered.&lt;br /&gt;
&lt;br /&gt;
== string ==&lt;br /&gt;
&lt;br /&gt;
A string is just a UTF_8 encoded character string&lt;br /&gt;
&lt;br /&gt;
== DbfMenu  and DbfEnum ==&lt;br /&gt;
&lt;br /&gt;
Handled as an enum&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfLink ==&lt;br /&gt;
&lt;br /&gt;
A string with the same syntax as defined for a link field in &amp;quot;V4 DB Record Instance Syntax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== timeStamp ==&lt;br /&gt;
&lt;br /&gt;
This is just transfered like a struct with two fields:&lt;br /&gt;
* int64 secondsSinceEpoch&lt;br /&gt;
* int32 nanoSeconds&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== struct ==&lt;br /&gt;
&lt;br /&gt;
The individual fields can be accessed directly so this discussion&lt;br /&gt;
only involves access to the entire structure.&lt;br /&gt;
&lt;br /&gt;
The entire structure can be accessed as a string with the same syntax&lt;br /&gt;
as defined for a struct field in &amp;quot;V4 DB Record Instance Syntax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== array ==&lt;br /&gt;
&lt;br /&gt;
Arrays of the following types are accessable:&lt;br /&gt;
* primitive - DbfBool,...,DbfFloat64&lt;br /&gt;
* DbfString&lt;br /&gt;
* DbfStruct - As long as its fields are valid types&lt;br /&gt;
&lt;br /&gt;
Note that arrays of structs are not accessable in the early V4 releases.&lt;br /&gt;
&lt;br /&gt;
Arrays still need lots more discussion!!!&lt;br /&gt;
The database definition syntax allow an array to be any of the basic types, i.e. DbfBool,...,DbfFloat64, DbfString, DbfArray, DbfStruct.&lt;br /&gt;
&lt;br /&gt;
For the initial V4 version, database access only allows access to arrays of the following types.&lt;br /&gt;
* primitive - DbfBool,...,DbfFloat64&lt;br /&gt;
* DbfString&lt;br /&gt;
* ???? What else&lt;br /&gt;
&lt;br /&gt;
An individual element of an array of type DbfStruct can be accessed&lt;br /&gt;
directly if it satisfies the criteria for accessing a DbfStruct.&lt;br /&gt;
&lt;br /&gt;
Question: Should database Access be implemented so that record/link support can transfer an array in segments. Examples:&lt;br /&gt;
* If the array is a circular buffer, it is presented in two segements&lt;br /&gt;
* If the array is stored in hardware, e.g. a transient recorder, the array can be read from the hardware and passed to the client in segments.&lt;br /&gt;
&lt;br /&gt;
If an array is available only in segments then can we&lt;br /&gt;
prevent two clients from trying to access the same array simultaneously?&lt;br /&gt;
&lt;br /&gt;
Perhaps this is a problem that must be solved by an application:&lt;br /&gt;
* runControl records are one solution&lt;br /&gt;
* Other solutions can be envisioned&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MDArray ==&lt;br /&gt;
&lt;br /&gt;
Not implemented if the early V4 releases.&lt;br /&gt;
&lt;br /&gt;
== Associated Data ==&lt;br /&gt;
&lt;br /&gt;
The typical example is a client that asks for timeStamp, severity, status,&lt;br /&gt;
and data.&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=2742</id>
		<title>V4 DB RecordCommon</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=2742"/>
		<updated>2005-11-02T19:51:09Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Standard Support November 02 2005 &lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes two base supplied components for EPICS V4 databases.&lt;br /&gt;
# menuStructBase.dbd - menu and struct definitions &lt;br /&gt;
# baseSupport.dbd - link definitions for base supplied support&lt;br /&gt;
&lt;br /&gt;
This document requires that the reader be familiar with:&lt;br /&gt;
# V3 iocCore&lt;br /&gt;
# V4 DBD Statement Syntax&lt;br /&gt;
# V4 DB Record Instance Syntax&lt;br /&gt;
&lt;br /&gt;
NOTE: This document is ahead of the two above V4 documents so it may use&lt;br /&gt;
slightly different syntax.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= menuStructBase.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Links ==&lt;br /&gt;
&lt;br /&gt;
     struct(ProcessLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
     }&lt;br /&gt;
     struct(MonitorLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean) &lt;br /&gt;
     }&lt;br /&gt;
     struct(InputLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(OutputLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== asynDriver Link ==&lt;br /&gt;
     struct(AsynLink) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Definitions for recordCommon ==&lt;br /&gt;
&lt;br /&gt;
     # menu definitions for recordCommon fields&lt;br /&gt;
     menu(menuPriority) {&lt;br /&gt;
         choice(menuPriorityLow, &amp;quot;Low&amp;quot;)&lt;br /&gt;
         choice(menuPriorityMedium, &amp;quot;Medium&amp;quot;)&lt;br /&gt;
         choice(menuPriorityHigh, &amp;quot;High&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuScan) {&lt;br /&gt;
         choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
         choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
         choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
         choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
         choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuAlarmSevr) {&lt;br /&gt;
         choice(menuAlarmSevrNone, &amp;quot;None&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMinor, &amp;quot;Minor&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMajor, &amp;quot;Major&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrInvalid, &amp;quot;Invalid&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     #struct definitions for recordCommon&lt;br /&gt;
     struct(TimeStamp) {&lt;br /&gt;
         field(secondsPastEpoch,int64)&lt;br /&gt;
         field(nanoSeconds,int32)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Scan {&lt;br /&gt;
         field(scan,menu(menuScan)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(phase,int16)&lt;br /&gt;
         field(priority,menu(menuPriority)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;b&amp;gt;Event NEEDS NEW DEFINITIONS&amp;lt;/b&amp;gt;&lt;br /&gt;
     struct Event {&lt;br /&gt;
         field(eventNumber,int16) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(timeStampEvent,int16)&lt;br /&gt;
         field(timeStampLink,link)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Disable {&lt;br /&gt;
         field(disabled,boolean)&lt;br /&gt;
         field(disableValue,int16) {&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(disableInput,int16)&lt;br /&gt;
         field(disableLink,link)&lt;br /&gt;
         field(disableAlarmSeverity,menu(menuAlarmSevr))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(ProcessLink) {&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(link,link)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(RecordCommon) {&lt;br /&gt;
         field(description,string)&lt;br /&gt;
         field(scan,struct(Scan))&lt;br /&gt;
         field(event,struct(Event))&lt;br /&gt;
         field(accessSecurityGroup,string)&lt;br /&gt;
         field(processAtInit,boolean)&lt;br /&gt;
         field(disablePutField,boolean)&lt;br /&gt;
         field(alarmAckSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmNoAckTransient,menu(menuAlarmSevr)) {&lt;br /&gt;
         # highest level of alarm that does not have to be acknowledged&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         field(undefined,boolean) {&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             default(true)&lt;br /&gt;
         }&lt;br /&gt;
         field(time,struct(TimeStamp)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(disable,struct(Disable)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmStatus,string) {&lt;br /&gt;
             default(&amp;quot;UDF&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;Invalid&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(processLink,array(ProcessLink[])) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Although it has many fewer fields,&lt;br /&gt;
RecordCommon is a complete replacement for the V3 dbCommon.&lt;br /&gt;
The following V3 fields are no longer needed:&lt;br /&gt;
* private fields - Private fields will truly be private to the implementation&lt;br /&gt;
* previous value fields - All puts to database fields will be posted. The layer above will decide if clients should be notified of changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Other common definitions ==&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;Raw&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(engUnitsHigh,float64) &lt;br /&gt;
         field(engUnitsLow,float64)&lt;br /&gt;
         field(slope,float64) &lt;br /&gt;
         field(intercept,float64) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ControlLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
     }&lt;br /&gt;
     struct(AlarmLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(lowSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(lowWarning,float64) &lt;br /&gt;
         field(lowWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(highWarning,float64) &lt;br /&gt;
         field(highWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
         field(highSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(hysteresis,float64)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;MAY NEED NEW DEFINITION&amp;lt;/b&amp;gt;&lt;br /&gt;
     struct(SimulationFloat64) {&lt;br /&gt;
         field(modeLink,link)&lt;br /&gt;
         field(mode,boolean)&lt;br /&gt;
         field(link,link)&lt;br /&gt;
         field(value,float64)&lt;br /&gt;
         field(alarmSevr,menu(menuAlarmSevr))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= definition of record types =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
Most record types are defined as follows:&lt;br /&gt;
     #include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
     record(AiRecord) {&lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
     ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= baseSupport.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Support ==&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* monitor support&lt;br /&gt;
* input support&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For monitor, input, and output The following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
     support(processLink,ProcessLink)&lt;br /&gt;
     support(monitorLink,MonitorLink)&lt;br /&gt;
     support(monitorLinkArray,MonitorLink)&lt;br /&gt;
     support(inputLink,InputLink)&lt;br /&gt;
     support(inputLinkArray,InputLink)&lt;br /&gt;
     support(outputLink,OutputLink)&lt;br /&gt;
     support(outputLinkArray)&lt;br /&gt;
&lt;br /&gt;
== asynDriver support ==&lt;br /&gt;
&lt;br /&gt;
     support(asynInt32,AsynLink)&lt;br /&gt;
     support(asynInt32Average,AsynLink)&lt;br /&gt;
     support(asynInt32Monitor,AsynLink)&lt;br /&gt;
     support(asynFloat64,AsynLink)&lt;br /&gt;
     support(asynFloat64Average,AsynLink)&lt;br /&gt;
     support(asynFloat64Monitor,AsynLink)&lt;br /&gt;
     support(asynDigitalMonitor,AsynLink)&lt;br /&gt;
     support(asynDigital,AsynLink)&lt;br /&gt;
     support(asynInt32Array,AsynLink)&lt;br /&gt;
     support(asynFloat64Array,AsynLink)&lt;br /&gt;
     support(asynOctet,AsynLink)&lt;br /&gt;
&lt;br /&gt;
== struct support ==&lt;br /&gt;
For RecordCommon&lt;br /&gt;
     support(common) # no SupportStruct&lt;br /&gt;
For linear conversion&lt;br /&gt;
     support(linearConvert)&lt;br /&gt;
For simulation&lt;br /&gt;
     support(simulation)&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_Record_Instance_Syntax&amp;diff=2726</id>
		<title>V4 DB Record Instance Syntax</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_Record_Instance_Syntax&amp;diff=2726"/>
		<updated>2005-11-02T19:50:07Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;2005-11-02 MRK&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The syntax used for record instances has to change in EPICS V4,&lt;br /&gt;
since we now have to support structured data.&lt;br /&gt;
A complete redesign of the syntax has been done to help improve parsing, and to provide commonality between the syntax of a DB file and the string representation of structured data values passed through Channel Access.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE:&amp;lt;/b&amp;gt; See the note at the beginning of the &amp;quot;V4 DBD Statement Syntax&amp;quot;&lt;br /&gt;
concerning the syntax for link and struct fields.&lt;br /&gt;
&lt;br /&gt;
= Document Conventions =&lt;br /&gt;
&lt;br /&gt;
This syntax is presented below in the form of a grammar. The conventions I'm using are as follows:&lt;br /&gt;
&lt;br /&gt;
;''symbolBeingDefined:''&lt;br /&gt;
: ''otherSymbol''&lt;br /&gt;
: ''alternateSymbolFollowedBy'' &amp;lt;tt&amp;gt;literal&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;list of posible literal values&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Common Symbols =&lt;br /&gt;
&lt;br /&gt;
The symbols described in this section are used in the grammar, but may be implemented as lexical tokens.&lt;br /&gt;
&lt;br /&gt;
;''identifier:''&lt;br /&gt;
: A legal C99 identifier. Note that C99 permits implementations to allow extended characters to be used in identifiers, but does not require it, so the use of extended characters may reduce portability and is not recommended.&lt;br /&gt;
&lt;br /&gt;
== Integer Constants ==&lt;br /&gt;
&lt;br /&gt;
;''integerConstant:''&lt;br /&gt;
: ''positiveInteger''&lt;br /&gt;
&lt;br /&gt;
;''positiveInteger:''&lt;br /&gt;
: ''octalConstant''&lt;br /&gt;
: ''hexConstant''&lt;br /&gt;
: ''decimalConstant''&lt;br /&gt;
&lt;br /&gt;
;''octalConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''octalConstant'' ''octalDigit''&lt;br /&gt;
&lt;br /&gt;
;''octalDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-7&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''hexConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0x&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0X&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: ''hexConstant'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
;''hexDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9 a-f A-F&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''decimalConstant:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;1-9&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''decimalConstant'' ''decimalDigit''&lt;br /&gt;
&lt;br /&gt;
;''decimalDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This was meant to be a description of the C99 standard integer representation, but I made it up myself so it may be flawed.  Note that we will not accept the C99 numeric suffixes u/U and l/L since (unlike a C compiler) we know the type of the number we're expecting.&lt;br /&gt;
&lt;br /&gt;
== Floating Point Constants ==&lt;br /&gt;
&lt;br /&gt;
;''realConstant:''&lt;br /&gt;
:'' positiveReal''&lt;br /&gt;
: &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt; ''positiveReal''&lt;br /&gt;
&lt;br /&gt;
;''positiveReal:''&lt;br /&gt;
: ''digitSequence''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''exponentPart''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence'' ''exponentPart''&lt;br /&gt;
: &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence'' ''exponentPart''&lt;br /&gt;
: ''digitSequence'' ''exponentPart''&lt;br /&gt;
&lt;br /&gt;
;''digitSequence:''&lt;br /&gt;
: ''decimalDigit''&lt;br /&gt;
: ''digitSequence'' ''decimalDigit''&lt;br /&gt;
&lt;br /&gt;
;''exponentPart:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;e&amp;lt;/tt&amp;gt; ''signedExponent''&lt;br /&gt;
: &amp;lt;tt&amp;gt;E&amp;lt;/tt&amp;gt; ''signedExponent''&lt;br /&gt;
&lt;br /&gt;
;''signedExponent:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: ''digitSequence''&lt;br /&gt;
&lt;br /&gt;
In ANSI C source code, a sequence of decimal digits with neither a decimal point nor an exponent is an integer constant, not a floating-point constant.  We will permit this however, since we always know the field type in advance.&lt;br /&gt;
&lt;br /&gt;
== Boolean Constants ==&lt;br /&gt;
&lt;br /&gt;
We can afford to be generous in what we accept as a boolean value:&lt;br /&gt;
&lt;br /&gt;
;''booleanConstant:''&lt;br /&gt;
: ''booleanTrue''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''booleanTrue'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''booleanFalse''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''booleanFalse'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''booleanTrue:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;1 T TRUE t true True Y YES Yes y yes&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''booleanFalse:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0 F FALSE f false False N NO No n no&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''I'm proposing all these possibilities for true/false as they are all obvious in meaning, and will allow a CA Put of any of these strings to a boolean field. We might even want to allow registration of boolean strings in other languages...'''&lt;br /&gt;
&lt;br /&gt;
== String Constants ==&lt;br /&gt;
&lt;br /&gt;
;''stringConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''escapedCharacterList'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''escapedCharacterList:''&lt;br /&gt;
: A series of characters, using the C99 ''escapeSequence'' syntax defined below:&lt;br /&gt;
&lt;br /&gt;
;''escapeSequence:''&lt;br /&gt;
: ''simpleEscapeSequence''&lt;br /&gt;
: ''octalEscapeSequence''&lt;br /&gt;
: ''hexEscapeSequence''&lt;br /&gt;
: ''universalCharacterName''&lt;br /&gt;
&lt;br /&gt;
;''simpleEscapeSequence:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;\' \&amp;quot; \? \\ \a \b \f \n \r \t \v&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''octalEscapeSequence:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit'' ''octalDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit'' ''octalDigit'' ''octalDigit''&lt;br /&gt;
&lt;br /&gt;
;''hexEscapeSequence:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\x&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: ''hexEscapeSequence'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
Note: C99 does not limit the number of hexadecimal digits that can appear in a ''hexEscapeSequence'', but it does state that the behaviour is undefined if the resulting character value exceeds that of the largest character.&lt;br /&gt;
&lt;br /&gt;
;''universalCharacterName:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\u&amp;lt;/tt&amp;gt; ''hexQuad''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\U&amp;lt;/tt&amp;gt; ''hexQuad'' ''hexQuad''&lt;br /&gt;
&lt;br /&gt;
;''hexQuad:''&lt;br /&gt;
: ''hexDigit'' ''hexDigit'' ''hexDigit'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Database File =&lt;br /&gt;
&lt;br /&gt;
This section will eventually define what can appear in a .db file.  That currently means:&lt;br /&gt;
&lt;br /&gt;
* record instances&lt;br /&gt;
* comments&lt;br /&gt;
* macro instances, including where they will be allowed&lt;br /&gt;
* template files and substitution macro definitions&lt;br /&gt;
* port definitions for template instances&lt;br /&gt;
* data for tools such as VDCT, that will not be discarded by .db processing tools.&lt;br /&gt;
&lt;br /&gt;
The templates, macros and ports design should be very similar to the ideas produced for R3.14 VDCT templates.&lt;br /&gt;
&lt;br /&gt;
= Record Definitions =&lt;br /&gt;
&lt;br /&gt;
;''recordDefinition:''&lt;br /&gt;
: ''recordType'' ''recordName'' &amp;lt;tt&amp;gt;= {&amp;lt;/tt&amp;gt; ''recordBody'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''recordType:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
;''recordName:''&lt;br /&gt;
: ''recordNameChar''&lt;br /&gt;
: ''recordName'' ''recordNameChar''&lt;br /&gt;
&lt;br /&gt;
;''recordNameChar:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9 A-Z a-z _ - : ; &amp;lt; &amp;gt; [ ]&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Any Unicode/UTF-8 character outside of the Basic Latin set&lt;br /&gt;
&lt;br /&gt;
This extends the character set available to a V3 record name, adding all possible multi-byte characters.  However, EPICS sites are strongly advised to confirm that such record names can be processed using all of their database and CA client tools before actually making use of this particular extension.&lt;br /&gt;
&lt;br /&gt;
;''recordBody:''&lt;br /&gt;
: ''recordBodyItem''&lt;br /&gt;
: ''recordBody'' ''recordBodyItem''&lt;br /&gt;
&lt;br /&gt;
Record instance definitions in EPICS V4 look very similar to a C99 structure definition with initialization. For example:&lt;br /&gt;
&lt;br /&gt;
   ai foo:bar:temperature = {&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
Inside the body of the record definition, there are three possible kinds of statements, similar to a C assignment statement.  Note these statements must be terminated with a semi-colon (which is different from inside a struct).  The reason for this difference is to prevent database instance files from becoming dependent on the order of fields in a record; if we permit record instances to be created from a single comma-separated list of field values without the field names, it could lead to significant confusion if the field order ever changes.&lt;br /&gt;
&lt;br /&gt;
;''recordBodyItem:''&lt;br /&gt;
: ''infoAssignment''&lt;br /&gt;
: ''fieldAssignment''&lt;br /&gt;
: ''extraFieldAssigment''&lt;br /&gt;
&lt;br /&gt;
== Information Fields ==&lt;br /&gt;
&lt;br /&gt;
;''infoAssignment:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; ''infoName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''stringConstant'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''infoName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
: ''stringConstant''&lt;br /&gt;
&lt;br /&gt;
Info items provide additional configuration data about this record that can be accessed by other software running on the IOC.&lt;br /&gt;
&lt;br /&gt;
   info savePeriod = &amp;quot;30.0&amp;quot;;&lt;br /&gt;
   info restorePhase = &amp;quot;1&amp;quot;;&lt;br /&gt;
   info &amp;quot;my favourite things&amp;quot; = &amp;quot;raindrops on roses&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
== Field Assignment ==&lt;br /&gt;
&lt;br /&gt;
;''fieldAssignment:''&lt;br /&gt;
: ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializer'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''fieldName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
;''initializer:''&lt;br /&gt;
: ''constant''&lt;br /&gt;
: ''structInitializer''&lt;br /&gt;
: ''arrayInitializer''&lt;br /&gt;
: ''linkInitializer''&lt;br /&gt;
&lt;br /&gt;
;''initializerList:''&lt;br /&gt;
: ''initializer''&lt;br /&gt;
: ''initializerList'' &amp;lt;tt&amp;gt;,&amp;lt;/tt&amp;gt; ''initializer''&lt;br /&gt;
&lt;br /&gt;
The ''initializer'' in a field assignment is also the exact same syntax that will be used when converting a string value from a CA client for example into a field value that is being put into a field.&lt;br /&gt;
&lt;br /&gt;
=== Basic and Enumerated Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''constant:''&lt;br /&gt;
: ''booleanConstant''&lt;br /&gt;
: ''integerConstant''&lt;br /&gt;
: ''realConstant''&lt;br /&gt;
: ''stringConstant''&lt;br /&gt;
&lt;br /&gt;
The syntax for the field initializer depends on the data type represented by fieldName.  Basic types (numeric or string) should need no comment other than to note that values for numeric fields must not be given inside quotes (unlike EPICS V3).  Menu field values may be given as either a string or an integer. For enum fields, if the related field that contains the strings is defined first, the enum field may be specified using a string; otherwise it can only be set using an integer value.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
   ai foo:bar:temperature = {&lt;br /&gt;
       inputSmoothing = 0.98;&lt;br /&gt;
       invalidValue = 1000;&lt;br /&gt;
       units = &amp;quot;Celcius&amp;quot;;&lt;br /&gt;
       scan = &amp;quot;Interrupt&amp;quot;;&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Structure Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''structInitializer:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''structAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''structAssignmentList:''&lt;br /&gt;
: ''initializerList''&lt;br /&gt;
: ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
: ''structAssignmentList'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
&lt;br /&gt;
Initializers for a structure field look similar to a nested record body, but the rules are slightly different:&lt;br /&gt;
* You can give a series of values for adjacent items using a simple comma-separated list (for a record body, you ''must'' name each field)&lt;br /&gt;
* Semi-colons are required between a value and a following named item.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   ai foo:temperature:sensor = {&lt;br /&gt;
       linearConvert = {&lt;br /&gt;
           mode = &amp;quot;Linear&amp;quot;;&lt;br /&gt;
           low = -12.5, 133.5&lt;br /&gt;
       };&lt;br /&gt;
       displayLimit = { 0, 100 };&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
=== Link Initializer ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;''linkInitializer:''&lt;br /&gt;
: ''support(choiceName) supportStructName'' &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''structAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;''choiceName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
;''supportStructName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
These select a particular link support and interface for the field, and set its address according to the structure type defined for that link type.&lt;br /&gt;
&lt;br /&gt;
   calcout foo:temperature:controller = {&lt;br /&gt;
       block = true&lt;br /&gt;
       output = support(outputLink) OutputLink{&lt;br /&gt;
                pvname = &amp;quot;fum:baz:heater&amp;quot;;&lt;br /&gt;
                process = true;&lt;br /&gt;
                wait = true;&lt;br /&gt;
       }&lt;br /&gt;
       input = [2] {&lt;br /&gt;
           {   link = {&lt;br /&gt;
                   support(monitorLink) MonitorLink{&lt;br /&gt;
                       pvname = &amp;quot;foo:temperature:setpoint&amp;quot;;&lt;br /&gt;
                       process = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
           {  block=true&lt;br /&gt;
              link = {&lt;br /&gt;
                   support(inputLink) InputLink {&lt;br /&gt;
                       pvname = &amp;quot;foo:temperature:sensor&amp;quot;;&lt;br /&gt;
                       process = true;&lt;br /&gt;
                       wait = true;&lt;br /&gt;
                       inheritSeverity = true&lt;br /&gt;
                   }&lt;br /&gt;
              }&lt;br /&gt;
           }&lt;br /&gt;
       };&lt;br /&gt;
       expression = &amp;quot;(B - A) &amp;gt; 0&amp;quot;;&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   mbbi foo:bar:door = {&lt;br /&gt;
       input = support(acro9440) VME{0, 5};&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;QUESTION&amp;lt;/b&amp;gt; There is nothing that allows a DVT to prompt a user&lt;br /&gt;
with a valid set if support for a particular link. Should there be?&lt;br /&gt;
&lt;br /&gt;
=== Array Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''arrayInitializer:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''arrayType'' &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''arrayCapacity'' &amp;lt;tt&amp;gt;] {&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''arrayType'' &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''arrayCapacity'' &amp;lt;tt&amp;gt;] {&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''arrayAssignmentList:''&lt;br /&gt;
: ''initializerList''&lt;br /&gt;
: &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''integerConstant'' &amp;lt;tt&amp;gt;] =&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
: ''arrayAssignmentList'' &amp;lt;tt&amp;gt;; [&amp;lt;/tt&amp;gt; ''integerConstant'' &amp;lt;tt&amp;gt;] =&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
&lt;br /&gt;
;''arrayType:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;int16&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;uint16&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;int32&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;uint32&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;float32&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;float64&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;octet&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''arrayCapacity:''&lt;br /&gt;
: ''integerConstant''&lt;br /&gt;
: ''arrayCapacity'' &amp;lt;tt&amp;gt;,&amp;lt;/tt&amp;gt; ''integerConstant''&lt;br /&gt;
&lt;br /&gt;
If the definition of the array field being set did not do so, an array field initialization must include the size of the array and/or the type of the data stored in it. Inside the braces data values are given in a comma-separated list; the index can also be set to initialize individual values, and any mixture of the two can be used as desired:&lt;br /&gt;
&lt;br /&gt;
   mbbi foo:bar:door = {&lt;br /&gt;
       stateNames = [4] {&amp;quot;Broken&amp;quot;, &amp;quot;Closed&amp;quot;, &amp;quot;Open&amp;quot;, &amp;quot;Moving&amp;quot;};&lt;br /&gt;
       stateSeverity = [4] {&amp;quot;Major&amp;quot;; [3] = &amp;quot;Minor&amp;quot;};&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
For multi-dimensional arrays, data values can only appear inside the inner-most sets of braces, although index settings are permitted outside of these.  These two definitions give the same result:&lt;br /&gt;
&lt;br /&gt;
   matrix identity1 = {&lt;br /&gt;
       value = float32 [3,3] { {1, 0, 0}, {0, 1, 0}, {1, 0, 0}};&lt;br /&gt;
   }&lt;br /&gt;
   matrix identity2 = {&lt;br /&gt;
       value = float32 [3,3] { {1}, {[1] = 1}, {[2] = 1}};&lt;br /&gt;
   }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=585</id>
		<title>V4 Link Support Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=585"/>
		<updated>2005-11-02T19:48:50Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC link and struct Support November 02 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
The V4 link/struct support is a replacement for V3 &lt;br /&gt;
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK&lt;br /&gt;
# device DBD definition and device support&lt;br /&gt;
# driver DBD definition and driver support&lt;br /&gt;
&lt;br /&gt;
Each link and struct field in a record can have associated support.&lt;br /&gt;
* record support communicates with support via interfaces&lt;br /&gt;
* link or struct support implements interfaces&lt;br /&gt;
** link or struct support registers the interfaces it implements&lt;br /&gt;
** record support looks for interfaces it uses&lt;br /&gt;
*** it uses only the interfaces it finds&lt;br /&gt;
*** if no interfaces are found it reports an error&lt;br /&gt;
&lt;br /&gt;
Support has no knowledge of what record types are using it.&lt;br /&gt;
Struct support may have knowledge of the struct field&lt;br /&gt;
but not of the record type.&lt;br /&gt;
recordSupport has no knowledge about support other than the&lt;br /&gt;
interface it is using.&lt;br /&gt;
&lt;br /&gt;
For the rest of this document recordSupport means record support and support,&lt;br /&gt;
unless qualified, means link or struct support.&lt;br /&gt;
&lt;br /&gt;
EPICS base defines a standard set of interfaces for support,&lt;br /&gt;
which includes enough functionality such that&lt;br /&gt;
most support can be implemented via just these interfaces.&lt;br /&gt;
&lt;br /&gt;
Most of the support supplied with base is link support. In particular&lt;br /&gt;
support for channel/database access links. It also briefly describes&lt;br /&gt;
support for interfacing with asynDriver.&lt;br /&gt;
&lt;br /&gt;
The link interfaces support Channel/Database access&lt;br /&gt;
and the standard interfaces used by asynDriver.&lt;br /&gt;
Since asynDriver is intended as a framework for interfacing to most hardware,&lt;br /&gt;
this means that the interfaces supplied and used by base allows support&lt;br /&gt;
for most hardware. The support can communicate with the hardware&lt;br /&gt;
however it wants but must implement some set of the interfaces defined&lt;br /&gt;
by base.&lt;br /&gt;
&lt;br /&gt;
This document gives a brief overview of the V4 link/struct support model.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Database Definitions For links and structures =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section first reviews the DBD syntax related to link definitions.&lt;br /&gt;
It then gives a brief description of link related definitions in dbCommon.dbd&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
A record link has the syntax:&lt;br /&gt;
     field(name,link)&lt;br /&gt;
A record struct has the syntax&lt;br /&gt;
     field(name,struct(structName))&lt;br /&gt;
Support for a struct or link has the syntax&lt;br /&gt;
     support(choiceName) // no SupportStruct&lt;br /&gt;
     support(choiceName,supportStructName)&lt;br /&gt;
A record instance struct has the the syntax&lt;br /&gt;
    field = StructName{structAssignmentList} // no support&lt;br /&gt;
    field = support(choiceName)&lt;br /&gt;
            StructName{structAssignmentList} // support has no SupportStruct&lt;br /&gt;
    field = support(choiceName) SupportStruct{structAssignmentList}&lt;br /&gt;
            StructName{structAssignmentList}&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;structName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice. Each support must have a unique name.&lt;br /&gt;
; &amp;lt;tt&amp;gt;SupportStruct&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the support. recordSupport normally does not access this structure. Database configuration tools prompt the user to assign values to the structure.&lt;br /&gt;
&lt;br /&gt;
Assume the following definitions:&lt;br /&gt;
     record(AiRecord) {&lt;br /&gt;
         ...&lt;br /&gt;
         field(in,link)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     struct(MonitorLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(InputLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     support(monitorLink,MonitorLink)&lt;br /&gt;
     support(inputLink,InputLink)&lt;br /&gt;
     struct VME{&lt;br /&gt;
         field(a16,int16) &lt;br /&gt;
         field(a32,int32)&lt;br /&gt;
         field(channel,int16)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     support(someVmeADC,VME)&lt;br /&gt;
&lt;br /&gt;
The first example instance definition selects a monitor link.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {support(monitorLink)&lt;br /&gt;
                   MonitorLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                         process = true;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The next example selects a channel access input link.&lt;br /&gt;
     AiRecord aiInputExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {support(inputLink)&lt;br /&gt;
                   InputLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                        process = true;&lt;br /&gt;
                        wait = true;&lt;br /&gt;
                        timeout = 1.0;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The last example selects support for a VME Analog to Digital device.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {support(someVmeADC) VME {a16 = 0xc000; channel = 1} }&lt;br /&gt;
&lt;br /&gt;
== Standard Definitions For Channel/Database Access ==&lt;br /&gt;
&lt;br /&gt;
menuStructBase.dbd defines definitions for Channel/Database Access Links.&lt;br /&gt;
The base supplied support registers each choiceName in the support definitions.&lt;br /&gt;
The complete set of data structure and support definitions are defined&lt;br /&gt;
in &amp;quot;V4 DB RecordCommon&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* process&lt;br /&gt;
* monitor&lt;br /&gt;
* input&lt;br /&gt;
* output&lt;br /&gt;
&lt;br /&gt;
For monitor, input, and output the following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
&lt;br /&gt;
These are definitions that are used by the standard EPICS device support&lt;br /&gt;
for asynDriver. Since asynDriver is a generic way of interfacing arbitrary&lt;br /&gt;
hardware support, this is a generic way of attaching links in records to&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLink) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== support definitions ===&lt;br /&gt;
&lt;br /&gt;
     support(asynInt32,AsynLink)&lt;br /&gt;
     support(asynInt32Average,AsynLink)&lt;br /&gt;
     support(asynInt32Monitor,AsynLink)&lt;br /&gt;
     support(asynFloat64,AsynLink)&lt;br /&gt;
     support(asynFloat64Average,AsynLink)&lt;br /&gt;
     support(asynFloat64Monitor,AsynLink)&lt;br /&gt;
     support(asynDigitalMonitor,AsynLink)&lt;br /&gt;
     support(asynDigital,AsynLink)&lt;br /&gt;
     support(asynInt32Array,AsynLink)&lt;br /&gt;
     support(asynFloat64Array,AsynLink)&lt;br /&gt;
     support(asynOctet,AsynLink)&lt;br /&gt;
&lt;br /&gt;
This is the set of definitions for the standard EPICS device support implemented&lt;br /&gt;
by asynDriver. At least for the first few V4 releases,&lt;br /&gt;
asynDriver will not be part of base.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
An arbitrary number of Link Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
Whenever possible support should implement the standard interfaces&lt;br /&gt;
defined by EPICS base, since these are the interfaces that the record types&lt;br /&gt;
supplied with base use.&lt;br /&gt;
&lt;br /&gt;
Soft support should try to implement the same interfaces implemented by&lt;br /&gt;
the Channel/Database access support supplied with base. The support&lt;br /&gt;
can define support structures for it's own use.&lt;br /&gt;
Implementing these interfaces means that the support will work for&lt;br /&gt;
the same set of record links as the Channel/Database access support.&lt;br /&gt;
&lt;br /&gt;
Hardware support should, if possible, also implement the same interfaces&lt;br /&gt;
implemented by the Channel/Database access support.&lt;br /&gt;
Message based support may also have to implement the AsynOctet interface&lt;br /&gt;
but this interface is only used by a few record types.&lt;br /&gt;
&lt;br /&gt;
This section describes the interfaces implemented by all link support&lt;br /&gt;
and then the standard interfaces used by the records supplied with base.&lt;br /&gt;
&lt;br /&gt;
The syntax is similar to Java syntax since it is more concise than C++.&lt;br /&gt;
It can easily be translated to C++ syntax. For example the&lt;br /&gt;
definition:&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,int16 data);&lt;br /&gt;
         boolean getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class LinkInt16 {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual LinkResult get(Callback &amp;amp;callback, int16_t &amp;amp;data) = 0;&lt;br /&gt;
         virtual LinkResult put(Callback &amp;amp;callback, int16_t data) = 0;&lt;br /&gt;
         virtual bool getBounds(int16_t &amp;amp;low, int16_t &amp;amp;high) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE:&amp;lt;/b&amp;gt; Int16 becomes int16_t &amp;amp;data and int16 data becomes int16_t data.&lt;br /&gt;
&lt;br /&gt;
== Link and MonitorLink ==&lt;br /&gt;
&lt;br /&gt;
All support &amp;lt;b&amp;gt;must&amp;lt;/b&amp;gt; register interface &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt;&lt;br /&gt;
and if it supports monitors interface &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE: arguments and return types ignored for now&amp;lt;/b&amp;gt;&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; is an interface that is implemented by link support that&lt;br /&gt;
supports monitors. An example is support for hardware interrupts.&lt;br /&gt;
The &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally recordSupport does not need to call any of the Link &lt;br /&gt;
or MonitorLink methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call destroy before modifying the link&lt;br /&gt;
and initialize and connect after the link is modified.&lt;br /&gt;
&lt;br /&gt;
Note that neither Link or MonitorLink is listed in the &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; database&lt;br /&gt;
definition since they are generic.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
These are the definitions used by the Channel/Database access support&lt;br /&gt;
supplied with base.&lt;br /&gt;
&lt;br /&gt;
     enum LinkResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface LinkProcess {&lt;br /&gt;
         LinkResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
&lt;br /&gt;
     interface LinkOctet {&lt;br /&gt;
         LinkResult get(Callback callback, Octet data);&lt;br /&gt;
         LinkResult put(Callback callback, octet data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkResult get(Callback callback, octet[] data);&lt;br /&gt;
         LinkResult put(Callback callback, octet[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== asynDigital Support ==&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkResult write(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          LinkResult read(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,Boolean data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,boolean[] data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,int16 data);&lt;br /&gt;
         boolean getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,int16[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int16[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,int32 data);&lt;br /&gt;
         boolean getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,int32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,Int64 data);&lt;br /&gt;
         LinkResult put(Callback callback,int64 data);&lt;br /&gt;
         boolean getBounds(Int64 low, Int64 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,int64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,Float32 data);&lt;br /&gt;
         LinkResult put(Callback callback,float32 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,float32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,Float64 data);&lt;br /&gt;
         LinkResult put(Callback callback,float64 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,float64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkResult get(Callback callback,string data);&lt;br /&gt;
         LinkResult put(Callback callback,string data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkResult get(Callback callback,string[] data);&lt;br /&gt;
         LinkResult put(Callback callback,string[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Example - VME ADC support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
Assume the VME and support definitions given in the examples at the beginning&lt;br /&gt;
of this document.&lt;br /&gt;
&lt;br /&gt;
The following is presented with Java syntax.&lt;br /&gt;
It assumes that there is VME support of the form&lt;br /&gt;
&lt;br /&gt;
     public class vme {&lt;br /&gt;
         static public short getShort(long addr);&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The link support would be something like:&lt;br /&gt;
&lt;br /&gt;
     class AdcSupport implements Link LinkInt32 {&lt;br /&gt;
     AdcSupport(VME fromFactory)&lt;br /&gt;
     {&lt;br /&gt;
         addr = fromFactory;&lt;br /&gt;
         connected = false;&lt;br /&gt;
         //  from the VME initialize vmeaddr and channel&lt;br /&gt;
         // details left to your imagination&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Link methods&lt;br /&gt;
     void report(int16_t level)&lt;br /&gt;
     {&lt;br /&gt;
         printf(&amp;quot;AdcSupport a16 %x channel %d\n&amp;quot;,a16,channel);&lt;br /&gt;
     }&lt;br /&gt;
     void cancel() {} // nothing to do&lt;br /&gt;
     void destroy() {} //nothing to do&lt;br /&gt;
     void initialize()&lt;br /&gt;
     {&lt;br /&gt;
         // make sure we can access a16&lt;br /&gt;
     }&lt;br /&gt;
     void connect() {connected = true}&lt;br /&gt;
     void disconnect() {connected = false}&lt;br /&gt;
     &lt;br /&gt;
     // LinkInt32 methods&lt;br /&gt;
     LinkResult get(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         data = (Int)VME.getShort(vmeaddr);&lt;br /&gt;
         return linkDone;&lt;br /&gt;
     }&lt;br /&gt;
     LinkResult put(Callback callback, int data)&lt;br /&gt;
     {&lt;br /&gt;
         throw CantWriteAdc;&lt;br /&gt;
     }&lt;br /&gt;
     void getBounds(Int low, Int high) &lt;br /&gt;
     {&lt;br /&gt;
         // assume 16 bit unipolor adc&lt;br /&gt;
         low = 0; high = 0xffff;&lt;br /&gt;
     }&lt;br /&gt;
     private:&lt;br /&gt;
         VME addr;&lt;br /&gt;
         int vmeaddr;&lt;br /&gt;
         int channel;&lt;br /&gt;
         boolean connected;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Discussion of link support interfaces =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The definitions: record link, support, record instance links,&lt;br /&gt;
and the link interfaces are designed to support channel/database links,&lt;br /&gt;
links to hardware support, and links to other types of support.&lt;br /&gt;
&lt;br /&gt;
The following are two important requirements:&lt;br /&gt;
* analog I/O&lt;br /&gt;
** link support can return raw value. Support must convert to engineering units.&lt;br /&gt;
** link support can return engineering units&lt;br /&gt;
* output records&lt;br /&gt;
** Can link support provide initial value?&lt;br /&gt;
** What if multiple sources can change linked output?&lt;br /&gt;
&lt;br /&gt;
Lets consider each of these separately.&lt;br /&gt;
== Analog I/O ==&lt;br /&gt;
In V3 the aiRecord and aoRecords are responsible for conversion between&lt;br /&gt;
raw values and engineering units. Raw values are 32 bit integers. Device&lt;br /&gt;
support is responsible for setting the slope and intercept fields of the record.&lt;br /&gt;
recordSupport takes care of the actual conversions.&lt;br /&gt;
Device support can tell recordSupport that it set the engineering units&lt;br /&gt;
rather than a raw value by a different return value.&lt;br /&gt;
&lt;br /&gt;
For V4 the following is done:&lt;br /&gt;
&lt;br /&gt;
aiRecord and aoRecord both have the following fields:&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;None&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(engUnitsHigh,float64)&lt;br /&gt;
         field(engUnitsLow,float64)&lt;br /&gt;
         field(slope,float64)&lt;br /&gt;
         field(intercept,float64)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     ...&lt;br /&gt;
     field(convert, menu(menuConvert))&lt;br /&gt;
     field(linearConvert, struct(LinearConvert))&lt;br /&gt;
     field(convertTable,string);&lt;br /&gt;
     field(units, string)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; This section is written as though record support itself does&lt;br /&gt;
the conversions. Most record support would call the standard support&lt;br /&gt;
for LinearConvert.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a record instance has convert set to None then recordSupport does the following.&lt;br /&gt;
* if link support implements LinkFloat64 it just calls this to obtain an engineering units value&lt;br /&gt;
* otherwise it gets a value via interface LinkInt32 and converts the value from in int32 to a float64.&lt;br /&gt;
&lt;br /&gt;
If a record instance has convert linear&lt;br /&gt;
* if link support implements LinkInt32 it uses LinkInt32 otherwise it uses LinkFloat64&lt;br /&gt;
* it uses slope and interccept to convert from raw to engineering units&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;LinkInt32&amp;lt;/tt&amp;gt; is defined as:&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         boolean getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
If convert is linear and getBounds returns true than recordSupport&lt;br /&gt;
uses the returned value to compute slope and intercept. In all&lt;br /&gt;
other cases recordSupport just uses whatever values they have.&lt;br /&gt;
&lt;br /&gt;
For example support for a 16 bit unipolar ADC would set low=0, high=65535,&lt;br /&gt;
and return true.&lt;br /&gt;
If link support can not determine the bounds then getBounds returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE:&amp;lt;/b&amp;gt;The interface implemented by breakpoint tables must be defined.&lt;br /&gt;
It will support the same semantics as the V3 breakpoint tables.&lt;br /&gt;
&lt;br /&gt;
== Output Records ==&lt;br /&gt;
&lt;br /&gt;
The following are two features that link support should implement&lt;br /&gt;
whenever possible:&lt;br /&gt;
# When a record is initalized provide the current value of the output&lt;br /&gt;
# If the actual output is changed by something other than the output record than the output record should also be modified to reflect the new output value.&lt;br /&gt;
&lt;br /&gt;
The first feature is especially desirable when an IOC is rebooted.&lt;br /&gt;
If a hardware output can survive a reboot this is a very desirable feature.&lt;br /&gt;
If the output is to a field bus, a PLC, or to a record in another IOC&lt;br /&gt;
it is often possible for the link support to determine the current value.&lt;br /&gt;
&lt;br /&gt;
The second feature is something that was often asked for in V3 but&lt;br /&gt;
only implemented&lt;br /&gt;
for some special cases. This is especially desirable when the output is&lt;br /&gt;
connected to a system that can have multiple sources of control.&lt;br /&gt;
Examples are GPIB devices with front pannel controls, PLC systems that&lt;br /&gt;
have manual controls or non-epics network access.&lt;br /&gt;
&lt;br /&gt;
For V3 some of the hardware , but none of the soft,&lt;br /&gt;
support implemented the first feature but by&lt;br /&gt;
modifying actual fields in the record. V3 did not implement the second&lt;br /&gt;
feature. Some special device support, not part of base, was implemented&lt;br /&gt;
to support this feature.&lt;br /&gt;
&lt;br /&gt;
For V4 these features are supported as follows:&lt;br /&gt;
&lt;br /&gt;
=== record initialization ===&lt;br /&gt;
&lt;br /&gt;
The link support implements an interface that has a put and a get method.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         boolean getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
If the link support can support readbacks then it implements get&lt;br /&gt;
and returns linkDone. If it does not support readbacks&lt;br /&gt;
then it implements get by just returning linkNoop.&lt;br /&gt;
&lt;br /&gt;
=== monitors for outputs ===&lt;br /&gt;
&lt;br /&gt;
If output link support can detect when something besides the link support&lt;br /&gt;
itself modifies the output then it implements interface &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt;&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
At initialization recordSupport looks for this interface and if found&lt;br /&gt;
it calls &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt;. The link support calls the callback whenever&lt;br /&gt;
it detects a change in the output that it did not cause. recordSupport&lt;br /&gt;
causes itself to be processed without making a new call to the&lt;br /&gt;
link support.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Struct Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
== support for RecordCommon ==&lt;br /&gt;
This implements an interface, not yet defined, that is similar to the&lt;br /&gt;
interface record support implements.&lt;br /&gt;
== support for LinearConvert ==&lt;br /&gt;
This implements the interface&lt;br /&gt;
     interface LinearConvertSupport {&lt;br /&gt;
          convert(int32 raw,Float64 value) // from raw to eng&lt;br /&gt;
          convert(float64 value,Int32 raw) // from eng to raw&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In addition it provides a factory&lt;br /&gt;
     interface LinearConvertFactory {&lt;br /&gt;
         LinearConvertSupport(string choiceName,&lt;br /&gt;
             DbfStruct linearConvert,DbfLink inlink)&lt;br /&gt;
     }&lt;br /&gt;
== support for simulation ==&lt;br /&gt;
This needs to be defined.&lt;br /&gt;
== support for breakpoint tables ==&lt;br /&gt;
This needs to be defined.&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=582</id>
		<title>V4 DBD Statement Syntax</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=582"/>
		<updated>2005-11-01T20:49:53Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DBD Statement Syntax November 01 2005&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
This document presents the syntax for V4 database definition files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; This version of the database definition and database instance&lt;br /&gt;
syntax does not provide:&lt;br /&gt;
# a direction for links&lt;br /&gt;
# a way to select a subset of the support definitions&lt;br /&gt;
&lt;br /&gt;
Support can exist for either a link field or a struct field.&lt;br /&gt;
The support definition is just&lt;br /&gt;
&lt;br /&gt;
    support(choiceName,supportStructName)&lt;br /&gt;
&lt;br /&gt;
When a record instance is created any choiceName can be specified for&lt;br /&gt;
a link or struct field. If an invalid choice is made, an error will&lt;br /&gt;
be issued during initialization.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= General Statements =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== include ==&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;filename&amp;quot;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;filename&amp;lt;/tt&amp;gt;&lt;br /&gt;
: must be a valid filename&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Include statements can be used at the top level, or inside the braces of a &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definition.&lt;br /&gt;
&lt;br /&gt;
== # comment ==&lt;br /&gt;
&lt;br /&gt;
 # anything&lt;br /&gt;
&lt;br /&gt;
Anything on a line after a &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; 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 &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; character has no special meaning.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== menu ==&lt;br /&gt;
&lt;br /&gt;
A menu is an enumerated type where the choice strings are defined once for each IOC.  Menus are defined like this:&lt;br /&gt;
&lt;br /&gt;
 menu(menuName) {&lt;br /&gt;
     choice(choiceName, &amp;quot;choiceValue&amp;quot;)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can be any UTF-8 compatible string, which should be unique within the context of this menu.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 menu(menuScan) {&lt;br /&gt;
     choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
     choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
     choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
     choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
     choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Structures, Record types, Fields and Views =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== struct ==&lt;br /&gt;
&lt;br /&gt;
A structure is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 struct(name) {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The structure name must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular structure.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
&lt;br /&gt;
== record ==&lt;br /&gt;
&lt;br /&gt;
A record type is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 record(name) extends RecordCommon {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     view(viewName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The record type name. It must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;extends RecordCommon&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This states that the record type extends the set of fields defined in &amp;quot;V4 DB RecordCommon&amp;quot;. 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 &amp;lt;tt&amp;gt;extends&amp;lt;/tt&amp;gt; phrase.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular record type and its parents (extends ...).&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#Views of a record|Views of a record]] below.&lt;br /&gt;
&lt;br /&gt;
== fieldType ==&lt;br /&gt;
&lt;br /&gt;
Both &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; define a field as:&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The syntax for &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
=== Basic types: octet, boolean, numerics, and string ===&lt;br /&gt;
&lt;br /&gt;
The following field types have no arguments:&lt;br /&gt;
&amp;lt;tt&amp;gt;octet&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int32&amp;lt;/tt&amp;gt;,  &amp;lt;tt&amp;gt;int64&amp;lt;/tt&amp;gt;,&lt;br /&gt;
&amp;lt;tt&amp;gt;float32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;float64&amp;lt;/tt&amp;gt;,  and &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Examples: &lt;br /&gt;
     field(description,string)&lt;br /&gt;
     field(value,float64)&lt;br /&gt;
&lt;br /&gt;
=== enum ===&lt;br /&gt;
&lt;br /&gt;
An &amp;lt;tt&amp;gt;enum&amp;lt;/tt&amp;gt; field takes one argument after the type name:&lt;br /&gt;
&lt;br /&gt;
     enum(fieldName)&lt;br /&gt;
&lt;br /&gt;
where fieldName is the name of another field in the same record that must be of type &amp;lt;tt&amp;gt;array(string[])&amp;lt;/tt&amp;gt;.  The values in this other field at runtime define the available choice strings for the enum field.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
     field(choices, array(string[])&lt;br /&gt;
     field(value, enum(choices))&lt;br /&gt;
&lt;br /&gt;
=== menu ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt; field is defined like this:&lt;br /&gt;
     menu(menuName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt; is the name of the menu.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     field(scan, menu(menuScan))&lt;br /&gt;
&lt;br /&gt;
=== struct ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; field is declared using the type name&lt;br /&gt;
     struct(structName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;structName&amp;lt;/tt&amp;gt; is the name of a struct which must have been previously defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
      struct(Point) {&lt;br /&gt;
          field(x,float64)&lt;br /&gt;
          field(y,float64)&lt;br /&gt;
          field(z,float64)&lt;br /&gt;
       }&lt;br /&gt;
       ...&lt;br /&gt;
       record(haspoint) extends RecordCommon {&lt;br /&gt;
           ...&lt;br /&gt;
           field(point, struct(point))&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
=== array ===&lt;br /&gt;
&lt;br /&gt;
An array field uses definitions like these:&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 3-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[,,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 2-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;arrayType&amp;lt;/tt&amp;gt; may be any fieldType except &amp;lt;tt&amp;gt;array&amp;lt;/tt&amp;gt;, 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]]&lt;br /&gt;
* &amp;lt;tt&amp;gt;capacity&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(VAL1D,array(float64[]))  #1d array with arbitrary capacity&lt;br /&gt;
     field(VAL2D,array(float64[,])) #2d array with arbitrary capacities&lt;br /&gt;
     field(anyTypeAnyD,array())     #arbitrary type,number of dimensions, and capacities&lt;br /&gt;
&lt;br /&gt;
=== link ===&lt;br /&gt;
&lt;br /&gt;
This field type can get or put data from/to some source outside of the record.&lt;br /&gt;
Link fields replace the DBF_INLINK, DBF_OUTLINK, and DTYP fields from EPICS V3.&lt;br /&gt;
&lt;br /&gt;
A link field's choices come from link definitions - see the [[#link]] section below for more details.&lt;br /&gt;
A link can be a link to another database record, to hardware device support,&lt;br /&gt;
or something else.&lt;br /&gt;
&lt;br /&gt;
The syntax is:&lt;br /&gt;
&lt;br /&gt;
     field(name,link)&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(disableLink,link)&lt;br /&gt;
     field(process, link)&lt;br /&gt;
     field(inp,link)&lt;br /&gt;
&lt;br /&gt;
== fieldAttribute ==&lt;br /&gt;
&lt;br /&gt;
Each field definition has several associated attributes, the values of which are set like this:&lt;br /&gt;
&lt;br /&gt;
     default(&amp;quot;fieldValue&amp;quot;)&lt;br /&gt;
     readonly(yesNo)&lt;br /&gt;
     design(yesNo)&lt;br /&gt;
     special(yesNo)&lt;br /&gt;
     asl(securityLevel)&lt;br /&gt;
     link(yesNo)&lt;br /&gt;
&lt;br /&gt;
'''Marty thinks we should get rid of these two:'''&lt;br /&gt;
     prompt(&amp;quot;promptString&amp;quot;)&lt;br /&gt;
     group(&amp;quot;promptGroup&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
'''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.'''&lt;br /&gt;
&lt;br /&gt;
The attribute parameter values have the following meanings:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;default(&amp;quot;fieldValue&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;readonly(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can this field be modified via channel access or database links?  Takes the value No if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;design(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;special(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;asl(securityLevel)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Channel Access security level for this field, 0 or 1.  Takes the value 1 if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
''These attributes may disappear, see comment above:''&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;prompt(&amp;quot;promptString&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;group(&amp;quot;promptGroup&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
== view ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;field&amp;quot; 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).&lt;br /&gt;
&lt;br /&gt;
A simple view looks like this:&lt;br /&gt;
&lt;br /&gt;
 view(viewName) {&lt;br /&gt;
     property(propName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     property(propName, fieldPath)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The view name must be a valid C identifier, which must be unique in the context of the particular record type.&lt;br /&gt;
; &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: A Data Access property name, which must be a valid C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The path to a field in this record type. To use a field inside a structure field, give the full path to that field: &amp;lt;tt&amp;gt;controlLimit.upper&amp;lt;/tt&amp;gt; for example.&lt;br /&gt;
: If &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; resolves to a structure, a property catalog containing the whole structure will be sent, with property names matching the structure's field names.&lt;br /&gt;
: The &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; may be omitted as long as there is a subordinate property catalog below this property.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 record(ao) extends RecordCommon {&lt;br /&gt;
     field(value, float64) { ... }&lt;br /&gt;
     field(outValue, float64) { ... }&lt;br /&gt;
     field(rawValue, int32) { ... }&lt;br /&gt;
     field(units, string) { ... }&lt;br /&gt;
     field(displayLimit, struct(displayLimit)) { ... }&lt;br /&gt;
     ...&lt;br /&gt;
     view(value)&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(outValue)&lt;br /&gt;
         property(value, outValue) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(rawValue)&lt;br /&gt;
         property(value, rawValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;support&amp;lt;/tt&amp;gt; statement describes an implementation of support for a link&lt;br /&gt;
or struct field.&lt;br /&gt;
Link support can be any of the following:&lt;br /&gt;
* A link to another record either local or remote&lt;br /&gt;
* A link to hardware support&lt;br /&gt;
* Something else.&lt;br /&gt;
&lt;br /&gt;
The syntax for these is:&lt;br /&gt;
&lt;br /&gt;
 support(choiceName)&lt;br /&gt;
or&lt;br /&gt;
 support(choiceName,supportStructName)&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;supportStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
When a record instance is created the choiceName&lt;br /&gt;
selects the support to attach to a record link.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     link(processLink)&lt;br /&gt;
     link(monitorLink,MonitorLinkData)&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_Record_Instance_Syntax&amp;diff=579</id>
		<title>V4 DB Record Instance Syntax</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_Record_Instance_Syntax&amp;diff=579"/>
		<updated>2005-11-01T20:48:20Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;2005-11-01 MRK&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The syntax used for record instances has to change in EPICS V4,&lt;br /&gt;
since we now have to support structured data.&lt;br /&gt;
A complete redesign of the syntax has been done to help improve parsing, and to provide commonality between the syntax of a DB file and the string representation of structured data values passed through Channel Access.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE:&amp;lt;/b&amp;gt; See the note at the beginning of the &amp;quot;V4 DBD Statement Syntax&amp;quot;&lt;br /&gt;
concerning the syntax for link and struct fields.&lt;br /&gt;
&lt;br /&gt;
= Document Conventions =&lt;br /&gt;
&lt;br /&gt;
This syntax is presented below in the form of a grammar. The conventions I'm using are as follows:&lt;br /&gt;
&lt;br /&gt;
;''symbolBeingDefined:''&lt;br /&gt;
: ''otherSymbol''&lt;br /&gt;
: ''alternateSymbolFollowedBy'' &amp;lt;tt&amp;gt;literal&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;list of posible literal values&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Common Symbols =&lt;br /&gt;
&lt;br /&gt;
The symbols described in this section are used in the grammar, but may be implemented as lexical tokens.&lt;br /&gt;
&lt;br /&gt;
;''identifier:''&lt;br /&gt;
: A legal C99 identifier. Note that C99 permits implementations to allow extended characters to be used in identifiers, but does not require it, so the use of extended characters may reduce portability and is not recommended.&lt;br /&gt;
&lt;br /&gt;
== Integer Constants ==&lt;br /&gt;
&lt;br /&gt;
;''integerConstant:''&lt;br /&gt;
: ''positiveInteger''&lt;br /&gt;
&lt;br /&gt;
;''positiveInteger:''&lt;br /&gt;
: ''octalConstant''&lt;br /&gt;
: ''hexConstant''&lt;br /&gt;
: ''decimalConstant''&lt;br /&gt;
&lt;br /&gt;
;''octalConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''octalConstant'' ''octalDigit''&lt;br /&gt;
&lt;br /&gt;
;''octalDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-7&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''hexConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0x&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0X&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: ''hexConstant'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
;''hexDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9 a-f A-F&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''decimalConstant:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;1-9&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''decimalConstant'' ''decimalDigit''&lt;br /&gt;
&lt;br /&gt;
;''decimalDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This was meant to be a description of the C99 standard integer representation, but I made it up myself so it may be flawed.  Note that we will not accept the C99 numeric suffixes u/U and l/L since (unlike a C compiler) we know the type of the number we're expecting.&lt;br /&gt;
&lt;br /&gt;
== Floating Point Constants ==&lt;br /&gt;
&lt;br /&gt;
;''realConstant:''&lt;br /&gt;
:'' positiveReal''&lt;br /&gt;
: &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt; ''positiveReal''&lt;br /&gt;
&lt;br /&gt;
;''positiveReal:''&lt;br /&gt;
: ''digitSequence''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''exponentPart''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence'' ''exponentPart''&lt;br /&gt;
: &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence'' ''exponentPart''&lt;br /&gt;
: ''digitSequence'' ''exponentPart''&lt;br /&gt;
&lt;br /&gt;
;''digitSequence:''&lt;br /&gt;
: ''decimalDigit''&lt;br /&gt;
: ''digitSequence'' ''decimalDigit''&lt;br /&gt;
&lt;br /&gt;
;''exponentPart:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;e&amp;lt;/tt&amp;gt; ''signedExponent''&lt;br /&gt;
: &amp;lt;tt&amp;gt;E&amp;lt;/tt&amp;gt; ''signedExponent''&lt;br /&gt;
&lt;br /&gt;
;''signedExponent:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: ''digitSequence''&lt;br /&gt;
&lt;br /&gt;
In ANSI C source code, a sequence of decimal digits with neither a decimal point nor an exponent is an integer constant, not a floating-point constant.  We will permit this however, since we always know the field type in advance.&lt;br /&gt;
&lt;br /&gt;
== Boolean Constants ==&lt;br /&gt;
&lt;br /&gt;
We can afford to be generous in what we accept as a boolean value:&lt;br /&gt;
&lt;br /&gt;
;''booleanConstant:''&lt;br /&gt;
: ''booleanTrue''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''booleanTrue'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''booleanFalse''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''booleanFalse'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''booleanTrue:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;1 T TRUE t true True Y YES Yes y yes&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''booleanFalse:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0 F FALSE f false False N NO No n no&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''I'm proposing all these possibilities for true/false as they are all obvious in meaning, and will allow a CA Put of any of these strings to a boolean field. We might even want to allow registration of boolean strings in other languages...'''&lt;br /&gt;
&lt;br /&gt;
== String Constants ==&lt;br /&gt;
&lt;br /&gt;
;''stringConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''escapedCharacterList'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''escapedCharacterList:''&lt;br /&gt;
: A series of characters, using the C99 ''escapeSequence'' syntax defined below:&lt;br /&gt;
&lt;br /&gt;
;''escapeSequence:''&lt;br /&gt;
: ''simpleEscapeSequence''&lt;br /&gt;
: ''octalEscapeSequence''&lt;br /&gt;
: ''hexEscapeSequence''&lt;br /&gt;
: ''universalCharacterName''&lt;br /&gt;
&lt;br /&gt;
;''simpleEscapeSequence:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;\' \&amp;quot; \? \\ \a \b \f \n \r \t \v&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''octalEscapeSequence:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit'' ''octalDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit'' ''octalDigit'' ''octalDigit''&lt;br /&gt;
&lt;br /&gt;
;''hexEscapeSequence:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\x&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: ''hexEscapeSequence'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
Note: C99 does not limit the number of hexadecimal digits that can appear in a ''hexEscapeSequence'', but it does state that the behaviour is undefined if the resulting character value exceeds that of the largest character.&lt;br /&gt;
&lt;br /&gt;
;''universalCharacterName:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\u&amp;lt;/tt&amp;gt; ''hexQuad''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\U&amp;lt;/tt&amp;gt; ''hexQuad'' ''hexQuad''&lt;br /&gt;
&lt;br /&gt;
;''hexQuad:''&lt;br /&gt;
: ''hexDigit'' ''hexDigit'' ''hexDigit'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Database File =&lt;br /&gt;
&lt;br /&gt;
This section will eventually define what can appear in a .db file.  That currently means:&lt;br /&gt;
&lt;br /&gt;
* record instances&lt;br /&gt;
* comments&lt;br /&gt;
* macro instances, including where they will be allowed&lt;br /&gt;
* template files and substitution macro definitions&lt;br /&gt;
* port definitions for template instances&lt;br /&gt;
* data for tools such as VDCT, that will not be discarded by .db processing tools.&lt;br /&gt;
&lt;br /&gt;
The templates, macros and ports design should be very similar to the ideas produced for R3.14 VDCT templates.&lt;br /&gt;
&lt;br /&gt;
= Record Definitions =&lt;br /&gt;
&lt;br /&gt;
;''recordDefinition:''&lt;br /&gt;
: ''recordType'' ''recordName'' &amp;lt;tt&amp;gt;= {&amp;lt;/tt&amp;gt; ''recordBody'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''recordType:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
;''recordName:''&lt;br /&gt;
: ''recordNameChar''&lt;br /&gt;
: ''recordName'' ''recordNameChar''&lt;br /&gt;
&lt;br /&gt;
;''recordNameChar:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9 A-Z a-z _ - : ; &amp;lt; &amp;gt; [ ]&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Any Unicode/UTF-8 character outside of the Basic Latin set&lt;br /&gt;
&lt;br /&gt;
This extends the character set available to a V3 record name, adding all possible multi-byte characters.  However, EPICS sites are strongly advised to confirm that such record names can be processed using all of their database and CA client tools before actually making use of this particular extension.&lt;br /&gt;
&lt;br /&gt;
;''recordBody:''&lt;br /&gt;
: ''recordBodyItem''&lt;br /&gt;
: ''recordBody'' ''recordBodyItem''&lt;br /&gt;
&lt;br /&gt;
Record instance definitions in EPICS V4 look very similar to a C99 structure definition with initialization. For example:&lt;br /&gt;
&lt;br /&gt;
   ai foo:bar:temperature = {&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
Inside the body of the record definition, there are three possible kinds of statements, similar to a C assignment statement.  Note these statements must be terminated with a semi-colon (which is different from inside a struct).  The reason for this difference is to prevent database instance files from becoming dependent on the order of fields in a record; if we permit record instances to be created from a single comma-separated list of field values without the field names, it could lead to significant confusion if the field order ever changes.&lt;br /&gt;
&lt;br /&gt;
;''recordBodyItem:''&lt;br /&gt;
: ''infoAssignment''&lt;br /&gt;
: ''fieldAssignment''&lt;br /&gt;
: ''extraFieldAssigment''&lt;br /&gt;
&lt;br /&gt;
== Information Fields ==&lt;br /&gt;
&lt;br /&gt;
;''infoAssignment:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; ''infoName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''stringConstant'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''infoName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
: ''stringConstant''&lt;br /&gt;
&lt;br /&gt;
Info items provide additional configuration data about this record that can be accessed by other software running on the IOC.&lt;br /&gt;
&lt;br /&gt;
   info savePeriod = &amp;quot;30.0&amp;quot;;&lt;br /&gt;
   info restorePhase = &amp;quot;1&amp;quot;;&lt;br /&gt;
   info &amp;quot;my favourite things&amp;quot; = &amp;quot;raindrops on roses&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
== Field Assignment ==&lt;br /&gt;
&lt;br /&gt;
;''fieldAssignment:''&lt;br /&gt;
: ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializer'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''fieldName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
;''initializer:''&lt;br /&gt;
: ''constant''&lt;br /&gt;
: ''structInitializer''&lt;br /&gt;
: ''arrayInitializer''&lt;br /&gt;
: ''linkInitializer''&lt;br /&gt;
&lt;br /&gt;
;''initializerList:''&lt;br /&gt;
: ''initializer''&lt;br /&gt;
: ''initializerList'' &amp;lt;tt&amp;gt;,&amp;lt;/tt&amp;gt; ''initializer''&lt;br /&gt;
&lt;br /&gt;
The ''initializer'' in a field assignment is also the exact same syntax that will be used when converting a string value from a CA client for example into a field value that is being put into a field.&lt;br /&gt;
&lt;br /&gt;
=== Basic and Enumerated Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''constant:''&lt;br /&gt;
: ''booleanConstant''&lt;br /&gt;
: ''integerConstant''&lt;br /&gt;
: ''realConstant''&lt;br /&gt;
: ''stringConstant''&lt;br /&gt;
&lt;br /&gt;
The syntax for the field initializer depends on the data type represented by fieldName.  Basic types (numeric or string) should need no comment other than to note that values for numeric fields must not be given inside quotes (unlike EPICS V3).  Menu field values may be given as either a string or an integer. For enum fields, if the related field that contains the strings is defined first, the enum field may be specified using a string; otherwise it can only be set using an integer value.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
   ai foo:bar:temperature = {&lt;br /&gt;
       inputSmoothing = 0.98;&lt;br /&gt;
       invalidValue = 1000;&lt;br /&gt;
       units = &amp;quot;Celcius&amp;quot;;&lt;br /&gt;
       scan = &amp;quot;Interrupt&amp;quot;;&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Structure Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''structInitializer:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''structAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''structAssignmentList:''&lt;br /&gt;
: ''initializerList''&lt;br /&gt;
: ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
: ''structAssignmentList'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
&lt;br /&gt;
Initializers for a structure field look similar to a nested record body, but the rules are slightly different:&lt;br /&gt;
* You can give a series of values for adjacent items using a simple comma-separated list (for a record body, you ''must'' name each field)&lt;br /&gt;
* Semi-colons are required between a value and a following named item.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   ai foo:temperature:sensor = {&lt;br /&gt;
       linearConvert = {&lt;br /&gt;
           mode = &amp;quot;Linear&amp;quot;;&lt;br /&gt;
           low = -12.5, 133.5&lt;br /&gt;
       };&lt;br /&gt;
       displayLimit = { 0, 100 };&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
=== Link Initializer ===&lt;br /&gt;
&lt;br /&gt;
; '''Comment from ANJ'''&lt;br /&gt;
: I do not like this syntax, which is verbose and requires the application developer to know the interface names supported by that particular field of the record type (DCTs can provide a menu to choose from, but for anyone who doesn't use a DCT this is not a nice thing to require users to get right).&lt;br /&gt;
: The calcout example presented uses generic choice names which presumably are equivalent to the version 3 PV_LINK type, but the meaning of the link parameters for these is under debate.&lt;br /&gt;
: The syntax for link fields should only need the user to learn a single choice name for each link type. There may be more link types and more choice names as a result, but the interface names themselves should not have to appear in DB files at all.&lt;br /&gt;
: The mbbi example below uses my original and preferred syntax, which is shorter and more in keeping with the rest of the new DB file syntax.&lt;br /&gt;
&lt;br /&gt;
;''linkInitializer:''&lt;br /&gt;
: ''choice(choiceName) supportStructName'' &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''structAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;''choiceName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
;''supportStructName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
These select a particular link support and interface for the field, and set its address according to the structure type defined for that link type.&lt;br /&gt;
&lt;br /&gt;
   calcout foo:temperature:controller = {&lt;br /&gt;
       block = true&lt;br /&gt;
       output = choice(outputLink) PvOutputLink{&lt;br /&gt;
                pvname = &amp;quot;fum:baz:heater&amp;quot;;&lt;br /&gt;
                process = true;&lt;br /&gt;
                wait = true;&lt;br /&gt;
       }&lt;br /&gt;
       input = [2] {&lt;br /&gt;
           {   link = {&lt;br /&gt;
                   choice(monitorLink) PvMonitorLink{&lt;br /&gt;
                       pvname = &amp;quot;foo:temperature:setpoint&amp;quot;;&lt;br /&gt;
                       process = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
           {  block=true&lt;br /&gt;
              link = {&lt;br /&gt;
                   choice(inputLink) PvInputLink {&lt;br /&gt;
                       pvname = &amp;quot;foo:temperature:sensor&amp;quot;;&lt;br /&gt;
                       process = true;&lt;br /&gt;
                       wait = true;&lt;br /&gt;
                       inheritSeverity = true&lt;br /&gt;
                   }&lt;br /&gt;
              }&lt;br /&gt;
           }&lt;br /&gt;
       };&lt;br /&gt;
       expression = &amp;quot;(B - A) &amp;gt; 0&amp;quot;;&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   mbbi foo:bar:door = {&lt;br /&gt;
       input = choice(acro9440) VME{0, 5};&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;QUESTION&amp;lt;/b&amp;gt; There is nothing that allows a DVT to prompt a user&lt;br /&gt;
with a valid set if support for a particular link. Should there be?&lt;br /&gt;
&lt;br /&gt;
=== Array Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''arrayInitializer:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''arrayType'' &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''arrayCapacity'' &amp;lt;tt&amp;gt;] {&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''arrayType'' &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''arrayCapacity'' &amp;lt;tt&amp;gt;] {&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''arrayAssignmentList:''&lt;br /&gt;
: ''initializerList''&lt;br /&gt;
: &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''integerConstant'' &amp;lt;tt&amp;gt;] =&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
: ''arrayAssignmentList'' &amp;lt;tt&amp;gt;; [&amp;lt;/tt&amp;gt; ''integerConstant'' &amp;lt;tt&amp;gt;] =&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
&lt;br /&gt;
;''arrayType:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;int16&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;uint16&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;int32&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;uint32&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;float32&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;float64&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;octet&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''arrayCapacity:''&lt;br /&gt;
: ''integerConstant''&lt;br /&gt;
: ''arrayCapacity'' &amp;lt;tt&amp;gt;,&amp;lt;/tt&amp;gt; ''integerConstant''&lt;br /&gt;
&lt;br /&gt;
If the definition of the array field being set did not do so, an array field initialization must include the size of the array and/or the type of the data stored in it. Inside the braces data values are given in a comma-separated list; the index can also be set to initialize individual values, and any mixture of the two can be used as desired:&lt;br /&gt;
&lt;br /&gt;
   mbbi foo:bar:door = {&lt;br /&gt;
       stateNames = [4] {&amp;quot;Broken&amp;quot;, &amp;quot;Closed&amp;quot;, &amp;quot;Open&amp;quot;, &amp;quot;Moving&amp;quot;};&lt;br /&gt;
       stateSeverity = [4] {&amp;quot;Major&amp;quot;; [3] = &amp;quot;Minor&amp;quot;};&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
For multi-dimensional arrays, data values can only appear inside the inner-most sets of braces, although index settings are permitted outside of these.  These two definitions give the same result:&lt;br /&gt;
&lt;br /&gt;
   matrix identity1 = {&lt;br /&gt;
       value = float32 [3,3] { {1, 0, 0}, {0, 1, 0}, {1, 0, 0}};&lt;br /&gt;
   }&lt;br /&gt;
   matrix identity2 = {&lt;br /&gt;
       value = float32 [3,3] { {1}, {[1] = 1}, {[2] = 1}};&lt;br /&gt;
   }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=580</id>
		<title>V4 DB RecordCommon</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=580"/>
		<updated>2005-11-01T20:27:19Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Standard Support November 01 2005 &lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes two base supplied components for EPICS V4 databases.&lt;br /&gt;
# menuStructBase.dbd - menu and struct definitions &lt;br /&gt;
# baseSupport.dbd - link definitions for base supplied support&lt;br /&gt;
&lt;br /&gt;
This document requires that the reader be familiar with:&lt;br /&gt;
# V3 iocCore&lt;br /&gt;
# V4 DBD Statement Syntax&lt;br /&gt;
# V4 DB Record Instance Syntax&lt;br /&gt;
&lt;br /&gt;
NOTE: This document is ahead of the two above V4 documents so it may use&lt;br /&gt;
slightly different syntax.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= menuStructBase.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Links ==&lt;br /&gt;
&lt;br /&gt;
     struct(PvProcessLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvMonitorLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean) &lt;br /&gt;
     }&lt;br /&gt;
     struct(PvInputLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvOutputLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== asynDriver Link ==&lt;br /&gt;
     struct(AsynLink) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Definitions for recordCommon ==&lt;br /&gt;
&lt;br /&gt;
     # menu definitions for recordCommon fields&lt;br /&gt;
     menu(menuPriority) {&lt;br /&gt;
         choice(menuPriorityLow, &amp;quot;Low&amp;quot;)&lt;br /&gt;
         choice(menuPriorityMedium, &amp;quot;Medium&amp;quot;)&lt;br /&gt;
         choice(menuPriorityHigh, &amp;quot;High&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuScan) {&lt;br /&gt;
         choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
         choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
         choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
         choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
         choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuAlarmSevr) {&lt;br /&gt;
         choice(menuAlarmSevrNone, &amp;quot;None&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMinor, &amp;quot;Minor&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMajor, &amp;quot;Major&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrInvalid, &amp;quot;Invalid&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     #struct definitions for recordCommon&lt;br /&gt;
     struct(TimeStamp) {&lt;br /&gt;
         field(secondsPastEpoch,int64)&lt;br /&gt;
         field(nanoSeconds,int32)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Scan {&lt;br /&gt;
         field(scan,menu(menuScan)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(phase,int16)&lt;br /&gt;
         field(priority,menu(menuPriority)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;b&amp;gt;Event NEEDS NEW DEFINITIONS&amp;lt;/b&amp;gt;&lt;br /&gt;
     struct Event {&lt;br /&gt;
         field(eventNumber,int16) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(timeStampEvent,int16)&lt;br /&gt;
         field(timeStampLink,link)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Disable {&lt;br /&gt;
         field(disableValue,int16) {&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(disableInput,int16)&lt;br /&gt;
         field(disableLink,link)&lt;br /&gt;
         field(disableAlarmSeverity,menu(menuAlarmSevr))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(ProcessLink) {&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(link,link)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(RecordCommon) {&lt;br /&gt;
         field(description,string)&lt;br /&gt;
         field(scan,struct(Scan))&lt;br /&gt;
         field(event,struct(Event))&lt;br /&gt;
         field(accessSecurityGroup,string)&lt;br /&gt;
         field(pini,boolean)&lt;br /&gt;
         field(disablePutField,boolean)&lt;br /&gt;
         field(alarmAckSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmNoAckTransient,menu(menuAlarmSevr)) {&lt;br /&gt;
         # highest level of alarm that does not have to be acknowledged&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         field(udf,boolean) {&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(time,struct(TimeStamp)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(disable,struct(Disable)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmStatus,string) {&lt;br /&gt;
             default(&amp;quot;UDF&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;Invalid&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(processLink,array(ProcessLink[])) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Although it has many fewer fields,&lt;br /&gt;
RecordCommon is a complete replacement for the V3 dbCommon.&lt;br /&gt;
The following V3 fields are no longer needed:&lt;br /&gt;
* private fields - Private fields will truly be private to the implementation&lt;br /&gt;
* previous value fields - All puts to database fields will be posted. The layer above will decide if clients should be notified of changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Other common definitions ==&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;Raw&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(eguf,float64) &lt;br /&gt;
         field(egul,float64)&lt;br /&gt;
         field(slope,float64) &lt;br /&gt;
         field(intercept,float64) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ControlLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
     }&lt;br /&gt;
     struct(AlarmLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(lowSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(lowWarning,float64) &lt;br /&gt;
         field(lowWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(highWarning,float64) &lt;br /&gt;
         field(highWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
         field(highSevr,menu(menuAlarmSevr)) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= definition of record types =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
Most record types are defined as follows:&lt;br /&gt;
     #include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
     record(AiRecord) {&lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
     ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= baseSupport.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Support ==&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* monitor support&lt;br /&gt;
* input support&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For monitor, input, and output The following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
     support(processLink,PvProcessLink)&lt;br /&gt;
     support(monitorLink,PvMonitorLink)&lt;br /&gt;
     support(monitorLinkArray,PvMonitorLink)&lt;br /&gt;
     support(inputLink,PvInputLink)&lt;br /&gt;
     support(inputLinkArray,PvInputLink)&lt;br /&gt;
     support(outputLink,PvOutputLink)&lt;br /&gt;
     support(outputLinkArray)&lt;br /&gt;
&lt;br /&gt;
== asynDriver support ==&lt;br /&gt;
&lt;br /&gt;
     support(asynInt32,AsynLink)&lt;br /&gt;
     support(asynInt32Average,AsynLink)&lt;br /&gt;
     support(asynInt32Monitor,AsynLink)&lt;br /&gt;
     support(asynFloat64,AsynLink)&lt;br /&gt;
     support(asynFloat64Average,AsynLink)&lt;br /&gt;
     support(asynFloat64Monitor,AsynLink)&lt;br /&gt;
     support(asynDigitalMonitor,AsynLink)&lt;br /&gt;
     support(asynDigital,AsynLink)&lt;br /&gt;
     support(asynInt32Array,AsynLink)&lt;br /&gt;
     support(asynFloat64Array,AsynLink)&lt;br /&gt;
     support(asynOctet,AsynLink)&lt;br /&gt;
&lt;br /&gt;
== struct support ==&lt;br /&gt;
For RecordCommon&lt;br /&gt;
     support(common) # no SupportStruct&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Examples&amp;diff=583</id>
		<title>V4 DBD Examples</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Examples&amp;diff=583"/>
		<updated>2005-11-01T20:25:03Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Example Record Types November 01 2005&lt;br /&gt;
= Overview =&lt;br /&gt;
This document present proposed V4 replacements for a few of the&lt;br /&gt;
V3 record types.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= aoRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
aoRecord.dbd might be defined as follows:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
 record(AoRecord) {&lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
     field(value, float64) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(outValue, float64) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(out,link)&lt;br /&gt;
     field(outputRateOfChange, float64)&lt;br /&gt;
     field(desiredOutputLink,link)&lt;br /&gt;
     field(closedLoop, bool)&lt;br /&gt;
     field(outputIncremental, bool)&lt;br /&gt;
     field(convert, menu(menuConvert)) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(linearConvert, struct(LinearConvert)) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(convertTable,string);&lt;br /&gt;
     field(units, string)&lt;br /&gt;
     field(displayLimit, struct(DisplayLimit))&lt;br /&gt;
     field(controlLimit, struct(ControlLimit))&lt;br /&gt;
     field(alarmLimit, struct(AlarmLimit))&lt;br /&gt;
     field(alarmDeadband, float64)&lt;br /&gt;
     field(rawValue, int32) {&lt;br /&gt;
         design(no)&lt;br /&gt;
     }&lt;br /&gt;
     field(readBackValue, int32) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(init, bool) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(simOutputLink,link)&lt;br /&gt;
&lt;br /&gt;
     field(simModeLink,link)&lt;br /&gt;
     field(simMode, bool) &lt;br /&gt;
     field(simSevr, menu(menuAlarmSevr))&lt;br /&gt;
     field(invalidAction, menu(menuIvoa))&lt;br /&gt;
     field(invalidValue, float64)&lt;br /&gt;
     field(outValueModified, bool) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     view(value) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
             property(controlLimit, controlLimit)&lt;br /&gt;
             property(alarmLimit, alarmLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(output) {&lt;br /&gt;
         property(value, outValue) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(raw) {&lt;br /&gt;
         property(value, rawValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(readback) {&lt;br /&gt;
         property(value, readBackValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 } &lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= calcRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
calcRecord.dbd defines the following:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
 struct(CalcInpLink) {&lt;br /&gt;
     field(block,boolean)&lt;br /&gt;
     field(link,link)&lt;br /&gt;
     field(value,float64)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 record(CalcRecord){&lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
     field(result,float64) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(calc,string) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(input,array(struct(CalcInpLink)[])) &lt;br /&gt;
     field(units,string)&lt;br /&gt;
     field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     field(alarmLimit,struct(AlarmLimit))&lt;br /&gt;
     field(alarmDeadband,float64)&lt;br /&gt;
     field(lastValueAlarmed,float64) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(rpcl,private(&amp;quot;char *&amp;quot;))&lt;br /&gt;
     view(result) {&lt;br /&gt;
         property(value, result) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
             property(alarmLimit, alarmLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(expression) {&lt;br /&gt;
         property(value, calc)&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= mbbiRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
mbbiRecord.dbd could be:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
 struct(MbbiState) {&lt;br /&gt;
     field(name, string)&lt;br /&gt;
     field(value, array(octet[]))&lt;br /&gt;
     field(severity, menu(menuAlarmSevr))&lt;br /&gt;
 }&lt;br /&gt;
 record(MbbiRecord) {&lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
     field(state, array(struct(MbbiState)[])) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
#NOTE: stateName needed because enum must refer to array of string&lt;br /&gt;
     field(stateName,array(string[])) {&lt;br /&gt;
         design(no) readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(value, enum(stateName)) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(unknownStateSeverity, menu(menuAlarmSevr))&lt;br /&gt;
     field(changeStateSeverity, menu(menuAlarmSevr))&lt;br /&gt;
     field(inp, link)&lt;br /&gt;
     field(rawValue, array(octet[])) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(hardwareShift, int16) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(hardwareMask, array(octet[]) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     view(choice) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(raw) {&lt;br /&gt;
         property(value, raw) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= waveformRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
waveformRecord.dbd defines the following:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
 record(WaveformRecord) {&lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
     field(value, array([])) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(reArm,bool)&lt;br /&gt;
     field(io,link)&lt;br /&gt;
     field(units,string)&lt;br /&gt;
     field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     field(busy,bool) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     view(value) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=578</id>
		<title>V4 Link Support Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=578"/>
		<updated>2005-11-01T20:23:00Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC link and struct Support November 01 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
The V4 link/struct support is a replacement for V3 &lt;br /&gt;
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK&lt;br /&gt;
# device DBD definition and device support&lt;br /&gt;
# driver DBD definition and driver support&lt;br /&gt;
&lt;br /&gt;
Each link and struct field in a record can have associated support.&lt;br /&gt;
* record support communicates with support via interfaces&lt;br /&gt;
* link or struct support implements interfaces&lt;br /&gt;
** link or struct support registers the interfaces it implements&lt;br /&gt;
** record support looks for interfaces it uses&lt;br /&gt;
*** it uses only the interfaces it finds&lt;br /&gt;
*** if no interfaces are found it reports an error&lt;br /&gt;
&lt;br /&gt;
Support has no knowledge of what record types are using it.&lt;br /&gt;
Struct support may have knowledge of the struct field&lt;br /&gt;
but not of the record type.&lt;br /&gt;
recordSupport has no knowledge about support other than the&lt;br /&gt;
interface it is using.&lt;br /&gt;
&lt;br /&gt;
For the rest of this document recordSupport means record support and support,&lt;br /&gt;
unless qualified, means link or struct support.&lt;br /&gt;
&lt;br /&gt;
EPICS base defines a standard set of interfaces for support,&lt;br /&gt;
which includes enough functionality such that&lt;br /&gt;
most support can be implemented via just these interfaces.&lt;br /&gt;
&lt;br /&gt;
Most of the support supplied with base is link support. In particular&lt;br /&gt;
support for channel/database access links. It also briefly describes&lt;br /&gt;
support for interfacing with asynDriver.&lt;br /&gt;
&lt;br /&gt;
The link interfaces support Channel/Database access&lt;br /&gt;
and the generic EPICS device support supplied by asynDriver.&lt;br /&gt;
Since asynDriver is intended as a framework for interfacing to most hardware,&lt;br /&gt;
this means that the interfaces supplied and used by base allows support&lt;br /&gt;
for most hardware. The support can communicate with the hardware&lt;br /&gt;
however it wants but must implement some set of the interfaces defined&lt;br /&gt;
by base.&lt;br /&gt;
&lt;br /&gt;
This document gives a brief overview of the V4 link/struct support model.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Database Definitions For links and structures =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section first reviews the DBD syntax related to link definitions.&lt;br /&gt;
It then gives a brief description of link related definitions in dbCommon.dbd&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
A record link has the syntax:&lt;br /&gt;
     field(name,link)&lt;br /&gt;
A record struct has the syntax&lt;br /&gt;
     field(name,struct(structName))&lt;br /&gt;
Support for a struct or link has the syntax&lt;br /&gt;
     support(choiceName) // no SupportStruct&lt;br /&gt;
     support(choiceName,supportStructName)&lt;br /&gt;
A record instance struct has the the syntax&lt;br /&gt;
    field = StructName{structAssignmentList} // no support&lt;br /&gt;
    field = support(choiceName)&lt;br /&gt;
            StructName{structAssignmentList} // support has no SupportStruct&lt;br /&gt;
    field = support(choiceName) SupportStruct{structAssignmentList}&lt;br /&gt;
            StructName{structAssignmentList}&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;structName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice. Each support must have a unique name.&lt;br /&gt;
; &amp;lt;tt&amp;gt;supportStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the support. recordSupport normally does not access this structure. Database configuration tools prompt the user to assign values to the structure.&lt;br /&gt;
&lt;br /&gt;
Assume the following definitions:&lt;br /&gt;
     record(AiRecord) {&lt;br /&gt;
         ...&lt;br /&gt;
         field(in,link)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     struct(PvMonitorLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvInputLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     support(monitorLink,PvMonitorLink)&lt;br /&gt;
     support(inputLink,PvInputLink)&lt;br /&gt;
     struct VME{&lt;br /&gt;
         field(a16,int16) &lt;br /&gt;
         field(a32,int32)&lt;br /&gt;
         field(channel,int16)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     support(someVmeADC,VME)&lt;br /&gt;
&lt;br /&gt;
The first example instance definition selects a monitor link.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {support(monitorLink)&lt;br /&gt;
                   PvMonitorLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                         process = true;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The next example selects a channel access input link.&lt;br /&gt;
     AiRecord aiInputExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {support(inputLink)&lt;br /&gt;
                   PvInputLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                        process = true;&lt;br /&gt;
                        wait = true;&lt;br /&gt;
                        timeout = 1.0;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The last example selects support for a VME Analog to Digital device.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {support(someVmeADC) VME {a16 = 0xc000; channel = 1} }&lt;br /&gt;
&lt;br /&gt;
== Standard Definitions For Channel/Database Access ==&lt;br /&gt;
&lt;br /&gt;
menuStructBase.dbd defines definitions for Channel/Database Access Links.&lt;br /&gt;
The base supplied support registers each choiceName in the support definitions.&lt;br /&gt;
The complete set of data structure and support definitions are defined&lt;br /&gt;
in &amp;quot;V4 DB RecordCommon&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* monitor&lt;br /&gt;
* input&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For monitor, input, and output the following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
&lt;br /&gt;
These are definitions that are used by the standard EPICS device support&lt;br /&gt;
for asynDriver. Since asynDriver is a generic way of interfacing arbitrary&lt;br /&gt;
hardware support, this is a generic way of attaching links in records to&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLink) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== support definitions ===&lt;br /&gt;
&lt;br /&gt;
     support(asynInt32,AsynLink)&lt;br /&gt;
     support(asynInt32Average,AsynLink)&lt;br /&gt;
     support(asynInt32Monitor,AsynLink)&lt;br /&gt;
     support(asynFloat64,AsynLink)&lt;br /&gt;
     support(asynFloat64Average,AsynLink)&lt;br /&gt;
     support(asynFloat64Monitor,AsynLink)&lt;br /&gt;
     support(asynDigitalMonitor,AsynLink)&lt;br /&gt;
     support(asynDigital,AsynLink)&lt;br /&gt;
     support(asynInt32Array,AsynLink)&lt;br /&gt;
     support(asynFloat64Array,AsynLink)&lt;br /&gt;
     support(asynOctet,AsynLink)&lt;br /&gt;
&lt;br /&gt;
This is the set of definitions for the standard EPICS device support implemented&lt;br /&gt;
by asynDriver. Although, at least for the first few V4 releases,&lt;br /&gt;
asynDriver will not be part of base, they are shown here because the&lt;br /&gt;
LinkInt32,... interface definitions are defined as part of base.&lt;br /&gt;
Again it is expected that almost all hardware support be created by&lt;br /&gt;
implementing a combination of these link interface definitions or&lt;br /&gt;
the interfaces implemented by Channel/Database access link support.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
An arbitrary number of Link Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
Other link support can also be supplied.&lt;br /&gt;
Whenever possible support should implement the standard interfaces&lt;br /&gt;
supplied by EPICS base, since these are the interfaces that the record types&lt;br /&gt;
supplied with base know how to use.&lt;br /&gt;
&lt;br /&gt;
Soft support should try to implement the same interfaces implemented by&lt;br /&gt;
the Channel/Database access support supplied with base. The support&lt;br /&gt;
can, of course, define data structures for it's own use.&lt;br /&gt;
Implementing these interfaces means that the support will work for&lt;br /&gt;
the same set of record links as the Channel/Database access support.&lt;br /&gt;
&lt;br /&gt;
Hardware support should, if possible, also implement the same interfaces&lt;br /&gt;
implemented by the Channel/Database access support.&lt;br /&gt;
Message based support may also have to implement the AsynOctet interface&lt;br /&gt;
but this interface is only used by a few record types.&lt;br /&gt;
&lt;br /&gt;
This section describes the interfaces implemented by all link support&lt;br /&gt;
and then the standard interfaces used by the records supplied with base.&lt;br /&gt;
&lt;br /&gt;
The syntax is similar to Java syntax since it is more concise than C++.&lt;br /&gt;
It can easily be translated to C++ syntax. For example the&lt;br /&gt;
definition:&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int16 data);&lt;br /&gt;
         boolean getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class LinkInt16 {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual LinkResult get(Callback &amp;amp;callback, int16_t &amp;amp;data) = 0;&lt;br /&gt;
         virtual LinkResult put(Callback &amp;amp;callback, int16_t data) = 0;&lt;br /&gt;
         virtual bool getBounds(int16_t &amp;amp;low, int16_t &amp;amp;high) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Link and MonitorLink ==&lt;br /&gt;
&lt;br /&gt;
All support &amp;lt;b&amp;gt;must&amp;lt;/b&amp;gt; register interface &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt;&lt;br /&gt;
and if it supports monitors interface &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE: arguments and return types ignored for now&amp;lt;/b&amp;gt;&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; is an interface that is implemented by link support that&lt;br /&gt;
supports monitors. An example is support for hardware interrupts.&lt;br /&gt;
The &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally recordSupport does not need to call any of the Link &lt;br /&gt;
or MonitorLink methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call destroy before modifying the link&lt;br /&gt;
and initialize and connect after the link is modified.&lt;br /&gt;
&lt;br /&gt;
Note that neither Link or MonitorLink is listed in the &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; database&lt;br /&gt;
definition since they are generic.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
These are the definitions used by the Channel/Database access support&lt;br /&gt;
supplied with base. It is also used by the standard EPICS support from asyn.&lt;br /&gt;
&lt;br /&gt;
     enum LinkResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface LinkProcess {&lt;br /&gt;
         LinkResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
&lt;br /&gt;
     interface LinkOctet {&lt;br /&gt;
         LinkResult get(Callback callback, Octet data);&lt;br /&gt;
         LinkResult put(Callback callback, octet data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkResult get(Callback callback, octet[] data);&lt;br /&gt;
         LinkResult put(Callback callback, octet[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;GENERIC QUESTION&amp;lt;/b&amp;gt; The data is passed as primitive or arrays of&lt;br /&gt;
primitive types. Should &amp;lt;tt&amp;gt;Dbf&amp;lt;/tt&amp;gt; interfaces be used? Needs thought.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== asynDigital Support ==&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkResult write(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          LinkResult read(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,Boolean data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,boolean[] data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int16 data);&lt;br /&gt;
         boolean getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,int16[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int16[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         boolean getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,int32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,Int64 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int64 data);&lt;br /&gt;
         boolean getBounds(Int64 low, Int64 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,int64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,Float32 data);&lt;br /&gt;
         LinkResult put(Callback callback,float32 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,float32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,Float64 data);&lt;br /&gt;
         LinkResult put(Callback callback,float64 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,float64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkResult get(Callback callback,string data);&lt;br /&gt;
         LinkResult put(Callback callback,string data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkResult get(Callback callback,string[] data);&lt;br /&gt;
         LinkResult put(Callback callback,string[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Example - VME ADC support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
Assume the VME and support definitions given in the examples at the beginning&lt;br /&gt;
of this document.&lt;br /&gt;
&lt;br /&gt;
The following is presented with Java syntax.&lt;br /&gt;
It assumes that there is VME support of the form&lt;br /&gt;
&lt;br /&gt;
     public class vme {&lt;br /&gt;
         static public short getShort(long addr);&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The link support would be something like:&lt;br /&gt;
&lt;br /&gt;
     class AdcSupport implements Link LinkInt32 {&lt;br /&gt;
     AdcSupport(VME fromFactory)&lt;br /&gt;
     {&lt;br /&gt;
         addr = fromFactory;&lt;br /&gt;
         connected = false;&lt;br /&gt;
         //  from the VME initialize vmeaddr and channel&lt;br /&gt;
         // details left to your imagination&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Link methods&lt;br /&gt;
     void report(int16_t level)&lt;br /&gt;
     {&lt;br /&gt;
         printf(&amp;quot;AdcSupport a16 %x channel %d\n&amp;quot;,a16,channel);&lt;br /&gt;
     }&lt;br /&gt;
     void cancel() {} // nothing to do&lt;br /&gt;
     void destroy() {} //nothing to do&lt;br /&gt;
     void initialize()&lt;br /&gt;
     {&lt;br /&gt;
         // make sure we can access a16&lt;br /&gt;
     }&lt;br /&gt;
     void connect() {connected = true}&lt;br /&gt;
     void disconnect() {connected = false}&lt;br /&gt;
     &lt;br /&gt;
     // LinkInt32 methods&lt;br /&gt;
     LinkResult get(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         data = (Int)VME.getShort(vmeaddr);&lt;br /&gt;
         return linkDone;&lt;br /&gt;
     }&lt;br /&gt;
     LinkResult put(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         throw CantWriteAdc;&lt;br /&gt;
     }&lt;br /&gt;
     void getBounds(Int low, Int high) &lt;br /&gt;
     {&lt;br /&gt;
         // assume 16 bit unipolor adc&lt;br /&gt;
         low = 0; high = 0xffff;&lt;br /&gt;
     }&lt;br /&gt;
     private:&lt;br /&gt;
         VME addr;&lt;br /&gt;
         int vmeaddr;&lt;br /&gt;
         int channel;&lt;br /&gt;
         boolean connected;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Discussion of link support interfaces =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The definitions: record link, support, record instance links,&lt;br /&gt;
and the link interfaces are designed to support channel/database links,&lt;br /&gt;
links to hardware support, and links to other types of support.&lt;br /&gt;
&lt;br /&gt;
The following are two important requirements:&lt;br /&gt;
* analog I/O&lt;br /&gt;
** link support can return raw value. Support must convert to engineering units.&lt;br /&gt;
** link support can return engineering units&lt;br /&gt;
* output records&lt;br /&gt;
** Can link support provide initial value?&lt;br /&gt;
** What if multiple sources can change linked output?&lt;br /&gt;
&lt;br /&gt;
Lets consider each of these separately.&lt;br /&gt;
== Analog I/O ==&lt;br /&gt;
In V3 the aiRecord and aoRecords are responsible for conversion between&lt;br /&gt;
raw values and engineering units. Raw values are 32 bit integers. Device&lt;br /&gt;
support is responsible for setting the slope and intercept fields of the record.&lt;br /&gt;
recordSupport takes care of the actual conversions.&lt;br /&gt;
Device support can tell recordSupport that it set the engineering units&lt;br /&gt;
rather than a raw value by a different return value.&lt;br /&gt;
&lt;br /&gt;
For V4 the following is done:&lt;br /&gt;
&lt;br /&gt;
aiRecord and aoRecord both have the following fields:&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;None&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(eguf,float64)&lt;br /&gt;
         field(egul,float64)&lt;br /&gt;
         field(slope,float64)&lt;br /&gt;
         field(intercept,float64)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     ...&lt;br /&gt;
     field(convert, menu(menuConvert))&lt;br /&gt;
     field(linearConvert, struct(LinearConvert))&lt;br /&gt;
     field(convertTable,string);&lt;br /&gt;
     field(units, string)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a record instance has convert set to None then recordSupport does the following.&lt;br /&gt;
* if link support implements LinkFloat64 it just calls this to obtain an engineering units value&lt;br /&gt;
* otherwise it gets a value via interface LinkInt32 and converts the value from in int32 to a float64.&lt;br /&gt;
&lt;br /&gt;
If a record instance has convert linear&lt;br /&gt;
* if link support implements LinkInt32 it uses LinkInt32 otherwise it uses LinkFloat64&lt;br /&gt;
* it uses slope and interccept to convert from raw to engineering units&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;LinkInt32&amp;lt;/tt&amp;gt; is defined as:&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         boolean getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
If convert is linear and getBounds returns true than recordSupport&lt;br /&gt;
uses the returned value to compute slope and intercept. In all&lt;br /&gt;
other cases recordSupport just uses whatever values they have.&lt;br /&gt;
&lt;br /&gt;
For example support for a 16 bit unipolar ADC would set low=0, high=65535,&lt;br /&gt;
and return true.&lt;br /&gt;
If link support can not determine the bounds then getBounds returns false.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE:&amp;lt;/b&amp;gt;The interface implemented by breakpoint tables must be defined.&lt;br /&gt;
It will support the same semantics as the V3 breakpoint tables.&lt;br /&gt;
&lt;br /&gt;
== Output Records ==&lt;br /&gt;
&lt;br /&gt;
The following are two features that link support should implement&lt;br /&gt;
whenever possible:&lt;br /&gt;
# When a record is initalized provide the current value of the output&lt;br /&gt;
# If something else modifies the actual output value in the record&lt;br /&gt;
&lt;br /&gt;
The first feature is especially desirable when an IOC is rebooted.&lt;br /&gt;
If a hardware output can survive a reboot this is a very desirable feature.&lt;br /&gt;
If the output is to a field bus, a PLC, or to a record in another IOC&lt;br /&gt;
it is often possible for the link support to determine the current value.&lt;br /&gt;
&lt;br /&gt;
The second feature is something that was often asked for in V3 but&lt;br /&gt;
only implemented&lt;br /&gt;
for some special cases. This is especially desirable when the output is&lt;br /&gt;
connected to a system that can have multiple sources of control.&lt;br /&gt;
Examples are GPIB devices with front pannel controls, PLC systems that&lt;br /&gt;
have manual controls or non-epics network access.&lt;br /&gt;
&lt;br /&gt;
For V3 some of the hardware , but none of the soft,&lt;br /&gt;
support implemented the first feature but by&lt;br /&gt;
modifying actual fields in the record. V3 did not implement the second&lt;br /&gt;
feature. Some special device support, not part of base, was implemented&lt;br /&gt;
to support this feature.&lt;br /&gt;
&lt;br /&gt;
For V4 these features are supported as follows:&lt;br /&gt;
&lt;br /&gt;
=== record initialization ===&lt;br /&gt;
&lt;br /&gt;
The link support implements an interface that has a put and a get method.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         boolean getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
If the link support can support readbacks then it implements get&lt;br /&gt;
and returns linkDone. If it does not support readbacks&lt;br /&gt;
then it implements get by just returning linkNoop.&lt;br /&gt;
&lt;br /&gt;
=== monitors for outputs ===&lt;br /&gt;
&lt;br /&gt;
If output link support can detect when something besides the link support&lt;br /&gt;
itself modifies the output then it implements interface &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt;&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
At initialization recordSupport looks for this interface and if found&lt;br /&gt;
it calls &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt;. The link support calls the callback whenever&lt;br /&gt;
it detects a change in the output that it did not cause. recordSupport&lt;br /&gt;
causes itself to be processed without making a new call to the&lt;br /&gt;
link support.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Struct Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
== support for RecordCommon ==&lt;br /&gt;
This implements the same interface a record support.&lt;br /&gt;
== support for LinearConvert ==&lt;br /&gt;
This implements the interface&lt;br /&gt;
     interface LinearConvertSupport {&lt;br /&gt;
          convert(int32 raw,Float64 value) // from raw to eng&lt;br /&gt;
          convert(float64 value,Int32 raw) // from eng to raw&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In addition it provides a factory&lt;br /&gt;
     interface LinearConvertFactory {&lt;br /&gt;
         LinearConvertSupport(string choiceName,&lt;br /&gt;
             DbfStruct linearConvert,DbfLink inlink)&lt;br /&gt;
     }&lt;br /&gt;
== support for simulation ==&lt;br /&gt;
This needs to be defined.&lt;br /&gt;
== support for breakpoint tables ==&lt;br /&gt;
This needs to be defined.&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Record_Processing&amp;diff=581</id>
		<title>V4 Design: Record Processing</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Record_Processing&amp;diff=581"/>
		<updated>2005-11-01T20:09:11Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Record Processing November 01 2005 &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;UNRESOLVED ISSUES&amp;lt;/b&amp;gt;&lt;br /&gt;
* This document is still evolving&lt;br /&gt;
* Monitors&lt;br /&gt;
** How will monitor data be managed?&lt;br /&gt;
** Big problem is how will array data be managed?&lt;br /&gt;
* Alarms&lt;br /&gt;
** How will V4 handle alarms?&lt;br /&gt;
* Events&lt;br /&gt;
** What is the V4 event model?&lt;br /&gt;
** What is required from the IOC database?&lt;br /&gt;
&lt;br /&gt;
This document described semantics for V4 record processing that are&lt;br /&gt;
different than for V3.&lt;br /&gt;
This includes the following:&lt;br /&gt;
* Semantics for record processing&lt;br /&gt;
* Semantics for Database and Channel Access Links.&lt;br /&gt;
* Record Locking&lt;br /&gt;
* Posting database monitors&lt;br /&gt;
* Status and Alarm Severity&lt;br /&gt;
* Access to array and structure fields.&lt;br /&gt;
&lt;br /&gt;
This version is based on feedback from the EPICS core developer's&lt;br /&gt;
meeting at ANL/APS on July 11th through July 14th.&lt;br /&gt;
In addition discussions with Andrew Johnson and Eric Norum have &lt;br /&gt;
led to many of the ideas described below.&lt;br /&gt;
This wiki is a companion to the wiki &amp;quot;V4 Design: dbdInterfaces&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
V3 record processing semantics do not work well for data&lt;br /&gt;
acquisition applications. An example of data acquisition is:&lt;br /&gt;
*  Move sample to new position.&lt;br /&gt;
** Several motors may be involved&lt;br /&gt;
** While moving post monitors to show current position, etc.&lt;br /&gt;
* Sample data&lt;br /&gt;
* Wait until CA client has fetched the data before next move.&lt;br /&gt;
&lt;br /&gt;
SynAPPS provides the Scan, motor, etc records which help with&lt;br /&gt;
data processing applications. These records process as follows:&lt;br /&gt;
&lt;br /&gt;
* Record does not complete processing until all inputs, outputs, etc done. Not completing means that they do not call recGblFwdLink until all proccessing is complete. Note that recGblFwdLink is what causes the V3 ioc to complete record processing.&lt;br /&gt;
* While waiting for asynchronous events these records have PACT=0 but keep state that shows it is still active&lt;br /&gt;
* Can be scanned and issue monitors while internal state is active&lt;br /&gt;
&lt;br /&gt;
Leaving PACT 0 but not calling recGblFwdLink was not anticipated when the V3 record processing semantics were created.&lt;br /&gt;
For V4 a record can be processed while it is waiting&lt;br /&gt;
for asynchronous processing to complete.&lt;br /&gt;
&lt;br /&gt;
In V3, if an input link is asynchronous, Process Passive does not wait&lt;br /&gt;
for asynchronous processing to complete before fetching data.&lt;br /&gt;
This also complicated data acquisition applications.&lt;br /&gt;
&lt;br /&gt;
V4 record processing is designed to make data acquisition easier.&lt;br /&gt;
Both input and output links can wait for record processing.&lt;br /&gt;
This is done, however, without record support blocking.&lt;br /&gt;
If blocking makes it easier to implement record support,&lt;br /&gt;
then the support can spawn a separate thread that does block.&lt;br /&gt;
Record support can communicate with the separate thread to decide when&lt;br /&gt;
to complete record processing.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Overview of V4 Record Processing =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
V4 will provide something analogous to V3 dbProcess.&lt;br /&gt;
The name may be different but for now it will still be called dbProcess.&lt;br /&gt;
&lt;br /&gt;
In V4 database access and channel access appear the same to record and&lt;br /&gt;
link support.&lt;br /&gt;
Only the implementation knows the difference.&lt;br /&gt;
In this document the term channelAccess will mean access to a record.&lt;br /&gt;
Thus it can mean a workstation client or a field of&lt;br /&gt;
a record that is a link to a record.&lt;br /&gt;
&lt;br /&gt;
V4 also allows support for &amp;lt;b&amp;gt;struct&amp;lt;/b&amp;gt; fields.&lt;br /&gt;
In particular base provides support for &lt;br /&gt;
     field(common,struct(RecordCommon))&lt;br /&gt;
This field appears as the first field in the record types provided with base&lt;br /&gt;
and can also appear as the first field of other types.&lt;br /&gt;
The fields in &amp;lt;b&amp;gt;RecordCommon&amp;lt;/b&amp;gt; are the V4 replacement for&lt;br /&gt;
the V3 dbCommon fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
V4 record processing has the following features.&lt;br /&gt;
&lt;br /&gt;
* database fields&lt;br /&gt;
** &amp;quot;owned&amp;quot; by database not record support&lt;br /&gt;
** fields can only be accessed via interfaces&lt;br /&gt;
** support can optionally provide storage for data associated with a field&lt;br /&gt;
** for channelAccess all fields appear as type primitive, string, struct, array or combination thereof&lt;br /&gt;
* dbProcess&lt;br /&gt;
** processes synchronous linked records by queuing requests rather than recursive calls to dbProcess&lt;br /&gt;
** can be called an arbitrary number of times while record is active&lt;br /&gt;
* link&lt;br /&gt;
** always has associated support&lt;br /&gt;
** can be record link or can be something else, e.g. a link to hardware&lt;br /&gt;
* record link&lt;br /&gt;
** can request process and/or wait for asynchronous completion&lt;br /&gt;
** local synchronous requests queued by dbProcess&lt;br /&gt;
** record is active and can be processed while asynchronous links active&lt;br /&gt;
* struct fields&lt;br /&gt;
** Can have associated support which can be synchronous or asynchronous&lt;br /&gt;
* block&lt;br /&gt;
** is requested via a separate field&lt;br /&gt;
** if true than support waits for all outstanding I/O to complete before calling link or struct support&lt;br /&gt;
** if false than asynchronous support can proceed in parallel&lt;br /&gt;
* lock&lt;br /&gt;
** record instances are locked&lt;br /&gt;
** dbProcess locks before calling support&lt;br /&gt;
** other code can also lock&lt;br /&gt;
** Two records can be locked without deadlock&lt;br /&gt;
* monitors&lt;br /&gt;
** dbProcess handles monitors&lt;br /&gt;
** support triggers monitors by writing to fields&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Database Fields =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
== Field Access by Support Code ==&lt;br /&gt;
Support code can access database fields only via interfaces implemented by&lt;br /&gt;
the IOC database.&lt;br /&gt;
Thus record fields are owned by the IOC database not by record support.&lt;br /&gt;
&lt;br /&gt;
Support code can register to provide storage for particular fields.&lt;br /&gt;
For example support code could implement a circular buffer for field &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
When some other code&lt;br /&gt;
request the array associated with &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, the IOC database&lt;br /&gt;
calls the support. The support returns the first portion of the circular&lt;br /&gt;
buffer and the caller must make an additional call to retrieve the rest of&lt;br /&gt;
the circular buffer.&lt;br /&gt;
&lt;br /&gt;
== Field Access by Channel Access ==&lt;br /&gt;
&lt;br /&gt;
For V4 database access and channel access appear the same to record&lt;br /&gt;
instances.&lt;br /&gt;
It is only the code that implements link support that knows the difference.&lt;br /&gt;
If a linked record is local, database access is used, and, if the record&lt;br /&gt;
is remote, channel access.&lt;br /&gt;
&lt;br /&gt;
V4 allows channel access to the following types of fields:&lt;br /&gt;
&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* one dimensional array of primitive or string or struct&lt;br /&gt;
* struct with fields of following types:&lt;br /&gt;
** primitive&lt;br /&gt;
** string&lt;br /&gt;
** struct&lt;br /&gt;
** array of primitive or string or struct&lt;br /&gt;
&lt;br /&gt;
For other database field types, i.e. links, the database will make the field&lt;br /&gt;
appear as one of the above types. For example a link field will appear&lt;br /&gt;
as a string with syntax that matches the information associated with the link.&lt;br /&gt;
For example a process link will have a string something like&lt;br /&gt;
    support(processLink) PvProcessLink(pvname = 'pvname'; wait = true)&lt;br /&gt;
where&lt;br /&gt;
; &amp;lt;tt&amp;gt;processLink&amp;lt;/tt&amp;gt;&lt;br /&gt;
: selects the support for a process link&lt;br /&gt;
; &amp;lt;tt&amp;gt;PvProcessLink&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Names the struct that the support uses for configuration information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Record Processing Semantics =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section describes the semantics implemented by dbProcess.&lt;br /&gt;
&lt;br /&gt;
The following are involved in record processing&lt;br /&gt;
* dbProcess&lt;br /&gt;
** implements a queue for local records that are processed because of record links&lt;br /&gt;
** posts monitors caused by field changes during record processing&lt;br /&gt;
* record support&lt;br /&gt;
** calls support code for RecordCommon fields&lt;br /&gt;
** is responsible for record instance fields&lt;br /&gt;
** calls link/struct support via interfaces implemented by the support&lt;br /&gt;
* link support&lt;br /&gt;
** can be links to other records, to driver support, etc&lt;br /&gt;
** implements interfaces called by record and/or other support&lt;br /&gt;
* struct support&lt;br /&gt;
** is responsible for all fields in the struct&lt;br /&gt;
** implements interfaces called by record and/or other support&lt;br /&gt;
&lt;br /&gt;
== Processing Life Cycle ==&lt;br /&gt;
Assume a record instance is idle, i.e. is ready to start processing.&lt;br /&gt;
*dbProcess calls record support with one of the following states&lt;br /&gt;
** processCancel - record support must terminate any outstanding processing&lt;br /&gt;
** processStart - start processing. record support returns one of&lt;br /&gt;
*** processDone - All done and successful&lt;br /&gt;
*** processQuit - dont do any more processing. Return to idle state&lt;br /&gt;
*** processActive - not done. Call again&lt;br /&gt;
** processContinue - another request to process while record is active. Record support again returns one of the above.&lt;br /&gt;
&lt;br /&gt;
Record support, with associated link/struct support does the following:&lt;br /&gt;
* When it is called for processStart&lt;br /&gt;
** calls the support for RecordCommon with state processStart. it returns&lt;br /&gt;
*** processDone - Record support starts processing record specific fields&lt;br /&gt;
*** processQuit - Record support just returns processQuit to dbProcess&lt;br /&gt;
*** processActive - Record returns processActive. It will be called again with state processContinue. It calls RecordCommon support with state processActive. This continues until Record Common returns processDone or processQuit&lt;br /&gt;
* When RecordCommon returns processDone it starts processing record specific fields&lt;br /&gt;
** Associated link or struct support may be called&lt;br /&gt;
*** Record support implements any &amp;lt;tt&amp;gt;block&amp;lt;/tt&amp;gt; fields.&lt;br /&gt;
*** It detects when asynchronous support completes&lt;br /&gt;
*** as long as there is incomplete asynchronous support it returns processActive to dbProcess&lt;br /&gt;
** When all record specific fields have been processed it calls RecordCommon suport with state processQuit&lt;br /&gt;
*** RecordCommon support can return processActive. Until it returns processDone, record support just returns processActive to dbProcess&lt;br /&gt;
** When RecordCommon returns processDone, record support returns processDone to dbProcess.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
struct and link fields can have associated support&lt;br /&gt;
* associated support may be asynchronous&lt;br /&gt;
** support returns indicating that it is active&lt;br /&gt;
** support is required to detect when asynchronous support completes&lt;br /&gt;
** when processing is complete support returns indicating that it is done.&lt;br /&gt;
* whenever record support returns to dbProcess, dbProcess posts any fields that were modified.&lt;br /&gt;
** record may be active or done&lt;br /&gt;
* when record support returns processDone or processQuit record is again set idle.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== record common ==&lt;br /&gt;
&lt;br /&gt;
These fields are optional but it is expected that most record&lt;br /&gt;
types will include a standard set of fields.&lt;br /&gt;
&lt;br /&gt;
The support for RecordCommon processes the following fields:&lt;br /&gt;
&lt;br /&gt;
* at the beginning of record processing&lt;br /&gt;
** disable - if true NO processing will be done, i.e. processQuit is returned&lt;br /&gt;
** scanDisable&lt;br /&gt;
*** has associated support&lt;br /&gt;
*** if record is scan disabled processQuit is returned&lt;br /&gt;
** alarm fields&lt;br /&gt;
*** alarm handling is described below&lt;br /&gt;
* after record support completes&lt;br /&gt;
** processLink array&lt;br /&gt;
*** has associated support&lt;br /&gt;
&lt;br /&gt;
== record support ==&lt;br /&gt;
&lt;br /&gt;
Record support is responsible for all its fields.&lt;br /&gt;
For link and struct fields there may be associated support which&lt;br /&gt;
may be synchronous or asynchronous.&lt;br /&gt;
Record support communicates with&lt;br /&gt;
the link/struct support via interfaces that are implemented by the support.&lt;br /&gt;
If the record includes a field for struct(RecordCommon) it should&lt;br /&gt;
use the associated support for its fields.&lt;br /&gt;
&lt;br /&gt;
Record support may be called multiple times by dbProcess while a record instance&lt;br /&gt;
is active.&lt;br /&gt;
One of the arguments to process is ProcessState which has the values:&lt;br /&gt;
* processCancel - Cancel any outstanding activity&lt;br /&gt;
* processStart - Start processing&lt;br /&gt;
* processContinue - Making additional call&lt;br /&gt;
&lt;br /&gt;
process returns ProcessReturn which is one of the following:&lt;br /&gt;
* processDone - Done and successful&lt;br /&gt;
* processQuit - Do not do any more processing&lt;br /&gt;
* processActive - Not done&lt;br /&gt;
&lt;br /&gt;
If record support returns processActive it must keep internal state so&lt;br /&gt;
that it knows how to handle processCancel and processContinue.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For record support the above rules allow:&lt;br /&gt;
* process can be called repeatedly. This will continue as long as it returns processActive&lt;br /&gt;
* Everytime process returns processActive DbProcess posts monitors.&lt;br /&gt;
&lt;br /&gt;
== Record Locking ==&lt;br /&gt;
&lt;br /&gt;
V3 implemented lock sets in order to prevent different threads&lt;br /&gt;
from simultaneously accessing linked records.&lt;br /&gt;
&lt;br /&gt;
Instead of lock sets V4:&lt;br /&gt;
* implements a per record instance lock.&lt;br /&gt;
* defines a rule that allows two records to be locked without deadlocks&lt;br /&gt;
&lt;br /&gt;
== Posting Monitors ==&lt;br /&gt;
&lt;br /&gt;
In V3 monitors are posted when code (record support, device support, database access, etc) calls db_post_event. In V4 database access will itself handle&lt;br /&gt;
the posting of monitors.&lt;br /&gt;
&lt;br /&gt;
Monitors are posted by DbProcess when&lt;br /&gt;
* record support returns processActive.&lt;br /&gt;
* at the end of record processing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= link/struct Semantics =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both link and struct fields can have associated support.&lt;br /&gt;
The support can be synchronous or asynchronous.&lt;br /&gt;
&lt;br /&gt;
Support code implements interfaces.&lt;br /&gt;
Code that is responsible for a field communicates with the support via&lt;br /&gt;
the interface. Lets call this code the client.&lt;br /&gt;
&lt;br /&gt;
Each link and struct field has a well defined client.&lt;br /&gt;
* dbProcess is the client for fields in dbCommon&lt;br /&gt;
* record support is the client for the other top level fields in a record&lt;br /&gt;
* the struct support is the client for any link or struct fields in the struct&lt;br /&gt;
&lt;br /&gt;
A link/struct may have an associated block. The client is responsible for&lt;br /&gt;
implementing block. If block is true then the support will not be called&lt;br /&gt;
until all outstanding record activity completes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= channelAccess links =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
channelAccess link means access to a record or field. The requester can be:&lt;br /&gt;
* A database link in a record&lt;br /&gt;
* A channel access link in a record&lt;br /&gt;
* A workstation channel access client&lt;br /&gt;
&lt;br /&gt;
A channelAccess link is one of the following types:&lt;br /&gt;
* Monitor Link&lt;br /&gt;
** Implemented via a monitor request on linked field&lt;br /&gt;
** Optionally process record containing the link when monitor value is returned.&lt;br /&gt;
* Input Link&lt;br /&gt;
** Optionally request that record be processed.&lt;br /&gt;
** Optionally wait for linked record to complete processing.&lt;br /&gt;
** Get value.&lt;br /&gt;
* Output Link: &lt;br /&gt;
** Put value&lt;br /&gt;
** Optionally request processing. &amp;lt;b&amp;gt;If record can not be processed should the value be changed?&amp;lt;/b&amp;gt;&lt;br /&gt;
** Optionally wait until completion&lt;br /&gt;
* Process Link: Perform the following actions&lt;br /&gt;
** Request processing&lt;br /&gt;
** Optionally wait until linked record completes&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* processLink is the replacement for the V3 forwardLink&lt;br /&gt;
* wait does NOT mean to wait synchronously. It means to save state, return, and resume at the saved state when called again.&lt;br /&gt;
&lt;br /&gt;
Links are processed as follows:&lt;br /&gt;
&lt;br /&gt;
The following rules apply when a process request is made:&lt;br /&gt;
* If record is already being processed the request is just ignored&lt;br /&gt;
* record support can specify that links to particular fields not cause processing.&lt;br /&gt;
** Where should this be specified?  In the Database Definition, the record instance, or both.&lt;br /&gt;
** If a process request is allowed, should it be done regardless of the scan mechanism, i.e. the record does not have to be passive?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Mutual Exclusion =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
V3 implemented lock sets, i.e. when a record was being processed it and all records linked via database links were locked.&lt;br /&gt;
&lt;br /&gt;
Lock sets solved two Mutual Exclusion problems:&lt;br /&gt;
* V3 allowed dbProcess to be called recursively.&lt;br /&gt;
** process passive database links and forward links were implemented via recursive calls to DbProcess&lt;br /&gt;
** Lock sets prevented deadly embrace problems for circular links.&lt;br /&gt;
* No puts could be done to an record in a lock set while record processing is active.&lt;br /&gt;
** For synchronous records this guarantees that no fields are modified except by record processing itself.&lt;br /&gt;
** For asynchronous records this guarantee is not valid.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
V4 does not call dbProcess recursively. Instead a process request is queued.&lt;br /&gt;
The request fails if either of the following is true:&lt;br /&gt;
* The record is active.&lt;br /&gt;
* The record is already queued.&lt;br /&gt;
&lt;br /&gt;
dbProcess itself manages the queue , which is FIFO.&lt;br /&gt;
When record support returns the first entry in the queue is processed.&lt;br /&gt;
In addition if link or struct support completes before the queue&lt;br /&gt;
is empty, a request to process the record containing the link/struct will&lt;br /&gt;
be added to the same queue.&lt;br /&gt;
Thus if a set of synchronous records are processed they will complete processing&lt;br /&gt;
without any context switch.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; What about periodically scanned records? Needs thought.&lt;br /&gt;
&lt;br /&gt;
This leaves the question of what should be done about mutual exclusion.&lt;br /&gt;
&lt;br /&gt;
For V4 there will be two locks associated with the IOC database:&lt;br /&gt;
1) a global lock, and 2) A per record instance lock.&lt;br /&gt;
&lt;br /&gt;
The global lock must be taken&lt;br /&gt;
whenever the structure of the database is modified. Examples are&lt;br /&gt;
1) adding new record types, 2) adding new record instances, and 3) modifying&lt;br /&gt;
database links. Global locks are not discussed further in this document.&lt;br /&gt;
&lt;br /&gt;
Each record instance has an associated lock.&lt;br /&gt;
When dbProcess is called it takes the lock.&lt;br /&gt;
Before it returns it unlocks.&lt;br /&gt;
Thus record support does not need to lock or unlock.&lt;br /&gt;
&lt;br /&gt;
Other code that needs access to fields of a record instance must&lt;br /&gt;
lock before accessing any fields and unlock after all accesses are complete.&lt;br /&gt;
&lt;br /&gt;
This leaves the problem of how to access fields from two different record&lt;br /&gt;
instances simultaneously. For example code that implements database&lt;br /&gt;
access needs such access. Code that needs such access must call dbLockLink before accessing the linked record and dbUnlockLink after access.&lt;br /&gt;
&lt;br /&gt;
dbLockLink is implemented as follows:&lt;br /&gt;
* Each Record instances has a unique ordinal number&lt;br /&gt;
* Assume Record X has a link to record Y&lt;br /&gt;
* If the ordinal number of X is less than that of Y&lt;br /&gt;
** Just call dbLock for record Y&lt;br /&gt;
* If the ordinal numnber of X is greater than that of Y&lt;br /&gt;
** call dbUnlock for X&lt;br /&gt;
** call dbLock for Y&lt;br /&gt;
** call dbLock for X&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Posting Modifications =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The document &amp;quot;V4 Design: dbdIterfaces&amp;quot; provides a design that allows&lt;br /&gt;
database access to handle all posting on monitors without requiring&lt;br /&gt;
any help from the code that modifies database fields.&lt;br /&gt;
It can do this because fields can be modified only via an&lt;br /&gt;
interface implemented by database access.&lt;br /&gt;
&lt;br /&gt;
dbProcess posts monitors when:&lt;br /&gt;
* When record support returns processActive.&lt;br /&gt;
* When it finishes record processing.&lt;br /&gt;
&lt;br /&gt;
How to implement monitors must be decided.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Alarm Processing =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; Will V4 alarm handling be different than V3? If so this section&lt;br /&gt;
may be meaningless.&lt;br /&gt;
&lt;br /&gt;
The V4 semantics for status and severity have the following goals:&lt;br /&gt;
* alarmSeverity has the same values as for V3&lt;br /&gt;
* alarmStatus is a string&lt;br /&gt;
* a record starts processing with alarmSeverity = &amp;quot;NO_ALARM&amp;quot; and status empty.&lt;br /&gt;
* status will ONLY be posted if it has changed since the last time it was posted.&lt;br /&gt;
* alarmSeverity will ONLY be posted if it has changed since the last time it was posted&lt;br /&gt;
&lt;br /&gt;
The semantics, which are implemented by recordCommon, are:&lt;br /&gt;
&lt;br /&gt;
* When recordCommon is called with processStart&lt;br /&gt;
** A private variable newSeverity is set to NO_ALARM&lt;br /&gt;
** A private variable prevSeverity is set to alarmSeverity&lt;br /&gt;
* When recordCommon completes its part of record processing&lt;br /&gt;
** If newSeverity is NO_ALARM and prevSeverity has a different value&lt;br /&gt;
*** alarmSeverity is set to NO_ALARM&lt;br /&gt;
*** alarmStatus is set to empty&lt;br /&gt;
&lt;br /&gt;
* When the recordCommon.setSeverity(sevr,status) is called&lt;br /&gt;
** If sevr is less than or equal to newSeverity nothing is done&lt;br /&gt;
** else&lt;br /&gt;
*** alarmSeverity is set to sevr&lt;br /&gt;
*** alarmStatus is set to status&lt;br /&gt;
*** newSeverity is set to sevr&lt;br /&gt;
&lt;br /&gt;
NOTE: alarmStatus and alarmSeverity are written by the normal method.&lt;br /&gt;
This means that their values will be posted.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Channel Access/ Database Access field types =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This section discusses how IOC database fields are accessed by channel access&lt;br /&gt;
or via database links.&lt;br /&gt;
&lt;br /&gt;
For the initial V4 implementation only the following types of data&lt;br /&gt;
will be accessable.&lt;br /&gt;
&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* enum&lt;br /&gt;
* one dimensional array of primitive or string or struct&lt;br /&gt;
* struct with fields of following types:&lt;br /&gt;
** primitive&lt;br /&gt;
** string&lt;br /&gt;
** enum&lt;br /&gt;
** struct (use recursion for allowed types)&lt;br /&gt;
** one dimensional array of primitive or string or struct&lt;br /&gt;
&lt;br /&gt;
The dbdInterfaces document defines database field types.&lt;br /&gt;
It also defines a subset called basic types, which consists&lt;br /&gt;
of primitive types, string, array, and structure.&lt;br /&gt;
For external access only basic types can be accessed.&lt;br /&gt;
This means that structures and arrays that do not consist of basic types&lt;br /&gt;
are not accessablevia clannelAccess. For example a DbfLink is&lt;br /&gt;
not accessable via channel access as a DbfLink.&lt;br /&gt;
&lt;br /&gt;
Non basic fields will only be available via some combination of basic types.&lt;br /&gt;
&lt;br /&gt;
For example a DbfLink field will appear as a string.&lt;br /&gt;
If a Database Definition is&lt;br /&gt;
&lt;br /&gt;
     struct(calcInpLink) {&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(link,link)&lt;br /&gt;
         field(value,float64)&lt;br /&gt;
     };&lt;br /&gt;
     &lt;br /&gt;
     record(xxx) {&lt;br /&gt;
         field(link,link)&lt;br /&gt;
         field(value,float64)&lt;br /&gt;
     ...&lt;br /&gt;
         field(inp,array(struct(calcInpLink)[]))&lt;br /&gt;
     ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
If a client attaches to &lt;br /&gt;
     record.field(link)&lt;br /&gt;
The data will be appear in the form:&lt;br /&gt;
     choice(choiceName) SupportStruct(pvname= ,;...)&lt;br /&gt;
where &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; is the name of the link support, &amp;lt;tt&amp;gt;SupportStruct&amp;lt;/tt&amp;gt; is the name of the support struct asociated with the support, and the arguments are the values for the support structure.&lt;br /&gt;
&lt;br /&gt;
Then if a client specifies the process variable:&lt;br /&gt;
     record.field(inp[1].link)&lt;br /&gt;
Then it connects to the link field of the second calcInpLink of field inp.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== primitive types ==&lt;br /&gt;
&lt;br /&gt;
This includes DbfBool, DbfOctet, DbfInt16, ... , DbfFloat64.&lt;br /&gt;
These do not present any problems. The scalar value is transfered.&lt;br /&gt;
&lt;br /&gt;
== string ==&lt;br /&gt;
&lt;br /&gt;
A string is just a UTF_8 encoded character string&lt;br /&gt;
&lt;br /&gt;
== DbfMenu  and DbfEnum ==&lt;br /&gt;
&lt;br /&gt;
Handled as an enum&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfLink ==&lt;br /&gt;
&lt;br /&gt;
Both of these have the following:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; A string that selects the link  support.&lt;br /&gt;
* &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt; Each support has an associated struct for configuration.&lt;br /&gt;
&lt;br /&gt;
How should these be made available? Perhaps:&lt;br /&gt;
&lt;br /&gt;
The field appears as a string with the following syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;choiceName(structAssignmentList)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where structAssignmentList has the same syntax as defined in &amp;quot;V4 DB Record Instance Syntax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== timeStamp ==&lt;br /&gt;
&lt;br /&gt;
This is just transfered like a struct with two fields:&lt;br /&gt;
* int64 secondsSinceEpoch&lt;br /&gt;
* int32 nanoSeconds&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== struct ==&lt;br /&gt;
&lt;br /&gt;
The database definition syntax allows a struct to be composed of fields&lt;br /&gt;
of any DbfType.&lt;br /&gt;
Database access, however, will only allow access to structs with fields&lt;br /&gt;
of the following types:&lt;br /&gt;
* primitive - DbfBool,...,DbfFloat64&lt;br /&gt;
* DbfString&lt;br /&gt;
* DbfArray of primitive type or string&lt;br /&gt;
* DbfStruct - As long as its fields are valid types&lt;br /&gt;
&lt;br /&gt;
The individual fields can be accessed directly so this discussion&lt;br /&gt;
only involves access to the entire structure.&lt;br /&gt;
&lt;br /&gt;
Access will only be available to clients that have knowledge of&lt;br /&gt;
fields within the structure. For channel access clients this means that&lt;br /&gt;
they provide a propertyCatalog that has some subset of the fields in the structure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== array ==&lt;br /&gt;
&lt;br /&gt;
Arrays of the following types are accessable:&lt;br /&gt;
* primitive - DbfBool,...,DbfFloat64&lt;br /&gt;
* DbfString&lt;br /&gt;
* DbfStruct - As long as its fields are valid types&lt;br /&gt;
&lt;br /&gt;
Note that arrays of structs are not accessable in the early V4 releases.&lt;br /&gt;
&lt;br /&gt;
Arrays still need lots more discussion!!!&lt;br /&gt;
The database definition syntax allow an array to be any of the basic types, i.e. DbfBool,...,DbfFloat64, DbfString, DbfArray, DbfStruct.&lt;br /&gt;
&lt;br /&gt;
For the initial V4 version, database access only allows access to arrays of the following types.&lt;br /&gt;
* primitive - DbfBool,...,DbfFloat64&lt;br /&gt;
* DbfString&lt;br /&gt;
* ???? What else&lt;br /&gt;
&lt;br /&gt;
An individual element of an array of type DbfStruct can be accessed&lt;br /&gt;
directly if it satisfies the criteria for accessing a DbfStruct.&lt;br /&gt;
&lt;br /&gt;
Question: Should database Access be implemented so that record/link support can transfer an array in segments. Examples:&lt;br /&gt;
* If the array is a circular buffer, it is presented in two segements&lt;br /&gt;
* If the array is stored in hardware, e.g. a transient recorder, the array can be read from the hardware and passed to the client in segments.&lt;br /&gt;
&lt;br /&gt;
If an array is available only in segments then can we&lt;br /&gt;
prevent two clients from trying to access the same array simultaneously?&lt;br /&gt;
&lt;br /&gt;
Perhaps this is a problem that must be solved by an application:&lt;br /&gt;
* runControl records are one solution&lt;br /&gt;
* Other solutions can be envisioned&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MDArray ==&lt;br /&gt;
&lt;br /&gt;
Not implemented if the early V4 releases.&lt;br /&gt;
&lt;br /&gt;
== Associated Data ==&lt;br /&gt;
&lt;br /&gt;
The typical example is a client that asks for timeStamp, severity, status,&lt;br /&gt;
and data.&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=573</id>
		<title>V4 Link Support Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=573"/>
		<updated>2005-10-26T18:17:33Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: added discussion about analog conversion and special support for output records&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Link Support Tutorial Oct 26 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
The V4 link support is a replacement for V3 &lt;br /&gt;
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK&lt;br /&gt;
# device DBD definition and device support&lt;br /&gt;
# driver DBD definition and driver support&lt;br /&gt;
&lt;br /&gt;
The link support model is:&lt;br /&gt;
* For each link, record support defines a list of interfaces it can use for communicating with link support&lt;br /&gt;
* Link support defines the set of interfaces it implements&lt;br /&gt;
&lt;br /&gt;
Link support has no knowledge of what record types are using it&lt;br /&gt;
and record support has no knowledge about link support other than the&lt;br /&gt;
interface it is using.&lt;br /&gt;
&lt;br /&gt;
EPICS base defines a standard set of interfaces for link support.&lt;br /&gt;
The intention is that the set includes enough functionality such that&lt;br /&gt;
most link support can be implemented via just these interfaces.&lt;br /&gt;
&lt;br /&gt;
The interfaces support all the functionality needed by Channel/Database access&lt;br /&gt;
and by the generic EPICS device support supplied by asynDriver.&lt;br /&gt;
Since asynDriver is intended as a framework for interfacing to most hardware,&lt;br /&gt;
this means that the interfaces supplied and used by base allows support&lt;br /&gt;
for most hardware. The support can communicate with the hardware&lt;br /&gt;
however it wants but must implement some set of the interfaces defined&lt;br /&gt;
by base.&lt;br /&gt;
&lt;br /&gt;
This document gives a brief overview of the V4 link support model.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Database Definitions For Links =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section first reviews the DBD syntax related to link definitions.&lt;br /&gt;
It then gives a brief description of link related definitions in dbCommon.dbd&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
A record link has the syntax:&lt;br /&gt;
     link(linkDirection,interface(interfaceName,...))&lt;br /&gt;
A link itself has the syntax:&lt;br /&gt;
     link(linkDirection,choiceName,dataStructName,interface(interfaceName,...))&lt;br /&gt;
A record instance link definition has the syntax:&lt;br /&gt;
     field = { choice(interfaceName) {structAssignmentList}}&lt;br /&gt;
      or&lt;br /&gt;
     field = { choice(interfaceName) dataStructName {structAssignmentList} }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;linkDirection&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be one of &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. Compatible checks are made to match the interface with a field.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interface&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is a list of the interfaces that the record support understands or that link support implements.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of an interface via which record support communicates with link support.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools prompt the user to assign values to the structure.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choice&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Selects a link with &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; = &amp;lt;tt&amp;gt;choice&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A record instance link definition selects a link as follows:&lt;br /&gt;
* The linkDirections must be compatible&lt;br /&gt;
** Except for inout the record link and link directions must be the same&lt;br /&gt;
** If record link specifies inout the link can specify either in or out or inout&lt;br /&gt;
* The interfaceName specified by the record instance must be in the record link interface list and in the link interface list.&lt;br /&gt;
* The dataStructName specified in the record instance must match the dataStructName in the link definition.&lt;br /&gt;
&lt;br /&gt;
Assume the following definitions:&lt;br /&gt;
     record(AiRecord) {&lt;br /&gt;
         ...&lt;br /&gt;
         field(in,link(in,interface(LinkInt64,LinkFloat64)))&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvMonitorLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvInputLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     link(in,monitorLink,PvMonitorLink,interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLink,PvInputLink,interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     ...&lt;br /&gt;
     struct VME{&lt;br /&gt;
         field(a16,int16) &lt;br /&gt;
         field(a32,int32)&lt;br /&gt;
         field(channel,int16)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     link(in,someVmeADC,VME, interface(LinkInt32))&lt;br /&gt;
&lt;br /&gt;
The first example instance definition selects a monitor link. It selects interface LinkInt32, which means the support will provide a &amp;quot;raw&amp;quot; value that the&lt;br /&gt;
record support will convert to engineering units.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {monitorLink(LinkInt32) &lt;br /&gt;
                   PvMonitorLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                         process = true;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The next example selects a channel access input link. It selects interface&lt;br /&gt;
LinkFloat64, which means the support will provide a value in engineering units.&lt;br /&gt;
It asks that the linked record be processed and that the link not complete&lt;br /&gt;
until the linked record completes processing.&lt;br /&gt;
     AiRecord aiInputExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {inputLink(LinkFloat64) &lt;br /&gt;
                   PvInputLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                        process = true;&lt;br /&gt;
                        wait = true;&lt;br /&gt;
                        timeout = 1.0;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The last example selects support for a VME Analog to Digital device.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {someVmeADC(LinkInt32) VME {a16 = 0xc000; channel = 1} }&lt;br /&gt;
&lt;br /&gt;
== Standard Definitions For Channel/Database Access ==&lt;br /&gt;
&lt;br /&gt;
These are the database definitions defined in dbCommon are used by&lt;br /&gt;
the base supplied support for Channel/Database access.&lt;br /&gt;
This support registers each choiceName in the link definitions.&lt;br /&gt;
The complete set of data structure and link definitions are defined&lt;br /&gt;
in &amp;quot;V4 DB RecordCommon&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* monitor&lt;br /&gt;
* input&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For monitor, input, and output the following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
&lt;br /&gt;
These are definitions that are used by the standard EPICS device support&lt;br /&gt;
for asynDriver. Since asynDriver is a generic way of interfacing arbitrary&lt;br /&gt;
hardware support, this is a generic way of attaching links in records to&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLink) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link definitions ===&lt;br /&gt;
&lt;br /&gt;
     link(inout,asynInt32,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Average,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Monitor,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(inout,asynFloat64,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Average,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Monitor,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynDigitalMonitor,AsynLink,interface(AsynDigital))&lt;br /&gt;
     link(inout,asynDigital,AsynLink,interface(AsynDigital)))&lt;br /&gt;
     link(inout,asynInt32Array,AsynLink,interface(LinkArrayInt32)))&lt;br /&gt;
     link(inout,asynFloat64Array,AsynLink,interface(LinkArrayFloat64)))&lt;br /&gt;
     link(inout,asynOctet,AsynLink,interface(AsynOctet)))&lt;br /&gt;
&lt;br /&gt;
This is the set of definitions for the standard EPICS device support implemented&lt;br /&gt;
by asynDriver. Although, at least for the first few V4 releases,&lt;br /&gt;
asynDriver will not be part of base, they are shown here because the&lt;br /&gt;
LinkInt32,... interface definitions are defined as part of base.&lt;br /&gt;
Again it is expected that almost all hardware support be created by&lt;br /&gt;
implementing a combination of these link interface definitions or&lt;br /&gt;
the interfaces implemented by Channel/Database access link support.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
An arbitrary number of Link Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
Other link support can also be supplied.&lt;br /&gt;
Whenever possible support should implement the standard interfaces&lt;br /&gt;
supplied by EPICS base, since these are the interfaces that the record types&lt;br /&gt;
supplied with base know how to use.&lt;br /&gt;
&lt;br /&gt;
Soft support should try to implement the same interfaces implemented by&lt;br /&gt;
the Channel/Database access support supplied with base. The support&lt;br /&gt;
can, of course, define data structures for it's own use.&lt;br /&gt;
Implementing these interfaces means that the support will work for&lt;br /&gt;
the same set of record links as the Channel/Database access support.&lt;br /&gt;
&lt;br /&gt;
Hardware support should, if possible, also implement the same interfaces&lt;br /&gt;
implemented by the Channel/Database access support.&lt;br /&gt;
Message based support may also have to implement the AsynOctet interface&lt;br /&gt;
but this interface is only used by a few record types.&lt;br /&gt;
&lt;br /&gt;
This section describes the interfaces implemented by all link support&lt;br /&gt;
and then the standard interfaces used by the records supplied with base.&lt;br /&gt;
&lt;br /&gt;
The syntax is similar to Java syntax since it is more concise than C++.&lt;br /&gt;
It can easily be translated to C++ syntax. For example the&lt;br /&gt;
definition:&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int16 data);&lt;br /&gt;
         boolean getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class LinkInt16 {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual LinkResult get(Callback &amp;amp;callback, int16_t &amp;amp;data) = 0;&lt;br /&gt;
         virtual LinkResult put(Callback &amp;amp;callback, int16_t data) = 0;&lt;br /&gt;
         virtual bool getBounds(int16_t &amp;amp;low, int16_t &amp;amp;high) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Link and MonitorLink ==&lt;br /&gt;
&lt;br /&gt;
All support &amp;lt;b&amp;gt;must&amp;lt;/b&amp;gt; register interface &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt;&lt;br /&gt;
and if it supports monitors interface &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE: arguments and return types ignored for now&amp;lt;/b&amp;gt;&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; is an interface that is implemented by link support that&lt;br /&gt;
supports monitors. An example is support for hardware interrupts.&lt;br /&gt;
The &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally record support does not need to call any of the Link &lt;br /&gt;
or MonitorLink methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call destroy before modifying the link&lt;br /&gt;
and initialize and connect after the link is modified.&lt;br /&gt;
&lt;br /&gt;
Note that neither Link or MonitorLink is listed in the &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; database&lt;br /&gt;
definition since they are generic.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
These are the definitions used by the Channel/Database access support&lt;br /&gt;
supplied with base. It is also used by the standard EPICS support from asyn.&lt;br /&gt;
&lt;br /&gt;
     enum LinkResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface LinkProcess {&lt;br /&gt;
         LinkResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
&lt;br /&gt;
     interface LinkOctet {&lt;br /&gt;
         LinkResult get(Callback callback, Octet data);&lt;br /&gt;
         LinkResult put(Callback callback, octet data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkResult get(Callback callback, octet[] data);&lt;br /&gt;
         LinkResult put(Callback callback, octet[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;GENERIC QUESTION&amp;lt;/b&amp;gt; The data is passed as primitive or arrays of&lt;br /&gt;
primitive types. Should &amp;lt;tt&amp;gt;Dbf&amp;lt;/tt&amp;gt; interfaces be used? Needs thought.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== asynDigital Support ==&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkResult write(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          LinkResult read(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,Boolean data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,boolean[] data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int16 data);&lt;br /&gt;
         boolean getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,int16[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int16[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         boolean getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,int32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,Int64 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int64 data);&lt;br /&gt;
         boolean getBounds(Int64 low, Int64 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,int64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,Float32 data);&lt;br /&gt;
         LinkResult put(Callback callback,float32 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,float32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,Float64 data);&lt;br /&gt;
         LinkResult put(Callback callback,float64 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,float64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkResult get(Callback callback,string data);&lt;br /&gt;
         LinkResult put(Callback callback,string data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkResult get(Callback callback,string[] data);&lt;br /&gt;
         LinkResult put(Callback callback,string[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Example - VME ADC support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
Assume the VME and link definitions given in the examples at the beginning&lt;br /&gt;
of this document.&lt;br /&gt;
&lt;br /&gt;
The following is presented with Java syntax.&lt;br /&gt;
It assumes that there is VME support of the form&lt;br /&gt;
&lt;br /&gt;
     public class vme {&lt;br /&gt;
         static public short getShort(long addr);&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The link support would be something like:&lt;br /&gt;
&lt;br /&gt;
     class AdcSupport implements Link LinkInt32 {&lt;br /&gt;
     AdcSupport(VME fromFactory)&lt;br /&gt;
     {&lt;br /&gt;
         addr = fromFactory;&lt;br /&gt;
         connected = false;&lt;br /&gt;
         //  from the VME initialize vmeaddr and channel&lt;br /&gt;
         // details left to your imagination&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Link methods&lt;br /&gt;
     void report(int16_t level)&lt;br /&gt;
     {&lt;br /&gt;
         printf(&amp;quot;AdcSupport a16 %x channel %d\n&amp;quot;,a16,channel);&lt;br /&gt;
     }&lt;br /&gt;
     void cancel() {} // nothing to do&lt;br /&gt;
     void destroy() {} //nothing to do&lt;br /&gt;
     void initialize()&lt;br /&gt;
     {&lt;br /&gt;
         // make sure we can access a16&lt;br /&gt;
     }&lt;br /&gt;
     void connect() {connected = true}&lt;br /&gt;
     void disconnect() {connected = false}&lt;br /&gt;
     &lt;br /&gt;
     // LinkInt32 methods&lt;br /&gt;
     LinkResult get(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         data = (Int)VME.getShort(vmeaddr);&lt;br /&gt;
         return linkDone;&lt;br /&gt;
     }&lt;br /&gt;
     LinkResult put(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         throw CantWriteAdc;&lt;br /&gt;
     }&lt;br /&gt;
     void getBounds(Int low, Int high) &lt;br /&gt;
     {&lt;br /&gt;
         // assume 16 bit unipolor adc&lt;br /&gt;
         low = 0; high = 0xffff;&lt;br /&gt;
     }&lt;br /&gt;
     private:&lt;br /&gt;
         VME addr;&lt;br /&gt;
         int vmeaddr;&lt;br /&gt;
         int channel;&lt;br /&gt;
         boolean connected;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Discussion of link support interfaces =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The link definitions: record link, link, record instance links,&lt;br /&gt;
and the link interfaces are designed to support channel/database links,&lt;br /&gt;
links to hardware support, and links to other types of support.&lt;br /&gt;
&lt;br /&gt;
The following are two important requirements:&lt;br /&gt;
* analog I/O&lt;br /&gt;
** link support can return raw value. Support must convert to engineering units.&lt;br /&gt;
** link support can return engineering units&lt;br /&gt;
* output records&lt;br /&gt;
** Can link support provide initial value?&lt;br /&gt;
** What if multiple sources can change linked output?&lt;br /&gt;
&lt;br /&gt;
Lets consider each of these separately.&lt;br /&gt;
== Analog I/O ==&lt;br /&gt;
In V3 the aiRecord and aoRecords are responsible for conversion between&lt;br /&gt;
raw values and engineering units. Raw values are 32 bit integers. Device&lt;br /&gt;
support is responsible for setting the slope and intercept fields of the record.&lt;br /&gt;
Record support takes care of the actual conversions.&lt;br /&gt;
Device support can tell record support that it set the engineering units&lt;br /&gt;
rather than a raw value by a different return value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE:&amp;lt;/b&amp;gt;Perhaps in V4 aiRecord should be separated into two records,&lt;br /&gt;
e.g. a record that always uses float values and an ADC record which handles&lt;br /&gt;
raw values. Another possibility is special link support that provides&lt;br /&gt;
floating values to the record support and links to the actual hardware support.&lt;br /&gt;
For this discussion it is assummed that aiRecord and aoRecord are still&lt;br /&gt;
responsible for conversions since most of the discussion is&lt;br /&gt;
independent of how the record support is structured.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For V4 the following is done:&lt;br /&gt;
&lt;br /&gt;
aiRecord and aoRecord both have the following fields:&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;Raw&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(eguf,float64)&lt;br /&gt;
         field(egul,float64)&lt;br /&gt;
         field(slope,float64)&lt;br /&gt;
         field(intercept,float64)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     ...&lt;br /&gt;
     field(convert, menu(menuConvert))&lt;br /&gt;
     field(linearConvert, struct(LinearConvert))&lt;br /&gt;
     field(convertTable,string);&lt;br /&gt;
     field(units, string)&lt;br /&gt;
&lt;br /&gt;
The link field for aiRecord is&lt;br /&gt;
     field(in,link(in,interface( LinkInt32, LinkFloat64)))&lt;br /&gt;
&lt;br /&gt;
The link field for aoRecord is&lt;br /&gt;
     field(out,link(out,interface( LinkInt32, LinkFloat64)))&lt;br /&gt;
&lt;br /&gt;
When a record instance is defined the link specifies the interface to use.&lt;br /&gt;
If the interface is:&lt;br /&gt;
* &amp;lt;tt&amp;gt;LinkInt32&amp;lt;/tt&amp;gt; - Then the link support supplies raw values&lt;br /&gt;
* &amp;lt;tt&amp;gt;LinkFloat64&amp;lt;/tt&amp;gt; - Then the link support supplies engineering units&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;LinkInt32&amp;lt;/tt&amp;gt; is defined as:&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         void getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
Thus link support is responsible for returning the ADC bounds.&lt;br /&gt;
For example support for a 16 bit unipolar ADC would set low=0, high=65535,&lt;br /&gt;
and return true.&lt;br /&gt;
If link support can not determine the bounds then getBounds returns false.&lt;br /&gt;
&lt;br /&gt;
If the link interface is LinkFloat64 then record support does no conversion.&lt;br /&gt;
Thus the following only applys if the interface is LinkInt32.&lt;br /&gt;
&lt;br /&gt;
Record support handles conversions as follows:&lt;br /&gt;
* Raw - The value obtained from the link support is converted to a double.&lt;br /&gt;
* Linear&lt;br /&gt;
** If link support returned the bounds record support computes slope and intercept&lt;br /&gt;
** otherwise it uses the slope and intercept from instance definition&lt;br /&gt;
* Table - The interface implementation for convertTable is located and used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE:&amp;lt;/b&amp;gt;The interface implemented by breakpoint tables must be defined.&lt;br /&gt;
It will support the same semantics as the V3 breakpoint tables.&lt;br /&gt;
&lt;br /&gt;
== Output Records ==&lt;br /&gt;
&lt;br /&gt;
The following are two features that link support should implement&lt;br /&gt;
whenever possible:&lt;br /&gt;
# When a record is initalized provide the current value of the output&lt;br /&gt;
# If something else modifies the actual output value in the record&lt;br /&gt;
&lt;br /&gt;
The first feature is especially desirable when an IOC is rebooted.&lt;br /&gt;
If a hardware output can survive a reboot this is a very desirable feature.&lt;br /&gt;
If the output is to a field bus, a PLC, or to a record in another IOC&lt;br /&gt;
it is often possible for the link support to determine the current value.&lt;br /&gt;
&lt;br /&gt;
The second feature is something that was often asked for in V3 but&lt;br /&gt;
only implemented&lt;br /&gt;
for some special cases. This is especially desirable when the output is&lt;br /&gt;
connected to a system that can have multiple sources of control.&lt;br /&gt;
Examples are GPIB devices with front pannel controls, PLC systems that&lt;br /&gt;
have manual controls or non-epics network access.&lt;br /&gt;
&lt;br /&gt;
For V3 some of the hardware , but none of the soft,&lt;br /&gt;
support implemented the first feature but by&lt;br /&gt;
modifying actual fields in the record. V3 did not implement the second&lt;br /&gt;
feature. Some special device support, not part of base, was implemented&lt;br /&gt;
to support this feature.&lt;br /&gt;
&lt;br /&gt;
For V4 these features are supported as follows:&lt;br /&gt;
&lt;br /&gt;
=== record initialization ===&lt;br /&gt;
&lt;br /&gt;
The link support implements an interface that has a put and a get method.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         boolean getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
If the link support can support readbacks then it implements get&lt;br /&gt;
and returns linkDone. If it does not support readbacks&lt;br /&gt;
then it implements get by just returning linkNoop.&lt;br /&gt;
&lt;br /&gt;
=== monitors for outputs ===&lt;br /&gt;
&lt;br /&gt;
If output link support can detect when something besides the link support&lt;br /&gt;
itself modifies the output then it implements interface &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt;&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
At initialization record support looks for this interface and if found&lt;br /&gt;
it calls &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt;. The link support calls the callback whenever&lt;br /&gt;
it detects a change in the output that it did not cause. Record support&lt;br /&gt;
causes itself to be processed without making a new call to the&lt;br /&gt;
link support.&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=568</id>
		<title>V4 Link Support Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=568"/>
		<updated>2005-10-25T19:29:24Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Link Support Tutorial Oct 25 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
The V4 link support is a replacement for V3 &lt;br /&gt;
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK&lt;br /&gt;
# device DBD definition and device support&lt;br /&gt;
# driver DBD definition and driver support&lt;br /&gt;
&lt;br /&gt;
The link support model is:&lt;br /&gt;
* For each link, record support defines a list of interfaces it can use for communicating with link support&lt;br /&gt;
* Link support defines the set of interfaces it implements&lt;br /&gt;
&lt;br /&gt;
Link support has no knowledge of what record types are using it&lt;br /&gt;
and record support has no knowledge about link support other than the&lt;br /&gt;
interface it is using.&lt;br /&gt;
&lt;br /&gt;
EPICS base defines a standard set of interfaces for link support.&lt;br /&gt;
The intention is that the set includes enough functionality such that&lt;br /&gt;
most link support can be implemented via just these interfaces.&lt;br /&gt;
&lt;br /&gt;
The interfaces support all the functionality needed by Channel/Database access&lt;br /&gt;
and by the generic EPICS device support supplied by asynDriver.&lt;br /&gt;
Since asynDriver is intended as a framework for interfacing to most hardware,&lt;br /&gt;
this means that the interfaces supplied and used by base allows support&lt;br /&gt;
for most hardware. The support can communicate with the hardware&lt;br /&gt;
however it wants but must implement some set of the interfaces defined&lt;br /&gt;
by base.&lt;br /&gt;
&lt;br /&gt;
This document gives a brief overview of the V4 link support model.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Database Definitions For Links =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section first reviews the DBD syntax related to link definitions.&lt;br /&gt;
It then gives a brief description of link related definitions in dbCommon.dbd&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
A record link has the syntax:&lt;br /&gt;
     link(linkDirection,interface(interfaceName,...))&lt;br /&gt;
A link itself has the syntax:&lt;br /&gt;
     link(linkDirection,choiceName,dataStructName,interface(interfaceName,...))&lt;br /&gt;
A record instance link definition has the syntax:&lt;br /&gt;
     field = { choice(interfaceName) {structAssignmentList}}&lt;br /&gt;
      or&lt;br /&gt;
     field = { choice(interfaceName) dataStructName {structAssignmentList} }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;linkDirection&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be one of &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. Compatible checks are made to match the interface with a field.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interface&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is a list of the interfaces that the record support understands or that link support implements.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of an interface via which record support communicates with link support.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools prompt the user to assign values to the structure.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choice&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Selects a link with &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; = &amp;lt;tt&amp;gt;choice&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A record instance link definition selects a link as follows:&lt;br /&gt;
* The linkDirections must be compatible&lt;br /&gt;
** Except for inout the record link and link directions must be the same&lt;br /&gt;
** If record link specifies inout the link can specify either in or out or inout&lt;br /&gt;
* The interfaceName specified by the record instance must be in the record link interface list and in the link interface list.&lt;br /&gt;
* The dataStructName specified in the record instance must match the dataStructName in the link definition.&lt;br /&gt;
&lt;br /&gt;
Assume the following definitions:&lt;br /&gt;
     record(AiRecord) {&lt;br /&gt;
         ...&lt;br /&gt;
         field(in,link(in,interface(LinkInt64,LinkFloat64)))&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvMonitorLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvInputLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     link(in,monitorLink,PvMonitorLink,interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLink,PvInputLink,interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     ...&lt;br /&gt;
     struct VME{&lt;br /&gt;
         field(a16,int16) &lt;br /&gt;
         field(a32,int32)&lt;br /&gt;
         field(channel,int16)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     link(in,someVmeADC,VME, interface(LinkInt32))&lt;br /&gt;
&lt;br /&gt;
The first example instance definition selects a monitor link. It selects interface LinkInt32, which means the support will provide a &amp;quot;raw&amp;quot; value that the&lt;br /&gt;
record support will convert to engineering units.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {monitorLink(LinkInt32) &lt;br /&gt;
                   PvMonitorLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                         process = true;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The next example selects a channel access input link. It selects interface&lt;br /&gt;
LinkFloat64, which means the support will provide a value in engineering units.&lt;br /&gt;
It asks that the linked record be processed and that the link not complete&lt;br /&gt;
until the linked record completes processing.&lt;br /&gt;
     AiRecord aiInputExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {inputLink(LinkFloat64) &lt;br /&gt;
                   PvInputLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                        process = true;&lt;br /&gt;
                        wait = true;&lt;br /&gt;
                        timeout = 1.0;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The last example selects support for a VME Analog to Digital device.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {someVmeADC(LinkInt32) VME {a16 = 0xc000; channel = 1} }&lt;br /&gt;
&lt;br /&gt;
== Standard Definitions For Channel/Database Access ==&lt;br /&gt;
&lt;br /&gt;
These are the database definitions defined in dbCommon are used by&lt;br /&gt;
the base supplied support for Channel/Database access.&lt;br /&gt;
This support registers each choiceName in the link definitions.&lt;br /&gt;
The complete set of data structure and link definitions are defined&lt;br /&gt;
in &amp;quot;V4 DB RecordCommon&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* monitor&lt;br /&gt;
* input&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For monitor, input, and output the following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
&lt;br /&gt;
These are definitions that are used by the standard EPICS device support&lt;br /&gt;
for asynDriver. Since asynDriver is a generic way of interfacing arbitrary&lt;br /&gt;
hardware support, this is a generic way of attaching links in records to&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLink) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link definitions ===&lt;br /&gt;
&lt;br /&gt;
     link(inout,asynInt32,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Average,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Monitor,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(inout,asynFloat64,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Average,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Monitor,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynDigitalMonitor,AsynLink,interface(AsynDigital))&lt;br /&gt;
     link(inout,asynDigital,AsynLink,interface(AsynDigital)))&lt;br /&gt;
     link(inout,asynInt32Array,AsynLink,interface(LinkArrayInt32)))&lt;br /&gt;
     link(inout,asynFloat64Array,AsynLink,interface(LinkArrayFloat64)))&lt;br /&gt;
     link(inout,asynOctet,AsynLink,interface(AsynOctet)))&lt;br /&gt;
&lt;br /&gt;
This is the set of definitions for the standard EPICS device support implemented&lt;br /&gt;
by asynDriver. Although, at least for the first few V4 releases,&lt;br /&gt;
asynDriver will not be part of base, they are shown here because the&lt;br /&gt;
LinkInt32,... interface definitions are defined as part of base.&lt;br /&gt;
Again it is expected that almost all hardware support be created by&lt;br /&gt;
implementing a combination of these link interface definitions or&lt;br /&gt;
the interfaces implemented by Channel/Database access link support.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
An arbitrary number of Link Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
Other link support can also be supplied.&lt;br /&gt;
Whenever possible support should implement the standard interfaces&lt;br /&gt;
supplied by EPICS base, since these are the interfaces that the record types&lt;br /&gt;
supplied with base know how to use.&lt;br /&gt;
&lt;br /&gt;
Soft support should try to implement the same interfaces implemented by&lt;br /&gt;
the Channel/Database access support supplied with base. The support&lt;br /&gt;
can, of course, define data structures for it's own use.&lt;br /&gt;
Implementing these interfaces means that the support will work for&lt;br /&gt;
the same set of record links as the Channel/Database access support.&lt;br /&gt;
&lt;br /&gt;
Hardware support should, if possible, also implement the same interfaces&lt;br /&gt;
implemented by the Channel/Database access support.&lt;br /&gt;
Message based support may also have to implement the AsynOctet interface&lt;br /&gt;
but this interface is only used by a few record types.&lt;br /&gt;
&lt;br /&gt;
This section describes the interfaces implemented by all link support&lt;br /&gt;
and then the standard interfaces used by the records supplied with base.&lt;br /&gt;
&lt;br /&gt;
The syntax is similar to Java syntax since it is more concise than C++.&lt;br /&gt;
It can easily be translated to C++ syntax. For example the&lt;br /&gt;
definition:&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int16 data);&lt;br /&gt;
         void getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class LinkInt16 {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual LinkResult get(Callback &amp;amp;callback, int16_t &amp;amp;data) = 0;&lt;br /&gt;
         virtual LinkResult put(Callback &amp;amp;callback, int16_t data) = 0;&lt;br /&gt;
         virtual void getBounds(int16_t &amp;amp;low, int16_t &amp;amp;high) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Link and MonitorLink ==&lt;br /&gt;
&lt;br /&gt;
All support &amp;lt;b&amp;gt;must&amp;lt;/b&amp;gt; register interface &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt;&lt;br /&gt;
and if it supports monitors interface &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE: arguments and return types ignored for now&amp;lt;/b&amp;gt;&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; is an interface that is implemented by link support that&lt;br /&gt;
supports monitors. An example is support for hardware interrupts.&lt;br /&gt;
The &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally record support does not need to call any of the Link &lt;br /&gt;
or MonitorLink methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call destroy before modifying the link&lt;br /&gt;
and initialize and connect after the link is modified.&lt;br /&gt;
&lt;br /&gt;
Note that neither Link or MonitorLink is listed in the &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; database&lt;br /&gt;
definition since they are generic.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
These are the definitions used by the Channel/Database access support&lt;br /&gt;
supplied with base. It is also used by the standard EPICS support from asyn.&lt;br /&gt;
&lt;br /&gt;
     enum LinkResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface LinkProcess {&lt;br /&gt;
         LinkResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
&lt;br /&gt;
     interface LinkOctet {&lt;br /&gt;
         LinkResult get(Callback callback, Octet data);&lt;br /&gt;
         LinkResult put(Callback callback, octet data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkResult get(Callback callback, octet[] data);&lt;br /&gt;
         LinkResult put(Callback callback, octet[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;GENERIC QUESTION&amp;lt;/b&amp;gt; The data is passed as primitive or arrays of&lt;br /&gt;
primitive types. Should &amp;lt;tt&amp;gt;Dbf&amp;lt;/tt&amp;gt; interfaces be used? Needs thought.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== asynDigital Support ==&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkResult write(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          LinkResult read(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,Boolean data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,boolean[] data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int16 data);&lt;br /&gt;
         void getBounds(Int16 low, Int16 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,int16[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int16[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         void getBounds(Int32 low, Int32 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,int32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,Int64 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int64 data);&lt;br /&gt;
         void getBounds(Int64 low, Int64 high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,int64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,Float32 data);&lt;br /&gt;
         LinkResult put(Callback callback,float32 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,float32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,Float64 data);&lt;br /&gt;
         LinkResult put(Callback callback,float64 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,float64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkResult get(Callback callback,string data);&lt;br /&gt;
         LinkResult put(Callback callback,string data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkResult get(Callback callback,string[] data);&lt;br /&gt;
         LinkResult put(Callback callback,string[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Example - VME ADC support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
Assume the VME and link definitions given in the examples at the beginning&lt;br /&gt;
of this document.&lt;br /&gt;
&lt;br /&gt;
The following is presented with Java syntax.&lt;br /&gt;
It assumes that there is VME support of the form&lt;br /&gt;
&lt;br /&gt;
     public class vme {&lt;br /&gt;
         static public short getShort(long addr);&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The link support would be something like:&lt;br /&gt;
&lt;br /&gt;
     class AdcSupport implements Link LinkInt32 {&lt;br /&gt;
     AdcSupport(VME fromFactory)&lt;br /&gt;
     {&lt;br /&gt;
         addr = fromFactory;&lt;br /&gt;
         connected = false;&lt;br /&gt;
         //  from the VME initialize vmeaddr and channel&lt;br /&gt;
         // details left to your imagination&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Link methods&lt;br /&gt;
     void report(int16_t level)&lt;br /&gt;
     {&lt;br /&gt;
         printf(&amp;quot;AdcSupport a16 %x channel %d\n&amp;quot;,a16,channel);&lt;br /&gt;
     }&lt;br /&gt;
     void cancel() {} // nothing to do&lt;br /&gt;
     void destroy() {} //nothing to do&lt;br /&gt;
     void initialize()&lt;br /&gt;
     {&lt;br /&gt;
         // make sure we can access a16&lt;br /&gt;
     }&lt;br /&gt;
     void connect() {connected = true}&lt;br /&gt;
     void disconnect() {connected = false}&lt;br /&gt;
     &lt;br /&gt;
     // LinkInt32 methods&lt;br /&gt;
     LinkResult get(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         data = (Int)VME.getShort(vmeaddr);&lt;br /&gt;
         return linkDone;&lt;br /&gt;
     }&lt;br /&gt;
     LinkResult put(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         throw CantWriteAdc;&lt;br /&gt;
     }&lt;br /&gt;
     void getBounds(Int low, Int high) &lt;br /&gt;
     {&lt;br /&gt;
         // assume 16 bit unipolor adc&lt;br /&gt;
         low = 0; high = 0xffff;&lt;br /&gt;
     }&lt;br /&gt;
     private:&lt;br /&gt;
         VME addr;&lt;br /&gt;
         int vmeaddr;&lt;br /&gt;
         int channel;&lt;br /&gt;
         boolean connected;&lt;br /&gt;
     }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=575</id>
		<title>V4 DB RecordCommon</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=575"/>
		<updated>2005-10-25T19:07:05Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Standard Support October 25 2005 &lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes three base supplied components for EPICS V4 databases.&lt;br /&gt;
# menuStructBase.dbd - menu and struct definitions &lt;br /&gt;
# recordCommon.dbd - common fields for record definitions&lt;br /&gt;
# baseSupport.dbd - link definitions for base supplied support&lt;br /&gt;
&lt;br /&gt;
This document requires that the reader be familiar with:&lt;br /&gt;
# V3 iocCore&lt;br /&gt;
# V4 DBD Statement Syntax&lt;br /&gt;
# V4 DB Record Instance Syntax&lt;br /&gt;
&lt;br /&gt;
NOTE: This document is ahead of the two above V4 documents so it may use&lt;br /&gt;
slightly different syntax.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= menuStructBase.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Links ==&lt;br /&gt;
&lt;br /&gt;
     struct(PvProcessLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvMonitorLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean) &lt;br /&gt;
     }&lt;br /&gt;
     struct(PvInputLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvOutputLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== asynDriver Link ==&lt;br /&gt;
     struct(AsynLink) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Definitions for recordCommon ==&lt;br /&gt;
&lt;br /&gt;
     # menu definitions for recordCommon fields&lt;br /&gt;
     menu(menuPriority) {&lt;br /&gt;
         choice(menuPriorityLow, &amp;quot;Low&amp;quot;)&lt;br /&gt;
         choice(menuPriorityMedium, &amp;quot;Medium&amp;quot;)&lt;br /&gt;
         choice(menuPriorityHigh, &amp;quot;High&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuScan) {&lt;br /&gt;
         choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
         choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
         choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
         choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
         choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuAlarmSevr) {&lt;br /&gt;
         choice(menuAlarmSevrNone, &amp;quot;None&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMinor, &amp;quot;Minor&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMajor, &amp;quot;Major&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrInvalid, &amp;quot;Invalid&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     #struct definitions for recordCommon&lt;br /&gt;
     struct(TimeStamp) {&lt;br /&gt;
         field(secondsPastEpoch,int64)&lt;br /&gt;
         field(nanoSeconds,int32)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Scan {&lt;br /&gt;
         field(scan,menu(menuScan)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(phase,int16)&lt;br /&gt;
         field(priority,menu(menuPriority)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;b&amp;gt;Event NEEDS NEW DEFINITIONS&amp;lt;/b&amp;gt;&lt;br /&gt;
     struct Event {&lt;br /&gt;
         field(eventNumber,int16) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(timeStampEvent,int16)&lt;br /&gt;
         field(timeStampLink,link(in,interface(????))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Disable {&lt;br /&gt;
         field(disableValue,int16) {&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(disableInput,int16)&lt;br /&gt;
         field(disableLink,link(in,interface(LinkBoolean)))&lt;br /&gt;
         field(disableAlarmSeverity,menu(menuAlarmSevr))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(ProcessLink) {&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(link,link(process,interface(ProcessLink)))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Other common definitions ==&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;Raw&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(full,float64) &lt;br /&gt;
         field(egul,float64)&lt;br /&gt;
         field(slope,float64) &lt;br /&gt;
         field(intercept,float64) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ControlLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
     }&lt;br /&gt;
     struct(AlarmLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(lowSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(lowWarning,float64) &lt;br /&gt;
         field(lowWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(highWarning,float64) &lt;br /&gt;
         field(highWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
         field(highSevr,menu(menuAlarmSevr)) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= recordCommon.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
This is a file that is included by most of the record types provided by&lt;br /&gt;
base. For example&lt;br /&gt;
     #include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
     record(AiRecord) {&lt;br /&gt;
     #include &amp;quot;recordCommon.dbd&amp;quot;&lt;br /&gt;
     ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;recordCommon.dbd&amp;lt;/tt&amp;gt; contains the following definitions&lt;br /&gt;
         field(description,string)&lt;br /&gt;
         field(scan,struct(Scan))&lt;br /&gt;
         field(event,struct(Event))&lt;br /&gt;
         field(accessSecurityGroup,string)&lt;br /&gt;
         field(pini,boolean)&lt;br /&gt;
         field(disablePutField,boolean)&lt;br /&gt;
         field(alarmAckSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmNoAckTransient,menu(menuAlarmSevr)) {&lt;br /&gt;
         # highest level of alarm that does not have to be acknowledged&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         field(udf,boolean) {&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(time,struct(TimeStamp)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(disable,struct(Disable)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmStatus,string) {&lt;br /&gt;
             default(&amp;quot;UDF&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;Invalid&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(processLink,array(ProcessLink[])) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
Although it has many fewer fields,&lt;br /&gt;
recordCommon.dbd is a complete replacement for the V3 dbCommon.&lt;br /&gt;
The following V3 fields are no longer needed:&lt;br /&gt;
* private fields - Private fields will truly be private to the implementation&lt;br /&gt;
* previous value fields - All puts to database fields will be posted. The layer above will decide if clients should be notified of changes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= baseSupport.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Support ==&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* monitor support&lt;br /&gt;
* input support&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For monitor, input, and output The following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
     link(process,processLink,PvProcessLink,interface(LinkProcess))&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLink,PvMonitorLink,interface(&lt;br /&gt;
         LinkOctet,LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,monitorLinkArray,PvMonitorLink,interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLink,PvInputLink, interface(&lt;br /&gt;
         LinkOctet,LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLinkArray,PvInputLink, interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
     link(out,outputLink,PvOutputLink, interface(&lt;br /&gt;
         LinkOctet,LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(out,outputLinkArray,PvOutputLink, interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynDriver support ==&lt;br /&gt;
&lt;br /&gt;
     link(inout,asynInt32,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Average,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Monitor,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(inout,asynFloat64,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Average,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Monitor,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynDigitalMonitor,AsynLink,interface(AsynDigital))&lt;br /&gt;
     link(inout,asynDigital,AsynLink,interface(AsynDigital)))&lt;br /&gt;
     link(inout,asynInt32Array,AsynLink,interface(LinkArrayInt32)))&lt;br /&gt;
     link(inout,asynFloat64Array,AsynLink,interface(LinkArrayFloat64)))&lt;br /&gt;
     link(inout,asynOctet,AsynLink,interface(AsynOctet)))&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=567</id>
		<title>V4 Link Support Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=567"/>
		<updated>2005-10-25T18:35:13Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Link Support Tutorial Oct 25 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
The V4 link support is a replacement for V3 &lt;br /&gt;
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK&lt;br /&gt;
# device DBD definition and device support&lt;br /&gt;
# driver DBD definition and driver support&lt;br /&gt;
&lt;br /&gt;
The link support model is:&lt;br /&gt;
* For each link, record support defines a list of interfaces it can use for communicating with link support&lt;br /&gt;
* Link support defines the set of interfaces it implements&lt;br /&gt;
&lt;br /&gt;
Link support has no knowledge of what record types are using it&lt;br /&gt;
and record support has no knowledge about link support other than the&lt;br /&gt;
interface it is using.&lt;br /&gt;
&lt;br /&gt;
EPICS base defines a standard set of interfaces for link support.&lt;br /&gt;
The intention is that the set includes enough functionality such that&lt;br /&gt;
most link support can be implemented via just these interfaces.&lt;br /&gt;
&lt;br /&gt;
The interfaces support all the functionality needed by Channel/Database access&lt;br /&gt;
and by the generic EPICS device support supplied by asynDriver.&lt;br /&gt;
Since asynDriver is intended as a framework for interfacing to most hardware,&lt;br /&gt;
this means that the interfaces supplied and used by base allows support&lt;br /&gt;
for most hardware. The support can communicate with the hardware&lt;br /&gt;
however it wants but must implement some set of the interfaces defined&lt;br /&gt;
by base.&lt;br /&gt;
&lt;br /&gt;
This document gives a brief overview of the V4 link support model.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Database Definitions For Links =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section first reviews the DBD syntax related to link definitions.&lt;br /&gt;
It then gives a brief description of link related definitions in dbCommon.dbd&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
A record link has the syntax:&lt;br /&gt;
     link(linkDirection,interface(interfaceName,...))&lt;br /&gt;
A link itself has the syntax:&lt;br /&gt;
     link(linkDirection,choiceName,dataStructName,interface(interfaceName,...))&lt;br /&gt;
A record instance link definition has the syntax:&lt;br /&gt;
     field = { choice(interfaceName) {structAssignmentList}}&lt;br /&gt;
      or&lt;br /&gt;
     field = { choice(interfaceName) dataStructName {structAssignmentList} }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;linkDirection&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be one of &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. Compatible checks are made to match the interface with a field.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interface&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is a list of the interfaces that the record support understands or that link support implements.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of an interface via which record support communicates with link support.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools prompt the user to assign values to the structure.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choice&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Selects a link with &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; = &amp;lt;tt&amp;gt;choice&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A record instance link definition selects a link as follows:&lt;br /&gt;
* The linkDirections must be compatible&lt;br /&gt;
** Except for inout the record link and link directions must be the same&lt;br /&gt;
** If record link specifies inout the link can specify either in or out or inout&lt;br /&gt;
* The interfaceName specified by the record instance must be in the record link interface list and in the link interface list.&lt;br /&gt;
* The dataStructName specified in the record instance must match the dataStructName in the link definition.&lt;br /&gt;
&lt;br /&gt;
Assume the following definitions:&lt;br /&gt;
     record(AiRecord) {&lt;br /&gt;
         ...&lt;br /&gt;
         field(in,link(in,interface(LinkInt64,LinkFloat64)))&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvMonitorLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvInputLink) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     link(in,monitorLink,PvMonitorLink,interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLink,PvInputLink,interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     ...&lt;br /&gt;
     struct VME{&lt;br /&gt;
         field(a16,int16) &lt;br /&gt;
         field(a32,int32)&lt;br /&gt;
         field(channel,int16)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     link(in,someVmeADC,VME, interface(LinkInt32))&lt;br /&gt;
&lt;br /&gt;
The first example instance definition selects a monitor link. It selects interface LinkInt32, which means the support will provide a &amp;quot;raw&amp;quot; value that the&lt;br /&gt;
record support will convert to engineering units.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {monitorLink(LinkInt32) &lt;br /&gt;
                   PvMonitorLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                         process = true;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The next example selects a channel access input link. It selects interface&lt;br /&gt;
LinkFloat64, which means the support will provide a value in engineering units.&lt;br /&gt;
It asks that the linked record be processed and that the link not complete&lt;br /&gt;
until the linked record completes processing.&lt;br /&gt;
     AiRecord aiInputExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {inputLink(LinkFloat64) &lt;br /&gt;
                   PvInputLink {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                        process = true;&lt;br /&gt;
                        wait = true;&lt;br /&gt;
                        timeout = 1.0;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The last example attaches the link to support for a VME Analog to Digital device.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {someVmeADC(LinkInt32) VME {a16 = 0xc000; channel = 1} }&lt;br /&gt;
&lt;br /&gt;
== Standard Definitions For Channel/Database Access ==&lt;br /&gt;
&lt;br /&gt;
These are the database definitions defined in dbCommon are used by&lt;br /&gt;
the base supplied support for Channel/Database access.&lt;br /&gt;
This support registers each choiceName in the link definitions.&lt;br /&gt;
The complete set of data structure and link definitions are defined&lt;br /&gt;
in &amp;quot;V4 DB RecordCommon&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* monitor&lt;br /&gt;
* input&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For monitor, input, and output the following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
&lt;br /&gt;
These are definitions that are used by the standard EPICS device support&lt;br /&gt;
for asynDriver. Since asynDriver is a generic way of interfacing arbitrary&lt;br /&gt;
hardware support, this is a generic way of attaching links in records to&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLink) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link definitions ===&lt;br /&gt;
&lt;br /&gt;
     link(inout,asynInt32,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Average,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Monitor,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(inout,asynFloat64,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Average,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Monitor,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynDigitalMonitor,AsynLink,interface(AsynDigital))&lt;br /&gt;
     link(inout,asynDigital,AsynLink,interface(AsynDigital)))&lt;br /&gt;
     link(inout,asynInt32Array,AsynLink,interface(LinkArrayInt32)))&lt;br /&gt;
     link(inout,asynFloat64Array,AsynLink,interface(LinkArrayFloat64)))&lt;br /&gt;
     link(inout,asynOctet,AsynLink,interface(AsynOctet)))&lt;br /&gt;
&lt;br /&gt;
This is the set of definitions for the standard EPICS device support implemented&lt;br /&gt;
by asynDriver. Although, at least for the first few V4 releases,&lt;br /&gt;
asynDriver will not be part of base, they are shown here because the&lt;br /&gt;
LinkInt32,... interface definitions are defined as part of base.&lt;br /&gt;
Again it is expected that almost all hardware support be created by&lt;br /&gt;
implementing a combination of these link interface definitions or&lt;br /&gt;
the interfaces implemented by Channel/Database access link support.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
An arbitrary number of Link Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
Other link support can also be supplied.&lt;br /&gt;
Whenever possible support should implement the standard interfaces&lt;br /&gt;
supplied by EPICS base, since these are the interfaces that the record types&lt;br /&gt;
supplied with base know how to use.&lt;br /&gt;
&lt;br /&gt;
Soft support should try to implement the same interfaces implemented by&lt;br /&gt;
the Channel/Database access support supplied with base. The support&lt;br /&gt;
can, of course, define data structures for it's own use.&lt;br /&gt;
Implementing these interfaces means that the support will work for&lt;br /&gt;
the same set of record links as the Channel/Database access support.&lt;br /&gt;
&lt;br /&gt;
Hardware support should, if possible, also implement the same interfaces&lt;br /&gt;
implemented by the Channel/Database access support.&lt;br /&gt;
Message based support may also have to implement the AsynOctet interface&lt;br /&gt;
but this interface is only used by a few record types.&lt;br /&gt;
&lt;br /&gt;
This section describes the interfaces implemented by all link support&lt;br /&gt;
and then the standard interfaces used by the records supplied with base.&lt;br /&gt;
&lt;br /&gt;
The syntax is similar to Java syntax since it is more concise than C++.&lt;br /&gt;
It can easily be translated to C++ syntax. For example the&lt;br /&gt;
definition:&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int16 data);&lt;br /&gt;
         void getBounds(&amp;lt;type&amp;gt; low, &amp;lt;type&amp;gt; high);&lt;br /&gt;
     }&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class LinkInt16 {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual LinkResult get(Callback &amp;amp;callback, int16_t *data) = 0;&lt;br /&gt;
         virtual LinkResult put(Callback &amp;amp;callback, int16_t data) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Link and MonitorLink ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE: arguments and return types ignored for now&amp;lt;/b&amp;gt;&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; is an interface that is implemented by link support that&lt;br /&gt;
supports monitors. An example is support for hardware interrupts.&lt;br /&gt;
The &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally record support does not need to call any of the Link &lt;br /&gt;
or MonitorLink methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call destroy before modifying the link&lt;br /&gt;
and initialize and connect after the link is modified.&lt;br /&gt;
&lt;br /&gt;
Note that neither Link or MonitorLink is listed in the &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; database&lt;br /&gt;
definition since they are generic.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
These are the definitions used by the Channel/Database access support&lt;br /&gt;
supplied with base. It is also used by the standard EPICS support from asyn.&lt;br /&gt;
&lt;br /&gt;
     enum LinkResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface LinkProcess {&lt;br /&gt;
         LinkResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
&lt;br /&gt;
     interface LinkOctet {&lt;br /&gt;
         LinkResult get(Callback callback, Octet data);&lt;br /&gt;
         LinkResult put(Callback callback, octet data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkResult get(Callback callback, octet[] data);&lt;br /&gt;
         LinkResult put(Callback callback, octet[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;GENERIC QUESTION&amp;lt;/b&amp;gt; The data is passed as primitive or arrays of&lt;br /&gt;
primitive types. Should &amp;lt;tt&amp;gt;Dbf&amp;lt;/tt&amp;gt; interfaces be used? Needs thought.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkResult write(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          LinkResult read(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,Boolean data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkResult get(Callback callback,boolean[] data);&lt;br /&gt;
         LinkResult put(Callback callback,boolean[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,Int16 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int16 data);&lt;br /&gt;
         void getBounds(&amp;lt;type&amp;gt; low, &amp;lt;type&amp;gt; high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt16 {&lt;br /&gt;
         LinkResult get(Callback callback,int16[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int16[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,Int32 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int32 data);&lt;br /&gt;
         void getBounds(&amp;lt;type&amp;gt; low, &amp;lt;type&amp;gt; high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt32 {&lt;br /&gt;
         LinkResult get(Callback callback,int32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,Int64 data);&lt;br /&gt;
         LinkResult put(Callback callback,Int64 data);&lt;br /&gt;
         void getBounds(&amp;lt;type&amp;gt; low, &amp;lt;type&amp;gt; high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayInt64 {&lt;br /&gt;
         LinkResult get(Callback callback,int64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,int64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     } &lt;br /&gt;
         &lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
&lt;br /&gt;
     interface LinkFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,Float32 data);&lt;br /&gt;
         LinkResult put(Callback callback,float32 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat32 {&lt;br /&gt;
         LinkResult get(Callback callback,float32[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float32[] data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,Float64 data);&lt;br /&gt;
         LinkResult put(Callback callback,float64 data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayFloat64 {&lt;br /&gt;
         LinkResult get(Callback callback,float64[] data);&lt;br /&gt;
         LinkResult put(Callback callback,float64[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkResult get(Callback callback,string data);&lt;br /&gt;
         LinkResult put(Callback callback,string data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkResult get(Callback callback,string[] data);&lt;br /&gt;
         LinkResult put(Callback callback,string[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Example - VME ADC support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
Assume the VME and link definitions given in the examples at the beginning&lt;br /&gt;
of this document.&lt;br /&gt;
&lt;br /&gt;
The following is presented with Java syntax.&lt;br /&gt;
It assumes that there is VME support of the form&lt;br /&gt;
&lt;br /&gt;
public class vme {&lt;br /&gt;
    static public short getShort(long addr);&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
The link support would be something like:&lt;br /&gt;
&lt;br /&gt;
     class AdcSupport implements Link LinkInt32 {&lt;br /&gt;
     AdcSupport(VME fromFactory)&lt;br /&gt;
     {&lt;br /&gt;
         addr = fromFactory;&lt;br /&gt;
         connected = false;&lt;br /&gt;
         //  from the VME initailze vmeaddr and channel&lt;br /&gt;
         // details left to your imagination&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Link methods&lt;br /&gt;
     void report(int16_t level)&lt;br /&gt;
     {&lt;br /&gt;
         printf(&amp;quot;AdcSupport a16 %x channel %d\n&amp;quot;,a16,channel);&lt;br /&gt;
     }&lt;br /&gt;
     void cancel() {} // nothing to do&lt;br /&gt;
     void destroy() {} //nothing to do&lt;br /&gt;
     void initialize()&lt;br /&gt;
     {&lt;br /&gt;
         // make sure we can access a16&lt;br /&gt;
     }&lt;br /&gt;
     void connect() {connected = true}&lt;br /&gt;
     void disconnect() {connected = false}&lt;br /&gt;
     &lt;br /&gt;
     // LinkInt32 methods&lt;br /&gt;
     LinkResult get(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         data = (Int)VME.getShort(vmeaddr);&lt;br /&gt;
         return linkDone;&lt;br /&gt;
     }&lt;br /&gt;
     LinkResult put(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         throw CantWriteAdc;&lt;br /&gt;
     }&lt;br /&gt;
     void getBounds(Int low, Int high) &lt;br /&gt;
     {&lt;br /&gt;
         // assume 16 bit unipolor adc&lt;br /&gt;
         low = 0; high = 0xffff;&lt;br /&gt;
     }&lt;br /&gt;
     private:&lt;br /&gt;
         VME addr;&lt;br /&gt;
         int vmeaddr;&lt;br /&gt;
         int channel;&lt;br /&gt;
         boolean connected;&lt;br /&gt;
     }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=566</id>
		<title>V4 DB RecordCommon</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=566"/>
		<updated>2005-10-25T18:33:11Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Standard Support October 25 2005 &lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes three base supplied components for EPICS V4 databases.&lt;br /&gt;
# menuStructBase.dbd - menu and struct definitions &lt;br /&gt;
# recordCommon.dbd - common fields for record definitions&lt;br /&gt;
# baseSupport.dbd - link definitions for base supplied support&lt;br /&gt;
&lt;br /&gt;
This document requires that the reader be familiar with:&lt;br /&gt;
# V3 iocCore&lt;br /&gt;
# V4 DBD Statement Syntax&lt;br /&gt;
# V4 DB Record Instance Syntax&lt;br /&gt;
&lt;br /&gt;
NOTE: This document is ahead of the two above V4 documents so it may use&lt;br /&gt;
slightly different syntax.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= menuStructBase.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Links ==&lt;br /&gt;
&lt;br /&gt;
     struct(PvMonitorLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean) &lt;br /&gt;
     }&lt;br /&gt;
     struct(PvInputLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvOutputLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(PvProcessLink) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== asynDriver Link ==&lt;br /&gt;
     struct(AsynLink) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Definitions for recordCommon ==&lt;br /&gt;
&lt;br /&gt;
     # menu definitions for recordCommon fields&lt;br /&gt;
     menu(menuPriority) {&lt;br /&gt;
         choice(menuPriorityLow, &amp;quot;Low&amp;quot;)&lt;br /&gt;
         choice(menuPriorityMedium, &amp;quot;Medium&amp;quot;)&lt;br /&gt;
         choice(menuPriorityHigh, &amp;quot;High&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuScan) {&lt;br /&gt;
         choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
         choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
         choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
         choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
         choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuAlarmSevr) {&lt;br /&gt;
         choice(menuAlarmSevrNone, &amp;quot;None&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMinor, &amp;quot;Minor&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMajor, &amp;quot;Major&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrInvalid, &amp;quot;Invalid&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     #struct definitions for recordCommon&lt;br /&gt;
     struct(TimeStamp) {&lt;br /&gt;
         field(secondsPastEpoch,int64)&lt;br /&gt;
         field(nanoSeconds,int32)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Scan {&lt;br /&gt;
         field(scan,menu(menuScan)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(phase,int16)&lt;br /&gt;
         field(priority,menu(menuPriority)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;b&amp;gt;Event NEEDS NEW DEFINITIONS&amp;lt;/b&amp;gt;&lt;br /&gt;
     struct Event {&lt;br /&gt;
         field(eventNumber,int16) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(timeStampEvent,int16)&lt;br /&gt;
         field(timeStampLink,link(in,interface(????))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Disable {&lt;br /&gt;
         field(disableValue,int16) {&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(disableInput,int16)&lt;br /&gt;
         field(disableLink,link(in,interface(LinkBoolean)))&lt;br /&gt;
         field(disableAlarmSeverity,menu(menuAlarmSevr))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(ProcessLink) {&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(link,link(process,interface(ProcessLink)))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Other common definitions ==&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;Raw&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(full,float64) &lt;br /&gt;
         field(egul,float64)&lt;br /&gt;
         field(slope,float64) &lt;br /&gt;
         field(intercept,float64) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ControlLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
     }&lt;br /&gt;
     struct(AlarmLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(lowSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(lowWarning,float64) &lt;br /&gt;
         field(lowWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(highWarning,float64) &lt;br /&gt;
         field(highWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
         field(highSevr,menu(menuAlarmSevr)) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= recordCommon.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
This is a file that is included by most of the record types provided by&lt;br /&gt;
base. For example&lt;br /&gt;
     #include &amp;quot;menuStructBase.dbd&amp;quot;&lt;br /&gt;
     record(AiRecord) {&lt;br /&gt;
     #include &amp;quot;recordCommon.dbd&amp;quot;&lt;br /&gt;
     ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;recordCommon.dbd&amp;lt;/tt&amp;gt; contains the following definitions&lt;br /&gt;
         field(description,string)&lt;br /&gt;
         field(scan,struct(Scan))&lt;br /&gt;
         field(event,struct(Event))&lt;br /&gt;
         field(accessSecurityGroup,string)&lt;br /&gt;
         field(pini,boolean)&lt;br /&gt;
         field(disablePutField,boolean)&lt;br /&gt;
         field(alarmAckSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmNoAckTransient,menu(menuAlarmSevr)) {&lt;br /&gt;
         # highest level of alarm that does not have to be acknowledged&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         field(udf,boolean) {&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(time,struct(TimeStamp)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(disable,struct(Disable)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmStatus,string) {&lt;br /&gt;
             default(&amp;quot;UDF&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;Invalid&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(processLink,array(RecordCommonProcessLink[])) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
Although it has many fewer fields,&lt;br /&gt;
recordCommon.dbd is a complete replacement for the V3 dbCommon.&lt;br /&gt;
The following V3 fields are no longer needed:&lt;br /&gt;
* private fields - Private fields will truly be privaye to the implementation&lt;br /&gt;
* previous value fields - All puts to database fields will be posted. The layer above will decide if clients should be notified of changes.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= baseSupport.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Support ==&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* monitor support&lt;br /&gt;
* input support&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For monitor, input, and output The following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
     link(process,processLink,PvProcessLink,interface(LinkProcess))&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLink,PvMonitorLink,interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,monitorLinkArray,PvMonitorLink,interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLink,PvInputLink, interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLinkArray,PvInputLink, interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
     link(out,outputLink,PvOutputLink, interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(out,outputLinkArray,PvOutputLink, interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynDriver support ==&lt;br /&gt;
&lt;br /&gt;
     link(inout,asynInt32,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Average,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Monitor,AsynLink,interface(LinkInt32))&lt;br /&gt;
     link(inout,asynFloat64,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Average,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Monitor,AsynLink,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynDigitalMonitor,AsynLink,interface(AsynDigital))&lt;br /&gt;
     link(inout,asynDigital,AsynLink,interface(AsynDigital)))&lt;br /&gt;
     link(inout,asynInt32Array,AsynLink,interface(LinkArrayInt32)))&lt;br /&gt;
     link(inout,asynFloat64Array,AsynLink,interface(LinkArrayFloat64)))&lt;br /&gt;
     link(inout,asynOctet,AsynLink,interface(AsynOctet)))&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=565</id>
		<title>V4 Link Support Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=565"/>
		<updated>2005-10-24T15:17:28Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Link Support Tutorial Oct 24 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
The V4 link support is a replacement for V3 &lt;br /&gt;
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK&lt;br /&gt;
# device DBD definition and device support&lt;br /&gt;
# driver DBD definition and driver support&lt;br /&gt;
&lt;br /&gt;
The link support model is:&lt;br /&gt;
* For each link, record support defines a list of interfaces it can use for communicating with link support&lt;br /&gt;
* Link support defines the set of interfaces it implements&lt;br /&gt;
&lt;br /&gt;
Link support has no knowledge of what record types are using it&lt;br /&gt;
and record support has no knowledge about link support other than the&lt;br /&gt;
interface it is using.&lt;br /&gt;
&lt;br /&gt;
EPICS base defines a standard set of interfaces for link support.&lt;br /&gt;
The intention is that the set includes enough functionality such that&lt;br /&gt;
most link support can be implemented via just these interfaces.&lt;br /&gt;
&lt;br /&gt;
The interfaces support all the functionality needed by Channel/Database access&lt;br /&gt;
and by the generic EPICS device support supplied by asynDriver.&lt;br /&gt;
Since asynDriver is intended as a framework for interfacing to most hardware,&lt;br /&gt;
this means that the interfaces supplied and used by base allows support&lt;br /&gt;
for most hardware. The support can communicate with the hardware&lt;br /&gt;
however it wants but must implement some set of the interfaces defined&lt;br /&gt;
by base.&lt;br /&gt;
&lt;br /&gt;
This document gives a brief overview of the V4 link support model.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Database Definitions For Links =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section first reviews the DBD syntax related to link definitions.&lt;br /&gt;
It then gives a brief description of link related definitions in dbCommon.dbd&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
A record link has the syntax:&lt;br /&gt;
     link(linkDirection,interface(interfaceName,...))&lt;br /&gt;
A link itself has the syntax:&lt;br /&gt;
     link(linkDirection,choiceName,dataStructName,interface(interfaceName,...))&lt;br /&gt;
A record instance link definition has the syntax:&lt;br /&gt;
     field = { blockValue, choice(interfaceName), {structAssignmentList}}&lt;br /&gt;
      or&lt;br /&gt;
     field = { block = blockValue; choiceName = choice(interfaceName);&lt;br /&gt;
                 dataStructName {structAssignmentList{}&lt;br /&gt;
              }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;linkDirection&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be one of &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. Compatible checks are made to match the interface with a field.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interface&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is a list of the interfaces that the record support understands.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of an interface via which record support communicates with device support.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools prompt the user to assign values to the structure.&lt;br /&gt;
; &amp;lt;tt&amp;gt;blockValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;choice&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Selects a link with &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; = &amp;lt;tt&amp;gt;choice&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A record instance link definition selects a link as follows:&lt;br /&gt;
* The linkDirections must be compatible&lt;br /&gt;
** Except for inout the record link and link directions must be the same&lt;br /&gt;
** If record link specifies inout the link can specify either in or out&lt;br /&gt;
* The interfaceName specified by the record instance must be in the record link interface list and in the link interface list.&lt;br /&gt;
* The dataStructName specified in the record instance must match the dataStructName in the link definition.&lt;br /&gt;
&lt;br /&gt;
Assume the following definitions:&lt;br /&gt;
     record(AiRecord) {&lt;br /&gt;
         ...&lt;br /&gt;
         field(in,link(in,interface(LinkInt64,LinkFloat64)))&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     struct(MonitorLinkData) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(InputLinkData) {&lt;br /&gt;
         field(pvname,string)&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     link(in,monitorLink,MonitorLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLink,InputLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     ...&lt;br /&gt;
     struct VME{&lt;br /&gt;
         field(a16,int16) &lt;br /&gt;
         field(a32,int32)&lt;br /&gt;
         field(channel,int16)&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     link(in,someVmeADC,VME, interface(LinkInt32))&lt;br /&gt;
&lt;br /&gt;
The first example instance definition selects a monitor link. It selects interface LinkInt32, which means the support will provide a &amp;quot;raw&amp;quot; value that the&lt;br /&gt;
record support will convert to engineering units.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {choiceName = monitorLink(LinkInt32) &lt;br /&gt;
                   MonitorLinkData {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                         process = true;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The next example selects a channel access input link. It selects interface&lt;br /&gt;
LinkFloat64, which means the support will provide a value in engineering units.&lt;br /&gt;
It asks that the linked record be processed and that the link not complete&lt;br /&gt;
until the linked record completes processing.&lt;br /&gt;
     AiRecord aiInputExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {choiceName = inputLink(LinkFloat64) &lt;br /&gt;
                   MonitorLinkData {    &lt;br /&gt;
                        pvname = &amp;quot;someRecord&amp;quot;;&lt;br /&gt;
                        process = true;&lt;br /&gt;
                        wait = true;&lt;br /&gt;
                        timeout = 1.0;&lt;br /&gt;
                        inheritSeverity = false&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
The last example attaches the link to support for a VME Analog to Digital device.&lt;br /&gt;
     AiRecord aiMonitorExample = {&lt;br /&gt;
         ...&lt;br /&gt;
         in = {choiceName = someVmeADC(LinkInt32) &lt;br /&gt;
                   VME {a16 = 0xc000; channel = 1}&lt;br /&gt;
               }&lt;br /&gt;
&lt;br /&gt;
== Standard Definitions For Channel/Database Access ==&lt;br /&gt;
&lt;br /&gt;
These are the database definitions defined in dbCommon are used by&lt;br /&gt;
the base supplied support for Channel/Database access.&lt;br /&gt;
This support registers each choiceName in the link definitions.&lt;br /&gt;
The complete set of data structure and link definitions are defined&lt;br /&gt;
in &amp;quot;V4 DB RecordCommon&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* monitor&lt;br /&gt;
* input&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For monitor, input, and output the following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
&lt;br /&gt;
These are definitions that are used by the standard EPICS device support&lt;br /&gt;
for asynDriver. Since asynDriver is a generic way of interfacing arbitrary&lt;br /&gt;
hardware support, this is a generic way of attaching links in records to&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLinkData) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link definitions ===&lt;br /&gt;
&lt;br /&gt;
     link(inout,asynInt32,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Average,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Monitor,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(inout,asynFloat64,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Average,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Monitor,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynDigitalMonitor,AsynLinkData,interface(AsynDigital))&lt;br /&gt;
     link(inout,asynDigital,AsynLinkData,interface(AsynDigital)))&lt;br /&gt;
     link(inout,asynInt32Array,AsynLinkData,interface(LinkArrayInt32)))&lt;br /&gt;
     link(inout,asynFloat64Array,AsynLinkData,interface(LinkArrayFloat64)))&lt;br /&gt;
     link(inout,asynOctet,AsynLinkData,interface(AsynOctet)))&lt;br /&gt;
&lt;br /&gt;
This is the set of definitions for the standard EPICS device support implemented&lt;br /&gt;
by asynDriver. Although, at least for the first few V4 releases,&lt;br /&gt;
asynDriver will not be part of base, they are shown here because the&lt;br /&gt;
LinkInt32,... interface definitions are defined as part of base.&lt;br /&gt;
Again it is expected that almost all hardware support be created by&lt;br /&gt;
implementing a combination of these link interface definitions or&lt;br /&gt;
the interfaces implemented by Channel/Database access link support.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
An arbitrary number of Link Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
Other link support can also be supplied.&lt;br /&gt;
Whenever possible support should implement the standard interfaces&lt;br /&gt;
supplied by EPICS base, since these are the interfaces that the record types&lt;br /&gt;
supplied with base know how to use.&lt;br /&gt;
&lt;br /&gt;
Soft support should try to implement the same interfaces implemented by&lt;br /&gt;
the Channel/Database access support supplied with base. The support&lt;br /&gt;
can, of course, define data structures for it's own use.&lt;br /&gt;
Implementing these interfaces means that the support will work for&lt;br /&gt;
the same set of record links as the Channel/Database access support.&lt;br /&gt;
&lt;br /&gt;
Hardware support should, if possible, also implement the same interfaces&lt;br /&gt;
implemented by the Channel/Database access support.&lt;br /&gt;
Message based support may also have to implement the AsynOctet interface&lt;br /&gt;
but this interface is only used by a few record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This section describes the interfaces implemented by all link support&lt;br /&gt;
and then the standard interfaces used by the records supplied with base.&lt;br /&gt;
&lt;br /&gt;
== Link and MonitorLink ==&lt;br /&gt;
&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; is an interface that is implemented by link support that&lt;br /&gt;
supports monitors. An example is support for hardware interrupts.&lt;br /&gt;
The &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally record support does not need to call any of the Link &lt;br /&gt;
or MonitorLink methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call destroy before modifying the link&lt;br /&gt;
and initialize and connect after the link is modified.&lt;br /&gt;
&lt;br /&gt;
Note that neither Link or MonitorLink is listed in the &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; database&lt;br /&gt;
definition since they are generic.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
These are the definitions used by the Channel/Database access support&lt;br /&gt;
supplied with base. It is also used by the standard EPICS support from asyn.&lt;br /&gt;
&lt;br /&gt;
     enum LinkWaitResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface LinkProcess {&lt;br /&gt;
         LinkWaitResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
&lt;br /&gt;
     interface LinkOctet {&lt;br /&gt;
         LinkWaitResult get(Callback callback, Octet data);&lt;br /&gt;
         LinkWaitResult put(Callback callback, Octet data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkWaitResult get(Callback callback, octet[] data);&lt;br /&gt;
         LinkWaitResult put(Callback callback, octet[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The data source must be an array of octets or the connect request will fail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;GENERIC QUESTION&amp;lt;/b&amp;gt; The data is passed as primitive or arrays of&lt;br /&gt;
primitive types. Should &amp;lt;tt&amp;gt;Dbf&amp;lt;/tt&amp;gt; interfaces be used? Needs thought.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkWaitResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkWaitResult write(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          LinkWaitResult read(Callback callback,octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkWaitResult get(Callback callback,Boolean data);&lt;br /&gt;
         LinkWaitResult put(Callback callback,boolean data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkWaitResult get(Callback callback,boolean[] data);&lt;br /&gt;
         LinkWaitResult put(Callback callback,boolean[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be int16, int32, or int64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult get(Callback callback,&amp;lt;type&amp;gt; data);&lt;br /&gt;
         LinkWaitResult put(Callback callback,&amp;lt;type&amp;gt; data);&lt;br /&gt;
         void getBounds(&amp;lt;type&amp;gt; low, &amp;lt;type&amp;gt; high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult get(Callback callback,&amp;lt;type&amp;gt;[] data);&lt;br /&gt;
         LinkWaitResult put(Callback callback,&amp;lt;type&amp;gt;[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     } &lt;br /&gt;
         &lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be float32 or float64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult get(Callback callback,&amp;lt;type&amp;gt; data);&lt;br /&gt;
         LinkWaitResult put(Callback callback,&amp;lt;type&amp;gt; data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult get(Callback callback,&amp;lt;type&amp;gt;[] data);&lt;br /&gt;
         LinkWaitResult put(Callback callback,&amp;lt;type&amp;gt;[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkWaitResult get(Callback callback,string data);&lt;br /&gt;
         LinkWaitResult put(Callback callback,string data);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkWaitResult get(Callback callback,string[] data);&lt;br /&gt;
         LinkWaitResult put(Callback callback,string[] data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Example - VME ADC support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
Assume the VME and link definitions given in the examples at the beginning&lt;br /&gt;
of this document.&lt;br /&gt;
&lt;br /&gt;
The following is presented with Java syntax.&lt;br /&gt;
It assumes that there is VME support of the form&lt;br /&gt;
&lt;br /&gt;
public class vme {&lt;br /&gt;
    static public short getShort(long addr);&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
The link support would be something like:&lt;br /&gt;
&lt;br /&gt;
     class AdcSupport implements Link LinkInt32 {&lt;br /&gt;
     AdcSupport(VME fromFactory)&lt;br /&gt;
     {&lt;br /&gt;
         addr = fromFactory;&lt;br /&gt;
         connected = false;&lt;br /&gt;
         //  from the VME initailze vmeaddr and channel&lt;br /&gt;
         // details left to your imagination&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Link methods&lt;br /&gt;
     void report(int16_t level)&lt;br /&gt;
     {&lt;br /&gt;
         printf(&amp;quot;AdcSupport a16 %x channel %d\n&amp;quot;,a16,channel);&lt;br /&gt;
     }&lt;br /&gt;
     void cancel() {} // nothing to do&lt;br /&gt;
     void destroy() {} //nothing to do&lt;br /&gt;
     void initialize()&lt;br /&gt;
     {&lt;br /&gt;
         // make sure we can access a16&lt;br /&gt;
     }&lt;br /&gt;
     void connect() {connected = true}&lt;br /&gt;
     void disconnect() {connected = false}&lt;br /&gt;
     &lt;br /&gt;
     // LinkInt32 methods&lt;br /&gt;
     LinkWaitResult get(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         data = (Int)VME.getShort(vmeaddr);&lt;br /&gt;
         return linkDone;&lt;br /&gt;
     }&lt;br /&gt;
     LinkWaitResult put(Callback callback, Int data)&lt;br /&gt;
     {&lt;br /&gt;
         throw CantWriteAdc;&lt;br /&gt;
     }&lt;br /&gt;
     void getBounds(Int low, Int high) &lt;br /&gt;
     {&lt;br /&gt;
         // assume 16 bit unipolor adc&lt;br /&gt;
         low = 0; high = 0xffff;&lt;br /&gt;
     }&lt;br /&gt;
     private:&lt;br /&gt;
         VME addr;&lt;br /&gt;
         int vmeaddr;&lt;br /&gt;
         int channel;&lt;br /&gt;
         boolean connected;&lt;br /&gt;
     }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Record_Processing&amp;diff=572</id>
		<title>V4 Design: Record Processing</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Record_Processing&amp;diff=572"/>
		<updated>2005-10-21T14:25:42Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Record Processing October 21 2005 &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;UNRESOLVED ISSUES&amp;lt;/b&amp;gt;&lt;br /&gt;
* This document is still evolving&lt;br /&gt;
* Monitors&lt;br /&gt;
** How will monitor data be managed?&lt;br /&gt;
** Big problem is how will array data be managed?&lt;br /&gt;
* Alarms&lt;br /&gt;
** How will V4 handle alarms?&lt;br /&gt;
* Events&lt;br /&gt;
** What is the V4 event model?&lt;br /&gt;
** What is required from the IOC database?&lt;br /&gt;
&lt;br /&gt;
This document described semantics for V4 record processing that are&lt;br /&gt;
different than for V3.&lt;br /&gt;
This includes the following:&lt;br /&gt;
* Semantics for record processing&lt;br /&gt;
* Semantics for Database and Channel Access Links.&lt;br /&gt;
* Record Locking&lt;br /&gt;
* Posting database monitors&lt;br /&gt;
* Status and Alarm Severity&lt;br /&gt;
* Access to array and structure fields.&lt;br /&gt;
&lt;br /&gt;
This version is based on feedback from the EPICS core developer's&lt;br /&gt;
meeting at ANL/APS on July 11th through July 14th.&lt;br /&gt;
In addition discussions with Andrew Johnson and Eric Norum have &lt;br /&gt;
led to many of the ideas described below.&lt;br /&gt;
This wiki is a companion to the wiki &amp;quot;V4 Design: dbdInterfaces&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
V3 record processing semantics do not work well for data&lt;br /&gt;
acquisition applications. An example of data acquisition is:&lt;br /&gt;
*  Move sample to new position.&lt;br /&gt;
** Several motors may be involved&lt;br /&gt;
** While moving post monitors to show current position, etc.&lt;br /&gt;
* Sample data&lt;br /&gt;
* Wait until CA client has fetched the data before next move.&lt;br /&gt;
&lt;br /&gt;
SynAPPS provides the Scan, motor, etc records which help with&lt;br /&gt;
data processing applications. These records process as follows:&lt;br /&gt;
&lt;br /&gt;
* Record does not complete processing until all inputs, outputs, etc done. Not completing means that they do not call recGblFwdLink until all proccessing is complete. Note that recGblFwdLink is what causes the V3 ioc to complete record processing.&lt;br /&gt;
* While waiting for asynchronous events these records have PACT=0 but keep state that shows it is still active&lt;br /&gt;
* Can be scanned and issue monitors while internal state is active&lt;br /&gt;
&lt;br /&gt;
Leaving PACT 0 but not calling recGblFwdLink was not anticipated when the V3 record processing semantics were created.&lt;br /&gt;
For V4 a record can be processed while it is waiting&lt;br /&gt;
for asynchronous processing to complete.&lt;br /&gt;
&lt;br /&gt;
In V3, if an input link is asynchronous, Process Passive does not wait&lt;br /&gt;
for asynchronous processing to complete before fetching data.&lt;br /&gt;
This also complicated data acquisition applications.&lt;br /&gt;
&lt;br /&gt;
V4 record processing is designed to make data acquisition easier.&lt;br /&gt;
Both input and output links can wait for record processing.&lt;br /&gt;
This is done, however, without record support blocking.&lt;br /&gt;
If blocking makes it easier to implement record support,&lt;br /&gt;
then the support can spawn a separate thread that does block.&lt;br /&gt;
Record support can communicate with the separate thread to decide when&lt;br /&gt;
to complete record processing.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Overview of V4 Record Processing =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
V4 will provide something analogous to V3 dbProcess.&lt;br /&gt;
The name may be different but for now it will still be called dbProcess.&lt;br /&gt;
&lt;br /&gt;
In V4 database access and channel access appear the same to record and&lt;br /&gt;
link support.&lt;br /&gt;
Only the implementation knows the difference.&lt;br /&gt;
In this document the term channelAccess will mean access to a record.&lt;br /&gt;
Thus it can mean a workstation client or a field of&lt;br /&gt;
a record that is a link to a record.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
V4 record processing has the following features.&lt;br /&gt;
&lt;br /&gt;
* database fields&lt;br /&gt;
** &amp;quot;owned&amp;quot; by database not record support&lt;br /&gt;
** fields can only be accessed via interfaces&lt;br /&gt;
** support can optionally provide storage for data associated with a field&lt;br /&gt;
** for channelAccess all fields appear as type primitive, string, struct, array or combination thereof&lt;br /&gt;
* dbProcess&lt;br /&gt;
** is responsible for common fields&lt;br /&gt;
** processes synchronous linked records by queuing requests rather than recursive calls to dbProcess&lt;br /&gt;
** can be called an arbitrary number of times while record is active&lt;br /&gt;
* link&lt;br /&gt;
** always has associated support&lt;br /&gt;
** can be record link or can be something else, e.g. a link to hardware&lt;br /&gt;
* record link&lt;br /&gt;
** can request process and/or wait for asynchronous completion&lt;br /&gt;
** local synchronous requests queued by dbProcess&lt;br /&gt;
** record is active and can be processed while asynchronous links active&lt;br /&gt;
* struct fields&lt;br /&gt;
** Can have associated support which can be synchronous or asynchronous&lt;br /&gt;
* block&lt;br /&gt;
** asynchronous support can proceed in parallel&lt;br /&gt;
** record instance can request that all active asynchronous support complete before calling link/struct support.&lt;br /&gt;
* lock&lt;br /&gt;
** record instances are locked&lt;br /&gt;
** dbProcess locks before calling support&lt;br /&gt;
** other code can also lock&lt;br /&gt;
** Two records can be locked without deadlock&lt;br /&gt;
* monitors&lt;br /&gt;
** dbProcess handles monitors&lt;br /&gt;
** support triggers monitors by writing to fields&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Database Fields =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
== Field Access by Support Code ==&lt;br /&gt;
Support code can access database fields only via interfaces implemented by&lt;br /&gt;
the IOC database.&lt;br /&gt;
Thus record fields are owned by the IOC database not by record support.&lt;br /&gt;
&lt;br /&gt;
Support code can register to provide storage for particular fields.&lt;br /&gt;
For example support code could implement a circular buffer for field &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
When some other code&lt;br /&gt;
request the array associated with &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, the IOC database&lt;br /&gt;
calls the support. The support returns the first portion of the circular&lt;br /&gt;
buffer and the caller must make an additional call to retrieve the rest of&lt;br /&gt;
the circular buffer.&lt;br /&gt;
&lt;br /&gt;
== Field Access by Channel Access ==&lt;br /&gt;
&lt;br /&gt;
For V4 database access and channel access appear the same to record&lt;br /&gt;
instances.&lt;br /&gt;
It is only the code that implements link support that knows the difference.&lt;br /&gt;
If a linked record is local, database access is used, and, if the record&lt;br /&gt;
is remote, channel access.&lt;br /&gt;
&lt;br /&gt;
V4 allows channel access to the following types of fields:&lt;br /&gt;
&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* one dimensional array of primitive or string or struct&lt;br /&gt;
* struct with fields of following types:&lt;br /&gt;
** primitive&lt;br /&gt;
** string&lt;br /&gt;
** struct&lt;br /&gt;
** array of primitive or string or struct&lt;br /&gt;
&lt;br /&gt;
For other database field types, i.e. links, the database will make the field&lt;br /&gt;
appear as one of the above types. For example a link field will appear&lt;br /&gt;
as a string with syntax that matches the information associated with the link.&lt;br /&gt;
For example a process link will have a string something like&lt;br /&gt;
    processLink(pvname = 'pvname', wait = true)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= dbProcess - Record Processing Semantics =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section describes the semantics implemented by dbProcess.&lt;br /&gt;
&lt;br /&gt;
The following are involved in record processing&lt;br /&gt;
* dbProcess&lt;br /&gt;
** is responsible for the fields in recordCommon&lt;br /&gt;
** implements a queue for local records that are processed because of record links&lt;br /&gt;
** posts monitors caused by field changes during record processing&lt;br /&gt;
* record support&lt;br /&gt;
** is responsible for record instance fields&lt;br /&gt;
** calls link/struct support via interfaces implemented by the support&lt;br /&gt;
* link support&lt;br /&gt;
** can be links to other records, to driver support, etc&lt;br /&gt;
** implements interfaces called by record and/or other support&lt;br /&gt;
* struct support&lt;br /&gt;
** is responsible for all fields in the struct&lt;br /&gt;
** implements interfaces called by record and/or other support&lt;br /&gt;
&lt;br /&gt;
== Processing Life Cycle ==&lt;br /&gt;
Assume a record instance is idle, i.e. is ready to start processing.&lt;br /&gt;
The following sequence of events occur:&lt;br /&gt;
* dbProcess processes the fields in recordCommon that must be processed before record support is called&lt;br /&gt;
** fields that have associated support may be asynchronous&lt;br /&gt;
** record support will not be called until all asynchronous support in recordCommon completes&lt;br /&gt;
* dbProcess calls record support after recordCommon support completes and as long as record support is active&lt;br /&gt;
** record support handles the record specific fields&lt;br /&gt;
** struct and link fields can have associated support&lt;br /&gt;
** associated support may be asynchronous&lt;br /&gt;
*** record support returns to dbProcess indicating that it is active&lt;br /&gt;
*** record support is required to detect when asynchronous support completes&lt;br /&gt;
*** when processing is complete record support returns to dbProcess indicating that it is done.&lt;br /&gt;
* whenever record support returns to dbProcess while still active, dbProcess posts any fields that were modified.&lt;br /&gt;
* when record support completes&lt;br /&gt;
** dbProcess processes the fields in recordCommon that must be processed after record support completes.&lt;br /&gt;
** dbProcess posts monitors for all fields that were modified since before the last time record support was called.&lt;br /&gt;
* record processing is complete. The record is again idle.&lt;br /&gt;
&lt;br /&gt;
An additional complication is that it is possible to cancel processing while&lt;br /&gt;
a record is active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== record common ==&lt;br /&gt;
&lt;br /&gt;
A record type can have fields that are processed by dbCommon rather than&lt;br /&gt;
record support. These fields are optional but it is expected that most record&lt;br /&gt;
types will include a standard set of fields.&lt;br /&gt;
&lt;br /&gt;
dbCommon will process the following fields:&lt;br /&gt;
&lt;br /&gt;
* before record support is called&lt;br /&gt;
** disable - if true NO processing will be done.&lt;br /&gt;
** scanDisable&lt;br /&gt;
*** has associated support&lt;br /&gt;
*** if record is scan disabled record processing completes immediately&lt;br /&gt;
** alarm fields&lt;br /&gt;
*** alarm handling is described below&lt;br /&gt;
* after record support completes&lt;br /&gt;
** processLink array&lt;br /&gt;
*** has associated support&lt;br /&gt;
&lt;br /&gt;
== record support ==&lt;br /&gt;
&lt;br /&gt;
Record support is responsible for all the fields not in dbCommon.&lt;br /&gt;
For link and struct fields there may be associated support which&lt;br /&gt;
may be synchronous or asynchronous. Record support communicates with&lt;br /&gt;
the link/struct support via interfaces that are implemented by the support.&lt;br /&gt;
&lt;br /&gt;
Record support may be called multiple times by dbProcess while a record instance&lt;br /&gt;
is active.&lt;br /&gt;
One of the arguments to process is ProcessState which has the values:&lt;br /&gt;
* processCancel - Cancel any outstanding activity&lt;br /&gt;
* processStart - Start processing&lt;br /&gt;
* processContinue - Making additional call&lt;br /&gt;
&lt;br /&gt;
process returns ProcessReturn which is one of the following:&lt;br /&gt;
* processDone - Done and successful&lt;br /&gt;
* processQuit - Do not do any more processing&lt;br /&gt;
* processActive - Not done&lt;br /&gt;
&lt;br /&gt;
If record support returns processActive it must keep internal state so&lt;br /&gt;
that it knows how to handle processCancel and processContinue.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For record support the above rules allow:&lt;br /&gt;
* process can be called repeatedly. This will continue as long as it returns processActive&lt;br /&gt;
* Everytime process returns processActive DbProcess posts monitors.&lt;br /&gt;
&lt;br /&gt;
== Record Locking ==&lt;br /&gt;
&lt;br /&gt;
V3 implemented lock sets in order to prevent different threads&lt;br /&gt;
from simultaneously accessing linked records.&lt;br /&gt;
&lt;br /&gt;
Instead of lock sets V4:&lt;br /&gt;
* implements a per record instance lock.&lt;br /&gt;
* defines a rule that allows two records to be locked without deadlocks&lt;br /&gt;
&lt;br /&gt;
== Posting Monitors ==&lt;br /&gt;
&lt;br /&gt;
In V3 monitors are posted when code (record support, device support, database access, etc) calls db_post_event. In V4 database access will itself handle&lt;br /&gt;
the posting of monitors.&lt;br /&gt;
&lt;br /&gt;
Monitors are posted by DbProcess when&lt;br /&gt;
* record support returns processActive.&lt;br /&gt;
* at the end of record processing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= link/struct Semantics =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both link and struct fields can have associated support.&lt;br /&gt;
The support can be synchronous or asynchronous.&lt;br /&gt;
&lt;br /&gt;
Support code implements interfaces.&lt;br /&gt;
Code that is responsible for a field communicates with the support via&lt;br /&gt;
the interface. Lets call this code the client.&lt;br /&gt;
&lt;br /&gt;
Each link and struct field has a well defined client.&lt;br /&gt;
* dbProcess is the client for fields in dbCommon&lt;br /&gt;
* record support is the client for the other top level fields in a record&lt;br /&gt;
* the struct support is the client for any link or struct fields in the struct&lt;br /&gt;
&lt;br /&gt;
Every link/struct has an associated block. The client is responsible for&lt;br /&gt;
implementing block. If block is true then the support will not be called&lt;br /&gt;
until all outstanding record activity completes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= channelAccess links =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
channelAccess link means access to a record or field. The requester can be:&lt;br /&gt;
* A database link in a record&lt;br /&gt;
* A channel access link in a record&lt;br /&gt;
* A workstation channel access client&lt;br /&gt;
&lt;br /&gt;
A channelAccess link is one of the following types:&lt;br /&gt;
* Monitor Link&lt;br /&gt;
** Implemented via a monitor request on linked field&lt;br /&gt;
** Optionally process record containing the link when monitor value is returned.&lt;br /&gt;
* Input Link&lt;br /&gt;
** Optionally request that record be processed.&lt;br /&gt;
** Optionally wait for linked record to complete processing.&lt;br /&gt;
** Get value.&lt;br /&gt;
* Output Link: &lt;br /&gt;
** Put value&lt;br /&gt;
** Optionally request processing. &amp;lt;b&amp;gt;If record can not be processed should the value be changed?&amp;lt;/b&amp;gt;&lt;br /&gt;
** Optionally wait until completion&lt;br /&gt;
* Process Link: Perform the following actions&lt;br /&gt;
** Request processing&lt;br /&gt;
** Optionally wait until linked record completes&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* processLink is the replacement for the V3 forwardLink&lt;br /&gt;
* wait does NOT mean to wait synchronously. It means to save state, return, and resume at the saved state when called again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Links are processed as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following rules apply when a process request is made:&lt;br /&gt;
* If record is already being processed the request is just ignored&lt;br /&gt;
* record support can specify that links to particular fields not cause processing.&lt;br /&gt;
** Where should this be specified?  In the Database Definition, the record instance, or both.&lt;br /&gt;
** If a process request is allowed, should it be done regardless of the scan mechanism, i.e. the record does not have to be passive?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Mutual Exclusion =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
V3 implemented lock sets, i.e. when a record was being processed it and all records linked via database links were locked.&lt;br /&gt;
&lt;br /&gt;
Lock sets solved two Mutual Exclusion problems:&lt;br /&gt;
* V3 allowed dbProcess to be called recursively.&lt;br /&gt;
** process passive database links and forward links were implemented via recursive calls to DbProcess&lt;br /&gt;
** Lock sets prevented deadly embrace problems for circular links.&lt;br /&gt;
* No puts could be done to an record in a lock set while record processing is active.&lt;br /&gt;
** For synchronous records this guarantees that no fields are modified except by record processing itself.&lt;br /&gt;
** For asynchronous records this guarantee is not valid.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
V4 does not call dbProcess recursively. Instead a process request is queued.&lt;br /&gt;
The request fails if either of the following is true:&lt;br /&gt;
* The record is active.&lt;br /&gt;
* The record is already queued.&lt;br /&gt;
&lt;br /&gt;
dbProcess itself manages the queue , which is FIFO.&lt;br /&gt;
When record support returns the first entry in the queue is processed.&lt;br /&gt;
In addition if link or struct support completes before the queue&lt;br /&gt;
is empty, a request to process the record containing the link/struct will&lt;br /&gt;
be added to the same queue.&lt;br /&gt;
Thus if a set of synchronous records are processed they will complete processing&lt;br /&gt;
without any context switch.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; What about periodically scanned records? Needs thought.&lt;br /&gt;
&lt;br /&gt;
This leaves the question of what should be done about mutual exclusion.&lt;br /&gt;
&lt;br /&gt;
For V4 there will be two locks associated with the IOC database:&lt;br /&gt;
1) a global lock, and 2) A per record instance lock.&lt;br /&gt;
&lt;br /&gt;
The global lock must be taken&lt;br /&gt;
whenever the structure of the database is modified. Examples are&lt;br /&gt;
1) adding new record types, 2) adding new record instances, and 3) modifying&lt;br /&gt;
database links. Global locks are not discussed further in this document.&lt;br /&gt;
&lt;br /&gt;
Each record instance has an associated lock.&lt;br /&gt;
When dbProcess is called it takes the lock.&lt;br /&gt;
Before it returns it unlocks.&lt;br /&gt;
Thus record support does not need to lock or unlock.&lt;br /&gt;
&lt;br /&gt;
Other code that needs access to fields of a record instance must&lt;br /&gt;
lock before accessing any fields and unlock after all accesses are complete.&lt;br /&gt;
&lt;br /&gt;
This leaves the problem of how to access fields from two different record&lt;br /&gt;
instances simultaneously. For example code that implements database&lt;br /&gt;
access needs such access. Code that needs such access must call dbLockLink before accessing the linked record and dbUnlockLink after access.&lt;br /&gt;
&lt;br /&gt;
dbLockLink is implemented as follows:&lt;br /&gt;
* Each Record instances has a unique ordinal number&lt;br /&gt;
* Assume Record X has a link to record Y&lt;br /&gt;
* If the ordinal number of X is less than that of Y&lt;br /&gt;
** Just call dbLock for record Y&lt;br /&gt;
* If the ordinal numnber of X is greater than that of Y&lt;br /&gt;
** call dbUnlock for X&lt;br /&gt;
** call dbLock for Y&lt;br /&gt;
** call dbLock for X&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Posting Modifications =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The document &amp;quot;V4 Design: dbdIterfaces&amp;quot; provides a design that allows&lt;br /&gt;
database access to handle all posting on monitors without requiring&lt;br /&gt;
any help from the code that modifies database fields.&lt;br /&gt;
It can do this because fields can be modified only via an&lt;br /&gt;
interface implemented by database access.&lt;br /&gt;
&lt;br /&gt;
dbProcess posts monitors when:&lt;br /&gt;
* When record support returns processActive.&lt;br /&gt;
* When it finishes record processing.&lt;br /&gt;
&lt;br /&gt;
How to implement monitors must be decided.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Alarm Processing =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; Will V4 alarm handling be different than V3? If so this section&lt;br /&gt;
may be meaningless.&lt;br /&gt;
&lt;br /&gt;
The V4 semantics for status and severity have the following goals:&lt;br /&gt;
* alarmSeverity has the same values as for V3&lt;br /&gt;
* alarmStatus is a string&lt;br /&gt;
* a record starts processing with alarmSeverity = &amp;quot;NO_ALARM&amp;quot; and status empty.&lt;br /&gt;
* status will ONLY be posted if it has changed since the last time it was posted.&lt;br /&gt;
* alarmSeverity will ONLY be posted if it has changed since the last time it was posted&lt;br /&gt;
&lt;br /&gt;
The semantics, which are implemented by recordCommon, are:&lt;br /&gt;
&lt;br /&gt;
* When recordCommon is called with processStart&lt;br /&gt;
** A private variable newSeverity is set to NO_ALARM&lt;br /&gt;
** A private variable prevSeverity is set to alarmSeverity&lt;br /&gt;
* When recordCommon completes its part of record processing&lt;br /&gt;
** If newSeverity is NO_ALARM and prevSeverity has a different value&lt;br /&gt;
*** alarmSeverity is set to NO_ALARM&lt;br /&gt;
*** alarmStatus is set to empty&lt;br /&gt;
&lt;br /&gt;
* When the recordCommon.setSeverity(sevr,status) is called&lt;br /&gt;
** If sevr is less than or equal to newSeverity nothing is done&lt;br /&gt;
** else&lt;br /&gt;
*** alarmSeverity is set to sevr&lt;br /&gt;
*** alarmStatus is set to status&lt;br /&gt;
*** newSeverity is set to sevr&lt;br /&gt;
&lt;br /&gt;
NOTE: alarmStatus and alarmSeverity are written by the normal method.&lt;br /&gt;
This means that their values will be posted.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Channel Access/ Database Access field types =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This section discusses how IOC database fields are accessed by channel access&lt;br /&gt;
or via database links.&lt;br /&gt;
&lt;br /&gt;
For the initial V4 implementation only the following types of data&lt;br /&gt;
will be accessable.&lt;br /&gt;
&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* enum&lt;br /&gt;
* one dimensional array of primitive or string or struct&lt;br /&gt;
* struct with fields of following types:&lt;br /&gt;
** primitive&lt;br /&gt;
** string&lt;br /&gt;
** enum&lt;br /&gt;
** struct (use recursion for allowed types)&lt;br /&gt;
** one dimensional array of primitive or string or struct&lt;br /&gt;
&lt;br /&gt;
The dbdInterfaces document defines database field types.&lt;br /&gt;
It also defines a subset called basic types, which consists&lt;br /&gt;
of primitive types, string, array, and structure.&lt;br /&gt;
For external access only basic types can be accessed.&lt;br /&gt;
This means that structures and arrays that do not consist of basic types&lt;br /&gt;
are not accessablevia clannelAccess. For example a DbfLink is&lt;br /&gt;
not accessable via channel access as a DbfLink.&lt;br /&gt;
&lt;br /&gt;
Non basic fields will only be available via some combination of basic types.&lt;br /&gt;
&lt;br /&gt;
For example a DbfLink field will appear as a string.&lt;br /&gt;
If a Database Definition is&lt;br /&gt;
&lt;br /&gt;
     struct(calcInpLink) {&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(value,float64)&lt;br /&gt;
     };&lt;br /&gt;
     &lt;br /&gt;
     record(xxx) {&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(value,float64)&lt;br /&gt;
     ...&lt;br /&gt;
         field(inp,array(struct(calcInpLink)[]))&lt;br /&gt;
     ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
If a client attaches to &lt;br /&gt;
     record.field(link)&lt;br /&gt;
The data will be appear in the form:&lt;br /&gt;
     choiceName(pvname,...)&lt;br /&gt;
where &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; is the name of the link support and the arguments&lt;br /&gt;
are the values of the dataStruct associated with the support.&lt;br /&gt;
&lt;br /&gt;
Then if a client specifies the process variable:&lt;br /&gt;
     record.field(inp[1].link)&lt;br /&gt;
Then it connects to the link field of the second calcInpLink of field inp.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== primitive types ==&lt;br /&gt;
&lt;br /&gt;
This includes DbfBool, DbfOctet, DbfInt16, ... , DbfFloat64.&lt;br /&gt;
These do not present any problems. The scalar value is transfered.&lt;br /&gt;
&lt;br /&gt;
== string ==&lt;br /&gt;
&lt;br /&gt;
A string is just a UTF_8 encoded character string&lt;br /&gt;
&lt;br /&gt;
== DbfMenu  and DbfEnum ==&lt;br /&gt;
&lt;br /&gt;
Handled as an enum&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfLink ==&lt;br /&gt;
&lt;br /&gt;
Both of these have the following:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; A string that selects the link  support.&lt;br /&gt;
* &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt; Each support has an associated struct for configuration.&lt;br /&gt;
&lt;br /&gt;
How should these be made available? Perhaps:&lt;br /&gt;
&lt;br /&gt;
The field appears as a string with the following syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;choiceName(structAssignmentList)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where structAssignmentList has the same syntax as defined in &amp;quot;V4 DB Record Instance Syntax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== timeStamp ==&lt;br /&gt;
&lt;br /&gt;
This is just transfered like a struct with two fields:&lt;br /&gt;
* int64 secondsSinceEpoch&lt;br /&gt;
* int32 nanoSeconds&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== struct ==&lt;br /&gt;
&lt;br /&gt;
The database definition syntax allows a struct to be composed of fields&lt;br /&gt;
of any DbfType.&lt;br /&gt;
Database access, however, will only allow access to structs with fields&lt;br /&gt;
of the following types:&lt;br /&gt;
* primitive - DbfBool,...,DbfFloat64&lt;br /&gt;
* DbfString&lt;br /&gt;
* DbfArray of primitive type or string&lt;br /&gt;
* DbfStruct - As long as its fields are valid types&lt;br /&gt;
&lt;br /&gt;
The individual fields can be accessed directly so this discussion&lt;br /&gt;
only involves access to the entire structure.&lt;br /&gt;
&lt;br /&gt;
Access will only be available to clients that have knowledge of&lt;br /&gt;
fields within the structure. For channel access clients this means that&lt;br /&gt;
they provide a propertyCatalog that has some subset of the fields in the structure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== array ==&lt;br /&gt;
&lt;br /&gt;
Arrays of the following types are accessable:&lt;br /&gt;
* primitive - DbfBool,...,DbfFloat64&lt;br /&gt;
* DbfString&lt;br /&gt;
* DbfStruct - As long as its fields are valid types&lt;br /&gt;
&lt;br /&gt;
Note that arrays of structs are not accessable in the early V4 releases.&lt;br /&gt;
&lt;br /&gt;
Arrays still need lots more discussion!!!&lt;br /&gt;
The database definition syntax allow an array to be any of the basic types, i.e. DbfBool,...,DbfFloat64, DbfString, DbfArray, DbfStruct.&lt;br /&gt;
&lt;br /&gt;
For the initial V4 version, database access only allows access to arrays of the following types.&lt;br /&gt;
* primitive - DbfBool,...,DbfFloat64&lt;br /&gt;
* DbfString&lt;br /&gt;
* ???? What else&lt;br /&gt;
&lt;br /&gt;
An individual element of an array of type DbfStruct can be accessed&lt;br /&gt;
directly if it satisfies the criteria for accessing a DbfStruct.&lt;br /&gt;
&lt;br /&gt;
Question: Should database Access be implemented so that record/link support can transfer an array in segments. Examples:&lt;br /&gt;
* If the array is a circular buffer, it is presented in two segements&lt;br /&gt;
* If the array is stored in hardware, e.g. a transient recorder, the array can be read from the hardware and passed to the client in segments.&lt;br /&gt;
&lt;br /&gt;
If an array is available only in segments then can we&lt;br /&gt;
prevent two clients from trying to access the same array simultaneously?&lt;br /&gt;
&lt;br /&gt;
Perhaps this is a problem that must be solved by an application:&lt;br /&gt;
* runControl records are one solution&lt;br /&gt;
* Other solutions can be envisioned&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MDArray ==&lt;br /&gt;
&lt;br /&gt;
Not implemented if the early V4 releases.&lt;br /&gt;
&lt;br /&gt;
== Associated Data ==&lt;br /&gt;
&lt;br /&gt;
The typical example is a client that asks for timeStamp, severity, status,&lt;br /&gt;
and data.&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_dbdInterfaces&amp;diff=584</id>
		<title>V4 Design: dbdInterfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_dbdInterfaces&amp;diff=584"/>
		<updated>2005-10-04T15:02:43Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: dbdInterfaces - IOC Database Description October 04 2005 &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes  definitions for code that accessses&lt;br /&gt;
IOC records, i.e. the records created from Database Definitions:&lt;br /&gt;
menu, struct, record, link, device, and record instances.&lt;br /&gt;
&lt;br /&gt;
The interfaces support introspection of everything created from Database&lt;br /&gt;
Definitions. The interfaces can be used by tools such as VDCT or on&lt;br /&gt;
a running IOC database.&lt;br /&gt;
&lt;br /&gt;
The definitions can be used by code that use code automatically&lt;br /&gt;
generated from DBD files or by code that uses only introspection.&lt;br /&gt;
&lt;br /&gt;
Code is automatically generated from the following definitions:&lt;br /&gt;
* &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; - Used by record support.&lt;br /&gt;
* &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; - Used by code that understands the struct.&lt;br /&gt;
* &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt; - Used by code that understands the menu.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Syntax =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax is defined so that either C++ and Java implementations can be created.&lt;br /&gt;
&lt;br /&gt;
NOTE: Most of the code fragments use Java syntax.&lt;br /&gt;
&lt;br /&gt;
== Primitive Types ==&lt;br /&gt;
* octet - 8 bit byte&lt;br /&gt;
* boolean - a value that takes the values &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt;&lt;br /&gt;
* int16 - 16 bit signed integer&lt;br /&gt;
* int32 - 32 bit signed integer&lt;br /&gt;
* int64 - 64 bit signed integer&lt;br /&gt;
* float32 - 32 bit IEEE float&lt;br /&gt;
* float64 - 64 bit IEEE float&lt;br /&gt;
&lt;br /&gt;
In Java these types become:&lt;br /&gt;
&lt;br /&gt;
* octet =&amp;gt; byte  BUT no arithmetic is implied&lt;br /&gt;
* boolean =&amp;gt; boolean&lt;br /&gt;
* int16 =&amp;gt; short&lt;br /&gt;
* int32 =&amp;gt; int&lt;br /&gt;
* int64 =&amp;gt; long&lt;br /&gt;
* float32 =&amp;gt; float&lt;br /&gt;
* float64 =&amp;gt; double&lt;br /&gt;
&lt;br /&gt;
In C++ these types become:&lt;br /&gt;
&lt;br /&gt;
* octet =&amp;gt; char  BUT no arithmetic is implied&lt;br /&gt;
* boolean =&amp;gt; bool BUT no arithmetic or conversion to/from int is implied&lt;br /&gt;
* int16 =&amp;gt; int16_t&lt;br /&gt;
* int32 =&amp;gt; int32_t&lt;br /&gt;
* int64 =&amp;gt; int64_t&lt;br /&gt;
* float32 =&amp;gt; float&lt;br /&gt;
* float64 =&amp;gt; double&lt;br /&gt;
&lt;br /&gt;
NOTE:&lt;br /&gt;
* The C++ integer types are from C99 stdint.h&lt;br /&gt;
* Should exceptions be defined?&lt;br /&gt;
&lt;br /&gt;
== enum, struct, interface, class,  string, array ==&lt;br /&gt;
&lt;br /&gt;
In adition to the primitive types the syntax&lt;br /&gt;
uses the terms enum, struct, interface, and array.&lt;br /&gt;
&lt;br /&gt;
=== enum ===&lt;br /&gt;
&lt;br /&gt;
An example of an enum is:&lt;br /&gt;
&lt;br /&gt;
     enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The C++  definition is identical. In Java 5 the definition would be:&lt;br /&gt;
&lt;br /&gt;
     public enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
=== struct ===&lt;br /&gt;
An example of a struct definition is:&lt;br /&gt;
&lt;br /&gt;
     struct DisplayLimitData {&lt;br /&gt;
         float64 low;&lt;br /&gt;
         float64 high;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In C++ this would be:&lt;br /&gt;
&lt;br /&gt;
    class DisplayLimitData {&lt;br /&gt;
    public:&lt;br /&gt;
         double low;&lt;br /&gt;
         double high;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
In Java this would be:&lt;br /&gt;
&lt;br /&gt;
     class DisplayLimitData {&lt;br /&gt;
         public double low;&lt;br /&gt;
         public double high;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== interface ===&lt;br /&gt;
An example of an interface definition is:&lt;br /&gt;
&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void    put(boolean val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class DbfBoolean : public Dbf {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual bool get() = 0;&lt;br /&gt;
         virtual void put(bool val) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
In Java would be:&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void    put(boolean val)&lt;br /&gt;
     }&lt;br /&gt;
=== class ===&lt;br /&gt;
&lt;br /&gt;
Any class definitions are language specific.&lt;br /&gt;
&lt;br /&gt;
=== string ===&lt;br /&gt;
&lt;br /&gt;
For C++ a string will be a &amp;lt;tt&amp;gt;char *&amp;lt;/tt&amp;gt; array containing UTF-8&lt;br /&gt;
compatible characters not necessarily terminated with a null character.&lt;br /&gt;
Wherever a &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt; argument appears, the C++ definition&lt;br /&gt;
will have &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;char *&amp;lt;/tt&amp;gt; arguments.&lt;br /&gt;
&lt;br /&gt;
For Java string will just be a &amp;lt;tt&amp;gt;String&amp;lt;/tt&amp;gt;.&lt;br /&gt;
It is assumed that Java Strings will be converted to/from UTF-8 byte streams&lt;br /&gt;
when the data is transfered to/from the network.&lt;br /&gt;
&lt;br /&gt;
An example of a definition that includes a string argument is&lt;br /&gt;
     void get(String name);&lt;br /&gt;
&lt;br /&gt;
In C++  this will become&lt;br /&gt;
     void get(int lenName, char *name);&lt;br /&gt;
In Java this will become&lt;br /&gt;
     void get(String name);&lt;br /&gt;
=== array ===&lt;br /&gt;
&lt;br /&gt;
An example of a definition that includes an array is:&lt;br /&gt;
&lt;br /&gt;
     void get(float64[] data);&lt;br /&gt;
&lt;br /&gt;
In C++ ,this would become:&lt;br /&gt;
&lt;br /&gt;
     void get(int lenData, double data[]);&lt;br /&gt;
&lt;br /&gt;
In Java this would be:&lt;br /&gt;
&lt;br /&gt;
     void get(double[] data);&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= DbfTypes =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
The following naming conventions are used:&lt;br /&gt;
; Dbf&lt;br /&gt;
: any class starting with Dbf describes a field in a header file generated from a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definition. For example DbfArray describes a field generated from &amp;lt;tt&amp;gt;field(name,array(float64[])&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; Dbd&lt;br /&gt;
: A class name starting with Dbd describes something related to dbd definitions. For example DbdMenu describes a dbd menu definition.&lt;br /&gt;
&lt;br /&gt;
All Dbf and Dbd definitions are interfaces. Thus all access to data is via&lt;br /&gt;
interfaces.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbfTypes.h&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
The following &amp;lt;tt&amp;gt;enum&amp;lt;/tt&amp;gt; definitions describe &lt;br /&gt;
each field in the header files generated from DBD &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; and&lt;br /&gt;
&amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
&lt;br /&gt;
     enum BasicType {&lt;br /&gt;
         basicTypeOctet,    // DbfOctet&lt;br /&gt;
         basicTypeBoolean,  // DbfBoolean&lt;br /&gt;
         basicTypeInt16,    // DbfInt16&lt;br /&gt;
         basicTypeInt32,    // DbfInt32&lt;br /&gt;
         basicTypeInt64,    // DbfInt64&lt;br /&gt;
         basicTypeFloat32,  // DbfFloat32&lt;br /&gt;
         basicTypeFloat64,  // DbfFloat64&lt;br /&gt;
         basicTypeString,   // DbfString&lt;br /&gt;
         basicTypeArray,    // DbfArray&lt;br /&gt;
         basicTypeStruct,   // DbfStruct&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum DbfType {&lt;br /&gt;
         dbfTypeBasic,       // DbfOctet,...,DbfStruct&lt;br /&gt;
         dbfTypeMenu,        // DbfMenu&lt;br /&gt;
         dbfTypeEnum,        // DbfEnum&lt;br /&gt;
         dbfTypeLink,        // DbfLink&lt;br /&gt;
         dbfTypeMDArray,     // DbfMDArray&lt;br /&gt;
         dbfTypeTimeStamp    // DbfTimeStamp&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Discussion of DbfTypes ==&lt;br /&gt;
&lt;br /&gt;
The example code shown below uses Java syntax.&lt;br /&gt;
It assumes the following definitions:&lt;br /&gt;
&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,double)&lt;br /&gt;
         field(high,double)&lt;br /&gt;
     }&lt;br /&gt;
     record(Example) extends RecordCommon {&lt;br /&gt;
         ...&lt;br /&gt;
         field(octet,octet)&lt;br /&gt;
         field(fboolean,boolean)&lt;br /&gt;
         field(fint,int16)&lt;br /&gt;
         ...&lt;br /&gt;
         field(ffloat,float64)&lt;br /&gt;
         field(string,string)&lt;br /&gt;
         field(array,array(double[])&lt;br /&gt;
         field(mdarray,array(double[,])&lt;br /&gt;
         field(menu,menu(name))&lt;br /&gt;
         field(fenum,enum)&lt;br /&gt;
         //FOLLOWING IS NOT VALID LINK DEFINITION&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
From this the following Java code is automatically generated.&lt;br /&gt;
     public class DisplayLimit implements Struct{&lt;br /&gt;
         public DbfFloat64 low;&lt;br /&gt;
         public DbfFloat64 high;&lt;br /&gt;
         ...&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case lowIndex: return(low);&lt;br /&gt;
                 case highIndex: return(high);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
             return null;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     public class ExampleRecord implements Struct {&lt;br /&gt;
         public DbfOctet     ctet;&lt;br /&gt;
         public DbfBoolean   fboolean;&lt;br /&gt;
         public DbfInt16     fint;&lt;br /&gt;
         ...&lt;br /&gt;
         public DbfFloat64   ffloat;&lt;br /&gt;
         public DbfString    string;&lt;br /&gt;
         public DbfArray     array;&lt;br /&gt;
         public DbfMDArray   mdarray;&lt;br /&gt;
         public DbfMenu      menu;&lt;br /&gt;
         public DbfEnum      fenum;&lt;br /&gt;
         public DbfLink      link;&lt;br /&gt;
         public DbfStruct    displayLimit;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case fbooleanIndex : return(fboolean);&lt;br /&gt;
                 ...&lt;br /&gt;
                 case displayLimitIndex: return(displayLimit);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Similar code is generated for C++.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Database Fields =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each database field is accessed via an interface which all extend&lt;br /&gt;
the following interface:&lt;br /&gt;
&lt;br /&gt;
     interface Dbf{&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         boolean isPrimitive(); // BasicTypeBoolean,...,BasicTypeFloat64&lt;br /&gt;
         boolean isBasic();&lt;br /&gt;
         BasicType getBasicType();&lt;br /&gt;
         RecordInstance getRecord();&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The interfaces are designed so that a field can be accessded&lt;br /&gt;
without exposing the address of its data.&lt;br /&gt;
&lt;br /&gt;
== Primitive Types ==&lt;br /&gt;
&lt;br /&gt;
DbfOctet, ..., DbfFloat64 are all interfaces with methods get and put.&lt;br /&gt;
    &lt;br /&gt;
     interface DbfOctet extends Dbf {&lt;br /&gt;
         octet get();&lt;br /&gt;
         void put(octet val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void put(boolean val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt16 extends Dbf {&lt;br /&gt;
         int16 get();&lt;br /&gt;
         void put(int16 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt32 extends Dbf {&lt;br /&gt;
         int32 get();&lt;br /&gt;
         void put(int32 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt64 extends Dbf {&lt;br /&gt;
         int64 get();&lt;br /&gt;
         void put(int64 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfFloat32 extends Dbf {&lt;br /&gt;
         float32 get();&lt;br /&gt;
         void put(float32 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfFloat64 extends Dbf {&lt;br /&gt;
         float64 get();&lt;br /&gt;
         void put(float64 val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Record support code can access such fields via the generated header&lt;br /&gt;
file. Some examples are:&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     short myint;&lt;br /&gt;
     ...&lt;br /&gt;
     precord.ffloat.put(10.0);&lt;br /&gt;
     ...&lt;br /&gt;
     myint = precord.fint.get();&lt;br /&gt;
&lt;br /&gt;
Code that does not include the generated header file can access these fields&lt;br /&gt;
via the introspection interfaces described later in this document.&lt;br /&gt;
For example code that expects a float64 field can access it via&lt;br /&gt;
&lt;br /&gt;
     Dbf dbf =  RecordInstanceLocate.getField(&amp;quot;recordname.value&amp;quot;);&lt;br /&gt;
     if(dbf==null&lt;br /&gt;
     || !dbf.isPrimitive()&lt;br /&gt;
     || (dbf.getBasicType() != basicTypeFloat64) ) // do something&lt;br /&gt;
     DbfFloat64 dbfdouble = (DbfFloat64)dbf;&lt;br /&gt;
     dbfdouble.put(10.0);&lt;br /&gt;
&lt;br /&gt;
or more concisely (but exception may be thrown)&lt;br /&gt;
     DbfConvertPrimitive(RecordInstanceLocate.getField(&amp;quot;recordname.value&amp;quot;),10.0);&lt;br /&gt;
&lt;br /&gt;
== String fields ==&lt;br /&gt;
&lt;br /&gt;
The interface for a string field is:&lt;br /&gt;
&lt;br /&gt;
     interface DbfString extends Dbf {&lt;br /&gt;
        int32 getLength();&lt;br /&gt;
        void get(string value);&lt;br /&gt;
        void setPutSize(int32 size);&lt;br /&gt;
        void put(string value);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following code prints a string.&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     String string;&lt;br /&gt;
     record.fstring.get(string);&lt;br /&gt;
     printf(&amp;quot;%s\n&amp;quot;,string);&lt;br /&gt;
&lt;br /&gt;
Code that does not include the header file can use the introspection methods&lt;br /&gt;
to locate the DbfString that provides access to the field.&lt;br /&gt;
&lt;br /&gt;
== Structure Fields ==&lt;br /&gt;
&lt;br /&gt;
     interface DbfStruct extends Dbf {&lt;br /&gt;
         int16 getNfields();&lt;br /&gt;
         Dbf getInterface(int16 index);&lt;br /&gt;
         DbdField getDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following traverses the fields of a DbfStruct&lt;br /&gt;
&lt;br /&gt;
     DbfStruct dbfStruct;&lt;br /&gt;
     &lt;br /&gt;
     for(i=0; i &amp;lt; dbfStruct.getNfields(); i++) {&lt;br /&gt;
         DbdField dbdField = dbfStruct.getDescription(i);&lt;br /&gt;
         String name;&lt;br /&gt;
         dbdField.getName(name);&lt;br /&gt;
         printf(&amp;quot;field %s\n&amp;quot;,name);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Structure fields can only be accessed via introspection.&lt;br /&gt;
However, for each structure, code is generated that does the introspection.&lt;br /&gt;
For example DisplayLimitData can be obtained via the statements:&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     DisplayLimitData limit = new DisplayLimitData();&lt;br /&gt;
     &lt;br /&gt;
     ...&lt;br /&gt;
     DisplayLimitSupport.get(record.displayLimit,limit);&lt;br /&gt;
     printf(&amp;quot;low %f high %f\n&amp;quot;,limit.low,limit.high);&lt;br /&gt;
&lt;br /&gt;
== Array Fields ==&lt;br /&gt;
&lt;br /&gt;
The generated header file will have a type that extends &amp;lt;tt&amp;gt;DbfArray&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     interface DbfArray extends Dbf {&lt;br /&gt;
        DbfType getType();&lt;br /&gt;
        int32 getNelements();&lt;br /&gt;
        void setNelements(int32 len);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfBooleanArray extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, boolean[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, boolean[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfOctetArray extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, octet[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, octet[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt16Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int16[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int16[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt32Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int32[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int32[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt64Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int64[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int64[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfFloat32Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, float32[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, float32[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfFloat64Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, float64[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, float64[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfStringArray extends DbfArray {&lt;br /&gt;
         DbfString getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfArrayArray extends DbfArray {&lt;br /&gt;
         DbfArray getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfStructArray extends DbfArray {&lt;br /&gt;
         DbfStruct getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfMenuArray extends DbfArray {&lt;br /&gt;
         DbfMenu getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfEnumArray extends DbfArray {&lt;br /&gt;
         DbfEnum getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfLinkArray extends DbfArray {&lt;br /&gt;
         DbfLink getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following puts data into a float64 field.&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
&lt;br /&gt;
     double[] data = new double[] {1.0,2.0,3.0};;&lt;br /&gt;
     if(!record.ffloat.isPrimitive()&lt;br /&gt;
     || record.ffloat.getBasicType()!=basicTypeFloat64)  // DO SOMTHING!!!!&lt;br /&gt;
     ...&lt;br /&gt;
     array.put(0,nelements,precord-&amp;gt;data);&lt;br /&gt;
&lt;br /&gt;
or more concisely&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     ...&lt;br /&gt;
     DbfConvertPrimitive.put(precord.array,new double[] {1.0,2.0,3.0});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfMDArray ==&lt;br /&gt;
NOT YET DEFINED&lt;br /&gt;
     &lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; is described as:&lt;br /&gt;
     interface DbfMenu extends Dbf {&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
         void putIndex(int16 val);&lt;br /&gt;
         DbdMenu getDbdMenu();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; allows the menu index to be set and retrieved&lt;br /&gt;
and also provides access to the DbdMenu.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; field can be accessed via the generated header file or via&lt;br /&gt;
the introspection methods.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfEnum ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfEnum&amp;lt;/tt&amp;gt; is described as:&lt;br /&gt;
     interface DbfEnum extends Dbf {&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
         void putIndex(int16 val);&lt;br /&gt;
         DbfStringArray getChoiceArray();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfEnum&amp;lt;/tt&amp;gt; allows the enum index to be set and retrieved&lt;br /&gt;
and also provides access to the The DbfArray field that contains the choices.&lt;br /&gt;
&lt;br /&gt;
== DbfLink and DbfDevice ==&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;tt&amp;gt;DbfLink&amp;lt;/tt&amp;gt; is described as&lt;br /&gt;
 &lt;br /&gt;
     enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfLink extends Dbf {&lt;br /&gt;
         LinkDir getDir();&lt;br /&gt;
         DbdLink getDbdLink();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== DbfTimeStamp ==&lt;br /&gt;
&lt;br /&gt;
     struct TimeStamp {&lt;br /&gt;
         int64 secondsSinceEpoch;&lt;br /&gt;
         int32 nanoSeconds;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfTimeStamp extends Dbf {&lt;br /&gt;
         void get(TimeStamp timeStamp);&lt;br /&gt;
         void put(TimeStamp timeStamp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= DbdStatements =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
These describe everything defined in database definition files.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdMenu&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdMenu {&lt;br /&gt;
         int32 getNameLength(&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         int16 getNchoices();&lt;br /&gt;
         int32 getChoiceNameLength(int16 index);&lt;br /&gt;
         void getChoice(int16 index,String choice);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdLink&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdLink {&lt;br /&gt;
         LinkDir getDir();&lt;br /&gt;
         int32 getChoiceNameLength();&lt;br /&gt;
         void getChoiceName(String name);&lt;br /&gt;
         int32 getInterfaceNameLength();&lt;br /&gt;
         void getInterfaceName(String name);&lt;br /&gt;
         int32 getDataStructNameLength();&lt;br /&gt;
         void getDataStructName(String name);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdStruct&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;DbdRecord&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdAttribute {&lt;br /&gt;
         int32 getDefaultLength();&lt;br /&gt;
         void getDefault(String value);&lt;br /&gt;
         boolean isReadonly();&lt;br /&gt;
         boolean isDesign();&lt;br /&gt;
         boolean isSpecial();&lt;br /&gt;
         int16 getAsl();&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbdDefaults {}&lt;br /&gt;
    &lt;br /&gt;
     interface DbdArrayDefaults extends DbdDefaults{&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         int32 getLength();&lt;br /&gt;
&lt;br /&gt;
     interface DbdStructDefaults extends DbdDefaults{&lt;br /&gt;
         DbdStruct getDescription();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdField {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         DbdDefaults getDefaults();&lt;br /&gt;
         DbdAttribute getAttributes();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdStruct {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         int16 getNumberFields();&lt;br /&gt;
         DbdField getFieldDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdRecord {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         int16 getNumberFields();&lt;br /&gt;
         DbdField getFieldDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Record Instance ==&lt;br /&gt;
&lt;br /&gt;
     interface RecordInstance {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         DbdRecord getDescription();&lt;br /&gt;
         DbdRecord getRecordCommonDescription();&lt;br /&gt;
         DbfStruct getInstance();&lt;br /&gt;
         DbfStruct getRecordCommonInstance();&lt;br /&gt;
         Dbf getField(String fieldName);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;getNameLength&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get length of record name&lt;br /&gt;
; &amp;lt;tt&amp;gt;getName&lt;br /&gt;
: get the record name&lt;br /&gt;
; &amp;lt;tt&amp;gt;getDescription&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the description of the record specific portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getRecordCommonDescription&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the description of RecordCommon&lt;br /&gt;
; &amp;lt;tt&amp;gt;getInstance&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get instance for the record specific portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getRecordCommonInstance&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get instance for for RecordCommon portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getField&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get field instance. Workd for both record specific or RecordCommon field&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Locate Interfaces =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Classes are available to find and traverse the various Dbd definitons&lt;br /&gt;
and record instances.&lt;br /&gt;
The implementation will be language specific. For Java they will be something&lt;br /&gt;
like the following:&lt;br /&gt;
&lt;br /&gt;
In addition the following is defined:&lt;br /&gt;
&lt;br /&gt;
     public class DbdLocate {&lt;br /&gt;
         public DbdMenu getMenu(String name);&lt;br /&gt;
         public DbdLink getLink(String name);&lt;br /&gt;
         public DbdStruct getStruct(String name);&lt;br /&gt;
         public DbdRecord getRecord(String name);&lt;br /&gt;
         public LinkedList&amp;lt;DbdMenu&amp;gt; menuList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdLink&amp;gt; linkList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdStruct&amp;gt; structList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdRecord&amp;gt; recordList;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public class RecordInstanceLocate {&lt;br /&gt;
         public RecordInstance getRecord(String name);&lt;br /&gt;
         public Dbf getField(String name);&lt;br /&gt;
         public Dbf getField(String recordName, String fieldName);&lt;br /&gt;
         public LinkedList&amp;lt;RecordInstance&amp;gt; instanceList;&lt;br /&gt;
         public LinkedList&amp;lt;RecordInstance&amp;gt; instanceList(String recordTypeName);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; Are the above methods static or should there be something like&lt;br /&gt;
     public class FindLocator {&lt;br /&gt;
         public static DbdLocate findDbdLocate();&lt;br /&gt;
         public static RecordInstance findRecordInstance();&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
The following locates a specific menu.&lt;br /&gt;
&lt;br /&gt;
     DbdMenu menu = DbdLocate.get(&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
     if(menu!=null) printf(&amp;quot;found menu %s\n&amp;quot;,&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
The following locates a field of a record instance.&lt;br /&gt;
&lt;br /&gt;
     Dbf field = RecordInstanceLocate.getField(&amp;quot;example.value&amp;quot;);&lt;br /&gt;
     if(addr!=null) printf(&amp;quot;found %s\n&amp;quot;,&amp;quot;example.value&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=563</id>
		<title>V4 Link Support Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=563"/>
		<updated>2005-10-04T15:00:44Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Link Support Tutorial Oct 04 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
The V4 link support is a replacement for V3 &lt;br /&gt;
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK&lt;br /&gt;
# device DBD definition and device support&lt;br /&gt;
# driver DBD definition and driver support&lt;br /&gt;
&lt;br /&gt;
The link support model is:&lt;br /&gt;
* For each link, record support defines a list of interfaces it can use for communicating with link support&lt;br /&gt;
* Link support defines the set of interfaces it implements&lt;br /&gt;
&lt;br /&gt;
Link support has no knowledge of what record types are using it&lt;br /&gt;
and record support has no knowledge about link support other than the&lt;br /&gt;
interface it is using.&lt;br /&gt;
&lt;br /&gt;
EPICS base defines a standard set of interfaces for link support.&lt;br /&gt;
The intention is that the set includes enough functionality such that&lt;br /&gt;
most link support can be implemented via just these interfaces.&lt;br /&gt;
&lt;br /&gt;
The interfaces support all the functionality needed by Channel/Database access&lt;br /&gt;
and by the generic EPICS device support supplied by asynDriver.&lt;br /&gt;
Since asynDriver is intended as a framework for interfacing to most hardware,&lt;br /&gt;
this means that the interfaces supplied and used by base allows support&lt;br /&gt;
for most hardware. The support can communicate with the hardware&lt;br /&gt;
however it wants but must implement some set of the interfaces defined&lt;br /&gt;
by base.&lt;br /&gt;
&lt;br /&gt;
This document gives a brief overview of the V4 link support model.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Database Definitions For Links =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section first reviews the DBD syntax related to link definitions.&lt;br /&gt;
It then gives a brief description of link related definitions in dbCommon.dbd&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
A record link has the syntax:&lt;br /&gt;
     link(linkDirection,interface(interfaceName,...))&lt;br /&gt;
A link itself has the syntax:&lt;br /&gt;
     link(linkDirection,choiceName,dataStructName,interface(interfaceName,...))&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;linkDirection&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be one of &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. Compatible checks are made to match the interface with a field.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interface&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is a list of the interfaces that the record support understands.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of an interface via which record support communicates with device support.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools do prompt the user to assign values to the structure.&lt;br /&gt;
&lt;br /&gt;
When a record instance is created the choiceName and interfaceName select&lt;br /&gt;
the support to attach to a record link.&lt;br /&gt;
The interfaceName must be one of the interface names the record&lt;br /&gt;
has listed as a valid type and linkDirection must be compatible&lt;br /&gt;
with the linkDirection the record type specified.&lt;br /&gt;
&lt;br /&gt;
== Standard Definitions For Channel/Database Access ==&lt;br /&gt;
&lt;br /&gt;
These are the database definitions defined in dbCommon are used by&lt;br /&gt;
the base supplied support for Channel/Database access.&lt;br /&gt;
&lt;br /&gt;
=== Data Structures ===&lt;br /&gt;
&lt;br /&gt;
The complete set of definitions are defined in &amp;quot;V4 DB RecordCommon&amp;quot;.&lt;br /&gt;
     struct(MonitorLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(InputLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     ... also OutputLinkData and ProcessLinkData&lt;br /&gt;
&lt;br /&gt;
A look at the fields shows that these are what is required to implement&lt;br /&gt;
the V4 semantics for Channel/Database access links.&lt;br /&gt;
&lt;br /&gt;
=== Link Definitions ===&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* input&lt;br /&gt;
** monitor support&lt;br /&gt;
** input support&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For input and output The following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
&amp;quot;V4 DB RecordCommon&amp;quot; describes the complete set of link definitions&lt;br /&gt;
supplied by EPICS base. These are:&lt;br /&gt;
&lt;br /&gt;
     link(process,processLink,ProcessLinkData,interface(ProcessLink))&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLink,MonitorLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,monitorLinkArray,MonitorLinkData interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLink,InputLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLinkArray,InputLinkData interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,outputLink,OutputLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,outputLinkArray,OutputLinkData interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
&lt;br /&gt;
These are the link definitions for the Channel/Database access link&lt;br /&gt;
support supplied with base. The support registers support for processLink,&lt;br /&gt;
monitorLinkArrayOctet, ...&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
&lt;br /&gt;
These are definitions that are used by the standard EPICS device support&lt;br /&gt;
for asynDriver. Since asynDriver is a generic way of interfacing arbitrary&lt;br /&gt;
hardware support, this is a generic way of attaching links in records to&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLinkData) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link definitions ===&lt;br /&gt;
&lt;br /&gt;
     link(inout,asynInt32,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Average,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Monitor,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(inout,asynFloat64,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Average,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Monitor,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynDigitalMonitor,AsynLinkData,interface(AsynDigital))&lt;br /&gt;
     link(inout,asynDigital,AsynLinkData,interface(AsynDigital)))&lt;br /&gt;
     link(inout,asynInt32Array,AsynLinkData,interface(LinkArrayInt32)))&lt;br /&gt;
     link(inout,asynFloat64Array,AsynLinkData,interface(LinkArrayFloat64)))&lt;br /&gt;
     link(inout,asynOctet,AsynLinkData,interface(AsynOctet)))&lt;br /&gt;
&lt;br /&gt;
This is the set of definitions for the standard EPICS device support implemented&lt;br /&gt;
by asynDriver. Although, at least for the first few V4 releases,&lt;br /&gt;
asynDriver will not be part of base, they are shown here because the&lt;br /&gt;
LinkInt32,... interface definitions are defined as part of base.&lt;br /&gt;
Again it is expected that almost all hardware support be created by&lt;br /&gt;
implementing a combination of these link interface definitions or&lt;br /&gt;
the interfaces implemented by Channel/Database access link support.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
An arbitrary number of Link Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
Other link support can also be supplied.&lt;br /&gt;
New support should try very hard to implement the standard interfaces&lt;br /&gt;
supplied by EPICS base. These are the interfaces that the record types&lt;br /&gt;
supplied with base know how to use.&lt;br /&gt;
&lt;br /&gt;
Soft support should try to implement the same interfaces implemented by&lt;br /&gt;
the Channel/Database access support supplied with base. The support&lt;br /&gt;
can, of course, define data structures for it's own use.&lt;br /&gt;
Implementing these interfaces means that nthe support will work for&lt;br /&gt;
the same set of record links as the Channel/Database access support.&lt;br /&gt;
&lt;br /&gt;
Hardware support should, if possible, also implement the same interfaces&lt;br /&gt;
implemented by the Channel/Database access support.&lt;br /&gt;
Message based support may also have to implement the AsynOctet interface&lt;br /&gt;
but this interface is only used by a few record links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This section describes the interfaces implemented by all link support&lt;br /&gt;
and then the standard interfaces used by the records supplied with base.&lt;br /&gt;
&lt;br /&gt;
== Link and MonitorLink ==&lt;br /&gt;
&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; is an interface that is implemented by link support that&lt;br /&gt;
supports monitors. An example is support for hardware interrupts.&lt;br /&gt;
The &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally record support does not need to call any of the Link &lt;br /&gt;
or MonitorLink methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call destroy before modifying the link&lt;br /&gt;
and initialize and connect after the link is modified.&lt;br /&gt;
&lt;br /&gt;
Neither Link or MonitorLink is listed in the &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; database&lt;br /&gt;
definition.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
These are the definitions used by the Channel/Database access support&lt;br /&gt;
supplied with base. It is also used by the standard EPICS support from asyn.&lt;br /&gt;
&lt;br /&gt;
     enum LinkWaitResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
         linkWaitBlock,      // waiting. dont do additional processing until&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface LinkProcess&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
There is no support for octet but there is support for an array of octets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkWaitResult getWait(octet[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(octet[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The data source must be an array of octets or the connect request will fail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;GENERIC QUESTION&amp;lt;/b&amp;gt; The data is passed as primitive or arrays of&lt;br /&gt;
primitive types. Should &amp;lt;tt&amp;gt;Dbf&amp;lt;/tt&amp;gt; interfaces be used? Needs thought.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkWaitResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkWaitResult write(octet[] value, octet[] mask);&lt;br /&gt;
          LinkWaitResult read(octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkWaitResult getWait(Boolean data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(boolean data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkWaitResult getWait(boolean[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(boolean[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be int16, int32, or int64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         void getBounds(&amp;lt;type&amp;gt; low, &amp;lt;type&amp;gt; high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     } &lt;br /&gt;
         &lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be float32 or float64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkWaitResult getWait(string data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(string data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkWaitResult getWait(string[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(string[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Example - VME ADC support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
== database definitions ==&lt;br /&gt;
The following struct is defined for configuration information.&lt;br /&gt;
     struct VMEADC {&lt;br /&gt;
         field(a16 int16)&lt;br /&gt;
         field(a32 int32)&lt;br /&gt;
         field(channel int16)&lt;br /&gt;
     }&lt;br /&gt;
The following link definition is defined:&lt;br /&gt;
     link(in,myAdcSupport,VMEADCinterface(LinkInt32))&lt;br /&gt;
&lt;br /&gt;
This allows record instance definitions like:&lt;br /&gt;
     AiRecord aiExample = {&lt;br /&gt;
        ...&lt;br /&gt;
        input = myAdcSupport(LinkInt32){a16=0x0010;channel=1}&lt;br /&gt;
        ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== link support implementation ==&lt;br /&gt;
The following is presented with Java syntax.&lt;br /&gt;
It assumes that there is VME support of the form&lt;br /&gt;
&lt;br /&gt;
public class VME {&lt;br /&gt;
    static public short getShort(long addr);&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
The link support would be something like:&lt;br /&gt;
&lt;br /&gt;
     class AdcSupport implements Link LinkInt32 {&lt;br /&gt;
     AdcSupport(VMEADCData fromFactory)&lt;br /&gt;
     {&lt;br /&gt;
         data = fromFactory;&lt;br /&gt;
         connected = false;&lt;br /&gt;
         //  from the VMEADC initailze vmeaddr and channel&lt;br /&gt;
         // details left to your imagination&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Link methods&lt;br /&gt;
     void report(int16_t level)&lt;br /&gt;
     {&lt;br /&gt;
         printf(&amp;quot;AdcSupport a16 %x channel %d\n&amp;quot;,a16,channel);&lt;br /&gt;
     }&lt;br /&gt;
     void cancel() {} // nothing to do&lt;br /&gt;
     void destroy() {} //nothing to do&lt;br /&gt;
     void initialize()&lt;br /&gt;
     {&lt;br /&gt;
         // make sure we can access a16&lt;br /&gt;
     }&lt;br /&gt;
     void connect() {connected = true}&lt;br /&gt;
     void disconnect() {connected = false}&lt;br /&gt;
     &lt;br /&gt;
     // LinkInt32 methods&lt;br /&gt;
     LinkWaitResult getWait(Int data,Callback callback)&lt;br /&gt;
     {&lt;br /&gt;
         data = (Int)VME.getShort(vmeaddr);&lt;br /&gt;
         return linkDone;&lt;br /&gt;
     }&lt;br /&gt;
     LinkWaitResult putWait(Int data,Callback callback)&lt;br /&gt;
     {&lt;br /&gt;
         throw CantWriteAdc;&lt;br /&gt;
     }&lt;br /&gt;
     void getBounds(Int low, Int high) &lt;br /&gt;
     {&lt;br /&gt;
         // assume 16 bit unipolor adc&lt;br /&gt;
         low = 0; high = 0xffff;&lt;br /&gt;
     }&lt;br /&gt;
     private:&lt;br /&gt;
         VMEADCData data;&lt;br /&gt;
         int vmeaddr;&lt;br /&gt;
         int channel;&lt;br /&gt;
         boolean connected;&lt;br /&gt;
     }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Runtime_Interfaces&amp;diff=586</id>
		<title>V4 Design: Runtime Interfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Runtime_Interfaces&amp;diff=586"/>
		<updated>2005-10-04T14:58:49Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: DbInstance =&amp;gt; RecordInstance; new state for process&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Runtime Interfaces Oct 04 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes  definitions for IOC runtime,&lt;br /&gt;
i.e. interfaces implemented or used by database access, record support,&lt;br /&gt;
link support, and device support.&lt;br /&gt;
&lt;br /&gt;
It assumes knowledge of the interfaces described in dbdInterfaces.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; IOC runtime needs lots more work&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Support Code =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section described interfaces for&lt;br /&gt;
strings, arrays, and conversions. &lt;br /&gt;
They are intended for use by Database Access, Record Support, etc.&lt;br /&gt;
&lt;br /&gt;
== C++ support for strings ==&lt;br /&gt;
&lt;br /&gt;
For most strings all the database  needs is a nonmutable string.&lt;br /&gt;
For these it wants to be able to pass a reference to it to arbitrary code.&lt;br /&gt;
It needs this for things like record type names, field names, record instance names, menu choice names, etc. etc. Some of these may change but very infrequently.&lt;br /&gt;
The string always contains UTF-8 encoded strings, which I believe can  be printed with a &amp;quot;%s&amp;quot; format if&lt;br /&gt;
the string is made available as a &amp;quot;const char *&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Perhaps the only type of  string connected with an IOC record that changes frequently is a field in a record type like stringin and stringout. In this case the record support can do what ever it wants to handle the string. It can even just use C style strings!!!&lt;br /&gt;
&lt;br /&gt;
Thus all the IOC database needs is a:&lt;br /&gt;
&lt;br /&gt;
1) nonmutable reference counted continguous string. When the reference count goes to 0 the storage can be reclaimed&lt;br /&gt;
2) The ability to copy the value from a nonmutable string to a mutable string.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In Java String and StringBuffer are all that is needed.&lt;br /&gt;
&lt;br /&gt;
In C++ all that is needed is&lt;br /&gt;
&lt;br /&gt;
1) A class that holds UFT-8 encoded non-mutable strings and make the contents available as a &amp;quot;const char *&amp;quot; and it's length. The class keeps a reference count and frees the storage when done.&lt;br /&gt;
2) The ability to copy the nonmutable string to a &amp;quot;char *&amp;quot; array allocated by the requester.&lt;br /&gt;
&lt;br /&gt;
That is all.&lt;br /&gt;
&lt;br /&gt;
== array copy ==&lt;br /&gt;
&lt;br /&gt;
ArrayCopy copies arrays an array performing conversions if necessary.&lt;br /&gt;
&lt;br /&gt;
     interface ArrayCopy {&lt;br /&gt;
         void copy(DbfArray from,DbfArray to);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
This only supports primitive types, i.e. DbfBoolean,...,DbfFloat64.&lt;br /&gt;
It does NOT convert between&lt;br /&gt;
* DbfBoolean and another type.&lt;br /&gt;
* DbfOctet and another type.&lt;br /&gt;
Thus for DbfBoolean and DbfOctet it is willing to copy&lt;br /&gt;
but not convert to/from other types.&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Conversions ==&lt;br /&gt;
This is a static class that converts between primitie types and arrays of primitive types.&lt;br /&gt;
&lt;br /&gt;
     static class DbfConvertPrimitive {&lt;br /&gt;
     public:&lt;br /&gt;
          int16 get(Dbf from);&lt;br /&gt;
          int32 get(Dbf from);&lt;br /&gt;
          int64 get(Dbf from);&lt;br /&gt;
          float32 get(Dbf from);&lt;br /&gt;
          float64 get(Dbf from);&lt;br /&gt;
          get(Dbf from, String value);&lt;br /&gt;
          get(DbfOctet from, String value);&lt;br /&gt;
          get(DbfBoolean from, String value);&lt;br /&gt;
          put(Dbf to, int16 value);&lt;br /&gt;
          put(Dbf to, int32 value);&lt;br /&gt;
          put(Dbf to, int64 value);&lt;br /&gt;
          put(Dbf to, float32 value);&lt;br /&gt;
          put(Dbf to, float64 value);&lt;br /&gt;
          put(Dbf to,int32 String value);&lt;br /&gt;
          put(DbfOctet to, String value);&lt;br /&gt;
          put(DbfBoolean to, String value);&lt;br /&gt;
&lt;br /&gt;
          get(DbfArray from, int16[] value);&lt;br /&gt;
          get(DbfArray from, int32[] value);&lt;br /&gt;
          get(DbfArray from, int64[] value);&lt;br /&gt;
          get(DbfArray from, float32[] value);&lt;br /&gt;
          get(DbfArray from, float64[] value);&lt;br /&gt;
          put(DbfArray to, int16[] value);&lt;br /&gt;
          put(DbfArray to, int32[] value);&lt;br /&gt;
          put(DbfArray to, int64[] value);&lt;br /&gt;
          put(DbfArray to, float32[] value);&lt;br /&gt;
          put(DbfArray to, float64[] value);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* For Dbf &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; must be one of &amp;lt;tt&amp;gt;DbfInt16&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;DbfFloat64&amp;lt;/tt&amp;gt;&lt;br /&gt;
* The get to a string implements printf semantics&lt;br /&gt;
* The put from a string value just scanf semantics.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;DbfOctet&amp;lt;/tt&amp;gt; methods convert to/from a string of the form &amp;quot;0xXX&amp;quot;&lt;br /&gt;
* The &amp;lt;tt&amp;gt;DbfBoolean&amp;lt;/tt&amp;gt; get method supports all the choices specified in the DBD Record Instance Specification&lt;br /&gt;
* For DbfArray &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; must be an array of one of &amp;lt;tt&amp;gt;DbfInt16&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;DbfFloat64&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code generated from Database Definition Files =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following shows the Java code generated from DBD files:&lt;br /&gt;
&lt;br /&gt;
== structure definitions ==&lt;br /&gt;
&lt;br /&gt;
Two files are generated from &amp;lt;tt&amp;gt;struct(name)&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
# &amp;lt;tt&amp;gt;name.java&amp;lt;/tt&amp;gt;&lt;br /&gt;
# &amp;lt;tt&amp;gt;nameSupport.java&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;name.java&amp;lt;/tt&amp;gt; implements:&lt;br /&gt;
     interface Struct {&lt;br /&gt;
         Dbf getField(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a structure is defined as:&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,double)&lt;br /&gt;
         field(high,double)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
A generated file &amp;lt;tt&amp;gt;DisplayLimit.java&amp;lt;/tt&amp;gt; contains:&lt;br /&gt;
&lt;br /&gt;
     public class DisplayLimit implements Struct{&lt;br /&gt;
         public DbfFloat64 low;&lt;br /&gt;
         public DbfFloat64 high;&lt;br /&gt;
         public static final short lowIndex = 1;&lt;br /&gt;
         public static final short highIndex = 2;&lt;br /&gt;
         public static final short lastIndex = indexHigh;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case lowIndex: return(low);&lt;br /&gt;
                 case highIndex: return(high);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
             return null;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
A generated file &amp;lt;tt&amp;gt;DisplayLimitAccess.java&amp;lt;/tt&amp;gt; contains:&lt;br /&gt;
&lt;br /&gt;
     public class DisplayLimitData {&lt;br /&gt;
         public double low;&lt;br /&gt;
         public double high;&lt;br /&gt;
     }&lt;br /&gt;
     public final class DisplayLimitAccess implements StructFactory{&lt;br /&gt;
         public Struct create() { return new DisplayLimit; }&lt;br /&gt;
         public static final void get(DbfStruct from,DisplayLimitData data) {&lt;br /&gt;
             DbfFloat64 dbf = from.getInterface(1);&lt;br /&gt;
             data.low = dbf.get();&lt;br /&gt;
             DbfFloat64 dbf = from.getInterface(2);&lt;br /&gt;
             data.high = dbf.get();&lt;br /&gt;
         }&lt;br /&gt;
         public static final void put(DbfStruct to, DisplayLimitData data) {&lt;br /&gt;
             DbfFloat64 dbf = to.getInterface(1);&lt;br /&gt;
             dbf.put(data.low);&lt;br /&gt;
             DbfFloat64 dbf = to.getInterface(2);&lt;br /&gt;
             dbf.put(data.high);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class DisplayLimitAccessRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             DisplayLimitAccess access = new DisplayLimitAccess;&lt;br /&gt;
             RegisterSupport.structure(access,&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTES&amp;lt;/b&amp;gt;&lt;br /&gt;
* The V4 replacement for registerRecordDeviceDriver must call DisplayLimitAccessRegister.createAndRegister.&lt;br /&gt;
* For non primitive fields the generated field is the Dbf type for the field.&lt;br /&gt;
&lt;br /&gt;
Similar files are generated for C++.&lt;br /&gt;
&lt;br /&gt;
== record definitions ==&lt;br /&gt;
If a record is defined as:&lt;br /&gt;
     record(Example) extends RecordCommon {&lt;br /&gt;
         ...&lt;br /&gt;
         field(fboolean,boolean)&lt;br /&gt;
         field(octet,octet)&lt;br /&gt;
         field(fint,int16)&lt;br /&gt;
         ...&lt;br /&gt;
         field(ffloat,float64)&lt;br /&gt;
         field(string,string)&lt;br /&gt;
         field(array,array(double[])&lt;br /&gt;
         field(mdarray,array(double[,])&lt;br /&gt;
         field(menu,menu(name))&lt;br /&gt;
         field(fenum,enum)&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(device,link(in,analogIO))&lt;br /&gt;
         field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The generated Java file is&lt;br /&gt;
&lt;br /&gt;
     public class ExampleRecord implements Struct {&lt;br /&gt;
         public DbfBoolean   fboolean;&lt;br /&gt;
         public DbfOctet     ctet;&lt;br /&gt;
         public DbfInt16     fint;&lt;br /&gt;
         ...&lt;br /&gt;
         public DbfFloat64   ffloat;&lt;br /&gt;
         public DbfString    string;&lt;br /&gt;
         public DbfArray     array;&lt;br /&gt;
         public DbfMDArray   mdarray;&lt;br /&gt;
         public DbfMenu      menu;&lt;br /&gt;
         public DbfEnum      fenum;&lt;br /&gt;
         public DbfLink      link;&lt;br /&gt;
         public DbfDevice    device;&lt;br /&gt;
         public DbfStruct    displayLimit;&lt;br /&gt;
         public static final int16 fbooleanIndex = 1;&lt;br /&gt;
         ...&lt;br /&gt;
         public static final int16 lastIndex = displayLimitIndex;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case fbooleanIndex : return(fboolean);&lt;br /&gt;
                 ...&lt;br /&gt;
                 case displayLimitIndex: return(displayLimit);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class ExampleRecordFactory implements StructFactory{&lt;br /&gt;
         public static final Struct create() { return new ExampleRecord; }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class ExampleRecordFactoryRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             ExampleRecordFactory  factory = new ExampleRecordFactory;&lt;br /&gt;
             RegisterSupport.record(factory,&amp;quot;ExampleRecord&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; The V4 replacement for registerRecordDeviceDriver must&lt;br /&gt;
call ExampleRecordFactoryRegister.createAndRegister&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar code is generated for C++.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Record Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     enum ProcessState {&lt;br /&gt;
         processCancel,&lt;br /&gt;
         processStart,&lt;br /&gt;
         processContinue,&lt;br /&gt;
         processFinish,&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum ProcessReturn {&lt;br /&gt;
         processDone,&lt;br /&gt;
         processAbort,&lt;br /&gt;
         processActive&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RecordSupport {&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize(int32 pass);&lt;br /&gt;
         ProcessState process(ProcessState state,Callback done);&lt;br /&gt;
         // if special returns false when after is false put fails&lt;br /&gt;
         boolean special(boolean after,Dbf[] field);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ProcessState&amp;lt;/tt&amp;gt; supports the following semantics:&lt;br /&gt;
* cancel - If the record is active terminate &lt;br /&gt;
* For all other states see the companion document &amp;quot;V4 Design: Record Processing&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The methods of &amp;lt;tt&amp;gt;RecordSupport&amp;lt;/tt&amp;gt; are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - Called when a record instance is deleted.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called twice (pass = 0,1) when a record is initialized.&lt;br /&gt;
* &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; - Called to process a record. See &amp;quot;V4 Design: Record Processing&amp;quot; for semantics.&lt;br /&gt;
* &amp;lt;tt&amp;gt;special&amp;lt;/tt&amp;gt; - Called when a field declared special in a DBD file is modified. &amp;lt;tt&amp;gt;field&amp;lt;/tt&amp;gt; is an array of Dbfs showing which field is being modified.&lt;br /&gt;
&lt;br /&gt;
== Discussion of special ==&lt;br /&gt;
&lt;br /&gt;
Special is passed a Dbf array that identifies the field being modified.&lt;br /&gt;
For example &amp;lt;tt&amp;gt;ExampleRecord.dbd&amp;lt;/tt&amp;gt; has a field:&lt;br /&gt;
     field(displayLimit,struct(displayLimit))&lt;br /&gt;
&amp;lt;tt&amp;gt;ExampleRecordSupport.java&amp;lt;/tt&amp;gt; might implement special as follows:&lt;br /&gt;
     boolean special(boolean after, Dbf[] field)&lt;br /&gt;
     {&lt;br /&gt;
         switch(field[0].getIndex()) {&lt;br /&gt;
         ...&lt;br /&gt;
         case ExampleRecord.displayLimitIndex:&lt;br /&gt;
             if(field.length==1) {&lt;br /&gt;
                 // displayLimits itself is being modified. Do something&lt;br /&gt;
             } else {&lt;br /&gt;
                // a field of displayLimits is being modified&lt;br /&gt;
                 switch(field[1].getIndex) {&lt;br /&gt;
                     case DisplayLimit.lowIndex:&lt;br /&gt;
                          // low being modified. do something&lt;br /&gt;
                     case DisplayLimit.highIndex:&lt;br /&gt;
                          // high being modified. do something&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         ...&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An arbitrary number of Link Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
EPICS base supplies support that accesses data via channel access, i.e.&lt;br /&gt;
access to records in the same or other IOCS.&lt;br /&gt;
&lt;br /&gt;
Recall that the link DBD definition is:&lt;br /&gt;
&lt;br /&gt;
    link(dir, choiceName, interfaceName, dataStructName)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; is the name that identifies the implementation.&lt;br /&gt;
&amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt; is the name of the interface that record support&lt;br /&gt;
uses and the support implements.&lt;br /&gt;
&amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt; is the name of a structure used by support for&lt;br /&gt;
configuration.&lt;br /&gt;
&lt;br /&gt;
This section describes that standard &amp;lt;tt&amp;gt;interfaceNames&amp;lt;/tt&amp;gt; that&lt;br /&gt;
are used by the record types supplied with epics base.&lt;br /&gt;
These interfaces are appropriate for the soft support supplied with EPICS&lt;br /&gt;
base and should also be sufficient for a wide variety of hardware support.&lt;br /&gt;
In particular it is sufficient for communication with asynDriver.&lt;br /&gt;
&lt;br /&gt;
== Link  ==&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
&amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; is an interface that is implemented by link support that&lt;br /&gt;
supports monitors. Example are hardware interrupts.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally record support does not need to call any of the Link &lt;br /&gt;
or MonitorLink methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call&lt;br /&gt;
destroy before modifying the link and initialize and connect after the&lt;br /&gt;
link is modified.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
&lt;br /&gt;
     enum LinkWaitResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
         linkWaitBlock,      // waiting. dont do additional processing until&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface LinkProcess&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
There is no support for octet but there is support for an array of octets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkWaitResult getWait(octet[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(octet[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The data source must be an array of octets or the connect request will fail.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkWaitResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkWaitResult write(octet[] value, octet[] mask);&lt;br /&gt;
          LinkWaitResult read(octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkWaitResult getWait(Boolean data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(boolean data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkWaitResult getWait(boolean[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(boolean[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be int16, int32, or int64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         void getBounds(&amp;lt;type&amp;gt; low, &amp;lt;type&amp;gt; high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     } &lt;br /&gt;
         &lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be float32 or float64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkWaitResult getWait(string data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(string data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkWaitResult getWait(string[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(string[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Registration and Instance Creation =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     interface StructFactory {&lt;br /&gt;
         DbfStruct create();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RecordSupportFactory {&lt;br /&gt;
         RecordSupport create(RecordInstance instance);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface SupportFactory {&lt;br /&gt;
         Support create(Dbf field);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RegisterSupport {&lt;br /&gt;
         structure(StructFactory create, string name);&lt;br /&gt;
         record(StructFactory create, string name);&lt;br /&gt;
         link(SupportFactory support,string name);&lt;br /&gt;
         device(SupportFactory support,string name);&lt;br /&gt;
         record(RecordSupportFactory support,string name);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;RegisterSupport&amp;lt;/tt&amp;gt; is implemented by iocCore.&lt;br /&gt;
Each &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; DBD definition must register a StructFactory to&lt;br /&gt;
create instances of the structure or record.&lt;br /&gt;
&lt;br /&gt;
Each link, device, and record support must register a SupportFactory to create&lt;br /&gt;
instances of the support to attach to the link, device, or record instance.&lt;br /&gt;
During database initialization, iocCore calls the factory methods.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtime Database Access =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Database Access, with help from record, link, and device support&lt;br /&gt;
implements the dbdInterfaces.&lt;br /&gt;
Other than Database Access, fields of a record can only&lt;br /&gt;
be accessed via the interfaces described in dbdInterfaces.&lt;br /&gt;
This allows the database to handle&lt;br /&gt;
actions like posting database monitors without any help from&lt;br /&gt;
record, link, or device support.&lt;br /&gt;
&lt;br /&gt;
Database access by default allocates the actual storage for each field&lt;br /&gt;
but allows support code to register itself to manage storage for field&lt;br /&gt;
instances.&lt;br /&gt;
Two examples, both involving arrays, are:&lt;br /&gt;
* The compress record  registers to provide storage for the value.&lt;br /&gt;
** This allows it to implement a circular buffer.&lt;br /&gt;
** Code that accesses the value field may have to issue two get requests.&lt;br /&gt;
* Device support for a transient recorder registers to provide storage for the array&lt;br /&gt;
** This allows device support to read data from hardware in segments&lt;br /&gt;
** Code that accesses the array may have to issue many get requests.&lt;br /&gt;
&lt;br /&gt;
The fact that each field of a record instance is an object means that additional storage is required.&lt;br /&gt;
Database Access  will probably have something like the following:&lt;br /&gt;
&lt;br /&gt;
    class Field {&lt;br /&gt;
        DbRecord instance;&lt;br /&gt;
        short          index;&lt;br /&gt;
    };&lt;br /&gt;
    ...&lt;br /&gt;
    class IntField extends Field {&lt;br /&gt;
        int data;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
This each field has the overhead of&lt;br /&gt;
* instance - a reference to DbRecord, i.e. record instance&lt;br /&gt;
* index - a 16 bit integer&lt;br /&gt;
* vtbl - a reference to the object implementation&lt;br /&gt;
&lt;br /&gt;
Additional fields will be needed for things like monitors.&lt;br /&gt;
These fields can start out null and only allocate storage as needed.&lt;br /&gt;
&lt;br /&gt;
== Database Access ==&lt;br /&gt;
&lt;br /&gt;
     interface DbAccess {&lt;br /&gt;
         void lock(RecordInstance instance);&lt;br /&gt;
         void unlock(RecordInstance instance);&lt;br /&gt;
         void process(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processCancel(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processContinue(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processRequestAccept(Dbf field, boolean yesNo);&lt;br /&gt;
         void registerDbfSource(Dbf field, Dbf source);&lt;br /&gt;
         LinkSupport getLinkSupport(Dbf field);&lt;br /&gt;
         Support getSupport(Dbf field);&lt;br /&gt;
         RecordSupport getRecordSupport(RecordInstance instance);&lt;br /&gt;
         RecordSupport getRecordCommonSupport(RecordInstance instance);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;lock&amp;lt;/tt&amp;gt; - lock the record.&lt;br /&gt;
* &amp;lt;tt&amp;gt;unlock&amp;lt;/tt&amp;gt; - unlock the record.&lt;br /&gt;
* &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; - Request processing. Record must be idle or active or request fails.&lt;br /&gt;
** &amp;lt;tt&amp;gt;instance&amp;lt;/tt&amp;gt; - The record to process&lt;br /&gt;
** &amp;lt;tt&amp;gt;callback&amp;lt;/tt&amp;gt; - A callback to call when processing completes or for failure.&lt;br /&gt;
* &amp;lt;tt&amp;gt;processRequestAccept&amp;lt;/tt&amp;gt; - Should a process request from channel access be accepted,&lt;br /&gt;
* &amp;lt;tt&amp;gt;registerDbfSource&amp;lt;/tt&amp;gt; - Register code that will implement storage for the field.&lt;br /&gt;
* &amp;lt;tt&amp;gt;getLinkSupport&amp;lt;/tt&amp;gt; - Find the link support for a link field&lt;br /&gt;
* &amp;lt;tt&amp;gt;getSupport&amp;lt;/tt&amp;gt; - Get the device support for a device field&lt;br /&gt;
* &amp;lt;tt&amp;gt;getRecordSupport&amp;lt;/tt&amp;gt; - Get the record support for the record&lt;br /&gt;
* &amp;lt;tt&amp;gt;getRecordCommonSupport&amp;lt;/tt&amp;gt; - Get the RecordCommon support for the record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTES&amp;lt;/b&amp;gt; This is just the beginning of defining the methods in DbAccess&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_RecordCommon_Support&amp;diff=2705</id>
		<title>V4 Design: RecordCommon Support</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_RecordCommon_Support&amp;diff=2705"/>
		<updated>2005-10-04T14:49:23Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: RecordCommonSupport - October 04 2005 &lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes the implementation of the record support&lt;br /&gt;
for RecordCommon, i.e. the set of fields associated with every record type.&lt;br /&gt;
&lt;br /&gt;
For V4 dbCommon.dbd and RecordCommon.dbd replace the V3 dbCommon.dbd.&lt;br /&gt;
dbCommon.dbd define widely used definitions and RecordCommon.dbd defines&lt;br /&gt;
the fields that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This document describes the following:&lt;br /&gt;
&lt;br /&gt;
* The code automatically generated from dbCommon.dbd and RecordCommon.dbd&lt;br /&gt;
* A proposed implementation of RecordCommonSupport.&lt;br /&gt;
&lt;br /&gt;
This document requires that the reader be familiar with:&lt;br /&gt;
# V3 iocCore&lt;br /&gt;
# V4 Design: Record Processing&lt;br /&gt;
# V4 Design: dbdInterfaces&lt;br /&gt;
# V4 Design: Runtime interfaces&lt;br /&gt;
# V4 Design: RecordCommon&lt;br /&gt;
&lt;br /&gt;
Java is used as the example code for two reasons:&lt;br /&gt;
# For V4 iocCore it is intended that both C++ and Java implementations will be provided. Since V3 is only implemented in C and C++ the Java implemention of V4 is described first to make sure that the interfaces defined in dbdInterfaces will work for Java.&lt;br /&gt;
# Java provides facilities that make it easy to handle strings, arrays, and structures.&lt;br /&gt;
&lt;br /&gt;
An implementaion of RecordCommonSupport is presented for two reasons:&lt;br /&gt;
# It demonstrates how to implement code that uses or implements the interfaces described in &amp;quot;V4 Design: dbdInterfaces&amp;quot; and &amp;quot;V4 Design: Runtime interfaces&amp;quot;.&lt;br /&gt;
# It helps refine the interfaces described in them&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= dbCommon.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the description of &amp;lt;tt&amp;gt;dbCommon.dbd&amp;lt;/tt&amp;gt; in &amp;quot;V4 Design: RecordCommon&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Link support must register support for each of the &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
         &lt;br /&gt;
From &amp;lt;tt&amp;gt;dbCommon.dbd&amp;lt;/tt&amp;gt; the following class implementations are generated:&lt;br /&gt;
* For the link structures:&lt;br /&gt;
** &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;MonitorLinkData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MonitorLinkSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;InputLink&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;InputLinkData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;InputLinkSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;OutputLink&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OutputLinkData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;OutputLinkSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;ProcessLink&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ProcessLinkData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;ProcessLinkSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
* For TimeStamp&lt;br /&gt;
** &amp;lt;tt&amp;gt;TimeStamp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;TimeStampData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;TimeStampSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
* For Scan&lt;br /&gt;
** &amp;lt;tt&amp;gt;Scan&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ScanData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;ScanSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;quot;V4 Design: Runtime interfaces&amp;quot; for an example of how these classes are defined.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= RecordCommon.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the description of &amp;lt;tt&amp;gt;RecordCommon.dbd&amp;lt;/tt&amp;gt; in &amp;quot;V4 Design: RecordCommon&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;RecordCommon.dbd&amp;lt;/tt&amp;gt; must be part of every record.&lt;br /&gt;
&lt;br /&gt;
Implementations of &amp;lt;tt&amp;gt;Disable&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DisableData&amp;lt;/tt&amp;gt;,&lt;br /&gt;
and &amp;lt;tt&amp;gt;DisableDataSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
are automatically generated.&lt;br /&gt;
&lt;br /&gt;
An implementations of RecordCommon is also generated.&lt;br /&gt;
See &amp;quot;V4 Design: Runtime interfaces&amp;quot; for an example of the generated&lt;br /&gt;
classes.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= RecordCommonSupport.java =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
This section describes the java implementation of RecordCommon&lt;br /&gt;
functionality. This code handles processing of the following fields&lt;br /&gt;
of RecordCommon:&lt;br /&gt;
; &amp;lt;tt&amp;gt;disable&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Decides if the record is disabled.&lt;br /&gt;
; &amp;lt;tt&amp;gt;alarmStatus&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;alarmSeverity&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The only way to change alarmStatus and alarmSeverity is via interface Common, which is implemented by RecordCommonSupport.&lt;br /&gt;
; &amp;lt;tt&amp;gt;processLink&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is an array of process links, which replace the V3 &amp;lt;tt&amp;gt;FLNK&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following subsection describes the code for RecordCommonSupport.java.&lt;br /&gt;
The remaining subsections describes the code for additional classes&lt;br /&gt;
that are part of the implementation.&lt;br /&gt;
&lt;br /&gt;
==  RecordCommonSupport.java ==&lt;br /&gt;
&lt;br /&gt;
 interface Common {&lt;br /&gt;
     boolean setSeverity(AlarmSeverity severity, string status);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public class RecordCommonSupport implements RecordSupport, Common&lt;br /&gt;
 {&lt;br /&gt;
     private RecordInstance instance;&lt;br /&gt;
     private Input          input;&lt;br /&gt;
     private Output         output;&lt;br /&gt;
     // The following are for implementing Common.setSeverity&lt;br /&gt;
     private short severity;&lt;br /&gt;
     private String status;&lt;br /&gt;
     private DbfMenu alarmSeverity;&lt;br /&gt;
     private DbfString alarmStatus;&lt;br /&gt;
     private boolean modifyingAlarm;&lt;br /&gt;
 &lt;br /&gt;
     // Constructor&lt;br /&gt;
     public RecordCommonSupport(RecordInstance instance) {&lt;br /&gt;
         this.instance = instance;&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     // Beginning of RecordSupport&lt;br /&gt;
     public destroy() {} // destroy not needed for Java&lt;br /&gt;
     public initialize(int pass) {&lt;br /&gt;
         if(pass==0) return;&lt;br /&gt;
         input = new Input(instance);&lt;br /&gt;
         output = new Output(instance);&lt;br /&gt;
         alarmSeverity = instance.getField(&amp;quot;alarmSeverity&amp;quot;);&lt;br /&gt;
         alarmStatus = instance.getField(&amp;quot;alarmStatus&amp;quot;);&lt;br /&gt;
         severity = alarmSeverity.get();&lt;br /&gt;
         alarmStatus.get(status);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     public ProcessReturn process(processState state,Callback callback) {&lt;br /&gt;
         if(state==processCancel) {&lt;br /&gt;
             input.process(state,callback);&lt;br /&gt;
             output.process(state,callback);&lt;br /&gt;
 	    return processDone;&lt;br /&gt;
         }&lt;br /&gt;
         if(state==processStart) {&lt;br /&gt;
             ProcessReturn result = input.process(state,callback);&lt;br /&gt;
             if(result!=processDone) return result;&lt;br /&gt;
         }&lt;br /&gt;
         if(state==processFinish) {&lt;br /&gt;
             ProcessReturn result = output.process(state,callback);&lt;br /&gt;
             if(result!=processDone) return result;&lt;br /&gt;
         }&lt;br /&gt;
         return output.process(state,callback)&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     public boolean special(boolean after,Dbf[] field) {&lt;br /&gt;
         int nlevels = field.length;&lt;br /&gt;
         assert(nlevels&amp;gt;0);&lt;br /&gt;
         if(index==alarmStatusIndex || index==alarmSeverityIndex) {&lt;br /&gt;
              if(!alarm.modifyingAlarm) return false;&lt;br /&gt;
              return true;&lt;br /&gt;
         }&lt;br /&gt;
         if(!after) return;&lt;br /&gt;
         switch(index) {&lt;br /&gt;
             case disableIndex: {&lt;br /&gt;
                 if(nlevels==1) {&lt;br /&gt;
                     input = new Input(instance);&lt;br /&gt;
                 } else {&lt;br /&gt;
                     input.special(instance,Dbf[1]);&lt;br /&gt;
                 }&lt;br /&gt;
                 break;&lt;br /&gt;
             }&lt;br /&gt;
             case processLinkIndex : output = new Output(instance); break;&lt;br /&gt;
             default: printf(&amp;quot;Why is special being called?\n&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     // Start of Common methods&lt;br /&gt;
     boolean setSeverity(AlarmSeverity severity, string status) {&lt;br /&gt;
         if(severity&amp;lt;= this.severity) return false;&lt;br /&gt;
         this.severity = severity;&lt;br /&gt;
         this.status = status;&lt;br /&gt;
         this.modifyingAlarm = true;&lt;br /&gt;
         this.alarmSeverity.putIndex(severity);&lt;br /&gt;
         this.alarmStatus.put(status);&lt;br /&gt;
         this.modifyingAlarm = false;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
RecordCommonSupport implements the following interfaces:&lt;br /&gt;
; &amp;lt;tt&amp;gt;RecordSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Record support for the fields in RecordCommon.&lt;br /&gt;
; &amp;lt;tt&amp;gt;Common&amp;lt;/tt&amp;gt;&lt;br /&gt;
: For now this just has the method &amp;lt;tt&amp;gt;setSeverity&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It has the following private fields:&lt;br /&gt;
* &amp;lt;tt&amp;gt;instance&amp;lt;/tt&amp;gt; -  The record instance to which it is attached. &amp;lt;tt&amp;gt;RecordCommonSupport&amp;lt;/tt&amp;gt; has a single constructor which is passed the &amp;lt;tt&amp;gt;RecordInstance&amp;lt;/tt&amp;gt; to which it is attached.&lt;br /&gt;
* &amp;lt;tt&amp;gt;input&amp;lt;/tt&amp;gt; - Input is a private class that provides access to the fields of disable.&lt;br /&gt;
* &amp;lt;tt&amp;gt;output&amp;lt;/tt&amp;gt; - Output is a private class that provides access to processLink.&lt;br /&gt;
* &amp;lt;tt&amp;gt;severity&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;modifyingAlarm&amp;lt;/tt&amp;gt; - private fields for implementing &amp;lt;tt&amp;gt;Common.setSeverity&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes about &amp;lt;tt&amp;gt;Input&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Output&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Each of these is a private class to RecordCommonSupport.&lt;br /&gt;
*  The implementations of each of these private classes is given after the implementaion of RecordCommonSupport.&lt;br /&gt;
&lt;br /&gt;
=== RecordSupport Methods ===&lt;br /&gt;
&lt;br /&gt;
==== destroy ====&lt;br /&gt;
         public destroy() {} // destroy not needed for Java&lt;br /&gt;
&lt;br /&gt;
Since Java does garbage collection destroy is not needed.&lt;br /&gt;
Note that iocCore will call all the link support destroy methods.&lt;br /&gt;
==== initialize ====&lt;br /&gt;
     &lt;br /&gt;
     public initialize(int pass) {&lt;br /&gt;
         if(pass==0) return;&lt;br /&gt;
         input = new Input(instance);&lt;br /&gt;
         output = new Output(instance);&lt;br /&gt;
         alarmSeverity = instance.getField(&amp;quot;alarmSeverity&amp;quot;);&lt;br /&gt;
         alarmStatus = instance.getField(&amp;quot;alarmStatus&amp;quot;);&lt;br /&gt;
         severity = alarmSeverity.get();&lt;br /&gt;
         alarmStatus.get(status);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
During the first pass of initialization, nothing needs to be done.&lt;br /&gt;
Before initialize is called on pass 1, iocInit has&lt;br /&gt;
already called link support so that it connects.&lt;br /&gt;
Initialize just creates it's private class instances for Input and Output,&lt;br /&gt;
and initializes the private fields for implementing setSeverity.&lt;br /&gt;
&lt;br /&gt;
==== process ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; is called by dbProcess at the beginning of record processing,&lt;br /&gt;
when a request is made to process while the record is active,&lt;br /&gt;
and after the record specific record support completes.&lt;br /&gt;
During the beginning of record processing&lt;br /&gt;
process takes care of field &amp;lt;tt&amp;gt;disable&amp;lt;/tt&amp;gt;, via class Input,&lt;br /&gt;
During the end of record processing process&lt;br /&gt;
takes care of field &amp;lt;tt&amp;gt;processLink&amp;lt;/tt&amp;gt;, via class Output&lt;br /&gt;
&lt;br /&gt;
     public ProcessReturn process(processState state,Callback callback) {&lt;br /&gt;
         if(state==processCancel) {&lt;br /&gt;
             input.process(state,callback);&lt;br /&gt;
             output.process(state,callback);&lt;br /&gt;
            return processDone;&lt;br /&gt;
         }&lt;br /&gt;
         if(state==processStart) {&lt;br /&gt;
             ProcessReturn result = input.process(state,callback);&lt;br /&gt;
             if(result!=processDone) return result;&lt;br /&gt;
         }&lt;br /&gt;
         if(state==processFinish) {&lt;br /&gt;
             ProcessReturn result = output.process(state,callback);&lt;br /&gt;
             if(result!=processDone) return result;&lt;br /&gt;
         }&lt;br /&gt;
         return output.process(state,callback)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== special ====&lt;br /&gt;
&amp;lt;tt&amp;gt;special&amp;lt;/tt&amp;gt; is called when any of the fields in &amp;lt;tt&amp;gt;disable&amp;lt;/tt&amp;gt;,&lt;br /&gt;
&amp;lt;tt&amp;gt;alarmStatus&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;alarmSeverity&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;processLink&amp;lt;/tt&amp;gt; are changed.&lt;br /&gt;
     public boolean special(boolean after,Dbf[] field) {&lt;br /&gt;
         int nlevels = field.length;&lt;br /&gt;
         assert(nlevels&amp;gt;0);&lt;br /&gt;
         if(index==alarmStatusIndex || index==alarmSeverityIndex) {&lt;br /&gt;
              if(!alarm.modifyingAlarm) return false;&lt;br /&gt;
              return true;&lt;br /&gt;
         }&lt;br /&gt;
         if(!after) return;&lt;br /&gt;
         switch(index) {&lt;br /&gt;
             case disableIndex: {&lt;br /&gt;
                 if(nlevels==1) {&lt;br /&gt;
                     input = new Input(instance);&lt;br /&gt;
                 } else {&lt;br /&gt;
                     input.special(instance,Dbf[1]);&lt;br /&gt;
                 }&lt;br /&gt;
                 break;&lt;br /&gt;
             }&lt;br /&gt;
             case processLinkIndex : output = new Output(instance); break;&lt;br /&gt;
             default: printf(&amp;quot;Why is special being called?\n&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
==== setSeverity ====&lt;br /&gt;
This is the implementation of Common.setSeverity.&lt;br /&gt;
&lt;br /&gt;
     boolean setSeverity(AlarmSeverity severity, string status) {&lt;br /&gt;
         if(severity&amp;lt;= this.severity) return false;&lt;br /&gt;
         this.severity = severity;&lt;br /&gt;
         this.status = status;&lt;br /&gt;
         this.modifyingAlarm = true;&lt;br /&gt;
         this.alarmSeverity.putIndex(severity);&lt;br /&gt;
         this.alarmStatus.put(status);&lt;br /&gt;
         this.modifyingAlarm = false;&lt;br /&gt;
     }&lt;br /&gt;
=== Input ===&lt;br /&gt;
This is the package private class the handles disable.&lt;br /&gt;
&lt;br /&gt;
 class Input implements Callback{&lt;br /&gt;
     RecordInstance instance;&lt;br /&gt;
     DisableData disable;&lt;br /&gt;
     LinkInt16   disableSupport;&lt;br /&gt;
     Callback    processCallback;&lt;br /&gt;
 &lt;br /&gt;
     Input(RecordInstance instance) {&lt;br /&gt;
         this.instance = instance;&lt;br /&gt;
         DisplayLimitAccess.get(&lt;br /&gt;
             (DbfStruct)instance.getField(&amp;quot;disable&amp;quot;),disable);&lt;br /&gt;
         disableSupport = DbAccess.getLinkSupport(disable.disableLink);&lt;br /&gt;
     }&lt;br /&gt;
     public ProcessReturn process(processState state,Callback callback) {&lt;br /&gt;
         switch(state) {&lt;br /&gt;
         case processCancel:&lt;br /&gt;
             processCallback = null;&lt;br /&gt;
             disableSupport.cancel(); return(processDone);&lt;br /&gt;
         case processStart:&lt;br /&gt;
             LinkWaitResult result;&lt;br /&gt;
             result = disableSupport.getWait(disable.disableInput,this);&lt;br /&gt;
             switch(result) {&lt;br /&gt;
             case linkNoop:&lt;br /&gt;
             case linkDone:&lt;br /&gt;
                 if(disable.disableInput==disable.disableValue)&lt;br /&gt;
                     return processAbort;&lt;br /&gt;
                 return processDone;&lt;br /&gt;
             case linkWait:&lt;br /&gt;
             case linkWaitBlock:&lt;br /&gt;
                 processCallback = callback;&lt;br /&gt;
                 return processActive;&lt;br /&gt;
         default:&lt;br /&gt;
                 throw java.lang.IllegalStateException;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     void special(RecordInstance instance,Dbf field) {&lt;br /&gt;
         int16 index = Dbf.getIndex();&lt;br /&gt;
         switch(index) {&lt;br /&gt;
             case disableValueIndex:&lt;br /&gt;
                 disable.disableValue = ((DbfInt16)Dbf).get(); break;&lt;br /&gt;
             case disableInputIndex:&lt;br /&gt;
                 disable.disableInput = ((DbfInt16)Dbf).get(); break;&lt;br /&gt;
             case disableAlarmSeverityIndex:&lt;br /&gt;
                 disable.alarmSeverity = ((dbfMenu)Dbf).getIndex(); break;&lt;br /&gt;
             case disableLinkIndex:&lt;br /&gt;
             case disableIndex:&lt;br /&gt;
                 DisplayLimitAccess.get(&lt;br /&gt;
                     (DbfStruct)instance.getField(&amp;quot;disable&amp;quot;),disable);&lt;br /&gt;
                 disableSupport = disable.disableLink.getSupport();&lt;br /&gt;
                 break;&lt;br /&gt;
             default:&lt;br /&gt;
                 throw java.lang.IllegalStateException;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     // Start of Callback methods&lt;br /&gt;
     public void done() {&lt;br /&gt;
         DbAccess.lock(instance);&lt;br /&gt;
         Callback callback = processCallback;&lt;br /&gt;
         processCallback = null;&lt;br /&gt;
         DbAccess.unlock(instance);&lt;br /&gt;
         if(callback!=null) callback.done();&lt;br /&gt;
     }&lt;br /&gt;
     public void failure() { done(); }&lt;br /&gt;
 }&lt;br /&gt;
     &lt;br /&gt;
=== Output ===&lt;br /&gt;
This is the package private class that handles processLink.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 class OutputLink {&lt;br /&gt;
     Link        link;&lt;br /&gt;
     LinkProcess support;&lt;br /&gt;
     void init(RecordInstance instance,String linkFieldName) {&lt;br /&gt;
         DbfLink link = (DbfLink)instance.getField(linkFieldName);&lt;br /&gt;
         support = DbAccess.getLinkSupport(link);&lt;br /&gt;
     }&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 class Output {&lt;br /&gt;
     RecordInstance instance;&lt;br /&gt;
     int          nextLink;&lt;br /&gt;
     int          numberLinksActive;&lt;br /&gt;
     OutputLink[] link;&lt;br /&gt;
     Callback     processCallback;&lt;br /&gt;
 &lt;br /&gt;
     Output(RecordInstance instance) {&lt;br /&gt;
         this.instance = instance;&lt;br /&gt;
         DbfArray array = instance.getField(&amp;quot;processLink&amp;quot;);&lt;br /&gt;
         int n = array.getNelements();&lt;br /&gt;
         link = new OutputLink[n];&lt;br /&gt;
         for(i=0; i&amp;lt; n; i++) {&lt;br /&gt;
             String field = &amp;quot;processLink[&amp;quot; + &amp;quot;i&amp;quot; + &amp;quot;]&amp;quot;;&lt;br /&gt;
             link[i].init(instance,field);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     public ProcessReturn process(processState state,Callback processCallback) {&lt;br /&gt;
         switch(state) {&lt;br /&gt;
         case processCancel:&lt;br /&gt;
             processCallback = null;&lt;br /&gt;
             for(int i=0; i&amp;lt;link.length) {&lt;br /&gt;
                 link[i].support.cancel();&lt;br /&gt;
             }&lt;br /&gt;
             return(processDone);&lt;br /&gt;
         case processDone: &lt;br /&gt;
             nextLink = 0;&lt;br /&gt;
             numberLinksActive = 0;&lt;br /&gt;
             // fall through to processOutputActive&lt;br /&gt;
         case processActive:&lt;br /&gt;
             LinkWaitResult result = linkWait;&lt;br /&gt;
             while(nextLink&amp;lt; link.length) {&lt;br /&gt;
                 result = link[nextLink].support.process(this);&lt;br /&gt;
                 if(result==linkWait || result==linkWaitBlock) {&lt;br /&gt;
                     link[nextLink].active = true;&lt;br /&gt;
                     numberLinksActive++;&lt;br /&gt;
                 }&lt;br /&gt;
                 if(result==linkWaitBlock) break;&lt;br /&gt;
                 output.nextLink++;&lt;br /&gt;
             }&lt;br /&gt;
             if(output.numberLinksActive==0) return processDone;&lt;br /&gt;
             return processActive;&lt;br /&gt;
         default:&lt;br /&gt;
                 throw java.lang.IllegalStateException;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
     // Start of Callback methods&lt;br /&gt;
     public void done() {&lt;br /&gt;
         DbAccess.lock(instance);&lt;br /&gt;
         numberLinksActive--;&lt;br /&gt;
         Callback callback = processCallback;&lt;br /&gt;
         processCallback = null;&lt;br /&gt;
         DbAccess.unlock(instance);&lt;br /&gt;
         if(numberLinksActive==0 &amp;amp;&amp;amp; callback!=null) callback.done();&lt;br /&gt;
     }&lt;br /&gt;
     public void failure() { done(); }&lt;br /&gt;
 }&lt;br /&gt;
== RecordCommonSupportFactory ==&lt;br /&gt;
This is the factory for creating an RecordCommonSupport.&lt;br /&gt;
It is called by dbLoadRecords.&lt;br /&gt;
&lt;br /&gt;
     public class RecordCommonSupportFactory implements RecordSupportFactory{&lt;br /&gt;
         RecordSupport create(RecordInstance instance) {&lt;br /&gt;
             return new RecordCommonSupport(instance);&lt;br /&gt;
         }&lt;br /&gt;
         void destroy(RecordSupport support) {&lt;br /&gt;
             RecordCommonSupport RecordCommonSupport = support;&lt;br /&gt;
             RecordCommonSupport.destroy();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class RecordCommonSupportFactoryRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             RecordCommonSupportFactory factory = new RecordCommonSupportFactory;&lt;br /&gt;
             RegisterSupport.record(factory,&amp;quot;RecordCommon&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt;&lt;br /&gt;
Who calls RecordCommonSupportFactoryRegister.createAndRegister?&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=555</id>
		<title>V4 Link Support Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=555"/>
		<updated>2005-09-30T15:15:05Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Link Support Tutorial Sept 30 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
The V4 link support is a replacement for V3 &lt;br /&gt;
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK&lt;br /&gt;
# device DBD definition and device support&lt;br /&gt;
# driver DBD definition and driver support&lt;br /&gt;
&lt;br /&gt;
The link support model is:&lt;br /&gt;
* For each link, record support defines a list of interfaces it can use for communicating with link support&lt;br /&gt;
* Link support defines the set of interfaces it implements&lt;br /&gt;
&lt;br /&gt;
Link support has no knowledge of what record types are using it&lt;br /&gt;
and record support has no knowledge about link support other than the&lt;br /&gt;
interface it is using.&lt;br /&gt;
&lt;br /&gt;
EPICS base defines a standard set of interfaces for link support.&lt;br /&gt;
The intention is that the set includes enough functionality such that&lt;br /&gt;
most link support can be implemented via just these interfaces.&lt;br /&gt;
&lt;br /&gt;
The interfaces support all the functionality needed by Channel/Database access&lt;br /&gt;
and by the generic EPICS device support supplied by asynDriver.&lt;br /&gt;
Since asynDriver is intended as a framework for interfacing to most hardware,&lt;br /&gt;
this means that the interfaces supplied and used by base allows support&lt;br /&gt;
for most hardware. The support can communicate with the hardware&lt;br /&gt;
however it wants but must implement some set of the interfaces defined&lt;br /&gt;
by base.&lt;br /&gt;
&lt;br /&gt;
This document gives a brief overview of the V4 link support model.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Database Definitions For Links =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section first reviews the DBD syntax related to link definitions.&lt;br /&gt;
It then gives a brief description of link related definitions in dbCommon.dbd&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
A record link has the syntax:&lt;br /&gt;
     link(linkDirection,interface(interfaceName,...))&lt;br /&gt;
A link itself has the syntax:&lt;br /&gt;
     link(linkDirection,choiceName,dataStructName,interface(interfaceName,...))&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;linkDirection&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be one of &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. Compatible checks are made to match the interface with a field.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interface&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is a list of the interfaces that the record support understands.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of an interface via which record support communicates with device support.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools do prompt the user to assign values to the structure.&lt;br /&gt;
&lt;br /&gt;
When a record instance is created the choiceName and interfaceName select&lt;br /&gt;
the support to attach to a record link.&lt;br /&gt;
The interfaceName must be one of the interface names the record&lt;br /&gt;
has listed as a valid type and linkDirection must be compatible&lt;br /&gt;
with the linkDirection the record type specified.&lt;br /&gt;
&lt;br /&gt;
== Standard Definitions For Channel/Database Access ==&lt;br /&gt;
&lt;br /&gt;
These are the database definitions defined in dbCommon are used by&lt;br /&gt;
the base supplied support for Channel/Database access.&lt;br /&gt;
&lt;br /&gt;
=== Data Structures ===&lt;br /&gt;
&lt;br /&gt;
The complete set of definitions are defined in &amp;quot;V4 DB RecordCommon&amp;quot;.&lt;br /&gt;
     struct(MonitorLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(InputLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     ... also OutputLinkData and ProcessLinkData&lt;br /&gt;
&lt;br /&gt;
A look at the fields shows that these are what is required to implement&lt;br /&gt;
the V4 semantics for Channel/Database access links.&lt;br /&gt;
&lt;br /&gt;
=== Link Definitions ===&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* input&lt;br /&gt;
** monitor support&lt;br /&gt;
** input support&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For input and output The following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
&amp;quot;V4 DB RecordCommon&amp;quot; describes the complete set of link definitions&lt;br /&gt;
supplied by EPICS base. These are:&lt;br /&gt;
&lt;br /&gt;
     link(process,processLink,ProcessLinkData,interface(ProcessLink))&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLink,MonitorLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,monitorLinkArray,MonitorLinkData interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLink,InputLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLinkArray,InputLinkData interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,outputLink,OutputLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,outputLinkArray,OutputLinkData interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
&lt;br /&gt;
These are the link definitions for the Channel/Database access link&lt;br /&gt;
support supplied with base. The support registers support for processLink,&lt;br /&gt;
monitorLinkArrayOctet, ...&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
&lt;br /&gt;
These are definitions that are used by the standard EPICS device support&lt;br /&gt;
for asynDriver. Since asynDriver is a generic way of interfacing arbitrary&lt;br /&gt;
hardware support, this is a generic way of attaching links in records to&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLinkData) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link definitions ===&lt;br /&gt;
&lt;br /&gt;
     link(inout,asynInt32,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Average,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Monitor,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(inout,asynFloat64,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Average,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Monitor,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynDigitalMonitor,AsynLinkData,interface(AsynDigital))&lt;br /&gt;
     link(inout,asynDigital,AsynLinkData,interface(AsynDigital)))&lt;br /&gt;
     link(inout,asynInt32Array,AsynLinkData,interface(LinkArrayInt32)))&lt;br /&gt;
     link(inout,asynFloat64Array,AsynLinkData,interface(LinkArrayFloat64)))&lt;br /&gt;
     link(inout,asynOctet,AsynLinkData,interface(AsynOctet)))&lt;br /&gt;
&lt;br /&gt;
This is the set of definitions for the standard EPICS device support implemented&lt;br /&gt;
by asynDriver. Although, at least for the first few V4 releases,&lt;br /&gt;
asynDriver will not be part of base, they are shown here because the&lt;br /&gt;
LinkInt32,... interface definitions are defined as part of base.&lt;br /&gt;
Again it is expected that almost all hardware support be created by&lt;br /&gt;
implementing a combination of these link interface definitions or&lt;br /&gt;
the interfaces implemented by Channel/Database access link support.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
An arbitrary number of Link Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
Other link support can also be supplied.&lt;br /&gt;
New support should try very hard to implement the standard interfaces&lt;br /&gt;
supplied by EPICS base. These are the interfaces that the record types&lt;br /&gt;
supplied with base know how to use.&lt;br /&gt;
&lt;br /&gt;
Soft support should try to implement the same interfaces implemented by&lt;br /&gt;
the Channel/Database access support supplied with base. The support&lt;br /&gt;
can, of course, define data structures for it's own use.&lt;br /&gt;
Implementing these interfaces means that nthe support will work for&lt;br /&gt;
the same set of record links as the Channel/Database access support.&lt;br /&gt;
&lt;br /&gt;
Hardware support should, if possible, also implement the same interfaces&lt;br /&gt;
implemented by the Channel/Database access support.&lt;br /&gt;
Message based support may also have to implement the AsynOctet interface&lt;br /&gt;
but this interface is only used by a few record links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This section describes the interfaces implemented by all link support&lt;br /&gt;
and then the standard interfaces used by the records supplied with base.&lt;br /&gt;
&lt;br /&gt;
== Link and MonitorLink ==&lt;br /&gt;
&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; is an interface that is implemented by link support that&lt;br /&gt;
supports monitors. An example is support for hardware interrupts.&lt;br /&gt;
The &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally record support does not need to call any of the Link &lt;br /&gt;
or MonitorLink methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call destroy before modifying the link&lt;br /&gt;
and initialize and connect after the link is modified.&lt;br /&gt;
&lt;br /&gt;
Neither Link or MonitorLink is listed in the &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; database&lt;br /&gt;
definition.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
These are the definitions used by the Channel/Database access support&lt;br /&gt;
supplied with base. It is also used by the standard EPICS support from asyn.&lt;br /&gt;
&lt;br /&gt;
     enum LinkWaitResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
         linkWaitBlock,      // waiting. dont do additional processing until&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface ProcessLinkSupport&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
There is no support for octet but there is support for an array of octets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkWaitResult getWait(octet[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(octet[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The data source must be an array of octets or the connect request will fail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;GENERIC QUESTION&amp;lt;/b&amp;gt; The data is passed as primitive or arrays of&lt;br /&gt;
primitive types. Should &amp;lt;tt&amp;gt;Dbf&amp;lt;/tt&amp;gt; interfaces be used? Needs thought.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkWaitResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkWaitResult write(octet[] value, octet[] mask);&lt;br /&gt;
          LinkWaitResult read(octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkWaitResult getWait(Boolean data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(boolean data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkWaitResult getWait(boolean[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(boolean[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be int16, int32, or int64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         void getBounds(&amp;lt;type&amp;gt; low, &amp;lt;type&amp;gt; high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     } &lt;br /&gt;
         &lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be float32 or float64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkWaitResult getWait(string data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(string data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkWaitResult getWait(string[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(string[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Example - VME ADC support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
== database definitions ==&lt;br /&gt;
The following struct is defined for configuration information.&lt;br /&gt;
     struct VMEADC {&lt;br /&gt;
         field(a16 int16)&lt;br /&gt;
         field(a32 int32)&lt;br /&gt;
         field(channel int16)&lt;br /&gt;
     }&lt;br /&gt;
The following link definition is defined:&lt;br /&gt;
     link(in,myAdcSupport,VMEADCinterface(LinkInt32))&lt;br /&gt;
&lt;br /&gt;
This allows record instance definitions like:&lt;br /&gt;
     AiRecord aiExample = {&lt;br /&gt;
        ...&lt;br /&gt;
        input = myAdcSupport(LinkInt32){a16=0x0010;channel=1}&lt;br /&gt;
        ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== link support implementation ==&lt;br /&gt;
The following is presented with Java syntax.&lt;br /&gt;
It assumes that there is VME support of the form&lt;br /&gt;
&lt;br /&gt;
public class VME {&lt;br /&gt;
    static public short getShort(long addr);&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
The link support would be something like:&lt;br /&gt;
&lt;br /&gt;
     class AdcSupport implements Link LinkInt32 {&lt;br /&gt;
     AdcSupport(VMEADCData fromFactory)&lt;br /&gt;
     {&lt;br /&gt;
         data = fromFactory;&lt;br /&gt;
         connected = false;&lt;br /&gt;
         //  from the VMEADC initailze vmeaddr and channel&lt;br /&gt;
         // details left to your imagination&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Link methods&lt;br /&gt;
     void report(int16_t level)&lt;br /&gt;
     {&lt;br /&gt;
         printf(&amp;quot;AdcSupport a16 %x channel %d\n&amp;quot;,a16,channel);&lt;br /&gt;
     }&lt;br /&gt;
     void cancel() {} // nothing to do&lt;br /&gt;
     void destroy() {} //nothing to do&lt;br /&gt;
     void initialize()&lt;br /&gt;
     {&lt;br /&gt;
         // make sure we can access a16&lt;br /&gt;
     }&lt;br /&gt;
     void connect() {connected = true}&lt;br /&gt;
     void disconnect() {connected = false}&lt;br /&gt;
     &lt;br /&gt;
     // LinkInt32 methods&lt;br /&gt;
     LinkWaitResult getWait(Int data,Callback callback)&lt;br /&gt;
     {&lt;br /&gt;
         data = (Int)VME.getShort(vmeaddr);&lt;br /&gt;
         return linkDone;&lt;br /&gt;
     }&lt;br /&gt;
     LinkWaitResult putWait(Int data,Callback callback)&lt;br /&gt;
     {&lt;br /&gt;
         throw CantWriteAdc;&lt;br /&gt;
     }&lt;br /&gt;
     void getBounds(Int low, Int high) &lt;br /&gt;
     {&lt;br /&gt;
         // assume 16 bit unipolor adc&lt;br /&gt;
         low = 0; high = 0xffff;&lt;br /&gt;
     }&lt;br /&gt;
     private:&lt;br /&gt;
         VMEADCData data;&lt;br /&gt;
         int vmeaddr;&lt;br /&gt;
         int channel;&lt;br /&gt;
         boolean connected;&lt;br /&gt;
     }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_Record_Instance_Syntax&amp;diff=560</id>
		<title>V4 DB Record Instance Syntax</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_Record_Instance_Syntax&amp;diff=560"/>
		<updated>2005-09-30T15:14:04Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: Change link syntax&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; Record Instance Syntax Sept 30 2005&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The syntax used for record instances has to change in EPICS V4,&lt;br /&gt;
since we now have to support structured data.&lt;br /&gt;
A complete redesign of the syntax has been done to help improve parsing, and to provide commonality between the syntax of a DB file and the string representation of structured data values passed through Channel Access.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Document Conventions =&lt;br /&gt;
&lt;br /&gt;
This syntax is presented below in the form of a grammar. The conventions I'm using are as follows:&lt;br /&gt;
&lt;br /&gt;
;''symbolBeingDefined:''&lt;br /&gt;
: ''otherSymbol''&lt;br /&gt;
: ''alternateSymbolFollowedBy'' &amp;lt;tt&amp;gt;literal&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;list of posible literal values&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Common Symbols =&lt;br /&gt;
&lt;br /&gt;
The symbols described in this section are used in the grammar, but may be implemented as lexical tokens.&lt;br /&gt;
&lt;br /&gt;
;''identifier:''&lt;br /&gt;
: A legal C99 identifier. Note that C99 permits implementations to allow extended characters to be used in identifiers, but does not require it, so the use of extended characters may reduce portability and is not recommended.&lt;br /&gt;
&lt;br /&gt;
== Integer Constants ==&lt;br /&gt;
&lt;br /&gt;
;''integerConstant:''&lt;br /&gt;
: ''positiveInteger''&lt;br /&gt;
&lt;br /&gt;
;''positiveInteger:''&lt;br /&gt;
: ''octalConstant''&lt;br /&gt;
: ''hexConstant''&lt;br /&gt;
: ''decimalConstant''&lt;br /&gt;
&lt;br /&gt;
;''octalConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''octalConstant'' ''octalDigit''&lt;br /&gt;
&lt;br /&gt;
;''octalDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-7&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''hexConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0x&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0X&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: ''hexConstant'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
;''hexDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9 a-f A-F&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''decimalConstant:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;1-9&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''decimalConstant'' ''decimalDigit''&lt;br /&gt;
&lt;br /&gt;
;''decimalDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This was meant to be a description of the C99 standard integer representation, but I made it up myself so it may be flawed.  Note that we will not accept the C99 numeric suffixes u/U and l/L since (unlike a C compiler) we know the type of the number we're expecting.&lt;br /&gt;
&lt;br /&gt;
== Floating Point Constants ==&lt;br /&gt;
&lt;br /&gt;
;''realConstant:''&lt;br /&gt;
:'' positiveReal''&lt;br /&gt;
: &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt; ''positiveReal''&lt;br /&gt;
&lt;br /&gt;
;''positiveReal:''&lt;br /&gt;
: ''digitSequence''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''exponentPart''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence'' ''exponentPart''&lt;br /&gt;
: &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence'' ''exponentPart''&lt;br /&gt;
: ''digitSequence'' ''exponentPart''&lt;br /&gt;
&lt;br /&gt;
;''digitSequence:''&lt;br /&gt;
: ''decimalDigit''&lt;br /&gt;
: ''digitSequence'' ''decimalDigit''&lt;br /&gt;
&lt;br /&gt;
;''exponentPart:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;e&amp;lt;/tt&amp;gt; ''signedExponent''&lt;br /&gt;
: &amp;lt;tt&amp;gt;E&amp;lt;/tt&amp;gt; ''signedExponent''&lt;br /&gt;
&lt;br /&gt;
;''signedExponent:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: ''digitSequence''&lt;br /&gt;
&lt;br /&gt;
In ANSI C source code, a sequence of decimal digits with neither a decimal point nor an exponent is an integer constant, not a floating-point constant.  We will permit this however, since we always know the field type in advance.&lt;br /&gt;
&lt;br /&gt;
== Boolean Constants ==&lt;br /&gt;
&lt;br /&gt;
We can afford to be generous in what we accept as a boolean value:&lt;br /&gt;
&lt;br /&gt;
;''booleanConstant:''&lt;br /&gt;
: ''booleanTrue''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''booleanTrue'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''booleanFalse''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''booleanFalse'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''booleanTrue:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;1 T TRUE t true True Y YES Yes y yes&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''booleanFalse:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0 F FALSE f false False N NO No n no&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''I'm proposing all these possibilities for true/false as they are all obvious in meaning, and will allow a CA Put of any of these strings to a boolean field. We might even want to allow registration of boolean strings in other languages...'''&lt;br /&gt;
&lt;br /&gt;
== String Constants ==&lt;br /&gt;
&lt;br /&gt;
;''stringConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''escapedCharacterList'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''escapedCharacterList:''&lt;br /&gt;
: A series of characters, using the C99 ''escapeSequence'' syntax defined below:&lt;br /&gt;
&lt;br /&gt;
;''escapeSequence:''&lt;br /&gt;
: ''simpleEscapeSequence''&lt;br /&gt;
: ''octalEscapeSequence''&lt;br /&gt;
: ''hexEscapeSequence''&lt;br /&gt;
: ''universalCharacterName''&lt;br /&gt;
&lt;br /&gt;
;''simpleEscapeSequence:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;\' \&amp;quot; \? \\ \a \b \f \n \r \t \v&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''octalEscapeSequence:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit'' ''octalDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit'' ''octalDigit'' ''octalDigit''&lt;br /&gt;
&lt;br /&gt;
;''hexEscapeSequence:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\x&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: ''hexEscapeSequence'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
Note: C99 does not limit the number of hexadecimal digits that can appear in a ''hexEscapeSequence'', but it does state that the behaviour is undefined if the resulting character value exceeds that of the largest character.&lt;br /&gt;
&lt;br /&gt;
;''universalCharacterName:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\u&amp;lt;/tt&amp;gt; ''hexQuad''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\U&amp;lt;/tt&amp;gt; ''hexQuad'' ''hexQuad''&lt;br /&gt;
&lt;br /&gt;
;''hexQuad:''&lt;br /&gt;
: ''hexDigit'' ''hexDigit'' ''hexDigit'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Database File =&lt;br /&gt;
&lt;br /&gt;
This section will eventually define what can appear in a .db file.  That currently means:&lt;br /&gt;
&lt;br /&gt;
* record instances&lt;br /&gt;
* comments&lt;br /&gt;
* macro instances, including where they will be allowed&lt;br /&gt;
* template files and substitution macro definitions&lt;br /&gt;
* port definitions for template instances&lt;br /&gt;
* data for tools such as VDCT, that will not be discarded by .db processing tools.&lt;br /&gt;
&lt;br /&gt;
The templates, macros and ports design should be very similar to the ideas produced for R3.14 VDCT templates.&lt;br /&gt;
&lt;br /&gt;
= Record Definitions =&lt;br /&gt;
&lt;br /&gt;
;''recordDefinition:''&lt;br /&gt;
: ''recordType'' ''recordName'' &amp;lt;tt&amp;gt;= {&amp;lt;/tt&amp;gt; ''recordBody'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''recordType:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
;''recordName:''&lt;br /&gt;
: ''recordNameChar''&lt;br /&gt;
: ''recordName'' ''recordNameChar''&lt;br /&gt;
&lt;br /&gt;
;''recordNameChar:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9 A-Z a-z _ - : ; &amp;lt; &amp;gt; [ ]&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Any Unicode/UTF-8 character outside of the Basic Latin set&lt;br /&gt;
&lt;br /&gt;
This extends the character set available to a V3 record name, adding all possible multi-byte characters.  However, EPICS sites are strongly advised to confirm that such record names can be processed using all of their database and CA client tools before actually making use of this particular extension.&lt;br /&gt;
&lt;br /&gt;
;''recordBody:''&lt;br /&gt;
: ''recordBodyItem''&lt;br /&gt;
: ''recordBody'' ''recordBodyItem''&lt;br /&gt;
&lt;br /&gt;
Record instance definitions in EPICS V4 look very similar to a C99 structure definition with initialization. For example:&lt;br /&gt;
&lt;br /&gt;
   ai foo:bar:temperature = {&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
Inside the body of the record definition, there are three possible kinds of statements, similar to a C assignment statement.  Note these statements must be terminated with a semi-colon (which is different from inside a struct).  The reason for this difference is to prevent database instance files from becoming dependent on the order of fields in a record; if we permit record instances to be created from a single comma-separated list of field values without the field names, it could lead to significant confusion if the field order ever changes.&lt;br /&gt;
&lt;br /&gt;
;''recordBodyItem:''&lt;br /&gt;
: ''infoAssignment''&lt;br /&gt;
: ''fieldAssignment''&lt;br /&gt;
: ''extraFieldAssigment''&lt;br /&gt;
&lt;br /&gt;
== Information Fields ==&lt;br /&gt;
&lt;br /&gt;
;''infoAssignment:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; ''infoName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''stringConstant'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''infoName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
: ''stringConstant''&lt;br /&gt;
&lt;br /&gt;
Info items provide additional configuration data about this record that can be accessed by other software running on the IOC.&lt;br /&gt;
&lt;br /&gt;
   info savePeriod = &amp;quot;30.0&amp;quot;;&lt;br /&gt;
   info restorePhase = &amp;quot;1&amp;quot;;&lt;br /&gt;
   info &amp;quot;my favourite things&amp;quot; = &amp;quot;raindrops on roses&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
== Field Assignment ==&lt;br /&gt;
&lt;br /&gt;
;''fieldAssignment:''&lt;br /&gt;
: ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializer'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''fieldName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
;''initializer:''&lt;br /&gt;
: ''constant''&lt;br /&gt;
: ''structInitializer''&lt;br /&gt;
: ''arrayInitializer''&lt;br /&gt;
: ''linkInitializer''&lt;br /&gt;
&lt;br /&gt;
;''initializerList:''&lt;br /&gt;
: ''initializer''&lt;br /&gt;
: ''initializerList'' &amp;lt;tt&amp;gt;,&amp;lt;/tt&amp;gt; ''initializer''&lt;br /&gt;
&lt;br /&gt;
The ''initializer'' in a field assignment is also the exact same syntax that will be used when converting a string value from a CA client for example into a field value that is being put into a field.&lt;br /&gt;
&lt;br /&gt;
=== Basic and Enumerated Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''constant:''&lt;br /&gt;
: ''booleanConstant''&lt;br /&gt;
: ''integerConstant''&lt;br /&gt;
: ''realConstant''&lt;br /&gt;
: ''stringConstant''&lt;br /&gt;
&lt;br /&gt;
The syntax for the field initializer depends on the data type represented by fieldName.  Basic types (numeric or string) should need no comment other than to note that values for numeric fields must not be given inside quotes (unlike EPICS V3).  Menu field values may be given as either a string or an integer. For enum fields, if the related field that contains the strings is defined first, the enum field may be specified using a string; otherwise it can only be set using an integer value.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
   ai foo:bar:temperature = {&lt;br /&gt;
       inputSmoothing = 0.98;&lt;br /&gt;
       invalidValue = 1000;&lt;br /&gt;
       units = &amp;quot;Celcius&amp;quot;;&lt;br /&gt;
       scan = &amp;quot;Interrupt&amp;quot;;&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Structure Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''structInitializer:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''structAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''structAssignmentList:''&lt;br /&gt;
: ''initializerList''&lt;br /&gt;
: ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
: ''structAssignmentList'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
&lt;br /&gt;
Initializers for a structure field look similar to a nested record body, but the rules are slightly different:&lt;br /&gt;
* You can give a series of values for adjacent items using a simple comma-separated list (for a record body, you ''must'' name each field)&lt;br /&gt;
* Semi-colons are required between a value and a following named item.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   ai foo:temperature:sensor = {&lt;br /&gt;
       linearConvert = {&lt;br /&gt;
           mode = &amp;quot;Linear&amp;quot;;&lt;br /&gt;
           low = -12.5, 133.5&lt;br /&gt;
       };&lt;br /&gt;
       displayLimit = { 0, 100 };&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
=== Link Initializer ===&lt;br /&gt;
&lt;br /&gt;
;''linkInitializer:''&lt;br /&gt;
: ''choiceName(interfaceName)'' &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''structAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''choiceName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
;''interfaceName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
These select a particular link support and interface for the field, and set its address according to the structure type defined for that link type.&lt;br /&gt;
&lt;br /&gt;
   calcout foo:temperature:controller = {&lt;br /&gt;
       output = outputLink(LinkFloat64){&lt;br /&gt;
                pvname = &amp;quot;fum:baz:heater&amp;quot;;&lt;br /&gt;
                process = true;&lt;br /&gt;
                wait = true;&lt;br /&gt;
                block = true;&lt;br /&gt;
       }&lt;br /&gt;
       input = [2] {&lt;br /&gt;
           {link = {&lt;br /&gt;
               monitorLink(LinkFloat64){&lt;br /&gt;
                   pvname = &amp;quot;foo:temperature:setpoint&amp;quot;;&lt;br /&gt;
                   process = false&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
           {link = {&lt;br /&gt;
               inputLink(LinkFloat64){&lt;br /&gt;
                   pvname = &amp;quot;foo:temperature:sensor&amp;quot;;&lt;br /&gt;
                   process = true;&lt;br /&gt;
                    wait = true;&lt;br /&gt;
                    block = true;&lt;br /&gt;
                   inheritSeverity = true&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
       };&lt;br /&gt;
       expression = &amp;quot;(setpoint - current) &amp;gt; 0&amp;quot;;&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   mbbi foo:bar:door = {&lt;br /&gt;
       input = acro9440(0, 5);&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
=== Array Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''arrayInitializer:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''arrayType'' &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''arrayCapacity'' &amp;lt;tt&amp;gt;] {&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''arrayType'' &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''arrayCapacity'' &amp;lt;tt&amp;gt;] {&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''arrayAssignmentList:''&lt;br /&gt;
: ''initializerList''&lt;br /&gt;
: &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''integerConstant'' &amp;lt;tt&amp;gt;] =&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
: ''arrayAssignmentList'' &amp;lt;tt&amp;gt;; [&amp;lt;/tt&amp;gt; ''integerConstant'' &amp;lt;tt&amp;gt;] =&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
&lt;br /&gt;
;''arrayType:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;int16&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;uint16&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;int32&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;uint32&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;float32&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;float64&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;octet&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''arrayCapacity:''&lt;br /&gt;
: ''integerConstant''&lt;br /&gt;
: ''arrayCapacity'' &amp;lt;tt&amp;gt;,&amp;lt;/tt&amp;gt; ''integerConstant''&lt;br /&gt;
&lt;br /&gt;
If the definition of the array field being set did not do so, an array field initialization must include the size of the array and/or the type of the data stored in it. Inside the braces data values are given in a comma-separated list; the index can also be set to initialize individual values, and any mixture of the two can be used as desired:&lt;br /&gt;
&lt;br /&gt;
   mbbi foo:bar:door = {&lt;br /&gt;
       stateNames = [4] {&amp;quot;Broken&amp;quot;, &amp;quot;Closed&amp;quot;, &amp;quot;Open&amp;quot;, &amp;quot;Moving&amp;quot;};&lt;br /&gt;
       stateSeverity = [4] {&amp;quot;Major&amp;quot;; [3] = &amp;quot;Minor&amp;quot;};&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
For multi-dimensional arrays, data values can only appear inside the inner-most sets of braces, although index settings are permitted outside of these.  These two definitions give the same result:&lt;br /&gt;
&lt;br /&gt;
   matrix identity1 = {&lt;br /&gt;
       value = float32 [3,3] { {1, 0, 0}, {0, 1, 0}, {1, 0, 0}};&lt;br /&gt;
   }&lt;br /&gt;
   matrix identity2 = {&lt;br /&gt;
       value = float32 [3,3] { {1}, {[1] = 1}, {[2] = 1}};&lt;br /&gt;
   }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=577</id>
		<title>V4 DBD Statement Syntax</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=577"/>
		<updated>2005-09-30T15:12:36Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: Changed DBD link definition&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DBD Statement Syntax Sept 30 2005&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
This document presents the syntax for V4 database definition files.&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= General Statements =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== include ==&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;filename&amp;quot;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;filename&amp;lt;/tt&amp;gt;&lt;br /&gt;
: must be a valid filename&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Include statements can be used at the top level, or inside the braces of a &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definition.&lt;br /&gt;
&lt;br /&gt;
== # comment ==&lt;br /&gt;
&lt;br /&gt;
 # anything&lt;br /&gt;
&lt;br /&gt;
Anything on a line after a &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; 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 &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; character has no special meaning.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== menu ==&lt;br /&gt;
&lt;br /&gt;
A menu is an enumerated type where the choice strings are defined once for each IOC.  Menus are defined like this:&lt;br /&gt;
&lt;br /&gt;
 menu(menuName) {&lt;br /&gt;
     choice(choiceName, &amp;quot;choiceValue&amp;quot;)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can be any UTF-8 compatible string, which should be unique within the context of this menu.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 menu(menuScan) {&lt;br /&gt;
     choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
     choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
     choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
     choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
     choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Structures, Record types, Fields and Views =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== struct ==&lt;br /&gt;
&lt;br /&gt;
A structure is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 struct(name) {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The structure name must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular structure.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
&lt;br /&gt;
== record ==&lt;br /&gt;
&lt;br /&gt;
A record type is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 record(name) extends RecordCommon {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     view(viewName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The record type name. It must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;extends RecordCommon&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This states that the record type extends the set of fields defined in &amp;quot;V4 DB RecordCommon&amp;quot;. 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 &amp;lt;tt&amp;gt;extends&amp;lt;/tt&amp;gt; phrase.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular record type and its parents (extends ...).&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#Views of a record|Views of a record]] below.&lt;br /&gt;
&lt;br /&gt;
== fieldType ==&lt;br /&gt;
&lt;br /&gt;
Both &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; define a field as:&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The syntax for &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
=== Basic types: octet, boolean, numerics, and string ===&lt;br /&gt;
&lt;br /&gt;
The following field types have no arguments:&lt;br /&gt;
&amp;lt;tt&amp;gt;octet&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int32&amp;lt;/tt&amp;gt;,  &amp;lt;tt&amp;gt;int64&amp;lt;/tt&amp;gt;,&lt;br /&gt;
&amp;lt;tt&amp;gt;float32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;float64&amp;lt;/tt&amp;gt;,  and &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Examples: &lt;br /&gt;
     field(description,string)&lt;br /&gt;
     field(value,float64)&lt;br /&gt;
&lt;br /&gt;
=== enum ===&lt;br /&gt;
&lt;br /&gt;
An &amp;lt;tt&amp;gt;enum&amp;lt;/tt&amp;gt; field takes one argument after the type name:&lt;br /&gt;
&lt;br /&gt;
     enum(fieldName)&lt;br /&gt;
&lt;br /&gt;
where fieldName is the name of another field in the same record that must be of type &amp;lt;tt&amp;gt;array(string[])&amp;lt;/tt&amp;gt;.  The values in this other field at runtime define the available choice strings for the enum field.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
     field(choices, array(string[])&lt;br /&gt;
     field(value, enum(choices))&lt;br /&gt;
&lt;br /&gt;
=== menu ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt; field is defined like this:&lt;br /&gt;
     menu(menuName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt; is the name of the menu.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     field(scan, menu(menuScan))&lt;br /&gt;
&lt;br /&gt;
=== struct ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; field is declared using the type name&lt;br /&gt;
     struct(structName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;structName&amp;lt;/tt&amp;gt; is the name of a struct which must have been previously defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
      struct(Point) {&lt;br /&gt;
          field(x,float64)&lt;br /&gt;
          field(y,float64)&lt;br /&gt;
          field(z,float64)&lt;br /&gt;
       }&lt;br /&gt;
       ...&lt;br /&gt;
       record(haspoint) extends RecordCommon {&lt;br /&gt;
           ...&lt;br /&gt;
           field(point, struct(point))&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
=== array ===&lt;br /&gt;
&lt;br /&gt;
An array field uses definitions like these:&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 3-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[,,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 2-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;arrayType&amp;lt;/tt&amp;gt; may be any fieldType except &amp;lt;tt&amp;gt;array&amp;lt;/tt&amp;gt;, 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]]&lt;br /&gt;
* &amp;lt;tt&amp;gt;capacity&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(VAL1D,array(float64[]))  #1d array with arbitrary capacity&lt;br /&gt;
     field(VAL2D,array(float64[,])) #2d array with arbitrary capacities&lt;br /&gt;
     field(anyTypeAnyD,array())     #arbitrary type,number of dimensions, and capacities&lt;br /&gt;
&lt;br /&gt;
=== link ===&lt;br /&gt;
&lt;br /&gt;
This field type can get or put data from/to some source outside of the record.&lt;br /&gt;
Link fields replace the DBF_INLINK, DBF_OUTLINK, and DTYP fields from EPICS V3.&lt;br /&gt;
&lt;br /&gt;
A link field's choices come from link definitions - see the [[#link]] section below for more details.&lt;br /&gt;
A link can be a link to another database record, to hardware device support,&lt;br /&gt;
or something else.&lt;br /&gt;
&lt;br /&gt;
The syntax is:&lt;br /&gt;
&lt;br /&gt;
     link(linkDirection,interface(interfaceName,...))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;ANDREW&amp;lt;/b&amp;gt;&lt;br /&gt;
What syntax should we use?&lt;br /&gt;
The idea is that the record definition gives a list of interfaces it understands.&lt;br /&gt;
&lt;br /&gt;
where &lt;br /&gt;
* &amp;lt;tt&amp;gt;linkDirection&amp;lt;/tt&amp;gt; : &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. The direction &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt; means there is no direction associated with this interface.  For &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt; the direction is determined by the particular &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; that the record instance selects.&lt;br /&gt;
* &amp;lt;tt&amp;gt;interface(string,...)&amp;lt;/tt&amp;gt; : Each interfaceName is the name of an interface implemented by link support and used by record support.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(disableLink,&lt;br /&gt;
        link(in,interface ( LinkInt32, LinkFloat64 ))&lt;br /&gt;
     )&lt;br /&gt;
     field(process, link(process,interface(ProcessLink))&lt;br /&gt;
     field(inp,&lt;br /&gt;
        link(in, interface (LinkInt32, LinkFloat64, AsynDigital))&lt;br /&gt;
     )&lt;br /&gt;
&lt;br /&gt;
== fieldAttribute ==&lt;br /&gt;
&lt;br /&gt;
Each field definition has several associated attributes, the values of which are set like this:&lt;br /&gt;
&lt;br /&gt;
     default(&amp;quot;fieldValue&amp;quot;)&lt;br /&gt;
     readonly(yesNo)&lt;br /&gt;
     design(yesNo)&lt;br /&gt;
     special(yesNo)&lt;br /&gt;
     asl(securityLevel)&lt;br /&gt;
     link(yesNo)&lt;br /&gt;
&lt;br /&gt;
'''Marty thinks we should get rid of these two:'''&lt;br /&gt;
     prompt(&amp;quot;promptString&amp;quot;)&lt;br /&gt;
     group(&amp;quot;promptGroup&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
'''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.'''&lt;br /&gt;
&lt;br /&gt;
The attribute parameter values have the following meanings:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;default(&amp;quot;fieldValue&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;readonly(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can this field be modified via channel access or database links?  Takes the value No if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;design(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;special(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;asl(securityLevel)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Channel Access security level for this field, 0 or 1.  Takes the value 1 if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
''These attributes may disappear, see comment above:''&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;prompt(&amp;quot;promptString&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;group(&amp;quot;promptGroup&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
== view ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;field&amp;quot; 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).&lt;br /&gt;
&lt;br /&gt;
A simple view looks like this:&lt;br /&gt;
&lt;br /&gt;
 view(viewName) {&lt;br /&gt;
     property(propName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     property(propName, fieldPath)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The view name must be a valid C identifier, which must be unique in the context of the particular record type.&lt;br /&gt;
; &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: A Data Access property name, which must be a valid C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The path to a field in this record type. To use a field inside a structure field, give the full path to that field: &amp;lt;tt&amp;gt;controlLimit.upper&amp;lt;/tt&amp;gt; for example.&lt;br /&gt;
: If &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; resolves to a structure, a property catalog containing the whole structure will be sent, with property names matching the structure's field names.&lt;br /&gt;
: The &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; may be omitted as long as there is a subordinate property catalog below this property.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 record(ao) extends RecordCommon {&lt;br /&gt;
     field(value, float64) { ... }&lt;br /&gt;
     field(outValue, float64) { ... }&lt;br /&gt;
     field(rawValue, int32) { ... }&lt;br /&gt;
     field(units, string) { ... }&lt;br /&gt;
     field(displayLimit, struct(displayLimit)) { ... }&lt;br /&gt;
     ...&lt;br /&gt;
     view(value)&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(outValue)&lt;br /&gt;
         property(value, outValue) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(rawValue)&lt;br /&gt;
         property(value, rawValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= link =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; statement describes an implementation of support for a link&lt;br /&gt;
field. the support can be any of the following:&lt;br /&gt;
* A link to another record either local or remote&lt;br /&gt;
* A link to hardware support&lt;br /&gt;
* Something else.&lt;br /&gt;
&lt;br /&gt;
The syntax for these is:&lt;br /&gt;
&lt;br /&gt;
 link(dir, choiceName,  dataStructName, interface(interfaceName,...))&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dir&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be one of &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. Compatible checks are made to match the interface with a field.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools do prompt the user to assign values to the structure.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interface&amp;lt;/tt&amp;gt;&lt;br /&gt;
: A list of the interfaces implemented by the link support&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When a record instance is created the choiceName and interfaceName&lt;br /&gt;
selects the support to attach to a record link.&lt;br /&gt;
The interfaceName must be one of the&lt;br /&gt;
interface names the record has listed as a valid type and dir must be compatible&lt;br /&gt;
with the dir the record type specified.&lt;br /&gt;
Compatibility means that the dir specified in the link definition is at&lt;br /&gt;
least as generic as the link definition in the record.&lt;br /&gt;
If the record link dir is:&lt;br /&gt;
; &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The link definition must also be &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The link definition must also be &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The link definition must be &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The link definition must be &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The link definition must be &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     link(process,processLink,ProcessLinkData,interface(ProcessLink))&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLink,MonitorLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=564</id>
		<title>V4 DB RecordCommon</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=564"/>
		<updated>2005-09-30T15:11:15Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Standard Support September 30 2005 &lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
For V4 dbCommon.dbd and RecordCommon.dbd replace the V3 dbCommon.dbd.&lt;br /&gt;
dbCommon.dbd defines widely used definitions and RecordCommon.dbd defines&lt;br /&gt;
the fields that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This document requires that the reader be familiar with:&lt;br /&gt;
# V3 iocCore&lt;br /&gt;
# V4 DBD Statement Syntax&lt;br /&gt;
# V4 DB Record Instance Syntax&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= dbCommon =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Support ==&lt;br /&gt;
&lt;br /&gt;
=== Data Structures ===&lt;br /&gt;
     struct(MonitorLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean) &lt;br /&gt;
     }&lt;br /&gt;
     struct(InputLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(OutputLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ProcessLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link support definitions ===&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* input&lt;br /&gt;
** monitor support&lt;br /&gt;
** input support&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For input and output The following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
     link(process,processLink,ProcessLinkData,interface(ProcessLink))&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLink,MonitorLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,monitorLinkArray,MonitorLinkData interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLink,InputLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,inputLinkArray,InputLinkData interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,outputLink,OutputLinkData interface(&lt;br /&gt;
         LinkBoolean,&lt;br /&gt;
         LinkInt16,LinkInt32,LinkInt64,&lt;br /&gt;
         LinkFloat32,LinkFloat64,&lt;br /&gt;
         LinkString&lt;br /&gt;
     ))&lt;br /&gt;
     link(in,outputLinkArray,OutputLinkData interface(&lt;br /&gt;
         LinkArrayOctet,LinkArrayBoolean,&lt;br /&gt;
         LinkArrayInt16,LinkArrayInt32,LinkArrayInt64,&lt;br /&gt;
         LinkArrayFloat32,LinkArrayFloat64,&lt;br /&gt;
         LinkArrayString&lt;br /&gt;
     ))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLinkData) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link definitions ===&lt;br /&gt;
&lt;br /&gt;
     link(inout,asynInt32,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Average,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(in,asynInt32Monitor,AsynLinkData,interface(LinkInt32))&lt;br /&gt;
     link(inout,asynFloat64,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Average,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynFloat64Monitor,AsynLinkData,interface(LinkFloat64))&lt;br /&gt;
     link(in,asynDigitalMonitor,AsynLinkData,interface(AsynDigital))&lt;br /&gt;
     link(inout,asynDigital,AsynLinkData,interface(AsynDigital)))&lt;br /&gt;
     link(inout,asynInt32Array,AsynLinkData,interface(LinkArrayInt32)))&lt;br /&gt;
     link(inout,asynFloat64Array,AsynLinkData,interface(LinkArrayFloat64)))&lt;br /&gt;
     link(inout,asynOctet,AsynLinkData,interface(AsynOctet)))&lt;br /&gt;
== Other common definitions ==&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;Raw&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     # usefull struct definitions&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(full,float64) &lt;br /&gt;
         field(egul,float64)&lt;br /&gt;
         field(slope,float64) &lt;br /&gt;
         field(intercept,float64) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ControlLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
     }&lt;br /&gt;
     struct(AlarmLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(lowSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(lowWarning,float64) &lt;br /&gt;
         field(lowWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(highWarning,float64) &lt;br /&gt;
         field(highWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
         field(highSevr,menu(menuAlarmSevr)) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= RecordCommon =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Menu Definitions ==&lt;br /&gt;
&lt;br /&gt;
     # menu definitions for RecordCommon fields&lt;br /&gt;
     menu(menuPriority) {&lt;br /&gt;
         choice(menuPriorityLow, &amp;quot;Low&amp;quot;)&lt;br /&gt;
         choice(menuPriorityMedium, &amp;quot;Medium&amp;quot;)&lt;br /&gt;
         choice(menuPriorityHigh, &amp;quot;High&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuScan) {&lt;br /&gt;
         choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
         choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
         choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
         choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
         choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuAlarmSevr) {&lt;br /&gt;
         choice(menuAlarmSevrNone, &amp;quot;None&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMinor, &amp;quot;Minor&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMajor, &amp;quot;Major&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrInvalid, &amp;quot;Invalid&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
== struct definitions for RecordSupport ==&lt;br /&gt;
     struct(TimeStamp) {&lt;br /&gt;
         field(secondsPastEpoch,int64)&lt;br /&gt;
         field(nanoSeconds,int32)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Scan {&lt;br /&gt;
         field(scan,menu(menuScan)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(phase,int16)&lt;br /&gt;
         field(priority,menu(menuPriority)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;b&amp;gt;Event NEEDS NEW DEFINITIONS&amp;lt;/b&amp;gt;&lt;br /&gt;
     struct Event {&lt;br /&gt;
         field(eventNumber,int16) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(timeStampEvent,int16)&lt;br /&gt;
         field(timeStampLink,link(in,interface(????))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Disable {&lt;br /&gt;
         field(disableValue,int16) {&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(disableInput,int16)&lt;br /&gt;
         field(disableLink,link(in,interface(LinkBoolean)))&lt;br /&gt;
         field(disableAlarmSeverity,menu(menuAlarmSevr))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== RecordCommon Record Definition ==&lt;br /&gt;
&lt;br /&gt;
     struct(RecordCommonProcessLink) {&lt;br /&gt;
         field(link,link(process,interface(ProcessLink)))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     record(RecordCommon) {&lt;br /&gt;
         field(description,string)&lt;br /&gt;
         field(scan,struct(Scan))&lt;br /&gt;
         field(event,struct(Event))&lt;br /&gt;
         field(accessSecurityGroup,string)&lt;br /&gt;
         field(pini,boolean)&lt;br /&gt;
         field(disablePutField,boolean)&lt;br /&gt;
         field(alarmAckSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmAckTransient,boolean) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;YES&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(udf,boolean) {&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(time,struct(TimeStamp)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(disable,struct(Disable)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmStatus,string) {&lt;br /&gt;
             default(&amp;quot;UDF&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;Invalid&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(processLink,array(RecordCommonProcessLink[])) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Although it has many fewer fields,&lt;br /&gt;
RecordCommon.dbd is a complete replacement for the V3 dbCommon.&lt;br /&gt;
The following V3 fields are no longer needed:&lt;br /&gt;
* private fields - Private fields will truly be privaye to the implementation&lt;br /&gt;
* previous value fields - All puts to database fields will be posted. The layer above will decide if clients should be notified of changes.&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=551</id>
		<title>V4 Link Support Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Link_Support_Tutorial&amp;diff=551"/>
		<updated>2005-09-29T19:26:18Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Link Support Tutorial Sept 29 2005&lt;br /&gt;
&amp;lt;b&amp;gt;UNDER CONSTRUCTION&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
The V4 link support is a replacement for V3 &lt;br /&gt;
# DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK&lt;br /&gt;
# device DBD definition and device support&lt;br /&gt;
# driver DBD definition and driver support&lt;br /&gt;
&lt;br /&gt;
The link support model is:&lt;br /&gt;
* For each link, record support defines a list of interfaces it can use for communicating with link support&lt;br /&gt;
* Link support registers the set of interfaces it implements&lt;br /&gt;
&lt;br /&gt;
Link support has no knowledge of what record types are using it&lt;br /&gt;
and record support has no knowledge about link support other than the&lt;br /&gt;
interface it is using.&lt;br /&gt;
&lt;br /&gt;
EPICS base defines a standard set of interfaces for link support.&lt;br /&gt;
The intention is that the set includes enough functionality such that&lt;br /&gt;
most link support can be implemented via just these interfaces.&lt;br /&gt;
&lt;br /&gt;
The interfaces support all the functionality needed by Channel/Database access&lt;br /&gt;
and by the generic EPICS device support supplied by asynDriver.&lt;br /&gt;
Since asynDriver is intended as a framework for interfacing to most hardware,&lt;br /&gt;
this means that the interfaces supplied and used by base allows support&lt;br /&gt;
for most hardware. The support can communicate with the hardware&lt;br /&gt;
however it wants but must implement some set of the interfaces defined&lt;br /&gt;
by base.&lt;br /&gt;
&lt;br /&gt;
This document gives a brief overview of the V4 link support model.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Database Definitions For Links =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section first reviews the DBD syntax related to link definitions.&lt;br /&gt;
It then gives a brief description of link related definitions in dbCommon.dbd&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
A record link has the syntax:&lt;br /&gt;
     link(linkDirection,interface(string,...))&lt;br /&gt;
A link itself has the syntax:&lt;br /&gt;
     link(linkDirection, choiceName, interfaceName, dataStructName)&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;linkDirection&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be one of &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. Compatible checks are made to match the interface with a field.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interface&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is a list of the interfaces that the record support understands.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of an interface via which record support communicates with device support.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools do prompt the user to assign values to the structure.&lt;br /&gt;
&lt;br /&gt;
When a record instance is created the choiceName selects the support&lt;br /&gt;
to attach to a record link. The interfaceName must be one of the&lt;br /&gt;
interface names the record has listed as a valid type and linkDirection must be compatible&lt;br /&gt;
with the linkDirection the record type specified.&lt;br /&gt;
&lt;br /&gt;
== Standard Definitions For Channel/Database Access ==&lt;br /&gt;
&lt;br /&gt;
These are the database definitions defined in dbCommon are used by&lt;br /&gt;
the base supplied support for Channel/Database access.&lt;br /&gt;
&lt;br /&gt;
=== Data Structures ===&lt;br /&gt;
&lt;br /&gt;
The complete set of definitions are defined in &amp;quot;V4 DB RecordCommon&amp;quot;.&lt;br /&gt;
     struct(MonitorLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(InputLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     ... also OutputLinkData and ProcessLinkData&lt;br /&gt;
&lt;br /&gt;
A look at the fields shows that these are what is required to implement&lt;br /&gt;
the V4 semantics for Channel/Database access links.&lt;br /&gt;
&lt;br /&gt;
=== Link Definitions ===&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* input&lt;br /&gt;
** monitor support&lt;br /&gt;
** input support&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For input and output The following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
&amp;quot;V4 DB RecordCommon&amp;quot; describes the complete set of link definitions&lt;br /&gt;
supplied by EPICS base. Some examples are:&lt;br /&gt;
&lt;br /&gt;
     link(process,processLink,ProcessLink,ProcessLinkData);&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLinkArrayOctet,LinkArrayOctet,MonitorLinkData);&lt;br /&gt;
     link(in,inputLinkArrayOctet,LinkArrayOctet,InputLinkData);&lt;br /&gt;
     link(out,outputLinkArrayOctet,LinkArrayOctet,OutputLinkData);&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLinkBoolean,LinkBoolean,MonitorLinkData);&lt;br /&gt;
     ...&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLinkInt16,LinkInt16,MonitorLinkData);&lt;br /&gt;
     link(in,monitorLinkInt32,LinkInt32,MonitorLinkData);&lt;br /&gt;
     link(in,monitorLinkInt64,LinkInt64,MonitorLinkData);&lt;br /&gt;
     ...&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLinkFloat32,LinkFloat32,MonitorLinkData);&lt;br /&gt;
     link(in,monitorLinkFloat64,LinkFloat64,MonitorLinkData);&lt;br /&gt;
     ...&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLinkArrayString,LinkArrayString,MonitorLinkData);&lt;br /&gt;
     link(in,inputLinkArrayString,LinkArrayString,InputLinkData);&lt;br /&gt;
     link(out,outputLinkArrayString,LinkArrayString,OutputLinkData);&lt;br /&gt;
&lt;br /&gt;
These are the link definitions for the Channel/Database access link&lt;br /&gt;
support supplied with base. The support registers support for processLink,&lt;br /&gt;
monitorLinkArrayOctet, ...&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
&lt;br /&gt;
These are definitions that are used by the standard EPICS device support&lt;br /&gt;
for asynDriver. Since asynDriver is a generic way of interfacing arbitrary&lt;br /&gt;
hardware support, this is a generic way of attaching links in records to&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLinkData) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link definitions ===&lt;br /&gt;
&lt;br /&gt;
     link(inout,asynInt32,LinkInt32,AsynLinkData)&lt;br /&gt;
     link(in,asynInt32Average,LinkInt32,AsynLinkData)&lt;br /&gt;
     link(in,asynInt32Monitor,LinkInt32,AsynLinkData)&lt;br /&gt;
     link(inout,asynFloat64,LinkFloat64,AsynLinkData)&lt;br /&gt;
     link(in,asynFloat64Average,LinkFloat64,AsynLinkData)&lt;br /&gt;
     link(in,asynFloat64Monitor,LinkFloat64,AsynLinkData)&lt;br /&gt;
     link(in,asynDigitalMonitor,AsynDigital,AsynLinkData)&lt;br /&gt;
     link(inout,asynDigital,AsynDigital,AsynLinkData)&lt;br /&gt;
     link(inout,asynInt32Array,LinkArrayInt32,AsynLinkData)&lt;br /&gt;
     link(inout,asynFloat64Array,LinkArrayFloat64,AsynLinkData)&lt;br /&gt;
     link(inout,asynOctet,AsynOctet,AsynLinkData)&lt;br /&gt;
&lt;br /&gt;
This is the set of definitions for the standard EPICS device support implemented&lt;br /&gt;
by asynDriver. Although, at least for the first few V4 releases,&lt;br /&gt;
asynDriver will not be part of base, they are shown here because the&lt;br /&gt;
LinkInt32,... interface definitions are defined as part of base.&lt;br /&gt;
Again it is expected that almost all hardware support be created by&lt;br /&gt;
implementing a combination of these link interface definitions or&lt;br /&gt;
the interfaces implemented by Channel/Database access link support.&lt;br /&gt;
---&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
An arbitrary number of Link Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
&lt;br /&gt;
Other link support can also be supplied.&lt;br /&gt;
New support should try very hard to implement the standard interfaces&lt;br /&gt;
supplied by EPICS base. These are the interfaces that the record types&lt;br /&gt;
supplied with base know how to use.&lt;br /&gt;
&lt;br /&gt;
Soft support should try to implement the same interfaces implemented by&lt;br /&gt;
the Channel/Database access support supplied with base. The support&lt;br /&gt;
can, of course, define data structures for it's own use.&lt;br /&gt;
Implementing these interfaces means that nthe support will work for&lt;br /&gt;
the same set of record links as the Channel/Database access support.&lt;br /&gt;
&lt;br /&gt;
Hardware support should, if possible, also implement the same interfaces&lt;br /&gt;
implemented by the Channel/Database access support.&lt;br /&gt;
Message based support may also have to implement the AsynOctet interface&lt;br /&gt;
but this interface is only used by a few record links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This section describes the interfaces implemented by all link support&lt;br /&gt;
and then the standard interfaces used by the records supplied with base.&lt;br /&gt;
&lt;br /&gt;
== Link and MonitorLink ==&lt;br /&gt;
&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; is an interface that is implemented by link support that&lt;br /&gt;
supports monitors. An example is support for hardware interrupts.&lt;br /&gt;
The &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally record support does not need to call any of the Link &lt;br /&gt;
or MonitorLink methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call destroy before modifying the link&lt;br /&gt;
and initialize and connect after the link is modified.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
These are the definitions used by the Channel/Database access support&lt;br /&gt;
supplied with base. It is also used by the standard EPICS support from asyn.&lt;br /&gt;
&lt;br /&gt;
     enum LinkWaitResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
         linkWaitBlock,      // waiting. dont do additional processing until&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface ProcessLinkSupport&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
There is no support for octet but there is support for an array of octets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkWaitResult getWait(octet[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(octet[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The data source must be an array of octets or the connect request will fail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;GENERIC QUESTION&amp;lt;/b&amp;gt; The data is passed as primitive or arrays of&lt;br /&gt;
primitive types. Should &amp;lt;tt&amp;gt;Dbf&amp;lt;/tt&amp;gt; interfaces be used? Needs thought.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkWaitResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkWaitResult write(octet[] value, octet[] mask);&lt;br /&gt;
          LinkWaitResult read(octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkWaitResult getWait(Boolean data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(boolean data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkWaitResult getWait(boolean[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(boolean[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be int16, int32, or int64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         void getBounds(&amp;lt;type&amp;gt; low, &amp;lt;type&amp;gt; high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     } &lt;br /&gt;
         &lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be float32 or float64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkWaitResult getWait(string data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(string data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkWaitResult getWait(string[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(string[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Example - VME ADC support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
== DBD definitions ==&lt;br /&gt;
The following struct is defined for configuration information.&lt;br /&gt;
     struct VMEADC {&lt;br /&gt;
         field(a16 int16)&lt;br /&gt;
         field(a32 int32)&lt;br /&gt;
         field(channel int16)&lt;br /&gt;
     }&lt;br /&gt;
The following link definition is defined:&lt;br /&gt;
     link(in,myAdcSupport,LinkInt32,VMEADC)&lt;br /&gt;
&lt;br /&gt;
This allows record instance definitions like:&lt;br /&gt;
     AiRecord aiExample = {&lt;br /&gt;
        ...&lt;br /&gt;
        input = myAdcSupport{a16=0x0010;channel=1}&lt;br /&gt;
        ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The link support would be something like:&lt;br /&gt;
&lt;br /&gt;
     class AdcSupport : public Link LinkInt32 {&lt;br /&gt;
     public:&lt;br /&gt;
     AdcSupport(VMEADCData fromFactory) : data(fromFactory) connected(false)&lt;br /&gt;
     {&lt;br /&gt;
         //  from the VMEADC initailze vmeaddr and channel&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Link methods&lt;br /&gt;
     void report(int16_t level)&lt;br /&gt;
     {&lt;br /&gt;
         printf(&amp;quot;AdcSupport a16 %x channel %d\n&amp;quot;,a16,channel);&lt;br /&gt;
     }&lt;br /&gt;
     void cancel() {} // nothing to do&lt;br /&gt;
     void destroy() {delete this};&lt;br /&gt;
     void initialize()&lt;br /&gt;
     {&lt;br /&gt;
         // make sure we can access a16&lt;br /&gt;
     }&lt;br /&gt;
     void connect() {connected = true}&lt;br /&gt;
     void disconnect() {connected = false}&lt;br /&gt;
     &lt;br /&gt;
     // LinkInt32 methods&lt;br /&gt;
     LinkWaitResult getWait(int32_t *data,Callback callback)&lt;br /&gt;
     {&lt;br /&gt;
         *data = (int32_t)vmeaddr[1];&lt;br /&gt;
         return linkDone;&lt;br /&gt;
     }&lt;br /&gt;
     LinkWaitResult putWait(int32_t *data,Callback callback)&lt;br /&gt;
     {&lt;br /&gt;
         throw CantWriteAdc;&lt;br /&gt;
     }&lt;br /&gt;
     void getBounds(int32_t *low, int32_t *high) &lt;br /&gt;
     {&lt;br /&gt;
         // assume 16 bit unipolor adc&lt;br /&gt;
         *low = 0; *high = 0xffff;&lt;br /&gt;
     }&lt;br /&gt;
     private:&lt;br /&gt;
         VMEADCData data;&lt;br /&gt;
         uint16_t *vmeaddr;&lt;br /&gt;
         int channel;&lt;br /&gt;
         bool connected;&lt;br /&gt;
     }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=Ancient_V4_Design&amp;diff=552</id>
		<title>Ancient V4 Design</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=Ancient_V4_Design&amp;diff=552"/>
		<updated>2005-09-29T18:22:58Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page links to various documents for discussion by the EPICS core developers.&lt;br /&gt;
&lt;br /&gt;
'''Code to implement this stuff doesn't exist yet, and the designs may change!'''&lt;br /&gt;
&lt;br /&gt;
''Note to authors: please use 'V4' at the start of page names for Version 4 documentation, as this makes it clear which wiki pages refer to the new designs just from the page name.''&lt;br /&gt;
&lt;br /&gt;
I've started listing some discussion topics for a [[V4 July Meeting Agenda]], feel free to add to these - Andrew Johnson&lt;br /&gt;
&lt;br /&gt;
== Overall Design ==&lt;br /&gt;
* [[V4 Use Cases]] - Bob Dalesio, Kay Kasemir&lt;br /&gt;
&lt;br /&gt;
== Core and Database ==&lt;br /&gt;
&lt;br /&gt;
* [[V4 Modules and Interfaces]] - Andrew Johnson&lt;br /&gt;
&lt;br /&gt;
* [[V4 Requirements for Standard Types]] - Andrew Johnson&lt;br /&gt;
* [[V4 Standard Properties and Events]] - Andrew Johnson&lt;br /&gt;
&lt;br /&gt;
* V4 Database Definition - Marty Kraimer, Andrew Johnson&lt;br /&gt;
** [[V4 DBD Statement Syntax]] - Marty Kraimer, Andrew Johnson&lt;br /&gt;
** [[V4 DB Record Instance Syntax]] - Andrew Johnson&lt;br /&gt;
** [[V4 DB RecordCommon]] - Marty Kraimer&lt;br /&gt;
** [[V4 DBD Examples]] - Marty Kraimer, Andrew Johnson&lt;br /&gt;
** [[V4 Link Support Tutorial]] - Marty Kraimer&lt;br /&gt;
** [[V4 View Generated Code]] - Andrew Johnson&lt;br /&gt;
&lt;br /&gt;
* V4 Database Runtime&lt;br /&gt;
** [[V4 Design: Record Processing]] - Marty Kraimer&lt;br /&gt;
** [[V4 Design: dbdInterfaces]] - Marty Kraimer&lt;br /&gt;
** [[V4 Design: Runtime Interfaces]] - Marty Kraimer&lt;br /&gt;
** [[V4 Design: RecordCommon Support]] - Marty Kraimer&lt;br /&gt;
&lt;br /&gt;
* V4 Database Access:&lt;br /&gt;
** [[V4 Design: epicsTypes]] - Marty Kraimer, Andrew Johnson&lt;br /&gt;
** [[V4 Design: Assembling Record Support]] - Ben Franksen&lt;br /&gt;
** [[V4 Design: driverInterfaces]] - Marty Kraimer&lt;br /&gt;
&lt;br /&gt;
* [[V4 User-defined fields]] - Kay Kasemir&lt;br /&gt;
&lt;br /&gt;
* [[V4 Server Side Plugins]] - Ralph Lange, Benjamin Franksen&lt;br /&gt;
&lt;br /&gt;
* Obsolete&lt;br /&gt;
** [[V4 DBD dbCommon and iocRecord]] - Marty Kraimer&lt;br /&gt;
** [[V4 DBD Generated Code]] - Marty Kraimer&lt;br /&gt;
** [[V4 Design: dbdClass]] - Marty Kraimer&lt;br /&gt;
** [[V4 Design: dbdClass Examples]] - Marty Kraimer&lt;br /&gt;
** [[V4 Design: Database Initialization]] - Marty Kraimer&lt;br /&gt;
** [[V4 Design: Database Access Semantics]] - Marty Kraimer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Network Communications ==&lt;br /&gt;
&lt;br /&gt;
* [[V4 Name Server]] - Doug Murray, Kay Kasemir&lt;br /&gt;
* [[V4 CA Interfaces]] - Jeff Hill&lt;br /&gt;
* [[V4 CA Client User Interface]] - Doug Murray, Kay Kasemir&lt;br /&gt;
* [[V4 Data Interface]] - Kay Kasemir&lt;br /&gt;
* [[V4 CA example timeStamp, sevr, status, data]] - Marty Kraimer&lt;br /&gt;
&lt;br /&gt;
== Other Services ==&lt;br /&gt;
&lt;br /&gt;
* [[V4 Replacement for drvTS]] - Timo Korhonen&lt;br /&gt;
* [[V4 Replacement for SNL]] - Ben Franksen, Go&amp;quot;tz Pfeiffer&lt;br /&gt;
* [[V4 Data Store]] - Ralph Lange&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_RecordCommon_Support&amp;diff=553</id>
		<title>V4 Design: RecordCommon Support</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_RecordCommon_Support&amp;diff=553"/>
		<updated>2005-09-28T19:41:08Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: RecordCommonSupport - September 22 2005 &lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;THIS WIKI IS OUT OF SYNC WITH OTHER WIKI PAGES. IT NEEDS LOTS OF WORK&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This document describes the implementation of the record support&lt;br /&gt;
for RecordCommon, i.e. the set of fields associated with every record type.&lt;br /&gt;
&lt;br /&gt;
For V4 dbCommon.dbd and RecordCommon.dbd replace the V3 dbCommon.dbd.&lt;br /&gt;
dbCommon.dbd define widely used definitions and RecordCommon.dbd defines&lt;br /&gt;
the fields that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This document describes the following:&lt;br /&gt;
&lt;br /&gt;
* The code automatically generated from dbCommon.dbd and RecordCommon.dbd&lt;br /&gt;
* A proposed implementation of RecordCommonSupport.&lt;br /&gt;
&lt;br /&gt;
This document requires that the reader be familiar with:&lt;br /&gt;
# V3 iocCore&lt;br /&gt;
# V4 Design: Record Processing&lt;br /&gt;
# V4 Design: dbdInterfaces&lt;br /&gt;
# V4 Design: Runtime interfaces&lt;br /&gt;
# V4 Design: RecordCommon&lt;br /&gt;
&lt;br /&gt;
Unless the reader is familiar with these most of this document will&lt;br /&gt;
be very difficult to understand.&lt;br /&gt;
&lt;br /&gt;
Java is used as the example code for two reasons:&lt;br /&gt;
# For V4 iocCore it is intended that both C++ and Java implementations will be provided. Since V3 is only implemented in C and C++ the Java implemention of V4 is described first to make sure that the interfaces defined in dbdInterfaces will work for Java.&lt;br /&gt;
# Java provides facilities that make it easy to handle strings, arrays, and structures.&lt;br /&gt;
&lt;br /&gt;
An implementaion of RecordCommonSupport is presented for two reasons:&lt;br /&gt;
# It demonstrates how to implement code that uses or implements the interface described in &amp;quot;V4 Design: dbdInterfaces&amp;quot; and &amp;quot;V4 Design: Runtime interfaces&amp;quot;.&lt;br /&gt;
# It helps refine the interfaces described in them&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= dbCommon.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the description of &amp;lt;tt&amp;gt;dbCommon.dbd&amp;lt;/tt&amp;gt; in &amp;quot;V4 Design: RecordCommon&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Link support must register support each of the &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
         &lt;br /&gt;
From &amp;lt;tt&amp;gt;dbCommon.dbd&amp;lt;/tt&amp;gt; the following class implementations are generated:&lt;br /&gt;
* For the link structures:&lt;br /&gt;
** &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;MonitorLinkData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MonitorLinkSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;InputLink&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;InputLinkData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;InputLinkSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;OutputLink&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OutputLinkData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;OutputLinkSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;ProcessLink&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ProcessLinkData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;ProcessLinkSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
* For TimeStamp&lt;br /&gt;
** &amp;lt;tt&amp;gt;TimeStamp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;TimeStampData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;TimeStampSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
* For Scan&lt;br /&gt;
** &amp;lt;tt&amp;gt;Scan&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ScanData&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;ScanSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See &amp;quot;V4 Design: Runtime interfaces&amp;quot; for an example of how these classes are defined.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= RecordCommon.dbd =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the description of &amp;lt;tt&amp;gt;RecordCommon.dbd&amp;lt;/tt&amp;gt; in &amp;quot;V4 Design: RecordCommon&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;RecordCommon.dbd&amp;lt;/tt&amp;gt; must be part of every record.&lt;br /&gt;
&lt;br /&gt;
Implementations of &amp;lt;tt&amp;gt;Disable&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DisableData&amp;lt;/tt&amp;gt;,&lt;br /&gt;
and &amp;lt;tt&amp;gt;DisableDataSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
are automatically generated.&lt;br /&gt;
&lt;br /&gt;
An implementations of RecordCommon is also generated.&lt;br /&gt;
See &amp;quot;V4 Design: Runtime interfaces&amp;quot; for an example of the generated&lt;br /&gt;
classes.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= RecordCommonSupport.java =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
This section describes the java implementation of RecordCommon&lt;br /&gt;
functionality. This code handles processing of the following fields&lt;br /&gt;
of RecordCommon:&lt;br /&gt;
; &amp;lt;tt&amp;gt;disable&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Decides if the record is disabled.&lt;br /&gt;
; &amp;lt;tt&amp;gt;alarmStatus&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;alarmSeverity&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The only way to change alarmStatus and alarmSeverity is via interface Common, which is implemented by RecordCommonSupport.&lt;br /&gt;
; &amp;lt;tt&amp;gt;processLink&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This is an array of process links, which replace the V3 &amp;lt;tt&amp;gt;FLNK&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following subsection contains the complete code for RecordCommonSupport.java.&lt;br /&gt;
The remaining subsections discuss each part of the code.&lt;br /&gt;
&lt;br /&gt;
== IocCommon.java ==&lt;br /&gt;
&lt;br /&gt;
This defines &lt;br /&gt;
     interface Common {&lt;br /&gt;
         bool setSeverity(AlarmSeverity severity, string status);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  RecordCommonSupport.java ==&lt;br /&gt;
     enum Mode {modeNone,modeInput,modeOutput};&lt;br /&gt;
     &lt;br /&gt;
     public class RecordCommonSupport implements RecordSupport,Callback,Common&lt;br /&gt;
     {&lt;br /&gt;
         private RecordInstance instance;&lt;br /&gt;
         private Mode           mode;&lt;br /&gt;
         private Input          input;&lt;br /&gt;
         private Output         output;&lt;br /&gt;
         private Alarm          alarm;&lt;br /&gt;
         private bool           requestProcess;&lt;br /&gt;
     &lt;br /&gt;
         // Constructor&lt;br /&gt;
         public RecordCommonSupport(RecordInstance instance) {&lt;br /&gt;
             this.instance = instance;&lt;br /&gt;
         }&lt;br /&gt;
     &lt;br /&gt;
         // Beginning of RecordSupport&lt;br /&gt;
	          public destroy() {} // destroy not needed for Java&lt;br /&gt;
         public destroy() {} // destroy not needed for Java&lt;br /&gt;
         public initialize(int pass) {&lt;br /&gt;
             if(pass==0) return;&lt;br /&gt;
             input.init(instance);&lt;br /&gt;
             output.init(instance);&lt;br /&gt;
             alarm.init(instance);&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         public processState process(processState state) {&lt;br /&gt;
             switch(state) {&lt;br /&gt;
             case processCancel:&lt;br /&gt;
	         //MUCH MORE NEEDS TO BE DONE&lt;br /&gt;
		 // MUST CANCAL ANY OUTSTANDING I/O&lt;br /&gt;
	         mode = modeNone; return processDone;&lt;br /&gt;
             case processStart: {&lt;br /&gt;
                 mode = modeInput;&lt;br /&gt;
                 requestProcess = false;&lt;br /&gt;
                 LinkWaitResult result = input.disableSupport.getWait(&lt;br /&gt;
                     input.disableInput,0.0,this);&lt;br /&gt;
                 if(result==linkNoop || result==linkDone) return processDone;&lt;br /&gt;
                 requestProcess = true;&lt;br /&gt;
             }&lt;br /&gt;
             // fall through to processInputActive&lt;br /&gt;
             case processInputActive: {&lt;br /&gt;
                 if(requestProcess) return processInputActive;&lt;br /&gt;
                 if(input.disable.disableValue == disable.disableInput)&lt;br /&gt;
                         return processDone;&lt;br /&gt;
                 return processActive;&lt;br /&gt;
             }&lt;br /&gt;
             case processDone: {&lt;br /&gt;
                 mode = modeOutput;&lt;br /&gt;
                 output.nextLink = 0;&lt;br /&gt;
                 output.numberLinksActive = 0;&lt;br /&gt;
                     &lt;br /&gt;
             }&lt;br /&gt;
             // fall through to processOutputActive&lt;br /&gt;
             case processOutputActive:&lt;br /&gt;
                 LinkWaitResult result = linkWaitParallel;&lt;br /&gt;
                 requestProcess = false;&lt;br /&gt;
                 while(output.nextLink&amp;lt; output.link.length) {&lt;br /&gt;
                     if(result==linkWaitSequential) break;&lt;br /&gt;
                     result = output.link[nextLink].support.processWait(0.0,this);&lt;br /&gt;
                     if(result==linkWaitSequential || result==linkWaitParallel)&lt;br /&gt;
                         output.numberLinksActive++&lt;br /&gt;
                     output.nextLink++;&lt;br /&gt;
                 }&lt;br /&gt;
                 if(output.numberLinksActive==0) {&lt;br /&gt;
                      mode = modeNone;&lt;br /&gt;
                      return processDone;&lt;br /&gt;
                 }&lt;br /&gt;
                 requestProcess = true;&lt;br /&gt;
                 return processOutputActive;&lt;br /&gt;
             default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         public bool special(bool after,Dbf[] field) {&lt;br /&gt;
             int nlevels = field.length;&lt;br /&gt;
             assert(nlevels&amp;gt;0);&lt;br /&gt;
             if(index==alarmStatusIndex || index==alarmSeverityIndex) {&lt;br /&gt;
                  if(!alarm.modifyingAlarm) return false;&lt;br /&gt;
                  return true;&lt;br /&gt;
             }&lt;br /&gt;
             if(!after) return;&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case disableIndex: {&lt;br /&gt;
                     if(nlevels==1) {&lt;br /&gt;
                         input.init(instance);&lt;br /&gt;
                     } else {&lt;br /&gt;
                         input.special(instance,Dbf[1]);&lt;br /&gt;
                     }&lt;br /&gt;
                     break;&lt;br /&gt;
                 }&lt;br /&gt;
                 case processLinkIndex : output.init(instance); break;&lt;br /&gt;
                 default: printf(&amp;quot;Why is special being called?\n&amp;quot;);&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         // Start of Callback methods&lt;br /&gt;
         public void done() {&lt;br /&gt;
             lock(instance);&lt;br /&gt;
             switch(mode) {&lt;br /&gt;
             case modeNone:&lt;br /&gt;
                  unlock(instance)&lt;br /&gt;
                  throw java.lang.IllegalStateException;&lt;br /&gt;
             case modeInput:&lt;br /&gt;
                 if(requestProcess) {&lt;br /&gt;
                     requestProcess = false;&lt;br /&gt;
                     DbAccess.process(instance);&lt;br /&gt;
                 }&lt;br /&gt;
                 break;&lt;br /&gt;
             case modeOutput:&lt;br /&gt;
                 output.numberLinksActive--;&lt;br /&gt;
                 if(output.numberLinksActive==0 &amp;amp;&amp;amp; requestProcess) {&lt;br /&gt;
                     requestProcess = false;&lt;br /&gt;
                     DbAccess.process(instance); &lt;br /&gt;
                 }&lt;br /&gt;
                 if(output.numberLinksActive==0 &amp;amp;&amp;amp; requestProcess)&lt;br /&gt;
                 break;&lt;br /&gt;
             }&lt;br /&gt;
             unlock(instance)&lt;br /&gt;
         }&lt;br /&gt;
         public void failure() { done(); }&lt;br /&gt;
&lt;br /&gt;
         // Start of Common methods&lt;br /&gt;
         bool setSeverity(AlarmSeverity severity, string status) {&lt;br /&gt;
             Alarm alarm = this.alarm;&lt;br /&gt;
             if(severity&amp;lt;= alarm.severity) return false;&lt;br /&gt;
             alarm.severity = severity;&lt;br /&gt;
             alarm.status = status;&lt;br /&gt;
             alarm.modifyingAlarm = true;&lt;br /&gt;
             alarm.alarmSeverity.putIndex(severity);&lt;br /&gt;
             alarm.alarmStatus.put(status);&lt;br /&gt;
             alarm.modifyingAlarm = false;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     // Definitions for modeInput&lt;br /&gt;
     class Input {&lt;br /&gt;
         DisableData disable;&lt;br /&gt;
         LinkSupport disableSupport;&lt;br /&gt;
         DbfInt16    disableInput;&lt;br /&gt;
         DbfInt16    disableValue;&lt;br /&gt;
         DbfInt16    alarmSeverity;&lt;br /&gt;
     &lt;br /&gt;
         void init(RecordInstance instance) {&lt;br /&gt;
             RecordAccess recordAccess = instance.getRecordCommonAccess();&lt;br /&gt;
             DbfLink link = recordAccess.getField(&amp;quot;disable.disableLink&amp;quot;);&lt;br /&gt;
             disableSupport = link.getSupport();&lt;br /&gt;
             DisplayLimitAccess.get(&lt;br /&gt;
                 recordAccess.getField(&amp;quot;disable&amp;quot;),disable);&lt;br /&gt;
             recordAccess.getField(&amp;quot;disable.disableInput&amp;quot;,disableInput);&lt;br /&gt;
         }&lt;br /&gt;
         void special(RecordInstance instance,Dbf field) {&lt;br /&gt;
             int16 index = Dbf.getIndex();&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case disableValueIndex:&lt;br /&gt;
                     disableValue = ((DbfInt16)Dbf).get(); break;&lt;br /&gt;
                 case disableInputIndex:&lt;br /&gt;
                     disableInput = ((DbfInt16)Dbf).get(); break;&lt;br /&gt;
                 case disableAlarmSeverityIndex:&lt;br /&gt;
                     alarmSeverity = ((dbfMenu)Dbf).getIndex(); break;&lt;br /&gt;
                 case disableLinkIndex:&lt;br /&gt;
                     init(instance); break;&lt;br /&gt;
                 default:&lt;br /&gt;
                     throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Definitions for modeOutput&lt;br /&gt;
     class OutputLink {&lt;br /&gt;
         Link        link;&lt;br /&gt;
         LinkSupport support;&lt;br /&gt;
         void init(RecordInstance instance,String linkFieldName) {&lt;br /&gt;
             RecordAccess recordAccess = instance.getRecordCommonAccess();&lt;br /&gt;
             DbfLink link = recordAccess.getField(linkFieldName);&lt;br /&gt;
             support = link.getSupport();&lt;br /&gt;
         }&lt;br /&gt;
     };&lt;br /&gt;
     &lt;br /&gt;
     class Output {&lt;br /&gt;
         int          nextLink;&lt;br /&gt;
         int          numberLinksActive;&lt;br /&gt;
         OutputLink[] link;&lt;br /&gt;
         void init(RecordInstance instance) {&lt;br /&gt;
             RecordAccess recordAccess = instance.getRecordCommonAccess();&lt;br /&gt;
             DbfArray array = recordAccess.getField(&amp;quot;processLink&amp;quot;);&lt;br /&gt;
             int n = array.getNelements();&lt;br /&gt;
             link = new OutputLink[n];&lt;br /&gt;
             for(i=0; i&amp;lt; n; i++) {&lt;br /&gt;
                 String field = &amp;quot;processLink[&amp;quot; + &amp;quot;i&amp;quot; + &amp;quot;]&amp;quot;;&lt;br /&gt;
                 link[i].init(instance,field);&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // Definitions for alarm handling&lt;br /&gt;
     class Alarm {&lt;br /&gt;
         short severity;&lt;br /&gt;
         String status;&lt;br /&gt;
         DbfMenu alarmSeverity;&lt;br /&gt;
         DbfString alarmStatus;&lt;br /&gt;
         bool modifyingAlarm;&lt;br /&gt;
         void init(RecordInstance instance) {&lt;br /&gt;
             RecordAccess recordAccess = instance.getRecordCommonAccess();&lt;br /&gt;
             alarmSeverity = recordAccess.getField(&amp;quot;alarmSeverity&amp;quot;);&lt;br /&gt;
             alarmStatus = recordAccess.getField(&amp;quot;alarmStatus&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Beginning of class definition ==&lt;br /&gt;
     enum Mode {modeNone,modeInput,modeOutput};&lt;br /&gt;
     &lt;br /&gt;
     public class RecordCommonSupport implements RecordSupport,Callback, Common&lt;br /&gt;
     {&lt;br /&gt;
         private RecordInstance instance;&lt;br /&gt;
         private Mode           mode;&lt;br /&gt;
         private Input          input;&lt;br /&gt;
         private Output         output;&lt;br /&gt;
         private Alarm          alarm;&lt;br /&gt;
         private bool           requestProcess;&lt;br /&gt;
     &lt;br /&gt;
         // Constructor&lt;br /&gt;
         public RecordCommonSupport(RecordInstance instance) {&lt;br /&gt;
             this.instance = instance;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
RecordCommonSupport implements the following interfaces:&lt;br /&gt;
; &amp;lt;tt&amp;gt;RecordSupport&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Record support for the fields in RecordCommon.&lt;br /&gt;
; &amp;lt;tt&amp;gt;Callback&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The callbacks called by link support&lt;br /&gt;
; &amp;lt;tt&amp;gt;Common&amp;lt;/tt&amp;gt;&lt;br /&gt;
: For now this just has the method &amp;lt;tt&amp;gt;setSeverity&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It has the following private fields:&lt;br /&gt;
* &amp;lt;tt&amp;gt;instance&amp;lt;/tt&amp;gt; -  The record instance to which it is attached. &amp;lt;tt&amp;gt;RecordCommonSupport&amp;lt;/tt&amp;gt; has a single constructor which is passed the &amp;lt;tt&amp;gt;RecordInstance&amp;lt;/tt&amp;gt; to which it is attached.&lt;br /&gt;
* &amp;lt;tt&amp;gt;mode&amp;lt;/tt&amp;gt; - This keeps the state for record processing:&lt;br /&gt;
** &amp;lt;tt&amp;gt;modeNone&amp;lt;/tt&amp;gt; - The record is not being processed.&lt;br /&gt;
** &amp;lt;tt&amp;gt;modeInput&amp;lt;/tt&amp;gt; - The disable link is active but not complete.&lt;br /&gt;
** &amp;lt;tt&amp;gt;modeOutput&amp;lt;/tt&amp;gt; - The processLinks are active but not complete.&lt;br /&gt;
* &amp;lt;tt&amp;gt;input&amp;lt;/tt&amp;gt; - Input is a private class that provides access to the fields of disable.&lt;br /&gt;
* &amp;lt;tt&amp;gt;output&amp;lt;/tt&amp;gt; - Output is a private class that provides access to processLink.&lt;br /&gt;
* &amp;lt;tt&amp;gt;alarm&amp;lt;/tt&amp;gt; - Alarm is a private class that provides access to fields alarmSeverity and alarmStatus.&lt;br /&gt;
* &amp;lt;tt&amp;gt;requestProcess&amp;lt;/tt&amp;gt; - This is used by callback to decide if a request should be made to process the record.&lt;br /&gt;
&lt;br /&gt;
Notes about &amp;lt;tt&amp;gt;Input&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;Output&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;Alarm&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Each of these is a private class to RecordCommonSupport.&lt;br /&gt;
* Each makes fields available to RecordCommonSupport.&lt;br /&gt;
* Each has &amp;quot;introspection&amp;quot; code that gets the values of the private fields from RecordCommon fields during record initialization of if the an RecordCommon fields is changed via a call to &amp;lt;tt&amp;gt;Dbf.put&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*  The implementations of each of these private classes is given after the implementaion of RecordCommonSupport.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RecordSupport Methods ==&lt;br /&gt;
=== initialize ===&lt;br /&gt;
     &lt;br /&gt;
         public initialize(int pass) {&lt;br /&gt;
             if(pass==0) return;&lt;br /&gt;
             input.init(instance);&lt;br /&gt;
             output.init(instance);&lt;br /&gt;
             alarm.init(instance);&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
During the first pass of initialization, nothing needs to be done.&lt;br /&gt;
Before initialize is called on pass 1, iocInit has&lt;br /&gt;
already called link support so that it connects.&lt;br /&gt;
Initialize just calls its private class init methods. They get the&lt;br /&gt;
current values of their private fields.&lt;br /&gt;
&lt;br /&gt;
=== destroy ===&lt;br /&gt;
         public destroy() {} // destroy not needed for Java&lt;br /&gt;
&lt;br /&gt;
Since Java does garbage collection destroy is not needed.&lt;br /&gt;
Note that iocCore will call all the link support destroy methods.&lt;br /&gt;
&lt;br /&gt;
=== process ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; is called by dbProcess at the beginning of record processing&lt;br /&gt;
and after the record specific record support completes.&lt;br /&gt;
During the beginning of record processing&lt;br /&gt;
process takes care of field &amp;lt;tt&amp;gt;disable&amp;lt;/tt&amp;gt;&lt;br /&gt;
During the end of record processing process&lt;br /&gt;
takes care of field &amp;lt;tt&amp;gt;processLink&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few features of &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; are:&lt;br /&gt;
* implements a state machine that handles the links.&lt;br /&gt;
* interacts with Callback, which is called by link support when links complete.&lt;br /&gt;
* interacts with special, which is called when fields in RecordCommon are modified.&lt;br /&gt;
&lt;br /&gt;
         public processState process(processState state) {&lt;br /&gt;
             switch(state) {&lt;br /&gt;
             case processCancel: mode = modeNone; return processDone;&lt;br /&gt;
             case processStart: {&lt;br /&gt;
                 mode = modeInput;&lt;br /&gt;
                 requestProcess = false;&lt;br /&gt;
                 LinkWaitResult result = input.disableSupport.getWait(&lt;br /&gt;
                     input.disableInput,0.0,this);&lt;br /&gt;
                 if(result==linkNoop || result==linkDone) return processDone;&lt;br /&gt;
                 requestProcess = true;&lt;br /&gt;
             }&lt;br /&gt;
             // fall through to processInputActive&lt;br /&gt;
             case processInputActive: {&lt;br /&gt;
                 if(requestProcess) return processInputActive;&lt;br /&gt;
                 if(input.disable.disableValue == disable.disableInput)&lt;br /&gt;
                         return processDone;&lt;br /&gt;
                 return processActive;&lt;br /&gt;
             }&lt;br /&gt;
             case processDone: {&lt;br /&gt;
                 mode = modeOutput;&lt;br /&gt;
                 output.nextLink = 0;&lt;br /&gt;
                 output.numberLinksActive = 0;&lt;br /&gt;
                     &lt;br /&gt;
             }&lt;br /&gt;
             // fall through to processOutputActive&lt;br /&gt;
             case processOutputActive:&lt;br /&gt;
                 LinkWaitResult result = linkWaitParallel;&lt;br /&gt;
                 requestProcess = false;&lt;br /&gt;
                 while(output.nextLink&amp;lt; output.link.length) {&lt;br /&gt;
                     if(result==linkWaitSequential) break;&lt;br /&gt;
                     result = output.link[nextLink].support.processWait(0.0,this);&lt;br /&gt;
                     if(result==linkWaitSequential || result==linkWaitParallel)&lt;br /&gt;
                         output.numberLinksActive++&lt;br /&gt;
                     output.nextLink++;&lt;br /&gt;
                 }&lt;br /&gt;
                 if(output.numberLinksActive==0) {&lt;br /&gt;
                      mode = modeNone;&lt;br /&gt;
                      return processDone;&lt;br /&gt;
                 }&lt;br /&gt;
                 requestProcess = true;&lt;br /&gt;
                 return processOutputActive;&lt;br /&gt;
             default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
=== special ===&lt;br /&gt;
&amp;lt;tt&amp;gt;special&amp;lt;/tt&amp;gt; is called when any of the fields in &amp;lt;tt&amp;gt;disable&amp;lt;/tt&amp;gt;,&lt;br /&gt;
&amp;lt;tt&amp;gt;alarmStatus&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;alarmSeverity&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;processLink&amp;lt;/tt&amp;gt; are changed.&lt;br /&gt;
         public bool special(bool after,Dbf[] field) {&lt;br /&gt;
             int nlevels = field.length;&lt;br /&gt;
             assert(nlevels&amp;gt;0);&lt;br /&gt;
             if(index==alarmStatusIndex || index==alarmSeverityIndex) {&lt;br /&gt;
                  if(!alarm.modifyingAlarm) return false;&lt;br /&gt;
                  return true;&lt;br /&gt;
             }&lt;br /&gt;
             if(!after) return;&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case disableIndex: {&lt;br /&gt;
                     if(nlevels==1) {&lt;br /&gt;
                         input.init(instance);&lt;br /&gt;
                     } else {&lt;br /&gt;
                         input.special(instance,Dbf[1]);&lt;br /&gt;
                     }&lt;br /&gt;
                     break;&lt;br /&gt;
                 }&lt;br /&gt;
                 case processLinkIndex : output.init(instance); break;&lt;br /&gt;
                 default: printf(&amp;quot;Why is special being called?\n&amp;quot;);&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     &lt;br /&gt;
== Private Class Methods ==&lt;br /&gt;
=== Callback methods ===&lt;br /&gt;
These are the callback methods that are called by link support.&lt;br /&gt;
         // Start of Callback methods&lt;br /&gt;
         public void done() {&lt;br /&gt;
             lock(instance);&lt;br /&gt;
             switch(mode) {&lt;br /&gt;
             case modeNone:&lt;br /&gt;
                 unlock(instance);&lt;br /&gt;
                 throw java.lang.IllegalStateException;&lt;br /&gt;
             case modeInput:&lt;br /&gt;
                 if(requestProcess) {&lt;br /&gt;
                     requestProcess = false;&lt;br /&gt;
                     DbAccess.process(instance);&lt;br /&gt;
                 }&lt;br /&gt;
                 break;&lt;br /&gt;
             case modeOutput:&lt;br /&gt;
                 output.numberLinksActive--;&lt;br /&gt;
                 if(output.numberLinksActive==0 &amp;amp;&amp;amp; requestProcess) {&lt;br /&gt;
                     requestProcess = false;&lt;br /&gt;
                     DbAccess.process(instance); &lt;br /&gt;
                 }&lt;br /&gt;
                 return;&lt;br /&gt;
             }&lt;br /&gt;
             unlock(instance);&lt;br /&gt;
         }&lt;br /&gt;
         public void failure() { done(); }&lt;br /&gt;
     &lt;br /&gt;
=== Common methods ===&lt;br /&gt;
For now the only method is &amp;lt;tt&amp;gt;setSeverity,&amp;lt;/tt&amp;gt;&lt;br /&gt;
The only way code can change severity and status is to call this method.&lt;br /&gt;
&lt;br /&gt;
         // Start of Common methods&lt;br /&gt;
         bool setSeverity(AlarmSeverity severity, string status) {&lt;br /&gt;
             Alarm alarm = this.alarm;&lt;br /&gt;
             if(severity&amp;lt;= alarm.severity) return false;&lt;br /&gt;
             alarm.severity = severity;&lt;br /&gt;
             alarm.status = status;&lt;br /&gt;
             alarm.modifyingAlarm = true;&lt;br /&gt;
             alarm.alarmSeverity.putIndex(severity);&lt;br /&gt;
             alarm.alarmStatus.put(status);&lt;br /&gt;
             alarm.modifyingAlarm = false;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== Input ===&lt;br /&gt;
This is a private class for RecordCommonSupport.&lt;br /&gt;
It directly accesses the fields in this class.&lt;br /&gt;
The init and special methods are called to get values for the private fields.&lt;br /&gt;
     &lt;br /&gt;
     // Definitions for modeInput&lt;br /&gt;
     class Input {&lt;br /&gt;
         DisableData disable;&lt;br /&gt;
         LinkSupport disableSupport;&lt;br /&gt;
         DbfInt16    disableInput;&lt;br /&gt;
         DbfInt16    disableValue;&lt;br /&gt;
         DbfInt16    alarmSeverity;&lt;br /&gt;
     &lt;br /&gt;
         void init(RecordInstance instance) {&lt;br /&gt;
             RecordAccess recordAccess = instance.getRecordCommonAccess();&lt;br /&gt;
             DbfLink link = recordAccess.getField(&amp;quot;disable.disableLink&amp;quot;);&lt;br /&gt;
             disableSupport = link.getSupport();&lt;br /&gt;
             DisplayLimitAccess.get(&lt;br /&gt;
                 recordAccess.getField(&amp;quot;disable&amp;quot;),disable);&lt;br /&gt;
             recordAccess.getField(&amp;quot;disable.disableInput&amp;quot;,disableInput);&lt;br /&gt;
         }&lt;br /&gt;
         void special(RecordInstance instance,Dbf field) {&lt;br /&gt;
             int16 index = Dbf.getIndex();&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case disableValueIndex:&lt;br /&gt;
                     disableValue = ((DbfInt16)Dbf).get(); break;&lt;br /&gt;
                 case disableInputIndex:&lt;br /&gt;
                     disableInput = ((DbfInt16)Dbf).get(); break;&lt;br /&gt;
                 case disableAlarmSeverityIndex:&lt;br /&gt;
                     alarmSeverity = ((dbfMenu)Dbf).getIndex(); break;&lt;br /&gt;
                 case disableLinkIndex:&lt;br /&gt;
                     init(instance); break;&lt;br /&gt;
                 default:&lt;br /&gt;
                     throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
&lt;br /&gt;
=== OutputLink and Output ===&lt;br /&gt;
Output is a private class for RecordCommonSupport.&lt;br /&gt;
It directly accesses the fields in this class.&lt;br /&gt;
The init  method is called to get values for the private fields.&lt;br /&gt;
OutputLink is used by Output.&lt;br /&gt;
&lt;br /&gt;
     // Definitions for modeOutput&lt;br /&gt;
     class OutputLink {&lt;br /&gt;
         Link        link;&lt;br /&gt;
         LinkSupport support;&lt;br /&gt;
         void init(RecordInstance instance,String linkFieldName) {&lt;br /&gt;
             RecordAccess recordAccess = instance.getRecordCommonAccess();&lt;br /&gt;
             DbfLink link = recordAccess.getField(linkFieldName);&lt;br /&gt;
             support = link.getSupport();&lt;br /&gt;
         }&lt;br /&gt;
     };&lt;br /&gt;
     &lt;br /&gt;
     class Output {&lt;br /&gt;
         int          nextLink;&lt;br /&gt;
         int          numberLinksActive;&lt;br /&gt;
         OutputLink[] link;&lt;br /&gt;
         void init(RecordInstance instance) {&lt;br /&gt;
             RecordAccess recordAccess = instance.getRecordCommonAccess();&lt;br /&gt;
             DbfArray array = recordAccess.getField(&amp;quot;processLink&amp;quot;);&lt;br /&gt;
             int n = array.getNelements();&lt;br /&gt;
             link = new OutputLink[n];&lt;br /&gt;
             for(i=0; i&amp;lt; n; i++) {&lt;br /&gt;
                 String field = &amp;quot;processLink[&amp;quot; + &amp;quot;i&amp;quot; + &amp;quot;]&amp;quot;;&lt;br /&gt;
                 link[i].init(instance,field);&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
=== Alarm ===&lt;br /&gt;
This is a private class for RecordCommonSupport.&lt;br /&gt;
It directly accesses the fields in this class.&lt;br /&gt;
The init method is called to get values for the private fields.&lt;br /&gt;
&lt;br /&gt;
     // Definitions for alarm handling&lt;br /&gt;
     class Alarm {&lt;br /&gt;
         short severity;&lt;br /&gt;
         String status;&lt;br /&gt;
         DbfMenu alarmSeverity;&lt;br /&gt;
         DbfString alarmStatus;&lt;br /&gt;
         bool modifyingAlarm;&lt;br /&gt;
         void init(RecordInstance instance) {&lt;br /&gt;
             RecordAccess recordAccess = instance.getRecordCommonAccess();&lt;br /&gt;
             alarmSeverity = recordAccess.getField(&amp;quot;alarmSeverity&amp;quot;);&lt;br /&gt;
             alarmStatus = recordAccess.getField(&amp;quot;alarmStatus&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
== RecordCommonSupportFactory ==&lt;br /&gt;
This is the factory for creating an RecordCommonSupport.&lt;br /&gt;
It is called by dbLoadRecords.&lt;br /&gt;
&lt;br /&gt;
     public class RecordCommonSupportFactory implements RecordSupportFactory{&lt;br /&gt;
         RecordSupport create(RecordInstance instance) {&lt;br /&gt;
             return new RecordCommonSupport(instance);&lt;br /&gt;
         }&lt;br /&gt;
         void destroy(RecordSupport support) {&lt;br /&gt;
             RecordCommonSupport RecordCommonSupport = support;&lt;br /&gt;
             RecordCommonSupport.destroy();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class RecordCommonSupportFactoryRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             RecordCommonSupportFactory factory = new RecordCommonSupportFactory;&lt;br /&gt;
             RegisterSupport.record(factory,&amp;quot;RecordCommon&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt;&lt;br /&gt;
Who calls RecordCommonSupportFactoryRegister.createAndRegister?&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Runtime_Interfaces&amp;diff=554</id>
		<title>V4 Design: Runtime Interfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Runtime_Interfaces&amp;diff=554"/>
		<updated>2005-09-28T19:32:08Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Runtime Interfaces September 28 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes  definitions for IOC runtime,&lt;br /&gt;
i.e. interfaces implemented or used by database access, record support,&lt;br /&gt;
link support, and device support.&lt;br /&gt;
&lt;br /&gt;
It assumes knowledge of the interfaces described in dbdInterfaces.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; IOC runtime needs lots more work&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Support Code =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section described interfaces for&lt;br /&gt;
strings, arrays, and conversions. &lt;br /&gt;
They are intended for use by Database Access, Record Support, etc.&lt;br /&gt;
&lt;br /&gt;
== C++ support for strings ==&lt;br /&gt;
&lt;br /&gt;
For most strings all the database  needs is a nonmutable string.&lt;br /&gt;
For these it wants to be able to pass a reference to it to arbitrary code.&lt;br /&gt;
It needs this for things like record type names, field names, record instance names, menu choice names, etc. etc. Some of these may change but very infrequently.&lt;br /&gt;
The string always contains UTF-8 encoded strings, which I believe can  be printed with a &amp;quot;%s&amp;quot; format if&lt;br /&gt;
the string is made available as a &amp;quot;const char *&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Perhaps the only type of  string connected with an IOC record that changes frequently is a field in a record type like stringin and stringout. In this case the record support can do what ever it wants to handle the string. It can even just use C style strings!!!&lt;br /&gt;
&lt;br /&gt;
Thus all the IOC database needs is a:&lt;br /&gt;
&lt;br /&gt;
1) nonmutable reference counted continguous string. When the reference count goes to 0 the storage can be reclaimed&lt;br /&gt;
2) The ability to copy the value from a nonmutable string to a mutable string.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In Java String and StringBuffer are all that is needed.&lt;br /&gt;
&lt;br /&gt;
In C++ all that is needed is&lt;br /&gt;
&lt;br /&gt;
1) A class that holds UFT-8 encoded non-mutable strings and make the contents available as a &amp;quot;const char *&amp;quot; and it's length. The class keeps a reference count and frees the storage when done.&lt;br /&gt;
2) The ability to copy the nonmutable string to a &amp;quot;char *&amp;quot; array allocated by the requester.&lt;br /&gt;
&lt;br /&gt;
That is all.&lt;br /&gt;
&lt;br /&gt;
== array copy ==&lt;br /&gt;
&lt;br /&gt;
ArrayCopy copies arrays an array performing conversions if necessary.&lt;br /&gt;
&lt;br /&gt;
     interface ArrayCopy {&lt;br /&gt;
         void copy(DbfArray from,DbfArray to);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
This only supports primitive types, i.e. DbfBoolean,...,DbfFloat64.&lt;br /&gt;
It does NOT convert between&lt;br /&gt;
* DbfBoolean and another type.&lt;br /&gt;
* DbfOctet and another type.&lt;br /&gt;
Thus for DbfBoolean and DbfOctet it is willing to copy&lt;br /&gt;
but not convert to/from other types.&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Conversions ==&lt;br /&gt;
This is a static class that converts between primitie types and arrays of primitive types.&lt;br /&gt;
&lt;br /&gt;
     static class DbfConvertPrimitive {&lt;br /&gt;
     public:&lt;br /&gt;
          int16 get(Dbf from);&lt;br /&gt;
          int32 get(Dbf from);&lt;br /&gt;
          int64 get(Dbf from);&lt;br /&gt;
          float32 get(Dbf from);&lt;br /&gt;
          float64 get(Dbf from);&lt;br /&gt;
          get(Dbf from, String value);&lt;br /&gt;
          get(DbfOctet from, String value);&lt;br /&gt;
          get(DbfBoolean from, String value);&lt;br /&gt;
          put(Dbf to, int16 value);&lt;br /&gt;
          put(Dbf to, int32 value);&lt;br /&gt;
          put(Dbf to, int64 value);&lt;br /&gt;
          put(Dbf to, float32 value);&lt;br /&gt;
          put(Dbf to, float64 value);&lt;br /&gt;
          put(Dbf to,int32 String value);&lt;br /&gt;
          put(DbfOctet to, String value);&lt;br /&gt;
          put(DbfBoolean to, String value);&lt;br /&gt;
&lt;br /&gt;
          get(DbfArray from, int16[] value);&lt;br /&gt;
          get(DbfArray from, int32[] value);&lt;br /&gt;
          get(DbfArray from, int64[] value);&lt;br /&gt;
          get(DbfArray from, float32[] value);&lt;br /&gt;
          get(DbfArray from, float64[] value);&lt;br /&gt;
          put(DbfArray to, int16[] value);&lt;br /&gt;
          put(DbfArray to, int32[] value);&lt;br /&gt;
          put(DbfArray to, int64[] value);&lt;br /&gt;
          put(DbfArray to, float32[] value);&lt;br /&gt;
          put(DbfArray to, float64[] value);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* For Dbf &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; must be one of &amp;lt;tt&amp;gt;DbfInt16&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;DbfFloat64&amp;lt;/tt&amp;gt;&lt;br /&gt;
* The get to a string implements printf semantics&lt;br /&gt;
* The put from a string value just scanf semantics.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;DbfOctet&amp;lt;/tt&amp;gt; methods convert to/from a string of the form &amp;quot;0xXX&amp;quot;&lt;br /&gt;
* The &amp;lt;tt&amp;gt;DbfBoolean&amp;lt;/tt&amp;gt; get method supports all the choices specified in the DBD Record Instance Specification&lt;br /&gt;
* For DbfArray &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; must be an array of one of &amp;lt;tt&amp;gt;DbfInt16&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;DbfFloat64&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code generated from Database Definition Files =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following shows the Java code generated from DBD files:&lt;br /&gt;
&lt;br /&gt;
== structure definitions ==&lt;br /&gt;
&lt;br /&gt;
Two files are generated from &amp;lt;tt&amp;gt;struct(name)&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
# &amp;lt;tt&amp;gt;name.java&amp;lt;/tt&amp;gt;&lt;br /&gt;
# &amp;lt;tt&amp;gt;nameSupport.java&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;name.java&amp;lt;/tt&amp;gt; implements:&lt;br /&gt;
     interface Struct {&lt;br /&gt;
         Dbf getField(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a structure is defined as:&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,double)&lt;br /&gt;
         field(high,double)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
A generated file &amp;lt;tt&amp;gt;DisplayLimit.java&amp;lt;/tt&amp;gt; contains:&lt;br /&gt;
&lt;br /&gt;
     public class DisplayLimit implements Struct{&lt;br /&gt;
         public DbfFloat64 low;&lt;br /&gt;
         public DbfFloat64 high;&lt;br /&gt;
         public static final short lowIndex = 1;&lt;br /&gt;
         public static final short highIndex = 2;&lt;br /&gt;
         public static final short lastIndex = indexHigh;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case lowIndex: return(low);&lt;br /&gt;
                 case highIndex: return(high);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
             return null;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
A generated file &amp;lt;tt&amp;gt;DisplayLimitAccess.java&amp;lt;/tt&amp;gt; contains:&lt;br /&gt;
&lt;br /&gt;
     public class DisplayLimitData {&lt;br /&gt;
         public double low;&lt;br /&gt;
         public double high;&lt;br /&gt;
     }&lt;br /&gt;
     public final class DisplayLimitAccess implements StructFactory{&lt;br /&gt;
         public Struct create() { return new DisplayLimit; }&lt;br /&gt;
         public static final void get(DbfStruct from,DisplayLimitData data) {&lt;br /&gt;
             DbfFloat64 dbf = from.getInterface(1);&lt;br /&gt;
             data.low = dbf.get();&lt;br /&gt;
             DbfFloat64 dbf = from.getInterface(2);&lt;br /&gt;
             data.high = dbf.get();&lt;br /&gt;
         }&lt;br /&gt;
         public static final void put(DbfStruct to, DisplayLimitData data) {&lt;br /&gt;
             DbfFloat64 dbf = to.getInterface(1);&lt;br /&gt;
             dbf.put(data.low);&lt;br /&gt;
             DbfFloat64 dbf = to.getInterface(2);&lt;br /&gt;
             dbf.put(data.high);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class DisplayLimitAccessRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             DisplayLimitAccess access = new DisplayLimitAccess;&lt;br /&gt;
             RegisterSupport.structure(access,&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; The V4 replacement for registerRecordDeviceDriver must&lt;br /&gt;
call DisplayLimitAccessRegister.createAndRegister.&lt;br /&gt;
&lt;br /&gt;
Similar files are generated for C++.&lt;br /&gt;
&lt;br /&gt;
== record definitions ==&lt;br /&gt;
If a record is defined as:&lt;br /&gt;
     record(Example) extends RecordCommon {&lt;br /&gt;
         ...&lt;br /&gt;
         field(fboolean,boolean)&lt;br /&gt;
         field(octet,octet)&lt;br /&gt;
         field(fint,int16)&lt;br /&gt;
         ...&lt;br /&gt;
         field(ffloat,float64)&lt;br /&gt;
         field(string,string)&lt;br /&gt;
         field(array,array(double[])&lt;br /&gt;
         field(mdarray,array(double[,])&lt;br /&gt;
         field(menu,menu(name))&lt;br /&gt;
         field(fenum,enum)&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(device,link(in,analogIO))&lt;br /&gt;
         field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The generated Java file is&lt;br /&gt;
&lt;br /&gt;
     public class ExampleRecord implements Struct {&lt;br /&gt;
         public DbfBoolean   fboolean;&lt;br /&gt;
         public DbfOctet     ctet;&lt;br /&gt;
         public DbfInt16     fint;&lt;br /&gt;
         ...&lt;br /&gt;
         public DbfFloat64   ffloat;&lt;br /&gt;
         public DbfString    string;&lt;br /&gt;
         public DbfArray     array;&lt;br /&gt;
         public DbfMDArray   mdarray;&lt;br /&gt;
         public DbfMenu      menu;&lt;br /&gt;
         public DbfEnum      fenum;&lt;br /&gt;
         public DbfLink      link;&lt;br /&gt;
         public DbfDevice    device;&lt;br /&gt;
         public DbfStruct    displayLimit;&lt;br /&gt;
         public static final int16 fbooleanIndex = 1;&lt;br /&gt;
         ...&lt;br /&gt;
         public static final int16 lastIndex = displayLimitIndex;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case fbooleanIndex : return(fboolean);&lt;br /&gt;
                 ...&lt;br /&gt;
                 case displayLimitIndex: return(displayLimit);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class ExampleRecordFactory implements StructFactory{&lt;br /&gt;
         public static final Struct create() { return new ExampleRecord; }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class ExampleRecordFactoryRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             ExampleRecordFactory  factory = new ExampleRecordFactory;&lt;br /&gt;
             RegisterSupport.record(factory,&amp;quot;ExampleRecord&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; The V4 replacement for registerRecordDeviceDriver must&lt;br /&gt;
call ExampleRecordFactoryRegister.createAndRegister&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar code is generated for C++.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Record Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     enum ProcessState {&lt;br /&gt;
         processCancel,&lt;br /&gt;
         processStart,&lt;br /&gt;
         processContinue,&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum ProcessReturn {&lt;br /&gt;
         processDone,&lt;br /&gt;
         processAbort,&lt;br /&gt;
         processActive&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RecordSupport {&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize(int32 pass);&lt;br /&gt;
         ProcessState process(ProcessState state,Callback done);&lt;br /&gt;
         // if special returns false when after is false put fails&lt;br /&gt;
         boolean special(boolean after,Dbf[] field);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ProcessState&amp;lt;/tt&amp;gt; supports the following semantics:&lt;br /&gt;
* cancel - If the record is active terminate &lt;br /&gt;
* For all other states see the companion document &amp;quot;V4 Design: Record Processing&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The methods of &amp;lt;tt&amp;gt;RecordSupport&amp;lt;/tt&amp;gt; are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - Called when a record instance is deleted.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called twice (pass = 0,1) when a record is initialized.&lt;br /&gt;
* &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; - Called to process a record. See &amp;quot;V4 Design: Record Processing&amp;quot; for semantics.&lt;br /&gt;
* &amp;lt;tt&amp;gt;special&amp;lt;/tt&amp;gt; - Called when a field declared special in a DBD file is modified. &amp;lt;tt&amp;gt;field&amp;lt;/tt&amp;gt; is an array of Dbfs showing which field is being modified.&lt;br /&gt;
&lt;br /&gt;
== Discussion of special ==&lt;br /&gt;
&lt;br /&gt;
Special is passed a Dbf array that identifies the field being modified.&lt;br /&gt;
For example &amp;lt;tt&amp;gt;ExampleRecord.dbd&amp;lt;/tt&amp;gt; has a field:&lt;br /&gt;
     field(displayLimit,struct(displayLimit))&lt;br /&gt;
&amp;lt;tt&amp;gt;ExampleRecordSupport.java&amp;lt;/tt&amp;gt; might implement special as follows:&lt;br /&gt;
     boolean special(boolean after, Dbf[] field)&lt;br /&gt;
     {&lt;br /&gt;
         switch(field[0].getIndex()) {&lt;br /&gt;
         ...&lt;br /&gt;
         case ExampleRecord.displayLimitIndex:&lt;br /&gt;
             if(field.length==1) {&lt;br /&gt;
                 // displayLimits itself is being modified. Do something&lt;br /&gt;
             } else {&lt;br /&gt;
                // a field of displayLimits is being modified&lt;br /&gt;
                 switch(field[1].getIndex) {&lt;br /&gt;
                     case DisplayLimit.lowIndex:&lt;br /&gt;
                          // low being modified. do something&lt;br /&gt;
                     case DisplayLimit.highIndex:&lt;br /&gt;
                          // high being modified. do something&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         ...&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An arbitrary number of Link Support implementations can exist.&lt;br /&gt;
An implementation can be either soft support or support that communicates with&lt;br /&gt;
hardware.&lt;br /&gt;
EPICS base supplies support that accesses data via channel access, i.e.&lt;br /&gt;
access to records in the same or other IOCS.&lt;br /&gt;
&lt;br /&gt;
Recall that the link DBD definition is:&lt;br /&gt;
&lt;br /&gt;
    link(dir, choiceName, interfaceName, dataStructName)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; is the name that identifies the implementation.&lt;br /&gt;
&amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt; is the name of the interface that record support&lt;br /&gt;
uses and the support implements.&lt;br /&gt;
&amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt; is the name of a structure used by support for&lt;br /&gt;
configuration.&lt;br /&gt;
&lt;br /&gt;
This section describes that standard &amp;lt;tt&amp;gt;interfaceNames&amp;lt;/tt&amp;gt; that&lt;br /&gt;
are used by the record types supplied with epics base.&lt;br /&gt;
These interfaces are appropriate for the soft support supplied with EPICS&lt;br /&gt;
base and should also be sufficient for a wide variety of hardware support.&lt;br /&gt;
In particular it is sufficient for communication with asynDriver.&lt;br /&gt;
&lt;br /&gt;
== Link  ==&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink {&lt;br /&gt;
         void addMonitor(Callback callback);&lt;br /&gt;
         void removeMonitor();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
&amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; is an interface that is implemented by link support that&lt;br /&gt;
supports monitors. Example are hardware interrupts.&lt;br /&gt;
The &amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;MonitorLink&amp;lt;/tt&amp;gt; methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;addMonitor&amp;lt;/tt&amp;gt; - Add a monitor callback&lt;br /&gt;
* &amp;lt;tt&amp;gt;removeMonitor&amp;lt;/tt&amp;gt; - Remove monitor&lt;br /&gt;
&lt;br /&gt;
Normally record support does not need to call any of the Link &lt;br /&gt;
or MonitorLink methods since database access does this automatically.&lt;br /&gt;
For example if a link field is modified via a channel access put,&lt;br /&gt;
database access will call&lt;br /&gt;
destroy before modifying the link and initialize and connect after the&lt;br /&gt;
link is modified.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
&lt;br /&gt;
     enum LinkWaitResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
         linkWaitBlock,      // waiting. dont do additional processing until&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface ProcessLinkSupport&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult process(Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Octet Support ==&lt;br /&gt;
There is no support for octet but there is support for an array of octets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     interface LinkArrayOctet {&lt;br /&gt;
         LinkWaitResult getWait(octet[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(octet[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The data source must be an array of octets or the connect request will fail.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynOctet Support ==&lt;br /&gt;
&lt;br /&gt;
This still needs more work. It attempts to reproduce the functionality&lt;br /&gt;
of V3 asynDriver.&lt;br /&gt;
&lt;br /&gt;
     interface AsynOctet {&lt;br /&gt;
         LinkWaitResult write(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult writeRaw(Callback callback,&lt;br /&gt;
           octet[] data, int32 numchars, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult read(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         LinkWaitResult readRaw(Callback callback,&lt;br /&gt;
           octet[] data, Int32 nbytesTransfered);&lt;br /&gt;
         void flush();&lt;br /&gt;
         void setInputEos(octet[] eos);&lt;br /&gt;
         void getInputEos(octet[] eos);&lt;br /&gt;
         void setOutputEos(octet[] eos);&lt;br /&gt;
         void getOutputEos(octet[] eos);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     }&lt;br /&gt;
     struct asynDigitalInterrupt {&lt;br /&gt;
         octet[] mask;&lt;br /&gt;
         int32 addr;&lt;br /&gt;
         Callback callback&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface AsynDigital {&lt;br /&gt;
          LinkWaitResult write(octet[] value, octet[] mask);&lt;br /&gt;
          LinkWaitResult read(octet[] value, octet[] mask);&lt;br /&gt;
          void setInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void clearInterrupt(octet[] mask);&lt;br /&gt;
          void getInterrupt(octet[] mask, interruptReason reason);&lt;br /&gt;
          void registerInterruptUser(interruptCallbackUInt32Digital callback,&lt;br /&gt;
              octet[] mask);&lt;br /&gt;
          void cancelInterruptUser();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Boolean Support ==&lt;br /&gt;
     interface LinkBoolean {&lt;br /&gt;
         LinkWaitResult getWait(Boolean data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(boolean data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayBoolean {&lt;br /&gt;
         LinkWaitResult getWait(boolean[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(boolean[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a boolean or a string that contains a valid&lt;br /&gt;
boolean value.&lt;br /&gt;
&lt;br /&gt;
== Integer Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for int16, int32, and int64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be int16, int32, or int64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         void getBounds(&amp;lt;type&amp;gt; low, &amp;lt;type&amp;gt; high);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum interruptReason {&lt;br /&gt;
         interruptOnZeroToOne, interruptOnOneToZero, interruptOnBoth&lt;br /&gt;
     } &lt;br /&gt;
         &lt;br /&gt;
         &lt;br /&gt;
== Float Support ==&lt;br /&gt;
&lt;br /&gt;
Support is available. for float32 and float64.&lt;br /&gt;
This section uses the Java generic syntax, e.g. &amp;lt;type&amp;gt;. In this&lt;br /&gt;
section &amp;lt;type&amp;gt; must be float32 or float64.&lt;br /&gt;
&lt;br /&gt;
     interface Link&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt; data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArray&amp;lt;type&amp;gt; {&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(&amp;lt;type&amp;gt;[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== String Support ==&lt;br /&gt;
     interface LinkString {&lt;br /&gt;
         LinkWaitResult getWait(string data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(string data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
     interface LinkArrayString {&lt;br /&gt;
         LinkWaitResult getWait(string[] data,Callback callback);&lt;br /&gt;
         LinkWaitResult putWait(string[] data,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data source must be a string.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Registration and Instance Creation =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     interface StructFactory {&lt;br /&gt;
         DbfStruct create();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RecordSupportFactory {&lt;br /&gt;
         RecordSupport create(RecordInstance instance);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface SupportFactory {&lt;br /&gt;
         Support create(Dbf field);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RegisterSupport {&lt;br /&gt;
         structure(StructFactory create, string name);&lt;br /&gt;
         record(StructFactory create, string name);&lt;br /&gt;
         link(SupportFactory support,string name);&lt;br /&gt;
         device(SupportFactory support,string name);&lt;br /&gt;
         record(RecordSupportFactory support,string name);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;RegisterSupport&amp;lt;/tt&amp;gt; is implemented by iocCore.&lt;br /&gt;
Each &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; DBD definition must register a StructFactory to&lt;br /&gt;
create instances of the structure or record.&lt;br /&gt;
&lt;br /&gt;
Each link, device, and record support must register a SupportFactory to create&lt;br /&gt;
instances of the support to attach to the link, device, or record instance.&lt;br /&gt;
During database initialization, iocCore calls the factory methods.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtime Database Access =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Database Access, with help from record, link, and device support&lt;br /&gt;
implements the dbdInterfaces.&lt;br /&gt;
Other than Database Access, fields of a record can only&lt;br /&gt;
be accessed via the interfaces described in dbdInterfaces.&lt;br /&gt;
This allows the database to handle&lt;br /&gt;
actions like posting database monitors without any help from&lt;br /&gt;
record, link, or device support.&lt;br /&gt;
&lt;br /&gt;
Database access by default allocates the actual storage for each field&lt;br /&gt;
but allows support code to register itself to manage storage for field&lt;br /&gt;
instances.&lt;br /&gt;
Two examples, both involving arrays, are:&lt;br /&gt;
* The compress record  registers to provide storage for the value.&lt;br /&gt;
** This allows it to implement a circular buffer.&lt;br /&gt;
** Code that accesses the value field may have to issue two get requests.&lt;br /&gt;
* Device support for a transient recorder registers to provide storage for the array&lt;br /&gt;
** This allows device support to read data from hardware in segments&lt;br /&gt;
** Code that accesses the array may have to issue many get requests.&lt;br /&gt;
&lt;br /&gt;
The fact that each field of a record instance is an object means that additional storage is required.&lt;br /&gt;
Database Access  will probably have something like the following:&lt;br /&gt;
&lt;br /&gt;
    class Field {&lt;br /&gt;
        DbRecord instance;&lt;br /&gt;
        short          index;&lt;br /&gt;
    };&lt;br /&gt;
    ...&lt;br /&gt;
    class IntField extends Field {&lt;br /&gt;
        int data;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
This each field has the overhead of&lt;br /&gt;
* instance - a reference to DbRecord, i.e. record instance&lt;br /&gt;
* index - a 16 bit integer&lt;br /&gt;
* vtbl - a reference to the object implementation&lt;br /&gt;
&lt;br /&gt;
Additional fields will be needed for things like monitors.&lt;br /&gt;
These fields can start out null and only allocate storage as needed.&lt;br /&gt;
&lt;br /&gt;
== Database Access ==&lt;br /&gt;
&lt;br /&gt;
     interface DbAccess {&lt;br /&gt;
         void process(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processCancel(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processContinue(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processRequestAccept(Dbf field, boolean yesNo);&lt;br /&gt;
         void registerDbfSource(Dbf field, Dbf source);&lt;br /&gt;
         LinkSupport getLinkSupport(Dbf field);&lt;br /&gt;
         Support getSupport(Dbf field);&lt;br /&gt;
         RecordSupport getRecordSupport(DbInstance instance);&lt;br /&gt;
         RecordSupport getRecordCommonSupport(DbInstance instance);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; - Request processing. Record must be idle or active or request fails.&lt;br /&gt;
** &amp;lt;tt&amp;gt;instance&amp;lt;/tt&amp;gt; - The record to process&lt;br /&gt;
** &amp;lt;tt&amp;gt;callback&amp;lt;/tt&amp;gt; - A callback to call when processing completes or for failure.&lt;br /&gt;
* &amp;lt;tt&amp;gt;processRequestAccept&amp;lt;/tt&amp;gt; - Should a process request from channel access be accepted,&lt;br /&gt;
* &amp;lt;tt&amp;gt;registerDbfSource&amp;lt;/tt&amp;gt; - Register code that will implement storage for the field.&lt;br /&gt;
* &amp;lt;tt&amp;gt;getLinkSupport&amp;lt;/tt&amp;gt; - Find the link support for a link field&lt;br /&gt;
* &amp;lt;tt&amp;gt;getSupport&amp;lt;/tt&amp;gt; - Get the device support for a device field&lt;br /&gt;
* &amp;lt;tt&amp;gt;getRecordSupport&amp;lt;/tt&amp;gt; - Get the record support for the record&lt;br /&gt;
* &amp;lt;tt&amp;gt;getRecordCommonSupport&amp;lt;/tt&amp;gt; - Get the RecordCommon support for the record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTES&amp;lt;/b&amp;gt; This is just the beginning of defining the methods in DbAccess&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Examples&amp;diff=574</id>
		<title>V4 DBD Examples</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Examples&amp;diff=574"/>
		<updated>2005-09-28T19:30:45Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Example Record Types Sept 28 2005&lt;br /&gt;
= Overview =&lt;br /&gt;
This document present proposed V4 replacements for a few of the&lt;br /&gt;
V3 record types.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= aoRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
aoRecord.dbd might be defined as follows:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 record(AoRecord) extends RecordCommon {&lt;br /&gt;
     field(value, float64) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(outValue, float64) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(out,&lt;br /&gt;
        link(out,interface( LinkInt64, LinkFloat64))&lt;br /&gt;
     )&lt;br /&gt;
     field(outputRateOfChange, float64)&lt;br /&gt;
     field(desiredOutputLink,&lt;br /&gt;
        link(in,interface(LinkFloat64))&lt;br /&gt;
     )&lt;br /&gt;
     field(closedLoop, bool)&lt;br /&gt;
     field(outputIncremental, bool)&lt;br /&gt;
     field(convert, menu(menuConvert)) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(linearConvert, struct(LinearConvert)) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(units, string)&lt;br /&gt;
     field(displayLimit, struct(DisplayLimit))&lt;br /&gt;
     field(controlLimit, struct(ControlLimit))&lt;br /&gt;
     field(alarmLimit, struct(AlarmLimit))&lt;br /&gt;
     field(alarmDeadband, float64)&lt;br /&gt;
     field(rawValue, int64) {&lt;br /&gt;
         design(no)&lt;br /&gt;
     }&lt;br /&gt;
     field(prevRawValue, int64) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(readBackValue, int64) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(init, bool) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(simOutputLink,&lt;br /&gt;
        link(out,interface(LinkFloat64))&lt;br /&gt;
     )&lt;br /&gt;
&lt;br /&gt;
     field(simModeLink,&lt;br /&gt;
        link(in,interface(LinkBoolean))&lt;br /&gt;
     )&lt;br /&gt;
     field(simMode, bool) &lt;br /&gt;
     field(simSevr, menu(menuAlarmSevr))&lt;br /&gt;
     field(invalidAction, menu(menuIvoa))&lt;br /&gt;
     field(invalidValue, float64)&lt;br /&gt;
     field(outValueModified, bool) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     view(value) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
             property(controlLimit, controlLimit)&lt;br /&gt;
             property(alarmLimit, alarmLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(output) {&lt;br /&gt;
         property(value, outValue) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(raw) {&lt;br /&gt;
         property(value, rawValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(readback) {&lt;br /&gt;
         property(value, readBackValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 } &lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= calcRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
calcRecord.dbd defines the following:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 struct(CalcInpLink) {&lt;br /&gt;
     field(link,link(in,interface(LinkFloat64))&lt;br /&gt;
     field(value,float64)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 record(CalcRecord) extends RecordCommon {&lt;br /&gt;
     field(result,float64) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(calc,string) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(input,array(struct(CalcInpLink)[])) &lt;br /&gt;
     field(units,string)&lt;br /&gt;
     field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     field(alarmLimit,struct(AlarmLimit))&lt;br /&gt;
     field(alarmDeadband,float64)&lt;br /&gt;
     field(lastValueAlarmed,float64) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(rpcl,private(&amp;quot;char *&amp;quot;))&lt;br /&gt;
     view(result) {&lt;br /&gt;
         property(value, result) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
             property(alarmLimit, alarmLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(expression) {&lt;br /&gt;
         property(value, calc)&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= mbbiRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
mbbiRecord.dbd could be:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 struct(MbbiState) {&lt;br /&gt;
     field(name, string)&lt;br /&gt;
     field(value, array(octet[]))&lt;br /&gt;
     field(severity, menu(menuAlarmSevr))&lt;br /&gt;
 }&lt;br /&gt;
 record(MbbiRecord) extends RecordCommon {&lt;br /&gt;
     field(state, array(struct(MbbiState)[])) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
#NOTE: stateName needed because enum must refer to array of string&lt;br /&gt;
     field(stateName,array(string[])) {&lt;br /&gt;
         design(no) readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(value, enum(stateName)) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(unknownStateSeverity, menu(menuAlarmSevr))&lt;br /&gt;
     field(changeStateSeverity, menu(menuAlarmSevr))&lt;br /&gt;
     field(inp, link(in,interface(LinkOctetArray,AsynDigital))&lt;br /&gt;
     field(rawValue, array(octet[])) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(hardwareShift, int16) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(hardwareMask, array(octet[]) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     view(choice) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(raw) {&lt;br /&gt;
         property(value, raw) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= waveformRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
waveformRecord.dbd defines the following:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 record(WaveformRecord) extends RecordCommon {&lt;br /&gt;
     field(value, array([])) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(reArm,bool)&lt;br /&gt;
     field(io,&lt;br /&gt;
         link(inout,interface(&lt;br /&gt;
           &amp;quot;LinkArrayOctet&amp;quot;,&lt;br /&gt;
           &amp;quot;LinkArrayBoolean&amp;quot;,&lt;br /&gt;
           &amp;quot;LinkArrayInt16&amp;quot;,&lt;br /&gt;
           &amp;quot;LinkArrayInt32&amp;quot;,&lt;br /&gt;
           &amp;quot;LinkArrayInt64&amp;quot;,&lt;br /&gt;
           &amp;quot;LinkArrayFloat32&amp;quot;,&lt;br /&gt;
           &amp;quot;LinkArrayFloat64&amp;quot;,&lt;br /&gt;
           &amp;quot;LinkArrayString&amp;quot;,&lt;br /&gt;
        } ))&lt;br /&gt;
     )&lt;br /&gt;
     field(units,string)&lt;br /&gt;
     field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     field(busy,bool) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     view(value) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=548</id>
		<title>V4 DB RecordCommon</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=548"/>
		<updated>2005-09-28T19:29:23Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Standard Support September 28 2005 &lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
For V4 dbCommon.dbd and RecordCommon.dbd replace the V3 dbCommon.dbd.&lt;br /&gt;
dbCommon.dbd defines widely used definitions and RecordCommon.dbd defines&lt;br /&gt;
the fields that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This document requires that the reader be familiar with:&lt;br /&gt;
# V3 iocCore&lt;br /&gt;
# V4 DBD Statement Syntax&lt;br /&gt;
# V4 DB Record Instance Syntax&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= dbCommon =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Support ==&lt;br /&gt;
&lt;br /&gt;
=== Data Structures ===&lt;br /&gt;
     struct(MonitorLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean) &lt;br /&gt;
     }&lt;br /&gt;
     struct(InputLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(OutputLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ProcessLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link support definitions ===&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* input&lt;br /&gt;
** monitor support&lt;br /&gt;
** input support&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For input and output The following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
     link(process,processLink,ProcessLink,ProcessLinkData);&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLinkArrayOctet,LinkArrayOctet,MonitorLinkData);&lt;br /&gt;
     link(in,inputLinkArrayOctet,LinkArrayOctet,InputLinkData);&lt;br /&gt;
     link(out,outputLinkArrayOctet,LinkArrayOctet,OutputLinkData);&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLinkBoolean,LinkBoolean,MonitorLinkData);&lt;br /&gt;
     link(in,monitorLinkArrayBoolean,LinkArrayBoolean,MonitorLinkData);&lt;br /&gt;
     link(in,inputLinkBoolean,LinkBoolean,InputLinkData);&lt;br /&gt;
     link(in,inputLinkArrayBoolean,LinkArrayBoolean,InputLinkData);&lt;br /&gt;
     link(out,outputLinkBoolean,LinkBoolean,OutputLinkData);&lt;br /&gt;
     link(out,outputLinkArrayBoolean,LinkArrayBooleanData);&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLinkInt16,LinkInt16,MonitorLinkData);&lt;br /&gt;
     link(in,monitorLinkInt32,LinkInt32,MonitorLinkData);&lt;br /&gt;
     link(in,monitorLinkInt64,LinkInt64,MonitorLinkData);&lt;br /&gt;
     link(in,inputLinkInt16,LinkInt16,InputLinkData);&lt;br /&gt;
     link(in,inputLinkInt32,LinkInt32,InputLinkData);&lt;br /&gt;
     link(in,inputLinkInt64,LinkInt64,InputLinkData);&lt;br /&gt;
     link(out,outputLinkInt16,LinkInt16,OutputLinkData);&lt;br /&gt;
     link(out,outputLinkInt32,LinkInt32,OutputLinkData);&lt;br /&gt;
     link(out,outputLinkInt64,LinkInt64,OutputLinkData);&lt;br /&gt;
     link(in,monitorLinkArrayInt16,LinkArrayInt16,MonitorLinkData);&lt;br /&gt;
     link(in,monitorLinkArrayInt32,LinkArrayInt32,MonitorLinkData);&lt;br /&gt;
     link(in,monitorLinkArrayInt64,LinkArrayInt64,MonitorLinkData);&lt;br /&gt;
     link(in,inputLinkArrayInt16,LinkArrayInt16,InputLinkData);&lt;br /&gt;
     link(in,inputLinkArrayInt32,LinkArrayInt32,InputLinkData);&lt;br /&gt;
     link(in,inputLinkArrayInt64,LinkArrayInt64,InputLinkData);&lt;br /&gt;
     link(out,outputLinkArrayInt16,LinkArrayInt16,OutputLinkData);&lt;br /&gt;
     link(out,outputLinkArrayInt32,LinkArrayInt32,OutputLinkData);&lt;br /&gt;
     link(out,outputLinkArrayInt64,LinkArrayInt64,OutputLinkData);&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLinkFloat32,LinkFloat32,MonitorLinkData);&lt;br /&gt;
     link(in,monitorLinkFloat64,LinkFloat64,MonitorLinkData);&lt;br /&gt;
     link(in,monitorLinkString,LinkString,MonitorLinkData);&lt;br /&gt;
     link(in,inputLinkFloat32,LinkFloat32,InputLinkData);&lt;br /&gt;
     link(in,inputLinkFloat64,LinkFloat64,InputLinkData);&lt;br /&gt;
     link(in,inputLinkString,LinkString,InputLinkData);&lt;br /&gt;
     link(out,outputLinkFloat32,LinkFloat32,OutputLinkData);&lt;br /&gt;
     link(out,outputLinkFloat64,LinkFloat64,OutputLinkData);&lt;br /&gt;
     link(out,outputLinkString,LinkString,OutputLinkData);&lt;br /&gt;
     link(in,inputLinkArrayFloat32,LinkArrayFloat32,InputLinkData);&lt;br /&gt;
     link(in,inputLinkArrayFloat64,LinkArrayFloat64,InputLinkData);&lt;br /&gt;
     link(out,outputLinkArrayFloat32,LinkArrayFloat32,OutputLinkData);&lt;br /&gt;
     link(out,outputLinkArrayFloat64,LinkArrayFloat64,OutputLinkData);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     link(in,monitorLinkArrayString,LinkArrayString,MonitorLinkData);&lt;br /&gt;
     link(in,inputLinkArrayString,LinkArrayString,InputLinkData);&lt;br /&gt;
     link(out,outputLinkArrayString,LinkArrayString,OutputLinkData);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
     struct(AsynLinkData) {&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link definitions ===&lt;br /&gt;
&lt;br /&gt;
     link(inout,asynInt32,LinkInt32,AsynLinkData)&lt;br /&gt;
     link(in,asynInt32Average,LinkInt32,AsynLinkData)&lt;br /&gt;
     link(in,asynInt32Monitor,LinkInt32,AsynLinkData)&lt;br /&gt;
     link(inout,asynFloat64,LinkFloat64,AsynLinkData)&lt;br /&gt;
     link(in,asynFloat64Average,LinkFloat64,AsynLinkData)&lt;br /&gt;
     link(in,asynFloat64Monitor,LinkFloat64,AsynLinkData)&lt;br /&gt;
     link(in,asynDigitalMonitor,AsynDigital,AsynLinkData)&lt;br /&gt;
     link(inout,asynDigital,AsynDigital,AsynLinkData)&lt;br /&gt;
     link(inout,asynInt32Array,LinkArrayInt32,AsynLinkData)&lt;br /&gt;
     link(inout,asynFloat64Array,LinkArrayFloat64,AsynLinkData)&lt;br /&gt;
     link(inout,asynOctet,AsynOctet,AsynLinkData)&lt;br /&gt;
== Other common definitions ==&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;Raw&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     # usefull struct definitions&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(full,float64) &lt;br /&gt;
         field(egul,float64)&lt;br /&gt;
         field(slope,float64) &lt;br /&gt;
         field(intercept,float64) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ControlLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
     }&lt;br /&gt;
     struct(AlarmLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(lowSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(lowWarning,float64) &lt;br /&gt;
         field(lowWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(highWarning,float64) &lt;br /&gt;
         field(highWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
         field(highSevr,menu(menuAlarmSevr)) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= RecordCommon =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Menu Definitions ==&lt;br /&gt;
&lt;br /&gt;
     # menu definitions for RecordCommon fields&lt;br /&gt;
     menu(menuPriority) {&lt;br /&gt;
         choice(menuPriorityLow, &amp;quot;Low&amp;quot;)&lt;br /&gt;
         choice(menuPriorityMedium, &amp;quot;Medium&amp;quot;)&lt;br /&gt;
         choice(menuPriorityHigh, &amp;quot;High&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuScan) {&lt;br /&gt;
         choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
         choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
         choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
         choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
         choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuAlarmSevr) {&lt;br /&gt;
         choice(menuAlarmSevrNone, &amp;quot;None&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMinor, &amp;quot;Minor&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMajor, &amp;quot;Major&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrInvalid, &amp;quot;Invalid&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
== struct definitions for RecordSupport ==&lt;br /&gt;
     struct(TimeStamp) {&lt;br /&gt;
         field(secondsPastEpoch,int64)&lt;br /&gt;
         field(nanoSeconds,int32)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Scan {&lt;br /&gt;
         field(scan,menu(menuScan)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(phase,int16)&lt;br /&gt;
         field(priority,menu(menuPriority)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;b&amp;gt;Event NEEDS NEW DEFINITIONS&amp;lt;/b&amp;gt;&lt;br /&gt;
     struct Event {&lt;br /&gt;
         field(eventNumber,int16) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(timeStampEvent,int16)&lt;br /&gt;
         field(timeStampLink,link(in,interface(????))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Disable {&lt;br /&gt;
         field(disableValue,int16) {&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(disableInput,int16)&lt;br /&gt;
         field(disableLink,link(in,interface(LinkBoolean)))&lt;br /&gt;
         field(disableAlarmSeverity,menu(menuAlarmSevr))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== RecordCommon Record Definition ==&lt;br /&gt;
&lt;br /&gt;
     struct(RecordCommonProcessLink) {&lt;br /&gt;
         field(link,link(process,interface(ProcessLink)))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     record(RecordCommon) {&lt;br /&gt;
         field(description,string)&lt;br /&gt;
         field(scan,struct(Scan))&lt;br /&gt;
         field(event,struct(Event))&lt;br /&gt;
         field(accessSecurityGroup,string)&lt;br /&gt;
         field(pini,boolean)&lt;br /&gt;
         field(disablePutField,boolean)&lt;br /&gt;
         field(alarmAckSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmAckTransient,boolean) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;YES&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(udf,boolean) {&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(time,struct(TimeStamp)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(disable,struct(Disable)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmStatus,string) {&lt;br /&gt;
             default(&amp;quot;UDF&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;Invalid&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(processLink,array(RecordCommonProcessLink[])) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Although it has many fewer fields,&lt;br /&gt;
RecordCommon.dbd is a complete replacement for the V3 dbCommon.&lt;br /&gt;
The following V3 fields are no longer needed:&lt;br /&gt;
* private fields - Private fields will truly be privaye to the implementation&lt;br /&gt;
* previous value fields - All puts to database fields will be posted. The layer above will decide if clients should be notified of changes.&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=549</id>
		<title>V4 DBD Statement Syntax</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=549"/>
		<updated>2005-09-28T19:19:08Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DBD Statement Syntax Sept 28 2005&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
This document presents the syntax for V4 database definition files.&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= General Statements =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== include ==&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;filename&amp;quot;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;filename&amp;lt;/tt&amp;gt;&lt;br /&gt;
: must be a valid filename&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Include statements can be used at the top level, or inside the braces of a &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definition.&lt;br /&gt;
&lt;br /&gt;
== # comment ==&lt;br /&gt;
&lt;br /&gt;
 # anything&lt;br /&gt;
&lt;br /&gt;
Anything on a line after a &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; 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 &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; character has no special meaning.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== menu ==&lt;br /&gt;
&lt;br /&gt;
A menu is an enumerated type where the choice strings are defined once for each IOC.  Menus are defined like this:&lt;br /&gt;
&lt;br /&gt;
 menu(menuName) {&lt;br /&gt;
     choice(choiceName, &amp;quot;choiceValue&amp;quot;)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can be any UTF-8 compatible string, which should be unique within the context of this menu.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 menu(menuScan) {&lt;br /&gt;
     choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
     choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
     choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
     choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
     choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Structures, Record types, Fields and Views =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== struct ==&lt;br /&gt;
&lt;br /&gt;
A structure is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 struct(name) {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The structure name must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular structure.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
&lt;br /&gt;
== record ==&lt;br /&gt;
&lt;br /&gt;
A record type is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 record(name) extends RecordCommon {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     view(viewName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The record type name. It must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;extends RecordCommon&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This states that the record type extends the set of fields defined in &amp;quot;V4 DB RecordCommon&amp;quot;. 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 &amp;lt;tt&amp;gt;extends&amp;lt;/tt&amp;gt; phrase.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular record type and its parents (extends ...).&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#Views of a record|Views of a record]] below.&lt;br /&gt;
&lt;br /&gt;
== fieldType ==&lt;br /&gt;
&lt;br /&gt;
Both &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; define a field as:&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The syntax for &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
=== Basic types: octet, boolean, numerics, and string ===&lt;br /&gt;
&lt;br /&gt;
The following field types have no arguments:&lt;br /&gt;
&amp;lt;tt&amp;gt;octet&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int32&amp;lt;/tt&amp;gt;,  &amp;lt;tt&amp;gt;int64&amp;lt;/tt&amp;gt;,&lt;br /&gt;
&amp;lt;tt&amp;gt;float32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;float64&amp;lt;/tt&amp;gt;,  and &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Examples: &lt;br /&gt;
     field(description,string)&lt;br /&gt;
     field(value,float64)&lt;br /&gt;
&lt;br /&gt;
=== enum ===&lt;br /&gt;
&lt;br /&gt;
An &amp;lt;tt&amp;gt;enum&amp;lt;/tt&amp;gt; field takes one argument after the type name:&lt;br /&gt;
&lt;br /&gt;
     enum(fieldName)&lt;br /&gt;
&lt;br /&gt;
where fieldName is the name of another field in the same record that must be of type &amp;lt;tt&amp;gt;array(string[])&amp;lt;/tt&amp;gt;.  The values in this other field at runtime define the available choice strings for the enum field.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
     field(choices, array(string[])&lt;br /&gt;
     field(value, enum(choices))&lt;br /&gt;
&lt;br /&gt;
=== menu ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt; field is defined like this:&lt;br /&gt;
     menu(menuName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt; is the name of the menu.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     field(scan, menu(menuScan))&lt;br /&gt;
&lt;br /&gt;
=== struct ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; field is declared using the type name&lt;br /&gt;
     struct(structName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;structName&amp;lt;/tt&amp;gt; is the name of a struct which must have been previously defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
      struct(Point) {&lt;br /&gt;
          field(x,float64)&lt;br /&gt;
          field(y,float64)&lt;br /&gt;
          field(z,float64)&lt;br /&gt;
       }&lt;br /&gt;
       ...&lt;br /&gt;
       record(haspoint) extends RecordCommon {&lt;br /&gt;
           ...&lt;br /&gt;
           field(point, struct(point))&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
=== array ===&lt;br /&gt;
&lt;br /&gt;
An array field uses definitions like these:&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 3-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[,,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 2-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;arrayType&amp;lt;/tt&amp;gt; may be any fieldType except &amp;lt;tt&amp;gt;array&amp;lt;/tt&amp;gt;, 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]]&lt;br /&gt;
* &amp;lt;tt&amp;gt;capacity&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(VAL1D,array(float64[]))  #1d array with arbitrary capacity&lt;br /&gt;
     field(VAL2D,array(float64[,])) #2d array with arbitrary capacities&lt;br /&gt;
     field(anyTypeAnyD,array())     #arbitrary type,number of dimensions, and capacities&lt;br /&gt;
&lt;br /&gt;
=== link ===&lt;br /&gt;
&lt;br /&gt;
This field type can get or put data from/to some source outside of the record.&lt;br /&gt;
Link fields replace the DBF_INLINK, DBF_OUTLINK, and DTYP fields from EPICS V3.&lt;br /&gt;
&lt;br /&gt;
A link field's choices come from link definitions - see the [[#link]] section below for more details.&lt;br /&gt;
A link can be a link to another database record, to hardware device support,&lt;br /&gt;
or something else.&lt;br /&gt;
&lt;br /&gt;
The syntax is:&lt;br /&gt;
&lt;br /&gt;
     link(linkDirection,interface(string,...))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;ANDREW&amp;lt;/b&amp;gt;&lt;br /&gt;
What syntax should we use?&lt;br /&gt;
The idea is that the record definition gives a list of interfaces it understands.&lt;br /&gt;
&lt;br /&gt;
where &lt;br /&gt;
* &amp;lt;tt&amp;gt;linkDirection&amp;lt;/tt&amp;gt; : &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. The direction &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt; means there is no direction associated with this interface.  For &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt; the direction is determined by the particular &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; that the record instance selects.&lt;br /&gt;
* &amp;lt;tt&amp;gt;interface(string,...)&amp;lt;/tt&amp;gt; : Each string is the name of Link Interface implemented by link support and used by record support.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(disableLink,&lt;br /&gt;
        link(in,interface ( LinkInt32, LinkFloat64 ))&lt;br /&gt;
     )&lt;br /&gt;
     field(process, link(process,interface(ProcessLink))&lt;br /&gt;
     field(inp,&lt;br /&gt;
        link(in, interface (LinkInt32, LinkFloat64, AsynDigital))&lt;br /&gt;
     )&lt;br /&gt;
&lt;br /&gt;
== fieldAttribute ==&lt;br /&gt;
&lt;br /&gt;
Each field definition has several associated attributes, the values of which are set like this:&lt;br /&gt;
&lt;br /&gt;
     default(&amp;quot;fieldValue&amp;quot;)&lt;br /&gt;
     readonly(yesNo)&lt;br /&gt;
     design(yesNo)&lt;br /&gt;
     special(yesNo)&lt;br /&gt;
     asl(securityLevel)&lt;br /&gt;
     link(yesNo)&lt;br /&gt;
&lt;br /&gt;
'''Marty thinks we should get rid of these two:'''&lt;br /&gt;
     prompt(&amp;quot;promptString&amp;quot;)&lt;br /&gt;
     group(&amp;quot;promptGroup&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
'''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.'''&lt;br /&gt;
&lt;br /&gt;
The attribute parameter values have the following meanings:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;default(&amp;quot;fieldValue&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;readonly(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can this field be modified via channel access or database links?  Takes the value No if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;design(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;special(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;asl(securityLevel)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Channel Access security level for this field, 0 or 1.  Takes the value 1 if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
''These attributes may disappear, see comment above:''&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;prompt(&amp;quot;promptString&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;group(&amp;quot;promptGroup&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
== view ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;field&amp;quot; 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).&lt;br /&gt;
&lt;br /&gt;
A simple view looks like this:&lt;br /&gt;
&lt;br /&gt;
 view(viewName) {&lt;br /&gt;
     property(propName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     property(propName, fieldPath)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The view name must be a valid C identifier, which must be unique in the context of the particular record type.&lt;br /&gt;
; &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: A Data Access property name, which must be a valid C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The path to a field in this record type. To use a field inside a structure field, give the full path to that field: &amp;lt;tt&amp;gt;controlLimit.upper&amp;lt;/tt&amp;gt; for example.&lt;br /&gt;
: If &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; resolves to a structure, a property catalog containing the whole structure will be sent, with property names matching the structure's field names.&lt;br /&gt;
: The &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; may be omitted as long as there is a subordinate property catalog below this property.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 record(ao) extends RecordCommon {&lt;br /&gt;
     field(value, float64) { ... }&lt;br /&gt;
     field(outValue, float64) { ... }&lt;br /&gt;
     field(rawValue, int32) { ... }&lt;br /&gt;
     field(units, string) { ... }&lt;br /&gt;
     field(displayLimit, struct(displayLimit)) { ... }&lt;br /&gt;
     ...&lt;br /&gt;
     view(value)&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(outValue)&lt;br /&gt;
         property(value, outValue) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(rawValue)&lt;br /&gt;
         property(value, rawValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= link =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; statement describes an implementation of support for a link&lt;br /&gt;
field. the support can be any of the following:&lt;br /&gt;
* A link to another record either local or remote&lt;br /&gt;
* A link to hardware support&lt;br /&gt;
* Something else.&lt;br /&gt;
&lt;br /&gt;
The syntax for these is:&lt;br /&gt;
&lt;br /&gt;
 link(dir, choiceName, interfaceName, dataStructName)&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dir&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be one of &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. Compatible checks are made to match the interface with a field.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of an interface via which record support communicates with device support.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; containing configuration information for the link support. Record support normally does not access this structure. Database configuration tools do prompt the user to assign values to the structure.&lt;br /&gt;
&lt;br /&gt;
When a record instance is created the choiceName selects the support&lt;br /&gt;
to attach to a record link. The interfaceName must be one of the&lt;br /&gt;
interface names the record has listed as a valid type and dir must be compatible&lt;br /&gt;
with the dir the record type specified.&lt;br /&gt;
Compatibility means that the dir specified in the link definition is at&lt;br /&gt;
least as generic as the link definition in the record.&lt;br /&gt;
If the record link dir is:&lt;br /&gt;
; &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The link definition must also be &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The link definition must also be &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The link definition must be &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The link definition must be &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The link definition must be &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     link(in,monitorLinkInt16,LinkInt16,MonitorLinkData);&lt;br /&gt;
     link(in,inputLinkInt16,LinkInt16,InputLinkData);&lt;br /&gt;
     link(out,outputLinkInt16,LinkInt16,OutputLinkData);&lt;br /&gt;
     link(inout,asynInt32,LinkInt32,AsynLinkData)&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Runtime_Interfaces&amp;diff=545</id>
		<title>V4 Design: Runtime Interfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Runtime_Interfaces&amp;diff=545"/>
		<updated>2005-09-27T20:11:21Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Runtime Interfaces September 27 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes  definitions for IOC runtime,&lt;br /&gt;
i.e. interfaces implemented or used by database access, record support,&lt;br /&gt;
link support, and device support.&lt;br /&gt;
&lt;br /&gt;
It assumes knowledge of the interfaces described in dbdInterfaces.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; IOC runtime needs lots more work&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Support Code =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section described interfaces for&lt;br /&gt;
strings, arrays, and conversions. &lt;br /&gt;
They are intended for use by Database Access, Record Support, etc.&lt;br /&gt;
&lt;br /&gt;
== C++ support for strings ==&lt;br /&gt;
&lt;br /&gt;
For most strings all the database  needs is a nonmutable string.&lt;br /&gt;
For these it wants to be able to pass a reference to it to arbitrary code.&lt;br /&gt;
It needs this for things like record type names, field names, record instance names, menu choice names, etc. etc. Some of these may change but very infrequently.&lt;br /&gt;
The string always contains UTF-8 encoded strings, which I believe can  be printed with a &amp;quot;%s&amp;quot; format if&lt;br /&gt;
the string is made available as a &amp;quot;const char *&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Perhaps the only type of  string connected with an IOC record that changes frequently is a field in a record type like stringin and stringout. In this case the record support can do what ever it wants to handle the string. It can even just use C style strings!!!&lt;br /&gt;
&lt;br /&gt;
Thus all the IOC database needs is a:&lt;br /&gt;
&lt;br /&gt;
1) nonmutable reference counted continguous string. When the reference count goes to 0 the storage can be reclaimed&lt;br /&gt;
2) The ability to copy the value from a nonmutable string to a mutable string.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In Java String and StringBuffer are all that is needed.&lt;br /&gt;
&lt;br /&gt;
In C++ all that is needed is&lt;br /&gt;
&lt;br /&gt;
1) A class that holds UFT-8 encoded non-mutable strings and make the contents available as a &amp;quot;const char *&amp;quot; and it's length. The class keeps a reference count and frees the storage when done.&lt;br /&gt;
2) The ability to copy the nonmutable string to a &amp;quot;char *&amp;quot; array allocated by the requester.&lt;br /&gt;
&lt;br /&gt;
That is all.&lt;br /&gt;
&lt;br /&gt;
== array copy ==&lt;br /&gt;
&lt;br /&gt;
ArrayCopy copies arrays an array performing conversions if necessary.&lt;br /&gt;
&lt;br /&gt;
     interface ArrayCopy {&lt;br /&gt;
         void copy(DbfArray from,DbfArray to);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
This only supports primitive types, i.e. DbfBoolean,...,DbfFloat64.&lt;br /&gt;
It does NOT convert between&lt;br /&gt;
* DbfBoolean and another type.&lt;br /&gt;
* DbfOctet and another type.&lt;br /&gt;
Thus for DbfBoolean and DbfOctet it is willing to copy&lt;br /&gt;
but not convert to/from other types.&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Conversions ==&lt;br /&gt;
This is a static class that converts between primitie types and arrays of primitive types.&lt;br /&gt;
&lt;br /&gt;
     static class DbfConvertPrimitive {&lt;br /&gt;
     public:&lt;br /&gt;
          int16 get(Dbf from);&lt;br /&gt;
          int32 get(Dbf from);&lt;br /&gt;
          int64 get(Dbf from);&lt;br /&gt;
          float32 get(Dbf from);&lt;br /&gt;
          float64 get(Dbf from);&lt;br /&gt;
          get(Dbf from, String value);&lt;br /&gt;
          get(DbfOctet from, String value);&lt;br /&gt;
          get(DbfBoolean from, String value);&lt;br /&gt;
          put(Dbf to, int16 value);&lt;br /&gt;
          put(Dbf to, int32 value);&lt;br /&gt;
          put(Dbf to, int64 value);&lt;br /&gt;
          put(Dbf to, float32 value);&lt;br /&gt;
          put(Dbf to, float64 value);&lt;br /&gt;
          put(Dbf to,int32 String value);&lt;br /&gt;
          put(DbfOctet to, String value);&lt;br /&gt;
          put(DbfBoolean to, String value);&lt;br /&gt;
&lt;br /&gt;
          get(DbfArray from, int16[] value);&lt;br /&gt;
          get(DbfArray from, int32[] value);&lt;br /&gt;
          get(DbfArray from, int64[] value);&lt;br /&gt;
          get(DbfArray from, float32[] value);&lt;br /&gt;
          get(DbfArray from, float64[] value);&lt;br /&gt;
          put(DbfArray to, int16[] value);&lt;br /&gt;
          put(DbfArray to, int32[] value);&lt;br /&gt;
          put(DbfArray to, int64[] value);&lt;br /&gt;
          put(DbfArray to, float32[] value);&lt;br /&gt;
          put(DbfArray to, float64[] value);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* For Dbf &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; must be one of &amp;lt;tt&amp;gt;DbfInt16&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;DbfFloat64&amp;lt;/tt&amp;gt;&lt;br /&gt;
* The get to a string implements printf semantics&lt;br /&gt;
* The put from a string value just scanf semantics.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;DbfOctet&amp;lt;/tt&amp;gt; methods convert to/from a string of the form &amp;quot;0xXX&amp;quot;&lt;br /&gt;
* The &amp;lt;tt&amp;gt;DbfBoolean&amp;lt;/tt&amp;gt; get method supports all the choices specified in the DBD Record Instance Specification&lt;br /&gt;
* For DbfArray &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; must be an array of one of &amp;lt;tt&amp;gt;DbfInt16&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;DbfFloat64&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code generated from Database Definition Files =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following shows the Java code generated from DBD files:&lt;br /&gt;
&lt;br /&gt;
== structure definitions ==&lt;br /&gt;
&lt;br /&gt;
Two files are generated from &amp;lt;tt&amp;gt;struct(name)&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
# &amp;lt;tt&amp;gt;name.java&amp;lt;/tt&amp;gt;&lt;br /&gt;
# &amp;lt;tt&amp;gt;nameSupport.java&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;name.java&amp;lt;/tt&amp;gt; implements:&lt;br /&gt;
     interface Struct {&lt;br /&gt;
         Dbf getField(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a structure is defined as:&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,double)&lt;br /&gt;
         field(high,double)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
A generated file &amp;lt;tt&amp;gt;DisplayLimit.java&amp;lt;/tt&amp;gt; contains:&lt;br /&gt;
&lt;br /&gt;
     public class DisplayLimit implements Struct{&lt;br /&gt;
         public DbfFloat64 low;&lt;br /&gt;
         public DbfFloat64 high;&lt;br /&gt;
         public static final short lowIndex = 1;&lt;br /&gt;
         public static final short highIndex = 2;&lt;br /&gt;
         public static final short lastIndex = indexHigh;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case lowIndex: return(low);&lt;br /&gt;
                 case highIndex: return(high);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
             return null;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
A generated file &amp;lt;tt&amp;gt;DisplayLimitAccess.java&amp;lt;/tt&amp;gt; contains:&lt;br /&gt;
&lt;br /&gt;
     public class DisplayLimitData {&lt;br /&gt;
         public double low;&lt;br /&gt;
         public double high;&lt;br /&gt;
     }&lt;br /&gt;
     public final class DisplayLimitAccess implements StructFactory{&lt;br /&gt;
         public Struct create() { return new DisplayLimit; }&lt;br /&gt;
         public static final void get(DbfStruct from,DisplayLimitData data) {&lt;br /&gt;
             DbfFloat64 dbf = from.getInterface(1);&lt;br /&gt;
             data.low = dbf.get();&lt;br /&gt;
             DbfFloat64 dbf = from.getInterface(2);&lt;br /&gt;
             data.high = dbf.get();&lt;br /&gt;
         }&lt;br /&gt;
         public static final void put(DbfStruct to, DisplayLimitData data) {&lt;br /&gt;
             DbfFloat64 dbf = to.getInterface(1);&lt;br /&gt;
             dbf.put(data.low);&lt;br /&gt;
             DbfFloat64 dbf = to.getInterface(2);&lt;br /&gt;
             dbf.put(data.high);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class DisplayLimitAccessRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             DisplayLimitAccess access = new DisplayLimitAccess;&lt;br /&gt;
             RegisterSupport.structure(access,&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; The V4 replacement for registerRecordDeviceDriver must&lt;br /&gt;
call DisplayLimitAccessRegister.createAndRegister.&lt;br /&gt;
&lt;br /&gt;
Similar files are generated for C++.&lt;br /&gt;
&lt;br /&gt;
== record definitions ==&lt;br /&gt;
If a record is defined as:&lt;br /&gt;
     record(Example) extends RecordCommon {&lt;br /&gt;
         ...&lt;br /&gt;
         field(fboolean,boolean)&lt;br /&gt;
         field(octet,octet)&lt;br /&gt;
         field(fint,int16)&lt;br /&gt;
         ...&lt;br /&gt;
         field(ffloat,float64)&lt;br /&gt;
         field(string,string)&lt;br /&gt;
         field(array,array(double[])&lt;br /&gt;
         field(mdarray,array(double[,])&lt;br /&gt;
         field(menu,menu(name))&lt;br /&gt;
         field(fenum,enum)&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(device,link(in,analogIO))&lt;br /&gt;
         field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The generated Java file is&lt;br /&gt;
&lt;br /&gt;
     public class ExampleRecord implements Struct {&lt;br /&gt;
         public DbfBoolean   fboolean;&lt;br /&gt;
         public DbfOctet     ctet;&lt;br /&gt;
         public DbfInt16     fint;&lt;br /&gt;
         ...&lt;br /&gt;
         public DbfFloat64   ffloat;&lt;br /&gt;
         public DbfString    string;&lt;br /&gt;
         public DbfArray     array;&lt;br /&gt;
         public DbfMDArray   mdarray;&lt;br /&gt;
         public DbfMenu      menu;&lt;br /&gt;
         public DbfEnum      fenum;&lt;br /&gt;
         public DbfLink      link;&lt;br /&gt;
         public DbfDevice    device;&lt;br /&gt;
         public DbfStruct    displayLimit;&lt;br /&gt;
         public static final int16 fbooleanIndex = 1;&lt;br /&gt;
         ...&lt;br /&gt;
         public static final int16 lastIndex = displayLimitIndex;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case fbooleanIndex : return(fboolean);&lt;br /&gt;
                 ...&lt;br /&gt;
                 case displayLimitIndex: return(displayLimit);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class ExampleRecordFactory implements StructFactory{&lt;br /&gt;
         public static final Struct create() { return new ExampleRecord; }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class ExampleRecordFactoryRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             ExampleRecordFactory  factory = new ExampleRecordFactory;&lt;br /&gt;
             RegisterSupport.record(factory,&amp;quot;ExampleRecord&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; The V4 replacement for registerRecordDeviceDriver must&lt;br /&gt;
call ExampleRecordFactoryRegister.createAndRegister&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar code is generated for C++.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Record Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     enum ProcessState {&lt;br /&gt;
         processCancel,&lt;br /&gt;
         processStart,&lt;br /&gt;
         processContinue,&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum ProcessReturn {&lt;br /&gt;
         processDone,&lt;br /&gt;
         processAbort,&lt;br /&gt;
         processActive&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RecordSupport {&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize(int32 pass);&lt;br /&gt;
         ProcessState process(ProcessState state,Callback done);&lt;br /&gt;
         // if special returns false when after is false put fails&lt;br /&gt;
         boolean special(boolean after,Dbf[] field);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ProcessState&amp;lt;/tt&amp;gt; supports the following semantics:&lt;br /&gt;
* cancel - If the record is active terminate &lt;br /&gt;
* For all other states see the companion document &amp;quot;V4 Design: Record Processing&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The methods of &amp;lt;tt&amp;gt;RecordSupport&amp;lt;/tt&amp;gt; are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - Called when a record instance is deleted.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called twice (pass = 0,1) when a record is initialized.&lt;br /&gt;
* &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; - Called to process a record. See &amp;quot;V4 Design: Record Processing&amp;quot; for semantics.&lt;br /&gt;
* &amp;lt;tt&amp;gt;special&amp;lt;/tt&amp;gt; - Called when a field declared special in a DBD file is modified. &amp;lt;tt&amp;gt;field&amp;lt;/tt&amp;gt; is an array of Dbfs showing which field is being modified.&lt;br /&gt;
&lt;br /&gt;
== Discussion of special ==&lt;br /&gt;
&lt;br /&gt;
Special is passed a Dbf array that identifies the field being modified.&lt;br /&gt;
For example &amp;lt;tt&amp;gt;ExampleRecord.dbd&amp;lt;/tt&amp;gt; has a field:&lt;br /&gt;
     field(displayLimit,struct(displayLimit))&lt;br /&gt;
&amp;lt;tt&amp;gt;ExampleRecordSupport.java&amp;lt;/tt&amp;gt; might implement special as follows:&lt;br /&gt;
     boolean special(boolean after, Dbf[] field)&lt;br /&gt;
     {&lt;br /&gt;
         switch(field[0].getIndex()) {&lt;br /&gt;
         ...&lt;br /&gt;
         case ExampleRecord.displayLimitIndex:&lt;br /&gt;
             if(field.length==1) {&lt;br /&gt;
                 // displayLimits itself is being modified. Do something&lt;br /&gt;
             } else {&lt;br /&gt;
                // a field of displayLimits is being modified&lt;br /&gt;
                 switch(field[1].getIndex) {&lt;br /&gt;
                     case DisplayLimit.lowIndex:&lt;br /&gt;
                          // low being modified. do something&lt;br /&gt;
                     case DisplayLimit.highIndex:&lt;br /&gt;
                          // high being modified. do something&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         ...&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
=  Link Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Link  ==&lt;br /&gt;
     interface Link {&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Link&amp;lt;/tt&amp;gt; is an interface that must be implemented by every link&lt;br /&gt;
support.&lt;br /&gt;
An instance of this is connected to each DbfLink field.&lt;br /&gt;
The methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
Normally record support does not need to call any of the Link methods&lt;br /&gt;
since database access does this automatically. For example if a link&lt;br /&gt;
field is modified via a channel access put, database access will call&lt;br /&gt;
destroy before modifying the link and initialize and connect after the&lt;br /&gt;
link is modidied.&lt;br /&gt;
&lt;br /&gt;
== Definitions that apply to Process,Monitor,Input,and Output support ==&lt;br /&gt;
&lt;br /&gt;
     enum LinkWaitResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWait,           // waiting. can do additional procsssing&lt;br /&gt;
         linkWaitBlock,      // waiting. dont do additional processing until&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
== Process Link Support ==&lt;br /&gt;
     interface ProcessLinkSupport&amp;lt;type&amp;gt; {&lt;br /&gt;
         void process();&lt;br /&gt;
         LinkWaitResult processWait(double timeout,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Monitor Link Support ==&lt;br /&gt;
There is support for the following types: octet, boolean, int16, int32,&lt;br /&gt;
int64, float32, float64, and arrays of each of these types.&lt;br /&gt;
&lt;br /&gt;
     interface MonitorLink&amp;lt;type&amp;gt; {&lt;br /&gt;
         void get(&amp;lt;type&amp;gt; data);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Input Link Support ==&lt;br /&gt;
There is support for the following types: octet, boolean, int16, int32,&lt;br /&gt;
int64, float32, float64, and arrays of each of these types.&lt;br /&gt;
&lt;br /&gt;
     interface InputLinkSupport&amp;lt;type&amp;gt; {&lt;br /&gt;
         void get(&amp;lt;type&amp;gt; data);&lt;br /&gt;
         LinkWaitResult getWait(&amp;lt;type&amp;gt; data, double timeout,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
== Output Link Support ==&lt;br /&gt;
There is support for the following types: octet, boolean, int16, int32,&lt;br /&gt;
int64, float32, float64, and arrays of each of these types.&lt;br /&gt;
&lt;br /&gt;
     interface OutputLinkSupport&amp;lt;type&amp;gt; {&lt;br /&gt;
         void put(Dbf field);&lt;br /&gt;
         LinkWaitResult putWait(Dbf field, double timeout,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Registration and Instance Creation =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     interface StructFactory {&lt;br /&gt;
         DbfStruct create();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RecordSupportFactory {&lt;br /&gt;
         RecordSupport create(RecordInstance instance);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface SupportFactory {&lt;br /&gt;
         Support create(Dbf field);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RegisterSupport {&lt;br /&gt;
         structure(StructFactory create, string name);&lt;br /&gt;
         record(StructFactory create, string name);&lt;br /&gt;
         link(SupportFactory support,string name);&lt;br /&gt;
         device(SupportFactory support,string name);&lt;br /&gt;
         record(RecordSupportFactory support,string name);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;RegisterSupport&amp;lt;/tt&amp;gt; is implemented by iocCore.&lt;br /&gt;
Each &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; DBD definition must register a StructFactory to&lt;br /&gt;
create instances of the structure or record.&lt;br /&gt;
&lt;br /&gt;
Each link, device, and record support must register a SupportFactory to create&lt;br /&gt;
instances of the support to attach to the link, device, or record instance.&lt;br /&gt;
During database initialization, iocCore calls the factory methods.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtime Database Access =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Database Access, with help from record, link, and device support&lt;br /&gt;
implements the dbdInterfaces.&lt;br /&gt;
Other than Database Access, fields of a record can only&lt;br /&gt;
be accessed via the interfaces described in dbdInterfaces.&lt;br /&gt;
This allows the database to handle&lt;br /&gt;
actions like posting database monitors without any help from&lt;br /&gt;
record, link, or device support.&lt;br /&gt;
&lt;br /&gt;
Database access by default allocates the actual storage for each field&lt;br /&gt;
but allows support code to register itself to manage storage for field&lt;br /&gt;
instances.&lt;br /&gt;
Two examples, both involving arrays, are:&lt;br /&gt;
* The compress record  registers to provide storage for the value.&lt;br /&gt;
** This allows it to implement a circular buffer.&lt;br /&gt;
** Code that accesses the value field may have to issue two get requests.&lt;br /&gt;
* Device support for a transient recorder registers to provide storage for the array&lt;br /&gt;
** This allows device support to read data from hardware in segments&lt;br /&gt;
** Code that accesses the array may have to issue many get requests.&lt;br /&gt;
&lt;br /&gt;
The fact that each field of a record instance is an object means that additional storage is required.&lt;br /&gt;
Database Access  will probably have something like the following:&lt;br /&gt;
&lt;br /&gt;
    class Field {&lt;br /&gt;
        DbRecord instance;&lt;br /&gt;
        short          index;&lt;br /&gt;
    };&lt;br /&gt;
    ...&lt;br /&gt;
    class IntField extends Field {&lt;br /&gt;
        int data;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
This each field has the overhead of&lt;br /&gt;
* instance - a reference to DbRecord, i.e. record instance&lt;br /&gt;
* index - a 16 bit integer&lt;br /&gt;
* vtbl - a reference to the object implementation&lt;br /&gt;
&lt;br /&gt;
Additional fields will be needed for things like monitors.&lt;br /&gt;
These fields can start out null and only allocate storage as needed.&lt;br /&gt;
&lt;br /&gt;
== Database Access ==&lt;br /&gt;
&lt;br /&gt;
     interface DbAccess {&lt;br /&gt;
         void process(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processCancel(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processContinue(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processRequestAccept(Dbf field, boolean yesNo);&lt;br /&gt;
         void registerDbfSource(Dbf field, Dbf source);&lt;br /&gt;
         LinkSupport getLinkSupport(Dbf field);&lt;br /&gt;
         Support getSupport(Dbf field);&lt;br /&gt;
         RecordSupport getRecordSupport(DbInstance instance);&lt;br /&gt;
         RecordSupport getRecordCommonSupport(DbInstance instance);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; - Request processing. Record must be idle or active or request fails.&lt;br /&gt;
** &amp;lt;tt&amp;gt;instance&amp;lt;/tt&amp;gt; - The record to process&lt;br /&gt;
** &amp;lt;tt&amp;gt;callback&amp;lt;/tt&amp;gt; - A callback to call when processing completes or for failure.&lt;br /&gt;
* &amp;lt;tt&amp;gt;processRequestAccept&amp;lt;/tt&amp;gt; - Should a process request from channel access be accepted,&lt;br /&gt;
* &amp;lt;tt&amp;gt;registerDbfSource&amp;lt;/tt&amp;gt; - Register code that will implement storage for the field.&lt;br /&gt;
* &amp;lt;tt&amp;gt;getLinkSupport&amp;lt;/tt&amp;gt; - Find the link support for a link field&lt;br /&gt;
* &amp;lt;tt&amp;gt;getSupport&amp;lt;/tt&amp;gt; - Get the device support for a device field&lt;br /&gt;
* &amp;lt;tt&amp;gt;getRecordSupport&amp;lt;/tt&amp;gt; - Get the record support for the record&lt;br /&gt;
* &amp;lt;tt&amp;gt;getRecordCommonSupport&amp;lt;/tt&amp;gt; - Get the RecordCommon support for the record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTES&amp;lt;/b&amp;gt; This is just the beginning of defining the methods in DbAccess&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_dbdInterfaces&amp;diff=556</id>
		<title>V4 Design: dbdInterfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_dbdInterfaces&amp;diff=556"/>
		<updated>2005-09-27T20:09:03Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: dbdInterfaces - IOC Database Description September 27 2005 &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes  definitions for code that accessses&lt;br /&gt;
IOC records, i.e. the records created from Database Definitions:&lt;br /&gt;
menu, struct, record, link, device, and record instances.&lt;br /&gt;
&lt;br /&gt;
The interfaces support introspection of everything created from Database&lt;br /&gt;
Definitions. The interfaces can be used by tools such as VDCT or on&lt;br /&gt;
a running IOC database.&lt;br /&gt;
&lt;br /&gt;
The definitions can be used by code that use code automatically&lt;br /&gt;
generated from DBD files or by code that uses only introspection.&lt;br /&gt;
&lt;br /&gt;
Code is automatically generated from the following definitions:&lt;br /&gt;
* &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; - Used by record support.&lt;br /&gt;
* &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; - Used by code that understands the struct.&lt;br /&gt;
* &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt; - Used by code that understands the menu.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Syntax =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax is defined so that either C++ and Java implementations can be created.&lt;br /&gt;
&lt;br /&gt;
NOTE: Most of the code fragments use Java syntax.&lt;br /&gt;
&lt;br /&gt;
== Primitive Types ==&lt;br /&gt;
* octet - 8 bit byte&lt;br /&gt;
* boolean - a value that takes the values &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt;&lt;br /&gt;
* int16 - 16 bit signed integer&lt;br /&gt;
* int32 - 32 bit signed integer&lt;br /&gt;
* int64 - 64 bit signed integer&lt;br /&gt;
* float32 - 32 bit IEEE float&lt;br /&gt;
* float64 - 64 bit IEEE float&lt;br /&gt;
&lt;br /&gt;
In Java these types become:&lt;br /&gt;
&lt;br /&gt;
* octet =&amp;gt; byte  BUT no arithmetic is implied&lt;br /&gt;
* boolean =&amp;gt; boolean&lt;br /&gt;
* int16 =&amp;gt; short&lt;br /&gt;
* int32 =&amp;gt; int&lt;br /&gt;
* int64 =&amp;gt; long&lt;br /&gt;
* float32 =&amp;gt; float&lt;br /&gt;
* float64 =&amp;gt; double&lt;br /&gt;
&lt;br /&gt;
In C++ these types become:&lt;br /&gt;
&lt;br /&gt;
* octet =&amp;gt; char  BUT no arithmetic is implied&lt;br /&gt;
* boolean =&amp;gt; bool BUT no arithmetic or conversion to/from int is implied&lt;br /&gt;
* int16 =&amp;gt; int16_t&lt;br /&gt;
* int32 =&amp;gt; int32_t&lt;br /&gt;
* int64 =&amp;gt; int64_t&lt;br /&gt;
* float32 =&amp;gt; float&lt;br /&gt;
* float64 =&amp;gt; double&lt;br /&gt;
&lt;br /&gt;
NOTE:&lt;br /&gt;
* The C++ integer types are from C99 stdint.h&lt;br /&gt;
* Should exceptions be defined?&lt;br /&gt;
&lt;br /&gt;
== enum, struct, interface, class,  string, array ==&lt;br /&gt;
&lt;br /&gt;
In adition to the primitive types the syntax&lt;br /&gt;
uses the terms enum, struct, interface, and array.&lt;br /&gt;
&lt;br /&gt;
=== enum ===&lt;br /&gt;
&lt;br /&gt;
An example of an enum is:&lt;br /&gt;
&lt;br /&gt;
     enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The C++  definition is identical. In Java 5 the definition would be:&lt;br /&gt;
&lt;br /&gt;
     public enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
=== struct ===&lt;br /&gt;
An example of a struct definition is:&lt;br /&gt;
&lt;br /&gt;
     struct DisplayLimitData {&lt;br /&gt;
         float64 low;&lt;br /&gt;
         float64 high;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In C++ this would be:&lt;br /&gt;
&lt;br /&gt;
    class DisplayLimitData {&lt;br /&gt;
    public:&lt;br /&gt;
         double low;&lt;br /&gt;
         double high;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
In Java this would be:&lt;br /&gt;
&lt;br /&gt;
     class DisplayLimitData {&lt;br /&gt;
         public double low;&lt;br /&gt;
         public double high;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== interface ===&lt;br /&gt;
An example of an interface definition is:&lt;br /&gt;
&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void    put(boolean val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
In C++ would be:&lt;br /&gt;
     class DbfBoolean : public Dbf {&lt;br /&gt;
     public:&lt;br /&gt;
         virtual bool get() = 0;&lt;br /&gt;
         virtual void put(bool val) = 0;&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
In Java would be:&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void    put(boolean val)&lt;br /&gt;
     }&lt;br /&gt;
=== class ===&lt;br /&gt;
&lt;br /&gt;
Any class definitions are language specific.&lt;br /&gt;
&lt;br /&gt;
=== string ===&lt;br /&gt;
&lt;br /&gt;
For C++ a string will be a &amp;lt;tt&amp;gt;char *&amp;lt;/tt&amp;gt; array containing UTF-8&lt;br /&gt;
compatible characters not necessarily terminated with a null character.&lt;br /&gt;
Wherever a &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt; argument appears, the C++ definition&lt;br /&gt;
will have &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;char *&amp;lt;/tt&amp;gt; arguments.&lt;br /&gt;
&lt;br /&gt;
For Java string will just be a &amp;lt;tt&amp;gt;String&amp;lt;/tt&amp;gt;.&lt;br /&gt;
It is assumed that Java Strings will be converted to/from UTF-8 byte streams&lt;br /&gt;
when the data is transfered to/from the network.&lt;br /&gt;
&lt;br /&gt;
An example of a definition that includes a string argument is&lt;br /&gt;
     void get(String name);&lt;br /&gt;
&lt;br /&gt;
In C++  this will become&lt;br /&gt;
     void get(int lenName, char *name);&lt;br /&gt;
In Java this will become&lt;br /&gt;
     void get(String name);&lt;br /&gt;
=== array ===&lt;br /&gt;
&lt;br /&gt;
An example of a definition that includes an array is:&lt;br /&gt;
&lt;br /&gt;
     void get(float64[] data);&lt;br /&gt;
&lt;br /&gt;
In C++ ,this would become:&lt;br /&gt;
&lt;br /&gt;
     void get(int lenData, double data[]);&lt;br /&gt;
&lt;br /&gt;
In Java this would be:&lt;br /&gt;
&lt;br /&gt;
     void get(double[] data);&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= DbfTypes =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
The following naming conventions are used:&lt;br /&gt;
; Dbf&lt;br /&gt;
: any class starting with Dbf describes a field in a header file generated from a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definition. For example DbfArray describes a field generated from &amp;lt;tt&amp;gt;field(name,array(float64[])&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; Dbd&lt;br /&gt;
: A class name starting with Dbd describes something related to dbd definitions. For example DbdMenu describes a dbd menu definition.&lt;br /&gt;
&lt;br /&gt;
All Dbf and Dbd definitions are interfaces. Thus all access to data is via&lt;br /&gt;
interfaces.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbfTypes.h&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
The following &amp;lt;tt&amp;gt;enum&amp;lt;/tt&amp;gt; definitions describe &lt;br /&gt;
each field in the header files generated from DBD &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; and&lt;br /&gt;
&amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
&lt;br /&gt;
     enum BasicType {&lt;br /&gt;
         basicTypeOctet,    // DbfOctet&lt;br /&gt;
         basicTypeBoolean,  // DbfBoolean&lt;br /&gt;
         basicTypeInt16,    // DbfInt16&lt;br /&gt;
         basicTypeInt32,    // DbfInt32&lt;br /&gt;
         basicTypeInt64,    // DbfInt64&lt;br /&gt;
         basicTypeFloat32,  // DbfFloat32&lt;br /&gt;
         basicTypeFloat64,  // DbfFloat64&lt;br /&gt;
         basicTypeString,   // DbfString&lt;br /&gt;
         basicTypeArray,    // DbfArray&lt;br /&gt;
         basicTypeStruct,   // DbfStruct&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum DbfType {&lt;br /&gt;
         dbfTypeBasic,       // DbfOctet,...,DbfStruct&lt;br /&gt;
         dbfTypeMenu,        // DbfMenu&lt;br /&gt;
         dbfTypeEnum,        // DbfEnum&lt;br /&gt;
         dbfTypeLink,        // DbfLink&lt;br /&gt;
         dbfTypeMDArray,     // DbfMDArray&lt;br /&gt;
         dbfTypeTimeStamp    // DbfTimeStamp&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Discussion of DbfTypes ==&lt;br /&gt;
&lt;br /&gt;
The example code shown below uses Java syntax.&lt;br /&gt;
It assumes the following definitions:&lt;br /&gt;
&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,double)&lt;br /&gt;
         field(high,double)&lt;br /&gt;
     }&lt;br /&gt;
     record(Example) extends RecordCommon {&lt;br /&gt;
         ...&lt;br /&gt;
         field(octet,octet)&lt;br /&gt;
         field(fboolean,boolean)&lt;br /&gt;
         field(fint,int16)&lt;br /&gt;
         ...&lt;br /&gt;
         field(ffloat,float64)&lt;br /&gt;
         field(string,string)&lt;br /&gt;
         field(array,array(double[])&lt;br /&gt;
         field(mdarray,array(double[,])&lt;br /&gt;
         field(menu,menu(name))&lt;br /&gt;
         field(fenum,enum)&lt;br /&gt;
         //FOLLOWING IS NOT VALID LINK DEFINITION&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
From this the following Java code is automatically generated.&lt;br /&gt;
     public class DisplayLimit implements Struct{&lt;br /&gt;
         public DbfFloat64 low;&lt;br /&gt;
         public DbfFloat64 high;&lt;br /&gt;
         ...&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case lowIndex: return(low);&lt;br /&gt;
                 case highIndex: return(high);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
             return null;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     public class ExampleRecord implements Struct {&lt;br /&gt;
         public DbfOctet     ctet;&lt;br /&gt;
         public DbfBoolean   fboolean;&lt;br /&gt;
         public DbfInt16     fint;&lt;br /&gt;
         ...&lt;br /&gt;
         public DbfFloat64   ffloat;&lt;br /&gt;
         public DbfString    string;&lt;br /&gt;
         public DbfArray     array;&lt;br /&gt;
         public DbfMDArray   mdarray;&lt;br /&gt;
         public DbfMenu      menu;&lt;br /&gt;
         public DbfEnum      fenum;&lt;br /&gt;
         public DbfLink      link;&lt;br /&gt;
         public DbfStruct    displayLimit;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case fbooleanIndex : return(fboolean);&lt;br /&gt;
                 ...&lt;br /&gt;
                 case displayLimitIndex: return(displayLimit);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Similar code is generated for C++.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Database Fields =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each database field is accessed via an interface which all extend&lt;br /&gt;
the following interface:&lt;br /&gt;
&lt;br /&gt;
     interface Dbf{&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         boolean isPrimitive(); // BasicTypeBoolean,...,BasicTypeFloat64&lt;br /&gt;
         boolean isBasic();&lt;br /&gt;
         BasicType getBasicType();&lt;br /&gt;
         DbInstance getRecord();&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The interfaces are designed so that a field can be accessded&lt;br /&gt;
without exposing the address of its data.&lt;br /&gt;
&lt;br /&gt;
== Primitive Types ==&lt;br /&gt;
&lt;br /&gt;
DbfOctet, ..., DbfFloat64 are all interfaces with methods get and put.&lt;br /&gt;
    &lt;br /&gt;
     interface DbfOctet extends Dbf {&lt;br /&gt;
         octet get();&lt;br /&gt;
         void put(octet val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfBoolean extends Dbf {&lt;br /&gt;
         boolean get();&lt;br /&gt;
         void put(boolean val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt16 extends Dbf {&lt;br /&gt;
         int16 get();&lt;br /&gt;
         void put(int16 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt32 extends Dbf {&lt;br /&gt;
         int32 get();&lt;br /&gt;
         void put(int32 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfInt64 extends Dbf {&lt;br /&gt;
         int64 get();&lt;br /&gt;
         void put(int64 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfFloat32 extends Dbf {&lt;br /&gt;
         float32 get();&lt;br /&gt;
         void put(float32 val);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfFloat64 extends Dbf {&lt;br /&gt;
         float64 get();&lt;br /&gt;
         void put(float64 val);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Record support code can access such fields via the generated header&lt;br /&gt;
file. Some examples are:&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     short myint;&lt;br /&gt;
     ...&lt;br /&gt;
     precord.ffloat.put(10.0);&lt;br /&gt;
     ...&lt;br /&gt;
     myint = precord.fint.get();&lt;br /&gt;
&lt;br /&gt;
Code that does not include the generated header file can access these fields&lt;br /&gt;
via the introspection interfaces described later in this document.&lt;br /&gt;
For example code that expects a float64 field can access it via&lt;br /&gt;
&lt;br /&gt;
     Dbf dbf =  DbInstanceLocate.getField(&amp;quot;recordname.value&amp;quot;);&lt;br /&gt;
     if(dbf==null&lt;br /&gt;
     || !dbf.isPrimitive()&lt;br /&gt;
     || (dbf.getBasicType() != basicTypeFloat64) ) // do something&lt;br /&gt;
     DbfFloat64 dbfdouble = (DbfFloat64)dbf;&lt;br /&gt;
     dbfdouble.put(10.0);&lt;br /&gt;
&lt;br /&gt;
or more concisely (but exception may be thrown)&lt;br /&gt;
     DbfConvertPrimitive(DbInstanceLocate.getField(&amp;quot;recordname.value&amp;quot;),10.0);&lt;br /&gt;
&lt;br /&gt;
== String fields ==&lt;br /&gt;
&lt;br /&gt;
The interface for a string field is:&lt;br /&gt;
&lt;br /&gt;
     interface DbfString extends Dbf {&lt;br /&gt;
        int32 getLength();&lt;br /&gt;
        void get(string value);&lt;br /&gt;
        void setPutSize(int32 size);&lt;br /&gt;
        void put(string value);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following code prints a string.&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     String string;&lt;br /&gt;
     record.fstring.get(string);&lt;br /&gt;
     printf(&amp;quot;%s\n&amp;quot;,string);&lt;br /&gt;
&lt;br /&gt;
Code that does not include the header file can use the introspection methods&lt;br /&gt;
to locate the DbfString that provides access to the field.&lt;br /&gt;
&lt;br /&gt;
== Structure Fields ==&lt;br /&gt;
&lt;br /&gt;
     interface DbfStruct extends Dbf {&lt;br /&gt;
         int16 getNfields();&lt;br /&gt;
         Dbf getInterface(int16 index);&lt;br /&gt;
         DbdField getDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following traverses the fields of a DbfStruct&lt;br /&gt;
&lt;br /&gt;
     DbfStruct dbfStruct;&lt;br /&gt;
     &lt;br /&gt;
     for(i=0; i &amp;lt; dbfStruct.getNfields(); i++) {&lt;br /&gt;
         DbdField dbdField = dbfStruct.getDescription(i);&lt;br /&gt;
         String name;&lt;br /&gt;
         dbdField.getName(name);&lt;br /&gt;
         printf(&amp;quot;field %s\n&amp;quot;,name);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Structure fields can only be accessed via introspection.&lt;br /&gt;
However, for each structure, code is generated that does the introspection.&lt;br /&gt;
For example DisplayLimitData can be obtained via the statements:&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     DisplayLimitData limit = new DisplayLimitData();&lt;br /&gt;
     &lt;br /&gt;
     ...&lt;br /&gt;
     DisplayLimitSupport.get(record.displayLimit,limit);&lt;br /&gt;
     printf(&amp;quot;low %f high %f\n&amp;quot;,limit.low,limit.high);&lt;br /&gt;
&lt;br /&gt;
== Array Fields ==&lt;br /&gt;
&lt;br /&gt;
The generated header file will have a type that extends &amp;lt;tt&amp;gt;DbfArray&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     interface DbfArray extends Dbf {&lt;br /&gt;
        DbfType getType();&lt;br /&gt;
        int32 getNelements();&lt;br /&gt;
        void setNelements(int32 len);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfBooleanArray extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, boolean[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, boolean[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfOctetArray extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, octet[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, octet[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt16Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int16[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int16[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt32Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int32[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int32[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfInt64Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, int64[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, int64[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfFloat32Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, float32[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, float32[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfFloat64Array extends DbfArray {&lt;br /&gt;
        int32 get(int32 offset, int32 len, float64[] pto);&lt;br /&gt;
        int32 put(int32 offset, int32 len, float64[] pfrom);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfStringArray extends DbfArray {&lt;br /&gt;
         DbfString getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfArrayArray extends DbfArray {&lt;br /&gt;
         DbfArray getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfStructArray extends DbfArray {&lt;br /&gt;
         DbfStruct getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfMenuArray extends DbfArray {&lt;br /&gt;
         DbfMenu getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfEnumArray extends DbfArray {&lt;br /&gt;
         DbfEnum getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfLinkArray extends DbfArray {&lt;br /&gt;
         DbfLink getInterface(int32 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The following puts data into a float64 field.&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
&lt;br /&gt;
     double[] data = new double[] {1.0,2.0,3.0};;&lt;br /&gt;
     if(!record.ffloat.isPrimitive()&lt;br /&gt;
     || record.ffloat.getBasicType()!=basicTypeFloat64)  // DO SOMTHING!!!!&lt;br /&gt;
     ...&lt;br /&gt;
     array.put(0,nelements,precord-&amp;gt;data);&lt;br /&gt;
&lt;br /&gt;
or more concisely&lt;br /&gt;
&lt;br /&gt;
     ExampleRecord record;&lt;br /&gt;
     ...&lt;br /&gt;
     DbfConvertPrimitive.put(precord.array,new double[] {1.0,2.0,3.0});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfMDArray ==&lt;br /&gt;
NOT YET DEFINED&lt;br /&gt;
     &lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; is described as:&lt;br /&gt;
     interface DbfMenu extends Dbf {&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
         void putIndex(int16 val);&lt;br /&gt;
         DbdMenu getDbdMenu();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; allows the menu index to be set and retrieved&lt;br /&gt;
and also provides access to the DbdMenu.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;DbfMenu&amp;lt;/tt&amp;gt; field can be accessed via the generated header file or via&lt;br /&gt;
the introspection methods.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfEnum ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfEnum&amp;lt;/tt&amp;gt; is described as:&lt;br /&gt;
     interface DbfEnum extends Dbf {&lt;br /&gt;
         int16 getIndex();&lt;br /&gt;
         void putIndex(int16 val);&lt;br /&gt;
         DbfStringArray getChoiceArray();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;DbfEnum&amp;lt;/tt&amp;gt; allows the enum index to be set and retrieved&lt;br /&gt;
and also provides access to the The DbfArray field that contains the choices.&lt;br /&gt;
&lt;br /&gt;
== DbfLink and DbfDevice ==&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;tt&amp;gt;DbfLink&amp;lt;/tt&amp;gt; is described as&lt;br /&gt;
 &lt;br /&gt;
     enum LinkDir {&lt;br /&gt;
         LinkDirNone,&lt;br /&gt;
         LinkDirProcess,&lt;br /&gt;
         LinkDirIn,&lt;br /&gt;
         LinkDirOut,&lt;br /&gt;
         LinkDirInOut&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbfLink extends Dbf {&lt;br /&gt;
         LinkDir getDir();&lt;br /&gt;
         DbdLink getDbdLink();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== DbfTimeStamp ==&lt;br /&gt;
&lt;br /&gt;
     struct TimeStamp {&lt;br /&gt;
         int64 secondsSinceEpoch;&lt;br /&gt;
         int32 nanoSeconds;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbfTimeStamp extends Dbf {&lt;br /&gt;
         void get(TimeStamp timeStamp);&lt;br /&gt;
         void put(TimeStamp timeStamp);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= DbdStatements =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
These describe everything defined in database definition files.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdMenu&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdMenu {&lt;br /&gt;
         int32 getNameLength(&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         int16 getNchoices();&lt;br /&gt;
         int32 getChoiceNameLength(int16 index);&lt;br /&gt;
         void getChoice(int16 index,String choice);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdLink&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdLink {&lt;br /&gt;
         LinkDir getDir();&lt;br /&gt;
         int32 getChoiceNameLength();&lt;br /&gt;
         void getChoiceName(String name);&lt;br /&gt;
         int32 getInterfaceNameLength();&lt;br /&gt;
         void getInterfaceName(String name);&lt;br /&gt;
         int32 getDataStructNameLength();&lt;br /&gt;
         void getDataStructName(String name);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
== &amp;lt;tt&amp;gt;DbdStruct&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;DbdRecord&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
     interface DbdAttribute {&lt;br /&gt;
         int32 getDefaultLength();&lt;br /&gt;
         void getDefault(String value);&lt;br /&gt;
         boolean isReadonly();&lt;br /&gt;
         boolean isDesign();&lt;br /&gt;
         boolean isSpecial();&lt;br /&gt;
         int16 getAsl();&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     interface DbdDefaults {}&lt;br /&gt;
    &lt;br /&gt;
     interface DbdArrayDefaults extends DbdDefaults{&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         int32 getLength();&lt;br /&gt;
&lt;br /&gt;
     interface DbdStructDefaults extends DbdDefaults{&lt;br /&gt;
         DbdStruct getDescription();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdField {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         DbfType getType();&lt;br /&gt;
         DbdDefaults getDefaults();&lt;br /&gt;
         DbdAttribute getAttributes();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdStruct {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         int16 getNumberFields();&lt;br /&gt;
         DbdField getFieldDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface DbdRecord {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         int16 getNumberFields();&lt;br /&gt;
         DbdField getFieldDescription(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Record Instance ==&lt;br /&gt;
&lt;br /&gt;
     interface DbInstance {&lt;br /&gt;
         int32 getNameLength();&lt;br /&gt;
         void getName(String name);&lt;br /&gt;
         DbdRecord getDescription();&lt;br /&gt;
         DbdRecord getRecordCommonDescription();&lt;br /&gt;
         DbfStruct getInstance();&lt;br /&gt;
         DbfStruct getRecordCommonInstance();&lt;br /&gt;
         Dbf getField(String fieldName);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;getNameLength&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get length of record name&lt;br /&gt;
; &amp;lt;tt&amp;gt;getName&lt;br /&gt;
: get the record name&lt;br /&gt;
; &amp;lt;tt&amp;gt;getDescription&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the description of the record specific portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getRecordCommonDescription&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get the description of RecordCommon&lt;br /&gt;
; &amp;lt;tt&amp;gt;getInstance&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get instance for the record specific portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getRecordCommonInstance&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get instance for for RecordCommon portion of the record&lt;br /&gt;
; &amp;lt;tt&amp;gt;getField&amp;lt;/tt&amp;gt;&lt;br /&gt;
: get field instance. Workd for both record specific or RecordCommon field&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Locate Interfaces =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Classes are available to find and traverse the various Dbd definitons&lt;br /&gt;
and record instances.&lt;br /&gt;
The implementation will be language specific. For Java they will be something&lt;br /&gt;
like the following:&lt;br /&gt;
&lt;br /&gt;
In addition the following is defined:&lt;br /&gt;
&lt;br /&gt;
     public class DbdLocate {&lt;br /&gt;
         public DbdMenu getMenu(String name);&lt;br /&gt;
         public DbdLink getLink(String name);&lt;br /&gt;
         public DbdStruct getStruct(String name);&lt;br /&gt;
         public DbdRecord getRecord(String name);&lt;br /&gt;
         public LinkedList&amp;lt;DbdMenu&amp;gt; menuList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdLink&amp;gt; linkList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdStruct&amp;gt; structList;&lt;br /&gt;
         public LinkedList&amp;lt;DbdRecord&amp;gt; recordList;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public class DbInstanceLocate {&lt;br /&gt;
         public DbInstance getRecord(String name);&lt;br /&gt;
         public Dbf getField(String name);&lt;br /&gt;
         public Dbf getField(String recordName, String fieldName);&lt;br /&gt;
         public LinkedList&amp;lt;DbInstance&amp;gt; instanceList;&lt;br /&gt;
         public LinkedList&amp;lt;DbInstance&amp;gt; instanceList(String recordTypeName);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; Are the above methods static or should there be something like&lt;br /&gt;
     public class FindLocator {&lt;br /&gt;
         public static DbdLocate findDbdLocate();&lt;br /&gt;
         public static DbInstance findDbInstance();&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
The following locates a specific menu.&lt;br /&gt;
&lt;br /&gt;
     DbdMenu menu = DbdLocate.get(&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
     if(menu!=null) printf(&amp;quot;found menu %s\n&amp;quot;,&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
The following locates a field of a record instance.&lt;br /&gt;
&lt;br /&gt;
     Dbf field = DbInstanceLocate.getField(&amp;quot;example.value&amp;quot;);&lt;br /&gt;
     if(addr!=null) printf(&amp;quot;found %s\n&amp;quot;,&amp;quot;example.value&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Record_Processing&amp;diff=562</id>
		<title>V4 Design: Record Processing</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Record_Processing&amp;diff=562"/>
		<updated>2005-09-27T20:07:47Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Record Processing September 27 2005 &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;UNRESOLVED ISSUES&amp;lt;/b&amp;gt;&lt;br /&gt;
* This document will undergo LOTS of evolution1&lt;br /&gt;
* Monitors&lt;br /&gt;
** How will monitor data be managed?&lt;br /&gt;
** Big problem is how will array data be managed?&lt;br /&gt;
&lt;br /&gt;
This document described semantics for V4 record processing that are&lt;br /&gt;
different than for V3.&lt;br /&gt;
This includes the following:&lt;br /&gt;
* Semantics for Database and Channel Access Links.&lt;br /&gt;
* Semantics for record processing&lt;br /&gt;
* Record Locking&lt;br /&gt;
* Posting database monitors&lt;br /&gt;
* Status and Alarm Severity&lt;br /&gt;
* Access to array and structure fields.&lt;br /&gt;
&lt;br /&gt;
This version is based on feedback from the EPICS core developer's&lt;br /&gt;
meeting at ANL/APS on July 11th through July 14th.&lt;br /&gt;
In addition discussions with Andrew Johnson and Eric Norum have &lt;br /&gt;
led to many of the ideas described below.&lt;br /&gt;
This wiki is a companion to the wiki &amp;quot;V4 Design: dbdInterfaces&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
V3 record processing semantics do not work well for data&lt;br /&gt;
acquisition applications. An example of data acquisition is:&lt;br /&gt;
*  Move sample to new position.&lt;br /&gt;
** Several motors may be involved&lt;br /&gt;
** While moving post monitors to show current position, etc.&lt;br /&gt;
* Sample data&lt;br /&gt;
* Wait until CA client has fetched the data before next move.&lt;br /&gt;
&lt;br /&gt;
SynAPPS provides the Scan, motor, etc records which help with&lt;br /&gt;
data processing applications. These records process as follows:&lt;br /&gt;
&lt;br /&gt;
* Record does not complete processing until all inputs, outputs, etc done. Not completing means that they do not call recGblFwdLink until all proccessing is complete. Note that recGblFwdLink is what causes the V3 ioc to complete record processing.&lt;br /&gt;
* While waiting for asynchronous events these records have PACT=0 but keep state that shows it is still active&lt;br /&gt;
* Can be scanned and issue monitors while internal state is active&lt;br /&gt;
&lt;br /&gt;
Leaving PACT 0 but not calling recGblFwdLink was not anticipated when the V3 record processing semantics were created.&lt;br /&gt;
For V4 a record can be processed while it is waiting&lt;br /&gt;
for asynchronous processing to complete.&lt;br /&gt;
&lt;br /&gt;
In V3, if an input link is asynchronous, Process Passive does not wait&lt;br /&gt;
for asynchronous processing to complete before fetching data.&lt;br /&gt;
This also complicated data acquisition applications.&lt;br /&gt;
&lt;br /&gt;
V4 record processing is designed to make data acquisition easier.&lt;br /&gt;
Both input and output links can wait for record processing.&lt;br /&gt;
This is done, however, without record support blocking.&lt;br /&gt;
If blocking makes it easier to implement record support,&lt;br /&gt;
then the support can spawn a separate thread that does block.&lt;br /&gt;
Record support can communicate with the separate thread to decide when&lt;br /&gt;
to complete record processing.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Goals for V4 Record Processing =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
V4 record processing has the following features.&lt;br /&gt;
Some of these features were partially available in V3 but not in a&lt;br /&gt;
consistant way.&lt;br /&gt;
&lt;br /&gt;
* All links to other records:&lt;br /&gt;
** Can request that the linked record be processed.&lt;br /&gt;
** Can wait until the linked record completes asynchronous processing.&lt;br /&gt;
* While record support is active a record can still be processed and post monitors.&lt;br /&gt;
* Database links are processed via queue requests rather than recursive calls to dbProcess&lt;br /&gt;
* Instead of lock sets, each record instance has a lock.&lt;br /&gt;
* Monitors are implemented by database access without help from record support&lt;br /&gt;
&lt;br /&gt;
== Link Semantics ==&lt;br /&gt;
&lt;br /&gt;
The link semanics are similar for database and channel access links (&lt;br /&gt;
input, output, and process).&lt;br /&gt;
All provide the ability to request processing and to wait until processing completes.&lt;br /&gt;
&lt;br /&gt;
== Processing Local Links ==&lt;br /&gt;
&lt;br /&gt;
A local link just means a link to a record in the same IOC.&lt;br /&gt;
In V3 records linked via database links are processed via recursive calls to&lt;br /&gt;
dbProcess. In V4 this will no longer be done.&lt;br /&gt;
Each thread that scans records,&lt;br /&gt;
e.g. the 1 second scan thread does the following&lt;br /&gt;
when a record requests processing of a local link:&lt;br /&gt;
&lt;br /&gt;
* If the linked record is active or already queued the request fails.&lt;br /&gt;
* If the linked record does not allow link requests to cause processing the request fails.&lt;br /&gt;
* If a queue request is allowed then the request is handled as follows:&lt;br /&gt;
** The requests are queued if FIFO order&lt;br /&gt;
** The queue is emptied immediately after the record containing the link returns to DbProcess&lt;br /&gt;
** If all linked records complete synchronously the record containing the link is reprocessed before the thread processes any other records.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Record Locking ==&lt;br /&gt;
&lt;br /&gt;
V3 implemented lock sets in order to prevent different threads&lt;br /&gt;
from simultaneously accessing linked records.&lt;br /&gt;
&lt;br /&gt;
Instead of lock sets V4:&lt;br /&gt;
* Implements a per record instance lock.&lt;br /&gt;
* Defines a rule that allows two records to be locked without deadlocks&lt;br /&gt;
&lt;br /&gt;
== Posting Monitors ==&lt;br /&gt;
&lt;br /&gt;
In V3 monitors are posted when code (record support, device support, database access, etc) calls db_post_event. In V4 database access will itself handle&lt;br /&gt;
the posting of monitors.&lt;br /&gt;
&lt;br /&gt;
Monitors are posted by DbProcess when&lt;br /&gt;
* record support returns processActive.&lt;br /&gt;
* at the end of record processing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Database Field Types ==&lt;br /&gt;
&lt;br /&gt;
V4 allows Channel and Database Access to the&lt;br /&gt;
following types of fields:&lt;br /&gt;
&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* one dimensional array of primitive or string or struct&lt;br /&gt;
* struct with fields of following types:&lt;br /&gt;
** primitive&lt;br /&gt;
** string&lt;br /&gt;
** struct&lt;br /&gt;
** array of primitive or string or struct&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Link Semantics =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* Link just means access to a record or field. The requester can be:&lt;br /&gt;
** A database link in a record&lt;br /&gt;
** A channel access link in a record&lt;br /&gt;
** A channel access client PV.&lt;br /&gt;
* Instead of &amp;quot;forward link&amp;quot; the name &amp;quot;process link&amp;quot; is used.&lt;br /&gt;
* wait does NOT mean to wait synchronously. It means to save state, return, and resume at the saved state when called again.&lt;br /&gt;
* block means to pause additional record processing until link completion. It doesd NOT mean to block synchronously. This determines if multiple links can be procesed in parallel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Links are processed as follows:&lt;br /&gt;
&lt;br /&gt;
* Process Link: Perform the following actions&lt;br /&gt;
** Request processing&lt;br /&gt;
** Optionally wait until linked record completes&lt;br /&gt;
** Optionally block until linked record completes&lt;br /&gt;
* Output Link: &lt;br /&gt;
** Put value&lt;br /&gt;
** Optionally request processing. &amp;lt;b&amp;gt;If record can not be processed should the value be changed?&amp;lt;/b&amp;gt;&lt;br /&gt;
** Optionally wait until completion&lt;br /&gt;
** Optionally block until completion&lt;br /&gt;
* Input Link: Two flavors are available&lt;br /&gt;
** Monitor Link&lt;br /&gt;
*** Implemented via a monitor request on linked field&lt;br /&gt;
*** Optionally process record containing the link when monitor value is returned.&lt;br /&gt;
** Input Link: Perform the following actions&lt;br /&gt;
*** Optionally request that record be processed.&lt;br /&gt;
*** Optionally wait for linked record to complete processing.&lt;br /&gt;
*** Optionally block until completion&lt;br /&gt;
*** Get value.&lt;br /&gt;
&lt;br /&gt;
The following rules apply when a process request is made:&lt;br /&gt;
* If record is already being processed the request fails.&lt;br /&gt;
* Record support can specify that links to particular fields not cause processing.&lt;br /&gt;
* A record can declare that it can not be processed via process links.&lt;br /&gt;
** This can be specified in the Database Definition or the record instance.&lt;br /&gt;
* If a process request is allowed, it will be done regardless of the scan mechanism, i.e. the record does not have to be passive.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Record Processing Semantics =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section describes the semantics implemented by DbProcess.&lt;br /&gt;
&lt;br /&gt;
Each record type has two sets of record support.&lt;br /&gt;
One is implemented by RecordCommonSupport, which provides support for the&lt;br /&gt;
fields in RecordCommon.&lt;br /&gt;
The other is the record support for the fields in the record type,&lt;br /&gt;
which will be called RecordSupport in this section.&lt;br /&gt;
When &amp;quot;record support&amp;quot; is mentioned it can apply to either RecordCommonSupport or&lt;br /&gt;
RecordSupport.&lt;br /&gt;
Each support implements method process.&lt;br /&gt;
&lt;br /&gt;
One of the arguments to process is processState which has the values:&lt;br /&gt;
* processCancel - Cancel any outstanding activity&lt;br /&gt;
* processStart - Start processing&lt;br /&gt;
* processContinue - Making additional call&lt;br /&gt;
&lt;br /&gt;
process returns ProcessReturn which is one of the following:&lt;br /&gt;
* processDone - Done and successful&lt;br /&gt;
* processQuit - Do not do any more processing&lt;br /&gt;
* processActive - Not done&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are three stages to processing a record:&lt;br /&gt;
* RecordCommonSupport perform initial processing, e.g. all input links are processed.&lt;br /&gt;
* RecordSupport performs its processing in collaboration with link support&lt;br /&gt;
* RecordCommonSupport performs final processing, e.g. ouput links and process links are processed.&lt;br /&gt;
&lt;br /&gt;
It is up to RecordCommonSupport to keep internal state so that it knows if&lt;br /&gt;
it is being called for initial or final processing.&lt;br /&gt;
&lt;br /&gt;
During each stage DbProcess can call process multiple times:&lt;br /&gt;
* At the beginning of each stage process is called with state processStart. process returns one of:&lt;br /&gt;
** processDone - DbProcess proceeds to the next stage of record processing:&lt;br /&gt;
*** RecordCommonSupport initial - DbProcess calls RecordSupport&lt;br /&gt;
*** RecordSupport - Calls RecordCommonSupport&lt;br /&gt;
*** RecordCommonSupport final - DbProcess performs final processing and sets record idle.&lt;br /&gt;
** processActive&lt;br /&gt;
*** RecordCommonSupport must call the callback passed to process to continue processing&lt;br /&gt;
*** RecordSupport can call the callback passed to process when it is done.  A call to DbProcess will also call process.&lt;br /&gt;
** processQuit&lt;br /&gt;
*** If RecordSupport returned this DbProcess calls RecordCommonSupport with state processCancel&lt;br /&gt;
*** Otherwise RecordSupport does its normal end of processing and sets the record idle.&lt;br /&gt;
&lt;br /&gt;
For RecordCommonSupport the above rules allow asynchronous links.&lt;br /&gt;
The standard RecordCommonSupport does the following:&lt;br /&gt;
* initial processing means to handle the disable fields&lt;br /&gt;
** A get request is made for the disable link&lt;br /&gt;
***  If it is synchronous RecordCommonSupport returns processAbort if the record is disable or processDone  otherwise.&lt;br /&gt;
*** If it is asynchronous, processContinue is returned and RecordCommonSupport arranges for DbProcessContinue to be called when the link completes.&lt;br /&gt;
* final processing means to handle the array of process links&lt;br /&gt;
** If all are synchronous RecordCommonSupport returns processDone&lt;br /&gt;
** If any are asynchronous, processContinue is returned and RecordCommonSupport arranges for DbProcessContinue to be called when the link completes.&lt;br /&gt;
&lt;br /&gt;
For RecordSupport the above rules allow:&lt;br /&gt;
* process can be called repeatedly. This will continue as long as it returns processActive&lt;br /&gt;
* Everytime process returns processActive DbProcess posts monitors.&lt;br /&gt;
* The record can be periodically scanned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links to Other Records ==&lt;br /&gt;
&lt;br /&gt;
Links can be processed in parallel, sequentially, or a&lt;br /&gt;
combination of these.&lt;br /&gt;
RecordCommonSupport handles the links in RecordCommon and RecordSupport&lt;br /&gt;
handles record specific links. Record support is responsible for&lt;br /&gt;
implementing sequential or parallel link processing.&lt;br /&gt;
LinkSupport performs the actual I/O. The LinkSupport methods&lt;br /&gt;
provide options specifying if the linked record should be processed and&lt;br /&gt;
provide a callback to call when link processing completes. It is up to&lt;br /&gt;
RecordCommonSupport or RecordSupport to call DbProcessContinue&lt;br /&gt;
when all links complete.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Mutual Exclusion =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
V3 implemented lock sets, i.e. when a record was being processed it and all records linked via database links were locked.&lt;br /&gt;
&lt;br /&gt;
Lock sets solved two Mutual Exclusion problems:&lt;br /&gt;
* V3 allowed dbProcess to be called recursively.&lt;br /&gt;
** process passive database links and forward links were implemented via recursive calls to DbProcess&lt;br /&gt;
** Lock sets prevented deadly embrace problems for circular links.&lt;br /&gt;
* No puts could be done to an record in a lock set while record processing is active.&lt;br /&gt;
** For synchronous records this guarantees that no fields are modified except by record processing itself.&lt;br /&gt;
** For asynchronous records this guarantee is not valid.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
V4 does not call DbProcess recursively. Instead a process request is queued.&lt;br /&gt;
The request fails if either of the following is true:&lt;br /&gt;
* The record is active.&lt;br /&gt;
* The record is already queued.&lt;br /&gt;
&lt;br /&gt;
Queuing requests to process rather than recursively calling DbProcess&lt;br /&gt;
does not necessarily cause unnecessary context switches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&lt;br /&gt;
Must design a way to queue process requests to the same thread&lt;br /&gt;
that issues the requests if the link is to a local record.&lt;br /&gt;
First thoughts is that this should be FIFO and queue emptied immediately&lt;br /&gt;
after the requesting record returns from process.&lt;br /&gt;
&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example if all linked records are passive and the same priority then&lt;br /&gt;
all processing can occur without any context switches.&lt;br /&gt;
* A request is made to a thread to call DbProcess.&lt;br /&gt;
** The request is put on a queue associated with the thread.&lt;br /&gt;
* Sometime later the request is dequeued and DbProcess is called.&lt;br /&gt;
** For each link, with a request to process request, the request is put on the queue for the same thread&lt;br /&gt;
** After all requests are queued DbProcess returns&lt;br /&gt;
* The thread takes each request off the queue and calls DbProcess for the associated linked record&lt;br /&gt;
** When all linked records finish processing a request is queued to call DbProcess for the original record&lt;br /&gt;
* The request for the original record is removed from the queue and it's DbProcess is again called.&lt;br /&gt;
** The record completes.&lt;br /&gt;
&amp;lt;b&amp;gt;Question&amp;lt;/b&amp;gt; What about periodically scanned records? Needs thought.&lt;br /&gt;
&lt;br /&gt;
This leaves the question of what should be done about mutual exclusion.&lt;br /&gt;
&lt;br /&gt;
For V4 there will be two locks associated with the IOC database:&lt;br /&gt;
1) a global lock, and 2) A per record instance lock.&lt;br /&gt;
&lt;br /&gt;
The global lock, which is implemented by DbAccess,  must be taken&lt;br /&gt;
whenever the structure of the database is modified. Examples are&lt;br /&gt;
1) adding new record types, 2) adding new record instances, and 3) modifying&lt;br /&gt;
database links. Global locks are not discussed further in this document.&lt;br /&gt;
&lt;br /&gt;
Each record instance has an associated lock maintained by dbAccess.&lt;br /&gt;
When DbProcess is called it takes the lock.&lt;br /&gt;
Before it returns it unlocks.&lt;br /&gt;
Thus recordCommon and record support do not need to lock or unlock.&lt;br /&gt;
&lt;br /&gt;
Other code that needs access to fields of a record instance must call&lt;br /&gt;
dbLock before accessing any fields and dbUnlock after all accesses are complete.&lt;br /&gt;
&lt;br /&gt;
This leaves the problem of how to access fields from two different record&lt;br /&gt;
instances simultaneously. For example code that implements database&lt;br /&gt;
access needs such access. Code that needs such access must call dbLockLink before accessing the linked record and dbUnlockLink after access.&lt;br /&gt;
&lt;br /&gt;
dbLockLink is implemented as follows:&lt;br /&gt;
* Each Record instances has a unique ordinal number&lt;br /&gt;
* Assume Record X has a link to record Y&lt;br /&gt;
* If the ordinal number of X is less than that of Y&lt;br /&gt;
** Just call dbLock for record Y&lt;br /&gt;
* If the ordinal numnber of X is greater than that of Y&lt;br /&gt;
** call dbUnlock for X&lt;br /&gt;
** call dbLock for Y&lt;br /&gt;
** call dbLock for X&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Posting Modifications =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The document &amp;quot;V4 Design: dbdIterfaces&amp;quot; provides a design that allows&lt;br /&gt;
database access to handle all posting on monitors without requiring&lt;br /&gt;
any help from the code that modifies database fields.&lt;br /&gt;
It can do this because fields can be modified only via an&lt;br /&gt;
interface implemented by database access.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fields are modified in one of two ways:&lt;br /&gt;
* Changes made while record is being processed. For these posting is handled by DbProcess.&lt;br /&gt;
* Changes by other code. For these posting is handled by dbLock/dbUnlock.&lt;br /&gt;
&lt;br /&gt;
Each field of a record instance has two associated &amp;quot;modified&amp;quot; bits.&lt;br /&gt;
One is for changes handled by DbProcess. The other is for changes made&lt;br /&gt;
by dbLock/dbUnlock.&lt;br /&gt;
&lt;br /&gt;
DbProcess posts monitors when:&lt;br /&gt;
* When record support returns processActive.&lt;br /&gt;
* When it finishes record processing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other code can only change fields between calls to dbLock/dbUnlock&lt;br /&gt;
* When dbLock is called all its modify bits are false.&lt;br /&gt;
* Each field modification causes the associated modify bit to be set true.&lt;br /&gt;
* When dbUnlock is called it&lt;br /&gt;
** posts all fields that have changed&lt;br /&gt;
** sets the associated modify bits false&lt;br /&gt;
&lt;br /&gt;
The following is the initial attempt to describe how monitors are implemented.&lt;br /&gt;
&lt;br /&gt;
The following definitions are used:&lt;br /&gt;
* monitor - A client has asked to be notified when a field value changes.&lt;br /&gt;
* post - Create storage, copy the current value of the field into the storage, and pass the storage to the monitor subsystem.&lt;br /&gt;
&lt;br /&gt;
Separate discussions is required for the following: 1) primitive fields,&lt;br /&gt;
2) string fields, 3) structured fields, and  4) array fields.&lt;br /&gt;
&lt;br /&gt;
The following are just some thoughts.&lt;br /&gt;
&lt;br /&gt;
* primitive fields - No problems.&lt;br /&gt;
* string fields - Memory is an issue.&lt;br /&gt;
** Should there be a way to postpone posting until the monitor is ready to retrieve the value?&lt;br /&gt;
** If so who decides?&lt;br /&gt;
* struct fields - Memory is again an issue.&lt;br /&gt;
** Structure with only primitive field or string should be posted immediately but what about array fields?&lt;br /&gt;
** Who decides?&lt;br /&gt;
** How?&lt;br /&gt;
* array fields - memory is an issue&lt;br /&gt;
** It should be possible to post small arrays of primitive type.&lt;br /&gt;
** Large arrays should not be posted until monitor system is ready to accept the data.&lt;br /&gt;
*** It should also be possible to just notify the client that the array changed but the client must issue a read request to retrieve the data.&lt;br /&gt;
&lt;br /&gt;
In any case the way monitors are posted must take into consideration&lt;br /&gt;
the views defined in the database definition for each record.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Alarm Processing =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The V4 semantics for status and severity have the following goals:&lt;br /&gt;
* alarmSeverity has the same values as for V3&lt;br /&gt;
* alarmStatus is a string&lt;br /&gt;
* a record starts processing with alarmSeverity = &amp;quot;NO_ALARM&amp;quot; and status empty.&lt;br /&gt;
* status will ONLY be posted if it has changed since the last time it was posted.&lt;br /&gt;
* alarmSeverity will ONLY be posted if it has changed since the last time it was posted&lt;br /&gt;
&lt;br /&gt;
The semantics, which are implemented by recordCommon, are:&lt;br /&gt;
&lt;br /&gt;
* When recordCommon is called with processStart&lt;br /&gt;
** A private variable newSeverity is set to NO_ALARM&lt;br /&gt;
** A private variable prevSeverity is set to alarmSeverity&lt;br /&gt;
* When recordCommon completes its part of record processing&lt;br /&gt;
** If newSeverity is NO_ALARM and prevSeverity has a different value&lt;br /&gt;
*** alarmSeverity is set to NO_ALARM&lt;br /&gt;
*** alarmStatus is set to empty&lt;br /&gt;
&lt;br /&gt;
* When the recordCommon.setSeverity(sevr,status) is called&lt;br /&gt;
** If sevr is less than or equal to newSeverity nothing is done&lt;br /&gt;
** else&lt;br /&gt;
*** alarmSeverity is set to sevr&lt;br /&gt;
*** alarmStatus is set to status&lt;br /&gt;
*** newSeverity is set to sevr&lt;br /&gt;
&lt;br /&gt;
NOTE: alarmStatus and alarmSeverity are written by the normal method.&lt;br /&gt;
This means that their values will be posted.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Channel Access/ Database Access field types =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This section discusses how IOC database fields are accessed by channel access&lt;br /&gt;
or via database links.&lt;br /&gt;
&lt;br /&gt;
For the initial V4 implementation only the following types of data&lt;br /&gt;
will be accessable.&lt;br /&gt;
&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* enum&lt;br /&gt;
* one dimensional array of primitive or string or struct&lt;br /&gt;
* struct with fields of following types:&lt;br /&gt;
** primitive&lt;br /&gt;
** string&lt;br /&gt;
** enum&lt;br /&gt;
** struct (use recursion for allowed types)&lt;br /&gt;
** one dimensional array of primitive or string or struct&lt;br /&gt;
&lt;br /&gt;
The dbdInterfaces document defines database field types.&lt;br /&gt;
It also defines a subset called basic types, which consists&lt;br /&gt;
of primitive types, string, array, and structure.&lt;br /&gt;
For external access only basic types can be accessed.&lt;br /&gt;
This means that structures and arrays that do not consist of basic types&lt;br /&gt;
are not accessable outside the record. For example a DbfLink is&lt;br /&gt;
not accessable via channel access as a DbfLink.&lt;br /&gt;
&lt;br /&gt;
Non basic fields will only be available via some combination of basic types.&lt;br /&gt;
&lt;br /&gt;
For example a DbfLink field will appear as a string.&lt;br /&gt;
If a Database Definition is&lt;br /&gt;
&lt;br /&gt;
     struct(calcInpLink) {&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(value,float64)&lt;br /&gt;
     };&lt;br /&gt;
     &lt;br /&gt;
     record(xxx) {&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(value,float64)&lt;br /&gt;
     ...&lt;br /&gt;
         field(inp,array(struct(calcInpLink)[]))&lt;br /&gt;
     ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
If a client attaches to &lt;br /&gt;
     record.field(link)&lt;br /&gt;
The data will be appear in the form:&lt;br /&gt;
     choiceName(pvname,...)&lt;br /&gt;
where &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; is the name of the link support and the arguments&lt;br /&gt;
are the values of the dataStruct associated with the support.&lt;br /&gt;
&lt;br /&gt;
Then if a client specifies the process variable:&lt;br /&gt;
     record.field(inp[1].link)&lt;br /&gt;
Then it connects to the link field of the second calcInpLink of field inp.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== primitive types ==&lt;br /&gt;
&lt;br /&gt;
This includes DbfBool, DbfOctet, DbfInt16, ... , DbfFloat64.&lt;br /&gt;
These do not present any problems. The scalar value is transfered.&lt;br /&gt;
&lt;br /&gt;
== string ==&lt;br /&gt;
&lt;br /&gt;
A string is just a UTF_8 encoded character string&lt;br /&gt;
&lt;br /&gt;
== DbfMenu  and DbfEnum ==&lt;br /&gt;
&lt;br /&gt;
Handled as an enum&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DbfLink ==&lt;br /&gt;
&lt;br /&gt;
Both of these have the following:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt; A string that selects the link  support.&lt;br /&gt;
* &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt; Each support has an associated struct for configuration.&lt;br /&gt;
&lt;br /&gt;
How should these be made available? Perhaps:&lt;br /&gt;
&lt;br /&gt;
The field appears as a string with the following syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;choiceName(structAssignmentList)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where structAssignmentList has the same syntax as defined in &amp;quot;V4 DB Record Instance Syntax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== timeStamp ==&lt;br /&gt;
&lt;br /&gt;
This is just transfered like a struct with two fields:&lt;br /&gt;
* int64 secondsSinceEpoch&lt;br /&gt;
* int32 nanoSeconds&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== struct ==&lt;br /&gt;
&lt;br /&gt;
The database definition syntax allows a struct to be composed of fields&lt;br /&gt;
of any DbfType.&lt;br /&gt;
Database access, however, will only allow access to structs with fields&lt;br /&gt;
of the following types:&lt;br /&gt;
* primitive - DbfBool,...,DbfFloat64&lt;br /&gt;
* DbfString&lt;br /&gt;
* DbfArray of primitive type or string&lt;br /&gt;
* DbfStruct - As long as its fields are valid types&lt;br /&gt;
&lt;br /&gt;
The individual fields can be accessed directly so this discussion&lt;br /&gt;
only involves access to the entire structure.&lt;br /&gt;
&lt;br /&gt;
Access will only be available to clients that have knowledge of&lt;br /&gt;
fields within the structure. For channel access clients this means that&lt;br /&gt;
they provide a propertyCatalog that has some subset of the fields in the structure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== array ==&lt;br /&gt;
&lt;br /&gt;
Arrays of the following types are accessable:&lt;br /&gt;
* primitive - DbfBool,...,DbfFloat64&lt;br /&gt;
* DbfString&lt;br /&gt;
* DbfStruct - As long as its fields are valid types&lt;br /&gt;
&lt;br /&gt;
Note that arrays of structs are not accessable in the early V4 releases.&lt;br /&gt;
&lt;br /&gt;
Arrays still need lots more discussion!!!&lt;br /&gt;
The database definition syntax allow an array to be any of the basic types, i.e. DbfBool,...,DbfFloat64, DbfString, DbfArray, DbfStruct.&lt;br /&gt;
&lt;br /&gt;
For the initial V4 version, database access only allows access to arrays of the following types.&lt;br /&gt;
* primitive - DbfBool,...,DbfFloat64&lt;br /&gt;
* DbfString&lt;br /&gt;
* ???? What else&lt;br /&gt;
&lt;br /&gt;
An individual element of an array of type DbfStruct can be accessed&lt;br /&gt;
directly if it satisfies the criteria for accessing a DbfStruct.&lt;br /&gt;
&lt;br /&gt;
Question: Should database Access be implemented so that record/link support can transfer an array in segments. Examples:&lt;br /&gt;
* If the array is a circular buffer, it is presented in two segements&lt;br /&gt;
* If the array is stored in hardware, e.g. a transient recorder, the array can be read from the hardware and passed to the client in segments.&lt;br /&gt;
&lt;br /&gt;
If an array is available only in segments then can we&lt;br /&gt;
prevent two clients from trying to access the same array simultaneously?&lt;br /&gt;
&lt;br /&gt;
Perhaps this is a problem that must be solved by an application:&lt;br /&gt;
* runControl records are one solution&lt;br /&gt;
* Other solutions can be envisioned&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MDArray ==&lt;br /&gt;
&lt;br /&gt;
Not implemented if the early V4 releases.&lt;br /&gt;
&lt;br /&gt;
== Associated Data ==&lt;br /&gt;
&lt;br /&gt;
The typical example is a client that asks for timeStamp, severity, status,&lt;br /&gt;
and data.&lt;br /&gt;
These are handled automatically as described in &amp;quot;Posting Modifications&amp;quot;&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=543</id>
		<title>V4 DB RecordCommon</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=543"/>
		<updated>2005-09-27T20:05:18Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Standard Support September 27 2005 &lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
For V4 dbCommon.dbd and RecordCommon.dbd replace the V3 dbCommon.dbd.&lt;br /&gt;
dbCommon.dbd defines widely used definitions and RecordCommon.dbd defines&lt;br /&gt;
the fields that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This document requires that the reader be familiar with:&lt;br /&gt;
# V3 iocCore&lt;br /&gt;
# V4 DBD Statement Syntax&lt;br /&gt;
# V4 DB Record Instance Syntax&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= dbCommon =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Support ==&lt;br /&gt;
&lt;br /&gt;
=== Data Structures ===&lt;br /&gt;
     struct(MonitorLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,boolean) &lt;br /&gt;
     }&lt;br /&gt;
     struct(InputLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(OutputLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,boolean)&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
         field(inheritSeverity,boolean)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ProcessLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(wait,boolean)&lt;br /&gt;
         field(block,boolean)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link support definitions ===&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* input&lt;br /&gt;
** monitor support&lt;br /&gt;
** input support&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For input and output The following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
     link(in,&amp;quot;monitorLinkOctet&amp;quot;,&amp;quot;monitorLinkOctet&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkBoolean&amp;quot;,&amp;quot;monitorLinkBoolean&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkInt16&amp;quot;,&amp;quot;monitorLinkInt16&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkInt32&amp;quot;,&amp;quot;monitorLinkInt32&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkInt64&amp;quot;,&amp;quot;monitorLinkInt64&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkFloat32&amp;quot;,&amp;quot;monitorLinkFloat32&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkFloat64&amp;quot;,&amp;quot;monitorLinkFloat64&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkString&amp;quot;,&amp;quot;monitorLinkString&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkOctet&amp;quot;,&amp;quot;inputLinkOctet&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkBoolean&amp;quot;,&amp;quot;inputLinkBoolean&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkInt16&amp;quot;,&amp;quot;inputLinkInt16&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkInt32&amp;quot;,&amp;quot;inputLinkInt32&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkInt64&amp;quot;,&amp;quot;inputLinkInt64&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkFloat32&amp;quot;,&amp;quot;inputLinkFloat32&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkFloat64&amp;quot;,&amp;quot;inputLinkFloat64&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkString&amp;quot;,&amp;quot;inputLinkString&amp;quot;,InputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkOctet&amp;quot;,&amp;quot;outputLinkOctet&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkBoolean&amp;quot;,&amp;quot;outputLinkBoolean&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkInt16&amp;quot;,&amp;quot;outputLinkInt16&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkInt32&amp;quot;,&amp;quot;outputLinkInt32&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkInt64&amp;quot;,&amp;quot;outputLinkInt64&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkFloat32&amp;quot;,&amp;quot;outputLinkFloat32&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkFloat64&amp;quot;,&amp;quot;outputLinkFloat64&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkString&amp;quot;,&amp;quot;outputLinkString&amp;quot;,OutputLinkData);&lt;br /&gt;
&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayOctet&amp;quot;,&amp;quot;monitorLinkArrayOctet&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayBoolean&amp;quot;,&amp;quot;monitorLinkArrayBoolean&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayInt16&amp;quot;,&amp;quot;monitorLinkArrayInt16&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayInt32&amp;quot;,&amp;quot;monitorLinkArrayInt32&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayInt64&amp;quot;,&amp;quot;monitorLinkArrayInt64&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayFloat32&amp;quot;,&amp;quot;monitorLinkArrayFloat32&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayFloat64&amp;quot;,&amp;quot;monitorLinkArrayFloat64&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayString&amp;quot;,&amp;quot;monitorLinkArrayString&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayOctet&amp;quot;,&amp;quot;inputLinkArrayOctet&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayBoolean&amp;quot;,&amp;quot;inputLinkArrayBoolean&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayInt16&amp;quot;,&amp;quot;inputLinkArrayInt16&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayInt32&amp;quot;,&amp;quot;inputLinkArrayInt32&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayInt64&amp;quot;,&amp;quot;inputLinkArrayInt64&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayFloat32&amp;quot;,&amp;quot;inputLinkArrayFloat32&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayFloat64&amp;quot;,&amp;quot;inputLinkArrayFloat64&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayString&amp;quot;,&amp;quot;inputLinkArrayString&amp;quot;,InputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayOctet&amp;quot;,&amp;quot;outputLinkArrayOctetData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayBoolean&amp;quot;,&amp;quot;outputLinkArrayBooleanData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayInt16&amp;quot;,&amp;quot;outputLinkArrayInt16&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayInt32&amp;quot;,&amp;quot;outputLinkArrayInt32&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayInt64&amp;quot;,&amp;quot;outputLinkArrayInt64&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayFloat32&amp;quot;,&amp;quot;outputLinkArrayFloat32&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayFloat64&amp;quot;,&amp;quot;outputLinkArrayFloat64&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayString&amp;quot;,&amp;quot;outputLinkArrayString&amp;quot;,OutputLinkData);&lt;br /&gt;
&lt;br /&gt;
     link(process,&amp;quot;processLink&amp;quot;,ProcessLink,ProcessLinkData);&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
&lt;br /&gt;
     struct(AsynDevice) }&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
=== link definitions ===&lt;br /&gt;
&lt;br /&gt;
     link(in,&amp;quot;asynInt32&amp;quot;,&amp;quot;inputLinkInt32&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynInt32Average&amp;quot;,&amp;quot;inputLinkInt32&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynInt32Monitor&amp;quot;,&amp;quot;monitorLinkInt32&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynFloat64&amp;quot;,&amp;quot;inputLinkFloat64&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynFloat64Average&amp;quot;,&amp;quot;inputLinkFloat64&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynFloat64Monitor&amp;quot;,&amp;quot;monitorLinkFloat64&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynInt32&amp;quot;,&amp;quot;outputLinkInt32&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynFloat64&amp;quot;,&amp;quot;outputLinkFloat64&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynDigital&amp;quot;,&amp;quot;asynDigital&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynDigitalMonitor&amp;quot;,&amp;quot;asynDigitalMonitor&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynDigital&amp;quot;,&amp;quot;asynDigital&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynInt32Array&amp;quot;,&amp;quot;inputLinkArrayInt32&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynInt32Array&amp;quot;,&amp;quot;outputLinkArrayInt32&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynFloat64Array&amp;quot;,&amp;quot;inputLinkArrayFloat64&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynFloat64Array&amp;quot;,&amp;quot;outputLinkArrayFloat64&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynOctetArray&amp;quot;,&amp;quot;asynOctetArray&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynOctetArray&amp;quot;,&amp;quot;asynOctetArray&amp;quot;,AsynDevice)&lt;br /&gt;
== Other common definitions ==&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;Raw&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     # usefull struct definitions&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(full,float64) &lt;br /&gt;
         field(egul,float64)&lt;br /&gt;
         field(slope,float64) &lt;br /&gt;
         field(intercept,float64) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ControlLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
     }&lt;br /&gt;
     struct(AlarmLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(lowSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(lowWarning,float64) &lt;br /&gt;
         field(lowWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(highWarning,float64) &lt;br /&gt;
         field(highWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
         field(highSevr,menu(menuAlarmSevr)) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= RecordCommon =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Menu Definitions ==&lt;br /&gt;
&lt;br /&gt;
     # menu definitions for RecordCommon fields&lt;br /&gt;
     menu(menuPriority) {&lt;br /&gt;
         choice(menuPriorityLow, &amp;quot;Low&amp;quot;)&lt;br /&gt;
         choice(menuPriorityMedium, &amp;quot;Medium&amp;quot;)&lt;br /&gt;
         choice(menuPriorityHigh, &amp;quot;High&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuScan) {&lt;br /&gt;
         choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
         choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
         choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
         choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
         choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuAlarmSevr) {&lt;br /&gt;
         choice(menuAlarmSevrNone, &amp;quot;None&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMinor, &amp;quot;Minor&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMajor, &amp;quot;Major&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrInvalid, &amp;quot;Invalid&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
== struct definitions for RecordSupport ==&lt;br /&gt;
     struct(TimeStamp) {&lt;br /&gt;
         field(secondsPastEpoch,int64)&lt;br /&gt;
         field(nanoSeconds,int32)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Scan {&lt;br /&gt;
         field(scan,menu(menuScan)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(phase,int16)&lt;br /&gt;
         field(priority,menu(menuPriority)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;b&amp;gt;Event NEEDS NEW DEFINITIONS&amp;lt;/b&amp;gt;&lt;br /&gt;
     struct Event {&lt;br /&gt;
         field(eventNumber,int16) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(timeStampEvent,int16)&lt;br /&gt;
         field(timeStampLink,link(in))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Disable {&lt;br /&gt;
         field(disableValue,int16) {&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(disableInput,int16)&lt;br /&gt;
         field(disableLink,link(in))&lt;br /&gt;
         field(disableAlarmSeverity,menu(menuAlarmSevr))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== RecordCommon Record Definition ==&lt;br /&gt;
&lt;br /&gt;
     record(RecordCommon) {&lt;br /&gt;
         field(description,string)&lt;br /&gt;
         field(scan,struct(Scan))&lt;br /&gt;
         field(event,struct(Event))&lt;br /&gt;
         field(accessSecurityGroup,string)&lt;br /&gt;
         field(pini,boolean)&lt;br /&gt;
         field(disablePutField,boolean)&lt;br /&gt;
         field(alarmAckSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmAckTransient,boolean) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;YES&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(udf,boolean) {&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(time,struct(TimeStamp)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(disable,struct(Disable)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmStatus,string) {&lt;br /&gt;
             default(&amp;quot;UDF&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;Invalid&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(processLink,array(link[])) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Although it has many fewer fields,&lt;br /&gt;
RecordCommon.dbd is a complete replacement for the V3 dbCommon.&lt;br /&gt;
The following V3 fields are no longer needed:&lt;br /&gt;
* private fields - Private fields will truly be privaye to the implementation&lt;br /&gt;
* previous value fields - All puts to database fields will be posted. The layer above will decide if clients should be notified of changes.&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=542</id>
		<title>V4 DBD Statement Syntax</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=542"/>
		<updated>2005-09-27T20:02:43Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DBD Statement Syntax Sept 27 2005&lt;br /&gt;
= Overview =&lt;br /&gt;
This document presents the syntax for V4 database definition files.&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= General Statements =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== include ==&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;filename&amp;quot;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;filename&amp;lt;/tt&amp;gt;&lt;br /&gt;
: must be a valid filename&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Include statements can be used at the top level, or inside the braces of a &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definition.&lt;br /&gt;
&lt;br /&gt;
== # comment ==&lt;br /&gt;
&lt;br /&gt;
 # anything&lt;br /&gt;
&lt;br /&gt;
Anything on a line after a &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; 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 &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; character has no special meaning.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== menu ==&lt;br /&gt;
&lt;br /&gt;
A menu is an enumerated type where the choice strings are defined once for each IOC.  Menus are defined like this:&lt;br /&gt;
&lt;br /&gt;
 menu(menuName) {&lt;br /&gt;
     choice(choiceName, &amp;quot;choiceValue&amp;quot;)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can be any UTF-8 compatible string, which should be unique within the context of this menu.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 menu(menuScan) {&lt;br /&gt;
     choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
     choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
     choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
     choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
     choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Structures, Record types, Fields and Views =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== struct ==&lt;br /&gt;
&lt;br /&gt;
A structure is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 struct(name) {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The structure name must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular structure.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
&lt;br /&gt;
== record ==&lt;br /&gt;
&lt;br /&gt;
A record type is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 record(name) extends RecordCommon {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     view(viewName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The record type name. It must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;extends RecordCommon&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This states that the record type extends the set of fields defined in &amp;quot;V4 DB RecordCommon&amp;quot;. 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 &amp;lt;tt&amp;gt;extends&amp;lt;/tt&amp;gt; phrase.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular record type and its parents (extends ...).&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#Views of a record|Views of a record]] below.&lt;br /&gt;
&lt;br /&gt;
== fieldType ==&lt;br /&gt;
&lt;br /&gt;
Both &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; define a field as:&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The syntax for &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Basic types: octet, boolean, numerics, and string ===&lt;br /&gt;
&lt;br /&gt;
The following field types have no arguments:&lt;br /&gt;
&amp;lt;tt&amp;gt;octet&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int32&amp;lt;/tt&amp;gt;,  &amp;lt;tt&amp;gt;int64&amp;lt;/tt&amp;gt;,&lt;br /&gt;
&amp;lt;tt&amp;gt;float32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;float64&amp;lt;/tt&amp;gt;,  and &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Examples: &lt;br /&gt;
     field(description,string)&lt;br /&gt;
     field(value,float64)&lt;br /&gt;
&lt;br /&gt;
=== enum ===&lt;br /&gt;
&lt;br /&gt;
An &amp;lt;tt&amp;gt;enum&amp;lt;/tt&amp;gt; field takes one argument after the type name:&lt;br /&gt;
&lt;br /&gt;
     enum(fieldName)&lt;br /&gt;
&lt;br /&gt;
where fieldName is the name of another field in the same record that must be of type &amp;lt;tt&amp;gt;array(string[])&amp;lt;/tt&amp;gt;.  The values in this other field at runtime define the available choice strings for the enum field.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
     field(choices, array(string[])&lt;br /&gt;
     field(value, enum(choices))&lt;br /&gt;
&lt;br /&gt;
=== menu ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt; field is defined like this:&lt;br /&gt;
     menu(menuName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt; is the name of the menu.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     field(scan, menu(menuScan))&lt;br /&gt;
&lt;br /&gt;
=== struct ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; field is declared using the type name&lt;br /&gt;
     struct(structName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;structName&amp;lt;/tt&amp;gt; is the name of a struct which must have been previously defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
      struct(Point) {&lt;br /&gt;
          field(x,float64)&lt;br /&gt;
          field(y,float64)&lt;br /&gt;
          field(z,float64)&lt;br /&gt;
       }&lt;br /&gt;
       ...&lt;br /&gt;
       record(haspoint) extends RecordCommon {&lt;br /&gt;
           ...&lt;br /&gt;
           field(point, struct(point))&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
=== array ===&lt;br /&gt;
&lt;br /&gt;
An array field uses definitions like these:&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 3-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[,,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 2-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;arrayType&amp;lt;/tt&amp;gt; may be any fieldType except &amp;lt;tt&amp;gt;array&amp;lt;/tt&amp;gt;, 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]]&lt;br /&gt;
* &amp;lt;tt&amp;gt;capacity&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(VAL1D,array(float64[]))  #1d array with arbitrary capacity&lt;br /&gt;
     field(VAL2D,array(float64[,])) #2d array with arbitrary capacities&lt;br /&gt;
     field(anyTypeAnyD,array())     #arbitrary type,number of dimensions, and capacities&lt;br /&gt;
&lt;br /&gt;
=== link ===&lt;br /&gt;
&lt;br /&gt;
This field type can get or put data from/to some source outside of the record.&lt;br /&gt;
Link fields replace the DBF_INLINK, DBF_OUTLINK, and DTYP fields from EPICS V3.&lt;br /&gt;
&lt;br /&gt;
A link field's choices come from link definitions - see the [[#link]] section below for more details.&lt;br /&gt;
A link can be a link to another database record, to hardware device support,&lt;br /&gt;
or something else.&lt;br /&gt;
&lt;br /&gt;
The syntax is:&lt;br /&gt;
&lt;br /&gt;
     link(linkDirection,array(string[])= {name,...})&lt;br /&gt;
&lt;br /&gt;
where &lt;br /&gt;
* &amp;lt;tt&amp;gt;linkDirection&amp;lt;/tt&amp;gt; : &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. The direction &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt; means there is no direction associated with this interface.  For &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt; the direction is determined by the particular &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; that the record instance selects.&lt;br /&gt;
* &amp;lt;tt&amp;gt;array(string[])&amp;lt;/tt&amp;gt; : Each string is the name of Link Interface implemented by link support and used by record support.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(disableLink,&lt;br /&gt;
        link(in,array(string[4]) = {&lt;br /&gt;
           &amp;quot;monitorLinkInt32&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkInt32&amp;quot;,&lt;br /&gt;
           &amp;quot;monitorLinkFloat64&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkFloat64&amp;quot;&lt;br /&gt;
        } ))&lt;br /&gt;
     )&lt;br /&gt;
     field(process, link(process,array(string[1])= {processLink}))&lt;br /&gt;
     field(inp,&lt;br /&gt;
        link(in, array(string[3]) = {&lt;br /&gt;
           &amp;quot;monitorLinkInt32&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkInt32&amp;quot;,&lt;br /&gt;
            &amp;quot;digitalIO&amp;quot;&lt;br /&gt;
         }))&lt;br /&gt;
     )&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Andrew: Do we want the above syntax? Another possibility is just:&lt;br /&gt;
    link(linkDirection,interface(string,...))&lt;br /&gt;
&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== fieldAttribute ==&lt;br /&gt;
&lt;br /&gt;
Each field definition has several associated attributes, the values of which are set like this:&lt;br /&gt;
&lt;br /&gt;
     default(&amp;quot;fieldValue&amp;quot;)&lt;br /&gt;
     readonly(yesNo)&lt;br /&gt;
     design(yesNo)&lt;br /&gt;
     special(yesNo)&lt;br /&gt;
     asl(securityLevel)&lt;br /&gt;
     link(yesNo)&lt;br /&gt;
&lt;br /&gt;
'''Marty thinks we should get rid of these two:'''&lt;br /&gt;
     prompt(&amp;quot;promptString&amp;quot;)&lt;br /&gt;
     group(&amp;quot;promptGroup&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
'''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.'''&lt;br /&gt;
&lt;br /&gt;
The attribute parameter values have the following meanings:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;default(&amp;quot;fieldValue&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;readonly(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can this field be modified via channel access or database links?  Takes the value No if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;design(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;special(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;asl(securityLevel)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Channel Access security level for this field, 0 or 1.  Takes the value 1 if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
''These attributes may disappear, see comment above:''&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;prompt(&amp;quot;promptString&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;group(&amp;quot;promptGroup&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
== view ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;field&amp;quot; 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).&lt;br /&gt;
&lt;br /&gt;
A simple view looks like this:&lt;br /&gt;
&lt;br /&gt;
 view(viewName) {&lt;br /&gt;
     property(propName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     property(propName, fieldPath)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The view name must be a valid C identifier, which must be unique in the context of the particular record type.&lt;br /&gt;
; &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: A Data Access property name, which must be a valid C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The path to a field in this record type. To use a field inside a structure field, give the full path to that field: &amp;lt;tt&amp;gt;controlLimit.upper&amp;lt;/tt&amp;gt; for example.&lt;br /&gt;
: If &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; resolves to a structure, a property catalog containing the whole structure will be sent, with property names matching the structure's field names.&lt;br /&gt;
: The &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; may be omitted as long as there is a subordinate property catalog below this property.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 record(ao) extends RecordCommon {&lt;br /&gt;
     field(value, float64) { ... }&lt;br /&gt;
     field(outValue, float64) { ... }&lt;br /&gt;
     field(rawValue, int32) { ... }&lt;br /&gt;
     field(units, string) { ... }&lt;br /&gt;
     field(displayLimit, struct(displayLimit)) { ... }&lt;br /&gt;
     ...&lt;br /&gt;
     view(value)&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(outValue)&lt;br /&gt;
         property(value, outValue) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(rawValue)&lt;br /&gt;
         property(value, rawValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= link =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; statement describes an implementation of support for a link&lt;br /&gt;
field. the support can be any of the following:&lt;br /&gt;
* A link to another record either local or remote&lt;br /&gt;
* A link to hardware support&lt;br /&gt;
* Something else.&lt;br /&gt;
&lt;br /&gt;
The syntax for these is:&lt;br /&gt;
&lt;br /&gt;
 link(dir, choiceName, interfaceName, dataStructName)&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dir&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be one of &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. Compatible checks are made to match the interface with a field.&lt;br /&gt;
: '''Q: What are the rules?'''&lt;br /&gt;
:: ''It certainly doesn't seem to make sense to have a none or inout link for instance.''&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of an interface via which record support communicates with device support.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; that the interface understands. This interface can contain data and configuration information. The &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; must be defined before record instances can be created that assign values to it.&lt;br /&gt;
:: ''Need to rewrite this paragraph to clarify.''&lt;br /&gt;
&lt;br /&gt;
When a record instance is created the choiceName selects the support&lt;br /&gt;
to attach to a record link. The interfaceName must be one of the&lt;br /&gt;
interface names the record has listed as a valid type and dir must be compatible&lt;br /&gt;
with the dir the record type specified.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     link(in,&amp;quot;monitorLinkInt16&amp;quot;,&amp;quot;monitorLinkInt16&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkInt16&amp;quot;,&amp;quot;inputLinkInt16&amp;quot;,InputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkFloat64&amp;quot;,&amp;quot;outputLinkFloat64&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(process,&amp;quot;processLink&amp;quot;,ProcessLink,ProcessLinkData);&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Examples&amp;diff=544</id>
		<title>V4 DBD Examples</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Examples&amp;diff=544"/>
		<updated>2005-09-27T15:23:02Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Example Record Types Sept 27 2005&lt;br /&gt;
= Overview =&lt;br /&gt;
This document present proposed V4 replacements for a few of the&lt;br /&gt;
V3 record types.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= aoRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
aoRecord.dbd might be defined as follows:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 record(AoRecord) extends RecordCommon {&lt;br /&gt;
     field(value, float64) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(outValue, float64) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(out,&lt;br /&gt;
        link(out,array(string[3]) = {&lt;br /&gt;
            &amp;quot;outputLinkInt64&amp;quot;,&lt;br /&gt;
            &amp;quot;outputLinkFloat64&amp;quot;,&lt;br /&gt;
            &amp;quot;asynInt32&amp;quot;,&lt;br /&gt;
            &amp;quot;asynFloat64&amp;quot;&lt;br /&gt;
         } ))&lt;br /&gt;
     )&lt;br /&gt;
     field(outputRateOfChange, float64)&lt;br /&gt;
     field(desiredOutputLink,&lt;br /&gt;
        link(in,array(string[2]) = {&lt;br /&gt;
           &amp;quot;monitorLinkFloat64&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkFloat64&amp;quot;&lt;br /&gt;
        } ))&lt;br /&gt;
     )&lt;br /&gt;
     field(closedLoop, bool)&lt;br /&gt;
     field(outputIncremental, bool)&lt;br /&gt;
     field(convert, menu(menuConvert)) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(linearConvert, struct(LinearConvert)) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(units, string)&lt;br /&gt;
     field(displayLimit, struct(DisplayLimit))&lt;br /&gt;
     field(controlLimit, struct(ControlLimit))&lt;br /&gt;
     field(alarmLimit, struct(AlarmLimit))&lt;br /&gt;
     field(alarmDeadband, float64)&lt;br /&gt;
     field(rawValue, int64) {&lt;br /&gt;
         design(no)&lt;br /&gt;
     }&lt;br /&gt;
     field(prevRawValue, int64) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(readBackValue, int64) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(init, bool) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(simOutputLink,&lt;br /&gt;
        link(out,array(string[2]) = {&lt;br /&gt;
            &amp;quot;outputLinkInt64&amp;quot;,&lt;br /&gt;
            &amp;quot;outputLinkFloat64&amp;quot;,&lt;br /&gt;
         } ))&lt;br /&gt;
     )&lt;br /&gt;
&lt;br /&gt;
     field(simModeLink,&lt;br /&gt;
        link(in,array(string[2]) = {&lt;br /&gt;
           &amp;quot;monitorLinkString&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkString&amp;quot;&lt;br /&gt;
        } ))&lt;br /&gt;
     )&lt;br /&gt;
     field(simMode, bool) &lt;br /&gt;
     field(simSevr, menu(menuAlarmSevr))&lt;br /&gt;
     field(invalidAction, menu(menuIvoa))&lt;br /&gt;
     field(invalidValue, float64)&lt;br /&gt;
     field(outValueModified, bool) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     view(value) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
             property(controlLimit, controlLimit)&lt;br /&gt;
             property(alarmLimit, alarmLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(output) {&lt;br /&gt;
         property(value, outValue) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(raw) {&lt;br /&gt;
         property(value, rawValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(readback) {&lt;br /&gt;
         property(value, readBackValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 } &lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= calcRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
calcRecord.dbd defines the following:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 struct(CalcInpLink) {&lt;br /&gt;
     field(link,link(in))&lt;br /&gt;
        link(in,array(string[2]) = {&lt;br /&gt;
           &amp;quot;monitorLinkFloat64&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkFloat64&amp;quot;&lt;br /&gt;
        } ))&lt;br /&gt;
     )&lt;br /&gt;
     field(value,float64)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 record(CalcRecord) extends RecordCommon {&lt;br /&gt;
     field(result,float64) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(calc,string) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(input,array(struct(CalcInpLink)[])) &lt;br /&gt;
     field(units,string)&lt;br /&gt;
     field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     field(alarmLimit,struct(AlarmLimit))&lt;br /&gt;
     field(alarmDeadband,float64)&lt;br /&gt;
     field(lastValueAlarmed,float64) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(rpcl,private(&amp;quot;char *&amp;quot;))&lt;br /&gt;
     view(result) {&lt;br /&gt;
         property(value, result) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
             property(alarmLimit, alarmLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(expression) {&lt;br /&gt;
         property(value, calc)&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= mbbiRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
mbbiRecord.dbd could be:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 struct(MbbiState) {&lt;br /&gt;
     field(name, string)&lt;br /&gt;
     field(value, array(octet[]))&lt;br /&gt;
     field(severity, menu(menuAlarmSevr))&lt;br /&gt;
 }&lt;br /&gt;
 record(MbbiRecord) extends RecordCommon {&lt;br /&gt;
     field(state, array(struct(MbbiState)[])) {&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
#NOTE: stateName needed because enum must refer to array of string&lt;br /&gt;
     field(stateName,array(string[])) {&lt;br /&gt;
         design(no) readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(value, enum(stateName)) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
     }&lt;br /&gt;
     field(unknownStateSeverity, menu(menuAlarmSevr))&lt;br /&gt;
     field(changeStateSeverity, menu(menuAlarmSevr))&lt;br /&gt;
     field(inp, &lt;br /&gt;
        link(in,array(string[3]) = {&lt;br /&gt;
            &amp;quot;inputLinkOctet&amp;quot;,&lt;br /&gt;
            &amp;quot;asynDigital&amp;quot;,&lt;br /&gt;
         } ))&lt;br /&gt;
     )&lt;br /&gt;
     field(rawValue, array(octet[])) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(hardwareShift, int16) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(hardwareMask, array(octet[]) {&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     view(choice) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(raw) {&lt;br /&gt;
         property(value, raw) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= waveformRecord =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
waveformRecord.dbd defines the following:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 record(WaveformRecord) extends RecordCommon {&lt;br /&gt;
     field(value, array([])) {&lt;br /&gt;
         asl(0)&lt;br /&gt;
         special(yes)&lt;br /&gt;
     }&lt;br /&gt;
     field(reArm,bool)&lt;br /&gt;
     field(io,&lt;br /&gt;
         link(inout,array(string[4]) = {&lt;br /&gt;
           &amp;quot;monitorLinkArrayOctet&amp;quot;,&lt;br /&gt;
           &amp;quot;monitorLinkArrayBoolean&amp;quot;,&lt;br /&gt;
           &amp;quot;monitorLinkArrayInt16&amp;quot;,&lt;br /&gt;
           &amp;quot;monitorLinkArrayInt32&amp;quot;,&lt;br /&gt;
           &amp;quot;monitorLinkArrayInt64&amp;quot;,&lt;br /&gt;
           &amp;quot;monitorLinkArrayFloat32&amp;quot;,&lt;br /&gt;
           &amp;quot;monitorLinkArrayFloat64&amp;quot;,&lt;br /&gt;
           &amp;quot;monitorLinkArrayString&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkArrayOctet&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkArrayBoolean&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkArrayInt16&amp;quot;,&lt;br /&gt;
           ... all input and link types&lt;br /&gt;
        } ))&lt;br /&gt;
     )&lt;br /&gt;
     field(units,string)&lt;br /&gt;
     field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     field(busy,bool) {&lt;br /&gt;
         design(no)&lt;br /&gt;
         readonly(yes)&lt;br /&gt;
     }&lt;br /&gt;
     view(value) {&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=538</id>
		<title>V4 DB RecordCommon</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_RecordCommon&amp;diff=538"/>
		<updated>2005-09-27T15:21:51Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS V4: Standard Support September 27 2005 &lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
For V4 dbCommon.dbd and RecordCommon.dbd replace the V3 dbCommon.dbd.&lt;br /&gt;
dbCommon.dbd defines widely used definitions and RecordCommon.dbd defines&lt;br /&gt;
the fields that are common to all record types.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This document requires that the reader be familiar with:&lt;br /&gt;
# V3 iocCore&lt;br /&gt;
# V4 DBD Statement Syntax&lt;br /&gt;
# V4 DB Record Instance Syntax&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= dbCommon =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Channel/Database Access Support ==&lt;br /&gt;
&lt;br /&gt;
=== Data Structures ===&lt;br /&gt;
     struct(MonitorLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,bool) // process this record when monitor occurs&lt;br /&gt;
         field(inheritSeverity,bool) &lt;br /&gt;
     }&lt;br /&gt;
     struct(InputLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,bool)&lt;br /&gt;
         field(wait,bool)&lt;br /&gt;
         field(block,bool)&lt;br /&gt;
         field(inheritSeverity,bool)&lt;br /&gt;
     }&lt;br /&gt;
     struct(OutputLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(process,bool)&lt;br /&gt;
         field(wait,bool)&lt;br /&gt;
         field(block,bool)&lt;br /&gt;
         field(inheritSeverity,bool)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ProcessLinkData) {&lt;br /&gt;
         field(pvname,string) { link}&lt;br /&gt;
         field(wait,bool)&lt;br /&gt;
         field(block,bool)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
=== link support definitions ===&lt;br /&gt;
&lt;br /&gt;
Link support is provided for&lt;br /&gt;
* input&lt;br /&gt;
** monitor support&lt;br /&gt;
** input support&lt;br /&gt;
* output&lt;br /&gt;
* process&lt;br /&gt;
&lt;br /&gt;
For input and output The following data types are supported:&lt;br /&gt;
* primitive types&lt;br /&gt;
* string&lt;br /&gt;
* arrays of primitive types and strings&lt;br /&gt;
&lt;br /&gt;
     link(in,&amp;quot;monitorLinkOctet&amp;quot;,&amp;quot;monitorLinkOctet&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkBoolean&amp;quot;,&amp;quot;monitorLinkBoolean&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkInt16&amp;quot;,&amp;quot;monitorLinkInt16&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkInt32&amp;quot;,&amp;quot;monitorLinkInt32&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkInt64&amp;quot;,&amp;quot;monitorLinkInt64&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkFloat32&amp;quot;,&amp;quot;monitorLinkFloat32&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkFloat64&amp;quot;,&amp;quot;monitorLinkFloat64&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkString&amp;quot;,&amp;quot;monitorLinkString&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkOctet&amp;quot;,&amp;quot;inputLinkOctet&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkBoolean&amp;quot;,&amp;quot;inputLinkBoolean&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkInt16&amp;quot;,&amp;quot;inputLinkInt16&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkInt32&amp;quot;,&amp;quot;inputLinkInt32&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkInt64&amp;quot;,&amp;quot;inputLinkInt64&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkFloat32&amp;quot;,&amp;quot;inputLinkFloat32&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkFloat64&amp;quot;,&amp;quot;inputLinkFloat64&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkString&amp;quot;,&amp;quot;inputLinkString&amp;quot;,InputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkOctet&amp;quot;,&amp;quot;outputLinkOctet&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkBoolean&amp;quot;,&amp;quot;outputLinkBoolean&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkInt16&amp;quot;,&amp;quot;outputLinkInt16&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkInt32&amp;quot;,&amp;quot;outputLinkInt32&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkInt64&amp;quot;,&amp;quot;outputLinkInt64&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkFloat32&amp;quot;,&amp;quot;outputLinkFloat32&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkFloat64&amp;quot;,&amp;quot;outputLinkFloat64&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkString&amp;quot;,&amp;quot;outputLinkString&amp;quot;,OutputLinkData);&lt;br /&gt;
&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayOctet&amp;quot;,&amp;quot;monitorLinkArrayOctet&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayBoolean&amp;quot;,&amp;quot;monitorLinkArrayBoolean&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayInt16&amp;quot;,&amp;quot;monitorLinkArrayInt16&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayInt32&amp;quot;,&amp;quot;monitorLinkArrayInt32&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayInt64&amp;quot;,&amp;quot;monitorLinkArrayInt64&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayFloat32&amp;quot;,&amp;quot;monitorLinkArrayFloat32&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayFloat64&amp;quot;,&amp;quot;monitorLinkArrayFloat64&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;monitorLinkArrayString&amp;quot;,&amp;quot;monitorLinkArrayString&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayOctet&amp;quot;,&amp;quot;inputLinkArrayOctet&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayBoolean&amp;quot;,&amp;quot;inputLinkArrayBoolean&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayInt16&amp;quot;,&amp;quot;inputLinkArrayInt16&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayInt32&amp;quot;,&amp;quot;inputLinkArrayInt32&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayInt64&amp;quot;,&amp;quot;inputLinkArrayInt64&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayFloat32&amp;quot;,&amp;quot;inputLinkArrayFloat32&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayFloat64&amp;quot;,&amp;quot;inputLinkArrayFloat64&amp;quot;,InputLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkArrayString&amp;quot;,&amp;quot;inputLinkArrayString&amp;quot;,InputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayOctet&amp;quot;,&amp;quot;outputLinkArrayOctetData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayBoolean&amp;quot;,&amp;quot;outputLinkArrayBooleanData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayInt16&amp;quot;,&amp;quot;outputLinkArrayInt16&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayInt32&amp;quot;,&amp;quot;outputLinkArrayInt32&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayInt64&amp;quot;,&amp;quot;outputLinkArrayInt64&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayFloat32&amp;quot;,&amp;quot;outputLinkArrayFloat32&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayFloat64&amp;quot;,&amp;quot;outputLinkArrayFloat64&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkArrayString&amp;quot;,&amp;quot;outputLinkArrayString&amp;quot;,OutputLinkData);&lt;br /&gt;
&lt;br /&gt;
     link(process,&amp;quot;processLink&amp;quot;,ProcessLink,ProcessLinkData);&lt;br /&gt;
&lt;br /&gt;
== asynDriver link support ==&lt;br /&gt;
=== Data Definitions ===&lt;br /&gt;
&lt;br /&gt;
     struct(AsynDevice) }&lt;br /&gt;
         field(portName,string)&lt;br /&gt;
         field(addr,int32)&lt;br /&gt;
         field(timeout,float64)&lt;br /&gt;
         field(drvPvt,string)&lt;br /&gt;
     }&lt;br /&gt;
=== link definitions ===&lt;br /&gt;
&lt;br /&gt;
     link(in,&amp;quot;asynInt32&amp;quot;,&amp;quot;asynInt32&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynInt32Average&amp;quot;,&amp;quot;asynInt32Average&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynInt32Monitor&amp;quot;,&amp;quot;asynInt32Monitor&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynFloat64&amp;quot;,&amp;quot;asynFloat64&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynFloat64Average&amp;quot;,&amp;quot;asynFloat64Average&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynFloat64Monitor&amp;quot;,&amp;quot;asynFloat64Monitor&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynInt32&amp;quot;,&amp;quot;asynInt32&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynFloat64&amp;quot;,&amp;quot;asynFloat64&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynDigital&amp;quot;,&amp;quot;asynDigital&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynDigitalMonitor&amp;quot;,&amp;quot;asynDigitalMonitor&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynDigital&amp;quot;,&amp;quot;asynDigital&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynInt32Array&amp;quot;,&amp;quot;asynInt32Array&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynInt32Array&amp;quot;,&amp;quot;asynInt32Array&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynFloat64Array&amp;quot;,&amp;quot;asynFloat64Array&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynFloat64Array&amp;quot;,&amp;quot;asynFloat64Array&amp;quot;,AsynDevice)&lt;br /&gt;
     link(in,&amp;quot;asynOctetArray&amp;quot;,&amp;quot;asynOctetArray&amp;quot;,AsynDevice)&lt;br /&gt;
     link(out,&amp;quot;asynOctetArray&amp;quot;,&amp;quot;asynOctetArray&amp;quot;,AsynDevice)&lt;br /&gt;
== Other common definitions ==&lt;br /&gt;
&lt;br /&gt;
     menu(menuConvert) {&lt;br /&gt;
         choice(menuConvertRaw, &amp;quot;Raw&amp;quot;)&lt;br /&gt;
         choice(menuConvertLinear, &amp;quot;Linear&amp;quot;)&lt;br /&gt;
         choice(menuConvertTable, &amp;quot;Table&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
     # usefull struct definitions&lt;br /&gt;
&lt;br /&gt;
     struct(LinearConvert) {&lt;br /&gt;
         field(full,float64) &lt;br /&gt;
         field(egul,float64)&lt;br /&gt;
         field(slope,float64) &lt;br /&gt;
         field(intercept,float64) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64)&lt;br /&gt;
     }&lt;br /&gt;
     struct(ControlLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
     }&lt;br /&gt;
     struct(AlarmLimit) {&lt;br /&gt;
         field(low,float64) &lt;br /&gt;
         field(lowSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(lowWarning,float64) &lt;br /&gt;
         field(lowWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(highWarning,float64) &lt;br /&gt;
         field(highWarningSevr,menu(menuAlarmSevr)) &lt;br /&gt;
         field(high,float64) &lt;br /&gt;
         field(highSevr,menu(menuAlarmSevr)) &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= RecordCommon =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Menu Definitions ==&lt;br /&gt;
&lt;br /&gt;
     # menu definitions for RecordCommon fields&lt;br /&gt;
     menu(menuPriority) {&lt;br /&gt;
         choice(menuPriorityLow, &amp;quot;Low&amp;quot;)&lt;br /&gt;
         choice(menuPriorityMedium, &amp;quot;Medium&amp;quot;)&lt;br /&gt;
         choice(menuPriorityHigh, &amp;quot;High&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuScan) {&lt;br /&gt;
         choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
         choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
         choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
         choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
         choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
         choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     menu(menuAlarmSevr) {&lt;br /&gt;
         choice(menuAlarmSevrNone, &amp;quot;None&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMinor, &amp;quot;Minor&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrMajor, &amp;quot;Major&amp;quot;)&lt;br /&gt;
         choice(menuAlarmSevrInvalid, &amp;quot;Invalid&amp;quot;)&lt;br /&gt;
     }&lt;br /&gt;
== struct definitions for RecordSupport ==&lt;br /&gt;
     struct(TimeStamp) {&lt;br /&gt;
         field(secondsPastEpoch,int64)&lt;br /&gt;
         field(nanoSeconds,int32)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Scan {&lt;br /&gt;
         field(scan,menu(menuScan)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(phase,int16)&lt;br /&gt;
         field(priority,menu(menuPriority)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;b&amp;gt;Event NEEDS NEW DEFINITIONS&amp;lt;/b&amp;gt;&lt;br /&gt;
     struct Event {&lt;br /&gt;
         field(eventNumber,int16) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(timeStampEvent,int16)&lt;br /&gt;
         field(timeStampLink,link(in))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     struct Disable {&lt;br /&gt;
         field(disableValue,int16) {&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(disableInput,int16)&lt;br /&gt;
         field(disableLink,link(in))&lt;br /&gt;
         field(disableAlarmSeverity,menu(menuAlarmSevr))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== RecordCommon Record Definition ==&lt;br /&gt;
&lt;br /&gt;
     record(RecordCommon) {&lt;br /&gt;
         field(description,string)&lt;br /&gt;
         field(scan,struct(Scan))&lt;br /&gt;
         field(event,struct(Event))&lt;br /&gt;
         field(accessSecurityGroup,string)&lt;br /&gt;
         field(pini,bool)&lt;br /&gt;
         field(disablePutField,bool)&lt;br /&gt;
         field(alarmAckSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmAckTransient,bool) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;YES&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(udf,bool) {&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             default(&amp;quot;1&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(time,struct(TimeStamp)) {&lt;br /&gt;
             design(no)&lt;br /&gt;
             dynamic(yes)&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(disable,struct(Disable)) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmStatus,string) {&lt;br /&gt;
             default(&amp;quot;UDF&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(alarmSeverity,menu(menuAlarmSevr)) {&lt;br /&gt;
             readonly(yes)&lt;br /&gt;
             default(&amp;quot;Invalid&amp;quot;)&lt;br /&gt;
         }&lt;br /&gt;
         field(processLink,array(link[])) {&lt;br /&gt;
             special(yes)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
Although it has many fewer fields,&lt;br /&gt;
RecordCommon.dbd is a complete replacement for the V3 dbCommon.&lt;br /&gt;
The following V3 fields are no longer needed:&lt;br /&gt;
* private fields - Private fields will truly be privaye to the implementation&lt;br /&gt;
* previous value fields - All puts to database fields will be posted. The layer above will decide if clients should be notified of changes.&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_Record_Instance_Syntax&amp;diff=550</id>
		<title>V4 DB Record Instance Syntax</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DB_Record_Instance_Syntax&amp;diff=550"/>
		<updated>2005-09-27T15:18:51Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; Record Instance Syntax Sept 27 2005&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The syntax used for record instances has to change in EPICS V4,&lt;br /&gt;
since we now have to support structured data.&lt;br /&gt;
A complete redesign of the syntax has been done to help improve parsing, and to provide commonality between the syntax of a DB file and the string representation of structured data values passed through Channel Access.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Document Conventions =&lt;br /&gt;
&lt;br /&gt;
This syntax is presented below in the form of a grammar. The conventions I'm using are as follows:&lt;br /&gt;
&lt;br /&gt;
;''symbolBeingDefined:''&lt;br /&gt;
: ''otherSymbol''&lt;br /&gt;
: ''alternateSymbolFollowedBy'' &amp;lt;tt&amp;gt;literal&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;list of posible literal values&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Common Symbols =&lt;br /&gt;
&lt;br /&gt;
The symbols described in this section are used in the grammar, but may be implemented as lexical tokens.&lt;br /&gt;
&lt;br /&gt;
;''identifier:''&lt;br /&gt;
: A legal C99 identifier. Note that C99 permits implementations to allow extended characters to be used in identifiers, but does not require it, so the use of extended characters may reduce portability and is not recommended.&lt;br /&gt;
&lt;br /&gt;
== Integer Constants ==&lt;br /&gt;
&lt;br /&gt;
;''integerConstant:''&lt;br /&gt;
: ''positiveInteger''&lt;br /&gt;
&lt;br /&gt;
;''positiveInteger:''&lt;br /&gt;
: ''octalConstant''&lt;br /&gt;
: ''hexConstant''&lt;br /&gt;
: ''decimalConstant''&lt;br /&gt;
&lt;br /&gt;
;''octalConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''octalConstant'' ''octalDigit''&lt;br /&gt;
&lt;br /&gt;
;''octalDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-7&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''hexConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0x&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;0X&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: ''hexConstant'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
;''hexDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9 a-f A-F&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''decimalConstant:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;1-9&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''decimalConstant'' ''decimalDigit''&lt;br /&gt;
&lt;br /&gt;
;''decimalDigit:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This was meant to be a description of the C99 standard integer representation, but I made it up myself so it may be flawed.  Note that we will not accept the C99 numeric suffixes u/U and l/L since (unlike a C compiler) we know the type of the number we're expecting.&lt;br /&gt;
&lt;br /&gt;
== Floating Point Constants ==&lt;br /&gt;
&lt;br /&gt;
;''realConstant:''&lt;br /&gt;
:'' positiveReal''&lt;br /&gt;
: &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt; ''positiveReal''&lt;br /&gt;
&lt;br /&gt;
;''positiveReal:''&lt;br /&gt;
: ''digitSequence''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''exponentPart''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: ''digitSequence'' &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence'' ''exponentPart''&lt;br /&gt;
: &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; ''digitSequence'' ''exponentPart''&lt;br /&gt;
: ''digitSequence'' ''exponentPart''&lt;br /&gt;
&lt;br /&gt;
;''digitSequence:''&lt;br /&gt;
: ''decimalDigit''&lt;br /&gt;
: ''digitSequence'' ''decimalDigit''&lt;br /&gt;
&lt;br /&gt;
;''exponentPart:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;e&amp;lt;/tt&amp;gt; ''signedExponent''&lt;br /&gt;
: &amp;lt;tt&amp;gt;E&amp;lt;/tt&amp;gt; ''signedExponent''&lt;br /&gt;
&lt;br /&gt;
;''signedExponent:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt; ''digitSequence''&lt;br /&gt;
: ''digitSequence''&lt;br /&gt;
&lt;br /&gt;
In ANSI C source code, a sequence of decimal digits with neither a decimal point nor an exponent is an integer constant, not a floating-point constant.  We will permit this however, since we always know the field type in advance.&lt;br /&gt;
&lt;br /&gt;
== Boolean Constants ==&lt;br /&gt;
&lt;br /&gt;
We can afford to be generous in what we accept as a boolean value:&lt;br /&gt;
&lt;br /&gt;
;''booleanConstant:''&lt;br /&gt;
: ''booleanTrue''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''booleanTrue'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''booleanFalse''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''booleanFalse'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''booleanTrue:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;1 T TRUE t true True Y YES Yes y yes&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''booleanFalse:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0 F FALSE f false False N NO No n no&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''I'm proposing all these possibilities for true/false as they are all obvious in meaning, and will allow a CA Put of any of these strings to a boolean field. We might even want to allow registration of boolean strings in other languages...'''&lt;br /&gt;
&lt;br /&gt;
== String Constants ==&lt;br /&gt;
&lt;br /&gt;
;''stringConstant:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; ''escapedCharacterList'' &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''escapedCharacterList:''&lt;br /&gt;
: A series of characters, using the C99 ''escapeSequence'' syntax defined below:&lt;br /&gt;
&lt;br /&gt;
;''escapeSequence:''&lt;br /&gt;
: ''simpleEscapeSequence''&lt;br /&gt;
: ''octalEscapeSequence''&lt;br /&gt;
: ''hexEscapeSequence''&lt;br /&gt;
: ''universalCharacterName''&lt;br /&gt;
&lt;br /&gt;
;''simpleEscapeSequence:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;\' \&amp;quot; \? \\ \a \b \f \n \r \t \v&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''octalEscapeSequence:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit'' ''octalDigit''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt; ''octalDigit'' ''octalDigit'' ''octalDigit''&lt;br /&gt;
&lt;br /&gt;
;''hexEscapeSequence:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\x&amp;lt;/tt&amp;gt; ''hexDigit''&lt;br /&gt;
: ''hexEscapeSequence'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
Note: C99 does not limit the number of hexadecimal digits that can appear in a ''hexEscapeSequence'', but it does state that the behaviour is undefined if the resulting character value exceeds that of the largest character.&lt;br /&gt;
&lt;br /&gt;
;''universalCharacterName:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\u&amp;lt;/tt&amp;gt; ''hexQuad''&lt;br /&gt;
: &amp;lt;tt&amp;gt;\U&amp;lt;/tt&amp;gt; ''hexQuad'' ''hexQuad''&lt;br /&gt;
&lt;br /&gt;
;''hexQuad:''&lt;br /&gt;
: ''hexDigit'' ''hexDigit'' ''hexDigit'' ''hexDigit''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Database File =&lt;br /&gt;
&lt;br /&gt;
This section will eventually define what can appear in a .db file.  That currently means:&lt;br /&gt;
&lt;br /&gt;
* record instances&lt;br /&gt;
* comments&lt;br /&gt;
* macro instances, including where they will be allowed&lt;br /&gt;
* template files and substitution macro definitions&lt;br /&gt;
* port definitions for template instances&lt;br /&gt;
* data for tools such as VDCT, that will not be discarded by .db processing tools.&lt;br /&gt;
&lt;br /&gt;
The templates, macros and ports design should be very similar to the ideas produced for R3.14 VDCT templates.&lt;br /&gt;
&lt;br /&gt;
= Record Definitions =&lt;br /&gt;
&lt;br /&gt;
;''recordDefinition:''&lt;br /&gt;
: ''recordType'' ''recordName'' &amp;lt;tt&amp;gt;= {&amp;lt;/tt&amp;gt; ''recordBody'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''recordType:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
;''recordName:''&lt;br /&gt;
: ''recordNameChar''&lt;br /&gt;
: ''recordName'' ''recordNameChar''&lt;br /&gt;
&lt;br /&gt;
;''recordNameChar:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;0-9 A-Z a-z _ - : ; &amp;lt; &amp;gt; [ ]&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Any Unicode/UTF-8 character outside of the Basic Latin set&lt;br /&gt;
&lt;br /&gt;
This extends the character set available to a V3 record name, adding all possible multi-byte characters.  However, EPICS sites are strongly advised to confirm that such record names can be processed using all of their database and CA client tools before actually making use of this particular extension.&lt;br /&gt;
&lt;br /&gt;
;''recordBody:''&lt;br /&gt;
: ''recordBodyItem''&lt;br /&gt;
: ''recordBody'' ''recordBodyItem''&lt;br /&gt;
&lt;br /&gt;
Record instance definitions in EPICS V4 look very similar to a C99 structure definition with initialization. For example:&lt;br /&gt;
&lt;br /&gt;
   ai foo:bar:temperature = {&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
Inside the body of the record definition, there are three possible kinds of statements, similar to a C assignment statement.  Note these statements must be terminated with a semi-colon (which is different from inside a struct).  The reason for this difference is to prevent database instance files from becoming dependent on the order of fields in a record; if we permit record instances to be created from a single comma-separated list of field values without the field names, it could lead to significant confusion if the field order ever changes.&lt;br /&gt;
&lt;br /&gt;
;''recordBodyItem:''&lt;br /&gt;
: ''infoAssignment''&lt;br /&gt;
: ''fieldAssignment''&lt;br /&gt;
: ''extraFieldAssigment''&lt;br /&gt;
&lt;br /&gt;
== Information Fields ==&lt;br /&gt;
&lt;br /&gt;
;''infoAssignment:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; ''infoName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''stringConstant'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''infoName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
: ''stringConstant''&lt;br /&gt;
&lt;br /&gt;
Info items provide additional configuration data about this record that can be accessed by other software running on the IOC.&lt;br /&gt;
&lt;br /&gt;
   info savePeriod = &amp;quot;30.0&amp;quot;;&lt;br /&gt;
   info restorePhase = &amp;quot;1&amp;quot;;&lt;br /&gt;
   info &amp;quot;my favourite things&amp;quot; = &amp;quot;raindrops on roses&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
== Field Assignment ==&lt;br /&gt;
&lt;br /&gt;
;''fieldAssignment:''&lt;br /&gt;
: ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializer'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''fieldName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
;''initializer:''&lt;br /&gt;
: ''constant''&lt;br /&gt;
: ''structInitializer''&lt;br /&gt;
: ''arrayInitializer''&lt;br /&gt;
: ''linkInitializer''&lt;br /&gt;
&lt;br /&gt;
;''initializerList:''&lt;br /&gt;
: ''initializer''&lt;br /&gt;
: ''initializerList'' &amp;lt;tt&amp;gt;,&amp;lt;/tt&amp;gt; ''initializer''&lt;br /&gt;
&lt;br /&gt;
The ''initializer'' in a field assignment is also the exact same syntax that will be used when converting a string value from a CA client for example into a field value that is being put into a field.&lt;br /&gt;
&lt;br /&gt;
=== Basic and Enumerated Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''constant:''&lt;br /&gt;
: ''booleanConstant''&lt;br /&gt;
: ''integerConstant''&lt;br /&gt;
: ''realConstant''&lt;br /&gt;
: ''stringConstant''&lt;br /&gt;
&lt;br /&gt;
The syntax for the field initializer depends on the data type represented by fieldName.  Basic types (numeric or string) should need no comment other than to note that values for numeric fields must not be given inside quotes (unlike EPICS V3).  Menu field values may be given as either a string or an integer. For enum fields, if the related field that contains the strings is defined first, the enum field may be specified using a string; otherwise it can only be set using an integer value.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
   ai foo:bar:temperature = {&lt;br /&gt;
       inputSmoothing = 0.98;&lt;br /&gt;
       invalidValue = 1000;&lt;br /&gt;
       units = &amp;quot;Celcius&amp;quot;;&lt;br /&gt;
       scan = &amp;quot;Interrupt&amp;quot;;&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Structure Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''structInitializer:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''structAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''structAssignmentList:''&lt;br /&gt;
: ''initializerList''&lt;br /&gt;
: ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
: ''structAssignmentList'' &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; ''fieldName'' &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
&lt;br /&gt;
Initializers for a structure field look similar to a nested record body, but the rules are slightly different:&lt;br /&gt;
* You can give a series of values for adjacent items using a simple comma-separated list (for a record body, you ''must'' name each field)&lt;br /&gt;
* Semi-colons are required between a value and a following named item.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   ai foo:temperature:sensor = {&lt;br /&gt;
       linearConvert = {&lt;br /&gt;
           mode = &amp;quot;Linear&amp;quot;;&lt;br /&gt;
           low = -12.5, 133.5&lt;br /&gt;
       };&lt;br /&gt;
       displayLimit = { 0, 100 };&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
=== Link Initializer ===&lt;br /&gt;
&lt;br /&gt;
;''linkInitializer:''&lt;br /&gt;
: ''choiceName'' &amp;lt;tt&amp;gt;(&amp;lt;/tt&amp;gt; ''structAssignmentList'' &amp;lt;tt&amp;gt;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''choiceName:''&lt;br /&gt;
: ''identifier''&lt;br /&gt;
&lt;br /&gt;
These select a particular link support for the field, and set its address according to the structure type defined for that link type.&lt;br /&gt;
&lt;br /&gt;
   calcout foo:temperature:controller = {&lt;br /&gt;
       output = outputLinkFloat64(&lt;br /&gt;
                pvname = &amp;quot;fum:baz:heater&amp;quot;;&lt;br /&gt;
                process = true;&lt;br /&gt;
                wait = true;&lt;br /&gt;
                block = true;&lt;br /&gt;
       )&lt;br /&gt;
       input = [2] {&lt;br /&gt;
           {link = {&lt;br /&gt;
               monitorLinkFloat64{&lt;br /&gt;
                   pvname = &amp;quot;foo:temperature:setpoint&amp;quot;;&lt;br /&gt;
                   process = false&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
           {link = {&lt;br /&gt;
               inputLinkFloat64{&lt;br /&gt;
                   pvname = &amp;quot;foo:temperature:sensor&amp;quot;;&lt;br /&gt;
                   process = true;&lt;br /&gt;
                    wait = true;&lt;br /&gt;
                    block = true;&lt;br /&gt;
                   inheritSeverity = true&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
       };&lt;br /&gt;
       expression = &amp;quot;(setpoint - current) &amp;gt; 0&amp;quot;;&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   mbbi foo:bar:door = {&lt;br /&gt;
       input = acro9440(0, 5);&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
=== Array Initializers ===&lt;br /&gt;
&lt;br /&gt;
;''arrayInitializer:''&lt;br /&gt;
: &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''arrayType'' &amp;lt;tt&amp;gt;{&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''arrayCapacity'' &amp;lt;tt&amp;gt;] {&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''arrayType'' &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''arrayCapacity'' &amp;lt;tt&amp;gt;] {&amp;lt;/tt&amp;gt; ''arrayAssignmentList'' &amp;lt;tt&amp;gt;}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''arrayAssignmentList:''&lt;br /&gt;
: ''initializerList''&lt;br /&gt;
: &amp;lt;tt&amp;gt;[&amp;lt;/tt&amp;gt; ''integerConstant'' &amp;lt;tt&amp;gt;] =&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
: ''arrayAssignmentList'' &amp;lt;tt&amp;gt;; [&amp;lt;/tt&amp;gt; ''integerConstant'' &amp;lt;tt&amp;gt;] =&amp;lt;/tt&amp;gt; ''initializerList''&lt;br /&gt;
&lt;br /&gt;
;''arrayType:''&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;int16&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;uint16&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;int32&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;uint32&amp;lt;/tt&amp;gt;&lt;br /&gt;
: ''one of:'' &amp;lt;tt&amp;gt;float32&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;float64&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;octet&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;''arrayCapacity:''&lt;br /&gt;
: ''integerConstant''&lt;br /&gt;
: ''arrayCapacity'' &amp;lt;tt&amp;gt;,&amp;lt;/tt&amp;gt; ''integerConstant''&lt;br /&gt;
&lt;br /&gt;
If the definition of the array field being set did not do so, an array field initialization must include the size of the array and/or the type of the data stored in it. Inside the braces data values are given in a comma-separated list; the index can also be set to initialize individual values, and any mixture of the two can be used as desired:&lt;br /&gt;
&lt;br /&gt;
   mbbi foo:bar:door = {&lt;br /&gt;
       stateNames = [4] {&amp;quot;Broken&amp;quot;, &amp;quot;Closed&amp;quot;, &amp;quot;Open&amp;quot;, &amp;quot;Moving&amp;quot;};&lt;br /&gt;
       stateSeverity = [4] {&amp;quot;Major&amp;quot;; [3] = &amp;quot;Minor&amp;quot;};&lt;br /&gt;
       ...&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
For multi-dimensional arrays, data values can only appear inside the inner-most sets of braces, although index settings are permitted outside of these.  These two definitions give the same result:&lt;br /&gt;
&lt;br /&gt;
   matrix identity1 = {&lt;br /&gt;
       value = float32 [3,3] { {1, 0, 0}, {0, 1, 0}, {1, 0, 0}};&lt;br /&gt;
   }&lt;br /&gt;
   matrix identity2 = {&lt;br /&gt;
       value = float32 [3,3] { {1}, {[1] = 1}, {[2] = 1}};&lt;br /&gt;
   }&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=537</id>
		<title>V4 DBD Statement Syntax</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_DBD_Statement_Syntax&amp;diff=537"/>
		<updated>2005-09-27T15:16:38Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DBD Statement Syntax Sept 27 2005&lt;br /&gt;
= Overview =&lt;br /&gt;
This document presents the syntax for V4 database definition files.&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= General Statements =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== include ==&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;filename&amp;quot;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;filename&amp;lt;/tt&amp;gt;&lt;br /&gt;
: must be a valid filename&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Include statements can be used at the top level, or inside the braces of a &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; definition.&lt;br /&gt;
&lt;br /&gt;
== # comment ==&lt;br /&gt;
&lt;br /&gt;
 # anything&lt;br /&gt;
&lt;br /&gt;
Anything on a line after a &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; 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 &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; character has no special meaning.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== menu ==&lt;br /&gt;
&lt;br /&gt;
A menu is an enumerated type where the choice strings are defined once for each IOC.  Menus are defined like this:&lt;br /&gt;
&lt;br /&gt;
 menu(menuName) {&lt;br /&gt;
     choice(choiceName, &amp;quot;choiceValue&amp;quot;)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can be any UTF-8 compatible string, which should be unique within the context of this menu.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 menu(menuScan) {&lt;br /&gt;
     choice(menuScanPassive, &amp;quot;Passive&amp;quot;)&lt;br /&gt;
     choice(menuScanEvent, &amp;quot;Event&amp;quot;)&lt;br /&gt;
     choice(menuScanInterrupt, &amp;quot;Interrupt&amp;quot;)&lt;br /&gt;
     choice(menuScan10second, &amp;quot;10 second&amp;quot;)&lt;br /&gt;
     choice(menuScan5second, &amp;quot;5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan2second, &amp;quot;2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan1second, &amp;quot;1 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_5second, &amp;quot;.5 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_2second, &amp;quot;.2 second&amp;quot;)&lt;br /&gt;
     choice(menuScan_1second, &amp;quot;.1 second&amp;quot;)&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Structures, Record types, Fields and Views =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== struct ==&lt;br /&gt;
&lt;br /&gt;
A structure is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 struct(name) {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The structure name must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular structure.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
&lt;br /&gt;
== record ==&lt;br /&gt;
&lt;br /&gt;
A record type is defined as follows:&lt;br /&gt;
&lt;br /&gt;
 include &amp;quot;dbCommon.dbd&amp;quot;&lt;br /&gt;
 record(name) extends RecordCommon {&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     view(viewName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The record type name. It must be a valid, unique C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;extends RecordCommon&amp;lt;/tt&amp;gt;&lt;br /&gt;
: This states that the record type extends the set of fields defined in &amp;quot;V4 DB RecordCommon&amp;quot;. 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 &amp;lt;tt&amp;gt;extends&amp;lt;/tt&amp;gt; phrase.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be a valid C identifier, unique within the context of this particular record type and its parents (extends ...).&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldType|fieldType]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldAttribute&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;attributeValue&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#fieldAttribute|fieldAttribute]] below.&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: See [[#Views of a record|Views of a record]] below.&lt;br /&gt;
&lt;br /&gt;
== fieldType ==&lt;br /&gt;
&lt;br /&gt;
Both &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;record&amp;lt;/tt&amp;gt; define a field as:&lt;br /&gt;
     field(fieldName, fieldType) {&lt;br /&gt;
         fieldAttribute(attributeValue)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The syntax for &amp;lt;tt&amp;gt;fieldType&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Basic types: octet, boolean, numerics, and string ===&lt;br /&gt;
&lt;br /&gt;
The following field types have no arguments:&lt;br /&gt;
&amp;lt;tt&amp;gt;octet&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;int32&amp;lt;/tt&amp;gt;,  &amp;lt;tt&amp;gt;int64&amp;lt;/tt&amp;gt;,&lt;br /&gt;
&amp;lt;tt&amp;gt;float32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;float64&amp;lt;/tt&amp;gt;,  and &amp;lt;tt&amp;gt;string&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Examples: &lt;br /&gt;
     field(description,string)&lt;br /&gt;
     field(value,float64)&lt;br /&gt;
&lt;br /&gt;
=== enum ===&lt;br /&gt;
&lt;br /&gt;
An &amp;lt;tt&amp;gt;enum&amp;lt;/tt&amp;gt; field takes one argument after the type name:&lt;br /&gt;
&lt;br /&gt;
     enum(fieldName)&lt;br /&gt;
&lt;br /&gt;
where fieldName is the name of another field in the same record that must be of type &amp;lt;tt&amp;gt;array(string[])&amp;lt;/tt&amp;gt;.  The values in this other field at runtime define the available choice strings for the enum field.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
     field(choices, array(string[])&lt;br /&gt;
     field(value, enum(choices))&lt;br /&gt;
&lt;br /&gt;
=== menu ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;menu&amp;lt;/tt&amp;gt; field is defined like this:&lt;br /&gt;
     menu(menuName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;menuName&amp;lt;/tt&amp;gt; is the name of the menu.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     field(scan, menu(menuScan))&lt;br /&gt;
&lt;br /&gt;
=== struct ===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; field is declared using the type name&lt;br /&gt;
     struct(structName)&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;structName&amp;lt;/tt&amp;gt; is the name of a struct which must have been previously defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
      struct(Point) {&lt;br /&gt;
          field(x,float64)&lt;br /&gt;
          field(y,float64)&lt;br /&gt;
          field(z,float64)&lt;br /&gt;
       }&lt;br /&gt;
       ...&lt;br /&gt;
       record(haspoint) extends RecordCommon {&lt;br /&gt;
           ...&lt;br /&gt;
           field(point, struct(point))&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
=== array ===&lt;br /&gt;
&lt;br /&gt;
An array field uses definitions like these:&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 3-dimensional array of unknown size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array(arrayType[,,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacity])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; multi-dimensional array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([capacityX, capacityY, ...])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; arbitrarily dimensioned array of unknown type&lt;br /&gt;
: &amp;lt;tt&amp;gt;array()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; 1-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([])&amp;lt;/tt&amp;gt;&lt;br /&gt;
; 2-dimensional array of unknown type or size&lt;br /&gt;
: &amp;lt;tt&amp;gt;array([,])&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;arrayType&amp;lt;/tt&amp;gt; may be any fieldType except &amp;lt;tt&amp;gt;array&amp;lt;/tt&amp;gt;, 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]]&lt;br /&gt;
* &amp;lt;tt&amp;gt;capacity&amp;lt;/tt&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(VAL1D,array(float64[]))  #1d array with arbitrary capacity&lt;br /&gt;
     field(VAL2D,array(float64[,])) #2d array with arbitrary capacities&lt;br /&gt;
     field(anyTypeAnyD,array())     #arbitrary type,number of dimensions, and capacities&lt;br /&gt;
&lt;br /&gt;
=== link ===&lt;br /&gt;
&lt;br /&gt;
This field type can get or put data from/to some source outside of the record.&lt;br /&gt;
Link fields replace the DBF_INLINK, DBF_OUTLINK, and DTYP fields from EPICS V3.&lt;br /&gt;
&lt;br /&gt;
A link field's choices come from link definitions - see the [[#link]] section below for more details.&lt;br /&gt;
A link can be a link to another database record, to hardware device support,&lt;br /&gt;
or something else.&lt;br /&gt;
&lt;br /&gt;
The syntax is:&lt;br /&gt;
&lt;br /&gt;
     link(linkDirection,array(string[])= {name,...})&lt;br /&gt;
&lt;br /&gt;
where &lt;br /&gt;
* &amp;lt;tt&amp;gt;linkDirection&amp;lt;/tt&amp;gt; : &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. The direction &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt; means there is no direction associated with this interface.  For &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt; the direction is determined by the particular &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; that the record instance selects.&lt;br /&gt;
* &amp;lt;tt&amp;gt;array(string[])&amp;lt;/tt&amp;gt; : Each string is the name of Link Interface implemented by link support and used by record support.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     field(disableLink,&lt;br /&gt;
        link(in,array(string[4]) = {&lt;br /&gt;
           &amp;quot;monitorLinkInt32&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkInt32&amp;quot;,&lt;br /&gt;
           &amp;quot;monitorLinkFloat64&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkFloat64&amp;quot;&lt;br /&gt;
        } ))&lt;br /&gt;
     )&lt;br /&gt;
     field(process, link(process,array(string[1])= {processLink}))&lt;br /&gt;
     field(inp,&lt;br /&gt;
        link(in, array(string[3]) = {&lt;br /&gt;
           &amp;quot;monitorLinkInt32&amp;quot;,&lt;br /&gt;
           &amp;quot;inputLinkInt32&amp;quot;,&lt;br /&gt;
            &amp;quot;digitalIO&amp;quot;&lt;br /&gt;
         }))&lt;br /&gt;
     )&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Andrew: Do we want the above syntax? Another possibility is just:&lt;br /&gt;
    link(linkDirection,interface(string,...))&lt;br /&gt;
&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== fieldAttribute ==&lt;br /&gt;
&lt;br /&gt;
Each field definition has several associated attributes, the values of which are set like this:&lt;br /&gt;
&lt;br /&gt;
     default(&amp;quot;fieldValue&amp;quot;)&lt;br /&gt;
     readonly(yesNo)&lt;br /&gt;
     design(yesNo)&lt;br /&gt;
     special(yesNo)&lt;br /&gt;
     asl(securityLevel)&lt;br /&gt;
     link(yesNo)&lt;br /&gt;
&lt;br /&gt;
'''Marty thinks we should get rid of these two:'''&lt;br /&gt;
     prompt(&amp;quot;promptString&amp;quot;)&lt;br /&gt;
     group(&amp;quot;promptGroup&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
'''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.'''&lt;br /&gt;
&lt;br /&gt;
The attribute parameter values have the following meanings:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;default(&amp;quot;fieldValue&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;readonly(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Can this field be modified via channel access or database links?  Takes the value No if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;design(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;special(yesNo)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;asl(securityLevel)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Channel Access security level for this field, 0 or 1.  Takes the value 1 if not specified.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
''These attributes may disappear, see comment above:''&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;prompt(&amp;quot;promptString&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;group(&amp;quot;promptGroup&amp;quot;)&amp;lt;/tt&amp;gt;&lt;br /&gt;
: 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.&lt;br /&gt;
&lt;br /&gt;
== view ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;field&amp;quot; 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).&lt;br /&gt;
&lt;br /&gt;
A simple view looks like this:&lt;br /&gt;
&lt;br /&gt;
 view(viewName) {&lt;br /&gt;
     property(propName) {&lt;br /&gt;
         property(propName, fieldPath)&lt;br /&gt;
         ...&lt;br /&gt;
     }&lt;br /&gt;
     property(propName, fieldPath)&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;viewName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The view name must be a valid C identifier, which must be unique in the context of the particular record type.&lt;br /&gt;
; &amp;lt;tt&amp;gt;propName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: A Data Access property name, which must be a valid C identifier.&lt;br /&gt;
; &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The path to a field in this record type. To use a field inside a structure field, give the full path to that field: &amp;lt;tt&amp;gt;controlLimit.upper&amp;lt;/tt&amp;gt; for example.&lt;br /&gt;
: If &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; resolves to a structure, a property catalog containing the whole structure will be sent, with property names matching the structure's field names.&lt;br /&gt;
: The &amp;lt;tt&amp;gt;fieldPath&amp;lt;/tt&amp;gt; may be omitted as long as there is a subordinate property catalog below this property.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 record(ao) extends RecordCommon {&lt;br /&gt;
     field(value, float64) { ... }&lt;br /&gt;
     field(outValue, float64) { ... }&lt;br /&gt;
     field(rawValue, int32) { ... }&lt;br /&gt;
     field(units, string) { ... }&lt;br /&gt;
     field(displayLimit, struct(displayLimit)) { ... }&lt;br /&gt;
     ...&lt;br /&gt;
     view(value)&lt;br /&gt;
         property(value, value) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
             property(displayLimit, displayLimit)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(outValue)&lt;br /&gt;
         property(value, outValue) {&lt;br /&gt;
             property(units, units)&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
             property(alarmSeverity, alarmSeverity)&lt;br /&gt;
             property(alarmStatus, alarmStatus)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     view(rawValue)&lt;br /&gt;
         property(value, rawValue) {&lt;br /&gt;
             property(timeStamp, time)&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= link =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;link&amp;lt;/tt&amp;gt; statement describes an implementation of support for a link&lt;br /&gt;
field. the support can be any of the following:&lt;br /&gt;
* A link to another record either local or remote&lt;br /&gt;
* A link to hardware support&lt;br /&gt;
* Something else.&lt;br /&gt;
&lt;br /&gt;
The syntax for these is:&lt;br /&gt;
&lt;br /&gt;
 device(dir, choiceName, interfaceName, dataStructName)&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dir&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Must be one of &amp;lt;tt&amp;gt;none&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;,&amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt;. Compatible checks are made to match the interface with a field.&lt;br /&gt;
: '''Q: What are the rules?'''&lt;br /&gt;
:: ''It certainly doesn't seem to make sense to have a none or inout link for instance.''&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;choiceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: UTF-8 string that describes the choice&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;interfaceName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of an interface via which record support communicates with device support.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;tt&amp;gt;dataStructName&amp;lt;/tt&amp;gt;&lt;br /&gt;
: The name of a &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; that the interface understands. This interface can contain data and configuration information. The &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; must be defined before record instances can be created that assign values to it.&lt;br /&gt;
:: ''Need to rewrite this paragraph to clarify.''&lt;br /&gt;
&lt;br /&gt;
When a record instance is created the choiceName selects the support&lt;br /&gt;
to attach to a record link. The interfaceName must be one of the&lt;br /&gt;
interface names the record has listed as a valid type and dir must be compatible&lt;br /&gt;
with the dir the record type specified.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
     link(in,&amp;quot;monitorLinkInt16&amp;quot;,&amp;quot;monitorLinkInt16&amp;quot;,MonitorLinkData);&lt;br /&gt;
     link(in,&amp;quot;inputLinkInt16&amp;quot;,&amp;quot;inputLinkInt16&amp;quot;,InputLinkData);&lt;br /&gt;
     link(out,&amp;quot;outputLinkFloat64&amp;quot;,&amp;quot;outputLinkFloat64&amp;quot;,OutputLinkData);&lt;br /&gt;
     link(process,&amp;quot;processLink&amp;quot;,ProcessLink,ProcessLinkData);&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
	<entry>
		<id>https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Runtime_Interfaces&amp;diff=541</id>
		<title>V4 Design: Runtime Interfaces</title>
		<link rel="alternate" type="text/html" href="https://wiki-ext.aps.anl.gov/epics/index.php?title=V4_Design:_Runtime_Interfaces&amp;diff=541"/>
		<updated>2005-09-23T16:04:25Z</updated>

		<summary type="html">&lt;p&gt;MartyKraimer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;EPICS: IOC Runtime Interfaces September 23 2005&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
This document describes  definitions for IOC runtime,&lt;br /&gt;
i.e. interfaces implemented or used by database access, record support,&lt;br /&gt;
link support, and device support.&lt;br /&gt;
&lt;br /&gt;
It assumes knowledge of the interfaces described in dbdInterfaces.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; IOC runtime needs lots more work&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Support Code =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This section described interfaces for&lt;br /&gt;
strings, arrays, and conversions. &lt;br /&gt;
They are intended for use by Database Access, Record Support, etc.&lt;br /&gt;
&lt;br /&gt;
== C++ support for strings ==&lt;br /&gt;
&lt;br /&gt;
This subsection describes interfaces for C++ code that needs tempory storage&lt;br /&gt;
for strings. For Java the String class is used.&lt;br /&gt;
&lt;br /&gt;
The following interfaces are for allocating tempory storage for strings:&lt;br /&gt;
&lt;br /&gt;
     class NonmutableString {&lt;br /&gt;
     public:&lt;br /&gt;
        void destroy(); // Call this when done with string&lt;br /&gt;
        int32_t getLength();&lt;br /&gt;
        char data[];&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     class NonmutableStringFactory {&lt;br /&gt;
     public:&lt;br /&gt;
         static NonmutableString *create(int32_t len,char data[]);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     class MutableString : public NonmutableString {&lt;br /&gt;
     public:&lt;br /&gt;
        int32_t getCapacity();&lt;br /&gt;
        void setLength(int32_t len);&lt;br /&gt;
     }&lt;br /&gt;
    &lt;br /&gt;
     class MutableStringFactory {&lt;br /&gt;
         static MutableString *create(int32_t capacity);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
These will use free lists to manage the storage for the octet arrays.&lt;br /&gt;
&lt;br /&gt;
== array copy ==&lt;br /&gt;
&lt;br /&gt;
ArrayCopy copies arrays an array performing conversions if necessary.&lt;br /&gt;
&lt;br /&gt;
     interface ArrayCopy {&lt;br /&gt;
         void copy(DbfArray from,DbfArray to);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
This only supports primitive types, i.e. DbfBoolean,...,DbfFloat64.&lt;br /&gt;
It does NOT convert between&lt;br /&gt;
* DbfBoolean and another type.&lt;br /&gt;
* DbfOctet and another type.&lt;br /&gt;
Thus for DbfBoolean and DbfOctet it is willing to copy&lt;br /&gt;
but not convert to/from other types.&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Conversions ==&lt;br /&gt;
This is a static class that converts between primitie types and arrays of primitive types.&lt;br /&gt;
&lt;br /&gt;
     static class DbfConvertPrimitive {&lt;br /&gt;
     public:&lt;br /&gt;
          int16 get(Dbf from);&lt;br /&gt;
          int32 get(Dbf from);&lt;br /&gt;
          int64 get(Dbf from);&lt;br /&gt;
          float32 get(Dbf from);&lt;br /&gt;
          float64 get(Dbf from);&lt;br /&gt;
          get(Dbf from, String value);&lt;br /&gt;
          get(DbfOctet from, String value);&lt;br /&gt;
          get(DbfBoolean from, String value);&lt;br /&gt;
          put(Dbf to, int16 value);&lt;br /&gt;
          put(Dbf to, int32 value);&lt;br /&gt;
          put(Dbf to, int64 value);&lt;br /&gt;
          put(Dbf to, float32 value);&lt;br /&gt;
          put(Dbf to, float64 value);&lt;br /&gt;
          put(Dbf to,int32 String value);&lt;br /&gt;
          put(DbfOctet to, String value);&lt;br /&gt;
          put(DbfBoolean to, String value);&lt;br /&gt;
&lt;br /&gt;
          get(DbfArray from, int16[] value);&lt;br /&gt;
          get(DbfArray from, int32[] value);&lt;br /&gt;
          get(DbfArray from, int64[] value);&lt;br /&gt;
          get(DbfArray from, float32[] value);&lt;br /&gt;
          get(DbfArray from, float64[] value);&lt;br /&gt;
          put(DbfArray to, int16[] value);&lt;br /&gt;
          put(DbfArray to, int32[] value);&lt;br /&gt;
          put(DbfArray to, int64[] value);&lt;br /&gt;
          put(DbfArray to, float32[] value);&lt;br /&gt;
          put(DbfArray to, float64[] value);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
* For Dbf &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; must be one of &amp;lt;tt&amp;gt;DbfInt16&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;DbfFloat64&amp;lt;/tt&amp;gt;&lt;br /&gt;
* The get to a string implements printf semantics&lt;br /&gt;
* The put from a string value just scanf semantics.&lt;br /&gt;
* The &amp;lt;tt&amp;gt;DbfOctet&amp;lt;/tt&amp;gt; methods convert to/from a string of the form &amp;quot;0xXX&amp;quot;&lt;br /&gt;
* The &amp;lt;tt&amp;gt;DbfBoolean&amp;lt;/tt&amp;gt; get method supports all the choices specified in the DBD Record Instance Specification&lt;br /&gt;
* For DbfArray &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; must be an array of one of &amp;lt;tt&amp;gt;DbfInt16&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;DbfFloat64&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code generated from Database Definition Files =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following shows the Java code generated from DBD files:&lt;br /&gt;
&lt;br /&gt;
== structure definitions ==&lt;br /&gt;
&lt;br /&gt;
Two files are generated from &amp;lt;tt&amp;gt;struct(name)&amp;lt;/tt&amp;gt; definitions.&lt;br /&gt;
# &amp;lt;tt&amp;gt;name.java&amp;lt;/tt&amp;gt;&lt;br /&gt;
# &amp;lt;tt&amp;gt;nameSupport.java&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;name.java&amp;lt;/tt&amp;gt; implements:&lt;br /&gt;
     interface Struct {&lt;br /&gt;
         Dbf getField(int16 index);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If a structure is defined as:&lt;br /&gt;
     struct(DisplayLimit) {&lt;br /&gt;
         field(low,double)&lt;br /&gt;
         field(high,double)&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
A generated file &amp;lt;tt&amp;gt;DisplayLimit.java&amp;lt;/tt&amp;gt; contains:&lt;br /&gt;
&lt;br /&gt;
     public class DisplayLimit implements Struct{&lt;br /&gt;
         public DbfFloat64 low;&lt;br /&gt;
         public DbfFloat64 high;&lt;br /&gt;
         public static final short lowIndex = 1;&lt;br /&gt;
         public static final short highIndex = 2;&lt;br /&gt;
         public static final short lastIndex = indexHigh;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case lowIndex: return(low);&lt;br /&gt;
                 case highIndex: return(high);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
             return null;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
A generated file &amp;lt;tt&amp;gt;DisplayLimitAccess.java&amp;lt;/tt&amp;gt; contains:&lt;br /&gt;
&lt;br /&gt;
     public class DisplayLimitData {&lt;br /&gt;
         public double low;&lt;br /&gt;
         public double high;&lt;br /&gt;
     }&lt;br /&gt;
     public final class DisplayLimitAccess implements StructFactory{&lt;br /&gt;
         public Struct create() { return new DisplayLimit; }&lt;br /&gt;
         public static final void get(DbfStruct from,DisplayLimitData data) {&lt;br /&gt;
             DbfFloat64 dbf = from.getInterface(1);&lt;br /&gt;
             data.low = dbf.get();&lt;br /&gt;
             DbfFloat64 dbf = from.getInterface(2);&lt;br /&gt;
             data.high = dbf.get();&lt;br /&gt;
         }&lt;br /&gt;
         public static final void put(DbfStruct to, DisplayLimitData data) {&lt;br /&gt;
             DbfFloat64 dbf = to.getInterface(1);&lt;br /&gt;
             dbf.put(data.low);&lt;br /&gt;
             DbfFloat64 dbf = to.getInterface(2);&lt;br /&gt;
             dbf.put(data.high);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class DisplayLimitAccessRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             DisplayLimitAccess access = new DisplayLimitAccess;&lt;br /&gt;
             RegisterSupport.structure(access,&amp;quot;DisplayLimit&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; The V4 replacement for registerRecordDeviceDriver must&lt;br /&gt;
call DisplayLimitAccessRegister.createAndRegister.&lt;br /&gt;
&lt;br /&gt;
Similar files are generated for C++.&lt;br /&gt;
&lt;br /&gt;
== record definitions ==&lt;br /&gt;
If a record is defined as:&lt;br /&gt;
     record(Example) extends RecordCommon {&lt;br /&gt;
         ...&lt;br /&gt;
         field(fboolean,boolean)&lt;br /&gt;
         field(octet,octet)&lt;br /&gt;
         field(fint,int16)&lt;br /&gt;
         ...&lt;br /&gt;
         field(ffloat,float64)&lt;br /&gt;
         field(string,string)&lt;br /&gt;
         field(array,array(double[])&lt;br /&gt;
         field(mdarray,array(double[,])&lt;br /&gt;
         field(menu,menu(name))&lt;br /&gt;
         field(fenum,enum)&lt;br /&gt;
         field(link,link(in))&lt;br /&gt;
         field(device,link(in,analogIO))&lt;br /&gt;
         field(displayLimit,struct(DisplayLimit))&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The generated Java file is&lt;br /&gt;
&lt;br /&gt;
     public class ExampleRecord implements Struct {&lt;br /&gt;
         public DbfBoolean   fboolean;&lt;br /&gt;
         public DbfOctet     ctet;&lt;br /&gt;
         public DbfInt16     fint;&lt;br /&gt;
         ...&lt;br /&gt;
         public DbfFloat64   ffloat;&lt;br /&gt;
         public DbfString    string;&lt;br /&gt;
         public DbfArray     array;&lt;br /&gt;
         public DbfMDArray   mdarray;&lt;br /&gt;
         public DbfMenu      menu;&lt;br /&gt;
         public DbfEnum      fenum;&lt;br /&gt;
         public DbfLink      link;&lt;br /&gt;
         public DbfDevice    device;&lt;br /&gt;
         public DbfStruct    displayLimit;&lt;br /&gt;
         public static final int16 fbooleanIndex = 1;&lt;br /&gt;
         ...&lt;br /&gt;
         public static final int16 lastIndex = displayLimitIndex;&lt;br /&gt;
         Dbf getField(short index) {&lt;br /&gt;
             switch(index) {&lt;br /&gt;
                 case fbooleanIndex : return(fboolean);&lt;br /&gt;
                 ...&lt;br /&gt;
                 case displayLimitIndex: return(displayLimit);&lt;br /&gt;
                 default: throw java.lang.IllegalStateException;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class ExampleRecordFactory implements StructFactory{&lt;br /&gt;
         public static final Struct create() { return new ExampleRecord; }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     public final class ExampleRecordFactoryRegister {&lt;br /&gt;
         static public createAndRegister() {&lt;br /&gt;
             ExampleRecordFactory  factory = new ExampleRecordFactory;&lt;br /&gt;
             RegisterSupport.record(factory,&amp;quot;ExampleRecord&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE&amp;lt;/b&amp;gt; The V4 replacement for registerRecordDeviceDriver must&lt;br /&gt;
call ExampleRecordFactoryRegister.createAndRegister&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Similar code is generated for C++.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Record Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     enum ProcessState {&lt;br /&gt;
         processCancel,&lt;br /&gt;
         processStart,&lt;br /&gt;
         processContinue,&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     enum ProcessReturn {&lt;br /&gt;
         processDone,&lt;br /&gt;
         processAbort,&lt;br /&gt;
         processActive&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RecordSupport {&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize(int32 pass);&lt;br /&gt;
         ProcessState process(ProcessState state);&lt;br /&gt;
         // if special returns false when after is false put fails&lt;br /&gt;
         boolean special(boolean after,Dbf[] field);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ProcessState&amp;lt;/tt&amp;gt; supports the following semantics:&lt;br /&gt;
* cancel - If the record is active terminate &lt;br /&gt;
* For all other states see the companion document &amp;quot;V4 Design: Record Processing&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The methods of &amp;lt;tt&amp;gt;RecordSupport&amp;lt;/tt&amp;gt; are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - Called when a record instance is deleted.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called twice (pass = 0,1) when a record is initialized.&lt;br /&gt;
* &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; - Called to process a record. See &amp;quot;V4 Design: Record Processing&amp;quot; for semantics.&lt;br /&gt;
* &amp;lt;tt&amp;gt;special&amp;lt;/tt&amp;gt; - Called when a field declared special in a DBD file is modified. &amp;lt;tt&amp;gt;field&amp;lt;/tt&amp;gt; is an array of Dbfs showing which field is being modified.&lt;br /&gt;
&lt;br /&gt;
== Discussion of special ==&lt;br /&gt;
&lt;br /&gt;
Special is passed a Dbf array that identifies the field being modified.&lt;br /&gt;
For example &amp;lt;tt&amp;gt;ExampleRecord.dbd&amp;lt;/tt&amp;gt; has a field:&lt;br /&gt;
     field(displayLimit,struct(displayLimit))&lt;br /&gt;
&amp;lt;tt&amp;gt;ExampleRecordSupport.java&amp;lt;/tt&amp;gt; might implement special as follows:&lt;br /&gt;
     boolean special(boolean after, Dbf[] field)&lt;br /&gt;
     {&lt;br /&gt;
         switch(field[0].getIndex()) {&lt;br /&gt;
         ...&lt;br /&gt;
         case ExampleRecord.displayLimitIndex:&lt;br /&gt;
             if(field.length==1) {&lt;br /&gt;
                 // displayLimits itself is being modified. Do something&lt;br /&gt;
             } else {&lt;br /&gt;
                // a field of displayLimits is being modified&lt;br /&gt;
                 switch(field[1].getIndex) {&lt;br /&gt;
                     case DisplayLimit.lowIndex:&lt;br /&gt;
                          // low being modified. do something&lt;br /&gt;
                     case DisplayLimit.highIndex:&lt;br /&gt;
                          // high being modified. do something&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         ...&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
=  Link and Device Support =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Link/Device Base ==&lt;br /&gt;
     interface Support { // base for Link and Device support&lt;br /&gt;
         void report(int16 level);&lt;br /&gt;
         void cancel();&lt;br /&gt;
         void destroy();&lt;br /&gt;
         void initialize();&lt;br /&gt;
         void connect();&lt;br /&gt;
         void disconnect();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Support&amp;lt;/tt&amp;gt; is the base class for all link and device support.&lt;br /&gt;
An instance of this is connected to each DbfLink or DbfDevice field.&lt;br /&gt;
The methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;report&amp;lt;/tt&amp;gt; - report &lt;br /&gt;
* &amp;lt;tt&amp;gt;cancel&amp;lt;/tt&amp;gt; - Cancel any outstanding I/O&lt;br /&gt;
* &amp;lt;tt&amp;gt;destroy&amp;lt;/tt&amp;gt; - This is called if the field is being changed after initialization or if the record is being removed.&lt;br /&gt;
* &amp;lt;tt&amp;gt;initialize&amp;lt;/tt&amp;gt; - Called to initialize a link.&lt;br /&gt;
* &amp;lt;tt&amp;gt;connect&amp;lt;/tt&amp;gt; - Called to connect. Note that this is different than initilization.&lt;br /&gt;
* &amp;lt;tt&amp;gt;disconnect&amp;lt;/tt&amp;gt; - disconnect.&lt;br /&gt;
&lt;br /&gt;
Normally record support does not need to call any of the Base Support methods&lt;br /&gt;
since Database Access does this automatically. For example if a link or&lt;br /&gt;
device field is modified via a channel access put, database access will call&lt;br /&gt;
destroy before modifying the link and initialize and connect after the&lt;br /&gt;
link is modidied.&lt;br /&gt;
&lt;br /&gt;
== Link Support ==&lt;br /&gt;
     enum LinkWaitResult {&lt;br /&gt;
         linkNoop,           // Nothing was done, e.g. link is null link&lt;br /&gt;
         linkDone,           // field was modified. No wait is necessary&lt;br /&gt;
         linkWaitSequential, // waiting. must processes links sequentially&lt;br /&gt;
         linkWaitParallel,   // waiting. parallel processing OK&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface Callback {&lt;br /&gt;
         void done();&lt;br /&gt;
         void failure();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface LinkSupport extends Support {&lt;br /&gt;
         void get(Dbf field);&lt;br /&gt;
         LinkWaitResult getWait(Dbf field, double timeout,Callback callback);&lt;br /&gt;
         void put(Dbf field);&lt;br /&gt;
         LinkWaitResult putWait(Dbf field, double timeout,Callback callback);&lt;br /&gt;
         void process();&lt;br /&gt;
         LinkWaitResult processWait(double timeout,Callback callback);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;LinkSupport&amp;lt;/tt&amp;gt; supports the following semantics:&lt;br /&gt;
* Input Link from another record&lt;br /&gt;
**  get current value independent of processing state.&lt;br /&gt;
** Ask the record to process and wait for completion before fetching value.&lt;br /&gt;
** wait until next time record processes then get value. No request is made to process the record.&lt;br /&gt;
* Output Link to another record&lt;br /&gt;
** put value without requesting that record be processed.&lt;br /&gt;
** put value then process record but don't wait for processing to complete.&lt;br /&gt;
** put value, process record, and wait for completion&lt;br /&gt;
* process link to another record&lt;br /&gt;
** request processing but do not wait for completion&lt;br /&gt;
** request processing and wait for completion&lt;br /&gt;
&lt;br /&gt;
The Wait methods all return LinkWaitResult.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Device Support ==&lt;br /&gt;
&lt;br /&gt;
Other than that it must extend &amp;lt;tt&amp;gt;Support&amp;lt;/tt&amp;gt;,&lt;br /&gt;
nothing is defined for Device support in this document.&lt;br /&gt;
It will be modeled after the V3 asynDriver support.&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
= Registration and Instance Creation =&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     interface StructFactory {&lt;br /&gt;
         DbfStruct create();&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RecordSupportFactory {&lt;br /&gt;
         RecordSupport create(RecordInstance instance);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface SupportFactory {&lt;br /&gt;
         Support create(Dbf field);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     interface RegisterSupport {&lt;br /&gt;
         structure(StructFactory create, string name);&lt;br /&gt;
         record(StructFactory create, string name);&lt;br /&gt;
         link(SupportFactory support,string name);&lt;br /&gt;
         device(SupportFactory support,string name);&lt;br /&gt;
         record(RecordSupportFactory support,string name);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;RegisterSupport&amp;lt;/tt&amp;gt; is implemented by iocCore.&lt;br /&gt;
Each &amp;lt;tt&amp;gt;struct&amp;lt;/tt&amp;gt; DBD definition must register a StructFactory to&lt;br /&gt;
create instances of the structure or record.&lt;br /&gt;
&lt;br /&gt;
Each link, device, and record support must register a SupportFactory to create&lt;br /&gt;
instances of the support to attach to the link, device, or record instance.&lt;br /&gt;
During database initialization, iocCore calls the factory methods.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtime Database Access =&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Database Access, with help from record, link, and device support&lt;br /&gt;
implements the dbdInterfaces.&lt;br /&gt;
Other than Database Access, fields of a record can only&lt;br /&gt;
be accessed via the interfaces described in dbdInterfaces.&lt;br /&gt;
This allows the database to handle&lt;br /&gt;
actions like posting database monitors without any help from&lt;br /&gt;
record, link, or device support.&lt;br /&gt;
&lt;br /&gt;
Database access by default allocates the actual storage for each field&lt;br /&gt;
but allows support code to register itself to manage storage for field&lt;br /&gt;
instances.&lt;br /&gt;
Two examples, both involving arrays, are:&lt;br /&gt;
* The compress record  registers to provide storage for the value.&lt;br /&gt;
** This allows it to implement a circular buffer.&lt;br /&gt;
** Code that accesses the value field may have to issue two get requests.&lt;br /&gt;
* Device support for a transient recorder registers to provide storage for the array&lt;br /&gt;
** This allows device support to read data from hardware in segments&lt;br /&gt;
** Code that accesses the array may have to issue many get requests.&lt;br /&gt;
&lt;br /&gt;
The fact that each field of a record instance is an object means that additional storage is required.&lt;br /&gt;
Database Access  will probably have something like the following:&lt;br /&gt;
&lt;br /&gt;
    class Field {&lt;br /&gt;
        DbRecord instance;&lt;br /&gt;
        short          index;&lt;br /&gt;
    };&lt;br /&gt;
    ...&lt;br /&gt;
    class IntField extends Field {&lt;br /&gt;
        int data;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
This each field has the overhead of&lt;br /&gt;
* instance - a reference to DbRecord, i.e. record instance&lt;br /&gt;
* index - a 16 bit integer&lt;br /&gt;
* vtbl - a reference to the object implementation&lt;br /&gt;
&lt;br /&gt;
Additional fields will be needed for things like monitors.&lt;br /&gt;
These fields can start out null and only allocate storage as needed.&lt;br /&gt;
&lt;br /&gt;
== Database Access ==&lt;br /&gt;
&lt;br /&gt;
     interface DbAccess {&lt;br /&gt;
         void process(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processCancel(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processContinue(RecordInstance instance, Callback callback);&lt;br /&gt;
         void processRequestAccept(Dbf field, boolean yesNo);&lt;br /&gt;
         void registerDbfSource(Dbf field, Dbf source);&lt;br /&gt;
         LinkSupport getLinkSupport(Dbf field);&lt;br /&gt;
         Support getSupport(Dbf field);&lt;br /&gt;
         RecordSupport getRecordSupport(DbInstance instance);&lt;br /&gt;
         RecordSupport getRecordCommonSupport(DbInstance instance);&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
The methods are:&lt;br /&gt;
* &amp;lt;tt&amp;gt;process&amp;lt;/tt&amp;gt; - Request processing. Record must be idle or active or request fails.&lt;br /&gt;
** &amp;lt;tt&amp;gt;instance&amp;lt;/tt&amp;gt; - The record to process&lt;br /&gt;
** &amp;lt;tt&amp;gt;callback&amp;lt;/tt&amp;gt; - A callback to call when processing completes or for failure.&lt;br /&gt;
* &amp;lt;tt&amp;gt;processRequestAccept&amp;lt;/tt&amp;gt; - Should a process request from channel access be accepted,&lt;br /&gt;
* &amp;lt;tt&amp;gt;registerDbfSource&amp;lt;/tt&amp;gt; - Register code that will implement storage for the field.&lt;br /&gt;
* &amp;lt;tt&amp;gt;getLinkSupport&amp;lt;/tt&amp;gt; - Find the link support for a link field&lt;br /&gt;
* &amp;lt;tt&amp;gt;getSupport&amp;lt;/tt&amp;gt; - Get the device support for a device field&lt;br /&gt;
* &amp;lt;tt&amp;gt;getRecordSupport&amp;lt;/tt&amp;gt; - Get the record support for the record&lt;br /&gt;
* &amp;lt;tt&amp;gt;getRecordCommonSupport&amp;lt;/tt&amp;gt; - Get the RecordCommon support for the record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTES&amp;lt;/b&amp;gt; This is just the beginning of defining the methods in DbAccess&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>MartyKraimer</name></author>
	</entry>
</feed>