Difference between revisions of "V4 Design: dbdClass"

From EPICSWIKI
 
Line 1: Line 1:
== EPICS: C++ class definitions for Database Definition ==
== EPICS: C++ class definitions for Database Definition ==


May 11 2005
May 12 2005


<b>UNDER CONSTRUCTION - DO NOT COMMENT</b>
<b>UNDER CONSTRUCTION - DO NOT COMMENT</b>
Line 11: Line 11:


This document describes the C++ class definitions for code that implements
This document describes the C++ class definitions for code that implements
the semantics for records created from Database Definitions. The classes can
the semantics for records created from Database Definitions. The definitions
be separated into two classes:
are intented by code that includes header files generated from dbd definitions
* <tt>dbdTypes.h</tt> - Classes that described fields in header files generated from dbd definitions. Header files are generated from the following dbd definitions:
and also by code that does not include the header files.
** <tt>record</tt>
Header files are generated from the following dbd definitions:
** <tt>struct</tt>
* <tt>record</tt>
** <tt>menu</tt>
* <tt>struct</tt>
* <tt>dbdIntrospect.h</tt> - Classes intended for introspection, i.e. for code that does not include the generated header files.
* <tt>menu</tt>
 
 
----
<center>
 
== dbdTypes.h ==
 
</center>
 
File dbdTypes.h describes the datatypes used by V4 databases:
The following naming conventions are used:
; dbf
: and name starting with dbf describes a struct or record field. For example dbfString describes a field(name,string).
; *Dbf*
: 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.
 
<tt>dbdTypes.h</tt> contains the following:
 
