Difference between revisions of "V4 Design: dbdClass"

From EPICSWIKI
 
(17 intermediate revisions by the same user not shown)
Line 1: Line 1:
== EPICS: dbdClasses - IOC records data == May 24 2005
This page is obsolete. It is replaced by dbdInterfaces.
<center>
 
== Overview ==
 
</center>
 
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:
** <tt>record</tt> - Should only be included by record support.
** <tt>struct</tt> - Included by code that understands the struct.
** <tt>menu</tt> - Included by code that understands the menu.
*  does not include the header files.
 
The following headers files are described:
* <tt>dbfTypes.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>dbdInterfaces.h</tt> - Type definitions for interfaces related to DBD definitions.
 
----
<center>
 
== dbfTypes ==
</center>
File <tt>dbfTypes.h</tt> describes types and classes that are used in header
files generated from dbd <tt>struct</tt> or <tt>record</tt> field definitions.
The following naming conventions are used:
; Dbf
: any class starting with Dbf describes a non epicsType struct or record field as it appears in a generated header file. For example DbfString describes a field generated from <tt>field(name,string)</tt>.
; Dbd
: A class name starting with Dbd describes something directly related to a dbd statement. For example DbdLinkSupport describes a dbd link definition.
 
=== <tt>dbdTypes.h</tt> ===
enum dbfType {
    dbfUnknownT,
    dbfEpicsT,  // an epicsType except epicsUnknownT
    dbfArrayT,
    dbfStructT,
    dbfMenuT,
    dbfEnumT,
    dbfLinkT,
    dbfDeviceT
};
 
class DbdStruct; //describes a dbd struct definition
class DbdMenu; //describes a dbd menu definition
class DbdLink;    //describes dbd link statement
class DbdDevice;  //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:
    DbdStruct *pDbdStruct;
    void        *pstorage;
};
 
class DbfMenu{
public:
    epicsInt16    index;
    DbdMenu  *pmenuDef; /* address of global menu */
};
 
class DbfEnum{
public:
    epicsInt16  index;
    EpicsArray  *pchoiceArray; // addr of field that is array of string
};
enum LinkDir {
    LinkDirNone,
    LinkDirForward,
    LinkDirIn,
    LinkDirOut,
    LinkDirInOut
};
 
class DbfLink{
public:
    LinkDir  dir;
    DbdLink  *plinkDef;
    EpicsStruct dataStruct;
};
 
