autosave Release Notes

5.6.1

asVerify can now be called from the IOC console

5.6

Manual restore of array PV now uses channel access, rather than database
access, so it behaves like manual restore of a scalar. (Previously, when
configMenu restored an array to a VAL field, the field value didn't get posted,
because database access doesn't cause record processing.)

5.5.1

myDbLoadRecordsHook() now calls macEnvExpand() for the filename

Defend against long lines in readReqFile: don't truncate string in the
middle of a macro definition.

5.5

In versions R5-4-*, array restore could fail to parse lines longer than 120
characters. This is fixed.

New functions, eraseFile() and appendToFile(), intended to work with
autosaveBuild().

5.4.2

set_pass1_restoreFile(), called from iocsh had wrong second argument.

5.4.1

Previously, restoring an array which had been saved with zero or one values
failed. Also, manual restore (including restore by configMenu) of any array PV
caused a seg fault.

Previously, manual restore (including restore by configMenu) of a long string
PV neglected to restore the trailing null character.

5.4

Can now do boot-time restore from a read-only .sav file located anywhere,
and can do macro substitution on the file contents. This is intended to support
a generic, default configuration for highly mobile iocs, such as those
supporting areaDetector.

Fixed bug in boot-time treatment of long-string values that are longer than
120 chars.

5.3.1

configMenu: In building the list of .cfg files from the autosave directory,
now require that .cfg file names begin with the config name followed by an
underscore, and end with ".cfg". Previously, they were only required to begin
with the config name (so config names SG and SG2 got mixed) and contain .cfg
without also containing .cfg_.

5.3

Beginning with R5.0, autosave failed to detect and reject a truncated .sav
file, and would segfault if the file was truncated in the middle of an array.
Thanks to Jon Thompson (Diamond) for reporting the problem.

In 5.1 through 5.2, "asVerify -r" was failing to write reboot files.

5.2

In autosave 5.1 and 5.1.1, asVerify did not print anything if all PVs
had the same values as in the supplied .sav file. Now asVerify goes back to
the original behavior, printing, for example, "0 PVs differed. (8 PVs checked;
0 PVs not connected)".

In autosave 5.1 and 5.1.1, the presence of the macro "CONFIG" anywhere in a
request file, or in a create_xxx_set() command, told autosave to refrain from
writing backup (".savB") and sequence (".savN") files. This didn't work very
well, because you generally want to include configMenu_settings.req in
auto_settings.req, and that requires the CONFIG macro. Now, autosave will
refrain from backups and sequence files if the macro CONFIGMENU is defined
with any value.

5.1.1

Declare pass0List and pass1List extern in save_restore.h

5.1

In autosave versions 4-8 through 5-0, if the save_restore task connected
to a remote PV that later was disconnected, it would crash the next time
that PV was used.

Modified autosave to correctly restore unsigned long values. Thanks to
Kukhee Kim (SSRL) for find and fixing the bug.

configMenu: new support for manually saving, restoring, and verifying
sets of PVs. configMenu operations can be driven by an EPICS record, or
by any channel-access client. configMenu list can be populated from the
existing config files on disk.

Modified parsing of "file" commands in request files. It's now ok to
include the '#' character in a macro definition. Consequently, it's
no longer legal to have a comment on the same line as a file command.

use 24-hour time-format string

5.0

Modified autosave and asVerify to handle long strings (PVs of type
DBF_STRING whose declared size is larger than the number of characters
channel access will transport as a DBF_STRING). Currently, only the first
120 characters of long strings are saved and restored. Request files must
specify the PV name with a trailing '$' to have a PV treated as a long
string; otherwise, only the first 39 characters of the string will be
saved/restored.

Fixed handling of arrays of DBF_LONG, DBF_ULONG for 64-bit architectures.

Rewrote fGetDateStr using epicsTimeToStrftime.

Modified autosave to build and run with either EPICS 3.15.0 or 3.14.

4.8

Folded in modifications by Zheqiao Geng (SLAC):

Introduced NFS remount function for RTEMS in case of too many file-write failures

Don't require successful dismount as prerequisite for mount. Most likely case
is that dismount will succeed on first try, remount will fail, and then dismount
will fail from then on because the file system has already been dismounted.

If array data is found in a .sav file, parse to end whether or not the array will
be restored.

Added .opi display files for CSS-BOY.

Fixed wrong seek distance on WIN32.

Compile-time option for Linux to manage or not manage NFS mount.

Make makeAutosaveFiles() callable from the vxWorks shell. (Previously, it was
callable only from iocsh.)

4.7

Previously, array-valued PV's whose representation in a .sav file was
exactly 119 bytes long would cause reboot_restore to process the PV
twice, the second time as a scalar with no restore data. In the case of
an array of char, this resulted in the first element of the array being
overwritten with a zero.