namespace Dbd {
/* TBD dbdNdimArrayT*/
enum dbfType {
    dbfUnknownT,dbfBooleanT,dbfOctetT,
    dbfInt16T,dbfUInt16T,dbfInt32T,dbfUInt32T,dbfInt64T,dbfUInt64T,
    dbfFloat32T,dbfFloat64T,
    dbfStringT,
    dbfStructT,
    dbfMenuT,dbfEnumT,
    dbfLinkT,dbfDeviceT,
    dbfArrayT
};
 
/* some of the following may require OSD definitions*/
typedef bool              dbfBoolean;
typedef char              dbfOctet;
typedef short              dbfInt16;
typedef unsigned short    dbfUInt16;
typedef int                dbfInt32;
typedef unsigned int      dbfUInt32;
typedef long long          dbfInt64;
typedef unsigned long long dbfUInt64;
typedef float              dbfFloat32;
typedef double            dbfFloat64;
 
/*dbfString holds UTF-8 characters*/
class dbfString {
public:
    dbfInt32  capacity;  /*capacity in bytes*/
    dbfOctet  *pstorage;
};
 
// FieldDbdPtr is the address of a dbfType
typedef void *FieldDbdPtr;
// StructDbdPtr references a class generated from a struct dbd
typedef void * StructDbdPtr;
 
// InterfacePtr references a class that contains only methods
typedef void *InterfacePtr;
class Interface {
public:
    dbfString    name;
    InterfacePtr interface;
};
 
// The following Interfaces are described below
class StructDbdLifetime;
class LinkDbdSupport;
 
class StructDbdMember {
public:
    dbfString name;
    dbfType  type;
};
 
class StructDbd{
public:
    dbfString    name;
    dbfInt16    nmembers;
    Interface    *plifetime; // references a StructDbdLifetime
    StructDbdMember *pmember[]; // ptr to array of ptr to StructDbdMember
};
 
class dbfStruct{
public:
    StructDbd *pstructDef;
    StructDbdPtr ptr;
};
 
class MenuDbfDef{
public:
    dbfString name;
    dbfInt16  nchoices;
    dbfString *pchoice[];
};
 
class dbfMenu{
public:
    dbfInt16    index;
    MenuDbfDef  *pmenuDef;
};
 
class dbfEnum{
public:
    dbfInt16  index;
    dbfInt16  nchoices;
    dbfString *pchoice[];
};
enum LinkDir {
    LinkDirNone,
    LinkDirForward,
    LinkDirIn,
    LinkDirOut,
    LinkDirInOut
};
class LinkDbd{ //describes dbd link statement
public:
    LinkDir    dir;
    dbfString    choiceName;
    dbfString    dataStructName;
    InterfacePtr *pinterface;
};
 
class dbfLink{
public:
    LinkDir  dir;
    dbfString  choiceName;
    LinkDbd  *plinkDef; //LinkDbd will reference a LinkDbdSupport
    dbfStruct  dataStruct;
};
 
class DeviceDbd { //describes dbd device statement
public:
    LinkDir  dir;
    dbfString    interfaceName;
    dbfString    choiceName;
    dbfString    dataStructName;
    InterfacePtr *pinterface;
};
 
class dbfDevice{
public:
    LinkDir  dir;
    dbfString    choiceName;
    DeviceDbd *pdeviceDef;
    dbfStruct    dataStruct;
};
 
template< class ARR_T > class dbfArray {
public:
    dbfInt32  capacity;  /*capacity in number of elements*/
    dbfInt32  size;      /*current number of elements*/
    dbfType  type;
    ARR_T    *pstorage;
};
 
/*  The following array types are supported by dbdCore
  *  dbfArray<void>;
  *  dbfArray<dbfOctet>;
  *  dbfArray<dbfInt16>;
  *  dbfArray<dbfUInt16>;
  *  dbfArray<dbfInt32>;
  *  dbfArray<dbfUInt32>;
  *  dbfArray<dbfInt64>;
  *  dbfArray<dbfUInt64>;
  *  dbfArray<dbfFloat32>;
  *  dbfArray<dbfFloat64>;
  *  dbfArray<dbfString>;
  *  dbfArray<dbfLinkField>;
**/
 
// The following describes record types and record instances
class UserDbdField;
class userFieldHandler {
public:
    virtual bool initialize(dbfString *errorMessage,
                      iocRecord *precord,UserDbdField *puserField) = 0;
    virtual bool finalize(dbfString *errorMessage,
                      iocRecord *precord,UserDbdField *puserField) = 0;
    virtual bool process(dbfString *errorMessage,
                      iocRecord *precord,UserDbdField *puserField) = 0;
};
 
class UserDbdField {
public:
    dbfString  name;
    dbfType    type;
    FieldDbdPtr pfield;
    InterfacePtr *pinterface; // references userFieldHandler
}
 
class RecordDbdField {
public:
    dbfString name;
    dbfType  type;
};
   
class RecordDbd { // describes a record type
    dbfArray< UserDbdField > userField;
    dbfArray< RecordDbdField > recField;
    Interface    *plifetime; // references a StructDbdLifetime
}
 
// every struct and every record support module implements the following
// The implementation is generated from the dbd definition
class StructDbdLifetime {
public:
    virtual StructDbdPtr create() = 0;
    virtual bool initialize(dbfString *errorMessage,
                              StructDbdPtr ptr) = 0;
    virtual bool finalize(dbfString *errorMessage,
                              StructDbdPtr ptr) = 0;
    virtual void destroy(StructDbdPtr ptr) = 0;
    virtual void *indexToAddr(dbfString *errorMessage,
                              StructDbdPtr ptr, dbfInt16 index) = 0;
    // ???? is anything else needed
};
 
// every link support module implements the following interface
class LinkDbdSupport {
public:
    virtual void report(dbfString *errorMessage,
                      iocRecord *precord, dbfLink *pdbfLink) = 0;
    virtual bool initialize(dbfString *errorMessage,
                      iocRecord *precord, dbfLink *pdbfLink) = 0;
    virtual bool finalize(dbfString *errorMessage,
                      iocRecord *precord, dbfLink *pdbfLink) = 0;
    virtual bool connect(dbfString *errorMessage,
                      iocRecord *precord, dbfLink *pdbfLink) = 0;
    virtual bool disconnect(dbfString *errorMessage,
                      iocRecord *precord, dbfLink *pdbfLink) = 0;
    virtual bool get(dbfString *errorMessage,
                      iocRecord *precord, dbfLink *pdbfLink,
                      dbfType type, FieldDbdPtr pfield) = 0;
    virtual bool put(dbfString *errorMessage,
                      iocRecord *precord, dbfLink *pdbfLink,
                      dbfType type, FieldDbdPtr pfield) = 0;
};
 
/* record support implements the following*/
class RecordDbdSupport {
public:
    virtual iocRecord *create(dbfString *errorMessage) = 0;
    virtual bool destroy(dbfString *errorMessage, iocRecord *precord) = 0;
    virtual bool init(dbfString *errorMessage,
                      iocRecord *precord, bool firstPass) = 0;
    virtual void special(iocRecord *precord, iocRecord *precord,
            bool  after,
            dbfInt16 nlevels, // number of elements in fieldIndex
            dbfInt16 fieldIndex[] // array of field indices
            ) = 0;
};
}; // namespace Dbd
 
----
<center>
 
== Discussion of dbfTypes ==
 
</center>
 
=== Primitive Types ===
The types dbfBoolean, dbfOctet, dbfInt16, dbfUInt16, dbfInt32, dbfUInt32, dbfInt64,  dbfUInt64, dbfFloat32, dbfFloat64 all map to a C primitive type. Currently the C type is defined in <tt>iocTypes.h</tt>. It may be necessary to provide operating system dependent definitions for some of the types. For example on some architectures a dbfInt64 may have to be defined as a C <tt>long</tt> rather than a <tt>long long</tt>.
 
If a record is defined as:
    record(xxx) extends iocRecord {
        ...
        field(fbool,bool)
        field(foctet,octet)
        ...
        field(ffloat64,float64)
        ...
    }
Then the generated header file will be
    class xxxRecord : iocRecord {
    public:
        dbfBoolean fbool;
        dbfOctet  foctet;
        ...
        dbfFloat64 ffloat64;
        ...
    };
 
<tt>dbfType dbfTypeUnknownT</tt> is reserved for unknown types and will normally be cause by some configuration error.
=== dbfString ===
<tt>dbfString</tt> is described as:
    class dbfString {
    public:
        dbfInt32  capacity;  /*capacity in bytes*/
        dbfOctet  *pstorage;
    };
