V4 Design: dbdClass
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 intended for code that:
- includes header files generated from dbd definitions. Header files are generated from the following dbd definitions:
- record
- struct
- 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.
dbfFields
dbfFields.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:
/* 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 are described in dbdStatements.h 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>; **/
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.
dbdStatements
dbdStatements.h
dbdStatements.h contains the following:
// 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 }
Discussion of dbdStatements
NOT YET DONE
dbdInterfaces.h
dbdInterfaces.h
dbdInterfaces.h contains the following:
// 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; };
Discussion of dbdInterfaces
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 of Generated Header Files
Database Definition Files
menuAlarmSevr.dbd contains:
menu(menuAlarmSevr) { choice(menuAlarmSevrNO_ALARM,"NO_ALARM") choice(menuAlarmSevrMINOR,"MINOR") choice(menuAlarmSevrMAJOR,"MAJOR") choice(menuAlarmSevrINVALID,"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;