Difference between revisions of "V4 Design: dbdInterfaces"

From EPICSWIKI
Line 1: Line 1:
= EPICS: dbdInterfaces - IOC Database Description =
= EPICS: dbdInterfaces - IOC Database Description =
August 12 2005  
August 29 2005  


----
----
Line 68: Line 68:
     enum LinkDir {
     enum LinkDir {
         LinkDirNone,
         LinkDirNone,
         LinkDirForward,
         LinkDirProcess,
         LinkDirIn,
         LinkDirIn,
         LinkDirOut,
         LinkDirOut,
         LinkDirInOut
         LinkDirInOut
     };
     }


The C++  definition is identical. In Java 5 the definition would be:
The C++  definition is identical. In Java 5 the definition would be:
Line 78: Line 78:
     public enum LinkDir {
     public enum LinkDir {
         LinkDirNone,
         LinkDirNone,
         LinkDirForward,
         LinkDirProcess,
         LinkDirIn,
         LinkDirIn,
         LinkDirOut,
         LinkDirOut,
Line 90: Line 90:
         float64 low;
         float64 low;
         float64 high;
         float64 high;
     };
     }


In C++ this would be:
In C++ this would be:
Line 105: Line 105:
         public double low;
         public double low;
         public double high;
         public double high;
     };
     }


==== interface ====
==== interface ====
Line 113: Line 113:
         bool get();
         bool get();
         void put(bool val);
         void put(bool val);
     };
     }


In C++ would be:
In C++ would be:
Line 126: Line 126:
         bool get();
         bool get();
         void put(bool val)
         void put(bool val)
     };
     }
==== array ====
==== array ====


Line 158: Line 158:
         int32 getLength();
         int32 getLength();
         octet[] data;
         octet[] data;
     };
     }
      
      
     interface NonmutableStringFactory {
     interface NonmutableStringFactory {
Line 167: Line 167:
         int32 getCapacity();
         int32 getCapacity();
         void setLength(int32 len);
         void setLength(int32 len);
     };
     }
      
      
     interface MutableStringFactory {
     interface MutableStringFactory {
Line 189: Line 189:


     interface DbfConvertScalar {
     interface DbfConvertScalar {
         get(Dbf to, int16 value);
         int16 get(Dbf to);
         get(Dbf to, int32 value);
         int32 get(Dbf to);
         get(Dbf to, int64 value);
         int64 get(Dbf to);
         get(Dbf to, float32 value);
         float32 get(Dbf to);
         get(Dbf to, float64 value);
         float64 get(Dbf to);
         get(Dbf to, int32 len,octet[] value); //value is string
         get(Dbf to, int32 len,octet[] value); //value is string
         get(DbfBool to, int32 len,octet[] value); //value is string
         get(DbfBool to, int32 len,octet[] value); //value is string
Line 214: Line 214:
         put(DbfArray from, float32[] value);
         put(DbfArray from, float32[] value);
         put(DbfArray from, float64[] value);
         put(DbfArray from, float64[] value);
     };
     }


NOTES:
NOTES:
Line 258: Line 258:
         BasicTypeArray,    // DbfArray
         BasicTypeArray,    // DbfArray
         BasicTypeStruct,  // DbfStruct
         BasicTypeStruct,  // DbfStruct
     };
     }


     enum DbfType {
     enum DbfType {
Line 268: Line 268:
         DbfTypeMDArray,    // DbfMDArray
         DbfTypeMDArray,    // DbfMDArray
         DbfTypeTimeStamp    // DbfTimeStamp
         DbfTypeTimeStamp    // DbfTimeStamp
     };
     }




Line 301: Line 301:
         public static final int16 highIndex = 2;
         public static final int16 highIndex = 2;
         public static final int16 lastIndex = indexHigh;
         public static final int16 lastIndex = indexHigh;
     };
     }


In addition code will be generated that implements the following:
In addition code will be generated that implements the following:
Line 323: Line 323:
         ...
         ...
         field(ffloat,float64)
         field(ffloat,float64)
         field(fstring,string)
         field(string,string)
         field(farray,array(double[])
         field(array,array(double[])
         field(fmdarray,array(double[,])
         field(mdarray,array(double[,])
         field(fmenu,menu(name))
         field(menu,menu(name))
         field(fenum,enum)
         field(fenum,enum)
         field(flink,link(in))
         field(link,link(in))
         field(fdevice,link(in,analogIO))
         field(device,link(in,analogIO))
         field(DisplayLimit,struct(DisplayLimit))
         field(displayLimit,struct(DisplayLimit))
     }
     }


Line 336: Line 336:
     class IocRecord {
     class IocRecord {
     public:
     public:
         DbdRecordInstance *base;
         RecordInstance *base;
     };
     };


Line 346: Line 346:
         ...
         ...
         DbfFloat64  *ffloat;
         DbfFloat64  *ffloat;
         DbfString    *fstring;
         DbfString    *string;
         DbfArray    *farray;
         DbfArray    *array;
         DbfMDArray  *fmdarray;
         DbfMDArray  *mdarray;
         DbfMenu      *fmenu;
         DbfMenu      *menu;
         DbfEnum      *fenum;
         DbfEnum      *fenum;
         DbfLink      *flink;
         DbfLink      *link;
         DbfDevice    *fdevice;
         DbfDevice    *device;
         DbfStruct    *displayLimit;
         DbfStruct    *displayLimit;
         static int16 baseIndex = 1;
         static int16 baseIndex = 1;
         static int16 fboolIndex = 2;
         static int16 fboolIndex = 2;
         ...
         ...
         static int16 lastIndex = DisplayLimitIndex;
         static int16 lastIndex = displayLimitIndex;
};
    };


