1 /*-------------------------------------------------------------------------
4 * Virtual file descriptor code.
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.56 2000/04/12 17:15:35 momjian 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 *-------------------------------------------------------------------------
41 #include <sys/types.h>
43 #include <sys/param.h>
50 #include "miscadmin.h"
51 #include "storage/fd.h"
52 #include "storage/ipc.h"
55 * Problem: Postgres does a system(ld...) to do dynamic loading.
56 * This will open several extra files in addition to those used by
57 * Postgres. We need to guarantee that there are file descriptors free
60 * The current solution is to limit the number of file descriptors
61 * that this code will allocate at one time: it leaves RESERVE_FOR_LD free.
63 * (Even though most dynamic loaders now use dlopen(3) or the
64 * equivalent, the OS must still open several files to perform the
65 * dynamic loading. Keep this here.)
67 #ifndef RESERVE_FOR_LD
68 #define RESERVE_FOR_LD 10
72 * We need to ensure that we have at least some file descriptors
73 * available to postgreSQL after we've reserved the ones for LD,
74 * so we set that value here.
76 * I think 10 is an appropriate value so that's what it'll be
88 #define DO_DB(A) /* A */
91 #define VFD_CLOSED (-1)
93 #define FileIsValid(file) \
94 ((file) > 0 && (file) < (int) SizeVfdCache && VfdCache[file].fileName != NULL)
96 #define FileIsNotOpen(file) (VfdCache[file].fd == VFD_CLOSED)
100 signed short fd; /* current FD, or VFD_CLOSED if none */
101 unsigned short fdstate; /* bitflags for VFD's state */
103 /* these are the assigned bits in fdstate: */
104 #define FD_DIRTY (1 << 0)/* written to, but not yet fsync'd */
105 #define FD_TEMPORARY (1 << 1)/* should be unlinked when closed */
107 File nextFree; /* link to next free VFD, if in freelist */
108 File lruMoreRecently;/* doubly linked recency-of-use list */
109 File lruLessRecently;
110 long seekPos; /* current logical file position */
111 char *fileName; /* name of file, or NULL for unused VFD */
112 /* NB: fileName is malloc'd, and must be free'd when closing the VFD */
113 int fileFlags; /* open(2) flags for opening the file */
114 int fileMode; /* mode to pass to open(2) */
118 * Virtual File Descriptor array pointer and size. This grows as
119 * needed. 'File' values are indexes into this array.
120 * Note that VfdCache[0] is not a usable VFD, just a list header.
122 static Vfd *VfdCache;
123 static Size SizeVfdCache = 0;
126 * Number of file descriptors known to be in use by VFD entries.
128 static int nfile = 0;
131 * List of stdio FILEs opened with AllocateFile.
133 * Since we don't want to encourage heavy use of AllocateFile, it seems
134 * OK to put a pretty small maximum limit on the number of simultaneously
137 #define MAX_ALLOCATED_FILES 32
139 static int numAllocatedFiles = 0;
140 static FILE *allocatedFiles[MAX_ALLOCATED_FILES];
143 * Number of temporary files opened during the current transaction;
144 * this is used in generation of tempfile names.
146 static long tempFileCounter = 0;
149 /*--------------------
153 * Delete - delete a file from the Lru ring
154 * LruDelete - remove a file from the Lru ring and close its FD
155 * Insert - put a file at the front of the Lru ring
156 * LruInsert - put a file at the front of the Lru ring and open it
157 * ReleaseLruFile - Release an fd by closing the last entry in the Lru ring
158 * AllocateVfd - grab a free (or new) file record (from VfdArray)
159 * FreeVfd - free a file record
161 * The Least Recently Used ring is a doubly linked list that begins and
162 * ends on element zero. Element zero is special -- it doesn't represent
163 * a file and its "fd" field always == VFD_CLOSED. Element zero is just an
164 * anchor that shows us the beginning/end of the ring.
165 * Only VFD elements that are currently really open (have an FD assigned) are
166 * in the Lru ring. Elements that are "virtually" open can be recognized
167 * by having a non-null fileName field.
171 * /--less----\ /---------\
173 * #0 --more---> LeastRecentlyUsed --more-\ \
175 * \\less--> MostRecentlyUsedFile <---/ |
176 * \more---/ \--less--/
178 *--------------------
180 static void Delete(File file);
181 static void LruDelete(File file);
182 static void Insert(File file);
183 static int LruInsert(File file);
184 static void ReleaseLruFile(void);
185 static File AllocateVfd(void);
186 static void FreeVfd(File file);
188 static int FileAccess(File file);
189 static File fileNameOpenFile(FileName fileName, int fileFlags, int fileMode);
190 static char *filepath(char *filename);
191 static long pg_nofile(void);
194 * pg_fsync --- same as fsync except does nothing if -F switch was given
199 return disableFsync ? 0 : fsync(fd);
203 * pg_nofile: determine number of filedescriptors that fd.c is allowed to use
208 static long no_files = 0;
212 /* need do this calculation only once */
214 no_files = (long) NOFILE;
216 no_files = sysconf(_SC_OPEN_MAX);
219 elog(DEBUG, "pg_nofile: Unable to get _SC_OPEN_MAX using sysconf(); using %d", NOFILE);
220 no_files = (long) NOFILE;
224 if ((no_files - RESERVE_FOR_LD) < FD_MINFREE)
225 elog(FATAL, "pg_nofile: insufficient File Descriptors in postmaster to start backend (%ld).\n"
226 " O/S allows %ld, Postmaster reserves %d, We need %d (MIN) after that.",
227 no_files - RESERVE_FOR_LD, no_files, RESERVE_FOR_LD, FD_MINFREE);
229 no_files -= RESERVE_FOR_LD;
240 int mru = VfdCache[0].lruLessRecently;
241 Vfd *vfdP = &VfdCache[mru];
244 sprintf(buf, "LRU: MOST %d ", mru);
247 mru = vfdP->lruLessRecently;
248 vfdP = &VfdCache[mru];
249 sprintf(buf + strlen(buf), "%d ", mru);
251 sprintf(buf + strlen(buf), "LEAST");
264 DO_DB(elog(DEBUG, "Delete %d (%s)",
265 file, VfdCache[file].fileName));
268 vfdP = &VfdCache[file];
270 VfdCache[vfdP->lruLessRecently].lruMoreRecently = vfdP->lruMoreRecently;
271 VfdCache[vfdP->lruMoreRecently].lruLessRecently = vfdP->lruLessRecently;
284 DO_DB(elog(DEBUG, "LruDelete %d (%s)",
285 file, VfdCache[file].fileName));
287 vfdP = &VfdCache[file];
289 /* delete the vfd record from the LRU ring */
292 /* save the seek position */
293 vfdP->seekPos = (long) lseek(vfdP->fd, 0L, SEEK_CUR);
294 Assert(vfdP->seekPos != -1);
296 /* if we have written to the file, sync it before closing */
297 if (vfdP->fdstate & FD_DIRTY)
299 returnValue = pg_fsync(vfdP->fd);
300 Assert(returnValue != -1);
301 vfdP->fdstate &= ~FD_DIRTY;
305 returnValue = close(vfdP->fd);
306 Assert(returnValue != -1);
309 vfdP->fd = VFD_CLOSED;
319 DO_DB(elog(DEBUG, "Insert %d (%s)",
320 file, VfdCache[file].fileName));
323 vfdP = &VfdCache[file];
325 vfdP->lruMoreRecently = 0;
326 vfdP->lruLessRecently = VfdCache[0].lruLessRecently;
327 VfdCache[0].lruLessRecently = file;
328 VfdCache[vfdP->lruLessRecently].lruMoreRecently = file;
341 DO_DB(elog(DEBUG, "LruInsert %d (%s)",
342 file, VfdCache[file].fileName));
344 vfdP = &VfdCache[file];
346 if (FileIsNotOpen(file))
349 while (nfile + numAllocatedFiles >= pg_nofile())
353 * The open could still fail for lack of file descriptors, eg due
354 * to overall system file table being full. So, be prepared to
355 * release another FD if necessary...
358 vfdP->fd = open(vfdP->fileName, vfdP->fileFlags, vfdP->fileMode);
359 if (vfdP->fd < 0 && (errno == EMFILE || errno == ENFILE))
368 DO_DB(elog(DEBUG, "RE_OPEN FAILED: %d",
374 DO_DB(elog(DEBUG, "RE_OPEN SUCCESS"));
378 /* seek to the right position */
379 if (vfdP->seekPos != 0L)
381 returnValue = lseek(vfdP->fd, vfdP->seekPos, SEEK_SET);
382 Assert(returnValue != -1);
387 * put it at the head of the Lru ring
398 DO_DB(elog(DEBUG, "ReleaseLruFile. Opened %d", nfile));
401 elog(ERROR, "ReleaseLruFile: No open files available to be closed");
404 * There are opened files and so there should be at least one used vfd
407 Assert(VfdCache[0].lruMoreRecently != 0);
408 LruDelete(VfdCache[0].lruMoreRecently);
412 * Force one kernel file descriptor to be released (temporarily).
417 DO_DB(elog(DEBUG, "ReleaseDataFile. Opened %d", nfile));
421 Assert(VfdCache[0].lruMoreRecently != 0);
422 LruDelete(VfdCache[0].lruMoreRecently);
433 DO_DB(elog(DEBUG, "AllocateVfd. Size %d", SizeVfdCache));
435 if (SizeVfdCache == 0)
437 /* initialize header entry first time through */
438 VfdCache = (Vfd *) malloc(sizeof(Vfd));
439 Assert(VfdCache != NULL);
440 MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
441 VfdCache->fd = VFD_CLOSED;
446 * register proc-exit call to ensure temp files are dropped at
449 on_proc_exit(AtEOXact_Files, NULL);
452 if (VfdCache[0].nextFree == 0)
456 * The free list is empty so it is time to increase the size of
457 * the array. We choose to double it each time this happens.
458 * However, there's not much point in starting *real* small.
460 Size newCacheSize = SizeVfdCache * 2;
462 if (newCacheSize < 32)
465 VfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize);
466 Assert(VfdCache != NULL);
469 * Initialize the new entries and link them into the free list.
472 for (i = SizeVfdCache; i < newCacheSize; i++)
474 MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
475 VfdCache[i].nextFree = i + 1;
476 VfdCache[i].fd = VFD_CLOSED;
478 VfdCache[newCacheSize - 1].nextFree = 0;
479 VfdCache[0].nextFree = SizeVfdCache;
482 * Record the new size
485 SizeVfdCache = newCacheSize;
488 file = VfdCache[0].nextFree;
490 VfdCache[0].nextFree = VfdCache[file].nextFree;
498 Vfd *vfdP = &VfdCache[file];
500 DO_DB(elog(DEBUG, "FreeVfd: %d (%s)",
501 file, vfdP->fileName ? vfdP->fileName : ""));
503 if (vfdP->fileName != NULL)
505 free(vfdP->fileName);
506 vfdP->fileName = NULL;
509 vfdP->nextFree = VfdCache[0].nextFree;
510 VfdCache[0].nextFree = file;
514 * Convert given pathname to absolute.
516 * (Generally, this isn't actually necessary, considering that we
517 * should be cd'd into the database directory. Presently it is only
518 * necessary to do it in "bootstrap" mode. Maybe we should change
519 * bootstrap mode to do the cd, and save a few cycles/bytes here.)
522 filepath(char *filename)
527 /* Not an absolute path name? Then fill in with database path... */
528 if (*filename != SEP_CHAR)
530 len = strlen(DatabasePath) + strlen(filename) + 2;
531 buf = (char *) palloc(len);
532 sprintf(buf, "%s%c%s", DatabasePath, SEP_CHAR, filename);
536 buf = (char *) palloc(strlen(filename) + 1);
537 strcpy(buf, filename);
541 printf("filepath: path is %s\n", buf);
548 FileAccess(File file)
552 DO_DB(elog(DEBUG, "FileAccess %d (%s)",
553 file, VfdCache[file].fileName));
556 * Is the file open? If not, open it and put it at the head of the
557 * LRU ring (possibly closing the least recently used file to get an
561 if (FileIsNotOpen(file))
563 returnValue = LruInsert(file);
564 if (returnValue != 0)
567 else if (VfdCache[0].lruLessRecently != file)
571 * We now know that the file is open and that it is not the last
572 * one accessed, so we need to move it to the head of the Lru
584 * Called when we get a shared invalidation message on some relation.
588 FileInvalidate(File file)
590 Assert(FileIsValid(file));
591 if (!FileIsNotOpen(file))
598 fileNameOpenFile(FileName fileName,
605 if (fileName == NULL)
606 elog(ERROR, "fileNameOpenFile: NULL fname");
608 DO_DB(elog(DEBUG, "fileNameOpenFile: %s %x %o",
609 fileName, fileFlags, fileMode));
611 file = AllocateVfd();
612 vfdP = &VfdCache[file];
614 while (nfile + numAllocatedFiles >= pg_nofile())
618 vfdP->fd = open(fileName, fileFlags, fileMode);
619 if (vfdP->fd < 0 && (errno == EMFILE || errno == ENFILE))
621 DO_DB(elog(DEBUG, "fileNameOpenFile: not enough descs, retry, er= %d",
634 DO_DB(elog(DEBUG, "fileNameOpenFile: success %d",
639 vfdP->fileName = malloc(strlen(fileName) + 1);
640 strcpy(vfdP->fileName, fileName);
642 vfdP->fileFlags = fileFlags & ~(O_TRUNC | O_EXCL);
643 vfdP->fileMode = fileMode;
651 * open a file in the database directory ($PGDATA/base/...)
654 FileNameOpenFile(FileName fileName, int fileFlags, int fileMode)
659 fname = filepath(fileName);
660 fd = fileNameOpenFile(fname, fileFlags, fileMode);
666 * open a file in an arbitrary directory
669 PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
671 return fileNameOpenFile(fileName, fileFlags, fileMode);
675 * Open a temporary file that will disappear when we close it.
677 * This routine takes care of generating an appropriate tempfile name.
678 * There's no need to pass in fileFlags or fileMode either, since only
679 * one setting makes any sense for a temp file.
682 OpenTemporaryFile(void)
684 char tempfilename[64];
688 * Generate a tempfile name that's unique within the current
691 snprintf(tempfilename, sizeof(tempfilename),
692 "pg_sorttemp%d.%ld", MyProcPid, tempFileCounter++);
696 file = FileNameOpenFile(tempfilename,
697 O_RDWR | O_CREAT | O_TRUNC, 0600);
699 file = FileNameOpenFile(tempfilename,
700 O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600);
704 elog(ERROR, "Failed to create temporary file %s", tempfilename);
706 /* Mark it for deletion at close or EOXact */
707 VfdCache[file].fdstate |= FD_TEMPORARY;
713 * close a file when done with it
720 Assert(FileIsValid(file));
722 DO_DB(elog(DEBUG, "FileClose: %d (%s)",
723 file, VfdCache[file].fileName));
725 if (!FileIsNotOpen(file))
728 /* remove the file from the lru ring */
731 /* if we did any writes, sync the file before closing */
732 if (VfdCache[file].fdstate & FD_DIRTY)
734 returnValue = pg_fsync(VfdCache[file].fd);
735 Assert(returnValue != -1);
736 VfdCache[file].fdstate &= ~FD_DIRTY;
740 returnValue = close(VfdCache[file].fd);
741 Assert(returnValue != -1);
744 VfdCache[file].fd = VFD_CLOSED;
748 * Delete the file if it was temporary
750 if (VfdCache[file].fdstate & FD_TEMPORARY)
751 unlink(VfdCache[file].fileName);
754 * Return the Vfd slot to the free list
760 * close a file and forcibly delete the underlying Unix file
763 FileUnlink(File file)
765 Assert(FileIsValid(file));
767 DO_DB(elog(DEBUG, "FileUnlink: %d (%s)",
768 file, VfdCache[file].fileName));
770 /* force FileClose to delete it */
771 VfdCache[file].fdstate |= FD_TEMPORARY;
777 FileRead(File file, char *buffer, int amount)
781 Assert(FileIsValid(file));
783 DO_DB(elog(DEBUG, "FileRead: %d (%s) %d %p",
784 file, VfdCache[file].fileName, amount, buffer));
787 returnCode = read(VfdCache[file].fd, buffer, amount);
789 VfdCache[file].seekPos += returnCode;
795 FileWrite(File file, char *buffer, int amount)
799 Assert(FileIsValid(file));
801 DO_DB(elog(DEBUG, "FileWrite: %d (%s) %d %p",
802 file, VfdCache[file].fileName, amount, buffer));
805 returnCode = write(VfdCache[file].fd, buffer, amount);
807 VfdCache[file].seekPos += returnCode;
809 /* mark the file as needing fsync */
810 VfdCache[file].fdstate |= FD_DIRTY;
816 FileSeek(File file, long offset, int whence)
818 Assert(FileIsValid(file));
820 DO_DB(elog(DEBUG, "FileSeek: %d (%s) %ld %d",
821 file, VfdCache[file].fileName, offset, whence));
823 if (FileIsNotOpen(file))
828 VfdCache[file].seekPos = offset;
831 VfdCache[file].seekPos += offset;
835 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
838 elog(ERROR, "FileSeek: invalid whence: %d", whence);
843 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
844 return VfdCache[file].seekPos;
848 * XXX not actually used but here for completeness
854 Assert(FileIsValid(file));
855 DO_DB(elog(DEBUG, "FileTell %d (%s)",
856 file, VfdCache[file].fileName));
857 return VfdCache[file].seekPos;
863 FileTruncate(File file, long offset)
867 Assert(FileIsValid(file));
869 DO_DB(elog(DEBUG, "FileTruncate %d (%s)",
870 file, VfdCache[file].fileName));
874 returnCode = ftruncate(VfdCache[file].fd, (size_t) offset);
879 * FileSync --- if a file is marked as dirty, fsync it.
881 * The FD_DIRTY bit is slightly misnamed: it doesn't mean that we need to
882 * write the file, but that we *have* written it and need to execute an
883 * fsync() to ensure the changes are down on disk before we mark the current
884 * transaction committed.
886 * FD_DIRTY is set by FileWrite or by an explicit FileMarkDirty() call.
887 * It is cleared after successfully fsync'ing the file. FileClose() will
888 * fsync a dirty File that is about to be closed, since there will be no
889 * other place to remember the need to fsync after the VFD is gone.
891 * Note that the DIRTY bit is logically associated with the actual disk file,
892 * not with any particular kernel FD we might have open for it. We assume
893 * that fsync will force out any dirty buffers for that file, whether or not
894 * they were written through the FD being used for the fsync call --- they
895 * might even have been written by some other backend!
897 * Note also that LruDelete currently fsyncs a dirty file that it is about
898 * to close the kernel file descriptor for. The idea there is to avoid
899 * having to re-open the kernel descriptor later. But it's not real clear
900 * that this is a performance win; we could end up fsyncing the same file
901 * multiple times in a transaction, which would probably cost more time
902 * than is saved by avoiding an open() call. This should be studied.
904 * This routine used to think it could skip the fsync if the file is
905 * physically closed, but that is now WRONG; see comments for FileMarkDirty.
912 Assert(FileIsValid(file));
914 if (!(VfdCache[file].fdstate & FD_DIRTY))
916 /* Need not sync if file is not dirty. */
919 else if (disableFsync)
921 /* Don't force the file open if pg_fsync isn't gonna sync it. */
923 VfdCache[file].fdstate &= ~FD_DIRTY;
929 * We don't use FileAccess() because we don't want to force the
930 * file to the front of the LRU ring; we aren't expecting to
931 * access it again soon.
933 if (FileIsNotOpen(file))
935 returnCode = LruInsert(file);
939 returnCode = pg_fsync(VfdCache[file].fd);
941 VfdCache[file].fdstate &= ~FD_DIRTY;
948 * FileMarkDirty --- mark a file as needing fsync at transaction commit.
950 * Since FileWrite marks the file dirty, this routine is not needed in
951 * normal use. It is called when the buffer manager detects that some other
952 * backend has written out a shared buffer that this backend dirtied (but
953 * didn't write) in the current xact. In that scenario, we need to fsync
954 * the file before we can commit. We cannot assume that the other backend
955 * has fsync'd the file yet; we need to do our own fsync to ensure that
956 * (a) the disk page is written and (b) this backend's commit is delayed
957 * until the write is complete.
959 * Note we are assuming that an fsync issued by this backend will write
960 * kernel disk buffers that were dirtied by another backend. Furthermore,
961 * it doesn't matter whether we currently have the file physically open;
962 * we must fsync even if we have to re-open the file to do it.
965 FileMarkDirty(File file)
967 Assert(FileIsValid(file));
969 DO_DB(elog(DEBUG, "FileMarkDirty: %d (%s)",
970 file, VfdCache[file].fileName));
972 VfdCache[file].fdstate |= FD_DIRTY;
977 * Routines that want to use stdio (ie, FILE*) should use AllocateFile
978 * rather than plain fopen(). This lets fd.c deal with freeing FDs if
979 * necessary to open the file. When done, call FreeFile rather than fclose.
981 * Note that files that will be open for any significant length of time
982 * should NOT be handled this way, since they cannot share kernel file
983 * descriptors with other files; there is grave risk of running out of FDs
984 * if anyone locks down too many FDs. Most callers of this routine are
985 * simply reading a config file that they will read and close immediately.
987 * fd.c will automatically close all files opened with AllocateFile at
988 * transaction commit or abort; this prevents FD leakage if a routine
989 * that calls AllocateFile is terminated prematurely by elog(ERROR).
993 AllocateFile(char *name, char *mode)
997 DO_DB(elog(DEBUG, "AllocateFile: Allocated %d.", numAllocatedFiles));
999 if (numAllocatedFiles >= MAX_ALLOCATED_FILES)
1000 elog(ERROR, "AllocateFile: too many private FDs demanded");
1003 if ((file = fopen(name, mode)) == NULL)
1005 if (errno == EMFILE || errno == ENFILE)
1007 DO_DB(elog(DEBUG, "AllocateFile: not enough descs, retry, er= %d",
1015 allocatedFiles[numAllocatedFiles++] = file;
1020 FreeFile(FILE *file)
1024 DO_DB(elog(DEBUG, "FreeFile: Allocated %d.", numAllocatedFiles));
1026 /* Remove file from list of allocated files, if it's present */
1027 for (i = numAllocatedFiles; --i >= 0;)
1029 if (allocatedFiles[i] == file)
1031 allocatedFiles[i] = allocatedFiles[--numAllocatedFiles];
1036 elog(NOTICE, "FreeFile: file was not obtained from AllocateFile");
1044 * Force all VFDs into the physically-closed state, so that the fewest
1045 * possible number of kernel file descriptors are in use. There is no
1046 * change in the logical state of the VFDs.
1053 if (SizeVfdCache > 0)
1055 Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
1056 for (i = 1; i < SizeVfdCache; i++)
1058 if (!FileIsNotOpen(i))
1067 * This routine is called during transaction commit or abort or backend
1068 * exit (it doesn't particularly care which). All still-open temporary-file
1069 * VFDs are closed, which also causes the underlying files to be deleted.
1070 * Furthermore, all "allocated" stdio files are closed.
1072 * This routine is not involved in fsync'ing non-temporary files at xact
1073 * commit; that is done by FileSync under control of the buffer manager.
1074 * During a commit, that is done *before* control gets here. If we still
1075 * have any needs-fsync bits set when we get here, we assume this is abort
1079 AtEOXact_Files(void)
1083 if (SizeVfdCache > 0)
1085 Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
1086 for (i = 1; i < SizeVfdCache; i++)
1088 if ((VfdCache[i].fdstate & FD_TEMPORARY) &&
1089 VfdCache[i].fileName != NULL)
1092 VfdCache[i].fdstate &= ~FD_DIRTY;
1096 while (numAllocatedFiles > 0)
1097 FreeFile(allocatedFiles[0]);
1100 * Reset the tempfile name counter to 0; not really necessary, but
1101 * helps keep the names from growing unreasonably long.
1103 tempFileCounter = 0;