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.57 2000/05/31 00:28:27 petere 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
206 * pg_nofile: determine number of filedescriptors that fd.c is allowed to use
211 static long no_files = 0;
215 /* need do this calculation only once */
217 no_files = (long) NOFILE;
219 no_files = sysconf(_SC_OPEN_MAX);
222 elog(DEBUG, "pg_nofile: Unable to get _SC_OPEN_MAX using sysconf(); using %d", NOFILE);
223 no_files = (long) NOFILE;
227 if ((no_files - RESERVE_FOR_LD) < FD_MINFREE)
228 elog(FATAL, "pg_nofile: insufficient File Descriptors in postmaster to start backend (%ld).\n"
229 " O/S allows %ld, Postmaster reserves %d, We need %d (MIN) after that.",
230 no_files - RESERVE_FOR_LD, no_files, RESERVE_FOR_LD, FD_MINFREE);
232 no_files -= RESERVE_FOR_LD;
243 int mru = VfdCache[0].lruLessRecently;
244 Vfd *vfdP = &VfdCache[mru];
247 sprintf(buf, "LRU: MOST %d ", mru);
250 mru = vfdP->lruLessRecently;
251 vfdP = &VfdCache[mru];
252 sprintf(buf + strlen(buf), "%d ", mru);
254 sprintf(buf + strlen(buf), "LEAST");
267 DO_DB(elog(DEBUG, "Delete %d (%s)",
268 file, VfdCache[file].fileName));
271 vfdP = &VfdCache[file];
273 VfdCache[vfdP->lruLessRecently].lruMoreRecently = vfdP->lruMoreRecently;
274 VfdCache[vfdP->lruMoreRecently].lruLessRecently = vfdP->lruLessRecently;
287 DO_DB(elog(DEBUG, "LruDelete %d (%s)",
288 file, VfdCache[file].fileName));
290 vfdP = &VfdCache[file];
292 /* delete the vfd record from the LRU ring */
295 /* save the seek position */
296 vfdP->seekPos = (long) lseek(vfdP->fd, 0L, SEEK_CUR);
297 Assert(vfdP->seekPos != -1);
299 /* if we have written to the file, sync it before closing */
300 if (vfdP->fdstate & FD_DIRTY)
302 returnValue = pg_fsync(vfdP->fd);
303 Assert(returnValue != -1);
304 vfdP->fdstate &= ~FD_DIRTY;
308 returnValue = close(vfdP->fd);
309 Assert(returnValue != -1);
312 vfdP->fd = VFD_CLOSED;
322 DO_DB(elog(DEBUG, "Insert %d (%s)",
323 file, VfdCache[file].fileName));
326 vfdP = &VfdCache[file];
328 vfdP->lruMoreRecently = 0;
329 vfdP->lruLessRecently = VfdCache[0].lruLessRecently;
330 VfdCache[0].lruLessRecently = file;
331 VfdCache[vfdP->lruLessRecently].lruMoreRecently = file;
344 DO_DB(elog(DEBUG, "LruInsert %d (%s)",
345 file, VfdCache[file].fileName));
347 vfdP = &VfdCache[file];
349 if (FileIsNotOpen(file))
352 while (nfile + numAllocatedFiles >= pg_nofile())
356 * The open could still fail for lack of file descriptors, eg due
357 * to overall system file table being full. So, be prepared to
358 * release another FD if necessary...
361 vfdP->fd = open(vfdP->fileName, vfdP->fileFlags, vfdP->fileMode);
362 if (vfdP->fd < 0 && (errno == EMFILE || errno == ENFILE))
371 DO_DB(elog(DEBUG, "RE_OPEN FAILED: %d",
377 DO_DB(elog(DEBUG, "RE_OPEN SUCCESS"));
381 /* seek to the right position */
382 if (vfdP->seekPos != 0L)
384 returnValue = lseek(vfdP->fd, vfdP->seekPos, SEEK_SET);
385 Assert(returnValue != -1);
390 * put it at the head of the Lru ring
401 DO_DB(elog(DEBUG, "ReleaseLruFile. Opened %d", nfile));
404 elog(ERROR, "ReleaseLruFile: No open files available to be closed");
407 * There are opened files and so there should be at least one used vfd
410 Assert(VfdCache[0].lruMoreRecently != 0);
411 LruDelete(VfdCache[0].lruMoreRecently);
415 * Force one kernel file descriptor to be released (temporarily).
420 DO_DB(elog(DEBUG, "ReleaseDataFile. Opened %d", nfile));
424 Assert(VfdCache[0].lruMoreRecently != 0);
425 LruDelete(VfdCache[0].lruMoreRecently);
436 DO_DB(elog(DEBUG, "AllocateVfd. Size %d", SizeVfdCache));
438 if (SizeVfdCache == 0)
440 /* initialize header entry first time through */
441 VfdCache = (Vfd *) malloc(sizeof(Vfd));
442 Assert(VfdCache != NULL);
443 MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
444 VfdCache->fd = VFD_CLOSED;
449 * register proc-exit call to ensure temp files are dropped at
452 on_proc_exit(AtEOXact_Files, NULL);
455 if (VfdCache[0].nextFree == 0)
459 * The free list is empty so it is time to increase the size of
460 * the array. We choose to double it each time this happens.
461 * However, there's not much point in starting *real* small.
463 Size newCacheSize = SizeVfdCache * 2;
465 if (newCacheSize < 32)
468 VfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize);
469 Assert(VfdCache != NULL);
472 * Initialize the new entries and link them into the free list.
475 for (i = SizeVfdCache; i < newCacheSize; i++)
477 MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
478 VfdCache[i].nextFree = i + 1;
479 VfdCache[i].fd = VFD_CLOSED;
481 VfdCache[newCacheSize - 1].nextFree = 0;
482 VfdCache[0].nextFree = SizeVfdCache;
485 * Record the new size
488 SizeVfdCache = newCacheSize;
491 file = VfdCache[0].nextFree;
493 VfdCache[0].nextFree = VfdCache[file].nextFree;
501 Vfd *vfdP = &VfdCache[file];
503 DO_DB(elog(DEBUG, "FreeVfd: %d (%s)",
504 file, vfdP->fileName ? vfdP->fileName : ""));
506 if (vfdP->fileName != NULL)
508 free(vfdP->fileName);
509 vfdP->fileName = NULL;
512 vfdP->nextFree = VfdCache[0].nextFree;
513 VfdCache[0].nextFree = file;
517 * Convert given pathname to absolute.
519 * (Generally, this isn't actually necessary, considering that we
520 * should be cd'd into the database directory. Presently it is only
521 * necessary to do it in "bootstrap" mode. Maybe we should change
522 * bootstrap mode to do the cd, and save a few cycles/bytes here.)
525 filepath(char *filename)
530 /* Not an absolute path name? Then fill in with database path... */
531 if (*filename != SEP_CHAR)
533 len = strlen(DatabasePath) + strlen(filename) + 2;
534 buf = (char *) palloc(len);
535 sprintf(buf, "%s%c%s", DatabasePath, SEP_CHAR, filename);
539 buf = (char *) palloc(strlen(filename) + 1);
540 strcpy(buf, filename);
544 printf("filepath: path is %s\n", buf);
551 FileAccess(File file)
555 DO_DB(elog(DEBUG, "FileAccess %d (%s)",
556 file, VfdCache[file].fileName));
559 * Is the file open? If not, open it and put it at the head of the
560 * LRU ring (possibly closing the least recently used file to get an
564 if (FileIsNotOpen(file))
566 returnValue = LruInsert(file);
567 if (returnValue != 0)
570 else if (VfdCache[0].lruLessRecently != file)
574 * We now know that the file is open and that it is not the last
575 * one accessed, so we need to move it to the head of the Lru
587 * Called when we get a shared invalidation message on some relation.
591 FileInvalidate(File file)
593 Assert(FileIsValid(file));
594 if (!FileIsNotOpen(file))
601 fileNameOpenFile(FileName fileName,
608 if (fileName == NULL)
609 elog(ERROR, "fileNameOpenFile: NULL fname");
611 DO_DB(elog(DEBUG, "fileNameOpenFile: %s %x %o",
612 fileName, fileFlags, fileMode));
614 file = AllocateVfd();
615 vfdP = &VfdCache[file];
617 while (nfile + numAllocatedFiles >= pg_nofile())
621 vfdP->fd = open(fileName, fileFlags, fileMode);
622 if (vfdP->fd < 0 && (errno == EMFILE || errno == ENFILE))
624 DO_DB(elog(DEBUG, "fileNameOpenFile: not enough descs, retry, er= %d",
637 DO_DB(elog(DEBUG, "fileNameOpenFile: success %d",
642 vfdP->fileName = malloc(strlen(fileName) + 1);
643 strcpy(vfdP->fileName, fileName);
645 vfdP->fileFlags = fileFlags & ~(O_TRUNC | O_EXCL);
646 vfdP->fileMode = fileMode;
654 * open a file in the database directory ($PGDATA/base/...)
657 FileNameOpenFile(FileName fileName, int fileFlags, int fileMode)
662 fname = filepath(fileName);
663 fd = fileNameOpenFile(fname, fileFlags, fileMode);
669 * open a file in an arbitrary directory
672 PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
674 return fileNameOpenFile(fileName, fileFlags, fileMode);
678 * Open a temporary file that will disappear when we close it.
680 * This routine takes care of generating an appropriate tempfile name.
681 * There's no need to pass in fileFlags or fileMode either, since only
682 * one setting makes any sense for a temp file.
685 OpenTemporaryFile(void)
687 char tempfilename[64];
691 * Generate a tempfile name that's unique within the current
694 snprintf(tempfilename, sizeof(tempfilename),
695 "pg_sorttemp%d.%ld", MyProcPid, tempFileCounter++);
699 file = FileNameOpenFile(tempfilename,
700 O_RDWR | O_CREAT | O_TRUNC, 0600);
702 file = FileNameOpenFile(tempfilename,
703 O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600);
707 elog(ERROR, "Failed to create temporary file %s", tempfilename);
709 /* Mark it for deletion at close or EOXact */
710 VfdCache[file].fdstate |= FD_TEMPORARY;
716 * close a file when done with it
723 Assert(FileIsValid(file));
725 DO_DB(elog(DEBUG, "FileClose: %d (%s)",
726 file, VfdCache[file].fileName));
728 if (!FileIsNotOpen(file))
731 /* remove the file from the lru ring */
734 /* if we did any writes, sync the file before closing */
735 if (VfdCache[file].fdstate & FD_DIRTY)
737 returnValue = pg_fsync(VfdCache[file].fd);
738 Assert(returnValue != -1);
739 VfdCache[file].fdstate &= ~FD_DIRTY;
743 returnValue = close(VfdCache[file].fd);
744 Assert(returnValue != -1);
747 VfdCache[file].fd = VFD_CLOSED;
751 * Delete the file if it was temporary
753 if (VfdCache[file].fdstate & FD_TEMPORARY)
754 unlink(VfdCache[file].fileName);
757 * Return the Vfd slot to the free list
763 * close a file and forcibly delete the underlying Unix file
766 FileUnlink(File file)
768 Assert(FileIsValid(file));
770 DO_DB(elog(DEBUG, "FileUnlink: %d (%s)",
771 file, VfdCache[file].fileName));
773 /* force FileClose to delete it */
774 VfdCache[file].fdstate |= FD_TEMPORARY;
780 FileRead(File file, char *buffer, int amount)
784 Assert(FileIsValid(file));
786 DO_DB(elog(DEBUG, "FileRead: %d (%s) %d %p",
787 file, VfdCache[file].fileName, amount, buffer));
790 returnCode = read(VfdCache[file].fd, buffer, amount);
792 VfdCache[file].seekPos += returnCode;
798 FileWrite(File file, char *buffer, int amount)
802 Assert(FileIsValid(file));
804 DO_DB(elog(DEBUG, "FileWrite: %d (%s) %d %p",
805 file, VfdCache[file].fileName, amount, buffer));
808 returnCode = write(VfdCache[file].fd, buffer, amount);
810 VfdCache[file].seekPos += returnCode;
812 /* mark the file as needing fsync */
813 VfdCache[file].fdstate |= FD_DIRTY;
819 FileSeek(File file, long offset, int whence)
821 Assert(FileIsValid(file));
823 DO_DB(elog(DEBUG, "FileSeek: %d (%s) %ld %d",
824 file, VfdCache[file].fileName, offset, whence));
826 if (FileIsNotOpen(file))
831 VfdCache[file].seekPos = offset;
834 VfdCache[file].seekPos += offset;
838 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
841 elog(ERROR, "FileSeek: invalid whence: %d", whence);
846 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
847 return VfdCache[file].seekPos;
851 * XXX not actually used but here for completeness
857 Assert(FileIsValid(file));
858 DO_DB(elog(DEBUG, "FileTell %d (%s)",
859 file, VfdCache[file].fileName));
860 return VfdCache[file].seekPos;
866 FileTruncate(File file, long offset)
870 Assert(FileIsValid(file));
872 DO_DB(elog(DEBUG, "FileTruncate %d (%s)",
873 file, VfdCache[file].fileName));
877 returnCode = ftruncate(VfdCache[file].fd, (size_t) offset);
882 * FileSync --- if a file is marked as dirty, fsync it.
884 * The FD_DIRTY bit is slightly misnamed: it doesn't mean that we need to
885 * write the file, but that we *have* written it and need to execute an
886 * fsync() to ensure the changes are down on disk before we mark the current
887 * transaction committed.
889 * FD_DIRTY is set by FileWrite or by an explicit FileMarkDirty() call.
890 * It is cleared after successfully fsync'ing the file. FileClose() will
891 * fsync a dirty File that is about to be closed, since there will be no
892 * other place to remember the need to fsync after the VFD is gone.
894 * Note that the DIRTY bit is logically associated with the actual disk file,
895 * not with any particular kernel FD we might have open for it. We assume
896 * that fsync will force out any dirty buffers for that file, whether or not
897 * they were written through the FD being used for the fsync call --- they
898 * might even have been written by some other backend!
900 * Note also that LruDelete currently fsyncs a dirty file that it is about
901 * to close the kernel file descriptor for. The idea there is to avoid
902 * having to re-open the kernel descriptor later. But it's not real clear
903 * that this is a performance win; we could end up fsyncing the same file
904 * multiple times in a transaction, which would probably cost more time
905 * than is saved by avoiding an open() call. This should be studied.
907 * This routine used to think it could skip the fsync if the file is
908 * physically closed, but that is now WRONG; see comments for FileMarkDirty.
915 Assert(FileIsValid(file));
917 if (!(VfdCache[file].fdstate & FD_DIRTY))
919 /* Need not sync if file is not dirty. */
922 else if (!enableFsync)
924 /* Don't force the file open if pg_fsync isn't gonna sync it. */
926 VfdCache[file].fdstate &= ~FD_DIRTY;
932 * We don't use FileAccess() because we don't want to force the
933 * file to the front of the LRU ring; we aren't expecting to
934 * access it again soon.
936 if (FileIsNotOpen(file))
938 returnCode = LruInsert(file);
942 returnCode = pg_fsync(VfdCache[file].fd);
944 VfdCache[file].fdstate &= ~FD_DIRTY;
951 * FileMarkDirty --- mark a file as needing fsync at transaction commit.
953 * Since FileWrite marks the file dirty, this routine is not needed in
954 * normal use. It is called when the buffer manager detects that some other
955 * backend has written out a shared buffer that this backend dirtied (but
956 * didn't write) in the current xact. In that scenario, we need to fsync
957 * the file before we can commit. We cannot assume that the other backend
958 * has fsync'd the file yet; we need to do our own fsync to ensure that
959 * (a) the disk page is written and (b) this backend's commit is delayed
960 * until the write is complete.
962 * Note we are assuming that an fsync issued by this backend will write
963 * kernel disk buffers that were dirtied by another backend. Furthermore,
964 * it doesn't matter whether we currently have the file physically open;
965 * we must fsync even if we have to re-open the file to do it.
968 FileMarkDirty(File file)
970 Assert(FileIsValid(file));
972 DO_DB(elog(DEBUG, "FileMarkDirty: %d (%s)",
973 file, VfdCache[file].fileName));
975 VfdCache[file].fdstate |= FD_DIRTY;
980 * Routines that want to use stdio (ie, FILE*) should use AllocateFile
981 * rather than plain fopen(). This lets fd.c deal with freeing FDs if
982 * necessary to open the file. When done, call FreeFile rather than fclose.
984 * Note that files that will be open for any significant length of time
985 * should NOT be handled this way, since they cannot share kernel file
986 * descriptors with other files; there is grave risk of running out of FDs
987 * if anyone locks down too many FDs. Most callers of this routine are
988 * simply reading a config file that they will read and close immediately.
990 * fd.c will automatically close all files opened with AllocateFile at
991 * transaction commit or abort; this prevents FD leakage if a routine
992 * that calls AllocateFile is terminated prematurely by elog(ERROR).
996 AllocateFile(char *name, char *mode)
1000 DO_DB(elog(DEBUG, "AllocateFile: Allocated %d.", numAllocatedFiles));
1002 if (numAllocatedFiles >= MAX_ALLOCATED_FILES)
1003 elog(ERROR, "AllocateFile: too many private FDs demanded");
1006 if ((file = fopen(name, mode)) == NULL)
1008 if (errno == EMFILE || errno == ENFILE)
1010 DO_DB(elog(DEBUG, "AllocateFile: not enough descs, retry, er= %d",
1018 allocatedFiles[numAllocatedFiles++] = file;
1023 FreeFile(FILE *file)
1027 DO_DB(elog(DEBUG, "FreeFile: Allocated %d.", numAllocatedFiles));
1029 /* Remove file from list of allocated files, if it's present */
1030 for (i = numAllocatedFiles; --i >= 0;)
1032 if (allocatedFiles[i] == file)
1034 allocatedFiles[i] = allocatedFiles[--numAllocatedFiles];
1039 elog(NOTICE, "FreeFile: file was not obtained from AllocateFile");
1047 * Force all VFDs into the physically-closed state, so that the fewest
1048 * possible number of kernel file descriptors are in use. There is no
1049 * change in the logical state of the VFDs.
1056 if (SizeVfdCache > 0)
1058 Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
1059 for (i = 1; i < SizeVfdCache; i++)
1061 if (!FileIsNotOpen(i))
1070 * This routine is called during transaction commit or abort or backend
1071 * exit (it doesn't particularly care which). All still-open temporary-file
1072 * VFDs are closed, which also causes the underlying files to be deleted.
1073 * Furthermore, all "allocated" stdio files are closed.
1075 * This routine is not involved in fsync'ing non-temporary files at xact
1076 * commit; that is done by FileSync under control of the buffer manager.
1077 * During a commit, that is done *before* control gets here. If we still
1078 * have any needs-fsync bits set when we get here, we assume this is abort
1082 AtEOXact_Files(void)
1086 if (SizeVfdCache > 0)
1088 Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
1089 for (i = 1; i < SizeVfdCache; i++)
1091 if ((VfdCache[i].fdstate & FD_TEMPORARY) &&
1092 VfdCache[i].fileName != NULL)
1095 VfdCache[i].fdstate &= ~FD_DIRTY;
1099 while (numAllocatedFiles > 0)
1100 FreeFile(allocatedFiles[0]);
1103 * Reset the tempfile name counter to 0; not really necessary, but
1104 * helps keep the names from growing unreasonably long.
1106 tempFileCounter = 0;