The generated Java file is
The generated Java file is


     class IocRecord {
     class IocRecord {
         public DbdRecordInstance base;
         public RecordInstance base;
     };
     }
     class ExampleRecord extends IocRecord {
     class ExampleRecord extends IocRecord {
         public DbfBool      fbool;
         public DbfBool      fbool;
Line 371: Line 371:
         ...
         ...
         public DbfFloat64  ffloat;
         public DbfFloat64  ffloat;
         public DbfString    fstring;
         public DbfString    string;
         public DbfArray    farray;
         public DbfArray    array;
         public DbfMDArray  fmdarray;
         public DbfMDArray  mdarray;
         public DbfMenu      fmenu;
         public DbfMenu      menu;
         public DbfEnum      fenum;
         public DbfEnum      fenum;
         public DbfLink      flink;
         public DbfLink      link;
         public DbfDevice    fdevice;
         public DbfDevice    device;
         public DbfStruct    DisplayLimit;
         public DbfStruct    displayLimit;
         public static final int16 baseIndex = 1;
         public static final int16 baseIndex = 1;
         public static final int16 fboolIndex = 2;
         public static final int16 fboolIndex = 2;
         ...
         ...
         public static final int16 lastIndex = DisplayLimitIndex;
         public static final int16 lastIndex = displayLimitIndex;
     };
     }


----
----
Line 398: Line 398:
         bool isBasic();
         bool isBasic();
         BasicType getBasicType();
         BasicType getBasicType();
         DbdRecordInstance getRecord();
         RecordInstance getRecord();
         int16 getIndex();
         int16 getIndex();
     };
     }


The interfaces are designed as follows:
The interfaces are designed as follows:
* DbAccess provides storage for fields and never exposes the address of any field.
* DbAccess provides storage for fields and never exposes the address of any field.
* DbAccess notifies Channel Access when an field is modified.
* DbAccess posts monitors when a field is modified.
* Can we just lock individual records rather than lock sets?
** What about deadlock copying from one record to another?


The fact the each field is an object means that additional storage is required.
The fact the each field is an object means that additional storage is required.
Line 413: Line 411:
     class Field {
     class Field {
     public:
     public:
         DbdRecordInstance &instance;
         RecordInstance &instance;
         short            index;
         short            index;
     };
     };
Line 424: Line 422:


This each field has the overhead of
This each field has the overhead of
* instance - a reference to DbdRecordInstance
* instance - a reference to RecordInstance
* index - a 16 bit integer
* index - a 16 bit integer
* vtbl - a reference to the class implementation
* vtbl - a reference to the class implementation
An additional pointer field will be needed for things like monitors.
This field can start out null and only have additional storage as needed.




Line 436: Line 437:
         bool get();
         bool get();
         void put(bool val);
         void put(bool val);
     };
     }
      
      
     interface DbfOctet extends Dbf {
     interface DbfOctet extends Dbf {
         octet get();
         octet get();
         void put(octet val);
         void put(octet val);
     };
     }
      
      
     interface DbfInt16 extends Dbf {
     interface DbfInt16 extends Dbf {
         int16 get();
         int16 get();
         void put(int16 val);
         void put(int16 val);
     };
     }
      
      
     interface DbfInt32 extends Dbf {
     interface DbfInt32 extends Dbf {
         int32 get();
         int32 get();
         void put(int32 val);
         void put(int32 val);
     };
     }
      
      
     interface DbfInt64 extends Dbf {
     interface DbfInt64 extends Dbf {
         int64 get();
         int64 get();
         void put(int64 val);
         void put(int64 val);
     };
     }
      
      
     interface DbfFloat32 extends Dbf {
     interface DbfFloat32 extends Dbf {
         float32 get();
         float32 get();
         void put(float32 val);
         void put(float32 val);
     };
     }
      
      
     interface DbfFloat64 extends Dbf {
     interface DbfFloat64 extends Dbf {
         float64 get();
         float64 get();
         void put(float64 val);
         void put(float64 val);
     };
     }




Line 508: Line 509:
         void setPutSize(int32 size);
         void setPutSize(int32 size);
         void put(int32 len, octet[] string);
         void put(int32 len, octet[] string);
     };
     }


The following code prints a string.
The following code prints a string.


     ExampleRecord *precord;
     ExampleRecord *precord;
     epicsInt32 len = precord->fstring->getLength();
     epicsInt32 len = precord->string->getLength();
     MutableString *pstring = pMutableStringFactory->create(len);
     MutableString *pstring = pMutableStringFactory->create(len);
     ...
     ...
     precord->fstring->get(len,pstring->data);
     precord->string->get(len,pstring->data);
     printf("%.*s\n",len,pstring->data);
     printf("%.*s\n",len,pstring->data);
     pstring->destroy();
     pstring->destroy();
Line 532: Line 533:
         Dbf getInterface(int16 index);
         Dbf getInterface(int16 index);
         DbdField getDescription(int16 index);
         DbdField getDescription(int16 index);
     };
     }


