Difference between revisions of "V4 Design: dbdClass"

From EPICSWIKI
Line 1: Line 1:
== EPICS: C++ class definitions for Database Definition ==
May 24 2005
 
May 18 2005


<center>
<center>
Line 19: Line 17:


The following headers files are described:
The following headers files are described:
* <tt>epicsTypes.h</tt> - A set of primitive types that are part of <tt>base/src/libCom</tt>
* <tt>dbfTypes.h</tt> - Type definitions for <tt>field</tt> definitions in <tt>struct</tt> or <tt>record></tt> DBD definitions.
* <tt>dbdTypes.h</tt> - Type definitions for <tt>field</tt> definitions in <tt>struct</tt> or <tt>record></tt> DBD definitions.
* <tt>dbdStatements.h</tt>  - Type definitions for DBD statements.
* <tt>dbdStatements.h</tt>  - Type definitions for DBD statements.
* <tt>dbdInterfaces.h</tt> - Type definitions for interfaces related to DBD definitions.
* <tt>dbdInterfaces.h</tt> - Type definitions for interfaces related to DBD definitions.
Line 27: Line 24:
<center>
<center>


== epicsTypes ==
== dbfTypes ==
 
  </center>
  </center>
=== <tt>epicsTypes.h</tt> ===
<tt>epicsTypes.h</tt> defines a set of primitive tupes. It is used because the <tt>C99</tt> standard does not define the exact number of bits for the primitive data types. It only defines the minimum number of bits.


In addition two extra types are defined:
File <tt>dbfTypes.h</tt> describes types and classes that are used
* <tt>epicsUnknownT</tt> - Unknown
in header files generated from
* <tt>epicsOctetT</tt> - An 8 bit byte.
dbd <tt>struct</tt> or <tt>record</tt> field definitions.
 
<tt>epicsTypes.h</tt> contains the following:
 
enum epicsType {
    epicsUnknownT,
    epicsBooleanT,
    epicsOctetT,
    epicsInt16T,
    epicsUInt16T,
    epicsInt32T,
    epicsUInt32T,
    epicsInt64T,
    epicsUInt64T,
    epicsFloat32T,
    epicsFloat64T,
};
 
/* some of the following may require OSD definitions*/
typedef bool              epicsBoolean;
typedef char              epicsOctet;
typedef short              epicsInt16;
typedef unsigned short    epicsUInt16;
typedef int                epicsInt32;
typedef unsigned int      epicsUInt32;
typedef long long          epicsInt64;
typedef unsigned long long epicsUInt64;
typedef float              epicsFloat32;
typedef double            epicsFloat64;
 
=== Discussion of epicsTypes ===
 
 
Each epicsType maps to a C++ primitive type.
It may be necessary to provide operating system dependent definitions for some of the types. For example on some architectures a epicsInt64 may have to be defined as a <tt>long</tt> rather than a <tt>long long</tt>.
 
<tt>epicsTypeUnknownT</tt> is reserved for unknown types and will normally be caused by a configuration error.
 
----
<center>
 
== dbdTypes ==
</center>


File <tt>dbdTypes.h</tt> describes types and classes related to
dbd <tt>struct</tt> or <tt>record</tt> field definitions.
The following naming conventions are used:
The following naming conventions are used:
; dbf
: A primitive field type
; Dbf
; Dbf
: any class starting with Dbf describes a non-primitive struct or record field. For example DbfString describes a field(name,string).
: any class starting with Dbf describes a non-primitive struct or record field. For example EpicsString describes a field(name,string).
; *Dbd*
; *Dbd*
: A class name that has Dbd imbeded in it describes something directly related to a dbd statement. For example LinkDbdSupport describes a dbd link definition.
: A class name that has Dbd imbeded in it describes something directly related to a dbd statement. For example LinkDbdSupport describes a dbd link definition.
Line 91: Line 39:
=== <tt>dbdTypes.h</tt> ===
=== <tt>dbdTypes.h</tt> ===
  enum dbfType {
  enum dbfType {
     dbfUnknownT = epicsUnknownT,
     dbfUnknownT,
     dbfBooleanT = epicsBooleanT,
     dbfEpicsT, // an epicsType except epicsUnknownT
    dbfOctetT = epicsOctetT,
     dbfArrayT,
    dbfInt16T = epicsInt16T,
    dbfUInt16T = epicsUInt16T,
    dbfInt32T = epicsInt32T,
    dbfUInt32T = epicsUInt32T,
    dbfInt64T = epicsInt64T,
    dbfUInt64T = epicsUInt64T,
    dbfFloat32T = epicsFloat32T,
    dbfFloat64T = epicsFloat64T,
     dbfStringT,
     dbfStructT,
     dbfStructT,
     dbfArrayT,
     dbfMenuT,
     dbfEnumT,
     dbfEnumT,
    dbfMenuT,
     dbfLinkT,
     dbfLinkT,
     dbfDeviceT
     dbfDeviceT
  };
  };


typedef epicsBoolean  dbfBoolean;
  class ArrayDbdDef; //describes a dbd array definition
typedef epicsOctet    dbfOctet;
typedef epicsInt16    dbfInt16;
typedef epicsUInt16  dbfUInt16;
typedef epicsInt32    dbfInt32;
typedef epicsUInt32  dbfUInt32;
typedef epicsInt64    dbfInt64;
typedef epicsUInt64  dbfUInt64;
typedef epicsFloat32  dbfFloat32;
typedef epicsFloat64  dbfFloat64;
 
// StructDbd is base class for classes implementing struct
  class StructDbd {};
// The following are described  in dbdStatements.h
  class StructDbdDef; //describes a dbd struct definition
  class StructDbdDef; //describes a dbd struct definition
  class MenuDbdDef; //describes a dbd menu definition
  class MenuDbdDef; //describes a dbd menu definition
Line 130: Line 55:
  class DeviceDbd;  //describes dbd device statement
  class DeviceDbd;  //describes dbd device statement


  /*DbfString holds UTF-8 characters*/
  // If array type is a known epicsType then EpicsArray
  class DbfString {
  class DbfArray : public EpicsArray {
public:
    dbfInt32  capacity;  /*capacity in bytes*/
    dbfBoolean isCharString;
    dbfOctet  *pstorage;
};
 
class DbfStruct{
  public:
  public:
     StructDbdDef *pstructDef;
     dbfType dbftype;
    StructDbd    *pstorage;
  };
  };


  class DbfArray {
// If every field is a known epicsType then EpicsStruct
  class DbfStruct {
  public:
  public:
     dbfInt32  capacity;  /*capacity in number of elements*/
     StructDbdDef *pStructDbdDef;
    dbfInt32  size;     /*current number of elements*/
     void         *pstorage;
    dbfType  type; // can be dbfBooleanT, ..., dbfArrayT
     void     *pstorage; // aligned on natural boundary
  };
  };


  class DbfMenu{
  class DbfMenu{
  public:
  public:
     dbfInt16   index;
     epicsInt16   index;
     MenuDbdDef  *pmenuDef; /* address of global menu */
     MenuDbdDef  *pmenuDef; /* address of global menu */
  };
  };
