[Date Prev][Date Next][Date Index]

Reassignable Database Links




In case some of you folks do not subscribe to the epics_applications
email list, here's an EPICS capability we've been lobbying for.


----- Begin Included Message -----

From nda@aps.anl.gov Thu May 12 12:25:47 1994
To: epics_applications@phebos.aps.anl.gov
Subject: Reassignable Database Links
Content-Length: 3434
X-Lines: 98


There has been some discussion recently about 'dynamic' or 'reassignable'
links within an EPICS database. There is currently a way to implement this
feature, with only a slight compromise in 'link' functionality.

There are fundamentally two mechanisms for reading/writing values in the
database :

    dbGetLink/dbPutLink   and   dbGetField/dbPutField

Most existing record support modules use dbGetLink/dbPutLink when processing
a linked field. The advantage of this is that each link has the settable
attributes of 'Process Passive' and 'Maximize Severity'. This gives the
application developer much flexibility in controlling the processing of records.
The disadvantage is that records that are linked (such that they force
processing) are included in the same lockset, which <currently> only gets
calculated at init time.

On the other hand, dbGetField calls cannot process the record prior to 
returning the value and dbPutField calls process the destination record only
if the destination field was defined to be Process Passive in the Ascii 
Definition File for that record. If these constraints for links are acceptable,
the following mechanism can be used to have 'reassignable' database links:


For each 'reassignable link', define three fields in the xxRecord.ascii : a
string for the PV name, a pointer to dbAddr, and a flag to indicate if
the pointer is valid. For example:

'Detector PV Name'     DPVN SPC_MOD    DBF_STRING     NO    1 40           6
'Detector dbAddr'      DDBA SPC_NOMOD  DBF_NOACCESS   NO    4  4  void * ddba;
'dbAddr Valid'         DDBV NULL       DBF_LONG       NO    1  0           0


During record init:

  pscan->ddbv = dbNameToAddr(pscan->dpvn,(struct dbAddr *)pscan->ddba);


To read from a link:

  if(!pscan->ddbv) {
    status = dbGetField(pscan->ddba, DBR_DOUBLE, &amp;(pscan->val), &amp;options,
                        &amp;nRequest, NULL);
  }


To write to a link, use a general purpose callback task (refer to Section 2.2.1
in the EPICS Application Developers Guide, Aug 1993) to execute the following
statements (using a separate execution thread will ensure no lockup's) :

  if(!pscan->ddbv) {
    status = dbPutField(pscan->ddba, DBR_DOUBLE, &amp;(pscan->val), nRequest);
  } 


To reassign the link, include the following in the special() routine:


static long special(paddr,after)
    struct dbAddr *paddr;
    int           after;
{
    struct scanRecord   *pscan = (struct scanRecord *)(paddr->precord);
    int                 special_type = paddr->special;
    long status;

    long prevValue;

    if(!after) {
        return(0);
    }

  switch(special_type) {
    case(SPC_MOD):
      if(paddr->pfield==(void *)&amp;pscan->dpvn) {
         prevValue = pscan->ddbv;
         pscan->ddbv = dbNameToAddr(pscan->dpvn,(struct dbAddr *)pscan->ddba);
         if(pscan->ddbv != prevValue) {
             db_post_events(pscan,&amp;pscan->ddbv,DBE_VALUE);
         }
         return(0);
      }


By writing a string to the .DPVN field of the record, one can reassign the
link on the fly. If you are using MEDM, dragging a PV Name into a text entry
widget tied to the .DPVN field will reassign this link without TYPING !!

Providing warning text (e.g. PV Name Invalid) that is visible when .ddbv != 0
will inform the operator of the validity of the PV name.

The above has been implemented and demonstrated. It also has the blessing of
Marty Kraimer as not breaking any EPICS rules.


	Ned Arnold



----- End Included Message -----