Difference between revisions of "V4 Design: Record Processing"

From EPICSWIKI
 
(12 intermediate revisions by the same user not shown)
Line 1: Line 1:
= EPICS V4: Record Processing =
EPICS V4: Record Processing November 02 2005  
August 18 2005  


----
----


<center>
= Overview =
== Overview ==
 
</center>
<b>UNRESOLVED ISSUES</b>
* This document is still evolving
* Monitors
** How will monitor data be managed?
** Big problem is how will array data be managed?
* Alarms
** How will V4 handle alarms?
* Events
** What is the V4 event model?
** What is required from the IOC database?
 
This document described semantics for V4 record processing that are
different than for V3.
This includes the following:
* Semantics for record processing
* Semantics for Database and Channel Access Links.
* Record Locking
* Posting database monitors
* Status and Alarm Severity
* Access to array and structure fields.


This version is based on feedback from the EPICS core developer's
This version is based on feedback from the EPICS core developer's
meeting at ANL/APS on July 11th through July 14th.
meeting at ANL/APS on July 11th through July 14th.
It is also a companion to the V4 Design: dbdInterfaces wiki.
In addition discussions with Andrew Johnson and Eric Norum have
led to many of the ideas described below.
This wiki is a companion to the wiki "V4 Design: dbdInterfaces".


The V3 record processing semantics do not work well for data
V3 record processing semantics do not work well for data
acquisition applications. An example of data acquisition is:
acquisition applications. An example of data acquisition is:
*  Move sample to new position.
*  Move sample to new position.
Line 28: Line 48:


Leaving PACT 0 but not calling recGblFwdLink was not anticipated when the V3 record processing semantics were created.
Leaving PACT 0 but not calling recGblFwdLink was not anticipated when the V3 record processing semantics were created.
For V4 it must be posssible for a record to be processed while it is waiting
For V4 a record can be processed while it is waiting
for asynchronous processing to complete.
for asynchronous processing to complete.


Line 37: Line 57:
V4 record processing is designed to make data acquisition easier.
V4 record processing is designed to make data acquisition easier.
Both input and output links can wait for record processing.
Both input and output links can wait for record processing.
This must be done, however, without record support blocking.
This is done, however, without record support blocking.
If blocking makes it easier to implement record support,
If blocking makes it easier to implement record support,
then the support can spawn a separate thread that does block.
then the support can spawn a separate thread that does block.
Line 46: Line 66:


<center>
<center>
== V4 Link Semantics ==
= Overview of V4 Record Processing =
  </center>
  </center>


Lets first state some goals for linking to other records:
V4 will provide a replacement for dbProcess.
The name may be different but for now it will still be called dbProcess.
 
In V4 database access and channel access appear the same to record and
link support.
Only the implementation knows the difference.
In this document the term channelAccess will mean access to a record.
Thus it can mean a workstation client or a field of
a record that is a link to a record.
 
V4 also allows support for <b>struct</b> fields.
For example base provides support for
    field(common,struct(RecordCommon))
In the record types provided with base, this is the first field.
The fields in <tt>RecordCommon</tt> are the V4 replacement for
the V3 dbCommon fields.


NOTE: Instead of "forward link" the name "process link" is used.


The features described next apply to both database and channel access links.
V4 record processing has the following features.


* Input Link from another record
* database fields
** get current value
** "owned" by database not record support
** wait until next record process and get value
** fields can only be accessed via interfaces
** request process, wait, get value
** support can optionally provide storage for data associated with a field
* Output Link to another record
** for channelAccess all fields appear as type primitive, string, struct, array or combination thereof
** put value
* dbProcess
** put value and request process
** processes synchronous linked records by queuing requests rather than recursive calls to dbProcess
** put value, request process, wait
** can be called an arbitrary number of times while record is active
* process link to another record
* link
** request processing
** always has associated support
** request processing and wait
** can be record link or can be something else, e.g. a link to hardware
* all links to other records
* record link
** Allow simultaneous requests, i.e. process and wait in parallel
** can request process and/or wait for asynchronous completion
** process one link at a time, i.e. process and wait serially.
** local synchronous requests queued by dbProcess
** record is active and can be processed while asynchronous links active
* struct fields
** Can have associated support which can be synchronous or asynchronous
* block
** is requested via a separate field
** if true than support waits for all outstanding I/O to complete before further processing
** if false than asynchronous support can proceed in parallel
* lock
** record instances are locked
** dbProcess locks before calling support
** other code can also lock
** Two records can be locked without deadlock
* monitors
** dbProcess handles monitors
** support triggers monitors by writing to fields


NOTE: wait does NOT mean to block. It means to save state, return,
and resume at the saved state when called again.


----
<center>
<center>
== V4 Processing States ==
= Database Fields =
  </center>
  </center>
== Field Access by Support Code ==
Support code can access database fields only via interfaces implemented by
the IOC database.
Thus record fields are owned by the IOC database not by record support.
Support code can register to provide storage for particular fields.
For example support code could implement a circular buffer for field <tt>value</tt>.
When some other code
request the array associated with <tt>value</tt>, the IOC database
calls the support. The support returns the first portion of the circular
buffer and the caller must make an additional call to retrieve the rest of
the circular buffer.
== Field Access by Channel Access ==


Instead of the V3 PROC field, V4 will have a field processState.
For V4 database access and channel access appear the same to record
This field has the states:
instances.
; processIdle
It is only the code that implements link support that knows the difference.
: record is not being processed
If a linked record is local, database access is used, and, if the record
; processInputActive
is remote, channel access.
: waiting for input links to complete
 
; processActive
V4 allows channel access to the following types of fields:
: record is waiting for completion of record specific activity
 
; processOutputActive
* primitive types
: waiting for output and process links to complete
* string
; processDone
* one dimensional array of primitive or string or struct
: process has completed.
* struct with fields of following types:
** primitive
** string
** struct
** array of primitive or string or struct


NOTES:
For other database field types, i.e. links, the database will make the field
* Each state may have substates. For example if a record has multiple input links that are to be processed sequentially, it can keep state describing which link is being processed. 
appear as one of the above types. For example a link field will appear
* Individual record types might use only a subset of the above states.
as a string with syntax that matches the information associated with the link.
* V3 link instances had attributes like CA, CP, CPP. For V4 these should be something like:
For example a process link will have a string something like
** process - a request to process the record before gets or after puts.
    support(processLink) ProcessLink(pvname = 'pvname'; wait = true)
** wait - a request to wait until it has processed all it's input links
where
** parallel - OK to allow simultaneous gets or puts
; <tt>processLink</tt>
: selects the support for a process link
; <tt>ProcessLink</tt>
: Names the struct that the support uses for configuration information