Line 160: Line 76:
  class DbfEnum{
  class DbfEnum{
  public:
  public:
     dbfInt16 index;
     epicsInt16 index;
     DbfArray  *pchoiceArray; // addr of field that is DbfArray on choices
     DbfArray  *pchoiceArray; // addr of field that is DbfArray on choices
  };
  };
Line 176: Line 92:
     LinkDir  dir;
     LinkDir  dir;
     LinkDbd  *plinkDef;
     LinkDbd  *plinkDef;
     DbfStruct dataStruct;
     EpicsStruct dataStruct;
  };
  };


Line 183: Line 99:
     LinkDir  dir;
     LinkDir  dir;
     DeviceDbd *pdeviceDef;
     DeviceDbd *pdeviceDef;
     DbfStruct dataStruct;
     EpicsStruct dataStruct;
  };
  };


=== Discussion of dbdTypes ===
=== Discussion of dbfTypes ===


==== Primitive Types ====
The classes defined in dbfTypes together with the definitions from epicsTypes
The primitive types, all map directly to an epicsType.
is a complete list of the definitions that appear in header files generated
from <tt>struct</tt> and <tt>record</tt> dbd definitions.
 
==== Epics Types ====
 
The types bool,...,string all map to an epicsType.
 
The type array maps to EpicsArray if the array type maps to an epicsType.
 
The type struct maps to EpicsStruct only if all fields in the struct map to
an epicsType other than epicsUnknownT.


If a record is defined as:
If a record is defined as:
    struct(displayLimits) {
        field(low,double)
        field(high,double)
    }
     record(xxx) extends iocRecord {
     record(xxx) extends iocRecord {
         ...
         ...
Line 199: Line 129:
         field(ffloat64,float64)
         field(ffloat64,float64)
         ...
         ...
        field(fstring,string)
        field(darray,array(double[])
        field(displayLimits,struct(displayLimits))
     }
     }
Then the generated header file will be
Then the generated header file will be
     class xxxRecord : public iocRecord {
     class xxxRecord : public iocRecord {
     public:
     public:
         dbfBoolean fbool;
         epicsBoolean fbool;
         dbfOctet   foctet;
         epicsOctet   foctet;
         ...
         ...
         dbfFloat64 ffloat64;
         epicsFloat64 ffloat64;
         ...
         ...
        EpicsString  fstring;
        EpicsArray  darray;
        EpicsStruct  displayLimits;
     };
     };


==== DbfString ====
==== DbfArray ====
<tt>DbfString</tt> is described as:
 
    class DbfString {
This is for array fields with a type that is not a standard epicsType, i.e. the epicsType is epicsUnknownT.
    public:
        dbfInt32  capacity;  /*capacity in bytes*/
        dbfBoolean isCharString;
        dbfOctet  *pstorage;
    };
If a record definition contains
    field(sfield,string)
Then the generated header file contains
    DbfString sfield;


; <tt>capacity</tt>
If a record definition contains:
: the the number of bytes referenced by <tt>pstorage</tt> NOT the number of characters.
; <tt>isCharString</tt>
: <tt>false</tt> if the current string can not be converted to a <tt>char</tt>
array, i.e. it can only be converted to a <tt>wchar_t</tt> array.
; <tt>pstorage</tt>
: the address of a UTF-8 null terminated character string.


An interface DbfStringSupport is defined to support DbfString.
    struct(calcInpLink) {
        field(link,link(in))
        field(value,float64)
    }
    record(calc) extends iocRecord {
        ...
        field(inp,array(struct(calcInpLink)[]))
        ...
    }


==== DbfStruct ====
Then the generated code contains:


<tt>DbfStruct></tt> is described as:
     DbfArray inp;
     class DbfStruct{
    public:
        StructDbdDef *pstructDef;
        StructDbd    *pstorage;
    };


If a record definition contains
====  DbfStruct ====
    field(sstruct,struct(name))
Then the generated header file contains
    DbfStruct sfield;
<tt>pstorage</tt> is the address of storage for the structure and <tt>pstructDef</tt> is the address of a description of the structure. StructDbdDef is described in <tt>dbdStatatements.h</tt>


Note that given a dbdStruct it is possible to locate both the address and description of the associated structure.
This is for a struct field that itself has fields that are not a standard epicsType, i.e. the epicsType is epicsUnknownT.


==== DbfArray ====
If a record definition contains:


A DbfArray describes a 1-dim array of a single dbfType. Multi dimensional
    struct(calcInpLink) {
array can be constructed since a DbfArray can be a 1 dim array of DbfArray.
        field(link,link(in))    // NOT a standard epicsType
        field(value,float64)
    }
    record(calc) extends iocRecord {
        ...
        field(inp,struct(calcInpLink))
        ...
    }
 
Then the generated code contains:


<tt>pstorage</tt> is guaranteed to be allocated on a natural boundary for dbfType.
    DbfArray inp;
   


==== DbfMenu ====
==== DbfMenu ====
Line 262: Line 192:
     class DbfMenu{
     class DbfMenu{
     public:
     public:
         dbfInt16   index;
         epicsInt16   index;
         MenuDbfDef *pmenuDef;
         MenuDbdDef *pmenuDef;
     };
     };


Line 276: Line 206:
     class DbfEnum{
     class DbfEnum{
     public:
     public:
         dbfInt16 index;
         epicsInt16 index;
         DbfArray  *pchoiceArray; // addr of field that is DbfArray on choices
         DbfArray  *pchoiceArray; // addr of field that is DbfArray on choices
     };
     };
Line 292: Line 222:
         LinkDir  dir;
         LinkDir  dir;
         LinkDbd  *plinkDef;
         LinkDbd  *plinkDef;
         DbfStruct dataStruct;
         EpicsStruct dataStruct;
     };
     };
If a record definition contains
If a record definition contains
Line 324: Line 254:
=== <tt>dbdStatements.h</tt> ===
=== <tt>dbdStatements.h</tt> ===


// FieldDbdPtr is the address of storage for a dbfType
typedef void *FieldDbdPtr;


  // Interface is base class for an interface
  // Interface is base class for an interface