The following traverses the fields of a DbfStruct
The following traverses the fields of a DbfStruct
Line 566: Line 567:
         int32 getNelements();
         int32 getNelements();
         void setNelements(int32 len);
         void setNelements(int32 len);
     };
     }


     interface DbfOctetArray extends DbfArray {
     interface DbfOctetArray extends DbfArray {
         int32 get(int32 offset, int32 len, octet[] pto);
         int32 get(int32 offset, int32 len, octet[] pto);
         int32 put(int32 offset, int32 len, octet[] pfrom);
         int32 put(int32 offset, int32 len, octet[] pfrom);
     };
     }


     interface DbfBoolArray extends DbfArray {
     interface DbfBoolArray extends DbfArray {
         int32 get(int32 offset, int32 len, bool[] pto);
         int32 get(int32 offset, int32 len, bool[] pto);
         int32 put(int32 offset, int32 len, bool[] pfrom);
         int32 put(int32 offset, int32 len, bool[] pfrom);
     };
     }


     interface DbfInt16Array extends DbfArray {
     interface DbfInt16Array extends DbfArray {
         int32 get(int32 offset, int32 len, int16[] pto);
         int32 get(int32 offset, int32 len, int16[] pto);
         int32 put(int32 offset, int32 len, int16[] pfrom);
         int32 put(int32 offset, int32 len, int16[] pfrom);
     };
     }


     interface DbfInt32Array extends DbfArray {
     interface DbfInt32Array extends DbfArray {
         int32 get(int32 offset, int32 len, int32[] pto);
         int32 get(int32 offset, int32 len, int32[] pto);
         int32 put(int32 offset, int32 len, int32[] pfrom);
         int32 put(int32 offset, int32 len, int32[] pfrom);
     };
     }


     interface DbfInt64Array extends DbfArray {
     interface DbfInt64Array extends DbfArray {
         int32 get(int32 offset, int32 len, int64[] pto);
         int32 get(int32 offset, int32 len, int64[] pto);
         int32 put(int32 offset, int32 len, int64[] pfrom);
         int32 put(int32 offset, int32 len, int64[] pfrom);
     };
     }


     interface DbfFloat32Array extends DbfArray {
     interface DbfFloat32Array extends DbfArray {
         int32 get(int32 offset, int32 len, float32[] pto);
         int32 get(int32 offset, int32 len, float32[] pto);
         int32 put(int32 offset, int32 len, float32[] pfrom);
         int32 put(int32 offset, int32 len, float32[] pfrom);
     };
     }


     interface DbfFloat64Array extends DbfArray {
     interface DbfFloat64Array extends DbfArray {
         int32 get(int32 offset, int32 len, float64[] pto);
         int32 get(int32 offset, int32 len, float64[] pto);
         int32 put(int32 offset, int32 len, float64[] pfrom);
         int32 put(int32 offset, int32 len, float64[] pfrom);
     };
     }


     interface DbfStringArray extends DbfArray {
     interface DbfStringArray extends DbfArray {
         DbfString getInterface(int32 index);
         DbfString getInterface(int32 index);
     };
     }


     interface DbfArrayArray extends DbfArray {
     interface DbfArrayArray extends DbfArray {
         DbfArray getInterface(int32 index);
         DbfArray getInterface(int32 index);
     };
     }


     interface DbfStructArray extends DbfArray {
     interface DbfStructArray extends DbfArray {
         DbfStruct getInterface(int32 index);
         DbfStruct getInterface(int32 index);
     };
     }


The following puts data into a float64 field.
The following puts data into a float64 field.
Line 620: Line 621:
     float64 *pdata; // assume this has been allocated somehow
     float64 *pdata; // assume this has been allocated somehow
     int32  nelements; // this is number of elements
     int32  nelements; // this is number of elements
     DbfFloat64Array *parray = dynamic_cast<DbfFloat64Array *>precord->farray;
     DbfFloat64Array *parray = dynamic_cast<DbfFloat64Array *>precord->array;
     ...
     ...
     parray->put(0,nelements,pdata);
     parray->put(0,nelements,pdata);
Line 643: Line 644:
         void putIndex(int16 val);
         void putIndex(int16 val);
         DbdMenu getDbdMenu();
         DbdMenu getDbdMenu();
     };
     }


<tt>DbfMenu</tt> allows the menu index to be set and retrieved
<tt>DbfMenu</tt> allows the menu index to be set and retrieved
Line 659: Line 660:
         void putIndex(int16 val);
         void putIndex(int16 val);
         DbfStringArray getChoiceArray();
         DbfStringArray getChoiceArray();
     };
     }




Line 672: Line 673:
     enum LinkDir {
     enum LinkDir {
         LinkDirNone,
         LinkDirNone,
         LinkDirForward,
         LinkDirProcess,
         LinkDirIn,
         LinkDirIn,
         LinkDirOut,
         LinkDirOut,
         LinkDirInOut
         LinkDirInOut
     };
     }
      
      
     interface DbfLink extends Dbf {
     interface DbfLink extends Dbf {
Line 682: Line 683:
         DbdLink getDbdLink();
         DbdLink getDbdLink();
         LinkSupport support;
         LinkSupport support;
     };
     }
      
      
     interface DbfDevice extends Dbf {
     interface DbfDevice extends Dbf {
Line 688: Line 689:
         DbdDevice getDbdDevice();
         DbdDevice getDbdDevice();
         Support support; // Support is base class for device support
         Support support; // Support is base class for device support
     };
     }


See below for the description of support, which included record, link,
See below for the description of support, which included record, link,
Line 698: Line 699:
         int64 secondsSinceEpoch;
         int64 secondsSinceEpoch;
         int32 nanoSeconds;
         int32 nanoSeconds;
     };
     }


     interface DbfTimeStamp extends Dbf {
     interface DbfTimeStamp extends Dbf {
         void get(TimeStamp timeStamp);
         void get(TimeStamp timeStamp);
         void put(TimeStamp timeStamp);
         void put(TimeStamp timeStamp);
     };
     }


----
----
Line 724: Line 725:
         int32 getChoiceLength(int16 index);
         int32 getChoiceLength(int16 index);
         void getChoice(int16 index,int32 len,octet[] data);
         void getChoice(int16 index,int32 len,octet[] data);
     };
     }




