1 / 15

Field Support Ideas

Field Support Ideas. Tech-talk, 19 July 2007. Good Afternoon,

tyrone
Télécharger la présentation

Field Support Ideas

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Field Support Ideas

  2. Tech-talk, 19 July 2007 Good Afternoon, I have now for the <n>th time explained to some desperate EPICS newbie all the hoops one has to go through in order to create an array field for a new record type. This is starting to get on my nerves, the more so because I can't really tell them to go away and RTFM…. I dearly hope that with 3.15 there will be a dbd syntax for creating array fields. Ideally there should be a way to specify another field whose value at startup time determines the maximum number of elements. Life would be almost perfect if in addition the runtime number of elements could be specified in a similar way. It could be as simple as just one more (possible) property for a field value like, for instance, field(BLA,DBF_UCHAR) { ... array(NELM,NORD) } which might optionally allow a literal number for the first argument (for a fixed size array) and where the second argument is optional (for arrays that don't change their number of elements at runtime). This would be a tremendously useful addition and would come at very low cost. It is even backward compatible. Frankly, I am amazed that something like this hasn't been done a long time ago. Cheers Ben (Franksen)

  3. How do we solve this problem? …start by looking at the record support

  4. Record support entry table typedef struct rset { long number; long (*report)(FILE fp, struct dbCommon * pRec); long (*init)(void); long (*init_record)( struct dbCommon *, int pass ); long (*process)( struct dbCommon * ); long (*special)( const struct dbAddr *paddr, int after ); long (*get_value)( struct dbCommon *, struct valueDes *p ); long (*cvt_dbaddr)( struct dbAddr * paddr ); long (*get_array_info)( const struct dbAddr *paddr, long *no_elements, long *offset); long (*put_array_info)( const struct dbAddr *paddr, long nRequest ); long (*get_units)(const struct dbAddr *paddr, char *units); long (*get_precision)(const struct dbAddr *paddr, long *precision); long (*get_enum_str)(const struct dbAddr *paddr, char * pbuffer); long (*get_enum_strs)(const struct dbAddr *paddr, struct dbr_enumStrs *p); long (*put_enum_str)(const struct dbAddr *paddr, const char * pbuffer); long (*get_graphic_double)(const struct dbAddr *paddr, struct dbr_grDouble *pgd); long (*get_control_double)(const struct dbAddr *paddr, struct dbr_ctrlDouble *pcd); long (*get_alarm_double)(const struct dbAddr *paddr,struct dbr_alDouble *p); } rset;

  5. Record support entry table typedef struct rset { long number; long (*report)(FILE fp, struct dbCommon * pRec); long (*init)(void); long (*init_record)( struct dbCommon *, int pass ); long (*process)( struct dbCommon * ); long (*special)( const struct dbAddr *paddr, int after ); long (*get_value)( struct dbCommon *, struct valueDes *p ); long (*cvt_dbaddr)( struct dbAddr * paddr ); long (*get_array_info)( const struct dbAddr *paddr, long *no_elements, long *offset); long (*put_array_info)( const struct dbAddr *paddr, long nRequest ); long (*get_units)(const struct dbAddr *paddr, char *units); long (*get_precision)(const struct dbAddr *paddr, long *precision); long (*get_enum_str)(const struct dbAddr *paddr, char * pbuffer); long (*get_enum_strs)(const struct dbAddr *paddr, struct dbr_enumStrs *p); long (*put_enum_str)(const struct dbAddr *paddr, const char * pbuffer); long (*get_graphic_double)(const struct dbAddr *paddr, struct dbr_grDouble *pgd); long (*get_control_double)(const struct dbAddr *paddr, struct dbr_ctrlDouble *pcd); long (*get_alarm_double)(const struct dbAddr *paddr, struct dbr_alDouble *p); } rset; All the highlighted routines take a field pointer, rather a record pointer.

  6. Field Support • Provides default handling for common field type behaviours. • Methods provided by a field support entry table, similar to record support. • It is independent of the record type, and can take parameters passed in the dbd file. • Important to remember that parameters are per record type, not per record instance. • At this point, I think field support should only access other fields in the current record, but not other records. • In the current implementation, everything handled by offsets – types are checked at initialisation.

  7. Progress so far • Made all the changes required in base to support field support. • Provided some helper routines to make field support easy to write. • Written a default field support implementation that does all the “normal” things you would expect, and could replace most of the cvt_dbaddr, get_array_info, put_array_info, get_units get_precision, get_graphic_double, get_control_double and get_alarm double routines in base.

  8. Field support entry table typedef struct { long number; long (*report)(FILE fp, struct dbFldDes * dbFldDes); long (*init)(void); void * (*init_field)( struct dbBase * dbbase, struct dbFldDes *); long (*init_record)( struct dbCommon *, struct dbFldDes * dbFldDes, int pass ); long (*special)( const struct dbAddr *paddr, int after ); long (*cvt_dbaddr)( struct dbAddr * paddr ); long (*get_array_info)( const struct dbAddr *paddr, long *no_elements, long *offset); long (*put_array_info)( const struct dbAddr *paddr, long nRequest ); long (*get_units)(const struct dbAddr *paddr, char *units); long (*get_precision)(const struct dbAddr *paddr, long *precision); long (*get_enum_str)(const struct dbAddr *paddr, char * pbuffer); long (*get_enum_strs)(const struct dbAddr *paddr, struct dbr_enumStrs *p); long (*put_enum_str)(const struct dbAddr *paddr, const char * pbuffer); long (*get_graphic_double)(const struct dbAddr *paddr, struct dbr_grDouble *pgd); long (*get_control_double)(const struct dbAddr *paddr, struct dbr_ctrlDouble *pcd); long (*get_alarm_double)(const struct dbAddr *paddr,struct dbr_alDouble *p); } fldSup_SET;

  9. Field support processing • If field support is defined and there is an appropriate entry in the field support table the routine is called. • If field support is not defined, or if there is no entry in the field support table then the record support routine is called. • If the field routine returns with failure then the record support routine is also called. • If both field and record support routines report failure, then recGbl default routines are called, if necessary.

  10. field(BLA,DBF_NOACCESS) { … special(SPC_DBADDR) fldSup(fldSupDefault_fset) fldSup_type(UCHAR) fldSup_nelm(NELM) fldSup_nord(NORD) extra("void * val") } This is the equivalent of Ben Franksen’s example in the tech-talk posting. fldSup_ prefix is ugly for something which is really a sub structure, but it doesn’t break the dbd file syntax and so existing applications (e.g. vdct) don’t have to change. It’s a bit more verbose than Ben’s, but probably acceptable. Example of field support in a dbd file

  11. field(VAL,DBF_NOACCESS) { prompt("Value") asl(ASL0) special(SPC_DBADDR) fldSup(fldSupDefault_fset) fldSup_bptr(BPTR) fldSup_type(FTVL) fldSup_nelm(NELM) fldSup_nord(NORD) fldSup_prec(PREC) fldSup_units(furlongs) fldSup_hopr(HOPR) fldSup_lopr(LOPR) fldSup_drvh(HOPR) fldSup_drvl(LOPR) fldSup_hihi(HOPR) fldSup_high(HOPR) fldSup_low(LOPR) fldSup_lolo(LOPR) pp(TRUE) extra("void * val") } Parameters can either be other fields in the record (e.g. PREC) or constants (e.g. furlongs). If you leave out fldSup_ declarations then the corresponding field support routine returns S_db_noRSET and defaults are used. A more complete example

  12. dbStatic field support helper routines fldSupParamId fldSupParamAdd( fldSupParamId pFldSup, char * name, char * value ); long fldSupParamFree(fldSupParamId pFldSup); char * fldSupParamGet(fldSupParamId pFldSup, const char * name ); long fldSupParamNth( fldSupParamId pFldSup, const unsigned int n, char ** name, char ** value); • These just maintain a linked list of name-value pairs, so they can regurgitated or queried at a later time. • Not to be accessed after runtime initialisation

  13. Field support structures • Field support structures stored in dbFldDes: • Field support entry table. • Name-value pairs generated by dbStatic and available at initialisation. • Pointer to a private runtime structure • dbFldDes can be accessed at run-time through dbAddr

  14. Field support runtime helpers • dbFldLookup( dbFldDes * pFldDes, char * name, type, int offset ); • Used at initialisation to check types and to get the record offset of other fields in the record. • void * dbFldSupPvt( DBADDR dbAddr ); • Returns field support private structure. • void * dbFldPtr( DBADDR dbAddr, offset ); • Returns a pointer to another field in a record given an offset. (prossibly a macro).

  15. Pros and Cons • Cons: • Fairly significant change • May be some more (or less) additional overhead if used. • Pros • Can provide simple support for arrays. • Backwards compatible – can be done now. • Can possibly provide support for dynamic strings. • Makes it more probable that better meta-data support is provided because it is easier to do. • Avoids a big switch statement in support routines. • Status • At present this has been submitted to base, but should only be viewed as a prototype implementation.

More Related