Line 332: Line 259:
  class InterfaceLocator {
  class InterfaceLocator {
  public:
  public:
     DbfString name;
     EpicsString name;
     Interface *pinterface;
     Interface *pinterface;
  };
  };


  class StructFieldAttribute {
  class StructFieldAttribute {
     DbfString default;
     EpicsString default;
     dbfBoolean readonly;
     epicsBoolean readonly;
     dbfBoolean design;
     epicsBoolean design;
     dbfBoolean special;
     epicsBoolean special;
     dbfBoolean dynamic;
     epicsBoolean dynamic;
     epicsInt16 asl;
     epicsInt16 asl;
  };
  };
Line 347: Line 274:
  class StructDbdField {
  class StructDbdField {
  public:
  public:
     DbfString name;
     EpicsString name;
     dbfType   type;
    epicsType  basic;
     dbfType     type;
     StructFieldAttribute *pattribute;
     StructFieldAttribute *pattribute;
  };
  };
Line 354: Line 282:
  class StructDbdDef{
  class StructDbdDef{
  public:
  public:
     DbfString   name;
     EpicsString   name;
     Interface    *plifetime; // references a StructDbdLifetime
     Interface    *plifetime; // references a StructLifetime
     dbfInt16     nfields;
     epicsInt16     nfields;
     StructDbdField *pfield[]; // ptr to array of ptr to StructDbdField
     StructDbdField *pfield[]; // ptr to array of ptr to StructDbdField
  };
  };
Line 362: Line 290:
  class MenuDbdDef{
  class MenuDbdDef{
  public:
  public:
     DbfString name;
     EpicsString name;
     dbfInt16 nchoices;
     epicsInt16 nchoices;
     DbfString *pchoice[];
     EpicsString *pchoice[];
  };
  };


Line 370: Line 298:
  public:
  public:
     LinkDir    dir;
     LinkDir    dir;
     DbfString choiceName;
     EpicsString choiceName;
     DbfString dataStructName;
     EpicsString dataStructName;
     Interface  *pinterface;
     Interface  *pinterface;
  };
  };
Line 378: Line 306:
  public:
  public:
     LinkDir  dir;
     LinkDir  dir;
     DbfString interfaceName;
     EpicsString interfaceName;
     DbfString choiceName;
     EpicsString choiceName;
     DbfString dataStructName;
     EpicsString dataStructName;
     Interface *pinterface;
     Interface *pinterface;
  };
  };


  // The following describes a record type
  // The following describes a record type
  class RecordDbdDef { // describes a record type
  class RecordDbd { // describes a record type
     DbfString   name;
     EpicsString   name;
     Interface    *plifetime; // references a StructDbdLifetime
     Interface    *plifetime; // references a RecordLifetime
     dbfInt16     nfields;
     epicsInt16     nfields;
     StructDbdField *pfield[]; // ptr to array of ptr to StructDbdField
     StructDbdField *pfield[]; // ptr to array of ptr to StructDbdField
  };
  };
Line 395: Line 323:
  class UserDbdField {
  class UserDbdField {
  public:
  public:
     dbfString  name;
     EpicsString  name;
     dbfType    type;
     epicsType    type;
     FieldDbdPtr pfield;
     void        *pfield;
     InterfacePtr *pinterface; // references userFieldHandler
     InterfacePtr *pinterface; // userFieldHandler
  };
  };


  class RecordInstanceDef { // describes a record instance
  class RecordInstance { // describes a record instance
     DbfString    name;
     EpicsString  name;
     RecordDbdDef *pRecordDbdDef;
     RecordDbd *pRecordDbd;
     FieldDbdPtr  *precord;    // address of record instance
     void        *precord;    // address of record instance
     UserDbdField *puserField[];
     UserDbdField *puserField[];
  };
  };
Line 410: Line 338:


=== Discussion of dbdStatements ===
=== Discussion of dbdStatements ===
==== Struct ====
==== StructXXX ====
The Struct classes describe the fields in a dbd <tt>struct</tt> or <tt>record</tt> definition. The classes are : <tt>StructDbdDef</tt>, <tt>StructDbdField</tt>,and <tt>StructFieldAttribute</tt>
The Struct classes describe the fields in a dbd <tt>struct</tt> or <tt>record</tt> definition. The classes are : <tt>StructDbdDef</tt>, <tt>StructDbdField</tt>,and <tt>StructFieldAttribute</tt>


Line 417: Line 345:
: The name of the struct.
: The name of the struct.
; <tt>plifetime</tt>
; <tt>plifetime</tt>
: The address of an implementation of interface <tt>StructDbdLifetime</tt>. The implementation is automatically generated from the dbd <tt>struct</tt> statement. See below for a description of the <tt>StructDbdLifetime</tt> methods.
: The address of an implementation of interface <tt>StructLifetime</tt>. The implementation is automatically generated from the dbd <tt>struct</tt> statement. See below for a description of the <tt>StructLifetime</tt> methods.
; <tt>nfields</tt>
; <tt>nfields</tt>
: The number of fields, e.g. fields in the structure.
: The number of fields, e.g. fields in the structure.
; <tt>pfields</tt>
; <tt>pfields</tt>
: pointer to an array of pointers to <tt>StructDbdField</tt>. Each StructDbdField contains the name and type of the fields.
: pointer to an array of pointers to <tt>StructDbdField</tt>.


The fields of <tt>StructDbdField</tt> are:
The fields of <tt>StructDbdField</tt> are:
; <tt>name</tt>
; <tt>name</tt>
: The name of the field
: The name of the field
; <tt>basic</tt>
: The epicsType of the field. Unless this is epicsUnknownT generic code is usually provided for accessing the field.
; <tt>type</tt>
; <tt>type</tt>
: The dbfType for the field.
: The dbfType for the field. Note that unless basic is epicsUnknownT this has the value dbfEpicsT.
; <tt>pattribute</tt>
; <tt>pattribute</tt>
: The address of a StructFieldAttribute for the field
: The address of a StructFieldAttribute for the field
Line 443: Line 373:
: The number of menu choices.
: The number of menu choices.
; <tt>pchoice</tt>
; <tt>pchoice</tt>
: The address of an array of pointers to DbfString. Each DbfString is a choice.
: The address of an array of pointers to EpicsString. Each EpicsString is a choice.


==== Link and Device ====
==== Link and Device ====
Line 470: Line 400:


