1 /*-------------------------------------------------------------------------
4 * Virtual file descriptor code.
6 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.93 2002/08/06 02:36:34 tgl Exp $
14 * This code manages a cache of 'virtual' file descriptors (VFDs).
15 * The server opens many file descriptors for a variety of reasons,
16 * including base tables, scratch files (e.g., sort and hash spool
17 * files), and random calls to C library routines like system(3); it
18 * is quite easy to exceed system limits on the number of open files a
19 * single process can have. (This is around 256 on many modern
20 * operating systems, but can be as low as 32 on others.)
22 * VFDs are managed as an LRU pool, with actual OS file descriptors
23 * being opened and closed as needed. Obviously, if a routine is
24 * opened using these interfaces, all subsequent operations must also
25 * be through these interfaces (the File type is not a real file
28 * For this scheme to work, most (if not all) routines throughout the
29 * server should use these interfaces instead of calling the C library
30 * routines (e.g., open(2) and fopen(3)) themselves. Otherwise, we
31 * may find ourselves short of real file descriptors anyway.
33 * This file used to contain a bunch of stuff to support RAID levels 0
34 * (jbod), 1 (duplex) and 5 (xor parity). That stuff is all gone
35 * because the parallel query processing code that called it is all
36 * gone. If you really need it you could get it from the original
38 *-------------------------------------------------------------------------
43 #include <sys/types.h>
45 #include <sys/param.h>
52 #include "miscadmin.h"
53 #include "storage/fd.h"
54 #include "storage/ipc.h"
57 /* Filename components for OpenTemporaryFile */
58 #define PG_TEMP_FILES_DIR "pgsql_tmp"
59 #define PG_TEMP_FILE_PREFIX "pgsql_tmp"
63 * Problem: Postgres does a system(ld...) to do dynamic loading.
64 * This will open several extra files in addition to those used by
65 * Postgres. We need to guarantee that there are file descriptors free
68 * The current solution is to limit the number of file descriptors
69 * that this code will allocate at one time: it leaves RESERVE_FOR_LD free.
71 * (Even though most dynamic loaders now use dlopen(3) or the
72 * equivalent, the OS must still open several files to perform the
73 * dynamic loading. And stdin/stdout/stderr count too. Keep this here.)
75 #ifndef RESERVE_FOR_LD
76 #define RESERVE_FOR_LD 10
80 * We need to ensure that we have at least some file descriptors
81 * available to postgreSQL after we've reserved the ones for LD,
82 * so we set that value here.
84 * I think 10 is an appropriate value so that's what it'll be
92 * A number of platforms return values for sysconf(_SC_OPEN_MAX) that are
93 * far beyond what they can really support. This GUC parameter limits what
96 int max_files_per_process = 1000;
104 #define DO_DB(A) /* A */
107 #define VFD_CLOSED (-1)
109 #define FileIsValid(file) \
110 ((file) > 0 && (file) < (int) SizeVfdCache && VfdCache[file].fileName != NULL)
112 #define FileIsNotOpen(file) (VfdCache[file].fd == VFD_CLOSED)
114 #define FileUnknownPos (-1L)
118 signed short fd; /* current FD, or VFD_CLOSED if none */
119 unsigned short fdstate; /* bitflags for VFD's state */
121 /* these are the assigned bits in fdstate: */
122 #define FD_TEMPORARY (1 << 0) /* should be unlinked when closed */
124 File nextFree; /* link to next free VFD, if in freelist */
125 File lruMoreRecently; /* doubly linked recency-of-use list */
126 File lruLessRecently;
127 long seekPos; /* current logical file position */
128 char *fileName; /* name of file, or NULL for unused VFD */
129 /* NB: fileName is malloc'd, and must be free'd when closing the VFD */
130 int fileFlags; /* open(2) flags for (re)opening the file */
131 int fileMode; /* mode to pass to open(2) */
135 * Virtual File Descriptor array pointer and size. This grows as
136 * needed. 'File' values are indexes into this array.
137 * Note that VfdCache[0] is not a usable VFD, just a list header.
139 static Vfd *VfdCache;
140 static Size SizeVfdCache = 0;
143 * Number of file descriptors known to be in use by VFD entries.
145 static int nfile = 0;
148 * List of stdio FILEs opened with AllocateFile.
150 * Since we don't want to encourage heavy use of AllocateFile, it seems
151 * OK to put a pretty small maximum limit on the number of simultaneously
154 #define MAX_ALLOCATED_FILES 32
156 static int numAllocatedFiles = 0;
157 static FILE *allocatedFiles[MAX_ALLOCATED_FILES];
160 * Number of temporary files opened during the current transaction;
161 * this is used in generation of tempfile names.
163 static long tempFileCounter = 0;
166 /*--------------------
170 * Delete - delete a file from the Lru ring
171 * LruDelete - remove a file from the Lru ring and close its FD
172 * Insert - put a file at the front of the Lru ring
173 * LruInsert - put a file at the front of the Lru ring and open it
174 * ReleaseLruFile - Release an fd by closing the last entry in the Lru ring
175 * AllocateVfd - grab a free (or new) file record (from VfdArray)
176 * FreeVfd - free a file record
178 * The Least Recently Used ring is a doubly linked list that begins and
179 * ends on element zero. Element zero is special -- it doesn't represent
180 * a file and its "fd" field always == VFD_CLOSED. Element zero is just an
181 * anchor that shows us the beginning/end of the ring.
182 * Only VFD elements that are currently really open (have an FD assigned) are
183 * in the Lru ring. Elements that are "virtually" open can be recognized
184 * by having a non-null fileName field.
188 * /--less----\ /---------\
190 * #0 --more---> LeastRecentlyUsed --more-\ \
192 * \\less--> MostRecentlyUsedFile <---/ |
193 * \more---/ \--less--/
195 *--------------------
197 static void Delete(File file);
198 static void LruDelete(File file);
199 static void Insert(File file);
200 static int LruInsert(File file);
201 static bool ReleaseLruFile(void);
202 static File AllocateVfd(void);
203 static void FreeVfd(File file);
205 static int FileAccess(File file);
206 static File fileNameOpenFile(FileName fileName, int fileFlags, int fileMode);
207 static char *filepath(const char *filename);
208 static long pg_nofile(void);
211 * pg_fsync --- same as fsync except does nothing if enableFsync is off
223 * pg_fdatasync --- same as fdatasync except does nothing if enableFsync is off
225 * Not all platforms have fdatasync; treat as fsync if not available.
232 #ifdef HAVE_FDATASYNC
233 return fdatasync(fd);
243 * BasicOpenFile --- same as open(2) except can free other FDs if needed
245 * This is exported for use by places that really want a plain kernel FD,
246 * but need to be proof against running out of FDs. Once an FD has been
247 * successfully returned, it is the caller's responsibility to ensure that
248 * it will not be leaked on elog()! Most users should *not* call this
249 * routine directly, but instead use the VFD abstraction level, which
250 * provides protection against descriptor leaks as well as management of
251 * files that need to be open for more than a short period of time.
253 * Ideally this should be the *only* direct call of open() in the backend.
254 * In practice, the postmaster calls open() directly, and there are some
255 * direct open() calls done early in backend startup. Those are OK since
256 * this module wouldn't have any open files to close at that point anyway.
259 BasicOpenFile(FileName fileName, int fileFlags, int fileMode)
264 fd = open(fileName, fileFlags, fileMode);
267 return fd; /* success! */
269 if (errno == EMFILE || errno == ENFILE)
271 int save_errno = errno;
273 DO_DB(elog(LOG, "BasicOpenFile: not enough descs, retry, er= %d",
276 if (ReleaseLruFile())
281 return -1; /* failure */
285 * pg_nofile: determine number of filedescriptors that fd.c is allowed to use
290 static long no_files = 0;
292 /* need do this calculation only once */
296 * Ask the system what its files-per-process limit is.
299 no_files = sysconf(_SC_OPEN_MAX);
303 no_files = (long) NOFILE;
305 no_files = (long) max_files_per_process;
307 elog(LOG, "pg_nofile: sysconf(_SC_OPEN_MAX) failed; using %ld",
310 #else /* !HAVE_SYSCONF */
312 no_files = (long) NOFILE;
314 no_files = (long) max_files_per_process;
316 #endif /* HAVE_SYSCONF */
319 * Some platforms return hopelessly optimistic values. Apply a
320 * configurable upper limit.
322 if (no_files > (long) max_files_per_process)
323 no_files = (long) max_files_per_process;
326 * Make sure we have enough to get by after reserving some for LD.
328 if ((no_files - RESERVE_FOR_LD) < FD_MINFREE)
329 elog(FATAL, "pg_nofile: insufficient file descriptors available to start backend.\n"
330 "\tSystem allows %ld, we need at least %d.",
331 no_files, RESERVE_FOR_LD + FD_MINFREE);
333 no_files -= RESERVE_FOR_LD;
344 int mru = VfdCache[0].lruLessRecently;
345 Vfd *vfdP = &VfdCache[mru];
348 sprintf(buf, "LRU: MOST %d ", mru);
351 mru = vfdP->lruLessRecently;
352 vfdP = &VfdCache[mru];
353 sprintf(buf + strlen(buf), "%d ", mru);
355 sprintf(buf + strlen(buf), "LEAST");
367 DO_DB(elog(LOG, "Delete %d (%s)",
368 file, VfdCache[file].fileName));
371 vfdP = &VfdCache[file];
373 VfdCache[vfdP->lruLessRecently].lruMoreRecently = vfdP->lruMoreRecently;
374 VfdCache[vfdP->lruMoreRecently].lruLessRecently = vfdP->lruLessRecently;
386 DO_DB(elog(LOG, "LruDelete %d (%s)",
387 file, VfdCache[file].fileName));
389 vfdP = &VfdCache[file];
391 /* delete the vfd record from the LRU ring */
394 /* save the seek position */
395 vfdP->seekPos = (long) lseek(vfdP->fd, 0L, SEEK_CUR);
396 Assert(vfdP->seekPos != -1L);
400 elog(LOG, "LruDelete: failed to close %s: %m",
404 vfdP->fd = VFD_CLOSED;
414 DO_DB(elog(LOG, "Insert %d (%s)",
415 file, VfdCache[file].fileName));
418 vfdP = &VfdCache[file];
420 vfdP->lruMoreRecently = 0;
421 vfdP->lruLessRecently = VfdCache[0].lruLessRecently;
422 VfdCache[0].lruLessRecently = file;
423 VfdCache[vfdP->lruLessRecently].lruMoreRecently = file;
435 DO_DB(elog(LOG, "LruInsert %d (%s)",
436 file, VfdCache[file].fileName));
438 vfdP = &VfdCache[file];
440 if (FileIsNotOpen(file))
442 while (nfile + numAllocatedFiles >= pg_nofile())
444 if (!ReleaseLruFile())
449 * The open could still fail for lack of file descriptors, eg due
450 * to overall system file table being full. So, be prepared to
451 * release another FD if necessary...
453 vfdP->fd = BasicOpenFile(vfdP->fileName, vfdP->fileFlags,
457 DO_DB(elog(LOG, "RE_OPEN FAILED: %d", errno));
462 DO_DB(elog(LOG, "RE_OPEN SUCCESS"));
466 /* seek to the right position */
467 if (vfdP->seekPos != 0L)
471 returnValue = (long) lseek(vfdP->fd, vfdP->seekPos, SEEK_SET);
472 Assert(returnValue != -1L);
477 * put it at the head of the Lru ring
488 DO_DB(elog(LOG, "ReleaseLruFile. Opened %d", nfile));
493 * There are opened files and so there should be at least one used
496 Assert(VfdCache[0].lruMoreRecently != 0);
497 LruDelete(VfdCache[0].lruMoreRecently);
498 return true; /* freed a file */
500 return false; /* no files available to free */
509 DO_DB(elog(LOG, "AllocateVfd. Size %d", SizeVfdCache));
511 if (SizeVfdCache == 0)
513 /* initialize header entry first time through */
514 VfdCache = (Vfd *) malloc(sizeof(Vfd));
515 if (VfdCache == NULL)
516 elog(FATAL, "AllocateVfd: no room for VFD array");
517 MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
518 VfdCache->fd = VFD_CLOSED;
523 * register proc-exit call to ensure temp files are dropped at
526 on_proc_exit(AtEOXact_Files, 0);
529 if (VfdCache[0].nextFree == 0)
532 * The free list is empty so it is time to increase the size of
533 * the array. We choose to double it each time this happens.
534 * However, there's not much point in starting *real* small.
536 Size newCacheSize = SizeVfdCache * 2;
539 if (newCacheSize < 32)
543 * Be careful not to clobber VfdCache ptr if realloc fails; we
544 * will need it during proc_exit cleanup!
546 newVfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize);
547 if (newVfdCache == NULL)
548 elog(FATAL, "AllocateVfd: no room to enlarge VFD array");
549 VfdCache = newVfdCache;
552 * Initialize the new entries and link them into the free list.
554 for (i = SizeVfdCache; i < newCacheSize; i++)
556 MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
557 VfdCache[i].nextFree = i + 1;
558 VfdCache[i].fd = VFD_CLOSED;
560 VfdCache[newCacheSize - 1].nextFree = 0;
561 VfdCache[0].nextFree = SizeVfdCache;
564 * Record the new size
566 SizeVfdCache = newCacheSize;
569 file = VfdCache[0].nextFree;
571 VfdCache[0].nextFree = VfdCache[file].nextFree;
579 Vfd *vfdP = &VfdCache[file];
581 DO_DB(elog(LOG, "FreeVfd: %d (%s)",
582 file, vfdP->fileName ? vfdP->fileName : ""));
584 if (vfdP->fileName != NULL)
586 free(vfdP->fileName);
587 vfdP->fileName = NULL;
591 vfdP->nextFree = VfdCache[0].nextFree;
592 VfdCache[0].nextFree = file;
596 * Convert given pathname to absolute.
598 * Result is a palloc'd string.
600 * (Generally, this isn't actually necessary, considering that we
601 * should be cd'd into the database directory. Presently it is only
602 * necessary to do it in "bootstrap" mode. Maybe we should change
603 * bootstrap mode to do the cd, and save a few cycles/bytes here.)
606 filepath(const char *filename)
610 /* Not an absolute path name? Then fill in with database path... */
611 if (*filename != '/')
613 buf = (char *) palloc(strlen(DatabasePath) + strlen(filename) + 2);
614 sprintf(buf, "%s/%s", DatabasePath, filename);
617 buf = pstrdup(filename);
620 printf("filepath: path is %s\n", buf);
627 FileAccess(File file)
631 DO_DB(elog(LOG, "FileAccess %d (%s)",
632 file, VfdCache[file].fileName));
635 * Is the file open? If not, open it and put it at the head of the
636 * LRU ring (possibly closing the least recently used file to get an
640 if (FileIsNotOpen(file))
642 returnValue = LruInsert(file);
643 if (returnValue != 0)
646 else if (VfdCache[0].lruLessRecently != file)
649 * We now know that the file is open and that it is not the last
650 * one accessed, so we need to move it to the head of the Lru
662 * Called when we get a shared invalidation message on some relation.
666 FileInvalidate(File file)
668 Assert(FileIsValid(file));
669 if (!FileIsNotOpen(file))
675 fileNameOpenFile(FileName fileName,
682 if (fileName == NULL)
683 elog(ERROR, "fileNameOpenFile: NULL fname");
685 DO_DB(elog(LOG, "fileNameOpenFile: %s %x %o",
686 fileName, fileFlags, fileMode));
688 file = AllocateVfd();
689 vfdP = &VfdCache[file];
691 while (nfile + numAllocatedFiles >= pg_nofile())
693 if (!ReleaseLruFile())
697 vfdP->fd = BasicOpenFile(fileName, fileFlags, fileMode);
705 DO_DB(elog(LOG, "fileNameOpenFile: success %d",
710 vfdP->fileName = (char *) malloc(strlen(fileName) + 1);
711 if (vfdP->fileName == NULL)
712 elog(FATAL, "fileNameOpenFile: no room to save VFD filename");
713 strcpy(vfdP->fileName, fileName);
715 /* Saved flags are adjusted to be OK for re-opening file */
716 vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
717 vfdP->fileMode = fileMode;
725 * open a file in the database directory ($PGDATA/base/...)
728 FileNameOpenFile(FileName fileName, int fileFlags, int fileMode)
733 fname = filepath(fileName);
734 fd = fileNameOpenFile(fname, fileFlags, fileMode);
740 * open a file in an arbitrary directory
743 PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
745 return fileNameOpenFile(fileName, fileFlags, fileMode);
749 * Open a temporary file that will disappear when we close it.
751 * This routine takes care of generating an appropriate tempfile name.
752 * There's no need to pass in fileFlags or fileMode either, since only
753 * one setting makes any sense for a temp file.
756 OpenTemporaryFile(void)
758 char tempfilepath[128];
762 * Generate a tempfile name that's unique within the current
763 * transaction and database instance.
765 snprintf(tempfilepath, sizeof(tempfilepath),
766 "%s/%s%d.%ld", PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
767 MyProcPid, tempFileCounter++);
770 * Open the file. Note: we don't use O_EXCL, in case there is an
771 * orphaned temp file that can be reused.
773 file = FileNameOpenFile(tempfilepath,
774 O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
781 * We might need to create the pg_tempfiles subdirectory, if no
782 * one has yet done so.
784 * Don't check for error from mkdir; it could fail if someone else
785 * just did the same thing. If it doesn't work then we'll bomb
786 * out on the second create attempt, instead.
788 dirpath = filepath(PG_TEMP_FILES_DIR);
789 mkdir(dirpath, S_IRWXU);
792 file = FileNameOpenFile(tempfilepath,
793 O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
796 elog(ERROR, "Failed to create temporary file %s", tempfilepath);
799 /* Mark it for deletion at close or EOXact */
800 VfdCache[file].fdstate |= FD_TEMPORARY;
806 * close a file when done with it
813 Assert(FileIsValid(file));
815 DO_DB(elog(LOG, "FileClose: %d (%s)",
816 file, VfdCache[file].fileName));
818 vfdP = &VfdCache[file];
820 if (!FileIsNotOpen(file))
822 /* remove the file from the lru ring */
827 elog(LOG, "FileClose: failed to close %s: %m",
831 vfdP->fd = VFD_CLOSED;
835 * Delete the file if it was temporary
837 if (vfdP->fdstate & FD_TEMPORARY)
839 /* reset flag so that die() interrupt won't cause problems */
840 vfdP->fdstate &= ~FD_TEMPORARY;
841 if (unlink(vfdP->fileName))
842 elog(LOG, "FileClose: failed to unlink %s: %m",
847 * Return the Vfd slot to the free list
853 * close a file and forcibly delete the underlying Unix file
856 FileUnlink(File file)
858 Assert(FileIsValid(file));
860 DO_DB(elog(LOG, "FileUnlink: %d (%s)",
861 file, VfdCache[file].fileName));
863 /* force FileClose to delete it */
864 VfdCache[file].fdstate |= FD_TEMPORARY;
870 FileRead(File file, char *buffer, int amount)
874 Assert(FileIsValid(file));
876 DO_DB(elog(LOG, "FileRead: %d (%s) %ld %d %p",
877 file, VfdCache[file].fileName,
878 VfdCache[file].seekPos, amount, buffer));
881 returnCode = read(VfdCache[file].fd, buffer, amount);
883 VfdCache[file].seekPos += returnCode;
885 VfdCache[file].seekPos = FileUnknownPos;
891 FileWrite(File file, char *buffer, int amount)
895 Assert(FileIsValid(file));
897 DO_DB(elog(LOG, "FileWrite: %d (%s) %ld %d %p",
898 file, VfdCache[file].fileName,
899 VfdCache[file].seekPos, amount, buffer));
904 returnCode = write(VfdCache[file].fd, buffer, amount);
906 /* if write didn't set errno, assume problem is no disk space */
907 if (returnCode != amount && errno == 0)
911 VfdCache[file].seekPos += returnCode;
913 VfdCache[file].seekPos = FileUnknownPos;
919 FileSeek(File file, long offset, int whence)
921 Assert(FileIsValid(file));
923 DO_DB(elog(LOG, "FileSeek: %d (%s) %ld %ld %d",
924 file, VfdCache[file].fileName,
925 VfdCache[file].seekPos, offset, whence));
927 if (FileIsNotOpen(file))
933 elog(ERROR, "FileSeek: invalid offset: %ld", offset);
934 VfdCache[file].seekPos = offset;
937 VfdCache[file].seekPos += offset;
941 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
944 elog(ERROR, "FileSeek: invalid whence: %d", whence);
954 elog(ERROR, "FileSeek: invalid offset: %ld", offset);
955 if (VfdCache[file].seekPos != offset)
956 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
959 if (offset != 0 || VfdCache[file].seekPos == FileUnknownPos)
960 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
963 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
966 elog(ERROR, "FileSeek: invalid whence: %d", whence);
970 return VfdCache[file].seekPos;
974 * XXX not actually used but here for completeness
980 Assert(FileIsValid(file));
981 DO_DB(elog(LOG, "FileTell %d (%s)",
982 file, VfdCache[file].fileName));
983 return VfdCache[file].seekPos;
988 FileTruncate(File file, long offset)
992 Assert(FileIsValid(file));
994 DO_DB(elog(LOG, "FileTruncate %d (%s)",
995 file, VfdCache[file].fileName));
998 returnCode = ftruncate(VfdCache[file].fd, (size_t) offset);
1004 * Routines that want to use stdio (ie, FILE*) should use AllocateFile
1005 * rather than plain fopen(). This lets fd.c deal with freeing FDs if
1006 * necessary to open the file. When done, call FreeFile rather than fclose.
1008 * Note that files that will be open for any significant length of time
1009 * should NOT be handled this way, since they cannot share kernel file
1010 * descriptors with other files; there is grave risk of running out of FDs
1011 * if anyone locks down too many FDs. Most callers of this routine are
1012 * simply reading a config file that they will read and close immediately.
1014 * fd.c will automatically close all files opened with AllocateFile at
1015 * transaction commit or abort; this prevents FD leakage if a routine
1016 * that calls AllocateFile is terminated prematurely by elog(ERROR).
1018 * Ideally this should be the *only* direct call of fopen() in the backend.
1021 AllocateFile(char *name, char *mode)
1025 DO_DB(elog(LOG, "AllocateFile: Allocated %d", numAllocatedFiles));
1027 if (numAllocatedFiles >= MAX_ALLOCATED_FILES)
1028 elog(ERROR, "AllocateFile: too many private FDs demanded");
1031 if ((file = fopen(name, mode)) != NULL)
1033 allocatedFiles[numAllocatedFiles] = file;
1034 numAllocatedFiles++;
1038 if (errno == EMFILE || errno == ENFILE)
1040 int save_errno = errno;
1042 DO_DB(elog(LOG, "AllocateFile: not enough descs, retry, er= %d",
1045 if (ReleaseLruFile())
1054 FreeFile(FILE *file)
1058 DO_DB(elog(LOG, "FreeFile: Allocated %d", numAllocatedFiles));
1060 /* Remove file from list of allocated files, if it's present */
1061 for (i = numAllocatedFiles; --i >= 0;)
1063 if (allocatedFiles[i] == file)
1065 numAllocatedFiles--;
1066 allocatedFiles[i] = allocatedFiles[numAllocatedFiles];
1071 elog(WARNING, "FreeFile: file was not obtained from AllocateFile");
1079 * Force all VFDs into the physically-closed state, so that the fewest
1080 * possible number of kernel file descriptors are in use. There is no
1081 * change in the logical state of the VFDs.
1088 if (SizeVfdCache > 0)
1090 Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
1091 for (i = 1; i < SizeVfdCache; i++)
1093 if (!FileIsNotOpen(i))
1102 * This routine is called during transaction commit or abort or backend
1103 * exit (it doesn't particularly care which). All still-open temporary-file
1104 * VFDs are closed, which also causes the underlying files to be deleted.
1105 * Furthermore, all "allocated" stdio files are closed.
1108 AtEOXact_Files(void)
1112 if (SizeVfdCache > 0)
1114 Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
1115 for (i = 1; i < SizeVfdCache; i++)
1117 if ((VfdCache[i].fdstate & FD_TEMPORARY) &&
1118 VfdCache[i].fileName != NULL)
1123 while (numAllocatedFiles > 0)
1124 FreeFile(allocatedFiles[0]);
1127 * Reset the tempfile name counter to 0; not really necessary, but
1128 * helps keep the names from growing unreasonably long.
1130 tempFileCounter = 0;
1135 * Remove old temporary files
1137 * This should be called during postmaster startup. It will forcibly
1138 * remove any leftover files created by OpenTemporaryFile.
1141 RemovePgTempFiles(void)
1143 char db_path[MAXPGPATH];
1144 char temp_path[MAXPGPATH];
1145 char rm_path[MAXPGPATH];
1148 struct dirent *db_de;
1149 struct dirent *temp_de;
1152 * Cycle through pg_tempfiles for all databases and remove old temp
1155 snprintf(db_path, sizeof(db_path), "%s/base", DataDir);
1156 if ((db_dir = opendir(db_path)) != NULL)
1158 while ((db_de = readdir(db_dir)) != NULL)
1160 if (strcmp(db_de->d_name, ".") == 0 ||
1161 strcmp(db_de->d_name, "..") == 0)
1164 snprintf(temp_path, sizeof(temp_path),
1166 db_path, db_de->d_name,
1168 if ((temp_dir = opendir(temp_path)) != NULL)
1170 while ((temp_de = readdir(temp_dir)) != NULL)
1172 if (strcmp(temp_de->d_name, ".") == 0 ||
1173 strcmp(temp_de->d_name, "..") == 0)
1176 snprintf(rm_path, sizeof(temp_path),
1178 db_path, db_de->d_name,
1182 if (strncmp(temp_de->d_name,
1183 PG_TEMP_FILE_PREFIX,
1184 strlen(PG_TEMP_FILE_PREFIX)) == 0)
1189 * would prefer to use elog here, but it's not up
1190 * and running during postmaster startup...
1193 "Unexpected file found in temporary-files directory: %s\n",