@ -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
{
@ -591,6 +590,7 @@ LruDelete(File file)
Vfd * vfdP ;
Assert ( file ! = 0 ) ;
Assert ( ! FileIsNotOpen ( file ) ) ;
DO_DB ( elog ( LOG , " LruDelete %d (%s) " ,
file , VfdCache [ file ] . fileName ) ) ;
@ -953,7 +953,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 +1026,25 @@ 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 when done with it
*/
@ -1778,8 +1797,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 +1822,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 +1842,51 @@ 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 FD , and remove the entry from the LRU ring ,
* 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 .
*/
if ( ! FileIsNotOpen ( i ) )
LruDelete ( i ) ;
VfdCache [ i ] . fdstate & = ~ FD_XACT_TRANSIENT ;
}
}
}
have_xact_temporary_files = false ;
have_pending_fd_cleanup = false ;
}
/* Clean up "allocated" stdio files and dirs. */