==== Record ====
==== Record ====
A record type has an associated class: <tt>RecordDbdDef</tt>.
A record type has an associated class: <tt>RecordDbd</tt>.
The fields of <tt>RecordDbdDef</tt> are the same as fields in <tt>StructDbdDef</tt> except that they refer to a record instead of a structure.
The fields of <tt>RecordDbd</tt> are the same as fields in <tt>StructDbdDef</tt> except that they refer to a record instead of a structure.
; <tt>name</tt>
; <tt>name</tt>
: The name of the record.
: The name of the record.
; <tt>plifetime</tt>
; <tt>plifetime</tt>
: The address of an implementation of interface <tt>StructDbdLifetime</tt>. The implementation is automatically generated from the dbd <tt>record</tt> statement. See below for a description of the <tt>StructDbdLifetime</tt> methods.
: The address of an implementation of interface <tt>RecordLifetime</tt>. The implementation is automatically generated from the dbd <tt>record</tt> statement. See below for a description of the <tt>RecordLifetime</tt> methods.
; <tt>nfields</tt>
; <tt>nfields</tt>
: The number of fields, e.g. fields in the record.
: The number of fields, e.g. fields in the record.
Line 483: Line 413:
: Address of an array of pointers to <tt>UserDbdField</tt>.
: Address of an array of pointers to <tt>UserDbdField</tt>.


Question? Is RecordDbdDef necessary? Might be good to keep it in case a difference between struct and record becomes necessary.


==== Record Instance ====
==== Record Instance ====


A record instance has two associated classes:<tt>UserDbdField</tt> and <tt>RecordInstanceDef</tt>.
A record instance has two associated classes:<tt>UserDbdField</tt> and <tt>RecordInstance</tt>.


<tt>UserDbdField</tt> contains information for a user defined field:
<tt>UserDbdField</tt> contains information for a user defined field:
Line 499: Line 428:
: The address of an implementation of interface userFieldHandler;
: The address of an implementation of interface userFieldHandler;


The fields of <tt>RecordInstanceDef</tt> are:
The fields of <tt>RecordInstance</tt> are:


; <tt>name</tt>
; <tt>name</tt>
: The name of the record instance
: The name of the record instance
; <tt>pRecordDbdDef</tt>
; <tt>pRecordDbd</tt>
: The address of the description of the record type
: The address of the description of the record type
; <tt>precord</tt>
; <tt>precord</tt>
Line 516: Line 445:


dbdInterfaces describes standard interfaces implemented by code that
dbdInterfaces describes standard interfaces implemented by code that
supports runtime database access. For some the code is automatically generated from the dbd definitions.
supports runtime database access.


  </center>
  </center>
Line 523: Line 452:
<tt>dbdInterfaces.h</tt> contains the following:
<tt>dbdInterfaces.h</tt> contains the following:


  // every struct and every record support module implements the following
  // For struct definitions that become EpicsStruct fields
  // The implementation is generated from the dbd definition
// An EpicsStructLifetime interface is automatically generated.
  class StructDbdLifetime {
 
// For struct definitions that become DbfStruct fields
// An StructLifetime interface is automatically generated.
class StructLifetime {
public:
    virtual void allocate(DbfStruct *pDbfStruct) = 0;
    virtual bool initialize(DbfStruct *pDbfStruct) = 0;
    virtual bool finalize(DbfStruct *pDbfStruct) = 0;
    virtual void destroy(DbfStruct *pDbfStruct) = 0;
    virtual void *expose(DbfStruct *pDbfStruct, epicsInt16 index) = 0;
};
 
  // For record definitions an RecordLifetime is automatically generated.
  class RecordLifetime {
  public:
  public:
     virtual StructDbdPtr create() = 0;
     virtual void allocate(void *precord) = 0;
     virtual bool initialize(dbfString *errorMessage,
     virtual bool initialize(void *precord) = 0;
                              StructDbdPtr ptr) = 0;
     virtual bool finalize(void *precord) = 0;
     virtual bool finalize(dbfString *errorMessage,
     virtual void destroy(void *precord) = 0;
                              StructDbdPtr ptr) = 0;
     virtual void *expose(void *precord, epicsInt16 index) = 0;
     virtual void destroy(StructDbdPtr ptr) = 0;
     virtual void *indexToAddr(dbfString *errorMessage,
                              StructDbdPtr ptr, dbfInt16 index) = 0;
    // ???? is anything else needed
  };
  };


Line 541: Line 479:
  class LinkDbdSupport {
  class LinkDbdSupport {
  public:
  public:
     virtual void report(dbfString *errorMessage,
     virtual void report(EpicsString *errorMessage,
                       iocRecord *precord, dbfLink *pdbfLink) = 0;
                       iocRecord *precord, DbfLink *pdbfLink) = 0;
     virtual bool initialize(dbfString *errorMessage,
     virtual bool initialize(EpicsString *errorMessage,
                       iocRecord *precord, dbfLink *pdbfLink) = 0;
                       iocRecord *precord, DbfLink *pdbfLink) = 0;
     virtual bool finalize(dbfString *errorMessage,
     virtual bool finalize(EpicsString *errorMessage,
                       iocRecord *precord, dbfLink *pdbfLink) = 0;
                       iocRecord *precord, DbfLink *pdbfLink) = 0;
     virtual bool connect(dbfString *errorMessage,
     virtual bool connect(EpicsString *errorMessage,
                       iocRecord *precord, dbfLink *pdbfLink) = 0;
                       iocRecord *precord, DbfLink *pdbfLink) = 0;
     virtual bool disconnect(dbfString *errorMessage,
     virtual bool disconnect(epicsfString *errorMessage,
                       iocRecord *precord, dbfLink *pdbfLink) = 0;
                       iocRecord *precord, DbffLink *pdbfLink) = 0;
     virtual bool get(dbfString *errorMessage,
     virtual bool get(EpicsString *errorMessage,
                       iocRecord *precord, dbfLink *pdbfLink,
                       iocRecord *precord, DbffLink *pdbfLink,
                       dbfType type, FieldDbdPtr pfield) = 0;
                       dbfType type, void *pfield) = 0;
     virtual bool put(dbfString *errorMessage,
     virtual bool put(EpicsString *errorMessage,
                       iocRecord *precord, dbfLink *pdbfLink,
                       iocRecord *precord, DbfLink *pdbfLink,
                       dbfType type, FieldDbdPtr pfield) = 0;
                       dbfType type, void *pfield) = 0;
  };
  };