4.6

Previously, autosave determined the element count of a PV in
connect_list(), never revisited it, and ignored PV's whose element
counts had not been determined. This prevented autosave from saving
PV's that failed to connect promptly.

Don't search for info nodes if a record is an alias.

4.5

Previously, autosave restored auto_positions.sav and auto_settings.sav
if no save file had been specified in a call to set_passn_restoreFile().
Now, autosave does not restore anything you don't tell it to restore.

Can now build with tornado 2.2.2.

save_restore.c:write_it() was calling open(), fdopen(), fclose(), and
close(), in that order, and this worked routinely. However, some doc suggests
close() should not be called, and we found a task suspended in the close() call,
so the call has been deleted.

4.4

If file close fails, retry once. (Previously, would retry up to 100 times.)

If file write (including close) fails, retry after save_restoreRetrySeconds
(default value is 60 seconds). Previously, would retry only after the file
system was remounted, or the next time the set was triggered.

4.3

New function, save_restoreSet_FilePermissions(), allows control
over permissions with which .sav files are created.

create_xxx_set() can now specify PV names from which file
path and file name are to be read, by including SAVENAMEPV
and/or SAVEPATHPV in the macro string supplied as an argument.
Note this can be done only on the first call to create_xxx_set()
for a save set, because only the first call results in a call to
readReqFile(), in which function the macro string is parsed. If either
macro is specified, save_restore will not maintain backup or sequence
files for the save set.

Don't print errno unless function returns an error.

New functions makeAutosaveFiles(), and
makeAutosaveFileFromDbInfo(), search the database for info nodes
indicating fields to be autosaved.

4.2.1

Added date/time to error messages printed to the console.

If asVerify is directed to create a restore file, it now writes a trial
restore file first, and overwrites the real restore file only if more than half
of the PV's were actually connected.

myPrintErrno modified to print the line and file of caller, and called only
if there was an actual error.

Don't hold epicsMutex for a long time, because any priority inheritance
that occurs while the mutex is held will persist until the mutex is released,
even if it's no longer needed. Now, the mutex is used to protect a variable
which, in turn, protects save_restore's save-set list.

Use binary mode for fopen() calls in myFileCopy() (dbrestore.c) to avoid
file-size differences resulting from different line terminators on different
operating systems. (Thanks to Kay Kasemir for this fix.)

EPICS 3.14.9 will no longer allow empty calc (special==SPC_CALC) strings,
so dbrestore now detects such strings in the .sav file and changes them to "0"
before restoring.

4.2

Added asVerify, a client-side tool to compare autosave .sav files
with current PV values. Also can write a .sav file useable for restoring
values.

4.1.3

Debug macros made more compliant with various compilers.

save_restore made less sensitive to errors. Previously, any file
write that set errno would abort the save, but this was just stupid,
and caused way more problems than it solved.

4.1.2

Request-file parsing fixed. Previously, blank but not empty lines (e.g.,
containing a space character) seemed to contain the first word of the previous
line, because name[] was not cleared before parsing a new line.

Dirk Zimoch (SLS) found and fixed problems with .sav files that lack a
header line, or a version number. Check return code from selected fseek()
calls.

4.1.1

Cleaned up asApp/src/Makefile so it did not put as_registerRecordDeviceDriver
in all applications using autosave.

v4.1

Allow user to comment out a line from a .sav file by beginning the
line with '#'

PV_NAME_LEN increased from 40 to 80

Check that chid is not NULL before calling ca_state()

The test for valid .sav files now permits files to end either with
"<END>?" or "<END>??", where
"?" is any character. This allows dos files, which end with
"\r\n", to be restored.

Use epicsTime() instead of time(). Defend against partial-init failures

Array support now understands max and curr number of elements, and is
prepared to see the current number of elements change.

v4.0

Status PV's have been reworked. Now you don't have to modify either the
database or the medm-display file to use your own save-set names.

v3.5

Sometime in the past, I made fdbrestore() and fdbrestoreX() unavailable to
console users by making them macros. This is fixed.

Beginning with version 3.5, arrays can be saved and restored much as scalar
PV's. Arrays are read and written using run-time database access, which
implies that they can only be written during pass 1 of the restore, and that
you cannot save the value of a non-local array PV. (Scalar PV's are read using
channel access and normally are written using static database access.)

Beginning with v3.5, scalar PV's which have type DBF_NOACCESS in the .dbd
file, and are set to some other DBF type during record initialization, can be
restored in pass 1. (Some fields of the genSub record behave in this way, and
previous versions of save_restore could not restore them.)