----
<center>
<center>
== dbProcess ==
= Record Processing Semantics =
  </center>
  </center>


The functionality described in this section will be divided between
This section describes the semantics implemented by dbProcess.
iocCore and iocRecord. iocRecord is the V4 successor to the V3 dbCommon.
 
For V4 it is a separate software component.
The following are involved in record processing
* dbProcess
** implements a queue for local records that are processed because of record links
** posts monitors caused by field changes during record processing
* record support
** calls support code for RecordCommon fields
** is responsible for record instance fields
** calls link/struct support via interfaces implemented by the support
* link support
** can be links to other records, to driver support, etc
** implements interfaces called by record and/or other support
* struct support
** is responsible for the fields in the struct
** implements interfaces called by record and/or other support
 
== Processing Life Cycle ==
Assume a record instance is idle, i.e. is ready to start processing.
*dbProcess calls record support with one of the following states
** processCancel - record support must terminate any outstanding processing
** processStart - start processing. record support returns one of
*** processDone - All done and successful
*** processQuit - dont do any more processing. Return to idle state
*** processActive - not done. Call again
** processContinue - another request to process while record is active. Record support again returns one of the above.
 
Record support, with associated link/struct support does the following:
* When it is called for processStart
** calls the support for RecordCommon with state processStart. it returns
*** processDone - Record support starts processing record specific fields
*** processQuit - Record support just returns processQuit to dbProcess
*** processActive - Record returns processActive. It will be called again with state processContinue. It calls RecordCommon support with state processActive. This continues until Record Common returns processDone or processQuit
* When RecordCommon returns processDone record support starts processing record specific fields
** Associated link or struct support may be called
*** Record support implements any <tt>block</tt> fields.
*** It detects when asynchronous support completes
*** as long as there is incomplete asynchronous support it returns processActive to dbProcess
** When all record specific fields have been processed it calls RecordCommon suport with state processQuit
*** RecordCommon support can return processActive. Until it returns processDone, record support just returns processActive to dbProcess
** When RecordCommon returns processDone, record support returns processDone to dbProcess.
 
 
struct and link fields can have associated support
* associated support may be asynchronous
** support returns indicating that it is active
** support is required to detect when asynchronous support completes
** when processing is complete support returns indicating that it is done.
* whenever record support returns to dbProcess, dbProcess posts any fields that were modified.
** record may be active or done
* when record support returns processDone or processQuit record is again set idle.


NOTE: FLNK (forward link) is replaced by an array of process links.




dbProcess implements a state machine that use processState as well
== record common ==
a private state dbProcessState which has the following:


; dbProcessIdle
These fields are optional but it is expected that most record
: record is not being processed
types will include a standard set of fields.
; dbProcessIocRecord
: iocRecord is in control
; dbProcessRecordSupport
: record support is in control
; dbProcessDone
: complete record processing


For each state the following actions are performed:
The support for RecordCommon processes the following fields:
* dbProcessIdle
** prepare record for processing and call iocRecord with processState = processIdle
** If iocRecord returns processInputActive set dbProcessState = dbProcessIocRecord and return
** If iocRecord returns processActive set processState = idle and goto state dbProcessRecordSupport
** If iocRecord returns processDone goto state dbProcessDone
* dbProcessIocRecord
** If processState = processInputActive call iocRecord
*** If iocRecord returns processInputActive return
*** If iocRecord returns processActive set processState = processIdle and goto state dbProcessRecordSupport
*** If iocRecord returns processDone goto state dbProcessDone
** If processState = processDone or processOutputActive call iocRecord
*** If iocRecord returns processOutputActive return
*** If iocRecord returns processDone goto state dbProcessDone
* dbProcessRecordSupport
** If processState = processIdle, processInputActive, or processActive call record support
*** If record support returns processInputActive return
*** If record support returns processActive handle monitors and return
*** If record support returns processDone goto dbProcessIocRecord
** If processState = processDone or processOutputActive call record support
*** If record support returns processOutputActive return
*** If record support returns processDone goto dbProcessIocRecord
* dbProcessDone
** Perform final processing - See below for details.
** set dbProcessState = dbProcessIdle and processState = processIdle
** return


The remaining subsections provide more details about each processState. Keep in mind
* at the beginning of record processing
that some actions are performed by dbProcess, some by iocRecord,
** disabled - if true NO processing will be done, i.e. processQuit is returned
some by record support, and some by link support.
** scanDisable
*** has associated support
*** if record is scan disabled processQuit is returned
** alarm fields
*** alarm handling is described below
* after record support completes
** processLink array
*** has associated support


=== processState processIdle ===
== record support ==


If dbProcess is called with dbProcessIdle and processIdle then it:
Record support is responsible for all its fields.
* Sets all dynamic monitor bits to 0
For link and struct fields there may be associated support which
* Other stuff?????
may be synchronous or asynchronous.
* calls iocRecord with processState processIdle
Record support communicates with
the link/struct support via interfaces that are implemented by the support.
If the record includes a field for struct(RecordCommon) it should
use the associated support for its fields.


When iocRecord is called with processState processIdle it:
Record support may be called multiple times by dbProcess while a record instance
* initializes severity. See Alarm Processing for details.
is active.
* initializes status. See Alarm Processing for details.
One of the arguments to process is ProcessState which has the values:
* starts processing it's input links. Details are given below.
* processCancel - Cancel any outstanding activity
* returns with processState one of the following:
* processStart - Start processing
** processInputActive - dbProcess will again call iocRecord.
* processContinue - Making additional call
** processActive - dbProcess will set processState to processIdle and call record support.
** processDone - dbProcess will complete processing. record support will NOT be called and iocRecord will not be called to handle output links


When record support is called with processState processIdle it:
process returns ProcessReturn which is one of the following:
* starts processing it's input links. Details are given below.
* processDone - Done and successful
* returns with processState one of the following:
* processQuit - Do not do any more processing
** processInputActive - dbProcess will again call record support
* processActive - Not done
** processActive - dbProcess will again call record support
** processOutputActive - dbProcess will again call record support
** processDone - dbProcess will call iocRecord to process it's output links


=== processState processInputActive ===
If record support returns processActive it must keep internal state so
that it knows how to handle processCancel and processContinue.


This state means that one or more input links to other records have not
completed. Links can be processed in parallel, sequentially, or a
combination of these. iocRecord handles the links in iocRecord and record
support handles record specific input links. The support is responsible for
implementing sequential or parallel link processing.
It calls link support to do the actual I/O. The Link support methods
provide options specifying if the linked record should be processed and
provide a callback to call when link processing completes. It is up to
iocRecord or record support to again call dbProcess when all input links
complete.