If a record definition contains
    field(sfield,string)
Then the generated header file contains
    dbfString sfield;
 
<tt>pstorage</tt>will always be the address of a UTF-8 null terminated character string. The <tt>capacity</tt> is the the number of bytes referenced by <tt>pstorage</tt> <bold>NOT</bold> the number of characters.
 
=== dbfStruct ===
 
<dbfStruct></tt> is described as:
    class dbfStruct{
    public:
        StructDbd *pstructDef;
        StructDbdPtr ptr;
    };
 
If a record definition contains
    field(sstruct,struct(name))
Then the generated header file contains
    dbfStruct sfield;
<tt>dbfStruct:ptr</tt> is the address of storage for the structure and <tt>pstructDef</tt> is the address of a description of the structure. The members of <tt>StructDbd</tt> are:
; <tt>name</tt>
: The name of the struct.
; <tt>nmembers</tt>
: The number of members, e.g. fields in the structure.
; <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.
; <tt>pmember</tt>
: pointer to an array of pointers to <tt>StructDbdMember</tt>. Each StructDbdMember contains the name and type of the member.
 
Note that given a dbfStruct it is possible to locate both the address and description of the associated structure.
 
 
 
=== dbfMenu ===
<dbfMenu></tt> is described as:
    class dbfMenu{
    public:
        dbfInt16    index;
        MenuDbfDef  *pmenuDef;
    };
 
If a record definition contains
    field(fmenu,menu(name))
Then the generated header file contains
    dbfMenu fmenu;
The definition of dbfMenu provides the current menu index and also the menu definition.
 
=== dbfEnum ===
<dbfEnum></tt> is described as:
    class dbfEnum{
    public:
        dbfInt16  index;
        dbfInt16  nchoices;
        dbfString *pchoice[];
    };
 
If a record definition contains
    field(fenum,enum)
Then the generated header file contains
    dbfEnum fenum;
The definition of dbfEnum provides the current enum index as well as a description on all the choices associated with the enum.
 
=== dbfLink ===
<tt>dbfLink</tt> is described as
    class dbfLink{
    public:
        LinkDir  dir;
        dbfString  choiceName;
        LinkDbd  *plinkDef; //LinkDbd will reference a LinkDbdSupport
        dbfStruct  dataStruct;
    };
If a record definition contains
    field(flink,link(in))
Then the generated header file contains
    dbfLink flink;
The members of dbfLink are initialized by locating a dbd <tt>link</tt> definition that matches the <tt>dir</tt> specified in the dbd <tt>field</tt> definition.
 
Each dbd <tt>link</tt> definition has an asociated C description:
    class LinkDbd{ //describes dbd link statement
    public:
        LinkDir    dir;
        dbfString    choiceName;
        dbfString    dataStructName;
        InterfacePtr *pinterface;
    };
 
The members of <tt>dbfLink</tt> are initialized as follows:
; <tt>dir</tt>
: This is taken from either the <tt>field</tt> definition or from the <tt>LinkDbd</tt> definition and is the most restrictive. For example if one says inout and the other says in then <tt>dir</tt> will be in.
; <tt>choiceName</tt>
: The record instance specifies this and it is used to locate the associated dbd <tt>link</tt> definition.
; <tt>plinkDef</tt>
: This is the address of the <tt>LinkDbd</tt>.
; <tt>dataStruct</tt>
: The describes the data structure specified in the dbd <tt>link</tt> definition. It contains data used by the link support.
 
Note that link support always implements interface <tt>LinkDbdSupport</tt>
=== dbfDevice ===
 
A <tt>dbfDevice</tt> is similar to a <tt>dbfLink</tt> except that the interface implemented by the device support is also specified, i.e. instead of implementing interface <tt>LinkDbdSupport</tt>, the device support implements an interface that both record support and device support understand.
 
 
=== dbfArray ===
 
Discussion needed. Note that multi-dimensional arrays must also be described.
 
----
<center>
 
== Discussion of Standard Interfaces ==
 
</center>
=== <tt>StructDbdLifetime</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.
<tt>StructDbdLifetime</tt> is described as:
    class StructDbdLifetime {
    public:
        virtual StructDbdPtr create() = 0;
        virtual bool initialize(dbfString *errorMessage,
                                  StructDbdPtr ptr) = 0;
        virtual bool finalize(dbfString *errorMessage,
                                  StructDbdPtr ptr) = 0;
        virtual void destroy(StructDbdPtr ptr) = 0;
        virtual void *indexToAddr(dbfString *errorMessage,
                                  StructDbdPtr ptr, dbfInt16 index) = 0;
        // ???? is anything else needed
    };
where:
; <tt>create</tt>
: Creates storage for the struct or record.
; <tt>initialize</tt>
: initializes the struct or record
; <tt>finalize<tt>
: cleans up but does not free storage
; <tt>destroy</tt>
: frees storage
; indexToAddr
: Given an index it returns the address of the storage. Note the the generated header files assign an index to each field.
 
=== <tt>LinkDbdSupport</tt> ===
Not yet described
 