Line 562: Line 500:
  class RecordDbdSupport {
  class RecordDbdSupport {
  public:
  public:
     virtual iocRecord *create(dbfString *errorMessage) = 0;
     virtual iocRecord *allocate(EpicsString *errorMessage) = 0;
     virtual bool destroy(dbfString *errorMessage, iocRecord *precord) = 0;
     virtual bool destroy(EpicsString *errorMessage, iocRecord *precord) = 0;
     virtual bool init(dbfString *errorMessage,
     virtual bool init(EpicsString *errorMessage,
                       iocRecord *precord, bool firstPass) = 0;
                       iocRecord *precord, bool firstPass) = 0;
     virtual void special(iocRecord *precord, iocRecord *precord,
     virtual void special(iocRecord *precord, iocRecord *precord,
             bool  after,
             bool  after,
             dbfInt16 nlevels, // number of elements in fieldIndex
             epicsInt16 nlevels, // number of elements in fieldIndex
             dbfInt16 fieldIndex[] // array of field indices
             epicsInt16 fieldIndex[] // array of field indices
             ) = 0;
             ) = 0;
  };
  };
Line 575: Line 513:
  class UserFieldHandler {
  class UserFieldHandler {
  public:
  public:
     virtual bool initialize(dbfString *errorMessage,
     virtual bool initialize(EpicsString *errorMessage,
                       iocRecord *precord,UserDbdField *puserField) = 0;
                       iocRecord *precord,UserDbdField *puserField) = 0;
     virtual bool finalize(dbfString *errorMessage,
     virtual bool finalize(EpicsString *errorMessage,
                       iocRecord *precord,UserDbdField *puserField) = 0;
                       iocRecord *precord,UserDbdField *puserField) = 0;
     virtual bool process(dbfString *errorMessage,
     virtual bool process(EpicsString *errorMessage,
                       iocRecord *precord,UserDbdField *puserField) = 0;
                       iocRecord *precord,UserDbdField *puserField) = 0;
  };
  };


=== Discussion of dbdInterfaces ===
=== Discussion of dbdInterfaces ===
==== <tt>StructDbdLifetime</tt> ====
==== <tt>StructLifetime</tt> ====
Every dbd <tt>struct</tt> and <tt>record</tt> has an associated <tt>StructDbdLifetime</tt> interface implementation. A tool is provided that automatically generates the implementation form the dbd definition.
Every dbd <tt>struct</tt> and <tt>record</tt> has an associated <tt>StructLifetime</tt> interface implementation. A tool is provided that automatically generates the implementation form the dbd definition.
<tt>StructDbdLifetime</tt> has the following fields:
<tt>StructLifetime</tt> has the following fields:
; <tt>create</tt>
; <tt>allocate</tt>
: Creates storage for the struct or record.
: Creates storage for the struct or record.
; <tt>initialize</tt>
; <tt>initialize</tt>
Line 595: Line 533:
; <tt>destroy</tt>
; <tt>destroy</tt>
: frees storage
: frees storage
; <tt>indexToAddr</tt>
; <tt>expose</tt>
: Given an index it returns the address of the storage. Note the the generated header files assign an index to each field.
: Given an index it returns the address of the storage. Note the the generated header files assign an index to each field.


Line 608: Line 546:




== Class Factories ==


 
     class DbfStructFactory {
<center>
 
== DbfStringSupport Interface ==
 
</center>
 
This describes a proposed interface to support DbfString.
 
The interface is "minimal" in that it provides only a basic set of methods.
If code needs to do serious character manipulation it must:
* Use toChar or toWcar to convert a DbfString to an array of char or wchar_t
* Use standard library support to do character manipulation
* Use fromChar or fromWChar to convert the result to a DbfString,
 
<tt>DbfString</tt> is defined as:
     class DbfString {
    public:
        dbfInt32  capacity;  /*capacity in bytes*/
        dbfBoolean isCharString;
        dbfOctet  *pstorage;
    };
 
; <tt>capacity</tt>
: is the amount of storage in bytes allocated for pstorage
; <tt>isCharString</tt>
: Is <tt>true</tt> if the UTF_8 null terminated string can be converted
to a char array. It is false if a wchar_t is required.
; <tt>pstorage</tt>
: Is a null terminated UTF_8 encoded character string.
 
<tt>DbfStringSupport.h</tt> contains:
 
    class DbfStringSupport {
        virtual bool allocate(DbfString *pstring, epicsInt32 capacity) = 0;
        virtual null free(DbfString *pstring) = 0;
        virtual bool isCharString(DbfString *pstring) = 0;
        virtual epicsInt32 length(DbfString *p) = 0;
        virtual epicsInt32 length(char *p,epicsInt32 maxsize) = 0;
        virtual epicsInt32 length(wchar_t *p,epicsInt32 maxsize) = 0;
        virtual bool isEqual(DbfString *p1st,DbfString *p2nd) = 0;
        virtual bool toChar(DbfString *pstring,DbfString error,
                    char *pcharstring, epicsInt32 maxsize) = 0;
        virtual bool fromChar(DbfString *pstring,
                    const char *pcharstring, epicsInt32 maxsize) = 0;
        virtual bool toWChar(DbfString *pstring,DbfString error,
                    wchar_t *pcharstring, epicsInt32 maxsize) = 0;
        virtual bool fromWChar(DbfString *pstring,
                    wchar_t *pcharstring) = 0;
    };
 
; <tt>allocate</tt>
: <tt>pstring.pstorage</tt> is set equal to the address of capacity bytes of memory.  <tt>pstring.capacity</tt> is set equal to the number of bytes.  pstorage MUST NEVER be allocated by any means other than calling allocate.
; <tt>free</tt>
: The storage referenced by pstring.pstorage is freed. <tt>pstring.capacity</tt> and <tt>pstring.pstorage</tt> are set to 0.
; <tt>length(DbfString *p)</tt>
: Returns the number of characters in the string.
; <tt>length(char *p,epicsInt32 maxsize)</tt>
: Returns the number of bytes required for a UTF_8 encoded string.
; <tt>length(wchar_t *p,epicsInt32 maxsize)</tt>
: Returns the number of bytes required for a UTF_8 encoded string.
; <tt>isEqual</tt>
: Performs a byte by byte comparison until a null byte is detected or capacity of either string is reached. It returns (false,true) if the strings (are not, are) equal.
; <tt>toChar</tt>
: Converts  a DbfString to a null terminated C char array.  A return of <tt>true</tt> means success.  A return of <tt>false</tt> means failure and the reason is returned in <tt>error</tt>.  : Converts  a null terminated C char array to a DbfString.  If the current capacity of pstring is not sufficent, free and allocate are called automatically.  A return of <tt>true</tt> means success.  A return of <tt>false</tt> means failure and the reason is returned in <tt>error</tt>.
; <tt>toWChar</tt>
: Converts  a DbfString to a null terminated C wchar_t array.  A return of <tt>true</tt> means success.  A return of <tt>false</tt> means failure and the reason is returned in <tt>error</tt>.  ; <tt>fromChar</tt>
; <tt>fromWChar</tt>
: Converts  a null terminated C wchar_t array to a DbfString.  The result is a UTF_8 encode string.  If the current capacity of pstring is not sufficent, free and allocate are called automatically.  A return of <tt>true</tt> means success.  A return of <tt>false</tt> means failure and the reason is returned in <tt>error</tt>.
 
 
Questions:
* Is one implementation of DbfStringSupport sufficient or is a separate implementation required for each locale?
* Hopefully only one implementation is required. But then are the above arguments sufficient.
 
 
 
----
 
<center>
 
== Example of Generated Header Files ==
 
</center>
 
=== Database Definition Files ===
 
<tt>menuAlarmSevr.dbd</tt> contains:
    menu(menuAlarmSevr) {
          choice(menuAlarmSevrNO_ALARM,"NO_ALARM")
          choice(menuAlarmSevrMINOR,"MINOR")
          choice(menuAlarmSevrMAJOR,"MAJOR")
          choice(menuAlarmSevrINVALID,"INVALID")
    }
 
<tt>displayLimit.dbd</tt> contains:
    struct(displayLimit) {
        field(low,float64)
        field(high,float64)
    }
<tt>exampleRecord.dbd</tt> contains:
    record(example) extends iocRecord {
        field(value,float64)
        field(displayLimit,struct(displayLimit))
    }
<tt>alltypesRecord.dbd</tt> contains:
    record(allTypes) extends iocRecord {
        field(fbool,bool)
        field(foctet,octet)
        field(fint16,int16)
        field(fuint16,uint16)
        field(fint32,int32)
        field(fuint32,uint32)
        field(fint64,int64)
        field(fuint64,uint64)
        field(ffloat32,float32)
        field(ffloat64,float64)
        field(fstring,string)
        field(fmenu,menu(menuName))
        field(fenum,enum(stateNames))
        field(stateNames,array(string[]))
        field(fstruct,struct(displayLimit))
        field(flink,link(dir))
        field(fdevice,device(dir,interfaceName))
    }
=== Generated Header Files ===
Tools are provided to generate header files from the following dbd definitions:
*menu
*struct
*record
<tt>menuAlarmSevr.h</tt> is generated from <tt>menuAlarmSevr.dbd</tt>
    enum menuAlarmSevr {
            menuAlarmSevrNO_ALARM,
            menuAlarmSevrMINOR,
            menuAlarmSevrMAJOR,
            menuAlarmSevrINVALID
    };
<tt>displayLimit.h</tt> is generated from <tt>displayLimit.dbd</tt>
    class displayLimit : public StructDbd {
     public:
     public:
         dbfFloat64 low;
         static DbfStructLifetime *find(const char *structName);
         dbfFloat64 high;
         static void register(const char *structName,
                              DbfStructDef, *pdef);
     };
     };
    const dbfInt16 displayLimit_firstIndex = 1
    const dbfInt16 displayLimit_low        = 1
    const dbfInt16 displayLimit_high      = 2
    const dbfInt16 displayLimit_lastIndex =displayLimit_high