class DbfDevice{
public:
    LinkDir  dir;
    DbdDevice *pDbdDevice;
    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 <tt>struct</tt> and <tt>record</tt> dbd definitions.
 
====  Epics Types ====
 
DBD types bool,...,string all become an epicsType.
 
DBD type array becomes an EpicsArray if the array type maps to an epicsType
or to DbfArray if the type is not an epicsType.
 
DBD type struct maps to EpicsStruct if all fields in the struct map to
an epicsType other than epicsUnknownT or otherwise to DbfStruct.
 
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 ====
<tt>DbfMenu></tt> is described as:
    class DbfMenu{
    public:
        epicsInt16    index;
        DbdMenu  *pmenuDef;
    };
 
If a record definition contains
    field(fmenu,menu(name))
Then the generated header file contains
    DbfMenu fmenu;
<tt>DbfMenu</tt> provides the current menu index and also the menu definition.
 
==== DbfEnum ====
<tt>DbfEnum></tt> 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;
<tt>pchoiceArray</tt> is the address of a field in the same record that is a
DbfArray of choices.
==== DbfLink ====
<tt>DbfLink</tt> is described as
    class DbfLink{
    public:
        LinkDir  dir;
        DbdLink  *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 <tt>link</tt> definition that matches the <tt>dir</tt> specified in the dbd <tt>field</tt> definition.
 
The fields 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>DbdLink</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>plinkDef</tt>
: This is the address of the <tt>DbdLink</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>DbdLinkSupport</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>DbdLinkSupport</tt>, the device support implements an interface that both record support and device support understand.
 
 
----
<center>
 
== dbdStatements ==
 
</center>
The classes in <tt>dbdStatements.h</tt> allow introspection of ioc records. They describe everything defined in DBD definitions.
 
=== <tt>dbdStatements.h</tt> ===
 
 
// 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 DbdStruct{
public:
    EpicsString    name;
    Interface    *plifetime; // references a StructLifetime
    epicsInt16    nfields;
    StructDbdField *pfield[]; // ptr to array of ptr to StructDbdField
};
 
class DbdMenu{
public:
    EpicsString name;
    epicsInt16  nchoices;
    EpicsString *pchoice[];
};
 
class DbdLink{ //describes dbd link statement
public:
    LinkDir    dir;
    EpicsString  choiceName;
    EpicsString  dataStructName;
    Interface  *pinterface;
};
 
class DbdDevice { //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 <tt>struct</tt> or <tt>record</tt> definition. The classes are : <tt>DbdStruct</tt>, <tt>StructDbdField</tt>,and <tt>StructFieldAttribute</tt>
 
The fields of <tt>DbdStruct</tt> are:
; <tt>name</tt>
: The name of the struct.
; <tt>plifetime</tt>
: 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>
: The number of fields, e.g. fields in the structure.
; <tt>pfields</tt>
: pointer to an array of pointers to <tt>StructDbdField</tt>.
 
The fields of <tt>StructDbdField</tt> are:
; <tt>name</tt>
: 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>
: The dbfType for the field. Note that unless basic is epicsUnknownT this has the value dbfEpicsT.
; <tt>pattribute</tt>
: The address of a StructFieldAttribute for the field
 
<tt>StructFieldAttribute</tt> has the attribute values for the field.
 
==== Menu ====
 
A dbd <tt>menu</tt> is described by class DbdMenu
 
The fields of DbdMenu are:
; <tt>name</tt>
: The menu name.
; <tt>nchoices</tt>
: The number of menu choices.
; <tt>pchoice</tt>
: The address of an array of pointers to EpicsString. Each EpicsString is a choice.
 
==== Link and Device ====
 
Each dbd <tt>link</tt> definition has an associated class <tt>DbdLink</tt> with fields:
; <tt>dir</tt>
: The link direction
; <tt>choiceName</tt>
: The name that matches a DbdLink for a DbfLink instance.
; <tt>dataStructName</tt>
: The class name of a DbfStruct for the Interface implementation
; <tt>pinterface</tt>
: The address of the Interface implementation. The interface class is DbdLinkSupport
 
Each dbd <tt>device</tt> definition has an associated class <tt>DbdDevice</tt> with fields:
; <tt>dir</tt>
: The link direction
; <tt>interfaceName</tt>
: The name of the interface class implemented by the device support
; <tt>choiceName</tt>
: The name that matches a DbdDevice for a DbfDevice instance.
; <tt>dataStructName</tt>
: The class name of a DbfStruct for the Interface implementation
; <tt>pinterface</tt>
: The address of the Interface implementation.
 
==== Record ====
A record type has an associated class: <tt>RecordDbd</tt>.
The fields of <tt>RecordDbd</tt> are the same as fields in <tt>DbdStruct</tt> except that they refer to a record instead of a structure.
; <tt>name</tt>
: The name of the record.
; <tt>plifetime</tt>
: 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>
: The number of fields, e.g. fields in the record.
; <tt>pfields</tt>
: pointer to an array of pointers to <tt>StructDbdField</tt>. Each StructDbdField contains the name and type of the fields.
; <tt>puserField</tt>
: Address of an array of pointers to <tt>UserDbdField</tt>.
 
 
==== Record Instance ====
 
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>name</tt>
: The name of the user defined field
; <tt>type</tt>
: The dbfType for the field.
; <tt>pfield</tt>
: Address of storage for field.
; <tt>pinterface</tt>
: The address of an implementation of interface userFieldHandler;
 
The fields of <tt>RecordInstance</tt> are:
 
; <tt>name</tt>
: The name of the record instance
; <tt>pRecordDbd</tt>
: The address of the description of the record type
; <tt>precord</tt>
: The address of the record itself.
; <tt>puserField</tt>
: The address of a array of pointers to UserDbdField
 
----
<center>
 
== dbdInterfaces ==
 
dbdInterfaces describes standard interfaces implemented by code that
supports runtime database access.
 
</center>
 
=== <tt>dbdInterfaces.h</tt> ===
<tt>dbdInterfaces.h</tt> 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 DbdLinkSupport {
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 ===
==== <tt>StructLifetime</tt> ====
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>StructLifetime</tt> has the following fields:
; <tt>allocate</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
; <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.
 
==== <tt>DbdLinkSupport</tt> ====
This describes the interface implemented by link support.
==== <tt>RecordDbdSupport</tt> ====
This is the interface implemented by record support.
==== <tt>UserFieldHandler</tt> ====
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);
    };

Latest revision as of 19:53, 11 August 2005

This page is obsolete. It is replaced by dbdInterfaces.