Generating autosave req files from DB templates#
builder2ibek autosave reads DLS EPICS DB template files that contain
# % autosave N comments and writes the standard autosave .req files
needed by the EPICS autosave module in a Generic IOC.
Background#
DLS DB templates embed autosave hints as structured comments immediately
before record(...) declarations:
# % autosave 0 VAL
record(ao, "$(device):SETPOINT") { ... }
These comments were consumed at build time by the DLS iocbuilder toolchain.
When migrating a support module to an ibek Generic IOC the same information
must be expressed as standard autosave request files (_positions.req and
_settings.req).
builder2ibek autosave extracts all autosave hints from the template files
and writes those request files automatically.
Autosave comment syntax#
# % autosave <level> [<FIELD> ...]
record(<type>, "<PV_NAME>") { ... }
The comment applies to the next record(...) declaration in the file.
<level>—0,1, or2(see level mapping below)<FIELD> ...— optional space-separated list of field names to save. If omitted, the entire record is saved (equivalent to writing the PV name without a field in the.reqfile).
A record can carry multiple autosave comments at different levels:
# % autosave 0 VAL
# % autosave 2 ZRST ONST TWST THST FRST FVST SXST SVST
record(mbbo, "$(device):$(loop_name):PID:SELECT") { ... }
Level mapping#
DLS level |
Meaning |
Output file |
|---|---|---|
|
Save on autosave pass 0 (restore on IOC start) |
|
|
Save on pass 0 and pass 1 |
|
|
Save on pass 1 only |
|
Levels 1 and 2 both map to _settings.req because AreaDetector and other
community modules use this convention, and the autosave documentation notes
that pass-1-only saves are rarely needed in practice.
Running the command#
uv run builder2ibek autosave <db_template> [<db_template> ...] --out-folder <path>
Arguments#
Argument |
Description |
|---|---|
|
One or more DB template files ( |
|
Directory to write |
Output files#
For each input file <name>.template the command creates:
<name>_positions.req— if any level-0 entries were found<name>_settings.req— if any level-1 or level-2 entries were found
Example#
Input: hiden_rga_sens_src.template#
# % autosave 2
record(ao, "$(P)$(Q):M$(M):SENS_SP") {
...
}
Command#
uv run builder2ibek autosave \
hidenRGAApp/Db/hiden_rga_sens_src.template \
--out-folder hidenRGAApp/Db/
Output: hiden_rga_sens_src_settings.req#
$(P)$(Q):M$(M):SENS_SP
(No _positions.req is written because there are no level-0 entries.)
Example with field-level saves#
Input: eurothermLoopPIDselect.template (excerpt)#
# % autosave 0 VAL
record(ao, "$(device):$(loop_name):PID:SETVALUE1") { ... }
# % autosave 0 VAL
# % autosave 2 ZRST ONST TWST THST FRST FVST SXST SVST
record(mbbo, "$(device):$(loop_name):PID:SELECT") { ... }
Output: eurothermLoopPIDselect_positions.req#
$(device):$(loop_name):PID:SETVALUE1.VAL
$(device):$(loop_name):PID:SELECT.VAL
Output: eurothermLoopPIDselect_settings.req#
$(device):$(loop_name):PID:SELECT.ZRST
$(device):$(loop_name):PID:SELECT.ONST
$(device):$(loop_name):PID:SELECT.TWST
$(device):$(loop_name):PID:SELECT.THST
$(device):$(loop_name):PID:SELECT.FRST
$(device):$(loop_name):PID:SELECT.FVST
$(device):$(loop_name):PID:SELECT.SXST
$(device):$(loop_name):PID:SELECT.SVST
Processing multiple templates at once#
Pass all template files as positional arguments to generate all .req files
in one invocation:
uv run builder2ibek autosave \
hidenRGAApp/Db/hiden_generic.db \
hidenRGAApp/Db/hiden_rga_sens_src.template \
hidenRGAApp/Db/hiden_rga_mid_mass.template \
--out-folder hidenRGAApp/Db/
Or use shell globbing:
uv run builder2ibek autosave hidenRGAApp/Db/*.template --out-folder hidenRGAApp/Db/
Where to place the generated files#
Place the .req files alongside the DB templates inside the support module
source tree, typically in <module>App/Db/. Commit them to version control
so that the Generic IOC Docker build includes them without needing to run
builder2ibek autosave at build time.
At runtime, ibek’s ibek runtime generate2 command scans all entities in
ioc.yaml and assembles the aggregate autosave_positions.req and
autosave_settings.req files in /epics/runtime/. The autosave.Autosave
entity then loads these via create_monitor_set in the startup script:
# from autosave.ibek.support.yaml
set_requestfile_path("/epics", "runtime")
...
create_monitor_set autosave_positions.req, 5, ""
create_monitor_set autosave_settings.req, 30, ""
This means the per-module .req files generated by builder2ibek autosave
feed into the ibek runtime generation pipeline rather than being loaded
directly by the EPICS autosave module.
Tip
If you are not using a DLS support module, but are switching to using the upstream module and it has no .req files then you have two options:
add the req files as above and submit a PR to upstream (not always possible)
drop the generated req files into the ibek-support folder alongside xxx.ibek.support.yaml. These will be used at runtime by ibek startup.
Integration with the conversion workflow#
If you are converting an existing DLS IOC support module to ibek, generate the autosave request files as part of the initial migration:
Run
builder2ibek autosaveon all DB templates that carry# % autosavecommentsCommit the generated
.reqfiles into the support module’sDb/directoryAdd an
autosave.Autosaveentity to yourioc.yaml(this is usually already present in converted IOCs — see Convert a builder XML IOC instance to ibek YAML)