<tt>exampleRecord.h</tt> is generated from <tt>exampleRecord.dbd</tt>
    class exampleRecord : public iocRecord{
    public:
        dbfFloat64 value;
        dbfStruct  displayLimit;
    };
   
    const dbfInt16 example_firstIndex = 1001001
    const dbfInt16 example_low = 1001001;
    const dbfInt16 example_high = 1001002;
    const dbfInt16 example_lastIndex = example_high;
<tt>alltypesRecord.h</tt> is generated from <tt>alltypesRecord.dbd</tt>
    class allTypesRecord : public iocRecord{
    public:
        dbfBoolean fbool;
        dbfOctet  foctet;
        dbfInt16  fint16;
        dbfUInt16  fuint16;
        dbfInt32  fint32;
        dbfUInt32  fuint32;
        dbfInt64  fint32;
        dbfUInt64  fuint32;
        dbfFloat32 ffloat32;
        dbfFloat64 ffloat64;
        DbfString  fstring;
        DbfMenu    fmenu;
        DbfEnum    fenum
        DbfArray  stateStrings;
        DbfStruct  fstruct;
        DbfLink    flink;
        DbfDevice  fdevice;
    };
   
    const dbfInt16 allTypes_firstIndex = 1001001;
    const dbfInt16 allTypes_fbool = 1001001;
    const dbfInt16 allTypes_foctet = 1001002;
    const dbfInt16 allTypes_fint16 = 1001003;
    const dbfInt16 allTypes_fuint16 = 1001004;
    const dbfInt16 allTypes_fint32 = 1001005;
    const dbfInt16 allTypes_fuint32 = 1001006;
    const dbfInt16 allTypes_fint64 = 1001007;
    const dbfInt16 allTypes_fuint64 = 1001008;
    const dbfInt16 allTypes_ffloat32 = 1001009;
    const dbfInt16 allTypes_ffloatn64 = 10010010;
    const dbfInt16 allTypes_ffstring = 10010011;
    const dbfInt16 allTypes_fmenu = 10010012;
    const dbfInt16 allTypes_fenum = 10010013;
    const dbfInt16 allTypes_stateStrings = 10010014;
    const dbfInt16 allTypes_fstruct = 10010015;
    const dbfInt16 allTypes_flink = 10010016;
    const dbfInt16 allTypes_fdevice = 10010017;
    const dbfInt16 allTypes_lastIndex = allTypes_fdevice;
----

Revision as of 19:38, 24 May 2005

May 24 2005

Overview

This document describes the C++ class definitions for code that implements the semantics for 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.

The following headers files are described:

  • dbfTypes.h - Type definitions for field definitions in struct or record> DBD definitions.
  • dbdStatements.h - Type definitions for DBD statements.
  • dbdInterfaces.h - Type definitions for interfaces related to DBD definitions.

dbfTypes

File dbfTypes.h describes types and classes that are used in header files generated from dbd struct or record field definitions.

The following naming conventions are used:

Dbf
any class starting with Dbf describes a non-primitive struct or record field. For example EpicsString describes a field(name,string).
*Dbd*
A class name that has Dbd imbeded in it describes something directly related to a dbd statement. For example LinkDbdSupport describes a dbd link definition.

dbdTypes.h