Prior to v3.5, PV's were listed 'backwards' in the save file -- i.e., the
first PV in the request file became the last PV in the save file. Now, both
files have the same ordering.

save_restore v3.3; dbrestore v3.3

In versions earlier than 3.3, save_restore's job was simply to save parameters
through a reboot. The file server to which save files were written was assumed
competent to protect those files, and when the server said a .sav file was
safe, save_restore believed it. Beginning with 3.3, the file server is viewed
as the enemy: save_restore expects it to lie about file status, to suddenly
stop recognizing previously valid file handles, and to return error codes that
don't make sense. Save_restore can now defend its NFS mount against a server
reboot, defend parameter values against a server power failure, and attempts to
defend against a user messing around with the directory into which save files
are being written.

Save_restore now allows you to change, at run time, the directory and/or the
server to which save files are written. Here's an example:

# The normal save_restore directory setup, in st.cmd:
save_restoreSet_NFSHost("oxygen", "164.54.52.4")
set_savefile_path(startup, "autosave")
...
iocBoot()
...
(end of st.cmd)
...
# Type the following into the ioc's console
save_restoreSet_NFSHost("wheaties", "164.54.53.101")
# You'll get an immediate error if the old save file path doesn't
# exist, or has adverse permissions, on the new server.
set_savefile_path("/local/autosave", "")
# save_restore will immediately attempt to mount the new file path

The above code assumes the ioc has permission to mount file systems on the host
('wheaties', in this case) and that the ioc has read/write/execute permission
to the directory in which it is supposed to write .sav files (in this case,
'/local/autosave'). Neither of these conditions are likely to be met by
default; you must take action to arrange them.

Several variables and user-callable functions have been renamed, as their
meanings have changed. In preparation for 3.14, most user-settable variables
can now be set by a function call. Here's a list of variables and functions
added, deleted, or changed:

OLD

NEW

sr_save_incomplete_sets_ok

save_restoreIncompleteSetsOk

sr_restore_incomplete_sets_ok

save_restoreIncompleteSetsOk

--no comparable function--

save_restoreSet_IncompleteSetsOk(value)

reboot_restoreDebug

save_restoreDebug

--no comparable function--

save_restoreSet_Debug(value)

reboot_restoreDatedBu

save_restoreDatedBackupFiles

--no comparable function--

save_restoreSet_DatedBackupFiles(value)

--no comparable variable--

save_restoreNumSeqFiles

--no comparable function--

save_restoreSet_NumSeqFiles(value)

--no comparable variable--

save_restoreSeqPeriodInSeconds

--no comparable function--

save_restoreSet_SeqPeriodInSeconds(value)

NOTE: if save_restoreNumSeqFiles > 0, redundant .sav file
will be written every save_restoreSeqPeriodInSeconds seconds

--no comparable function--

dbrestoreShow()

fdblist()

save_restoreShow(verbose)

NOTE: save_restoreShow() calls dbrestoreShow()

save_restore_test_fopen

--no comparable variable--

NOTE: test is no longer done

create_periodic_set(file,period)

create_periodic_set(file,period,macro)

create_triggered_set(file,trigPV)

create_triggered_set(file,trigPV,macro)

create_monitor_set(file,period)

create_monitor_set(file,period,macro)

create_manual_set(file)

create_manual_set(file,macro)

reload_periodic_set(file,period)

reload_periodic_set(file,period,macro)

reload_triggered_set(file,trigPV)

reload_triggered_set(file,trigPV,macro)

reload_monitor_set(file,period)

reload_monitor_set(file,period,macro)

reload_manual_set(file)

reload_manual_set(file,macro)

NOTE: macro string is optional and supplements any macro
strings defined in request files. You can only reload one set at a time;
you must wait for a reload to complete before starting another one.

NOTE: IN VERSIONS EARLIER THAN 2.7, Time PERIODS WERE SPECIFIED USING
FLOATING POINT NUMBERS. THEY ARE NOW SPECIFIED AS INTEGERS (IN SECONDS).

set_savefile_path(path)

set_savefile_path(path,pathsub)

set_requestfile_path(path) -> set_requestfile_path(path,pathsub)

NOTE: if pathsub is specified, it is appended to path. The purpose of
this change was to make it easier to use variabled defined in cdCommands
as path elements. Example: set_requestfile_path(std,"stdApp/Db")

--no comparable function--

save_restoreSet_status_prefix(value)

NOTE: save_restore expects PV's with which it can display its status.
Status PV's are request-file specific; the supplied database contains
PV's for auto_positions.req and auto_settings.req only. If you use
other request files, you can add your own PV's. It's OK if the PV's
don't exist, but you will get informational messages when their absence
is noticed.

--no comparable function--

save_restoreSet_NFSHost(host,IPaddress)

--no comparable variable--