Line 737: Line 738:
         int32 getDataStructNameLength();
         int32 getDataStructNameLength();
         void getDataStructName(int32 len,octet[] data);
         void getDataStructName(int32 len,octet[] data);
     };
     }
      
      
     interface DbdLink extends DbdSupport{
     interface DbdLink extends DbdSupport{
         LinkSupport create(DbfLink link);
         LinkSupport create(DbfLink link);
     };
     }
      
      
     interface DbdDevice extends DbdSupport{
     interface DbdDevice extends DbdSupport{
Line 747: Line 748:
         void getInterfaceName(int32 len,octet[] data);
         void getInterfaceName(int32 len,octet[] data);
         Support  create(DbfDevice device);
         Support  create(DbfDevice device);
     };
     }
      
      
=== <tt>DbdStruct</tt> and <tt>DbdRecord</tt> ===
=== <tt>DbdStruct</tt> and <tt>DbdRecord</tt> ===
Line 758: Line 759:
         bool isSpecial();
         bool isSpecial();
         int16 getAsl();
         int16 getAsl();
     };
     }
      
      
     interface DbdDefaults {};
     interface DbdDefaults {}
      
      
     interface DbdArrayDefaults extends DbdDefaults{
     interface DbdArrayDefaults extends DbdDefaults{
Line 768: Line 769:
     interface DbdStructDefaults extends DbdDefaults{
     interface DbdStructDefaults extends DbdDefaults{
         DbdStruct getDescription();
         DbdStruct getDescription();
     };
     }


     interface DbdField {
     interface DbdField {
Line 776: Line 777:
         DbdDefaults getDefaults();
         DbdDefaults getDefaults();
         DbdAttribute getAttributes();
         DbdAttribute getAttributes();
     };
     }


     interface DbdStruct {
     interface DbdStruct {
Line 784: Line 785:
         DbdField getFieldDescription(int16 index);
         DbdField getFieldDescription(int16 index);
         DbdStructLifetime getLifetime();
         DbdStructLifetime getLifetime();
     };
     }


     interrface DbdRecord {
     interrface DbdRecord {
Line 794: Line 795:
         DbdRecordSupport getSupport();
         DbdRecordSupport getSupport();
         DbdRecordLifetime getLifetime();
         DbdRecordLifetime getLifetime();
     };
     }


     interface DbdLocate
     interface DbdLocate
Line 802: Line 803:
         DbdStruct getStruct(int32 len,octet[] name);
         DbdStruct getStruct(int32 len,octet[] name);
         DbdRecord getRecord(int32 len,octet[] name);
         DbdRecord getRecord(int32 len,octet[] name);
     };
     }
 
 
----
<center>
 
== Run Time Interfaces ==


   
</center>
=== Record Instance ===
=== Record Instance ===


     interface DbdRecordInstance {
     interface RecordAccess {
         DbdRecord getDescription();
         RecordSupport getRecordSupport();
        Dbf &getField(int16 index);
    }
 
    interface RecordInstance {
         int32 getNameLength();
         int32 getNameLength();
         void getName(int32 len,octet[] data);
         void getName(int32 len,octet[] data);
         IocRecord getReference();
         DbdRecord getDescription();
     };
        RecordAccess getRecordAccess();
        WHAT ABOUT iocRecord???
     }


     interface DbdAddr {
     interface DbdAddr {
         void    destroy();  // call this when done with DbAddr
         void    destroy();  // call this when done with DbAddr
         DbfType getType();
         DbfType getType();
         DbdRecordInstance getInstance();
         RecordInstance getInstance();
         int16 getIndex();
         int16 getIndex();
         void  getField(int32 len,octet[] field);
         void  getField(int32 len,octet[] field);
     };
     }


     interface LocateInstance{
     interface LocateInstance{
Line 837: Line 850:
         device(SupportFactory support,int32 len,octet[] name);
         device(SupportFactory support,int32 len,octet[] name);
         record(SupportFactory support,int32 len,octet[] name);
         record(SupportFactory support,int32 len,octet[] name);
     };
     }


     interface SupportFactory {
     interface SupportFactory {
         Support create(Dbf field);
         Support create(Dbf field);
     };
     }


<tt>RegisterSupport</tt> is implemented by iocCore. Each support
<tt>RegisterSupport</tt> is implemented by iocCore. Each support
Line 856: Line 869:
         void connect();
         void connect();
         void disconnect();
         void disconnect();
     };
     }


<tt>Support is the base class for all link and device support.
<tt>Support is the base class for all link and device support.
Line 902: Line 915:


==== Record Support ====
==== Record Support ====
    // Each record type implements RecordFactory
    interface RecordFactory {
        RecordAccess create(RecordInstance instance);
        void destroy(RecordAccess access);
    }


     enum processState {
     enum processState {
Line 909: Line 928:
         processOutputActive,
         processOutputActive,
         processDone
         processDone
     };
     }
 


     interface RecordSupport extends Support{
     interface RecordSupport {
         void destroy();
         void destroy();
         void initialize();
         void initialize();
         processState process(processState state);
         processState process(processState state);
         void special(bool after,Dbf field);
         void special(bool after,Dbf field);
     };
     }
 
==== Database Access ====


    interface DbAccess {
        void process(RecordInstance instance);
    }


----
----

Revision as of 12:27, 29 August 2005

EPICS: dbdInterfaces - IOC Database Description

August 29 2005


Overview

This document describes definitions for code that accessses IOC records, i.e. the records created from Database Definitions. The definitions are intended for code that:

  • includes header files generated from dbd definitions. Header files are generated from the following dbd definitions:
    • record - Should only be included by record support.
    • struct - Included by code that understands the struct.
    • menu - Included by code that understands the menu.
  • does not include the header files.

Syntax

The syntax is defined so that it is easy to provide C++ and Java definitions.

NOTE: Most of the code fragments use C++ syntax.

