Open tim-speight opened 1 year ago
@tim-speight can you provide an example? I don't seem to see a problem when autosaving string PVs that are empty. For example this is the value in the auto_settings.sav file for the .DESC field of an ai record which has no value:
13IDC:A1init.DESC
This is what caget and cainfo show for that PV:
corvette:iocBoot/ioc13idc_linux/autosave>caget 13IDC:A1init.DESC
13IDC:A1init.DESC
corvette:iocBoot/ioc13idc_linux/autosave>cainfo 13IDC:A1init.DESC
13IDC:A1init.DESC
State: connected
Host: 164.54.160.146:5064
Access: read, write
Native data type: DBF_STRING
Request type: DBR_STRING
Element count: 1
This is what dbpr shows for that record in the IOC:
epics> dbpr 13IDC:A1init 2
ACKS: NO_ALARM ACKT: YES AMSG: ASG :
BKPT: 00 DESC: DISA: 0 DISP: 0
DISS: NO_ALARM DISV: 1 DLY0: 0 DLY1: 0.02
DLY2: 0.02 DLY3: 0.02 DLY4: 0.02 DLY5: 0.02
DLY6: 0.02 DLY7: 0.02 DLY8: 0.02 DLY9: 0.02
DLYA: 0 DLYB: 0 DLYC: 0 DLYD: 0
DLYE: 0 DLYF: 0 DO0 : 0 DO1 : 0
DO2 : 0 DO3 : 0 DO4 : 0 DO5 : 0
DO6 : 0 DO7 : 0 DO8 : 0 DO9 : 0
DOA : 0 DOB : 0 DOC : 0 DOD : 0
DOE : 0 DOF : 0 DOL0: CONSTANT
DOL1: DB_LINK 13IDC:A1invert_on.VAL NPP NMS
DOL2: DB_LINK 13IDC:A1blank_on.VAL NPP NMS
DOL3: DB_LINK 13IDC:A1sens_num.VAL NPP NMS
DOL4: DB_LINK 13IDC:A1gain_mode.VAL NPP NMS DOL5: CONSTANT
DOL6: CONSTANT DOL7: DB_LINK 13IDC:A1bias_on.VAL NPP NMS
DOL8: DB_LINK 13IDC:A1bias_tweak.VAL NPP NMS
DOL9: DB_LINK 13IDC:A1filter_type.VAL NPP NMS DOLA: CONSTANT
DOLB: CONSTANT DOLC: CONSTANT DOLD: CONSTANT DOLE: CONSTANT
DOLF: CONSTANT DTYP: EVNT:
FLNK: DB_LINK 13IDC:A1init1.PROC LCNT: 0 LNK0: CONSTANT
LNK1: DB_LINK 13IDC:A1invert_on.VAL PP MS
LNK2: DB_LINK 13IDC:A1blank_on.VAL PP MS
LNK3: DB_LINK 13IDC:A1sens_num.VAL PP MS
LNK4: DB_LINK 13IDC:A1gain_mode.VAL PP MS LNK5: CONSTANT
LNK6: CONSTANT LNK7: DB_LINK 13IDC:A1bias_on.VAL PP MS
LNK8: DB_LINK 13IDC:A1bias_tweak.VAL PP MS
LNK9: DB_LINK 13IDC:A1filter_type.VAL PP MS LNKA: CONSTANT
LNKB: CONSTANT LNKC: CONSTANT LNKD: CONSTANT LNKE: CONSTANT
LNKF: CONSTANT NAME: 13IDC:A1init NAMSG: NSEV: NO_ALARM
NSTA: NO_ALARM OFFS: 0 PACT: 0 PHAS: 0
PINI: NO PREC: 0 PRIO: LOW PUTF: 0
RPRO: 0 SCAN: Passive SDIS: CONSTANT SELL: CONSTANT
SELM: All SELN: 1 SEVR: INVALID SHFT: -1
STAT: UDF TIME: <undefined> TPRO: 0 TSE : 0
TSEL: CONSTANT UDF : 1 UDFS: INVALID VAL : 0
What version of autosave are you using?
Hi Mark, I am using 5.10.2 and doing some config for EPICS MOTOR with the motorAcsMotion controllers. ile "$(TOP)/db/basic_asyn_motor_clf.db" { pattern {N, M, DTYP, PORT, ADDR, DESC, EGU, TWV, SMGR, DIR, VELO, VMAX, VBAS, ACCL, BDST, BVEL, BACC, HLSV, HVEL, JVEL, JAR, SREV, MRES, ERES, PREC, DHLM, DLLM, URIP, UEIP, STAGE_TYPE} {1, "MS-$(N)", "asynMotor", ACS1, 0, "axis$(N)", "°", 1, 0.02, Pos, 1, 20, .1, .2, 0, 1, .2, 0, 1, 10, 10, 200, 1, 1, 0, 0, 0, 1, 0, ""}
record(stringout, "$(P)$(M):STAGE_TYPE") { field(DESC, "Stage or Load type") field(VAL, "$(STAGE_TYPE=0)") }
When I forgot to get my substitution file prepared - it ended up with a null value in the system and at the point it tried to write my new additional m1:STAGE_TYPE field autosave came up with cannot write file at its dated and time 'sav file'...
FYI I'm writing additional values in like "Lin OLV" - for a linear stage with OpenLoop verfication. And Rot OL for plain old open loop rotational stage and Lin ACL - to deign it has an active closed loop for that linear stage. More of an engineers description as I find EPICS MOTOR record a bit lacking here...
Record describing the loop status
record(stringout, "$(P)$(M):STAGE_TYPE") { field(DESC, "Stage or Load type") field(VAL, "$(STAGE_TYPE=0)") } When I forgot to get my substitution file prepared - it ended up with a null value in the system and at the point it tried to write my new additional m1:STAGE_TYPE field autosave came up with cannot write file at its dated and time 'sav file'...
I am not sure I understand this. A zero-length string has a null character in the first byte, and zero-length strings are saved with autosave with no problem. I have not tested what happens when the macro is not present like your case, but it seems strange that would not work.
I will try to give a better worked example. All my Linux perms were fine the file actually wrote the vast majority of the record and when I took a look at the dated sav file it blew up on that last field I had recently added to my UAT system
Sent from Android- 07725 477807
From: Mark Rivers @.> Sent: Friday, July 7, 2023 6:09:59 PM To: epics-modules/autosave @.> Cc: Speight, Timothy (STFC,RAL,CLF) @.>; Mention @.> Subject: Re: [epics-modules/autosave] Autosave when saving a string without value causes fprintf ERRLEVEL (Issue #55)
record(stringout, "$(P)$(M):STAGE_TYPE") { field(DESC, "Stage or Load type") field(VAL, "$(STAGE_TYPE=0)") } When I forgot to get my substitution file prepared - it ended up with a null value in the system and at the point it tried to write my new additional m1:STAGE_TYPE field autosave came up with cannot write file at its dated and time 'sav file'...
I am not sure I understand this. A zero-length string has a null character in the first byte, and zero-length strings are saved with autosave with no problem. I have not tested what happens when the macro is not present like your case, but it seems strange that would not work.
— Reply to this email directly, view it on GitHubhttps://github.com/epics-modules/autosave/issues/55#issuecomment-1625703461, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AOQ5OMRPF73IC4CAI62B5K3XPA7GPANCNFSM6AAAAAA2BTAGOU. You are receiving this because you were mentioned.Message ID: @.***>
I just tried to reproduce the problem and I cannot.
Here is my startup script:
corvette:CARS/iocBoot/ioc13test>more st.cmd.string_test
< envPaths
dbLoadDatabase("../../dbd/CARSLinux.dbd")
CARSLinux_registerRecordDeviceDriver(pdbbase)
dbLoadRecords("string_test.db", "")
< ../save_restore_IOCSH.cmd
iocInit
create_monitor_set("auto_settings.req", 30)
Here is string_test.db:
corvette:CARS/iocBoot/ioc13test>more string_test.db
record(stringout, "string_test") {
field(DESC, "This is the description")
field(VAL, "$(STAGE_TYPE=0)")
}
This is the complete output when the IOC boots:
corvette:CARS/iocBoot/ioc13test>../../bin/linux-x86_64/CARSApp st.cmd.string_test
< envPaths
epicsEnvSet("IOC","ioc13test")
epicsEnvSet("TOP","/home/epics/support/CARS")
epicsEnvSet("SUPPORT","/corvette/home/epics/support")
epicsEnvSet("AREA_DETECTOR","/corvette/home/epics/support/areaDetector-3-12-1")
epicsEnvSet("ASYN","/corvette/home/epics/support/asyn-4-44-2")
epicsEnvSet("ADSUPPORT","/corvette/home/epics/support/areaDetector-3-12-1/ADSupport")
epicsEnvSet("ADCORE","/corvette/home/epics/support/areaDetector-3-12-1/ADCore")
epicsEnvSet("AUTOSAVE","/corvette/home/epics/support/autosave-5-10-2")
epicsEnvSet("BUSY","/corvette/home/epics/support/busy-1-7-3")
epicsEnvSet("CALC","/corvette/home/epics/support/calc-3-7-4")
epicsEnvSet("SNCSEQ","/corvette/home/epics/support/seq-2-2-9")
epicsEnvSet("SSCAN","/corvette/home/epics/support/sscan-2-11-5")
epicsEnvSet("DEVIOCSTATS","/corvette/home/epics/support/devIocStats-3-1-16")
epicsEnvSet("EPICS_BASE","/corvette/usr/local/epics/base-7.0.7")
epicsEnvSet("ADANDOR","/corvette/home/epics/support/areaDetector-3-12-1/ADAndor")
epicsEnvSet("ADROPER","/corvette/home/epics/support/areaDetector-3-12-1/ADRoper")
epicsEnvSet("ADLIGHTFIELD","/corvette/home/epics/support/areaDetector-3-12-1/ADLightField")
epicsEnvSet("ADMAR345","/corvette/home/epics/support/areaDetector-3-12-1/ADmar345")
epicsEnvSet("ADMARCCD","/corvette/home/epics/support/areaDetector-3-12-1/ADmarCCD")
epicsEnvSet("ADPERKINELMER","/corvette/home/epics/support/areaDetector-3-12-1/ADPerkinElmer")
epicsEnvSet("ADPILATUS","/corvette/home/epics/support/areaDetector-3-12-1/ADPilatus")
epicsEnvSet("ADPROSILICA","/corvette/home/epics/support/areaDetector-3-12-1/ADProsilica")
epicsEnvSet("ADPOINTGREY","/corvette/home/epics/support/areaDetector-3-12-1/ADPointGrey")
epicsEnvSet("ADEIGER","/corvette/home/epics/support/areaDetector-3-12-1/ADEiger")
epicsEnvSet("ADGENICAM","/corvette/home/epics/support/areaDetector-3-12-1/ADGenICam")
epicsEnvSet("ADSPINNAKER","/corvette/home/epics/support/areaDetector-3-12-1/ADSpinnaker")
epicsEnvSet("ADARAVIS","/corvette/home/epics/support/areaDetector-3-12-1/ADAravis")
epicsEnvSet("ADVIMBA","/corvette/home/epics/support/areaDetector-3-12-1/ADVimba")
epicsEnvSet("CARS","/corvette/home/epics/support/CARS")
epicsEnvSet("CRYOCONM32","/corvette/home/epics/support/CryoconM32")
epicsEnvSet("DAC128V","/corvette/home/epics/support/dac128V-2-10-1")
epicsEnvSet("DANTE","/corvette/home/epics/support/dante-1-1")
epicsEnvSet("DELAYGEN","/corvette/home/epics/support/delaygen-1-2-3")
epicsEnvSet("DXP","/corvette/home/epics/support/dxp-6-0")
epicsEnvSet("GALIL","/corvette/home/epics/support/Galil/3-6")
epicsEnvSet("IP","/corvette/home/epics/support/ip-2-21-1")
epicsEnvSet("IPAC","/corvette/home/epics/support/ipac-2-16")
epicsEnvSet("IP330","/corvette/home/epics/support/ip330-2-10")
epicsEnvSet("IPUNIDIG","/corvette/home/epics/support/ipUnidig-2-12")
epicsEnvSet("MCA","/corvette/home/epics/support/mca-7-9")
epicsEnvSet("MEASCOMP","/corvette/home/epics/support/measComp-4-1")
epicsEnvSet("MODBUS","/corvette/home/epics/support/modbus-3-2")
epicsEnvSet("MOTOR","/corvette/home/epics/support/motor-7-3")
epicsEnvSet("OPTICS","/corvette/home/epics/support/optics-2-13-5")
epicsEnvSet("PMAC","/corvette/home/epics/support/pmac-2-5-13")
epicsEnvSet("QUADEM","/corvette/home/epics/support/quadEM-9-4")
epicsEnvSet("SCALER","/corvette/home/epics/support/scaler-4-0")
epicsEnvSet("SOFTGLUE","/corvette/home/epics/support/softGlue-2-8-3")
epicsEnvSet("STD","/corvette/home/epics/support/std-3-6-3")
epicsEnvSet("STREAM","/corvette/home/epics/support/stream-2-8-24")
epicsEnvSet("SYMETRIE","/corvette/home/epics/support/motorSymetrie-1-0")
epicsEnvSet("SYRINGEPUMP","/corvette/home/epics/support/SyringePump-0-1")
epicsEnvSet("TOMOSCAN","/corvette/home/epics/support/tomoscan")
epicsEnvSet("VAC","/corvette/home/epics/support/vac-1-9-1")
epicsEnvSet("VME","/corvette/home/epics/support/vme-2-9-4")
dbLoadDatabase("../../dbd/CARSLinux.dbd")
CARSLinux_registerRecordDeviceDriver(pdbbase)
dbLoadRecords("string_test.db", "")
< ../save_restore_IOCSH.cmd
### save_restore setup
#
# The rest this file does not require modification for standard use, but...
# If you want save_restore to manage its own NFS mount, specify the name and
# IP address of the file server to which save files should be written.
# This currently is supported only on vxWorks.
#save_restoreSet_NFSHost("oxygen", "164.54.52.4")
# status-PV prefix
#save_restoreSet_status_prefix("xxx:")
# Debug-output level
save_restoreSet_Debug(0)
# Ok to save/restore save sets with missing values (no CA connection to PV)?
save_restoreSet_IncompleteSetsOk(1)
# Save dated backup files?
save_restoreSet_DatedBackupFiles(1)
# Number of sequenced backup files to write
save_restoreSet_NumSeqFiles(3)
# Time interval between sequenced backups
save_restoreSet_SeqPeriodInSeconds(300)
# specify where save files should be
set_savefile_path(".", "autosave")
###
# specify what save files should be restored. Note these files must be
# in the directory specified in set_savefile_path(), or, if that function
# has not been called, from the directory current when iocInit is invoked
set_pass0_restoreFile("auto_positions.sav")
set_pass0_restoreFile("auto_settings.sav")
set_pass1_restoreFile("auto_settings.sav")
# load general-purpose interpolation tables with local, user-editable file
# (if interp_settings.req is included in auto_settings.req, the next line
# will overwrite those restored values)
#set_pass1_restoreFile("interp.sav")
###
# specify directories in which to to search for included request files
set_requestfile_path("./")
set_requestfile_path("/corvette/home/epics/support/CARS", "db")
set_requestfile_path("/corvette/home/epics/support/CARS", "iocBoot")
set_requestfile_path("/corvette/home/epics/support/areaDetector-3-12-1/ADCore", "db")
set_requestfile_path("/corvette/home/epics/support/autosave-5-10-2", "db")
set_requestfile_path("/corvette/home/epics/support/busy-1-7-3", "db")
set_requestfile_path("/corvette/home/epics/support/calc-3-7-4", "db")
set_requestfile_path("/corvette/home/epics/support/dac128V-2-10-1", "db")
set_requestfile_path("/corvette/home/epics/support/dxp-6-0", "db")
set_requestfile_path("/corvette/home/epics/support/Galil/3-6", "db")
set_requestfile_path("/corvette/home/epics/support/ip-2-21-1", "db")
set_requestfile_path("/corvette/home/epics/support/mca-7-9", "db")
set_requestfile_path("/corvette/home/epics/support/measComp-4-1", "db")
set_requestfile_path("/corvette/home/epics/support/motor-7-3", "db")
set_requestfile_path("/corvette/home/epics/support/optics-2-13-5", "db")
set_requestfile_path("/corvette/home/epics/support/quadEM-9-4", "db")
set_requestfile_path("/corvette/home/epics/support/scaler-4-0", "db")
set_requestfile_path("/corvette/home/epics/support/sscan-2-11-5", "db")
set_requestfile_path("/corvette/home/epics/support/SyringePump-0-1", "db")
set_requestfile_path("/corvette/home/epics/support/std-3-6-3", "db")
set_requestfile_path("/corvette/home/epics/support/tomoscan", "db")
set_requestfile_path("/corvette/home/epics/support/vme-2-9-4", "db")
#dbLoadRecords("$(AUTOSAVE)/db/save_restoreStatus.db", "P=xxx:")
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.7.1-DEV
## Rev. R7.0.7-125-g5a1f3ecc8b9d97a5fa4f-dirty
## Rev. Date Git: 2023-05-18 11:57:41 -0700
############################################################################
drvStreamInit: Warning! STREAM_PROTOCOL_PATH not set.
save_restore: Can't open file './autosave/auto_positions.sav'.
save_restore: Trying backup file './autosave/auto_positions.savB'
save_restore: Can't open file './autosave/auto_positions.savB'.
save_restore: Can't figure out which seq file is most recent,
save_restore: so I'm just going to start with './autosave/auto_positions.sav0'.
save_restore: Trying backup file './autosave/auto_positions.sav0'
save_restore: Can't open file './autosave/auto_positions.sav0'.
save_restore: Trying backup file './autosave/auto_positions.sav1'
save_restore: Can't open file './autosave/auto_positions.sav1'.
save_restore: Trying backup file './autosave/auto_positions.sav2'
save_restore: Can't open file './autosave/auto_positions.sav2'.
save_restore: Can't find a file to restore from...save_restore: ...last tried './autosave/auto_positions.sav2'. I give up.
save_restore: **********************************
save_restore: Can't open save file.cas WARNING: Configured TCP port was unavailable.
cas WARNING: Using dynamically assigned TCP port 41908,
cas WARNING: but now two or more servers share the same UDP port.
cas WARNING: Depending on your IP kernel this server may not be
cas WARNING: reachable with UDP unicast (a host's IP in EPICS_CA_ADDR_LIST)
iocRun: All initialization complete
2023-07-07T12:51:52.424 Using dynamically assigned TCP port 49353.
create_monitor_set("auto_settings.req", 30)
epics> auto_settings.sav: 2 of 2 PV's connected
So I don't get any autosave error, even though I have not passed the macro STAGE_TYPE when loading the database.
This is the resulting auto_settings.sav file:
corvette:CARS/iocBoot/ioc13test>more autosave/auto_settings.sav
# autosave R5.3 Automatically generated - DO NOT MODIFY - 230707-125223
string_test.VAL
string_test.DESC This is the description
<END>
Autosave when saving a string without value causes fprintf ERRLEVEL, which is problematic as you will incur data loss at the first null value one is trying to autosave.
Can null values be checked for and make this a warning or blank for the output sav files and the datestamped sav files