If is OK for dbProcess to be called multiple times while input links
For record support the above rules allow:
are being processed. When iocRecord detects that all it's input
* process can be called repeatedly. This will continue as long as it returns processActive
links have completed, it sets processState = processActive and returns.
* Everytime process returns processActive DbProcess posts monitors.
dbProcess then sets processState = processIdle and calls record support so
that it starts processing it's input links.


When record support is called it returns one of:
== Record Locking ==
* processActive - dbProcess will again call record support
* processOutputActive - dbProcess will again call record support
* processDone - dbProcess will call iocRecord to process it's output links


V3 implemented lock sets in order to prevent different threads
from simultaneously accessing linked records.


=== processState processActive ===
Instead of lock sets V4:
* implements a per record instance lock.
* defines a rule that allows two records to be locked without deadlocks


This state means that record support and associated device support
== Posting Monitors ==
are waiting for something to complete, e.g. for a motor to reach
 
some position.
In V3 monitors are posted when code (record support, device support, database access, etc) calls db_post_event. In V4 database access will itself handle
the posting of monitors.
 
Monitors are posted by DbProcess when
* record support returns processActive.
* at the end of record processing.
 
<center>
= link/struct Semantics =
</center>


The record, however, can be processed so that it can
Both link and struct fields can have associated support.
report intermediate data values, e.g. the current motor position.
The support can be synchronous or asynchronous.
For example the record can be periodically scanned.


When record support detects that it is done, it sets the processState to
Support code implements interfaces.
either processOutputActive or processDone.
Code that is responsible for a field communicates with the support via
the interface. Lets call this code the client.


While the processState is processActive dbProcess will post dynamic monitors.
Each link and struct field has a well defined client.
* The support for RecordCommon is the client for fields in dbCommon
* record support is the client for the other top level fields in a record
* the struct support is the client for any link or struct fields in the struct


=== processState processOutputActive ===
A link/struct may have an associated block. The client is responsible for
implementing block. If block is true then the support will not be called
until all outstanding record activity completes.


This state means that one or more output links to other records have not
<center>
completed. Links can be processed in parallel, sequencially, or a
= channelAccess links =
combination of these.
</center>
Record support handles the record specific output links and then iocRecord
handles the output and process links in iocRecord.
When record support detects that all it's output links are done,
it returns with processState processDone. dbProcess then calls iocRecord which
starts processing it's output and process links.
Until it is done it sets processState to processOutputActive.
When it is done it sets the processState to processDone.


channelAccess link means access to a record or field. The requester can be:
* A database link in a record
* A channel access link in a record
* A workstation channel access client


=== processState processDone ===
A channelAccess link is one of the following types:
* Monitor Link
** Implemented via a monitor request on linked field
** Optionally process record containing the link when monitor value is returned.
* Input Link
** Optionally request that record be processed.
** Optionally wait for linked record to complete processing.
** Get value.
* Output Link:
** Put value
** Optionally request processing.
** Optionally wait until completion
* Process Link: Perform the following actions
** Request processing
** Optionally wait until linked record completes


When both record support and iocRecord have reported that they are done,
NOTES:
dbProcess does some final steps and then sets the processState to processIdle.
* processLink is the replacement for the V3 forwardLink
* wait does NOT mean to wait synchronously. It means to save state, return, and resume at the saved state when called again.


The final steps are:
Links are processed as follows:


* If the request to process the record included a callback, the callback is called.
The following rules apply when a process request is made:
* If other record completion callback requests are present, call them.
* If record is already being processed the request is just ignored
* Dynamic monitors are posted
* record support can specify that links to particular fields not cause processing.
* ???
** Where should this be specified? In the Database Definition, the record instance, or both.
* The processState is set to processIdle and dbProcessState to dbProcessIdle.
** If a process request is allowed, should it be done regardless of the scan mechanism, i.e. the record does not have to be passive?




----
----
<center>
<center>
== Mutual Exclusion ==
= Mutual Exclusion =
  </center>
  </center>


V3 implemented lock sets, i.e. when a record was being processed it and all records linked via database links were locked.
V3 implemented lock sets, i.e. when a record was being processed it and all records linked via database links were locked.
For V4 we should try to get rid of lock sets.


Lock sets solved two Mutual Exclusion problems:
Lock sets solved two Mutual Exclusion problems:
* V3 allowed dbProcess to be called recursively.
* V3 allowed dbProcess to be called recursively.
** process passive database links and forward links were implemented via recursive calls to dbProcess
** process passive database links and forward links were implemented via recursive calls to DbProcess
** Lock sets prevented deadly embrace problems for circular links.
** Lock sets prevented deadly embrace problems for circular links.
* No puts could be done to an record in a lock set while record processing is active.
* No puts could be done to a record in a lock set while record processing is active.
** For synchronous records this guarantees that no fields are modified except by record processing itself.
** For synchronous records this guarantees that no fields are modified except by record processing itself.
** For asynchronous records this guarantee is no longer valid.
** For asynchronous records this guarantee is not valid.
 
 
V4 does not call dbProcess recursively. Instead a process request is queued.
The request fails if either of the following is true:
* The record is active.
* The record is already queued.
 
dbProcess itself manages the queue , which is FIFO.
When record support returns the first entry in the queue is processed.
In addition if link or struct support completes before the queue
is empty, a request to process the record containing the link/struct will
be added to the same queue.
Thus if a set of synchronous records are processed they will complete processing
without any context switch.
 
<b>Question</b> What about periodically scanned records? Needs thought.
 
This leaves the question of what should be done about mutual exclusion.
 
For V4 there will be two locks associated with the IOC database:
1) a global lock, and 2) A per record instance lock.
 
The global lock must be taken
whenever the structure of the database is modified. Examples are
1) adding new record types, 2) adding new record instances, and 3) modifying
database links. Global locks are not discussed further in this document.
 
Each record instance has an associated lock.
When dbProcess is called it takes the lock.
Before it returns it unlocks.
Thus record support does not need to lock or unlock.
 
Other code that needs access to fields of a record instance must
lock before accessing any fields and unlock after all accesses are complete.


This leaves the problem of how to access fields from two different record
instances simultaneously. For example code that implements database
access needs such access. Code that needs such access must call dbLockLink before accessing the linked record and dbUnlockLink after access.