enum dbfType {
    dbfUnknownT,
    dbfEpicsT,  // an epicsType except epicsUnknownT
    dbfArrayT,
    dbfStructT,
    dbfMenuT,
    dbfEnumT,
    dbfLinkT,
    dbfDeviceT
};
class ArrayDbdDef; //describes a dbd array definition
class StructDbdDef; //describes a dbd struct definition
class MenuDbdDef; //describes a dbd menu definition
class LinkDbd;    //describes dbd link statement
class DeviceDbd;  //describes dbd device statement
// If array type is a known epicsType then EpicsArray
class DbfArray : public EpicsArray {
public:
    dbfType dbftype;
};
// If every field is a known epicsType then EpicsStruct
class DbfStruct {
public:
    StructDbdDef *pStructDbdDef;
    void         *pstorage;
};
class DbfMenu{
public:
    epicsInt16    index;
    MenuDbdDef  *pmenuDef; /* address of global menu */
};
class DbfEnum{
public:
    epicsInt16  index;
    DbfArray  *pchoiceArray; // addr of field that is DbfArray on choices
};

enum LinkDir {
    LinkDirNone,
    LinkDirForward,
    LinkDirIn,
    LinkDirOut,
    LinkDirInOut
};
class DbfLink{ 
public:
    LinkDir   dir;
    LinkDbd   *plinkDef;
    EpicsStruct dataStruct;
};
class DbfDevice{
public:
    LinkDir   dir;
    DeviceDbd *pdeviceDef;
    EpicsStruct dataStruct;
};

Discussion of dbfTypes

The classes defined in dbfTypes together with the definitions from epicsTypes is a complete list of the definitions that appear in header files generated from struct and record dbd definitions.

Epics Types

The types bool,...,string all map to an epicsType.

The type array maps to EpicsArray if the array type maps to an epicsType.

The type struct maps to EpicsStruct only if all fields in the struct map to an epicsType other than epicsUnknownT.