Primitive Types

  • bool - a value that takes the values true or false
  • octet - an 8 bit byte
  • int16 - a 16 bits signed integer
  • int32 - a 32 bit signed integer
  • int64 - a 64 bit signed integer
  • float32 - a 32 bit IEEE float
  • float64 - a 64 bit IEEE float

In Java these types become:

  • bool => bool
  • octet => byte BUT no arithmetic is implied
  • int16 => short
  • int32 => int
  • int64 => long
  • float32 => float
  • float64 => double

In C++ these types become:

  • bool => bool
  • octet => char BUT no arithmetic is implied
  • int16 => short
  • int32 => int
  • int64 => long long
  • float32 => float
  • float64 => double

NOTES:

  • C++ may require something else to handle the integer types
  • Exceptions must be defined. TBD

enum, struct, interface, array

In adition to the primitive types the syntax uses the terms enum, struct, interface, and array.

enum

An example of an enum is:

    enum LinkDir {
        LinkDirNone,
        LinkDirProcess,
        LinkDirIn,
        LinkDirOut,
        LinkDirInOut
    }

The C++ definition is identical. In Java 5 the definition would be:

    public enum LinkDir {
        LinkDirNone,
        LinkDirProcess,
        LinkDirIn,
        LinkDirOut,
        LinkDirInOut
    };

struct

An example of a struct definition is:

    struct DisplayLimitData {
        float64 low;
        float64 high;
    }

In C++ this would be:

   class DisplayLimitData {
   public:
        double low;
        double high;
    };

In Java this would be:

    class DisplayLimitData {
        public double low;
        public double high;
    }

interface

An example of an interface definition is:

    interface DbfBool extends Dbf {
        bool get();
        void put(bool val);
    }

In C++ would be:

    class DbfBool : public Dbf {
    public:
        virtual bool get() = 0;
        virtual void put(bool val) = 0;
    };

In Java would be:

    interface DbfBool extends Dbf {
        bool get();
        void put(bool val)
    }

array

An example of a definition that includes an array is:

    void get(int32 len,octet[] data);

In C++ ,this would become:

    void get(int len, char data[]);

In Java this would be:

    void get(int len, byte[] data);

support for strings and arrays

string support

The string support is only needed for C++. The Java implementation can just use String wherever NonmutableString or MutableString appear.

The following interfaces are for allocating tempory storage for strings:

    interface NonmutableString {
       void destroy(); // Call this when done with string
       int32 getLength();
       octet[] data;
    }
   
    interface NonmutableStringFactory {
        NonmutableString create(int32 len,octet[] data);
    }
    interface MutableString extends NonmutableString {
       int32 getCapacity();
       void setLength(int32 len);
    }
   
    interface MutableStringFactory {
        MutableString create(int32 int32 capacity);
    }

These will use free lists to manage the storage for the octet arrays.

array support

This is only needed for C++. Java already provides an analogous facility.

    // ArrayCopy only works on primitive types
    interface ArrayCopy {
        copy(DbfArray from,DbfArray to);
    }

This only supports primitive types, i.e. DbfBool,...,DbfFloat64.

Arithmetic Type Conversions

    interface DbfConvertScalar {
        int16 get(Dbf to);
        int32 get(Dbf to);
        int64 get(Dbf to);
        float32 get(Dbf to);
        float64 get(Dbf to);
        get(Dbf to, int32 len,octet[] value); //value is string
        get(DbfBool to, int32 len,octet[] value); //value is string
        put(Dbf from, int16 value);
        put(Dbf from, int32 value);
        put(Dbf from, int64 value);
        put(Dbf from, float32 value);
        put(Dbf from, float64 value);
        put(Dbf from, int32 len,octet[] value); //value is string
        put(DbfBool from, int32 len,octet[] value); //value is string
        get(DbfArray to, int16[] value);
        get(DbfArray to, int32[] value);
        get(DbfArray to, int64[] value);
        get(DbfArray to, float32[] value);
        get(DbfArray to, float64[] value);
        put(DbfArray from, int16[] value);
        put(DbfArray from, int32[] value);
        put(DbfArray from, int64[] value);
        put(DbfArray from, float32[] value);
        put(DbfArray from, float64[] value);
    }

NOTES:

  • For Dbf to and from must be one of DbfInt16, ..., DbfFloat64
  • The get to a string uses printf semantics
  • The put from a string value just uses scanf semantics.
  • The DbfBool method supports all the choices specified in the DBD Record Instance Specification
  • For DbfArray tt>to and from must be an array of one of DbfInt16, ..., DbfFloat64

DbfTypes

The following naming conventions are used:

