V4 Design: Database Initialization
EPICS: IOC Database Initialization
May 26 2005
Overview
This document gives a summary of actions required to initialize an IOC database. This includes actions that must be taken when an IOC is booted and also during on-line add/delete of record intances, link support, and device support.
QUESTION? Should iocRecord.dbd define a field
field(pDbdRecord,private("DbdRecord *")
Perhaps not since DbdRecordInstance is passed to DbdRecordSupport
IOC Initialization
What must be done to prepare an IOC? This should include everything so that an IOC is prepared to handle everything connected with an IOC database. This includes things like:
- error logging system
- scan threads
- ???
record types, etc
This section describes how the following are created.
- DbdStructList - The list of the description of each structure type.
- DbdRecordList - The list of the description of each record type.
- DbdLinkList - The list of the description of each DBD link definition
- DbdDeviceList - The list of the description of each DBD device definition.
Not yet defined. Some Questions
- What is done by loading an executable that includes support code?
- What must be done by iocInit?
- How is on-line add/delete of new support code handled?
DbdRecordEpicsFieldPutString
This is an interface that is implemented by iocCore. It is responsible for
taking a string and converting to an epicsType.
It is defined as an interface instead of a class with static methods for consistency.
For all methods if pfrom.pbuffer is null an exception is raised.
epicsPrimitive
This implements:
epicsPrimitive(EpicsString *pfrom,epicsType type,void *pstorage) = 0;
type must be one of epicsBooleanT, ..., epicsFloat64T.
The string in pfrom is converted to type.
epicsString
This implements
epicsString(EpicsString *pfrom,EpicsString *pEpicsString)
It copies pfrom to pEpicsString.
epicsArray
This implements
epicsArray(EpicsString *pfrom, EpicsArray *pEpicsArray)
The array type must be one of epicsBooleanT, ..., epicsStringT. pfrom must be DBD array syntax .
For each array element epicsArray calls either epicsPrimitive or epicsString to do the conversion.
epicsStruct
This implements
epicsStruct(EpicsString *pfrom, EpicsStruct *pEpicsStruct)
pfrom must be DBD struct syntax .
For each struct field epicsStruct calls either epicsPrimitive or epicsString or epicsArray to do the conversion.
epicsMDArray
This implements
epicsMDArray(EpicsString *pfrom,EpicsMDArray *pEpicsMDArray)
The array type must be one of epicsBooleanT, ..., epicsStringT. pfrom must be DBD array syntax .
For each array element epicsMDArray calls either epicsPrimitive or epicsString to do the conversion.
iocLoadRecords
iocLoadRecords loads and initializes new record instances. This can be done during IOC initialization or on-line.
Initialization consists of the following phases:
- Allocate storage
- Allocate buffer managers
- Initialize storage
- Initialize external connections
- Enable record processing
Allocate Storage
Storage is allocated for each record and for any structures that are part of the record. Note that buffer storage for strings and arrays are not allocated during this phase.
For each instance of the set of records being loaded do the following:
pDbdRecord is set to record type pDbdRecordInstance = alloc pDbdRecordInstance->pDbdRecord = pDbdRecord; pDbdRecordInstance->precord = pDbdRecord->plifetime->allocate for each pDbdStructField in pDbdRecord->pfield[] get address of field via pDbdRecord->plifetime->expose switch pDbdStructField->type case dbfEpicsT if(pDbdStructField->basic==epicsStructT) pEpicsStruct = pDbdRecord->plifetime=>expose initialize pEpicsStruct->pstructDef pEpicsStruct->pstorage = pEpicsStruct->pstructDef->plifetime->allocate default: nothing to do for other basic types case dbfStructT pDbfStruct = pDbdRecord->plifetime=>expose initialize pDbfStruct->pDbdStruct; pDbfStruct->pstorage = pDbfStruct->pDbdStruct->plifetime->allocate case dbfMenuT initialize pDbfMenu->pmenuDef case dbfEnumT initialize pDbfEnum->pchoiceArray case dbfLinkT initialize pDbfLink->dir initialize pDbfLink->plinkDef initialize pDbfLink->dataStruct.pstructDef pDbfLink->dataStruct.pstorage = pDbfLink->dataStruct.pstructDef->plifetime->allocate case dbfDeviceT initialize pDbfDevice->dir initialize pDbfDevice->pDbdDevice initialize pDbfDevice->dataStruct.pstructDef pDbfDevice->dataStruct.pstorage = pDbfDevice->dataStruct.pstructDef->plifetime->allocate
DbdRecordLifetime.allocate just allocates storage for the record instance not for any arrays or structures that are part of the record.
EpicsStructDef.plifetime.allocate must allocate storage for an instance of itself and if any of its fields are of type epicsStructT it must
initialize pEpicsStruct->pstructDef by locating the fields EpicsStructDef pEpicsStruct->pstorage = pEpicsStruct->pstructDef->plifetime->allocate
DbdStruct.plifetime.allocate must allocate storage for an instance of itself and also allocate storage associated with fields of type epicsStructT or dbfStructT.
For epicsStructT fields it must
initialize pEpicsStruct->pstructDef by locating the fields EpicsStructDef pEpicsStruct->pstorage = pEpicsStruct->pstructDef->plifetime->allocate
For dbfStructT fields it must
initialize pDbfStruct->pDbdStruct by locating the fields DbdStruct pDbfStruct->pstorage = pDbfStruct->pDbdStruct->plifetime->allocate
Allocate Buffer Managers
The buffer managers associated with epicsStringT, epicsArrayT, epicsStructT, epicsMDArrayT, dbfArrayT, and dbfStructT are allocated during this phase. Allocating the buffer managers is the responsibility of record support. Record support may call interfaces associated with epicsStructT or dbfStructT so that aother support can decide the type of buffer manager.
Thus for each record instance the following is called
pDbdRecord->psupport->initBuffers
Initialize storage
The allocated storage is initialized. This does NOT include initializing connections outside the record.
For each instance of the set of records being loaded do the following:
for each DbdStructField in DbdRecord.pfield EpicsString *pfrom = DbdStructField.pattribute.default if(pfrom->pbuffer==null) next // no default defined get address of field via DbdRecordLifetime.expose switch DbdStructField.type case: epicsBooleanT, ..., epicsFloat64T DbdRecordEpicsFieldPutString:epicsPrimitive break; case: epicsStringT DbdRecordEpicsFieldPutString:epicsString break; case: epicsArrayT DbdRecordEpicsFieldPutString:epicsArray break; case: epicsStructT DbdRecordEpicsFieldPutString:epicsStruct break; case: epicsMDArrayT DbdRecordEpicsFieldPutString:epicsMDArray break; case: dbfArrayT case: dbfStructT do nothing. Let record support handle it case: dbfMenuT index = DbdRecordEpicsFieldPutString:epicsPrimitive case dbfEnumT index = DbdRecordEpicsFieldPutString:epicsPrimitive case dbfLinkT dataStruct = DbdRecordEpicsFieldPutString:epicsStruct case dbfDeviceT dataStruct = DbdRecordEpicsFieldPutString:epicsStruct
Initialize connections
The next step is to make external connections from record instances. This is the responsibility of record support. Record support may call interfaces associated with link and/or device support.
Thus for each record instance the following is called
pDbdRecord->psupport->initConnections