=== <tt>RecordDbdSupport</tt> ===
Not yet described




Line 67: Line 503:
     }
     }
=== Generated Header Files ===
=== 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>  
<tt>menuAlarmSevr.h</tt> is generated from <tt>menuAlarmSevr.dbd</tt>  
     enum menuAlarmSevr {
     enum menuAlarmSevr {
Line 76: Line 516:
<tt>displayLimit.h</tt> is generated from <tt>displayLimit.dbd</tt>  
<tt>displayLimit.h</tt> is generated from <tt>displayLimit.dbd</tt>  
     class displayLimit {
     class displayLimit {
         dbdFloat64 low;
    public:
         dbdFloat64 high;
         dbfFloat64 low;
         dbfFloat64 high;
     };
     };
     const dbdInt16 displayLimit_firstIndex = 1
     const dbfInt16 displayLimit_firstIndex = 1
     const dbdInt16 displayLimit_low        = 1
     const dbfInt16 displayLimit_low        = 1
     const dbdInt16 displayLimit_high      = 2
     const dbfInt16 displayLimit_high      = 2
     const dbdInt16 displayLimit_lastIndex =displayLimit_high
     const dbfInt16 displayLimit_lastIndex =displayLimit_high
<tt>exampleRecord.h</tt> is generated from <tt>exampleRecord.dbd</tt>  
<tt>exampleRecord.h</tt> is generated from <tt>exampleRecord.dbd</tt>  
     class exampleRecord {
     class exampleRecord {
     public:
     public:
         ...    All the fields from iocRecord.dbd
         ...    All the fields from iocRecord.dbd
         dbdFloat64 value;
         dbfFloat64 value;
         dbdStruct displayLimit;
         dbfStruct displayLimit;
     };
     };
      
      
     const dbdInt16 example_firstIndex = 1001001
     const dbfInt16 example_firstIndex = 1001001
     const dbdInt16 example_low = 1001001;
     const dbfInt16 example_low = 1001001;
     const dbdInt16 example_high = 1001002;
     const dbfInt16 example_high = 1001002;
     const dbdInt16 example_lastIndex = example_high;
     const dbfInt16 example_lastIndex = example_high;
<tt>alltypesRecord.h</tt> is generated from <tt>alltypesRecord.dbd</tt>  
<tt>alltypesRecord.h</tt> is generated from <tt>alltypesRecord.dbd</tt>  
     class allTypesRecord {
     class allTypesRecord {
     public:
     public:
         ...    All the fields from iocRecord.dbd
         ...    All the fields from iocRecord.dbd
         dbdRecord common;
         iocRecord common;
         dbdBoolean fbool;
         dbfBoolean fbool;
         dbdOctet   foctet;
         dbfOctet   foctet;
         dbdInt16   fint16;
         dbfInt16   fint16;
         dbdUInt16 fuint16;
         dbfUInt16 fuint16;
         dbdInt32   fint32;
         dbfInt32   fint32;
         dbdUInt32 fuint32;
         dbfUInt32 fuint32;
         dbdInt64   fint32;
         dbfInt64   fint32;
         dbdUInt64 fuint32;
         dbfUInt64 fuint32;
         dbdFloat32 ffloat32;
         dbfFloat32 ffloat32;
         dbdFloat64 ffloat64;
         dbfFloat64 ffloat64;
         dbdString fstring;
         dbfString fstring;
         dbdMenu   fmenu;
         dbfMenu   fmenu;
         dbdEnum   fenum
         dbfEnum   fenum
         dbdStruct fstruct;
         dbfStruct fstruct;
         dbdLink   flink;
         dbfLink   flink;
         dbdDevice fdevice;
         dbfDevice fdevice;
     };
     };
      
      
     const dbdInt16 allTypes_firstIndex = 1001001
     const dbfInt16 allTypes_firstIndex = 1001001
     const dbdInt16 allTypes_fbool = 1001001;
     const dbfInt16 allTypes_fbool = 1001001;
     const dbdInt16 allTypes_foctet = 1001002;
     const dbfInt16 allTypes_foctet = 1001002;
     const dbdInt16 allTypes_fint16 = 1001003;
     const dbfInt16 allTypes_fint16 = 1001003;
     const dbdInt16 allTypes_fuint16 = 1001004;
     const dbfInt16 allTypes_fuint16 = 1001004;
     const dbdInt16 allTypes_fint32 = 1001005;
     const dbfInt16 allTypes_fint32 = 1001005;
     const dbdInt16 allTypes_fuint32 = 1001006;
     const dbfInt16 allTypes_fuint32 = 1001006;
     const dbdInt16 allTypes_fint64 = 1001007;
     const dbfInt16 allTypes_fint64 = 1001007;
     const dbdInt16 allTypes_fuint64 = 1001008;
     const dbfInt16 allTypes_fuint64 = 1001008;
     const dbdInt16 allTypes_ffloat32 = 1001009;
     const dbfInt16 allTypes_ffloat32 = 1001009;
     const dbdInt16 allTypes_ffloatn64 = 10010010;
     const dbfInt16 allTypes_ffloatn64 = 10010010;
     const dbdInt16 allTypes_ffstring = 10010011;
     const dbfInt16 allTypes_ffstring = 10010011;
     const dbdInt16 allTypes_fmenu = 10010012;
     const dbfInt16 allTypes_fmenu = 10010012;
     const dbdInt16 allTypes_fenum = 10010013;
     const dbfInt16 allTypes_fenum = 10010013;
     const dbdInt16 allTypes_fstruct = 10010014;
     const dbfInt16 allTypes_fstruct = 10010014;
     const dbdInt16 allTypes_flink = 10010015
     const dbfInt16 allTypes_flink = 10010015
     const dbdInt16 allTypes_fdevice = 10010016
     const dbfInt16 allTypes_fdevice = 10010016
     const dbdInt16 allTypes_lastIndex = allTypes_fdevice;
     const dbfInt16 allTypes_lastIndex = allTypes_fdevice;
 
----
<center>
 
== dbdTypes.h ==
 
</center>
 
File dbdTypes.h describes the datatypes used by V4 databases:
 
/* TBD dbdNdimArrayT*/
enum dbdType {
    dbdUnknownT,dbdBooleanT,dbdOctetT,
    dbdInt16T,dbdUInt16T,dbdInt32T,dbdUInt32T,dbdInt64T,dbdUInt64T,
    dbdFloat32T,dbdFloat64T,
    dbdStringT,
    dbdStructT,
    dbdMenuT,dbdEnumT,
    dbdLinkT,dbdDeviceT,
    dbdArrayT
};
 
/* some of the following may require OSD definitions*/
typedef bool              dbdBoolean;
typedef char              dbdOctet;
typedef short              dbdInt16;
typedef unsigned short    dbdUInt16;
typedef int                dbdInt32;
typedef unsigned int      dbdUInt32;
typedef long long          dbdInt64;
typedef unsigned long long dbdUInt64;
typedef float              dbdFloat32;
typedef double            dbdFloat64;
 
class dbdRecord;
 
// dbdStructPtr always references a class generated from a struct dbd
typedef void * dbdStructPtr;
 
// dbdInterfacePtr always references a class that contains only methods
typedef void *dbdInterfacePtr;
 
class dbdInterface {
public:
    const char      *interfaceType;
    dbdInterfacePtr *pinterface;
};
 
/*dbdString holds UTF-8 characters*/
class dbdString {
public:
    dbdInt32  capacity;  /*capacity in bytes*/
    dbdOctet  *pstorage;
};
 
class dbdStructMember {
    dbdString name;
    dbdType  type;
};
 
class dbdStructDef{
    dbdString      name;
    dbdInt16        nmembers;
    dbdStructMember *pmember[];
    dbdInterface    interface;
};
 
class dbdStruct{ // for a field referencing a struct
    dbdStructDef *pdbdStructDef;
    dbdStructPtr ptr;
};
 
class dbdMenuDef{
public:
    dbdString name;
    dbdInt16  nchoices;
    dbdString *pchoice[];
};
 
class dbdMenu{ // for a struct or record field
public:
    dbdInt16    index;
    dbdMenuDef  *pdbdMenuDef[];
};
 
class dbdEnum{
public:
    dbdInt16  index;
    dbdInt16  nchoices;
    dbdString *pchoice[];
};
 
class dbdInterfaceDef {
public:
    dbdString interfaceName;
    dbdString choiceName;
    dbdString dataStructName;
    dbdInterface *pdbdInterface;
};
 
enum dbdLinkDir {
    dbdLinkDirNone,
    dbdLinkDirForward,
    dbdLinkDirIn,
    dbdLinkDirOut,
    dbdLinkDirInOut
};
class dbdLinkDef{
public:
    dbdLinkDir    dir;
    dbdString    choiceName;
    dbdInterface *pdbdInterface;
    dbdString    dataStructName;
};
class dbdLink{ // for a struct or record field
public:
    dbdLinkDir  dir;
    dbdString  choiceName;
    dbdLinkDef  *plinkDef;
    dbdStruct  dataStruct;
};
 
class dbdDeviceDef {
public:
    dbdLinkDir  dir;
    dbdString interfaceName;
    dbdString choiceName;
    dbdString dataStructName;
    dbdInterface *pdbdInterface;
};
 
class dbdDevice{ // for a struct or record field
public:
    dbdLinkDir  dir;
    dbdString    choiceName;
    dbdDeviceDef *pdeviceDef;
    dbdStruct    dataStruct;
};
 
template< class ARR_T > class dbdArray {
public:
    dbdInt32  capacity;  /*capacity in number of elements*/
    dbdInt32  size;      /*current number of elements*/
    dbdType  type;
    ARR_T    *pstorage;
};
 
/*  The following array types are supported by dbdCore
  *  dbdArray<void>;
  *  dbdArray<dbdOctet>;
  *  dbdArray<dbdInt16>;
  *  dbdArray<dbdUInt16>;
  *  dbdArray<dbdInt32>;
  *  dbdArray<dbdUInt32>;
  *  dbdArray<dbdInt64>;
  *  dbdArray<dbdUInt64>;
  *  dbdArray<dbdFloat32>;
  *  dbdArray<dbdFloat64>;
  *  dbdArray<dbdString>;
  *  dbdArray<dbdLinkField>;
**/
 
/* every struct and every record support module implements the following*/
class dbdStructMetaSupport {
    virtual dbdStructPtr create() = 0;
    virtual dbdBoolean initialize(dbdString *errorMessage, dbdStructPtr ptr) = 0;
    virtual dbdBoolean finalize(dbdString *errorMessage, dbdStructPtr ptr) = 0;
    virtual void destroy(dbdStructPtr ptr) = 0;
    virtual void *indexToAddr(dbdString *errorMessage,
            dbdStructPtr ptr, dbdInt16 index) = 0;
    // ???? is anything else needed
};
 
/* record support implements the following*/
class dbdRecordSupport {
    virtual void special(dbdRecord *pdbdRecord,
            dbdBoolean  after,
            dbdInt16 nlevels, // number of elements in fieldIndex
            dbdInt16 fieldIndex[] // array of field indices
            ) = 0;
};


----
----

Revision as of 20:14, 12 May 2005

EPICS: C++ class definitions for Database Definition

May 12 2005

UNDER CONSTRUCTION - DO NOT COMMENT

Overview

This document describes the C++ class definitions for code that implements the semantics for records created from Database Definitions. The definitions are intented by code that includes header files generated from dbd definitions and also by code that does not include the header files. Header files are generated from the following dbd definitions:

  • record
  • struct
  • menu



dbdTypes.h

File dbdTypes.h describes the datatypes used by V4 databases: The following naming conventions are used:

dbf
and name starting with dbf describes a struct or record field. For example dbfString describes a field(name,string).
*Dbf*
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 contains the following:

namespace Dbd {
/* TBD dbdNdimArrayT*/
enum dbfType {
    dbfUnknownT,dbfBooleanT,dbfOctetT,
    dbfInt16T,dbfUInt16T,dbfInt32T,dbfUInt32T,dbfInt64T,dbfUInt64T,
    dbfFloat32T,dbfFloat64T,
    dbfStringT,
    dbfStructT,
    dbfMenuT,dbfEnumT,
    dbfLinkT,dbfDeviceT,
    dbfArrayT
};
/* some of the following may require OSD definitions*/
typedef bool               dbfBoolean;
typedef char               dbfOctet;
typedef short              dbfInt16;
typedef unsigned short     dbfUInt16;
typedef int                dbfInt32;
typedef unsigned int       dbfUInt32;
typedef long long          dbfInt64;
typedef unsigned long long dbfUInt64;
typedef float              dbfFloat32;
typedef double             dbfFloat64;
/*dbfString holds UTF-8 characters*/
class dbfString {
public:
    dbfInt32  capacity;  /*capacity in bytes*/
    dbfOctet  *pstorage;
};
// FieldDbdPtr is the address of a dbfType
typedef void *FieldDbdPtr;
// StructDbdPtr references a class generated from a struct dbd
typedef void * StructDbdPtr;
// InterfacePtr references a class that contains only methods
typedef void *InterfacePtr;
class Interface {
public:
    dbfString    name;
    InterfacePtr interface;
};
// The following Interfaces are described below
class StructDbdLifetime;
class LinkDbdSupport;
class StructDbdMember {
public:
    dbfString name;
    dbfType   type;
};
class StructDbd{
public:
    dbfString    name;
    dbfInt16     nmembers;
    Interface    *plifetime; // references a StructDbdLifetime
    StructDbdMember *pmember[]; // ptr to array of ptr to StructDbdMember
};
class dbfStruct{
public:
    StructDbd *pstructDef;
    StructDbdPtr ptr;
};
class MenuDbfDef{
public:
    dbfString name;
    dbfInt16  nchoices;
    dbfString *pchoice[];
};
class dbfMenu{
public:
    dbfInt16    index;
    MenuDbfDef  *pmenuDef;
};
class dbfEnum{
public:
    dbfInt16  index;
    dbfInt16  nchoices;
    dbfString *pchoice[];
};

enum LinkDir {
    LinkDirNone,
    LinkDirForward,
    LinkDirIn,
    LinkDirOut,
    LinkDirInOut
};
class LinkDbd{ //describes dbd link statement
public:
    LinkDir    dir;
    dbfString     choiceName;
    dbfString     dataStructName;
    InterfacePtr *pinterface;
};
class dbfLink{ 
public:
    LinkDir  dir;
    dbfString   choiceName;
    LinkDbd  *plinkDef; //LinkDbd will reference a LinkDbdSupport
    dbfStruct   dataStruct;
};
class DeviceDbd { //describes dbd device statement
public:
    LinkDir   dir;
    dbfString    interfaceName;
    dbfString    choiceName;
    dbfString    dataStructName;
    InterfacePtr *pinterface;
};
class dbfDevice{
public:
    LinkDir   dir;
    dbfString    choiceName;
    DeviceDbd *pdeviceDef;
    dbfStruct    dataStruct;
};
template< class ARR_T > class dbfArray {
public:
    dbfInt32  capacity;  /*capacity in number of elements*/
    dbfInt32  size;      /*current number of elements*/
    dbfType   type;
    ARR_T     *pstorage;
};
/*  The following array types are supported by dbdCore
 *  dbfArray<void>;
 *  dbfArray<dbfOctet>;
 *  dbfArray<dbfInt16>;
 *  dbfArray<dbfUInt16>;
 *  dbfArray<dbfInt32>;
 *  dbfArray<dbfUInt32>;
 *  dbfArray<dbfInt64>;
 *  dbfArray<dbfUInt64>;
 *  dbfArray<dbfFloat32>;
 *  dbfArray<dbfFloat64>;
 *  dbfArray<dbfString>;
 *  dbfArray<dbfLinkField>;
**/
// The following describes record types and record instances
class UserDbdField;
class userFieldHandler {
public:
    virtual bool initialize(dbfString *errorMessage,
                     iocRecord *precord,UserDbdField *puserField) = 0;
    virtual bool finalize(dbfString *errorMessage,
                     iocRecord *precord,UserDbdField *puserField) = 0;
    virtual bool process(dbfString *errorMessage,
                     iocRecord *precord,UserDbdField *puserField) = 0;
};
class UserDbdField {
public:
    dbfString   name;
    dbfType     type;
    FieldDbdPtr pfield;
    InterfacePtr *pinterface; // references userFieldHandler
}
class RecordDbdField {
public:
    dbfString name;
    dbfType   type;
};
    
class RecordDbd { // describes a record type
    dbfArray< UserDbdField > userField;
    dbfArray< RecordDbdField > recField;
    Interface    *plifetime; // references a StructDbdLifetime
}
// every struct and every record support module implements the following
// The implementation is generated from the dbd definition
class StructDbdLifetime {
public:
    virtual StructDbdPtr create() = 0;
    virtual bool initialize(dbfString *errorMessage,
                             StructDbdPtr ptr) = 0;
    virtual bool finalize(dbfString *errorMessage,
                             StructDbdPtr ptr) = 0;
    virtual void destroy(StructDbdPtr ptr) = 0;
    virtual void *indexToAddr(dbfString *errorMessage,
                             StructDbdPtr ptr, dbfInt16 index) = 0;
    // ???? is anything else needed
};
// every link support module implements the following interface
class LinkDbdSupport {
public:
    virtual void report(dbfString *errorMessage,
                     iocRecord *precord, dbfLink *pdbfLink) = 0;
    virtual bool initialize(dbfString *errorMessage,
                     iocRecord *precord, dbfLink *pdbfLink) = 0;
    virtual bool finalize(dbfString *errorMessage,
                     iocRecord *precord, dbfLink *pdbfLink) = 0;
    virtual bool connect(dbfString *errorMessage,
                     iocRecord *precord, dbfLink *pdbfLink) = 0;
    virtual bool disconnect(dbfString *errorMessage,
                     iocRecord *precord, dbfLink *pdbfLink) = 0;
    virtual bool get(dbfString *errorMessage,
                     iocRecord *precord, dbfLink *pdbfLink,
                     dbfType type, FieldDbdPtr pfield) = 0;
    virtual bool put(dbfString *errorMessage,
                     iocRecord *precord, dbfLink *pdbfLink,
                     dbfType type, FieldDbdPtr pfield) = 0;
};
/* record support implements the following*/
class RecordDbdSupport {
public:
    virtual iocRecord *create(dbfString *errorMessage) = 0;
    virtual bool destroy(dbfString *errorMessage, iocRecord *precord) = 0;
    virtual bool init(dbfString *errorMessage,
                     iocRecord *precord, bool firstPass) = 0;
    virtual void special(iocRecord *precord, iocRecord *precord,
            bool  after,
            dbfInt16 nlevels, // number of elements in fieldIndex
            dbfInt16 fieldIndex[] // array of field indices
            ) = 0;
};
}; // namespace Dbd

Discussion of dbfTypes

Primitive Types

The types dbfBoolean, dbfOctet, dbfInt16, dbfUInt16, dbfInt32, dbfUInt32, dbfInt64, dbfUInt64, dbfFloat32, dbfFloat64 all map to a C primitive type. Currently the C type is defined in iocTypes.h. It may be necessary to provide operating system dependent definitions for some of the types. For example on some architectures a dbfInt64 may have to be defined as a C long rather than a long long.

If a record is defined as:

    record(xxx) extends iocRecord {
        ...
        field(fbool,bool)
        field(foctet,octet)
        ...
        field(ffloat64,float64)
        ...
    }

Then the generated header file will be

    class xxxRecord : iocRecord {
    public:
        dbfBoolean fbool;
        dbfOctet   foctet;
        ...
        dbfFloat64 ffloat64;
        ...
   };

dbfType dbfTypeUnknownT is reserved for unknown types and will normally be cause by some configuration error.

dbfString

dbfString is described as:

    class dbfString {
    public:
        dbfInt32  capacity;  /*capacity in bytes*/
        dbfOctet  *pstorage;
    };

If a record definition contains

    field(sfield,string)

Then the generated header file contains

    dbfString sfield;

pstoragewill always be the address of a UTF-8 null terminated character string. The capacity is the the number of bytes referenced by pstorage <bold>NOT</bold> the number of characters.

dbfStruct

<dbfStruct> is described as:

    class dbfStruct{
    public:
        StructDbd *pstructDef;
        StructDbdPtr ptr;
    };

If a record definition contains

    field(sstruct,struct(name))

Then the generated header file contains

    dbfStruct sfield;

dbfStruct:ptr is the address of storage for the structure and pstructDef is the address of a description of the structure. The members of StructDbd are:

name
The name of the struct.
nmembers
The number of members, e.g. fields in the structure.
plifetime
The address of an implementation of interface StructDbdLifetime. The implementation is automatically generated from the dbd struct statement. See below for a description of the StructDbdLifetime methods.
pmember
pointer to an array of pointers to StructDbdMember. Each StructDbdMember contains the name and type of the member.

Note that given a dbfStruct it is possible to locate both the address and description of the associated structure.


dbfMenu

<dbfMenu> is described as:

    class dbfMenu{
    public:
        dbfInt16    index;
        MenuDbfDef  *pmenuDef;
    };

If a record definition contains

    field(fmenu,menu(name))

Then the generated header file contains

    dbfMenu fmenu;

The definition of dbfMenu provides the current menu index and also the menu definition.

dbfEnum

<dbfEnum> is described as:

    class dbfEnum{
    public:
        dbfInt16  index;
        dbfInt16  nchoices;
        dbfString *pchoice[];
    };

If a record definition contains

    field(fenum,enum)

Then the generated header file contains

    dbfEnum fenum;

The definition of dbfEnum provides the current enum index as well as a description on all the choices associated with the enum.

dbfLink

dbfLink is described as

    class dbfLink{ 
    public:
        LinkDir  dir;
        dbfString   choiceName;
        LinkDbd  *plinkDef; //LinkDbd will reference a LinkDbdSupport
        dbfStruct   dataStruct;
    };

If a record definition contains

    field(flink,link(in))

Then the generated header file contains

    dbfLink flink;

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

Each dbd link definition has an asociated C description:

    class LinkDbd{ //describes dbd link statement
    public:
        LinkDir    dir;
        dbfString     choiceName;
        dbfString     dataStructName;
        InterfacePtr *pinterface;
    };

The members 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.
choiceName
The record instance specifies this and it is used to locate the associated dbd link definition.
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.


dbfArray

Discussion needed. Note that multi-dimensional arrays must also be described.



Discussion of Standard Interfaces

StructDbdLifetime

Every dbd struct and record has an associated StructDbdLifetime interface implementation. A tool is provided that automatically generates the implementation form the dbd definition. StructDbdLifetime is described as:

    class StructDbdLifetime {
    public:
        virtual StructDbdPtr create() = 0;
        virtual bool initialize(dbfString *errorMessage,
                                 StructDbdPtr ptr) = 0;
        virtual bool finalize(dbfString *errorMessage,
                                 StructDbdPtr ptr) = 0;
        virtual void destroy(StructDbdPtr ptr) = 0;
        virtual void *indexToAddr(dbfString *errorMessage,
                                 StructDbdPtr ptr, dbfInt16 index) = 0;
        // ???? is anything else needed
    };

where:

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

LinkDbdSupport

Not yet described

RecordDbdSupport

Not yet described



Example Database Definition Files

Database Definition Files

menuAlarmSevr.dbd contains:

    menu(menuAlarmSevr) { 
         choice("NO_ALARM") 
         choice("MINOR")
         choice("MAJOR")
         choice("INVALID")
    }

displayLimit.dbd contains:

    struct(displayLimit) {
        field(low,float64)
        field(high,float64)
    }

exampleRecord.dbd contains:

    record(example) extends iocRecord {
        field(value,float64)
        field(displayLimit,struct(displayLimit))
    }

alltypesRecord.dbd 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)
        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

menuAlarmSevr.h is generated from menuAlarmSevr.dbd

    enum menuAlarmSevr {
           menuAlarmSevrNO_ALARM,
           menuAlarmSevrMINOR,
           menuAlarmSevrMAJOR,
           menuAlarmSevrINVALID
    };

displayLimit.h is generated from displayLimit.dbd

    class displayLimit {
    public:
        dbfFloat64 low;
        dbfFloat64 high;
    };
    const dbfInt16 displayLimit_firstIndex = 1
    const dbfInt16 displayLimit_low        = 1
    const dbfInt16 displayLimit_high       = 2
    const dbfInt16 displayLimit_lastIndex =displayLimit_high

exampleRecord.h is generated from exampleRecord.dbd

    class exampleRecord {
    public:
        ...    All the fields from iocRecord.dbd
        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;

alltypesRecord.h is generated from alltypesRecord.dbd

    class allTypesRecord {
    public:
        ...    All the fields from iocRecord.dbd
        iocRecord  common;
        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
        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_fstruct = 10010014;
    const dbfInt16 allTypes_flink = 10010015
    const dbfInt16 allTypes_fdevice = 10010016
    const dbfInt16 allTypes_lastIndex = allTypes_fdevice;