For V4 dbProcess will not be called recursively.
dbLockLink is implemented as follows:
Instead a request will be made to process the record.
* Each Record instances has a unique ordinal number
* Assume Record X has a link to record Y
* If the ordinal number of X is less than that of Y
** Just call dbLock for record Y
* If the ordinal numnber of X is greater than that of Y
** call dbUnlock for X
** call dbLock for Y
** call dbLock for X


* If the link is a channel access link than channel access is used.
----
* If the link is a database link to a passive record then the following can be done
<center>
** A request is made for one of the standard callback threads to process the record,
= Posting Modifications =
** The priority will be taken from the priority field in iocRecord.
</center>


Note that if all linked records are passive and the same priority then
The document "V4 Design: dbdIterfaces" provides a design that allows
all processing can occur without any context switches.
database access to handle all posting on monitors without requiring
The following occurs:
any help from the code that modifies database fields.
* A request is made to a thread to call dbProcess.
It can do this because fields can be modified only via an
** The request is put on a queue associated with the thread.
interface implemented by database access.
* Sometime later the request is dequeued and dbProcess is called.
** For each link process request the request is put on the queue for the same thread
** After all requests are queued dbProcess returns
* The thread takes each request off the queue and calls dbProcess for the associated linked record
** When all linked records finish processing a request is queued to call dbProcess for the original record
* The request for the original record is removed from the queue and it's dbProcess is again called.
** The record completes.


This leaves the question of what should be done about mutual exclusion?
dbProcess posts monitors when:
At least the following two locks per record instance are needed:
* When record support returns processActive.
* When it finishes record processing.
 
How to implement monitors must be decided.
 
----
<center>
= Alarm Processing =
</center>


; recordLock
<b>Question</b> Will V4 alarm handling be different than V3? If so this section
: This is locked when dbProcess is called and unlocked before dbProcess returns. It is entirely private to dbProcess. This prevents simultaneous calls to dbProcess.
may be meaningless.
; fieldLock
: This must be taken before accessing any field.


Should fieldLock be private to database access?
The V4 semantics for status and severity have the following goals:
* yes - This simplifies code that accesses the database BUT it means that database access must lock/unlock every access of every field
* alarmSeverity has the same values as for V3
* no - Any code can access multiple fields with just one lock/unlock.
* alarmStatus is a string
* a record starts processing with alarmSeverity = "NO_ALARM" and status empty.
* status will ONLY be posted if it has changed since the last time it was posted.
* alarmSeverity will ONLY be posted if it has changed since the last time it was posted


Perhaps we should start with a private lock?
The semantics, which are implemented by the support for RecordCommon, are:


A problem remains: Array fields. As described below, array fields may only
* When recordCommon is called with processStart
be accessable in segments. It might be a channel access client that
** A private variable newSeverity is set to NO_ALARM
is accessing the array in segments and will block between segments while
** A private variable prevSeverity is set to alarmSeverity
waiting for the data to be transfered over the network.
* When recordCommon completes its part of record processing
** If newSeverity is NO_ALARM and prevSeverity has a different value
*** alarmSeverity is set to NO_ALARM
*** alarmStatus is set to empty


How to prevent two clients from trying to access the same array simultaneously?
* When the recordCommon.setSeverity(sevr,status) is called
* Does it matter?
** If sevr is less than or equal to newSeverity nothing is done
* If application wants to allow only single access let the apllication solve the problem
** else
** runControl records are one solution
*** alarmSeverity is set to sevr
** Other solutions can be envisioned
*** alarmStatus is set to status
* Conclusion is that this is not a database responsibility
*** newSeverity is set to sevr


NOTE: alarmStatus and alarmSeverity are written by the normal method.
This means that their values will be posted.
----
----
<center>
<center>
== get/put database fields ==
= Channel Access/ Database Access field types =
  </center>
  </center>


=== Overview ===
 
== Overview ==


This section discusses how IOC database fields are accessed by channel access
This section discusses how IOC database fields are accessed by channel access
or via database links. The following types of data are supported.
or via database links.
 
For the initial V4 implementation only the following types of data
will be accessable.


* primitive types
* primitive types
* string
* string
* array of primitive or string
* enum
* one dimensional array of primitive or string or struct
* struct with fields of following types:
* struct with fields of following types:
** primitive
** primitive
** string
** string
** array of primitive or string
** enum
** struct (use recursion for allowed types)
** one dimensional array of primitive or string or struct


Other fields will only be available as one of the above types.
The dbdInterfaces document defines database field types.
For example a DbfLink field will appear as a string.
It also defines a subset called basic types, which consists
of primitive types, string, array, and structure.
For external access only basic types can be accessed.
This means that structures and arrays that do not consist of basic types
are not accessablevia clannelAccess. For example a DbfLink is
not accessable via channel access as a DbfLink.


Since the field view provides access to subfields of a field and to
Non basic fields will only be available via some combination of basic types.
elements of an array, Information from every DbfType is available.


As an example if a Database Definition is
For example a DbfLink field will appear as a string.
If a Database Definition is


     struct(calcInpLink) {
     struct(calcInpLink) {
         field(link,link(in))
        field(block,boolean)
         field(link,link)
         field(value,float64)
         field(value,float64)
     };
     };
      
      
     struct(calcInpLink) {
     record(xxx) {
         field(link,link(in))
         field(link,link)
         field(value,float64)
         field(value,float64)
     ...
     ...
Line 351: Line 515:
     }
     }


Then if a client has attaches to a process variable:
If a client attaches to  
     record.field(calcInpLink[1].link)
     record.field(link)
Then the data will be presented as a string describing the link.
The data will be appear in the form:
An example of the string value is:
    choice(choiceName) SupportStruct(pvname= ...)
     acro9440(0,5)
where <tt>choiceName</tt> is the name of the link support, <tt>SupportStruct</tt> is the name of the support struct asociated with the support, and the arguments are the values for the support structure.
 
Then if a client specifies the process variable:
     record.field(inp[1].link)
Then it connects to the link field of the second calcInpLink of field inp.




=== primitive types ===
== primitive types ==


This includes DbfBool, DbfOctet, DbfInt16, ... , DbfFloat64.
This includes DbfBool, DbfOctet, DbfInt16, ... , DbfFloat64.
These do not present any problems. The scalar value is transfered.
These do not present any problems. The scalar value is transfered.


=== string ===
== string ==


A string is just a UTF_8 encoded character string
A string is just a UTF_8 encoded character string


=== DbfMenu ===
== DbfMenu and DbfEnum ==
 
The index value is handled just like DbfInt16.
Since the choices for a menu can't change, only the changes to the index
can occur.
 
=== DbfEnum ===
 
