When writing to SAS datasets or creating views in permanent libraries shared by lots of users, one will regularly have the problem that a user has a file open for viewing or other purposes, which prevents SAS from opening the file for update; although SAS will always create a new (.lck) file when a complete rewrite is done, it still blocks if it recognizes that the original file is opened.
Because of the way the UNIX filesystem is structured, a directory entry does not contain file metadata; instead, it points to a so-called inode that contains metadata and the pointers to the actual data blocks.
The file handle that is created when a file is opened therefore points to the inode, not the directory entry. This allows directory entries to be manipulated (including removal) even when the file they point to is in use.
The following macro makes use of this by:
%macro ds_delete(ds=,ext=Y,safe=N); /* ds_delete, Version 0.9 This macro is designed to use the UNIX operating system command rm to delete a dataset or view, in order to prevent a "Dataset is locked" message. It will automatically determine the physical path to the library and the proper filename extension. Depending on the presence of a second parameter, it will either use the FILENAME PIPE method to run the UNIX command, or the %SYSEXEC macro statement. */ %if %length(&ds.) lt 1 %then %do; /* issue a usage note */ %put Usage:; %put %nrstr(%ds_delete)(ds=dataset|view[,ext=y|n][,safe=y|n]); %put ds=dataset|view .. name of the dataset or view, single level considered in WORK; %put ext= (optional) .. Y will use external commands; %put safe=(optional) .. Y will cause macro code to be used (otherwise data step); %return; %end; /* make our macro behave gracefully */ %local dsid type suffix pathname fname command rc ; /* crude check for validity of dataset name */ %if %sysfunc(countw(&ds.,.)) gt 2 %then %do; %put Too many levels!; %return; %end; /* expand single-level dataset name */ %if %sysfunc(countw(&ds.,.)) lt 2 %then %let ds = WORK.&ds.; /* check if the dataset/view actually exists */ %let dsid = %sysfunc(open(&ds.)); %if &dsid. = 0 %then %do; %put Dataset or view does not exist!; %return; %end; /* determine physical filename suffix */ %let type = %sysfunc(attrc(&dsid.,MTYPE)); %if &type. = VIEW %then %let suffix = sas7bvew; %else %let suffix = sas7bdat; /* get physical name of the directory */ %let pathname = %sysfunc(pathname(%sysfunc(attrc(&dsid.,LIB)))); /* build the complete filename */ %let fname = %lowcase(%sysfunc(attrc(&dsid.,MEM))).&suffix.; /* external command or FDELETE */ %if %upcase(&ext.) = Y %then %do; /* build the command */ %let command = rm -f &pathname./&fname.; /* run the command, either with %SYSEXEC or FILENAME PIPE */ %if %upcase(&safe.) = Y %then %do; /* this makes the code "safe" for use anywhere in code, by using only macro statements */ %sysexec &command.; %end; %else %do; /* retrieve all responses (including stderr) and write them to the log */ data _null_; infile "&command. 2>&1" pipe; input; put _infile_; run; %end; %end; %else %do; %if %upcase(&safe.) = Y %then %do; /* macro statements */ %let rc = %sysfunc(filename(fref,&pathname./&fname.)); %if &rc = 0 %then %do; %let rc = %sysfunc(fdelete(&fref)); %put &=rc.; %let rc = %sysfunc(filename(fref)); %end; %end; %else %do; /* data step */ data _null_; length fref $8; rc = filename(fref,"&pathname/&fname."); rc = fdelete(fref); put rc=; rc = filename(fref); run; %end; %end; %let dsid = %sysfunc(close(&dsid.)); %mend;
If you ask yourself what will happen to a dataset file that is open at the time the macro is run: the directory entry will be removed, making the file "vanish" from a user's POV; but the actual data will be kept until the last file handle for the inode is closed. At this point the UNIX kernel realizes that the inode does no longer have a directory entry ("link") pointing to it, and removes it, clearing the allocation table entries along with it, and freeing the space.
In this particular case, it might be that a user runs out of space while writing the new dataset even if there is no more data than it originally contained; the "zombie" still occupies the space until it is closed.
Edit from 2021-05-22: copied the macro code from the SASGF 2021 paper/presentation, which can alternatively use FDELETE.
Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.
If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website.
Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning and boost your career prospects.