diff options
Diffstat (limited to 'src/backend/storage/file/fd.c')
-rw-r--r-- | src/backend/storage/file/fd.c | 111 |
1 files changed, 72 insertions, 39 deletions
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index b84e2cb82d1..5552a043399 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.97 2003/04/04 20:42:12 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.98 2003/04/29 03:21:29 tgl Exp $ * * NOTES: * @@ -113,8 +113,8 @@ int max_files_per_process = 1000; #define FileUnknownPos (-1L) /* these are the assigned bits in fdstate below: */ -#define FD_TEMPORARY (1 << 0) -#define FD_TXN_TEMPORARY (1 << 1) +#define FD_TEMPORARY (1 << 0) /* T = delete when closed */ +#define FD_XACT_TEMPORARY (1 << 1) /* T = delete at eoXact */ typedef struct vfd { @@ -156,7 +156,7 @@ static int numAllocatedFiles = 0; static FILE *allocatedFiles[MAX_ALLOCATED_FILES]; /* - * Number of temporary files opened during the current transaction; + * Number of temporary files opened during the current session; * this is used in generation of tempfile names. */ static long tempFileCounter = 0; @@ -205,6 +205,9 @@ static int FileAccess(File file); static File fileNameOpenFile(FileName fileName, int fileFlags, int fileMode); static char *filepath(const char *filename); static long pg_nofile(void); +static void AtProcExit_Files(void); +static void CleanupTempFiles(bool isProcExit); + /* * pg_fsync --- same as fsync except does nothing if enableFsync is off @@ -522,7 +525,7 @@ AllocateVfd(void) * register proc-exit call to ensure temp files are dropped at * exit */ - on_proc_exit(AtEOXact_Files, 0); + on_proc_exit(AtProcExit_Files, 0); } if (VfdCache[0].nextFree == 0) @@ -751,21 +754,21 @@ PathNameOpenFile(FileName fileName, int fileFlags, int fileMode) * There's no need to pass in fileFlags or fileMode either, since only * one setting makes any sense for a temp file. * - * keepOverTxn: if true, don't close the file at end-of-transaction. In + * interXact: if true, don't close the file at end-of-transaction. In * most cases, you don't want temporary files to outlive the transaction * that created them, so this should be false -- but if you need * "somewhat" temporary storage, this might be useful. In either case, - * the file is removed when the File is explicitely closed. + * the file is removed when the File is explicitly closed. */ File -OpenTemporaryFile(bool keepOverTxn) +OpenTemporaryFile(bool interXact) { - char tempfilepath[128]; + char tempfilepath[MAXPGPATH]; File file; /* - * Generate a tempfile name that's unique within the current - * transaction and database instance. + * Generate a tempfile name that should be unique within the current + * database instance. */ snprintf(tempfilepath, sizeof(tempfilepath), "%s/%s%d.%ld", PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX, @@ -798,15 +801,16 @@ OpenTemporaryFile(bool keepOverTxn) O_RDWR | O_CREAT | O_TRUNC | PG_BINARY, 0600); if (file <= 0) - elog(ERROR, "Failed to create temporary file %s", tempfilepath); + elog(ERROR, "Failed to create temporary file %s: %m", + tempfilepath); } /* Mark it for deletion at close */ VfdCache[file].fdstate |= FD_TEMPORARY; /* Mark it for deletion at EOXact */ - if (!keepOverTxn) - VfdCache[file].fdstate |= FD_TXN_TEMPORARY; + if (!interXact) + VfdCache[file].fdstate |= FD_XACT_TEMPORARY; return file; } @@ -1108,44 +1112,79 @@ closeAllVfds(void) /* * AtEOXact_Files * - * This routine is called during transaction commit or abort or backend - * exit (it doesn't particularly care which). All still-open temporary-file - * VFDs are closed, which also causes the underlying files to be deleted. - * Furthermore, all "allocated" stdio files are closed. + * This routine is called during transaction commit or abort (it doesn't + * particularly care which). All still-open per-transaction temporary file + * VFDs are closed, which also causes the underlying files to be + * deleted. Furthermore, all "allocated" stdio files are closed. */ void AtEOXact_Files(void) { - Index i; + CleanupTempFiles(false); +} + +/* + * AtProcExit_Files + * + * on_proc_exit hook to clean up temp files during backend shutdown. + * Here, we want to clean up *all* temp files including interXact ones. + */ +static void +AtProcExit_Files(void) +{ + CleanupTempFiles(true); +} + +/* + * Close temporary files and delete their underlying files. + * + * 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 + * that's not the case, we are being called for transaction commit/abort + * and should only remove transaction-local temp files. In either case, + * also clean up "allocated" stdio files. + */ +static void +CleanupTempFiles(bool isProcExit) +{ + Index i; if (SizeVfdCache > 0) { Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */ for (i = 1; i < SizeVfdCache; i++) { - if ((VfdCache[i].fdstate & FD_TEMPORARY) && - (VfdCache[i].fdstate & FD_TXN_TEMPORARY) && - VfdCache[i].fileName != NULL) - FileClose(i); + unsigned short fdstate = VfdCache[i].fdstate; + + if ((fdstate & FD_TEMPORARY) && 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. + */ + if (isProcExit || (fdstate & FD_XACT_TEMPORARY)) + FileClose(i); + } } } while (numAllocatedFiles > 0) FreeFile(allocatedFiles[0]); - - /* - * Reset the tempfile name counter to 0; not really necessary, but - * helps keep the names from growing unreasonably long. - */ - tempFileCounter = 0; } /* - * Remove old temporary files + * Remove temporary files left over from a prior postmaster session * * This should be called during postmaster startup. It will forcibly * remove any leftover files created by OpenTemporaryFile. + * + * NOTE: we could, but don't, call this during a post-backend-crash restart + * cycle. The argument for not doing it is that someone might want to examine + * the temp files for debugging purposes. This does however mean that + * OpenTemporaryFile had better allow for collision with an existing temp + * file name. */ void RemovePgTempFiles(void) @@ -1194,15 +1233,9 @@ RemovePgTempFiles(void) strlen(PG_TEMP_FILE_PREFIX)) == 0) unlink(rm_path); else - { - /* - * would prefer to use elog here, but it's not up - * and running during postmaster startup... - */ - fprintf(stderr, - "Unexpected file found in temporary-files directory: %s\n", - rm_path); - } + elog(LOG, + "Unexpected file found in temporary-files directory: %s", + rm_path); } closedir(temp_dir); } |