The index value is handled just like DbfInt16.
 
The choices are handled as an array of strings. See array below for details.
 
=== DbfLink and DbfDevice ===
 
Both of these have the following:
 
* <tt>choiceName</tt> A string that selects the link or device support.
* <tt>dataStruct</tt> Each support has an associated struct for configuration.


How should the be made available? Perhaps:
Handled as an enum


The field appears as a string with the following syntax:


<tt>choiceName(structAssignmentList)</tt>
== DbfLink ==


where structAssignmentList has the same syntax as defined in "V4 DB Record Instance Syntax"
A string with the same syntax as defined for a link field in "V4 DB Record Instance Syntax"


=== timeStamp ===
== timeStamp ==


This is just transfered a struct with two fields:
This is just transfered like a struct with two fields:
* int64 secondsSinceEpoch
* int64 secondsSinceEpoch
* int32 nanoSeconds
* int32 nanoSeconds


=== struct ===


The database definition syntax allows a struct to be composed of fields
== struct ==
of any DbfType.
Database access, however, will only allow access to structs with fields
of the following types:
* primitive - DbfBool,...,DbfFloat64
* DbfString
* DbfArray of primitive type or string


The individual fields can be accessed directly so this discussion
The individual fields can be accessed directly so this discussion
only involves access to the entire structure.
only involves access to the entire structure.


Note that if a struct contains a field that is a DbfStruct,
The entire structure can be accessed as a string with the same syntax
the struct field itself will not be available but
as defined for a struct field in "V4 DB Record Instance Syntax"
it is possible to access the DbfStruct field itself if it
is contains fields of the above types.
 
The following two forms of access available.


* Access by clients that have knowledge of the structure -
** In this case the data is transfered as a sequence of field values.
** Can we do this?
** Perhaps this looks like a synchronized set of requests to the fields?
* Access by clients that do not know about the structure -
**The structure value is presented as a string that has the structAssignmentList syntax defined in "V4 DB Record Instance Syntax"


 
== array ==
=== array ===


Arrays of the following types are accessable:
Arrays of the following types are accessable:
* primitive - DbfBool,...,DbfFloat64
* primitive - DbfBool,...,DbfFloat64
* DbfString
* DbfString
* DbfStruct - As long as its fields are valid types


Note that arrays of structs are not accessable.
Note that arrays of structs are not accessable in the early V4 releases.
 
Database Access is implemented so that record/link/device support can transfer an array in segments. Examples:
* If the array is a circular buffer, it is presented in two segements
* If the array is stored in hardware, e.g. a transient recorder, the array can be read from the hardware and passed to the client in segments.


Arrays still need lots more discussion!!!
The database definition syntax allow an array to be any of the basic types, i.e. DbfBool,...,DbfFloat64, DbfString, DbfArray, DbfStruct.
The database definition syntax allow an array to be any of the basic types, i.e. DbfBool,...,DbfFloat64, DbfString, DbfArray, DbfStruct.


Database access only allows access to arrays of the following types.
For the initial V4 version, database access only allows access to arrays of the following types.
* primitive - DbfBool,...,DbfFloat64
* primitive - DbfBool,...,DbfFloat64
* DbfString
* DbfString
* ???? What else


An individual element of an array of type DbfStruct can be accessed
An individual element of an array of type DbfStruct can be accessed
directly if it satisfies the criteria for accessing a DbfStruct.
directly if it satisfies the criteria for accessing a DbfStruct.


=== MDArray ===
Question: Should database Access be implemented so that record/link support can transfer an array in segments. Examples:
* If the array is a circular buffer, it is presented in two segements
* If the array is stored in hardware, e.g. a transient recorder, the array can be read from the hardware and passed to the client in segments.


TBD
If an array is available only in segments then can we
prevent two clients from trying to access the same array simultaneously?


=== Associated Data ===
Perhaps this is a problem that must be solved by an application:
* runControl records are one solution
* Other solutions can be envisioned


The typical example is a client that asks for timeStamp, severity, status,
and data.


Perhaps these can be handled as four synchronized requests to the same record?
== MDArray ==


How is this implemented?
Not implemented if the early V4 releases.


* What does dbProcess do?
== Associated Data ==
* How does a client make the request


----
The typical example is a client that asks for timeStamp, severity, status,
<center>
and data.
== Posting Modifications ==
</center>
 
The document "V4 Design: dbdIterfaces" provides a design that
allows dbAccess to detect all changes to fields of an IOC record.
 
dbAccess handles all posting on monitors without requiring
any help from the code that modifies database fields.
 
The following is the initial attempt to describe how monitors are handled.
 
The following definitions are used:
* monitor - A client has asked to be notified when a field value changes.
* post - Create storage, copy the current value of the field into the storage, and pass the storage to the monitor subsystem.
* static database field - A field that changes only because something external to the record modifies the field.
* dynamic database field - A field that changes because of record processing.
 
Static and dynamic fields have different semantics for monitors.
 
=== static fields ===
 
* primitive types - This includes DbfBool, DbfOctet, DbfInt16, ..., DbfFloat64. When a static primitive field is modified, a monitor is immediately posted.
* DbfMenu - Whenever the index is modified, a monitor is immediately posted. Since the choices for a menu can't change, only the changes to the index can occur.
* DbfEnum - Whenever the index is modified, a monitor is immediately posted.  What about when a  choice changes?
** Should only the choice that changes be posted? If so what is the syntax?
** Should the complete new set of choices be posted?
** Should the user just be notified that one or more choices changed and the user must issue a new read request?
* DbfLink and DbfDevice
**Both of these have the following:
*** <tt>choiceName</tt> A string that selects the link or device support.
*** <tt>dataStruct</tt> Each support has an associated struct for configuration.
** What should be made available?
*** Perhaps just notification that a change has occcured. Client must issue new read request
*string - Perhaps
**When a string field is modified, a monitor is immediately posted.
** Is this correct? For long strings it could cause excessive amounts of memory to be consumed. Probably not a big problem.
* array - Memory becomes a big issue.
**Perhaps the following semantics could be used.
*** The array is posted when the value changes.
*** When the value changes, the client is notified and must issue a read request to retrieve the data.
** Should both or only one be supported?  If both who decides which semantics to use?
*** client?
*** database developer?
*** ???
* struct - Can only have fields that are primitive, string, array
** Structure with only primitive or string fields should be posted immediately
** What about structures containing arrays?
 
=== dynamic fields ===
 
For each dynamic database field, dbAccess keeps a modify bit
that is set to 0 when the record starts processing and is set to 1
whenever the field is modified.
 