If a record is defined as:

    struct(displayLimits) {
        field(low,double)
        field(high,double)
    }
    record(xxx) extends iocRecord {
        ...
        field(fbool,bool)
        field(foctet,octet)
        ...
        field(ffloat64,float64)
        ...
        field(fstring,string)
        field(darray,array(double[])
        field(displayLimits,struct(displayLimits))
    }

Then the generated header file will be

    class xxxRecord : public iocRecord {
    public:
        epicsBoolean fbool;
        epicsOctet   foctet;
        ...
        epicsFloat64 ffloat64;
        ...
        EpicsString  fstring;
        EpicsArray   darray;
        EpicsStruct  displayLimits;
   };

DbfArray

This is for array fields with a type that is not a standard epicsType, i.e. the epicsType is epicsUnknownT.

If a record definition contains:

    struct(calcInpLink) {
        field(link,link(in))
        field(value,float64)
    }
    record(calc) extends iocRecord {
        ...
        field(inp,array(struct(calcInpLink)[]))
        ...
    }

Then the generated code contains:

    DbfArray inp;

DbfStruct

This is for a struct field that itself has fields that are not a standard epicsType, i.e. the epicsType is epicsUnknownT.

If a record definition contains:

    struct(calcInpLink) {
        field(link,link(in))     // NOT a standard epicsType
        field(value,float64)
    }
    record(calc) extends iocRecord {
        ...
        field(inp,struct(calcInpLink))
        ...
    }

Then the generated code contains:

    DbfArray inp;
    

DbfMenu

DbfMenu> is described as:

    class DbfMenu{
    public:
        epicsInt16    index;
        MenuDbdDef  *pmenuDef;
    };

If a record definition contains

    field(fmenu,menu(name))

Then the generated header file contains

    DbfMenu fmenu;

DbfMenu provides the current menu index and also the menu definition.

DbfEnum

DbfEnum> is described as:

    class DbfEnum{
    public:
        epicsInt16  index;
        DbfArray  *pchoiceArray; // addr of field that is DbfArray on choices
    };

If a record definition contains

    field(fenum,enum)

Then the generated header file contains

    DbfEnum fenum;

pchoiceArray is the address of a field in the same record that is a DbfArray of choices.

DbfLink

DbfLink is described as

    class DbfLink{ 
    public:
        LinkDir   dir;
        LinkDbd   *plinkDef;
        EpicsStruct dataStruct;
    };

If a record definition contains

    field(flink,link(in))

Then the generated header file contains

    DbfLink flink;

The fields of DbfLink are initialized by locating a dbd link definition that matches the dir specified in the dbd field definition.

The fields of DbfLink are initialized as follows:

dir
This is taken from either the field definition or from the LinkDbd definition and is the most restrictive. For example if one says inout and the other says in then dir will be in.
plinkDef
This is the address of the LinkDbd.
dataStruct
The describes the data structure specified in the dbd link definition. It contains data used by the link support.

Note that link support always implements interface LinkDbdSupport

DbfDevice

A DbfDevice is similar to a DbfLink except that the interface implemented by the device support is also specified, i.e. instead of implementing interface LinkDbdSupport, the device support implements an interface that both record support and device support understand.



dbdStatements

The classes in dbdStatements.h allow introspection of ioc records. They describe everything defined in DBD definitions.

dbdStatements.h

// Interface is base class for an interface
class Interface {};
class InterfaceLocator {
public:
    EpicsString name;
    Interface *pinterface;
};
class StructFieldAttribute {
    EpicsString  default;
    epicsBoolean readonly;
    epicsBoolean design;
    epicsBoolean special;
    epicsBoolean dynamic;
    epicsInt16 asl;
};
class StructDbdField {
public:
    EpicsString name;
    epicsType   basic;
    dbfType     type;
    StructFieldAttribute *pattribute;
};
class StructDbdDef{
public:
    EpicsString    name;
    Interface    *plifetime; // references a StructLifetime
    epicsInt16     nfields;
    StructDbdField *pfield[]; // ptr to array of ptr to StructDbdField
};
class MenuDbdDef{
public:
    EpicsString name;
    epicsInt16  nchoices;
    EpicsString *pchoice[];
};
class LinkDbd{ //describes dbd link statement
public:
    LinkDir    dir;
    EpicsString  choiceName;
    EpicsString  dataStructName;
    Interface  *pinterface;
};
class DeviceDbd { //describes dbd device statement
public:
    LinkDir   dir;
    EpicsString interfaceName;
    EpicsString choiceName;
    EpicsString dataStructName;
    Interface *pinterface;
};
// The following describes a record type
class RecordDbd { // describes a record type
    EpicsString    name;
    Interface    *plifetime; // references a RecordLifetime
    epicsInt16     nfields;
    StructDbdField *pfield[]; // ptr to array of ptr to StructDbdField
};
// The following describes a record instance
class UserDbdField {
public:
    EpicsString  name;
    epicsType    type;
    void         *pfield;
    InterfacePtr *pinterface; // userFieldHandler
};
class RecordInstance { // describes a record instance
    EpicsString  name;
    RecordDbd *pRecordDbd;
    void         *precord;     // address of record instance
    UserDbdField *puserField[];
};


Discussion of dbdStatements

StructXXX

The Struct classes describe the fields in a dbd struct or record definition. The classes are : StructDbdDef, StructDbdField,and StructFieldAttribute

The fields of StructDbdDef are:

name
The name of the struct.
plifetime
The address of an implementation of interface StructLifetime. The implementation is automatically generated from the dbd struct statement. See below for a description of the StructLifetime methods.
nfields
The number of fields, e.g. fields in the structure.
pfields
pointer to an array of pointers to StructDbdField.

The fields of StructDbdField are:

name
The name of the field
basic
The epicsType of the field. Unless this is epicsUnknownT generic code is usually provided for accessing the field.
type
The dbfType for the field. Note that unless basic is epicsUnknownT this has the value dbfEpicsT.
pattribute
The address of a StructFieldAttribute for the field

StructFieldAttribute has the attribute values for the field.

Menu

A dbd menu is described by class MenuDbdDef

The fields of MenuDbdDef are:

name
The menu name.
nchoices
The number of menu choices.
pchoice
The address of an array of pointers to EpicsString. Each EpicsString is a choice.

Link and Device

Each dbd link definition has an associated class LinkDbd with fields:

dir
The link direction
choiceName
The name that matches a LinkDbd for a DbfLink instance.
dataStructName
The class name of a DbfStruct for the Interface implementation
pinterface
The address of the Interface implementation. The interface class is LinkDbdSupport

Each dbd device definition has an associated class DeviceDbd with fields:

dir
The link direction
interfaceName
The name of the interface class implemented by the device support
choiceName
The name that matches a DeviceDbd for a DbfDevice instance.
dataStructName
The class name of a DbfStruct for the Interface implementation
pinterface
The address of the Interface implementation.

Record

A record type has an associated class: RecordDbd. The fields of RecordDbd are the same as fields in StructDbdDef except that they refer to a record instead of a structure.

name
The name of the record.
plifetime
The address of an implementation of interface RecordLifetime. The implementation is automatically generated from the dbd record statement. See below for a description of the RecordLifetime methods.
nfields
The number of fields, e.g. fields in the record.
pfields
pointer to an array of pointers to StructDbdField. Each StructDbdField contains the name and type of the fields.
puserField
Address of an array of pointers to UserDbdField.


Record Instance

A record instance has two associated classes:UserDbdField and RecordInstance.

UserDbdField contains information for a user defined field:

name
The name of the user defined field
type
The dbfType for the field.
pfield
Address of storage for field.
pinterface
The address of an implementation of interface userFieldHandler;

The fields of RecordInstance are:

name
The name of the record instance
pRecordDbd
The address of the description of the record type
precord
The address of the record itself.
puserField
The address of a array of pointers to UserDbdField

dbdInterfaces

dbdInterfaces describes standard interfaces implemented by code that supports runtime database access.

dbdInterfaces.h

dbdInterfaces.h contains the following:

// For struct definitions that become EpicsStruct fields
// An EpicsStructLifetime interface is automatically generated.
// For struct definitions that become DbfStruct fields
// An StructLifetime interface is automatically generated.
class StructLifetime {
public:
    virtual void allocate(DbfStruct *pDbfStruct) = 0;
    virtual bool initialize(DbfStruct *pDbfStruct) = 0;
    virtual bool finalize(DbfStruct *pDbfStruct) = 0;
    virtual void destroy(DbfStruct *pDbfStruct) = 0;
    virtual void *expose(DbfStruct *pDbfStruct, epicsInt16 index) = 0;
};
// For record definitions an RecordLifetime is automatically generated.
class RecordLifetime {
public:
    virtual void allocate(void *precord) = 0;
    virtual bool initialize(void *precord) = 0;
    virtual bool finalize(void *precord) = 0;
    virtual void destroy(void *precord) = 0;
    virtual void *expose(void *precord, epicsInt16 index) = 0;
};
// every link support module implements the following interface
class LinkDbdSupport {
public:
    virtual void report(EpicsString *errorMessage,
                     iocRecord *precord, DbfLink *pdbfLink) = 0;
    virtual bool initialize(EpicsString *errorMessage,
                     iocRecord *precord, DbfLink *pdbfLink) = 0;
    virtual bool finalize(EpicsString *errorMessage,
                     iocRecord *precord, DbfLink *pdbfLink) = 0;
    virtual bool connect(EpicsString *errorMessage,
                     iocRecord *precord, DbfLink *pdbfLink) = 0;
    virtual bool disconnect(epicsfString *errorMessage,
                     iocRecord *precord, DbffLink *pdbfLink) = 0;
    virtual bool get(EpicsString *errorMessage,
                     iocRecord *precord, DbffLink *pdbfLink,
                     dbfType type, void *pfield) = 0;
    virtual bool put(EpicsString *errorMessage,
                     iocRecord *precord, DbfLink *pdbfLink,
                     dbfType type, void *pfield) = 0;
};
/* record support implements the following*/
class RecordDbdSupport {
public:
    virtual iocRecord *allocate(EpicsString *errorMessage) = 0;
    virtual bool destroy(EpicsString *errorMessage, iocRecord *precord) = 0;
    virtual bool init(EpicsString *errorMessage,
                     iocRecord *precord, bool firstPass) = 0;
    virtual void special(iocRecord *precord, iocRecord *precord,
            bool  after,
            epicsInt16 nlevels, // number of elements in fieldIndex
            epicsInt16 fieldIndex[] // array of field indices
            ) = 0;
};
class UserFieldHandler {
public:
    virtual bool initialize(EpicsString *errorMessage,
                     iocRecord *precord,UserDbdField *puserField) = 0;
    virtual bool finalize(EpicsString *errorMessage,
                     iocRecord *precord,UserDbdField *puserField) = 0;
    virtual bool process(EpicsString *errorMessage,
                     iocRecord *precord,UserDbdField *puserField) = 0;
};

Discussion of dbdInterfaces

StructLifetime

Every dbd struct and record has an associated StructLifetime interface implementation. A tool is provided that automatically generates the implementation form the dbd definition. StructLifetime has the following fields:

allocate
Creates storage for the struct or record.
initialize
initializes the struct or record
finalize
cleans up but does not free storage
destroy
frees storage
expose
Given an index it returns the address of the storage. Note the the generated header files assign an index to each field.

LinkDbdSupport

This describes the interface implemented by link support.

RecordDbdSupport

This is the interface implemented by record support.

UserFieldHandler

This is the interface implemented by code for user extensible fields.



Class Factories

    class DbfStructFactory {
    public:
        static DbfStructLifetime *find(const char *structName);
        static void register(const char *structName,
                             DbfStructDef, *pdef);
    };