Autosave is a two-part operation: run-time save, and boot-time restore. The run-time part (the save_restore task or thread) is started by commands in the IOC startup file, and persists while the IOC is running. Its primary job is to save PV values to files on a server, but it also supports manual restore and other management operations. The boot-time part (dbrestore.c) is invoked during iocInit, via an EPICS initHook. It restores PV values from files written by the run-time part, and does not persist after iocInit() returns.
In addition to the autosave software, the autosave module contains a client program, asVerify, to compare written autosave files with current PV values. This program can also write an autosave file from which PV values can be restored. Because one use of asVerify is to retrieve PV values from an IOC that is having trouble (the save_restore task has crashed, for example), asVerify connects with only one PV at a time. This makes asVerify rather slow. In one trial, it took two minutes to verify a .sav file containing 5000 PVs.
Autosave also contains a facility, called configMenu, for creating, saving, finding, restoring, and verifying IOC configurations (that is, sets of PV values). configMenu is roughly comparable to the EPICS Backup and Restore Tool, BURT, but it uses autosave files, and is driven by EPICS PVs, so it can be used manually, by software clients, and by other IOC code.
Autosave also contains a facility, called autosaveBuild, to generate autosave-request files as part of the operation of the EPICS functions dbLoadRecords() and dbLoadTemplate(). This facility requires EPICS 3.15, or 3.14 with a patch.
If you want the restored value available for use by device support during its initialization, you must cause the value to be restored during pass 0. (Note that arrays cannot be restored at this time, because storage normally will not have been allocated for them yet.) If you want the restored value to overwrite the value written by record/device initialization, you must cause the value to be restored during pass 1.
Motor-record positions (VAL or DVAL) should be restored only before record initialization (that is, during pass 0), because this is the assumption under which motor-record device support was written.
In the lore that has built up around autosave, PV's that should be restored only before record initialization have been termed "positions". All other PV's have been termed "settings". Thus, you might run across a file called 'auto_positions.req', and now you'll know that the PVs in this file are intended to be restored only during autosave's pass-0.
save_restore.cmd
and create_monitor_set
.
AUTOSAVE=<path to the autosave module>to xxx/configure/RELEASE, add
xxx_LIBS += autosaveto xxxApp/src/Makefile, and add
include "asSupport.dbd"to iocxxxInclude.dbd.
xxx:m1.VAL xxx:m2.VAL
Request files can also contain macro variables, whose values will be defined
in the call that causes the request file to be processed. For example, the above
request file could also be written as shown below, with the macro P
defined by the command create_monitor_set("auto_settings.req", 30,
"P=xxx:")
:
$(P)m1.VAL $(P)m2.VAL
Request files can include other request files (nested includes are allowed) and macro substitution can be performed on the included files (using William Lupton's macro library), with the following syntax:
file <request_file> <macro-substitution_string>e.g.,
file motor_settings.req P=xxx:,M=m1
I've tried to defend against forseeable variations in syntax, so that "file" commands with embedded whitespace and/or quotes, macro strings without commas, and empty macro strings will be parsed as one would want. Generally, quotes are ignored, whitespace implies a comma but otherwise is ignored, and everything after the second sequence of non-whitespace characters (that is, after the file name) is taken as the macro-substitution string. Macro substitution is performed on the entire line, so it's possible to parameterize names of included files, as well as PV names. It is also possible to define a macro that replaces its target with nothing.
NOTE: Beginning with autosave 5.1, it's no longer legal to have a comment on the same line as a file command. This change was made to permit the use of the '#' character in a macro definition.
Most synApps modules contain autosave-request files that are intended to be included in an ioc's autosave-request file(s). For example, calc/calcApp/Db/scalcout_settings.req contains a list of the fields one might want to autosave for a single scalcout record. This file is included in calc/calcApp/Db/userStringCalcs10_settings.req, which, in turn, is included in xxx/iocBoot/iocvxWorks/auto_settings.req.
Beginning with version 4.3, autosave can generate request files from
info nodes contained in an EPICS database. See the function
makeAutosaveFiles()
, below, for more information on this topic.
Note: Beginning with synApps version 5.2.1, synApps contains software to generate autosave-request files from information contained in command and database files. See synApps/support/utils/makeAutosaveFiles.py.
Beginning with synApps version 5.5, autosave contains software to generate autosave-request files from dbLoadRecords() and dbLoadTemplate() calls. See autosaveBuild.
For systems using cdCommands
:
set_requestfile_path(startup, "") set_requestfile_path(startup, "autosave") set_requestfile_path(area_detector, "ADApp/Db") ...
For systems using envPaths
:
set_requestfile_path("$(TOP)/iocBoot/$(IOC)", "") set_requestfile_path("$(TOP)/iocBoot/$(IOC)", "autosave") set_requestfile_path("$(AREA_DETECTOR)", "ADApp/Db") ...
save_restoreSet_NFSHost("oxygen", "164.54.49.4")
When autosave manages its own NFS mount, as this command directs it to do, it can fix a stale file handle by dismounting and remounting the file system.
nfsMount()
command in your startup script. Save_restore is only
tested with NFS, and probably will not work with vxWorks' netDrv .
When autosave runs under operating systems other than vxWorks and RTEMS, it simply uses whatever mount the operating system, or a system administrator, has provided.
set_savefile_path("/full/path")in your startup script, before the
create_xxx_set()
commands, to
specify the path to the directory. If you are using NFS (strongly recommended),
ensure that the path does not contain symbolic links. In my experience, VxWorks
cannot write through a symbolic link. (I don't understand all the ins and outs
of this limitation. It may be that symbolic links are OK if they contain
absolute path names.)
Beginning with autosave v4.3, you can also specify the path and/or filename, to which an autosave .sav file is to be written, with an EPICS PV. See the documentation of create_xxx_set() for details.
set_pass0_restoreFile("auto_settings.req", "P=xxx:") set_pass1_restoreFile("auto_settings.req", "P=xxx:")(Note "macrostring" is optional, and a new feature of autosave 5.4.)
Place these commands in the startup file before iocInit
. In versions earlier
than 4.4, autosave would attempt to restore "auto_positions.sav" and "auto_settings.sav", if
no restore files had been specified. Beginning with version 4.5, only files specified in
calls to set_passn_restoreFile() are restored.
If you specify only a file name, not a path, to set_pass<n>_restoreFile(), autosave will prepend the path specified in set_savefile_path(). This is the most common way to specify a restore file.
Beginning with autosave 5.4, if you specify a full path beginning with '/', autosave will not prepend anything to it. (Also, autosave will not write a restore-time backup of the file in this case.)
To disable boot-time restore completely, delete or comment out all
set_passn_restoreFile()
calls.
Notes on restore passes:
Link fields cannot be restored (by dbStatic calls) after record initialization. If you want save/restore to work for link fields you must specify them in a pass-0 file.
Device support code for the motor record uses the value of the field DVAL, restored during pass 0, only if the value read from the hardware is zero. If the value from hardware is nonzero, it is used instead of the restored value.
Arrays cannot be restored during pass 0.
Scalar PV's that have type DBF_NOACCESS in the .dbd file, and are set to some other DBF type during record initialization, cannot be restored during pass 0.
save_restoreSet_DatedBackupFiles(1)
Note: If a save file is restored in both pass 0 and pass 1, the boot-backup file will be written only during pass 0.
save_restoreSet_NumSeqFiles(3) save_restoreSet_SeqPeriodInSeconds(600)will cause save_restore to maintain three copies of each .sav file, at ten-minute intervals. Note: if autosave fails to write the .sav file, it will stop making sequence copies until it again succeeds.
save_restoreSet_RetrySeconds(60)
save_restoreSet_CAReconnect(1)
save_restoreSet_CallbackTimeout(-1)
create_monitor_set("auto_positions.req", 5, "P=xxx:") create_monitor_set("auto_settings.req", 30, "P=xxx:")to your EPICS startup file after iocInit. The third argument to
create_monitor_set()
is a macro-substitution string, as described
above in the discussion of request files (step 2). If supplied, this
macro-substitution string supplements any macro strings supplied in include-file
directives of request files read for this save set.
Note: if you want to start the save task without also creating a save set, you
can call create_monitor_set()
with no arguments.
The macro string can also be used to override the default path and name to which the .sav file will be written. If the macro SAVEPATHPV=<pv-name> is included, autosave will write the .sav file to the path read from the EPICS PV <pv-name>, instead of writing to the path specified in set_savefile_path(). If the macro SAVENAMEPV=<pv-name> is included, autosave will write the .sav file to the filename read from the EPICS PV <pv-name>. (By default, the .sav file name is the request-file name, with .req replaced by .sav.)
NOTE: If either SAVEPATHPV or SAVENAMEPV occurs in the macro string, autosave will not attempt to save backup or sequence files for the save set.
For each create_monitor_set(<name>.req, <time>, <macro>)
command, the
save_restore process will write the files <name>.sav and <name>.savB every
<time> seconds, if any of the PVs named in the file <name>.req have changed
value since the last write. Other create_xxx_set()
commands do the same thing,
but with different conditions triggering the save operation.
Note that in versions prior to 2.7, create_monitor_set()
used an
argument of type double to specify the period (in seconds). This doesn't work on
PowerPC processors, under vWorks, so the arguments for this and similar functions
were changed to int.
If your IOC takes a really long time to boot, it's possible the PVs you want to save will not have the correct values when the save_restore task first looks at them. (If you are restoring lots of long arrays, this is even more likely.) Under vxWorks, you can avoid this by putting a
taskDelay(<number_of_60_Hz_clock_ticks>)before
create_monitor_set()
.
Note: this facility requires an EPICS base version higher than 3.15.0.2, or a patch to EPICS base 3.14. To enable the code in autosave, you must edit asApp/src/Makefile, and uncomment the line
#USR_CFLAGS += -DDBLOADRECORDSHOOKREGISTER
Many of the databases in synApps have associated autosave-request files. For
example, the calc module contains editSseq.db
and
editSseq_settings.req
. When adding a new database to an IOC, it's
common practice to add the associated request file to
auto_settings.req
and/or auto_positions.req
. For
clarity, st.cmd
contains this:
anddbLoadRecords("$(CALC)/calcApp/Db/editSseq.db", "P=xxxL:,Q=ES:")
auto_settings.req
contains this:
file editSseq_settings.req P=xxxL:,Q=ES:
It's tedious and error prone to have these entries separately maintained, so
autosave can do the request-file part for you. To do this, you tell autosave
to arrange to be called whenever dbLoadRecords()
is called (note
that dbLoadTemplate()
calls dbLoadRecords()
), you
tell it how to make a request-file name from a database-file name, and you give
it the name of the request file you want it to build. You can do this with
the following command:
This tells autosave to do the following:autosaveBuild("built_settings.req", "_settings.req", 1)
built_settings.req
. If this is
the first call that mentions built_settings.req
, erase the file.
built_settings.req
.
All this does is get the file built_settings.req
built. If you
want it to be used, you must add the following line to
auto_settings.req
:
file built_settings.req P=$(P)
autosaveBuild()
:
autosaveBuild("built_settings.req", "_settings.req", 1) autosaveBuild("built_settings.req", ".req", 1)After these calls, the request-file name for
abc.db
can be
either abc_settings.req
or abc.req
. If both are
found, lines for both will be added to built_settings.req
.
You can disable file/suffix combinations separately:
autosaveBuild("built_settings.req", "_settings.req", 0)
built_settings.req
.
autosaveBuild("built_settings.req", "*", 0)
built_settings.req
.
You can also add a line to built_settings.req
yourself:
appendToFile("built_settings.req", '$(P)userStringSeqEnable')Note the use of single quotes. This is for iocsh, because it will not accept failure to expand the macro
$(P)
, and single quotes tells it to
not do macro expansion.
--- src/db/dbAccess.c.ORIG 2014-10-16 16:51:21.778507000 -0500 +++ src/db/dbAccess.c 2014-11-03 12:16:51.394148000 -0600 @@ -815,9 +815,16 @@ return dbReadDatabase(&pdbbase, file, path, subs); } +/* dbLoadRecordsHook from base-3.15 */ +epicsShareDef DB_LOAD_RECORDS_HOOK_ROUTINE dbLoadRecordsHook = NULL; + int epicsShareAPI dbLoadRecords(const char* file, const char* subs) { - return dbReadDatabase(&pdbbase, file, 0, subs); + int status = dbReadDatabase(&pdbbase, file, 0, subs); + + if (!status && dbLoadRecordsHook) + dbLoadRecordsHook(file, subs); + return status; } --- src/db/dbAccessDefs.h.ORIG 2014-11-03 12:06:29.118353000 -0600 +++ src/db/dbAccessDefs.h 2014-11-03 12:08:27.229610000 -0600 @@ -276,6 +276,12 @@ short dbrType,long options,long nRequest); epicsShareFunc long epicsShareAPI dbValueSize(short dbrType); +/* Hook Routine */ + +typedef void (*DB_LOAD_RECORDS_HOOK_ROUTINE)(const char* filename, + const char* substitutions); +epicsShareExtern DB_LOAD_RECORDS_HOOK_ROUTINE dbLoadRecordsHook; + epicsShareFunc int epicsShareAPI dbLoadDatabase( const char *filename, const char *path, const char *substitutions);
usage: asVerify [-vrd] <autosave_file> -v (verbose) causes all PV's to be printed out Otherwise, only PV's whose values differ are printed. -r (restore_file) causes a restore file named '<autosave_file>.asVerify' to be written. -d (debug) increment debug level by one. -rv (or -vr) does both examples: asVerify auto_settings.sav (reports only PVs whose values differ from saved values) asVerify -v auto_settings.sav (reports all PVs, marking differences with '***'.) asVerify -vr auto_settings.sav (reports all PVs, and writes a restore file.) asVerify auto_settings.sav caput <myStatusPV> $? (writes number of differences found to a PV.)
Note that asVerify cannot read an autosave request file; it will understand any PV names contained in the file, but it cannot parse the "file" command, perform macro substitutions, or include other request files.
Beginning with autosave R5.6.1, asVerify can be called from the IOC console:
asVerify(char *fileName, int verbose, char *restoreFileName)Examples:
asVerify("auto_settings.sav")
This will print out differences.
asVerify("auto_settings.sav",0,"junk.sav")
This will print out differences and write "junk.sav" in the IOC's current directory.
Suppose we want to configure a set of three sscan records to perform any of 10 different types of scans. Here are the steps needed to implement a menu of scan types, and to give the user a GUI display for creating scan types and loading them. (In the following, scan1 is the name of this instance of configMenu. The files it loads and saves will be named "scan1_<config Name>.cfg".)
Here an example of what the user might see:
- Create an autosave request file, which I'll call "scan1Menu.req", with the following content:
file configMenu.req P=$(P),CONFIG=$(CONFIG) file scan_settings.req P=$(P),S=scan2 file scan_settings.req P=$(P),S=scan1 file scan_settings.req P=$(P),S=scanHThis is required only if scan1 config files are to be written at run time.- Add the following lines to
st.cmd
:
dbLoadRecords("$(AUTOSAVE)/asApp/Db/configMenu.db","P=xxx:,CONFIG=scan1")
This goes beforeiocInit
. You can disable the saving of scan1 config files by specifying the macroENABLE_SAVE=0
.
create_manual_set("scan1Menu.req","P=xxx:,CONFIG=scan1,CONFIGMENU=1")
This goes afteriocInit
, and is required only if you intend for scan1 config files to be written at run time, or if you need to have macro substitution performed on a scan1 config file to be loaded. The macroCONFIGMENU
tells autosave to refrain from writing backup (.savB) and sequence (.sav1, .sav2, etc.) files for this save set.- Add an MEDM related-display entry to bring up a configMenu*.adl display.
label="scan1Menu" name="configMenu.adl" args="P=xxx:,CONFIG=scan1"- If all of the PVs in a configuration are being autosaved, and you want the current configuration name and description, and the
enableSave
selection also to be autosaved, add the following line to auto_settings.req:file configMenu_settings.req P=$(P),CONFIG=scan1I'm not sure this is really a great idea, because the autosaved values aren't guaranteed to be the same as the values in the .cfg file. (The user might have loaded a .cfg file and then made some changes, for example.) But it's disconcerting for a user to reboot the ioc and not have everything come back just as it was, so I normally do this.
![]() configMenu_small.adl ![]() configMenu.adl ![]() configMenu_more.adl |
In configMenu_small.adl, the menu of configurations is displayed by
and selected from the enum PV, $(P)$(CONFIG)Menu
, (e.g.,
xxx:scan1Menu
). This is the most convenient way for configMenu to
be driven by CA-client software, because a single PV contains the menu choices
and is also the PV to which choices are written to cause loading. This display
cannot cause a configuration to be written. When the menu is repopulated, MEDM
will not automatically retrieve the new names for display by
$(P)$(CONFIG)Menu
. This must be done manually, by closing and
reopening the display, which is what the "Refresh menu choices" button does.
configMenu.adl and configMenu_more.adl show the menu choices as separate PVs, for which no manual refresh is needed, and provide buttons for loading and saving configurations.
configMenu_more.adl also shows description PVs. When the menu is
populated by searching for config files, descriptions are extracted from those
files. Otherwise, if configMenuNames.req is included in an autosave-request
file, names and descriptions will be restored at boot time. If the
enableSave
PV (labelled "permit save?") has the value "No" (0), the
"Save" buttons will not be displayed, and users will not be able to save
configuration files.
You don't want to make two configurations whose names differ only in non-alphanumeric characters; configMenu will gleefully treat them as the same configuration.
DBE_PROPERTY
when they subscribe to an enum PV will be notified
when the enum strings change.)
save_restoreSet_CAReconnect(1)
create_manual_set("SGMenu.req","P=xxx:,CONFIG=SG,CONFIGMENU=1,H=softGlue:")
error reading dir <mydirectoryname> errno: 0x300016One solution is to modify the board-support package to use nfs2Drv.
ca_get(DBR_STRING,...)
.
Most data types are read using channel access and written using dbStaticLib
calls. Four data types get special attention: Channel access does not distinguish these types, so neither does autosave. Autosave cannot write enums as strings, because enum strings may not have been defined at the time they must be restored.
Here is a sample save file. Characters in blue are documentation comments, and are not part of the file:
# save/restore V4.9 Automatically generated - DO NOT MODIFY - 060720-154526 ! 1 channel(s) not connected - or not all gets were successful xxx:SR_ao.DISP 0 (uchar) xxx:SR_ao.PREC 1 (short) xxx:SR_bo.IVOV 2 (ushort) xxx:SR_ao.SCAN 3 (enum - saved/restored as a short) xxx:SR_ao.VAL 4.1234567890123 (double, printed with format "%.14g") xxx:SR_scaler.RATE 1.234568 (float, printed with format "%.7g") xxx:SR_ao.DESC description (string) xxx:myCalc.CALC$ 123456789+123456789+123456789+123456789+123456789 (long string) xxx:SR_ao.OUT xxx:SR_bo.VAL NPP NMS (link) xxx:SR_ao.RVAL 4 (long) xxx:SR_bi.SVAL 2 (ulong) #i_dont_exist.VAL Search Issued (no such PV) xxx:SR_char_array @array@ { "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" } xxx:SR_double_array @array@ { "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" } xxx:SR_float_array @array@ { "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" } xxx:SR_long_array @array@ { "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" } xxx:SR_short_array @array@ { "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" } xxx:SR_string_array @array@ { "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" } xxx:SR_uchar_array @array@ { "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" } xxx:SR_ulong_array @array@ { "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" } xxx:SR_ushort_array @array@ { "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" } <END>Save files are not intended to be edited manually. If you, nevertheless, do edit a save file, you must end it with the text
<END>followed by one or two arbitrary characters (normally '\n' or '\r\n'). If the file does not end with this text, reboot_restore() will assume the crate crashed while the file was being written, or that some other bad thing happened, and will not use the file. Once a save file has been created successfully, save_restore will not overwrite the file unless a good ".savB" backup file exists. Similarly, it will not overwrite the ".savB" file unless the save file was successfully written.
You can comment out lines in a .sav file by beginning them with '#'.
int asVerify(char *fileName, int verbose, char *restoreFileName)
filename
(which should
be an autosave restore file, or at least look like one). If restoreFileName is not empty,
write a new restore file.
This function can be called at any time after iocInit.
int create_manual_set(char *request_file, char *macrostring)
manual_save()
is called with the same request-file
name.
See "Start the save task", above for information about the macro string.
This function can be called at any time after iocInit.
int create_monitor_set(char *request_file, int period, char *macrostring)
period
seconds, if any PV in the save set was posted (changed
value) since the last write.
See "Start the save task", above for information about the macro string.
This function can be called at any time after iocInit.
int create_periodic_set(char *request_file, int period, char *macrostring)
period
seconds.
See "Start the save task", above for information about the macro string.
This function can be called at any time after iocInit.
int create_triggered_set(char *request_file, char *trigger_channel,
char *macrostring)
trigger_channel
is posted. Normally
this occurs when the PV's value changes.
See "Start the save task", above for information about the macro string.
This function can be called at any time after iocInit.
int fdbrestore(char *save_file)
save_file
refers to a save set that exists in memory, then PV's
in the save set will be restored from values in memory. Otherwise, this
functions restores the PV's in <saveRestorePath>/<save_file> and creates
a new backup file "<saveRestorePath>/<save_file>.bu". The effect
probably will not be the same as a boot-time restore, because caput()
calls are used instead of static database access dbPutX() calls.
Record processing will result from caput()'s to inherently process-
passive fields.
This function can be called at any time after one of the create_*_set() functions have been called. If you want to call this function before creating any save sets, you can call create_*_set() with an empty request-file name. Autosave will complain about this, but it won't think you're a bad person.
int fdbrestoreX(char *save_file)
<END>
. No backup file will be written. The effect
probably will not be the same as a boot-time restore, because caput() calls are used instead of
static database access dbPut*() calls. Record processing will result from caput()'s to
inherently process-passive fields. This function can be called at any time after one of the create_*_set() functions have been called. If you want to call this function before creating any save sets, you can call create_*_set() with an empty request-file name. Autosave will not hate you for doing this, though it will complain.
int fdbrestoreX(char *filename, char *macrostring, callbackFunc callbackFunction, void *puser)
macrostring
is not NULL, the macro definitions it contains will be applied to
the contents of filename
. If callbackFunction
is not NULL, it
specifies a function of type void f(int status, void *puser)
that will be called
when the save operation is done.
char *getMacroString(char *request_file)
create_*_set()
was ever called for request_file
, then the
macro-substitution string supplied in that call was recorded by autosave, and can be recovered
with this function. This is part of the implementation of configMenu, and it allows .cfg
files to include macros.
void makeAutosaveFiles(void)
An info node, in an EPICS database, is similar to a field specification, but it has the word
info
instead of field
; and it has an arbitrary name, instead of the
name of a field in the record. Here's an EPICS database containing a single record with two
info nodes:
record(ao, "$(P)test1") { field(DTYP, "Soft Channel") info(autosaveFields, "PREC EGU DESC") info(autosaveFields_pass0, "VAL") }
From this information, makeAutosaveFiles()
will write the
following two files:
info_settings.req $(P)test1.PREC $(P)test1.EGU $(P)test1.DESC info_positions.req $(P)test1.VAL
This function can be called at any time after iocInit().
See also:
makeAutosaveFileFromDbInfo()
.
void makeAutosaveFileFromDbInfo(char *fileBaseName, char *info_name)
info_name
; construct a list of PV
names from the associated info_values found, and write the PV names to the
file fileBaseName
. If fileBaseName
does not
contain the string '.req', this string will be appended to it. See
makeAutosaveFiles()
for more information.
This function can be called at any time after iocInit().
int manual_save(char *request_file)
int manual_save(char *request_file, char *save_file, callbackFunc callbackFunction,
void *puser);
save_file
is not NULL and not empty, it specifies the name of the file that will
be written. If callbackFunction
is not NULL, it specifies a function of type
void f(int status, void *puser)
that will be called when the save operation is
done.
int reboot_restore(char *save_file, initHookState init_state)
int reload_manual_set(char * request_file, char *macrostring)
create_manual_set()
.
Note: Don't get too ambitious with the remove/reload functions. You have to wait for one to finish completely (the save_restore task must get through its service loop) before executing another. If you call one before the previous function is completely finished, I don't know what will happen.
int reload_monitor_set(char * request_file, int period, char *macrostring)
create_monitor_set()
.
int reload_periodic_set(char *request_file, int period, char *macrostring)
create_periodic_set()
.
int reload_triggered_set(char *request_file, char *trigger_channel,
char *macrostring)
create_triggered_set()
.
int remove_data_set(char *request_file)
request_file
, this function will
delete it.
void save_restoreSet_DatedBackupFiles(int ok)
(int) save_restoreDatedBackupFiles
(initially 1).
If zero, the backup file written at reboot time (a copy of the file
from which PV values are restored) will have the suffix '.bu',
and will be overwritten every reboot. If nonzero, each reboot will
leave behind its own backup file.
This function can be called at any time.
void save_restoreSet_Debug(int debug_level)
(int) save_restoreDebug
(initially 0). Increase to
get more informational messages printed to the console.
This function can be called at any time.
void save_restoreSet_FilePermissions(int permissions)
This function can be called at any time after iocInit.
void save_restoreSet_IncompleteSetsOk(int ok)
(int) save_restoreIncompleteSetsOk
(initially 1).
If set to zero, save files will not be restored at boot time unless
they are perfect, and they will not be overwritten at save time
unless a valid CA connection and value exists for every PV in the
list.
This function can be called at any time.
void save_restoreSet_NFSHost(char *hostname, char *address)
set_savefile_path()
has been called to specify
the file path, save_restore will manage its own NFS mount. This allows
save_restore to recover from a reboot of the NFS host (that is, a stale file
handle) and from some kinds of tampering with the save_restore directory.
void save_restoreSet_NumSeqFiles(int numSeqFiles)
(int) save_restoreNumSeqFiles
(initially 3).
This is the number of sequenced backup files to be maintained.
numSeqFiles
must be between 0 and 10 inclusive.
This function can be called at any time.
void save_restoreSet_RetrySeconds(int seconds)
(int) save_restoreRetrySeconds
(initially 60; minimum 10).
If the .sav-file write fails, it will be retried after this interval..
This function can be called at any time.
void save_restoreSet_SeqPeriodInSeconds(int period)
(int) save_restoreSeqPeriodInSeconds
(initially 60).
Sequenced backup files will be written with this period.
period
must be 10 or greater.
This function can be called at any time.
void save_restoreSet_status_prefix(char *prefix)
This function must be called before the first call to create_xxx_set()
.
void save_restoreSet_UseStatusPVs(int ok)
This function should be called before the first call to create_xxx_set()
.
void save_restoreShow(int verbose)
This function can be called at any time after iocInit.
int set_requestfile_path(char *path, char *pathsub)
pathsub
, if present, will be appended
to path
, if present, with a separating '/', whether or not path
ends
or pathsub
begins with '/'. If the result does not end in '/', one will
be appended to it.
You can specify several directories to be searched for request files by
calling this routine several times. Directories will be searched in the
order in which the set_requestfile_path()
calls were made. If you never
call the routine, the crate's current working directory will be searched.
If you ever call it, the current directory ("./") will be searched only if
you've asked for it explicitly.
int set_pass0_restoreFile(char *save_file)
set_savefile_path()
.
int set_pass1_restoreFile(char *save_file)
set_savefile_path()
.
int set_savefile_name(char *request_file, char *save_file)
int set_savefile_path(char *path, char *pathsub)
pathsub
, if present, will be
appended to path
, if present, with a separating '/', whether or not path
ends or pathsub
begins with '/'. If the result does not end in '/', one
will be appended to it.
If save_restore is managing its own NFS mount, this function specifies the mount point, and calling it will result in an NFS mount if all other requirements have already been met. If a valid NFS mount already exists, the file system will be dismounted and then mounted with the new path name. This function can be called at any time.
int set_saveTask_priority(int priority)
. . . dbLoadDatabase("$(TOP)/dbd/iocxxxVX.dbd") iocxxxVX_registerRecordDeviceDriver(pdbbase) . . . ### autoSaveRestore setup save_restoreSet_Debug(0) # status-PV prefix, so save_restore can find its status PV's. save_restoreSet_status_prefix("xxx:") # ok to restore a save set that had missing values (no CA connection to PV)? # ok to save a file if some CA connections are bad? save_restoreSet_IncompleteSetsOk(1) # In the restore operation, a copy of the save file will be written. The # file name can look like "auto_settings.sav.bu", and be overwritten every # reboot, or it can look like "auto_settings.sav_020306-083522" (this is what # is meant by a dated backup file) and every reboot will write a new copy. save_restoreSet_DatedBackupFiles(1) # specify where save files should go set_savefile_path(startup, "autosave"); ## specify where request files can be found # current directory set_requestfile_path(startup, "") # We want to include request files that are stored with the databases they # support — e.g., in stdApp/Db, mcaApp/Db, etc. The variables std and mca # are defined in cdCommands. The path is searched in the order in which # directories are specified. set_requestfile_path(startup) set_requestfile_path(std, "stdApp/Db") set_requestfile_path(motor, "motorApp/Db") set_requestfile_path(mca, "mcaApp/Db") set_requestfile_path(ip, "ipApp/Db") set_requestfile_path(ip330, "ip330App/Db") # [...] # Specify what save files should be restored when. # Up to eight files can be specified for each pass. set_pass0_restoreFile("auto_positions.sav") set_pass0_restoreFile("auto_settings.sav") set_pass1_restoreFile("auto_settings.sav") set_pass0_restoreFile("info_positions.sav") set_pass0_restoreFile("info_settings.sav") set_pass1_restoreFile("info_settings.sav") # [...] # Number of sequenced backup files (e.g., 'auto_settings.sav0') to write save_restoreSet_NumSeqFiles(3) # Time interval between sequenced backups save_restoreSet_SeqPeriodInSeconds(600) # Time between failed .sav-file write and the retry. save_restoreSet_RetrySeconds(60) # Ok to retry connecting to PVs whose initial connection attempt failed? save_restoreSet_CAReconnect(1) # Time interval in seconds between forced save-file writes. (-1 means forever). # This is intended to get save files written even if the normal trigger mechanism is broken. save_restoreSet_CallbackTimeout(-1) # NFS host name and IP address save_restoreSet_NFSHost("oxygen", "164.54.52.4") dbLoadRecords("$(AUTOSAVE)/asApp/Db/save_restoreStatus.db", "P=xxx:") . . . iocInit . . . ### Start up the save_restore task and tell it what to do. # The task is actually named "save_restore". # # save positions every five seconds create_monitor_set("auto_positions.req", 5, "P=xxx:") # save other things every thirty seconds create_monitor_set("auto_settings.req", 30, "P=xxx:") # Handle autosave 'commands' contained in loaded databases. makeAutosaveFiles() create_monitor_set("info_positions.req", 5, "P=xxx:") create_monitor_set("info_settings.req", 30, "P=xxx:") . . .---------- end excerpt from st.cmd ----------------------