Whenever record support returns with processState processActive or iocRecord
returns with processState processDone, then the following is done:
 
* The monitor subsystem is notified about the beginning of synchronized monitors.
* Each field with the modify bit set to 1 is posted.
* The modify bit is set back to 0.
* Since status, severity, and timeStamp are dynamic fields in iocRecord, they follow the same logic.
* The monitor subsystem is notified about the end of synchronized monitors.
 
Separate discussions are required for the following: 1) primitive fields,
2) string fields, 3) structured fields, and 4) array fields.
 
* primitive fields - No problems.
* string fields - Memory is an issue.
** Should there be a way to postpone posting until the monitor is ready to retrieve the value?
** If so who decides?
* struct fields - Memory is again an issue.
** Structure with only primitive field or string should be posted immediately but what about array fields?
** Who decides?
** How?
* array fields - memory is an issue
** It should be possible to post small arrays of primitive type.
** Large arrays should not be posted until monitor system is ready to accept the data.
*** It should also be possible to just notify the client that the array changed but the client must issue a read request to retrieve the data.
 
----
<center>
== Alarm Processing ==
</center>
 
The V4 semantics for status and severity have the following goals:
* alarmSeverity has the same values as for V3
* status is independent of alarmSeverity, i.e. it just reports a status.
* a record starts processing with alarmSeverity = "NO_ALARM" and status empty.
* status will ONLY be posted if it has changed since the last time it was posted.
* alarmSeverity will ONLY be posted if it has changed since the last time it was posted
 
The semantics that implement these goals are:
 
* When a record starts processing the following is done
** The status is saved in previousStatus
** status is set to an empty string
** The alarmSeverity is saved in previousAlarmSeverity
** alarmSeverity is set to NO_ALARM
* When the status is modified
** If the new status is different than previousStatus
*** previousStatus is set to the new status
*** the status modified bit is set
* When the alarmSeverity is modified
** If the new alarmSeverity is different than previousAlarmSeverity
*** previousAlarmSeverity is set to the new alarmSeverity
*** the alarmSeverity modified bit is set
* When dynamic monitors are posted
** If status != previousStatus the status modified bit is set
** If alarmSeverity != previousAlarmSeverity the alarmSeverity modified bit is set
**  If the status modified bit is set the status is posted and previousStatus set equal to status
**  If the alarmSeverity modified bit is set the alarmSeverity is posted and previousAlarmSeverity set equal to alarmSeverity

Latest revision as of 19:52, 2 November 2005

EPICS V4: Record Processing November 02 2005


Overview

UNRESOLVED ISSUES

  • This document is still evolving
  • Monitors
    • How will monitor data be managed?
    • Big problem is how will array data be managed?
  • Alarms
    • How will V4 handle alarms?
  • Events
    • What is the V4 event model?
    • What is required from the IOC database?

This document described semantics for V4 record processing that are different than for V3. This includes the following:

  • Semantics for record processing
  • Semantics for Database and Channel Access Links.
  • Record Locking
  • Posting database monitors
  • Status and Alarm Severity
  • Access to array and structure fields.

This version is based on feedback from the EPICS core developer's meeting at ANL/APS on July 11th through July 14th. In addition discussions with Andrew Johnson and Eric Norum have led to many of the ideas described below. This wiki is a companion to the wiki "V4 Design: dbdInterfaces".

V3 record processing semantics do not work well for data acquisition applications. An example of data acquisition is:

  • Move sample to new position.
    • Several motors may be involved
    • While moving post monitors to show current position, etc.
  • Sample data
  • Wait until CA client has fetched the data before next move.

SynAPPS provides the Scan, motor, etc records which help with data processing applications. These records process as follows:

  • Record does not complete processing until all inputs, outputs, etc done. Not completing means that they do not call recGblFwdLink until all proccessing is complete. Note that recGblFwdLink is what causes the V3 ioc to complete record processing.
  • While waiting for asynchronous events these records have PACT=0 but keep state that shows it is still active
  • Can be scanned and issue monitors while internal state is active

Leaving PACT 0 but not calling recGblFwdLink was not anticipated when the V3 record processing semantics were created. For V4 a record can be processed while it is waiting for asynchronous processing to complete.

In V3, if an input link is asynchronous, Process Passive does not wait for asynchronous processing to complete before fetching data. This also complicated data acquisition applications.

V4 record processing is designed to make data acquisition easier. Both input and output links can wait for record processing. This is done, however, without record support blocking. If blocking makes it easier to implement record support, then the support can spawn a separate thread that does block. Record support can communicate with the separate thread to decide when to complete record processing.


Overview of V4 Record Processing

V4 will provide a replacement for dbProcess. The name may be different but for now it will still be called dbProcess.

In V4 database access and channel access appear the same to record and link support. Only the implementation knows the difference. In this document the term channelAccess will mean access to a record. Thus it can mean a workstation client or a field of a record that is a link to a record.

V4 also allows support for struct fields. For example base provides support for

    field(common,struct(RecordCommon))

In the record types provided with base, this is the first field. The fields in RecordCommon are the V4 replacement for the V3 dbCommon fields.


V4 record processing has the following features.

  • database fields
    • "owned" by database not record support
    • fields can only be accessed via interfaces
    • support can optionally provide storage for data associated with a field
    • for channelAccess all fields appear as type primitive, string, struct, array or combination thereof
  • dbProcess
    • processes synchronous linked records by queuing requests rather than recursive calls to dbProcess
    • can be called an arbitrary number of times while record is active
  • link
    • always has associated support
    • can be record link or can be something else, e.g. a link to hardware
  • record link
    • can request process and/or wait for asynchronous completion
    • local synchronous requests queued by dbProcess
    • record is active and can be processed while asynchronous links active
  • struct fields
    • Can have associated support which can be synchronous or asynchronous
  • block
    • is requested via a separate field
    • if true than support waits for all outstanding I/O to complete before further processing
    • if false than asynchronous support can proceed in parallel
  • lock
    • record instances are locked
    • dbProcess locks before calling support
    • other code can also lock
    • Two records can be locked without deadlock
  • monitors
    • dbProcess handles monitors
    • support triggers monitors by writing to fields


Database Fields

Field Access by Support Code

Support code can access database fields only via interfaces implemented by the IOC database. Thus record fields are owned by the IOC database not by record support.

Support code can register to provide storage for particular fields. For example support code could implement a circular buffer for field value. When some other code request the array associated with value, the IOC database calls the support. The support returns the first portion of the circular buffer and the caller must make an additional call to retrieve the rest of the circular buffer.

Field Access by Channel Access