Dbf
any class starting with Dbf describes a field in a generated header file. For example DbfArray describes a field generated from field(name,array(float64[]).
Dbd
A class name starting with Dbd describes something related to dbd definitions. For example DbdLinkSupport describes a dbd link definition.

All Dbf and Dbd definitions are interfaces. Thus all access to data is via interfaces. The IOC database implements the interfaces, with help from record, link, and device support. After initialization data can only be accessed via the interfaces. This allows the database to handle actions like posting database monitors without any help from record, link, or device support.

DbfTypes.h

The following enum definitions describe each field in the header files generated from DBD struct and record definitions.

    enum BasicType {
        BasicTypeBool,     // DbfBool
        BasicTypeOctet,    // DbfOctet
        BasicTypeInt16,    // DbfInt16
        BasicTypeInt32,    // DbfInt32
        BasicTypeInt64,    // DbfInt64
        BasicTypeFloat32,  // DbfFloat32
        BasicTypeFloat64,  // DbfFloat64
        BasicTypeString,   // DbfString
        BasicTypeArray,    // DbfArray
        BasicTypeStruct,   // DbfStruct
    }
    enum DbfType {
        DbfTypeBasic,       // DbfBool,...,DbfStruct
        DbfTypeMenu,        // DbfMenu
        DbfTypeEnum,        // DbfEnum
        DbfTypeLink,        // DbfLink
        DbfTypeDevice,      // DbfDevice
        DbfTypeMDArray,     // DbfMDArray
        DbfTypeTimeStamp    // DbfTimeStamp
    }


Discussion of DbfTypes

The following shows the code generated from DBD files:

structure definitions

If a structure is defined as:

    struct(DisplayLimit) {
        field(low,double)
        field(high,double)
    }

Then the generated C++ header file will be

    class DisplayLimit {
    public:
        DbfFloat64 *low;
        DbfFloat64 *high;
        static int16 lowIndex = 1;
        static int16 highIndex = 2;
        static int16 lastIndex = highIndex;
    };

The generated Java file is

    class DisplayLimit {
        public DbfFloat64 low;
        public DbfFloat64 high;
        public static final int16 lowIndex = 1;
        public static final int16 highIndex = 2;
        public static final int16 lastIndex = indexHigh;
    }

In addition code will be generated that implements the following:

    struct DisplayLimitData {
        float64 low;
        float64 high;
    }
    interface DisplayLimitAccess{
        void get(DbfStruct, DisplayLimitData data);
        void put(DbfStruct, DisplayLimitData data);
    }

record definitions

If a record is defined as:

    record(Example) extends IocRecord {
        ...
        field(fbool,bool)
        field(foctet,octet)
        field(fint,int16)
        ...
        field(ffloat,float64)
        field(string,string)
        field(array,array(double[])
        field(mdarray,array(double[,])
        field(menu,menu(name))
        field(fenum,enum)
        field(link,link(in))
        field(device,link(in,analogIO))
        field(displayLimit,struct(DisplayLimit))
    }

Then the generated C++ header file will be

    class IocRecord {
    public:
        RecordInstance *base;
    };
    class ExampleRecord : public IocRecord {
    public:
        DbfBool      *fbool;
        DbfOctet     *foctet;
        DbfInt16     *fint;
        ...
        DbfFloat64   *ffloat;
        DbfString    *string;
        DbfArray     *array;
        DbfMDArray   *mdarray;
        DbfMenu      *menu;
        DbfEnum      *fenum;
        DbfLink      *link;
        DbfDevice    *device;
        DbfStruct    *displayLimit;
        static int16 baseIndex = 1;
        static int16 fboolIndex = 2;
        ...
        static int16 lastIndex = displayLimitIndex;
    };

The generated Java file is

    class IocRecord {
        public RecordInstance base;
    }
    class ExampleRecord extends IocRecord {
        public DbfBool      fbool;
        public DbfOctet     foctet;
        public DbfInt16     fint;
        ...
        public DbfFloat64   ffloat;
        public DbfString    string;
        public DbfArray     array;
        public DbfMDArray   mdarray;
        public DbfMenu      menu;
        public DbfEnum      fenum;
        public DbfLink      link;
        public DbfDevice    device;
        public DbfStruct    displayLimit;
        public static final int16 baseIndex = 1;
        public static final int16 fboolIndex = 2;
        ...
        public static final int16 lastIndex = displayLimitIndex;
    }

Database Fields

Each database field is accessed via an interface which all extend the following interface:

    interface Dbf{
        bool isPrimitive(); // BasicTypeBool,...,BasicTypeFloat64
        bool isBasic();
        BasicType getBasicType();
        RecordInstance getRecord();
        int16 getIndex();
    }

The interfaces are designed as follows:

  • DbAccess provides storage for fields and never exposes the address of any field.
  • DbAccess posts monitors when a field is modified.

The fact the each field is an object means that additional storage is required. DbAccess will probably have something like the following:

   class Field {
   public:
       RecordInstance &instance;
       short             index;
   };
   ...
   class IntField : public Field {
   public:
       int data;
   }
   ...

This each field has the overhead of

  • instance - a reference to RecordInstance
  • index - a 16 bit integer
  • vtbl - a reference to the class implementation

An additional pointer field will be needed for things like monitors. This field can start out null and only have additional storage as needed.


Primitive Types

DbfOctet, ..., DbfFloat64 are all interfaces with methods get and put.

    interface DbfBool extends Dbf {
        bool get();
        void put(bool val);
    }
   
    interface DbfOctet extends Dbf {
        octet get();
        void put(octet val);
    }
   
    interface DbfInt16 extends Dbf {
        int16 get();
        void put(int16 val);
    }
   
    interface DbfInt32 extends Dbf {
        int32 get();
        void put(int32 val);
    }
   
    interface DbfInt64 extends Dbf {
        int64 get();
        void put(int64 val);
    }
   
    interface DbfFloat32 extends Dbf {
        float32 get();
        void put(float32 val);
    }
   
    interface DbfFloat64 extends Dbf {
        float64 get();
        void put(float64 val);
    }


Record support code can access such fields via the generated header file. Some examples are:

    ExampleRecord *precord;
    short myint;
    ...
    precord->ffloat->put(10.0);
    ...
    myint = precord->fint->get();

Code that does not include the generated header file can access these fields via the introspecion interfaces described later in this document. For example code that expects a float64 field can access it via

    char *name = "recordname.value";
    int32 len = strlen(name);
    DbdAddr *pDbdAddr;
    DbfFloat64 *pfield;
    ...
    
    pDbdAddr = pLocateInstance->getPV(len,name);
    if(!pDbdAddr || (pDbdAddr->getType != DbfTypeFloat64)) // do SOMETHING
    pfield = dynamic_cast<DbfFloat64 *>pDbdAddr->getAddr();
    pfield->put(10.0);

Instead of the last three lines, DbfConvert could be called.

    pDbfConvert->put(pDbdAddr->getAddr,10.0);
    

String fields

The interface for a string field is:

    interface DbfString extends Dbf {
       int32 getLength();
       void get(int32 len, octet[] string);
       void setPutSize(int32 size);
       void put(int32 len, octet[] string);
    }

The following code prints a string.

    ExampleRecord *precord;
    epicsInt32 len = precord->string->getLength();
    MutableString *pstring = pMutableStringFactory->create(len);
    ...
    precord->string->get(len,pstring->data);
    printf("%.*s\n",len,pstring->data);
    pstring->destroy();

Code that does not include the header file can use the introspection methods to locate the DbfString that provides access to the field.

NOTES:

  • Does record support have to have any say in how DbAccess manages storage for strings? I don't think so.

Structure Fields

    interface DbfStruct extends Dbf {
        int16 getNfields();
        Dbf getInterface(int16 index);
        DbdField getDescription(int16 index);
    }

The following traverses the fields of a DbfStruct

    DbfStruct *pDbfStruct;
    MutableString *pMutableString;
    
    for(i=0; t< pDbfStruct->getNfields(); i++) {
        DbdField *pDbdField = pDbfStruct->getDescription(i);
        int len = pDbdField->getNameLength();
        MutableString *pname = pMutableStringFactory->create(len);
        pDbdField->getName(len,pname);
        DbfType type = pDbdField->getType();
        printf("field %s type %d\n",pname->data,type);
        pname->destroy();
    }


Structure fields can only be accessed via introspection. However, for each structure, code is generated that does the introspection. For example DisplayLimitData can be obtained via the statements:

    ExampleRecord *precord;
    DisplayLimitData limits;
    
    ...
    pDisplayLimitAccess->get(precord->displayLimit,limits);
    printf("low %f high %f\n",limits.low,limits.high);

Array Fields

    interface DbfArray extends Dbf {
       DbfType getType();
       int32 getNelements();
       void setNelements(int32 len);
    }
    interface DbfOctetArray extends DbfArray {
       int32 get(int32 offset, int32 len, octet[] pto);
       int32 put(int32 offset, int32 len, octet[] pfrom);
    }
    interface DbfBoolArray extends DbfArray {
       int32 get(int32 offset, int32 len, bool[] pto);
       int32 put(int32 offset, int32 len, bool[] pfrom);
    }
    interface DbfInt16Array extends DbfArray {
       int32 get(int32 offset, int32 len, int16[] pto);
       int32 put(int32 offset, int32 len, int16[] pfrom);
    }
    interface DbfInt32Array extends DbfArray {
       int32 get(int32 offset, int32 len, int32[] pto);
       int32 put(int32 offset, int32 len, int32[] pfrom);
    }
    interface DbfInt64Array extends DbfArray {
       int32 get(int32 offset, int32 len, int64[] pto);
       int32 put(int32 offset, int32 len, int64[] pfrom);
    }
    interface DbfFloat32Array extends DbfArray {
       int32 get(int32 offset, int32 len, float32[] pto);
       int32 put(int32 offset, int32 len, float32[] pfrom);
    }
    interface DbfFloat64Array extends DbfArray {
       int32 get(int32 offset, int32 len, float64[] pto);
       int32 put(int32 offset, int32 len, float64[] pfrom);
    }
    interface DbfStringArray extends DbfArray {
        DbfString getInterface(int32 index);
    }
    interface DbfArrayArray extends DbfArray {
        DbfArray getInterface(int32 index);
    }
    interface DbfStructArray extends DbfArray {
        DbfStruct getInterface(int32 index);
    }

The following puts data into a float64 field.

    ExampleRecord *precord;
    float64 *pdata; // assume this has been allocated somehow
    int32   nelements; // this is number of elements
    DbfFloat64Array *parray = dynamic_cast<DbfFloat64Array *>precord->array;
    ...
    parray->put(0,nelements,pdata);


NOTES:

  • It must be possible for support to provide an implementation of get and put. It must be possible to do this in segments. For example
    • A circular buffer requires two segments
    • If the memory is in hardware, the support can read/write the data in segments. Transient recorders are an example.
  • If support implements get and put then DbAccess does NOT manage storage but just calls support to get/put data.

DbfMDArray

NOT YET DEFINED


DbfMenu

DbfMenu is described as:

    interface DbfMenu extends Dbf {
        int16 getIndex();
        void putIndex(int16 val);
        DbdMenu getDbdMenu();
    }

DbfMenu allows the menu index to be set and retrieved and also provides access to the DbdMenu.

A DbfMenu field can be accessed via the generated header file or via the introspection methods.


DbfEnum

DbfEnum is described as:

    interface DbfEnum extends Dbf {
        int16 getIndex();
        void putIndex(int16 val);
        DbfStringArray getChoiceArray();
    }


DbfEnum allows the enum index to be set and retrieved and also provides access to the The DbfArray field that contains the choices.

DbfLink and DbfDevice

DbfLink is described as

    enum LinkDir {
        LinkDirNone,
        LinkDirProcess,
        LinkDirIn,
        LinkDirOut,
        LinkDirInOut
    }
   
    interface DbfLink extends Dbf {
        LinkDir getDir();
        DbdLink getDbdLink();
        LinkSupport support;
    }
   
    interface DbfDevice extends Dbf {
        LinkDir getDir();
        DbdDevice getDbdDevice();
        Support support; // Support is base class for device support
    }

See below for the description of support, which included record, link, and device support.

DbfTimeStamp

    struct TimeStamp {
        int64 secondsSinceEpoch;
        int32 nanoSeconds;
    }
    interface DbfTimeStamp extends Dbf {
        void get(TimeStamp timeStamp);
        void put(TimeStamp timeStamp);
    }

DbdStatements

These describe everything defined in database definition files.

In the definitions:


DbdMenu

    interface DbdMenu {
        int32 getNameLength();
        void getName(int32 len,octet[] data);
        int16 getNchoices();
        int32 getChoiceLength(int16 index);
        void getChoice(int16 index,int32 len,octet[] data);
    }


DbdLink and DbdDevice

    interface DbdSupport {
        LinkDir getDir();
        int32 getChoiceNameLength();
        void getChoiceName(int32 len,octet[] data);
        int32 getSupportNameLength();
        void getSupportName(int32 len,octet[] data);
        int32 getDataStructNameLength();
        void getDataStructName(int32 len,octet[] data);
    }
   
    interface DbdLink extends DbdSupport{
        LinkSupport create(DbfLink link);
    }
   
    interface DbdDevice extends DbdSupport{
        int32 getInterfaceNameLength();
        void getInterfaceName(int32 len,octet[] data);
        Support  create(DbfDevice device);
    }
   

DbdStruct and DbdRecord

    interface DbdAttribute {
        int32 getDefaultLength();
        void getDefault(int32 len,octet[] data);
        bool isReadonly();
        bool isDesign();
        bool isSpecial();
        int16 getAsl();
    }
   
    interface DbdDefaults {}
   
    interface DbdArrayDefaults extends DbdDefaults{
        DbfType getType();
        int32 getLength();
    interface DbdStructDefaults extends DbdDefaults{
        DbdStruct getDescription();
    }
    interface DbdField {
        int32 getNameLength();
        void getName(int32 len,octet[] data);
        DbfType getType();
        DbdDefaults getDefaults();
        DbdAttribute getAttributes();
    }
    interface DbdStruct {
        int32 getNameLength();
        void getName(int32 len,octet[] data);
        int16 getNumberFields();
        DbdField getFieldDescription(int16 index);
        DbdStructLifetime getLifetime();
    }
    interrface DbdRecord {
        // Need list of instances
        int32 getNameLength();
        void getName(int32 len,octet[] data);
        int16 getNumberFields();
        DbdField getFieldDescription(int16 index);
        DbdRecordSupport getSupport();
        DbdRecordLifetime getLifetime();
    }
    interface DbdLocate
        DbdMenu getMenu(int32 len,octet[] name);
        DbdLink getLink(int32 len,octet[] name);
        DbdDevice getDevice(int32 len,octet[] name);
        DbdStruct getStruct(int32 len,octet[] name);
        DbdRecord getRecord(int32 len,octet[] name);
    }



Run Time Interfaces

Record Instance

    interface RecordAccess {
        RecordSupport getRecordSupport();
        Dbf &getField(int16 index);
    }
    interface RecordInstance {
        int32 getNameLength();
        void getName(int32 len,octet[] data);
        DbdRecord getDescription();
        RecordAccess getRecordAccess();
        WHAT ABOUT iocRecord???
    }
    interface DbdAddr {
        void    destroy();  // call this when done with DbAddr
        DbfType getType();
        RecordInstance getInstance();
        int16 getIndex();
        void  getField(int32 len,octet[] field);
    }
    interface LocateInstance{
        DbdAddr getPV(int32 len,octet[] pvname);
        DbdAddr getField(int32 lenrecord,octet[] record,
                         int32 lenfield,octet[] field);
    }


Record, Link, Device Support

Registration and Instance Creation

    interface RegisterSupport {
        link(SupportFactory support,int32 len,octet[] name);
        device(SupportFactory support,int32 len,octet[] name);
        record(SupportFactory support,int32 len,octet[] name);
    }
    interface SupportFactory {
        Support create(Dbf field);
    }

RegisterSupport is implemented by iocCore. Each support implementation must register a "factory" for creating new instances to attach to database records (record support) or to database fields (link and device support). During database initialization, iocCore cxalls the factory methods.

Link/Device Base

    interface Support { // base for Link and Device support
        void report(int16 level);
        void destroy();
        void initialize();
        void connect();
        void disconnect();
    }

Support is the base class for all link and device support. An instance of this is connected to each DbfLink or DbfDevice field. The methods are:

  • report - report
  • destroy - This is called if the field is being changed after initialization or if the record is being removed.
  • initialize - Called to initialize a link.
  • connect - Called to connect. Note that this is different than initilization.
  • disconnect - disconnect.

Link Support

    interface Callback {
        void done();
        void timedout();
    }
    interface LinkSupport extends Support {
        void get(Dbf field);
        void getWait(Dbf field,bool process, double timeout,Callback callback);
        void put(Dbf field, bool process);
        void putWait(Dbf field,bool process, double timeout,Callback callback);
        void process();
        void processWait(double timeout,Callback callback);
    }

LinkSupport supports the following semantics:

  • Input Link from another record
    • get current value independent of processing state.
    • Ask the record to process and wait for completion before fetching value.
    • wait until next time record processes then get value. No request is made to process the record.
  • Output Link to another record
    • put value without requesting that record be processed.
    • put value then process record but don't wait for processing to complete.
    • put value, process record, and wait for completion
  • process link to another record
    • request processing but do not wait for completion
    • request processing and wait for completion


Device Support

Other than that it must extend Support, nothing is defined for Device support in this document. It will be modeled after the V3 asynDriver support.

Record Support

   // Each record type implements RecordFactory
    interface RecordFactory {
        RecordAccess create(RecordInstance instance);
        void destroy(RecordAccess access);
    }
    enum processState {
        processIdle,
        processInputActive,
        processActive,
        processOutputActive,
        processDone
    }


    interface RecordSupport {
        void destroy();
        void initialize();
        processState process(processState state);
        void special(bool after,Dbf field);
    }

Database Access

    interface DbAccess {
        void process(RecordInstance instance);
    }