V4 Design: Runtime Interfaces

From EPICSWIKI
Revision as of 19:21, 14 September 2005 by MartyKraimer (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

EPICS: IOC Runtime Interfaces

September 14


Overview

This document describes definitions for IOC runtime, i.e. interfaces implemented or used by database access, record support, link support, and device support.

It assumes knowledge of the interfaces described in dbdInterfaces.


Runtime Database Access

Database Access, with help from record, link, and device support implements the dbdInterfaces. Other than Database Access, fields of a record can only be accessed via the interfaces described in dbdInterfaces. This allows the database to handle actions like posting database monitors without any help from record, link, or device support.

Database access by default allocates the actual storage for each field but allows support code to register itself to manage storage for field instances. This is particularly usefull for array fields. Two examples are:

  • The compress record registers to provide storage for the value.
    • This allows it to implement a circular buffer.
    • Code that accesses the value field may have to issue two get requests.
  • Device support for a transient recorder registers to provide storage for the array
    • This allows device support to read data from hardware in segments
    • Code that accesses the array may have to issue many get requests.

The fact that each field of a record instance is an object means that additional storage is required. Database Access will probably have something like the following:

   class Field {
       DbRecord instance;
       short          index;
   };
   ...
   class IntField extends Field {
       int data;
   }
   ...

This each field has the overhead of

  • instance - a reference to DbRecord, i.e. record instance
  • index - a 16 bit integer
  • vtbl - a reference to the object implementation

An additional pointer field will be needed for things like monitors. This field can start out null and only allocate additional storage as needed.


Record Support

    enum ProcessState {
        processCancel,
        processIdle,
        processInputActive,
        processActive,
        processOutputActive,
        processDone
    }
    interface RecordSupport {
        void destroy();
        void initialize(int32 pass);
        ProcessState process(ProcessState state);
        // if special returns false when after is false put fails
        boolean special(boolean after,Dbf[] field);
    }

ProcessState supports the following semantics:

  • cancel - If the record is active terminate
  • For all other states see the companion document "V4 Design: Record Processing"

The methods of RecordSupport are:

  • destroy - Called when a record instance is deleted.
  • initialize - Called twice (pass = 0,1) when a record is initialized.
  • process - Called to process a record. See "V4 Design: Record Processing" for semantics.
  • special - Called when a field declared special in a DBD file is modified. field is an array of Dbfs showing which field is being modified.

Discussion of special

Special is passed a Dbf array that identifies the exact field being modified. For example ExampleRecord.dbd has a field:

    field(displayLimit,struct(displayLimit))

ExampleRecordSupport.java might implement special as follows:

    boolean special(boolean after, Dbf[] field)
    {
        switch(field[0].getIndex()) {
        ...
        case ExampleRecord.displayLimitIndex:
            if(field.length==1) {
                // displayLimits itself is being modified. Do something
            } else {
               // a field of displayLimits is being modified
                switch(field[1].getIndex) {
                    case DisplayLimit.lowIndex:
                         // low being modified. do something
                    case DisplayLimit.highIndex:
                         // high being modified. do something
                }
            }
        ...
        }
    }

Link and Device Support

Link/Device Base

    interface Support { // base for Link and Device support
        void report(int16 level);
        void cancel();
        void destroy();
        void initialize();
        void connect();
        void disconnect();
    }

Support is the base class for all link and device support. An instance of this is connected to each DbfLink or DbfDevice field. The methods are:

  • report - report
  • cancel - Cancel any outstanding I/O
  • destroy - This is called if the field is being changed after initialization or if the record is being removed.
  • initialize - Called to initialize a link.
  • connect - Called to connect. Note that this is different than initilization.
  • disconnect - disconnect.

Normally record support does not need to call any of the Base Support methods since Database Access does this automatically. For example if a link or device field is modified via a channel access put, database access will call destroy before modifying the link and initialize and connect after the link is modidied.

Link Support

    enum LinkWaitResult {
        linkNoop,           // Nothing was done, e.g. link is null link
        linkDone,           // field was modified. No wait is necessary
        linkWaitSequential, // waiting. must processes links sequentially
        linkWaitParallel,   // waiting. parallel processing OK
    }
    interface Callback {
        void done();
        void timedout();
    }
    interface LinkSupport extends Support {
        void get(Dbf field);
        LinkWaitResult getWait(Dbf field, double timeout,Callback callback);
        void put(Dbf field);
        LinkWaitResult putWait(Dbf field, double timeout,Callback callback);
        void process();
        LinkWaitResult processWait(double timeout,Callback callback);
    }

LinkSupport supports the following semantics:

  • Input Link from another record
    • get current value independent of processing state.
    • Ask the record to process and wait for completion before fetching value.
    • wait until next time record processes then get value. No request is made to process the record.
  • Output Link to another record
    • put value without requesting that record be processed.
    • put value then process record but don't wait for processing to complete.
    • put value, process record, and wait for completion
  • process link to another record
    • request processing but do not wait for completion
    • request processing and wait for completion

The Wait methods all return LinkWaitResult.


Device Support

Other than that it must extend Support, nothing is defined for Device support in this document. It will be modeled after the V3 asynDriver support.

Database Access

    class DbAccess {
        void process(RecordInstance instance);
        void registerDbfSource(Dbf field, Dbf source);
        LinkSupport getLinkSupport(Dbf field);
        Support getSupport(Dbf field);
        RecordSupport getRecordSupport();
    }

NOTES:

  • This is just the beginning of defining the methods in DbAccess
  • registerDbfSource is called by code that manages the strogae for a field.
    • The compress record would do this so that it can implement circular buffers.
    • Device support for arrays stored in hardware can do this so that data can be extracted in chunks.

Registration and Instance Creation

    interface StructFactory {
        DbfStruct create();
    }
    interface RecordSupportFactory {
        RecordSupport create(RecordInstance instance);
    }
    interface SupportFactory {
        Support create(Dbf field);
    }
    interface RegisterSupport {
        structure(StructFactory create, string name);
        record(StructFactory create, string name);
        link(SupportFactory support,string name);
        device(SupportFactory support,string name);
        record(RecordSupportFactory support,string name);
    }

RegisterSupport is implemented by iocCore. Each struct DBD definition must register a StructFactory to create instances of the structure or record.

Each link, device, and record support must register a SupportFactory to create instances of the support to attach to the link, device, or record instance. During database initialization, iocCore calls the factory methods.