For V4 database access and channel access appear the same to record instances. It is only the code that implements link support that knows the difference. If a linked record is local, database access is used, and, if the record is remote, channel access.

V4 allows channel access to the following types of fields:

  • primitive types
  • string
  • one dimensional array of primitive or string or struct
  • struct with fields of following types:
    • primitive
    • string
    • struct
    • array of primitive or string or struct

For other database field types, i.e. links, the database will make the field appear as one of the above types. For example a link field will appear as a string with syntax that matches the information associated with the link. For example a process link will have a string something like

   support(processLink) ProcessLink(pvname = 'pvname'; wait = true)

where

processLink
selects the support for a process link
ProcessLink
Names the struct that the support uses for configuration information


Record Processing Semantics

This section describes the semantics implemented by dbProcess.

The following are involved in record processing

  • dbProcess
    • implements a queue for local records that are processed because of record links
    • posts monitors caused by field changes during record processing
  • record support
    • calls support code for RecordCommon fields
    • is responsible for record instance fields
    • calls link/struct support via interfaces implemented by the support
  • link support
    • can be links to other records, to driver support, etc
    • implements interfaces called by record and/or other support
  • struct support
    • is responsible for the fields in the struct
    • implements interfaces called by record and/or other support

Processing Life Cycle

Assume a record instance is idle, i.e. is ready to start processing.

  • dbProcess calls record support with one of the following states
    • processCancel - record support must terminate any outstanding processing
    • processStart - start processing. record support returns one of
      • processDone - All done and successful
      • processQuit - dont do any more processing. Return to idle state
      • processActive - not done. Call again
    • processContinue - another request to process while record is active. Record support again returns one of the above.

Record support, with associated link/struct support does the following:

  • When it is called for processStart
    • calls the support for RecordCommon with state processStart. it returns
      • processDone - Record support starts processing record specific fields
      • processQuit - Record support just returns processQuit to dbProcess
      • processActive - Record returns processActive. It will be called again with state processContinue. It calls RecordCommon support with state processActive. This continues until Record Common returns processDone or processQuit
  • When RecordCommon returns processDone record support starts processing record specific fields
    • Associated link or struct support may be called
      • Record support implements any block fields.
      • It detects when asynchronous support completes
      • as long as there is incomplete asynchronous support it returns processActive to dbProcess
    • When all record specific fields have been processed it calls RecordCommon suport with state processQuit
      • RecordCommon support can return processActive. Until it returns processDone, record support just returns processActive to dbProcess
    • When RecordCommon returns processDone, record support returns processDone to dbProcess.


struct and link fields can have associated support

  • associated support may be asynchronous
    • support returns indicating that it is active
    • support is required to detect when asynchronous support completes
    • when processing is complete support returns indicating that it is done.
  • whenever record support returns to dbProcess, dbProcess posts any fields that were modified.
    • record may be active or done
  • when record support returns processDone or processQuit record is again set idle.


record common

These fields are optional but it is expected that most record types will include a standard set of fields.

The support for RecordCommon processes the following fields:

  • at the beginning of record processing
    • disabled - if true NO processing will be done, i.e. processQuit is returned
    • scanDisable
      • has associated support
      • if record is scan disabled processQuit is returned
    • alarm fields
      • alarm handling is described below
  • after record support completes
    • processLink array
      • has associated support

record support

Record support is responsible for all its fields. For link and struct fields there may be associated support which may be synchronous or asynchronous. Record support communicates with the link/struct support via interfaces that are implemented by the support. If the record includes a field for struct(RecordCommon) it should use the associated support for its fields.

Record support may be called multiple times by dbProcess while a record instance is active. One of the arguments to process is ProcessState which has the values:

  • processCancel - Cancel any outstanding activity
  • processStart - Start processing
  • processContinue - Making additional call

process returns ProcessReturn which is one of the following:

  • processDone - Done and successful
  • processQuit - Do not do any more processing
  • processActive - Not done

If record support returns processActive it must keep internal state so that it knows how to handle processCancel and processContinue.


For record support the above rules allow:

  • process can be called repeatedly. This will continue as long as it returns processActive
  • Everytime process returns processActive DbProcess posts monitors.

Record Locking

V3 implemented lock sets in order to prevent different threads from simultaneously accessing linked records.

Instead of lock sets V4:

  • implements a per record instance lock.
  • defines a rule that allows two records to be locked without deadlocks

Posting Monitors

In V3 monitors are posted when code (record support, device support, database access, etc) calls db_post_event. In V4 database access will itself handle the posting of monitors.

Monitors are posted by DbProcess when

  • record support returns processActive.
  • at the end of record processing.

link/struct Semantics

Both link and struct fields can have associated support. The support can be synchronous or asynchronous.

Support code implements interfaces. Code that is responsible for a field communicates with the support via the interface. Lets call this code the client.

Each link and struct field has a well defined client.

  • The support for RecordCommon is the client for fields in dbCommon
  • record support is the client for the other top level fields in a record
  • the struct support is the client for any link or struct fields in the struct

A link/struct may have an associated block. The client is responsible for implementing block. If block is true then the support will not be called until all outstanding record activity completes.

channelAccess links

channelAccess link means access to a record or field. The requester can be:

  • A database link in a record
  • A channel access link in a record
  • A workstation channel access client

A channelAccess link is one of the following types:

  • Monitor Link
    • Implemented via a monitor request on linked field
    • Optionally process record containing the link when monitor value is returned.
  • Input Link
    • Optionally request that record be processed.
    • Optionally wait for linked record to complete processing.
    • Get value.
  • Output Link:
    • Put value
    • Optionally request processing.
    • Optionally wait until completion
  • Process Link: Perform the following actions
    • Request processing
    • Optionally wait until linked record completes

NOTES:

  • processLink is the replacement for the V3 forwardLink
  • wait does NOT mean to wait synchronously. It means to save state, return, and resume at the saved state when called again.

Links are processed as follows:

The following rules apply when a process request is made:

  • If record is already being processed the request is just ignored
  • record support can specify that links to particular fields not cause processing.
    • Where should this be specified? In the Database Definition, the record instance, or both.
    • If a process request is allowed, should it be done regardless of the scan mechanism, i.e. the record does not have to be passive?



Mutual Exclusion

V3 implemented lock sets, i.e. when a record was being processed it and all records linked via database links were locked.

Lock sets solved two Mutual Exclusion problems:

  • V3 allowed dbProcess to be called recursively.
    • process passive database links and forward links were implemented via recursive calls to DbProcess
    • Lock sets prevented deadly embrace problems for circular links.
  • No puts could be done to a record in a lock set while record processing is active.
    • For synchronous records this guarantees that no fields are modified except by record processing itself.
    • For asynchronous records this guarantee is not valid.


