Problem:
lock library.formats.catalog list;
NOTE: LIBRARY.FORMATS.CATALOG is not locked or in use by you or any other users.
lock library.formats.catalog;
ERROR: A lock is not available for LIBRARY.FORMATS.CATALOG.
Background:
The above error can be reproduced by running a job that first locks the catalog and later runs out of memory, causing sas to crash and die without cleaning up the lock.
The way to release the lock (as far as I know) is to reboot the server/computer.
Stopping all SAS services and/or exiting all sas programs does not clear the lock.
My question:
If a dataset is locked, SAS puts a lock file in the directory where the dataset is stored.
No lock file is created in the directory where the catalog is stored when a catalog is locked.
How does SAS know that a catalog is locked?
Where is the "this catalog is locked" flag/status stored?
Probably a different kind of "lock" than what the LOCK statement does. Most likely it means that some process has the file OPEN so you cannot make any changes to it.
Make sure to use the ACCESS=READONLY option when you define the libref you use to use the formats. That should allow multiple processes to use the formats at once.
If you have to make changes to the format catalog do it with a separate step. In fact write the format catalog to a NEW file and then use operating system commands to swap the files to deploy the updated formats. That way if some process still has the old file open it will not prevent new processes from finding the new file.
I won't answer to your question, but maybe instead using `library.formats` in multiple sessions make a local copy of it at the beginning of the process:
options dlcreatedir;
libname localCp "%sysfunc(pathname(work))/localCopyFormats";
proc copy
OUT=localCp
CLONE
IN=library;
SELECT formats;
run;
options insert=(fmtsearch=(localCp)); /* to ensure it will be searched before library */
libname library clear;
Bart
Well, that would work if all you wanted was a copy of the formats. If you want to update the formats it does not work.
I tried using proc copy to another location, like you described, and then tried copying it back to where it belongs:
NOTE: Copying LOCALCP.FORMATS to LIBRARY.FORMATS (memtype=CATALOG).
ERROR: A lock is not available for LIBRARY.FORMATS.CATALOG.
ERROR: File LIBRARY.FORMATS.CATALOG has not been saved because copy could not be completed.
SAS still claims that it is not locked by me:
3228 lock library.formats.catalog clear;
ERROR: LIBRARY.FORMATS.CATALOG is not locked by you.
3229
In fact it claims it is not locked by anyone:
3230 lock localcp.formats.catalog list;
NOTE: LOCALCP.FORMATS.CATALOG is not locked or in use by you or any other users.
oops, typo in the last line, but the result is the same:
1 lock library.formats.catalog list;
NOTE: LIBRARY.FORMATS.CATALOG is not locked or in use by you or any other users.
Again, not the answer to the question but: How about using a SAS Package for storing and sharing formats?
Here is: a "hello world" example how to build a package (with format in the example): https://github.com/yabwon/SAS_PACKAGES/blob/main/SPF/Documentation/HelloWorldPackage.md
[EDIT:] Just a side note sas catalogs are OS dependent, packages are not.
Bart
How about a binary copy?
options dlcreatedir;
libname localCp "%sysfunc(pathname(work))/localCopyFormats";
filename f_in "%sysfunc(pathname(library))/formats.sas7bcat" lrecl=1 recfm=F;
filename f_out "%sysfunc(pathname(localCp))/formats.sas7bcat" lrecl=1 recfm=F;
data _null_;
rc = fcopy("f_in", "f_out");
run;
filename f_in clear;
filename f_out clear;
Bart
One more thing, you may like this reading by Troy Hughes, he has a paper about failures of the LOCK statement:
https://support.sas.com/resour
Bart
Probably a different kind of "lock" than what the LOCK statement does. Most likely it means that some process has the file OPEN so you cannot make any changes to it.
Make sure to use the ACCESS=READONLY option when you define the libref you use to use the formats. That should allow multiple processes to use the formats at once.
If you have to make changes to the format catalog do it with a separate step. In fact write the format catalog to a NEW file and then use operating system commands to swap the files to deploy the updated formats. That way if some process still has the old file open it will not prevent new processes from finding the new file.
Yes its a different lock.
That's why I'm asking how sas knows it is locked.
I've experimented with this and if I lock a catalog the sas7bcat file is locked by windows.
Windows should release file locks when the process dies, but maybe it does not always work.
I thought I checked that the last time it happened, and found the sas7bcat file to be unlocked (I think I was able to rename it) but can't be 100% sure.
I'll check for locked files in the OS the next time it happens.
The problem is, I have several batch jobs that all update the formats library. These jobs can't use an ACCESS=READONLY libname.
All other jobs can use a readonly library.
A couple of thoughts:
Updating of formats is usually quick so this problem can only occur if your batch jobs run PROC FORMAT at exactly the same time. Can you reschedule them to not run at the same time?
If you have to run them at the same time try the FILELOCKWAIT option on your FORMATS LIBNAME to get SAS to wait a number of seconds for the lock to clear - maybe try 30 seconds to start with.
My batch jobs that update formats are run in sequence, so they shouldn't be trying to update the formats at the same time.
In normal circumstances, it is not a problem. 99.99% of the time my batch jobs all work fine, both updating and using the formats is no issue.
It's when the process updating the format runs out of memory and dies, and leaves the file locked forever, that it's a problem, and I have to reboot in order to release the lock.
How about: first creating a temporary entry (new or updated format) in the WORK and then, when process of creating is done successfully (without out-of-memory crush), copying format from WORK to final destination?
Bart
This is more of an operating system problem than a SAS issue. A dead (read: removed from the process list) process should not leave anything behind; no used memory, no file handles, no locks.
So I suggest you look for a Windows equivalent for the UNIX fuser command.
In that case, increase your MEMESIZE SAS option to ensure you don't run out of memory. You can check the current setting by running this:
proc options option=memsize;
run;
If anyone is interested:
The problem is that SAS locks the formats.sas7bcat file on the file system level, even if reading it from a read-only library, if the CATCACHE option is set to anything other than 0.
That SAS does this does not make sense to me at all.
Example:
Set this in your config file and start sas:
CATCACHE=3K Specifies the number of SAS catalogs to keep open in cache memory.
Then run this code:
libname lib_ro "[path to your formats directory]" ACCESS=READONLY;
proc datasets library=lib_ro memtype=(catalog);
copy out=work;
select formats;
run;
Now open resource monitor in windows and search associated handles for formats.sas7bcat. You will find that SAS has locked the file.
Exit sas. Now search handles again, you will find that the lock is now released.
Then exit SAS, set the catcahe option to 0:
CATCACHE=0 Specifies the number of SAS catalogs to keep open in cache memory.
And do the same proc datasets again, and check handles - this time the file is not locked.
I understand the need to lock a file if it's going to be written to. But locking a file that you're not going to write to does not make sense to me.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.