initialize VAL of an mbbi/o record with a string

Bug #541396 reported by Ben Franksen
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
EPICS Base
Triaged
Wishlist
Andrew Johnson

Bug Description

With the following record in a db file

record(mbbo,"TEST:mbbo") {
 field(VAL,"Zero")
 field(ZRST,"Zero")
 field(ONST,"One")
}

I get

dbLoadRecords("test.db", "")
Error Last token ")"
input line: field(VAL,"Zero")
   in: path "." file test.db line 2

I think it would be nice to be able to initialize an mbbo or mbbi record with one of the configured string values.

Original Mantis Bug: mantis-373
    http://www.aps.anl.gov/epics/mantis/view_bug_page.php?f_id=373

Tags: 3.14
Revision history for this message
Andrew Johnson (anj) wrote :

I don't think this is likely to be possible anytime soon; only the record type code knows which fields make up the possible menu choices, and the record types don't get initialized until iocInit(), which currently can only happen after all the .db files have been loaded.

If we ever implement the ability to create new record instances while running it might be possible to use dbLoadRecords() after iocInit() in which case the desired behavior should be possible (as long as the VAL field is defined after the relevant ??ST field has been set). However I suspect there would be a significant loss of performance doing this; the current parser was written assuming the database is inactive when it runs, so it doesn't bother with things like record locking, recalculating lock-sets or adding records to the periodic scan lists.

Changed in epics-base:
status: New → Won't Fix
Revision history for this message
Ben Franksen (bfrk) wrote : Re: [Bug 541396] Re: initialize VAL of an mbbi/o record with a string

On Mittwoch, 24. März 2010, Andrew Johnson wrote:
> I don't think this is likely to be possible anytime soon; only the
> record type code knows which fields make up the possible menu choices,
> and the record types don't get initialized until iocInit(), which
> currently can only happen after all the .db files have been loaded.

You are taking the way record instances are initialised in EPICS for
granted. Of course, what I requested cannot be done without inventing some
mechanism that deals with the problem you describe. Such a mechanism need
not be as invasive as allowing to add record instances at runtime, not by
far.

To illustrate, here is a sketch of a possible solution. The idea is to
postpone (delay) initialisation of certain fields until the proper phase of
iocInit, i.e. init_record, is reached. Which fields should be treated in
this way is specified in the record type dbd with a new field property
named 'lazy' of type yes/no, defaulting to no(*). A 'lazy' field has its
initial string value stored along with the record instance (and the actual
record field uninitialised) until after init_record has been called, after
which the string becomes invalid. The init_record procedure is responsible
for interpreting these strings and for initialising the actual record field
accordingly. The address of the init string could be put into a union
together with the actual field type; this would have to be handled by the
dbToRecordTypeH tool.

(BTW, this is quite similar to how link fields are handled now.)

The above specification of the init string's guaranteed lifetime has the
advantage of allowing efficient allocation and deallocation of the memory
needed for them. More specifically, it allows for a strategy in which
memory gets allocated in large chunks and filled by incrementing a "free"
pointer (except when the chunk is full), thereby amortizing the allocation
(and deallocation) cost. After the init_record phase, all the memory can be
freed in one go, leaving a large hole without danger of fragmentation.

With such a mechanism in place, another long-standing problem could be
solved immediately, namely that fields of array type cannot currently be
initialised in the db file (leading to awkward work-arounds like using an
SNL program, calling procedures from the ioc shell, etc...). We simply
treat array fields as 'lazy' by default. All that needs to be done is to
invent a suitable array syntax; for convenience and to discourage
proliferation of custom syntaxes and parsers, we could provide a routine in
base (to be called by init_record) that interprets a string in array syntax
by successively returning the individual elements (as single strings).
Given properly light-weight array syntax, this would be more or less a thin
wrapper around strtok. (Note it's ok to destroy the original array value
string in the process: it is not used any further and will be freed soon
afterwards anyway.)

(*) A usual, concrete syntax is only for illustration, other names may be
more appropriate, such as 'postpone' or 'delay'...

Andrew Johnson (anj)
Changed in epics-base:
status: Won't Fix → Confirmed
Revision history for this message
Andrew Johnson (anj) wrote :

Comment from Tim Mooney:

I can't tell from context exactly what problem is being discussed, but it seems like you could take an exploratory stab, at some of what you'd like to do, using info nodes.

I'm imagining you would modify a record's init_record() routine to parse the record's info node(s), looking for a specially named or defined node to indicate a field that needs a lazy load, and the data that should be loaded. This would allow you to make at least some progress without waiting for any (other) changes in base.

Revision history for this message
Andrew Johnson (anj) wrote :

Would it be acceptable to do this through a constant string in the mbbo.DOL link instead of by setting VAL?

I can see this could be made to work if there were a new kind of constant link that can support non-numeric constants, including arrays, since as Ben suggests a PV link doesn't actually parse the string until iocInit() time.

This actually happens to be an area I've been working on in the last couple of weeks, and I suspect this ability might fall out of my work, so I'll see if I can implement something like it. I'm guessing it may need changes to the record type code, but that's not certain right now.

Changed in epics-base:
assignee: nobody → Andrew Johnson (anj)
status: Confirmed → Triaged
Revision history for this message
Andrew Johnson (anj) wrote :

It should now (Base-3.16 or later) be possible for an mbbo record to initialize itself from a constant string in DOL as previously described in this bug. However this could change existing initialization behavior unless the developer is careful, I suggest writing a number of self-tests first to capture what happens now when both DOL is set and dset::init_record() sets RVAL.

The same should be possible for an mbbi when INP is set to a constant string, but the code belongs in the Soft Channel dset::init_record() routines (in all devMbbiSoft*.c files).

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.