V4 does not call dbProcess recursively. Instead a process request is queued. The request fails if either of the following is true:

  • The record is active.
  • The record is already queued.

dbProcess itself manages the queue , which is FIFO. When record support returns the first entry in the queue is processed. In addition if link or struct support completes before the queue is empty, a request to process the record containing the link/struct will be added to the same queue. Thus if a set of synchronous records are processed they will complete processing without any context switch.

Question What about periodically scanned records? Needs thought.

This leaves the question of what should be done about mutual exclusion.

For V4 there will be two locks associated with the IOC database: 1) a global lock, and 2) A per record instance lock.

The global lock must be taken whenever the structure of the database is modified. Examples are 1) adding new record types, 2) adding new record instances, and 3) modifying database links. Global locks are not discussed further in this document.

Each record instance has an associated lock. When dbProcess is called it takes the lock. Before it returns it unlocks. Thus record support does not need to lock or unlock.

Other code that needs access to fields of a record instance must lock before accessing any fields and unlock after all accesses are complete.

This leaves the problem of how to access fields from two different record instances simultaneously. For example code that implements database access needs such access. Code that needs such access must call dbLockLink before accessing the linked record and dbUnlockLink after access.

dbLockLink is implemented as follows:

  • Each Record instances has a unique ordinal number
  • Assume Record X has a link to record Y
  • If the ordinal number of X is less than that of Y
    • Just call dbLock for record Y
  • If the ordinal numnber of X is greater than that of Y
    • call dbUnlock for X
    • call dbLock for Y
    • call dbLock for X

Posting Modifications

The document "V4 Design: dbdIterfaces" provides a design that allows database access to handle all posting on monitors without requiring any help from the code that modifies database fields. It can do this because fields can be modified only via an interface implemented by database access.

dbProcess posts monitors when:

  • When record support returns processActive.
  • When it finishes record processing.

How to implement monitors must be decided.


Alarm Processing

Question Will V4 alarm handling be different than V3? If so this section may be meaningless.

The V4 semantics for status and severity have the following goals:

  • alarmSeverity has the same values as for V3
  • alarmStatus is a string
  • a record starts processing with alarmSeverity = "NO_ALARM" and status empty.
  • status will ONLY be posted if it has changed since the last time it was posted.
  • alarmSeverity will ONLY be posted if it has changed since the last time it was posted

The semantics, which are implemented by the support for RecordCommon, are:

  • When recordCommon is called with processStart
    • A private variable newSeverity is set to NO_ALARM
    • A private variable prevSeverity is set to alarmSeverity
  • When recordCommon completes its part of record processing
    • If newSeverity is NO_ALARM and prevSeverity has a different value
      • alarmSeverity is set to NO_ALARM
      • alarmStatus is set to empty
  • When the recordCommon.setSeverity(sevr,status) is called
    • If sevr is less than or equal to newSeverity nothing is done
    • else
      • alarmSeverity is set to sevr
      • alarmStatus is set to status
      • newSeverity is set to sevr

NOTE: alarmStatus and alarmSeverity are written by the normal method. This means that their values will be posted.


Channel Access/ Database Access field types


Overview

This section discusses how IOC database fields are accessed by channel access or via database links.

For the initial V4 implementation only the following types of data will be accessable.

  • primitive types
  • string
  • enum
  • one dimensional array of primitive or string or struct
  • struct with fields of following types:
    • primitive
    • string
    • enum
    • struct (use recursion for allowed types)
    • one dimensional array of primitive or string or struct

The dbdInterfaces document defines database field types. It also defines a subset called basic types, which consists of primitive types, string, array, and structure. For external access only basic types can be accessed. This means that structures and arrays that do not consist of basic types are not accessablevia clannelAccess. For example a DbfLink is not accessable via channel access as a DbfLink.

Non basic fields will only be available via some combination of basic types.

For example a DbfLink field will appear as a string. If a Database Definition is

    struct(calcInpLink) {
        field(block,boolean)
        field(link,link)
        field(value,float64)
    };
    
    record(xxx) {
        field(link,link)
        field(value,float64)
    ...
        field(inp,array(struct(calcInpLink)[]))
    ...
    }

If a client attaches to

    record.field(link)

The data will be appear in the form:

    choice(choiceName) SupportStruct(pvname= ...)

where choiceName is the name of the link support, SupportStruct is the name of the support struct asociated with the support, and the arguments are the values for the support structure.

Then if a client specifies the process variable:

    record.field(inp[1].link)

Then it connects to the link field of the second calcInpLink of field inp.


primitive types

This includes DbfBool, DbfOctet, DbfInt16, ... , DbfFloat64. These do not present any problems. The scalar value is transfered.

string

A string is just a UTF_8 encoded character string

DbfMenu and DbfEnum

Handled as an enum


DbfLink

A string with the same syntax as defined for a link field in "V4 DB Record Instance Syntax"

timeStamp

This is just transfered like a struct with two fields:

  • int64 secondsSinceEpoch
  • int32 nanoSeconds


struct

The individual fields can be accessed directly so this discussion only involves access to the entire structure.

The entire structure can be accessed as a string with the same syntax as defined for a struct field in "V4 DB Record Instance Syntax"


array

Arrays of the following types are accessable:

  • primitive - DbfBool,...,DbfFloat64
  • DbfString
  • DbfStruct - As long as its fields are valid types

Note that arrays of structs are not accessable in the early V4 releases.

Arrays still need lots more discussion!!! The database definition syntax allow an array to be any of the basic types, i.e. DbfBool,...,DbfFloat64, DbfString, DbfArray, DbfStruct.

For the initial V4 version, database access only allows access to arrays of the following types.

  • primitive - DbfBool,...,DbfFloat64
  • DbfString
  • ???? What else

An individual element of an array of type DbfStruct can be accessed directly if it satisfies the criteria for accessing a DbfStruct.

Question: Should database Access be implemented so that record/link support can transfer an array in segments. Examples:

  • If the array is a circular buffer, it is presented in two segements
  • If the array is stored in hardware, e.g. a transient recorder, the array can be read from the hardware and passed to the client in segments.

If an array is available only in segments then can we prevent two clients from trying to access the same array simultaneously?

Perhaps this is a problem that must be solved by an application:

  • runControl records are one solution
  • Other solutions can be envisioned


MDArray

Not implemented if the early V4 releases.

Associated Data

The typical example is a client that asks for timeStamp, severity, status, and data.