@ -125,12 +125,11 @@ static int max_safe_fds = 32; /* default if not changed */
/* these are the assigned bits in fdstate below: */
# define FD_TEMPORARY (1 << 0) /* T = delete when closed */
# define FD_XACT_TEMPORARY (1 << 1) /* T = delete at eoXact */
# define FD_XACT_TRANSIENT (1 << 2) / * T = close (not delete) at aoXact,
* but keep VFD */
/*
* Flag to tell whether it ' s worth scanning VfdCache looking for temp files to
* close
*/
static bool have_xact_temporary_files = false ;
/* Flag to tell whether there are files to close/delete at end of transaction */
static bool have_pending_fd_cleanup = false ;
typedef struct vfd
{
@ -953,7 +952,7 @@ OpenTemporaryFile(bool interXact)
VfdCache [ file ] . resowner = CurrentResourceOwner ;
/* ensure cleanup happens at eoxact */
have_xact_temporary_files = true ;
have_pending_fd_cleanup = true ;
}
return file ;
@ -1026,6 +1025,45 @@ OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
return file ;
}
/*
* Set the transient flag on a file
*
* This flag tells CleanupTempFiles to close the kernel - level file descriptor
* ( but not the VFD itself ) at end of transaction .
*/
void
FileSetTransient ( File file )
{
Vfd * vfdP ;
Assert ( FileIsValid ( file ) ) ;
vfdP = & VfdCache [ file ] ;
vfdP - > fdstate | = FD_XACT_TRANSIENT ;
have_pending_fd_cleanup = true ;
}
/*
* Close a file at the kernel level , but keep the VFD open
*/
static void
FileKernelClose ( File file )
{
Vfd * vfdP ;
Assert ( FileIsValid ( file ) ) ;
vfdP = & VfdCache [ file ] ;
if ( ! FileIsNotOpen ( file ) )
{
if ( close ( vfdP - > fd ) )
elog ( ERROR , " could not close file \" %s \" : %m " , vfdP - > fileName ) ;
vfdP - > fd = VFD_CLOSED ;
}
}
/*
* close a file when done with it
*/
@ -1778,8 +1816,9 @@ AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
* particularly care which ) . All still - open per - transaction temporary file
* VFDs are closed , which also causes the underlying files to be deleted
* ( although they should ' ve been closed already by the ResourceOwner
* cleanup ) . Furthermore , all " allocated " stdio files are closed . We also
* forget any transaction - local temp tablespace list .
* cleanup ) . Transient files have their kernel file descriptors closed .
* Furthermore , all " allocated " stdio files are closed . We also forget any
* transaction - local temp tablespace list .
*/
void
AtEOXact_Files ( void )
@ -1802,7 +1841,10 @@ AtProcExit_Files(int code, Datum arg)
}
/*
* Close temporary files and delete their underlying files .
* General cleanup routine for fd . c .
*
* Temporary files are closed , and their underlying files deleted .
* Transient files are closed .
*
* isProcExit : if true , this is being called as the backend process is
* exiting . If that ' s the case , we should remove all temporary files ; if
@ -1819,35 +1861,49 @@ CleanupTempFiles(bool isProcExit)
* Careful here : at proc_exit we need extra cleanup , not just
* xact_temporary files .
*/
if ( isProcExit | | have_xact_temporary_files )
if ( isProcExit | | have_pending_fd_cleanup )
{
Assert ( FileIsNotOpen ( 0 ) ) ; /* Make sure ring not corrupted */
for ( i = 1 ; i < SizeVfdCache ; i + + )
{
unsigned short fdstate = VfdCache [ i ] . fdstate ;
if ( ( fdstate & FD_TEMPORARY ) & & VfdCache [ i ] . fileName ! = NULL )
if ( VfdCache [ i ] . fileName ! = NULL )
{
/*
* If we ' re in the process of exiting a backend process , close
* all temporary files . Otherwise , only close temporary files
* local to the current transaction . They should be closed by
* the ResourceOwner mechanism already , so this is just a
* debugging cross - check .
*/
if ( isProcExit )
FileClose ( i ) ;
else if ( fdstate & FD_XACT_TEMPORARY )
if ( fdstate & FD_TEMPORARY )
{
/*
* If we ' re in the process of exiting a backend process , close
* all temporary files . Otherwise , only close temporary files
* local to the current transaction . They should be closed by
* the ResourceOwner mechanism already , so this is just a
* debugging cross - check .
*/
if ( isProcExit )
FileClose ( i ) ;
else if ( fdstate & FD_XACT_TEMPORARY )
{
elog ( WARNING ,
" temporary file %s not closed at end-of-transaction " ,
VfdCache [ i ] . fileName ) ;
FileClose ( i ) ;
}
}
else if ( fdstate & FD_XACT_TRANSIENT )
{
elog ( WARNING ,
" temporary file %s not closed at end-of-transaction " ,
VfdCache [ i ] . fileName ) ;
FileClose ( i ) ;
/*
* Close the kernel file descriptor , but also remove the
* flag from the VFD . This is to ensure that if the VFD is
* reused in the future for non - transient access , we don ' t
* close it inappropriately then .
*/
FileKernelClose ( i ) ;
VfdCache [ i ] . fdstate & = ~ FD_XACT_TRANSIENT ;
}
}
}
have_xact_temporary_files = false ;
have_pending_fd_cleanup = false ;
}
/* Clean up "allocated" stdio files and dirs. */