autosave v4.1.3

This software automatically saves the values of EPICS process variables (PVs), to files on a server, and can automatically restore those values when the VME crate is rebooted. The original author is Bob Dalesio; I made some improvements; Frank Lenkszus made some more improvements, which I folded into the version I've been maintaining. A bunch of people contributed to getting the software running on PPC hardware, including Ron Sluiter, Andrew Johnson, and Pete Jemian (APS), Markus Janousch and David Maden (SLS), and I'm not sure who else.

Module contents

save_restore.c
saves PV values in files on a file server according to preset rules.
dbrestore.c
restore PV values at boot time, using dbStaticLib
initHooks.c
call restore routines at the correct time during boot.
fGetDateStr.c
Frank Lenkszus' date-string routines
save_restore.h, fGetDateStr.h
headers
auto_settings.req, auto_positions.req
Sample request files
save_restoreStatus*.adl, save_restoreStatusLegend.adl, save_restoreStatus_more.adl, save_restoreStatus_tiny.adl, SR_X_Status.adl
MEDM displays of save_restore status.
save_restoreStatus.db
database containing records save_restore uses to report status.
SR_array_test.vdb
Test database for array save_restore.

How to use this software

This software can be used in many different ways. I'll describe what you have to do to use it as it's commonly used at APS beamlines to save PV values periodically, and restore them on reboot.

About save files

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. Also, you can comment out lines in a .sav file by beginning them with '#'.

User-callable functions

int manual_save(char *request_file)
If a manual save set for the request file request_file was created with create_manual_set(), this command will cause current PV values to be saved.

int set_savefile_name(char *request_file, char *save_file)
If a save set has already been created for the request file, this function will change the save file name.

int create_periodic_set(char *request_file, int period, char *macrostring)
Create a save set for the request file. The save file will be written every period seconds.

This function can be called at any time after iocInit.

int create_triggered_set(char *request_file, char *trigger_channel, char *macrostring)
Create a save set for the request file. The save file will be written whenever the PV specified by trigger_channel is posted. Normally this occurs when the PV's value changes.

This function can be called at any time after iocInit.

int create_monitor_set(char *request_file, int period, char *macrostring)
Create a save set for the request file. The save file will be written every period seconds, if any PV in the save set was posted (changed value) since the last write.

This function can be called at any time after iocInit.

int create_manual_set(char *request_file, char *macrostring)
Create a save set for the request file. The save file will be written when the function manual_save() is called with the same request-file name.

This function can be called at any time after iocInit.

int fdbrestore(char *save_file)
If 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 iocInit.

int fdbrestoreX(char *save_file)
This function restores from the file <saveRestorePath>/<save_file>, which can look just like a save file, but which needn't end in <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 dbPutX() calls. Record processing will result from caput()'s to inherently process-passive fields.

This function can be called at any time after iocInit.

void save_restoreShow(int verbose)
List all the save sets currently being managed by the save_restore task. If (verbose != 0), lists the PV's as well.

This function can be called at any time after iocInit.

int set_requestfile_path(char *path, char *pathsub)
Called before create_xxx_set(), this function specifies the path to be prepended to request-file names. 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_savefile_path(char *path, char *pathsub)
Called before iocInit(), this function specifies the path to be prepended to save-file and restore-file names. pathsub, if present, will be appended to path, if present, with a separating '/' whether or not 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)
Set the priority of the save_restore task.

int remove_data_set(char *request_file)
If a save set has been created for request_file, this function will delete it.

int reload_periodic_set(char *request_file, int period, char *macrostring)
This function allows you to change the PV's and the period associated with a save set created by create_periodic_set().

int reload_triggered_set(char *request_file, char *trigger_channel, char *macrostring)
This function allows you to change the PV's and the trigger channel associated with a save set created by create_triggered_set().

int reload_monitor_set(char * request_file, int period, char *macrostring)
This function allows you to change the PV's and the period associated with a save set created by create_monitor_set().

int reload_manual_set(char * request_file, char *macrostring)
This function allows you to change the PV's associated with a save set created by 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 reboot_restore(char *save_file, initHookState init_state)
This should only be called from initHooks because it can only function correctly if called at particular times during iocInit.

int set_pass0_restoreFile(char *save_file)
This function specifies a save file to be restored during iocInit, before record initialization. Up to eight files can be specified using calls to this function.

int set_pass1_restoreFile(char *save_file)
This function specifies a save file to be restored during iocInit, after record initialization. Up to eight files can be specified using calls to this function.

void save_restoreSet_Debug(int debug_level)
Sets the value (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_IncompleteSetsOk(int ok)
Sets the value of (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_NumSeqFiles(int numSeqFiles)
Sets the value of (int) save_restoreNumSeqFiles (initially 3). This is the number of sequenced backup files to be maintained.

This function can be called at any time.

void save_restoreSet_SeqPeriodInSeconds(int period)
Sets the value of (int) save_restoreSeqPeriodInSeconds (initially 60). Sequenced backup files will be written with this period.

This function can be called at any time.

void save_restoreSet_DatedBackupFiles(int ok)
Sets the value of (int) save_restoreDatedBackupFiles (initially 1). If zero, the backup file written at reboot time (a copy of the file from which parameter 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_status_prefix(char *prefix)
Specifies the prefix to be used to construct the names of PV's with which save_restore reports its status.

This function must be called before the first call to create_xxx_set().

void save_restoreSet_NFSHost(char *hostname, char *address)
Specifies the name and IP address of the NFS host. If both have been specified, and 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 (i.e., a stale file handle) and from some kinds of tampering with the save_restore directory.

Example of use

---------- begin excerpt from st.cmd ----------------------
### Load custom EPICS software [including save_restore and initHooks]
ld < xxxLib
.
.
.
### 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")
# [...]

# Number of sequenced backup files (e.g., 'auto_settings.sav0') to write
save_restoreSet_NumSeqFiles(3)

# Time interval between sequenced backups
save_restoreSet_SeqPeriodInSeconds(60)

# NFS host name and IP address
save_restoreSet_NFSHost("oxygen", "164.54.52.4")
.
.
dbLoadDatabase("../../dbd/xxxApp.dbd")
dbLoadRecords("xxxApp/Db/whatever.db"...

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:")
.
.
.
---------- end excerpt from st.cmd ----------------------
Suggestions and Comments to:
Tim Mooney : (mooney@aps.anl.gov)
Last modified: April 7, 2006