save_restoreRemountThreshold

NOTE: If save_restore is managing its own NFS mount (i.e., if calls to
save_restoreSet_NFSHost() and set_savefile_path() succeeded) it will
dismount and remount after save_restoreRemountThreshold consecutive
I/O errors (e.g. to fix a stale file handle).

Save_restore now maintains status PV's for each PV list, and rolled-up status
PV's for overall save status and reboot status.

fdblist() renamed as save_restoreShow(), now enhanced with more status
information, including rolled-up reboot status.

Save_restore can now maintain up to ten "sequence files" (named *.savX, where X
is a digit in [0..(save_restoreNumSeqFiles-1)]), which are copies of the most
recent .sav or .savB file, copied at user-specified intervals. If no valid
.sav or .savB file exists, save_restore will write sequence files directly from
its PV list, as though it were writing a .sav file. At boot time, if .sav and
.savB are both corrupt or missing, save_restore will restore from the most
recent sequence file.

Save_restore no longer tests fopen() by writing a temporary file, before saving.

Save_restore will manage its own NFS mount, if the host name and address has
been specified with a call to save_restoreSet_NFSHost(), and the save-file path
(used as the mount point) has been set by a call to set_savefile_path(). When
more than 'save_restoreRemountThreshold' consecutive, unexpected I/O errors
(the default number is ten) have occurred, save_restore will attempt to remount
the file system.

Previously, save_restore saved floats and doubles using an algorithm that was
prone to failure, especially for PV's from another ioc. (Thanks to Mark Rivers
for finding and fixing this bug.)

Now use errlogPrintf() for all messages except those from callback routines,
where logMsg() is used.

All CA monitors are now set up by the save_restore task. Previously, some were
setup by whatever task called create_XXX_set().

Previously, if a save-file write failed, it would not be retried until the
normal conditions (e.g., a PV's value changed) were again met. Now, if
save_restore is managing its own NFS mount, and enough I/O errors have
accumulated to cause an NFS remount, all save sets in failure are written
immediately after the remount succeeds.

Some ca_pend timeouts adjusted or limited. Previous timeouts were
inappropriate if many thousands of PV's were specified in a request file.

Save files now contain the time at which they were written, in the format of
fGetDateStr() -- yymmdd-hhmmss.

Dated backup files now have an underscore between the name and the date.

Previously, if the second fopen() call in myFileCopy() failed, the function
would return without closing the first file.

Previously, save_restore would overwrite corrupted files in the normal course
of operation. Now, whenever a corrupted file is encountered, a copy is made.
If the copy is made at restore time, the copy is named, e.g.,
auto_settings.sav_RBAD_030818-134850; if at save time, it's named, e.g.,
auto_settings.sav_SBAD_030818-134850.

save_restore no longer uses the vxWorks 'copy' command for anything, because it
writes files with inconvenient permissions.

save_restore v2.9a; dbrestore v2.7

Previously, create_data_set() would return without releasing a semaphore
(causing the save_restore task to hang) if called with save_method==TRIGGERED,
but no trigger channel was specified.

Previously, fdbrestore() would return without releasing a semaphore (causing
the save_restore task to hang) if called with the name of a save set currently
being maintained, and the save list contained unconnected PV's, and the
variable 'sr_restore_incomplete_sets_ok' was false.

Added macro-string argument to create_xxx_set()

Added argument 'verbose' to fdblist()

Added second argument, 'subpath', to set_XXXfile_path(). This allows the caller
to pass the path as two args to be concatenated, making it easier to build the
path string using a variable set in the cdCommands file.

Use logMsg() instead of epicsPrintf() for several informational messages.

Changed call to macParseDefns() to specify the macro-substitution handle.

save_restore v2.7; dbrestore v2.7

ATTENTION

This version is incompatible in one important respect with versions of
save_restore.c numbered lower than 2.6: The functions

create_periodic_set()

create_monitor_set()

reload_periodic_set()

reload_monitor_set()

now take 'int' arguments to specify time periods, instead of 'double'
arguments. This change was required for compatibility with PPC
processors.

In Frank Lenkszus' version, the calls set_pass_restoreFile() were required
to specify files to be restored. In this version, if no restore files have
been specified, initHooks specifies the default files auto_positions.sav and
auto_settings.sav for you, for backward compatibility with my previous
version. If you really don't want to restore any files, you now must either
not load initHooks, or replace it with your own version.

In Frank Lenkszus' version, set_requestfile_path() could specify only a single
directory. Now that include files are a possibility, you can specify several
request-file directories by calling set_requestfile_path() several times.

Backup files made as part of a restore operation (i.e., files ending in ".bu",
or "YYMMDD-HHMMSS") are no longer created using the VxWorks "copy" command.