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.96 2003/03/27 16:51:29 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 *-------------------------------------------------------------------------
44 #include <sys/param.h>
51 #include "miscadmin.h"
52 #include "storage/fd.h"
53 #include "storage/ipc.h"
56 /* Filename components for OpenTemporaryFile */
57 #define PG_TEMP_FILES_DIR "pgsql_tmp"
58 #define PG_TEMP_FILE_PREFIX "pgsql_tmp"
62 * Problem: Postgres does a system(ld...) to do dynamic loading.
63 * This will open several extra files in addition to those used by
64 * Postgres. We need to guarantee that there are file descriptors free
67 * The current solution is to limit the number of file descriptors
68 * that this code will allocate at one time: it leaves RESERVE_FOR_LD free.
70 * (Even though most dynamic loaders now use dlopen(3) or the
71 * equivalent, the OS must still open several files to perform the
72 * dynamic loading. And stdin/stdout/stderr count too. Keep this here.)
74 #ifndef RESERVE_FOR_LD
75 #define RESERVE_FOR_LD 10
79 * We need to ensure that we have at least some file descriptors
80 * available to postgreSQL after we've reserved the ones for LD,
81 * so we set that value here.
83 * I think 10 is an appropriate value so that's what it'll be
91 * A number of platforms return values for sysconf(_SC_OPEN_MAX) that are
92 * far beyond what they can really support. This GUC parameter limits what
95 int max_files_per_process = 1000;
103 #define DO_DB(A) /* A */
106 #define VFD_CLOSED (-1)
108 #define FileIsValid(file) \
109 ((file) > 0 && (file) < (int) SizeVfdCache && VfdCache[file].fileName != NULL)
111 #define FileIsNotOpen(file) (VfdCache[file].fd == VFD_CLOSED)
113 #define FileUnknownPos (-1L)
115 /* these are the assigned bits in fdstate below: */
116 #define FD_TEMPORARY (1 << 0)
117 #define FD_TXN_TEMPORARY (1 << 1)
121 signed short fd; /* current FD, or VFD_CLOSED if none */
122 unsigned short fdstate; /* bitflags for VFD's state */
123 File nextFree; /* link to next free VFD, if in freelist */
124 File lruMoreRecently; /* doubly linked recency-of-use list */
125 File lruLessRecently;
126 long seekPos; /* current logical file position */
127 char *fileName; /* name of file, or NULL for unused VFD */
128 /* NB: fileName is malloc'd, and must be free'd when closing the VFD */
129 int fileFlags; /* open(2) flags for (re)opening the file */
130 int fileMode; /* mode to pass to open(2) */
134 * Virtual File Descriptor array pointer and size. This grows as
135 * needed. 'File' values are indexes into this array.
136 * Note that VfdCache[0] is not a usable VFD, just a list header.
138 static Vfd *VfdCache;
139 static Size SizeVfdCache = 0;
142 * Number of file descriptors known to be in use by VFD entries.
144 static int nfile = 0;
147 * List of stdio FILEs opened with AllocateFile.
149 * Since we don't want to encourage heavy use of AllocateFile, it seems
150 * OK to put a pretty small maximum limit on the number of simultaneously
153 #define MAX_ALLOCATED_FILES 32
155 static int numAllocatedFiles = 0;
156 static FILE *allocatedFiles[MAX_ALLOCATED_FILES];
159 * Number of temporary files opened during the current transaction;
160 * this is used in generation of tempfile names.
162 static long tempFileCounter = 0;
165 /*--------------------
169 * Delete - delete a file from the Lru ring
170 * LruDelete - remove a file from the Lru ring and close its FD
171 * Insert - put a file at the front of the Lru ring
172 * LruInsert - put a file at the front of the Lru ring and open it
173 * ReleaseLruFile - Release an fd by closing the last entry in the Lru ring
174 * AllocateVfd - grab a free (or new) file record (from VfdArray)
175 * FreeVfd - free a file record
177 * The Least Recently Used ring is a doubly linked list that begins and
178 * ends on element zero. Element zero is special -- it doesn't represent
179 * a file and its "fd" field always == VFD_CLOSED. Element zero is just an
180 * anchor that shows us the beginning/end of the ring.
181 * Only VFD elements that are currently really open (have an FD assigned) are
182 * in the Lru ring. Elements that are "virtually" open can be recognized
183 * by having a non-null fileName field.
187 * /--less----\ /---------\
189 * #0 --more---> LeastRecentlyUsed --more-\ \
191 * \\less--> MostRecentlyUsedFile <---/ |
192 * \more---/ \--less--/
194 *--------------------
196 static void Delete(File file);
197 static void LruDelete(File file);
198 static void Insert(File file);
199 static int LruInsert(File file);
200 static bool ReleaseLruFile(void);
201 static File AllocateVfd(void);
202 static void FreeVfd(File file);
204 static int FileAccess(File file);
205 static File fileNameOpenFile(FileName fileName, int fileFlags, int fileMode);
206 static char *filepath(const char *filename);
207 static long pg_nofile(void);
210 * pg_fsync --- same as fsync except does nothing if enableFsync is off
222 * pg_fdatasync --- same as fdatasync except does nothing if enableFsync is off
224 * Not all platforms have fdatasync; treat as fsync if not available.
231 #ifdef HAVE_FDATASYNC
232 return fdatasync(fd);
242 * BasicOpenFile --- same as open(2) except can free other FDs if needed
244 * This is exported for use by places that really want a plain kernel FD,
245 * but need to be proof against running out of FDs. Once an FD has been
246 * successfully returned, it is the caller's responsibility to ensure that
247 * it will not be leaked on elog()! Most users should *not* call this
248 * routine directly, but instead use the VFD abstraction level, which
249 * provides protection against descriptor leaks as well as management of
250 * files that need to be open for more than a short period of time.
252 * Ideally this should be the *only* direct call of open() in the backend.
253 * In practice, the postmaster calls open() directly, and there are some
254 * direct open() calls done early in backend startup. Those are OK since
255 * this module wouldn't have any open files to close at that point anyway.
258 BasicOpenFile(FileName fileName, int fileFlags, int fileMode)
263 fd = open(fileName, fileFlags, fileMode);
266 return fd; /* success! */
268 if (errno == EMFILE || errno == ENFILE)
270 int save_errno = errno;
272 DO_DB(elog(LOG, "BasicOpenFile: not enough descs, retry, er= %d",
275 if (ReleaseLruFile())
280 return -1; /* failure */
284 * pg_nofile: determine number of filedescriptors that fd.c is allowed to use
289 static long no_files = 0;
291 /* need do this calculation only once */
295 * Ask the system what its files-per-process limit is.
298 no_files = sysconf(_SC_OPEN_MAX);
302 no_files = (long) NOFILE;
304 no_files = (long) max_files_per_process;
306 elog(LOG, "pg_nofile: sysconf(_SC_OPEN_MAX) failed; using %ld",
309 #else /* !HAVE_SYSCONF */
311 no_files = (long) NOFILE;
313 no_files = (long) max_files_per_process;
315 #endif /* HAVE_SYSCONF */
318 * Some platforms return hopelessly optimistic values. Apply a
319 * configurable upper limit.
321 if (no_files > (long) max_files_per_process)
322 no_files = (long) max_files_per_process;
325 * Make sure we have enough to get by after reserving some for LD.
327 if ((no_files - RESERVE_FOR_LD) < FD_MINFREE)
328 elog(FATAL, "pg_nofile: insufficient file descriptors available to start backend.\n"
329 "\tSystem allows %ld, we need at least %d.",
330 no_files, RESERVE_FOR_LD + FD_MINFREE);
332 no_files -= RESERVE_FOR_LD;
343 int mru = VfdCache[0].lruLessRecently;
344 Vfd *vfdP = &VfdCache[mru];
347 snprintf(buf, sizeof(buf), "LRU: MOST %d ", mru);
350 mru = vfdP->lruLessRecently;
351 vfdP = &VfdCache[mru];
352 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%d ", mru);
354 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "LEAST");
366 DO_DB(elog(LOG, "Delete %d (%s)",
367 file, VfdCache[file].fileName));
370 vfdP = &VfdCache[file];
372 VfdCache[vfdP->lruLessRecently].lruMoreRecently = vfdP->lruMoreRecently;
373 VfdCache[vfdP->lruMoreRecently].lruLessRecently = vfdP->lruLessRecently;
385 DO_DB(elog(LOG, "LruDelete %d (%s)",
386 file, VfdCache[file].fileName));
388 vfdP = &VfdCache[file];
390 /* delete the vfd record from the LRU ring */
393 /* save the seek position */
394 vfdP->seekPos = (long) lseek(vfdP->fd, 0L, SEEK_CUR);
395 Assert(vfdP->seekPos != -1L);
399 elog(LOG, "LruDelete: failed to close %s: %m",
403 vfdP->fd = VFD_CLOSED;
413 DO_DB(elog(LOG, "Insert %d (%s)",
414 file, VfdCache[file].fileName));
417 vfdP = &VfdCache[file];
419 vfdP->lruMoreRecently = 0;
420 vfdP->lruLessRecently = VfdCache[0].lruLessRecently;
421 VfdCache[0].lruLessRecently = file;
422 VfdCache[vfdP->lruLessRecently].lruMoreRecently = file;
434 DO_DB(elog(LOG, "LruInsert %d (%s)",
435 file, VfdCache[file].fileName));
437 vfdP = &VfdCache[file];
439 if (FileIsNotOpen(file))
441 while (nfile + numAllocatedFiles >= pg_nofile())
443 if (!ReleaseLruFile())
448 * The open could still fail for lack of file descriptors, eg due
449 * to overall system file table being full. So, be prepared to
450 * release another FD if necessary...
452 vfdP->fd = BasicOpenFile(vfdP->fileName, vfdP->fileFlags,
456 DO_DB(elog(LOG, "RE_OPEN FAILED: %d", errno));
461 DO_DB(elog(LOG, "RE_OPEN SUCCESS"));
465 /* seek to the right position */
466 if (vfdP->seekPos != 0L)
470 returnValue = (long) lseek(vfdP->fd, vfdP->seekPos, SEEK_SET);
471 Assert(returnValue != -1L);
476 * put it at the head of the Lru ring
487 DO_DB(elog(LOG, "ReleaseLruFile. Opened %d", nfile));
492 * There are opened files and so there should be at least one used
495 Assert(VfdCache[0].lruMoreRecently != 0);
496 LruDelete(VfdCache[0].lruMoreRecently);
497 return true; /* freed a file */
499 return false; /* no files available to free */
508 DO_DB(elog(LOG, "AllocateVfd. Size %d", SizeVfdCache));
510 if (SizeVfdCache == 0)
512 /* initialize header entry first time through */
513 VfdCache = (Vfd *) malloc(sizeof(Vfd));
514 if (VfdCache == NULL)
515 elog(FATAL, "AllocateVfd: no room for VFD array");
516 MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
517 VfdCache->fd = VFD_CLOSED;
522 * register proc-exit call to ensure temp files are dropped at
525 on_proc_exit(AtEOXact_Files, 0);
528 if (VfdCache[0].nextFree == 0)
531 * The free list is empty so it is time to increase the size of
532 * the array. We choose to double it each time this happens.
533 * However, there's not much point in starting *real* small.
535 Size newCacheSize = SizeVfdCache * 2;
538 if (newCacheSize < 32)
542 * Be careful not to clobber VfdCache ptr if realloc fails; we
543 * will need it during proc_exit cleanup!
545 newVfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize);
546 if (newVfdCache == NULL)
547 elog(FATAL, "AllocateVfd: no room to enlarge VFD array");
548 VfdCache = newVfdCache;
551 * Initialize the new entries and link them into the free list.
553 for (i = SizeVfdCache; i < newCacheSize; i++)
555 MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
556 VfdCache[i].nextFree = i + 1;
557 VfdCache[i].fd = VFD_CLOSED;
559 VfdCache[newCacheSize - 1].nextFree = 0;
560 VfdCache[0].nextFree = SizeVfdCache;
563 * Record the new size
565 SizeVfdCache = newCacheSize;
568 file = VfdCache[0].nextFree;
570 VfdCache[0].nextFree = VfdCache[file].nextFree;
578 Vfd *vfdP = &VfdCache[file];
580 DO_DB(elog(LOG, "FreeVfd: %d (%s)",
581 file, vfdP->fileName ? vfdP->fileName : ""));
583 if (vfdP->fileName != NULL)
585 free(vfdP->fileName);
586 vfdP->fileName = NULL;
590 vfdP->nextFree = VfdCache[0].nextFree;
591 VfdCache[0].nextFree = file;
595 * Convert given pathname to absolute.
597 * Result is a palloc'd string.
599 * (Generally, this isn't actually necessary, considering that we
600 * should be cd'd into the database directory. Presently it is only
601 * necessary to do it in "bootstrap" mode. Maybe we should change
602 * bootstrap mode to do the cd, and save a few cycles/bytes here.)
605 filepath(const char *filename)
609 /* Not an absolute path name? Then fill in with database path... */
610 if (*filename != '/')
612 buf = (char *) palloc(strlen(DatabasePath) + strlen(filename) + 2);
613 sprintf(buf, "%s/%s", DatabasePath, filename);
616 buf = pstrdup(filename);
619 printf("filepath: path is %s\n", buf);
626 FileAccess(File file)
630 DO_DB(elog(LOG, "FileAccess %d (%s)",
631 file, VfdCache[file].fileName));
634 * Is the file open? If not, open it and put it at the head of the
635 * LRU ring (possibly closing the least recently used file to get an
639 if (FileIsNotOpen(file))
641 returnValue = LruInsert(file);
642 if (returnValue != 0)
645 else if (VfdCache[0].lruLessRecently != file)
648 * We now know that the file is open and that it is not the last
649 * one accessed, so we need to move it to the head of the Lru
661 * Called when we get a shared invalidation message on some relation.
665 FileInvalidate(File file)
667 Assert(FileIsValid(file));
668 if (!FileIsNotOpen(file))
674 fileNameOpenFile(FileName fileName,
681 if (fileName == NULL)
682 elog(ERROR, "fileNameOpenFile: NULL fname");
684 DO_DB(elog(LOG, "fileNameOpenFile: %s %x %o",
685 fileName, fileFlags, fileMode));
687 file = AllocateVfd();
688 vfdP = &VfdCache[file];
690 while (nfile + numAllocatedFiles >= pg_nofile())
692 if (!ReleaseLruFile())
696 vfdP->fd = BasicOpenFile(fileName, fileFlags, fileMode);
704 DO_DB(elog(LOG, "fileNameOpenFile: success %d",
709 vfdP->fileName = (char *) malloc(strlen(fileName) + 1);
710 if (vfdP->fileName == NULL)
711 elog(FATAL, "fileNameOpenFile: no room to save VFD filename");
712 strcpy(vfdP->fileName, fileName);
714 /* Saved flags are adjusted to be OK for re-opening file */
715 vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
716 vfdP->fileMode = fileMode;
724 * open a file in the database directory ($PGDATA/base/...)
727 FileNameOpenFile(FileName fileName, int fileFlags, int fileMode)
732 fname = filepath(fileName);
733 fd = fileNameOpenFile(fname, fileFlags, fileMode);
739 * open a file in an arbitrary directory
742 PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
744 return fileNameOpenFile(fileName, fileFlags, fileMode);
748 * Open a temporary file that will disappear when we close it.
750 * This routine takes care of generating an appropriate tempfile name.
751 * There's no need to pass in fileFlags or fileMode either, since only
752 * one setting makes any sense for a temp file.
754 * keepOverTxn: if true, don't close the file at end-of-transaction. In
755 * most cases, you don't want temporary files to outlive the transaction
756 * that created them, so this should be false -- but if you need
757 * "somewhat" temporary storage, this might be useful. In either case,
758 * the file is removed when the File is explicitely closed.
761 OpenTemporaryFile(bool keepOverTxn)
763 char tempfilepath[128];
767 * Generate a tempfile name that's unique within the current
768 * transaction and database instance.
770 snprintf(tempfilepath, sizeof(tempfilepath),
771 "%s/%s%d.%ld", PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
772 MyProcPid, tempFileCounter++);
775 * Open the file. Note: we don't use O_EXCL, in case there is an
776 * orphaned temp file that can be reused.
778 file = FileNameOpenFile(tempfilepath,
779 O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
786 * We might need to create the pg_tempfiles subdirectory, if no
787 * one has yet done so.
789 * Don't check for error from mkdir; it could fail if someone else
790 * just did the same thing. If it doesn't work then we'll bomb
791 * out on the second create attempt, instead.
793 dirpath = filepath(PG_TEMP_FILES_DIR);
794 mkdir(dirpath, S_IRWXU);
797 file = FileNameOpenFile(tempfilepath,
798 O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
801 elog(ERROR, "Failed to create temporary file %s", tempfilepath);
804 /* Mark it for deletion at close */
805 VfdCache[file].fdstate |= FD_TEMPORARY;
807 /* Mark it for deletion at EOXact */
809 VfdCache[file].fdstate |= FD_TXN_TEMPORARY;
815 * close a file when done with it
822 Assert(FileIsValid(file));
824 DO_DB(elog(LOG, "FileClose: %d (%s)",
825 file, VfdCache[file].fileName));
827 vfdP = &VfdCache[file];
829 if (!FileIsNotOpen(file))
831 /* remove the file from the lru ring */
836 elog(LOG, "FileClose: failed to close %s: %m",
840 vfdP->fd = VFD_CLOSED;
844 * Delete the file if it was temporary
846 if (vfdP->fdstate & FD_TEMPORARY)
848 /* reset flag so that die() interrupt won't cause problems */
849 vfdP->fdstate &= ~FD_TEMPORARY;
850 if (unlink(vfdP->fileName))
851 elog(LOG, "FileClose: failed to unlink %s: %m",
856 * Return the Vfd slot to the free list
862 * close a file and forcibly delete the underlying Unix file
865 FileUnlink(File file)
867 Assert(FileIsValid(file));
869 DO_DB(elog(LOG, "FileUnlink: %d (%s)",
870 file, VfdCache[file].fileName));
872 /* force FileClose to delete it */
873 VfdCache[file].fdstate |= FD_TEMPORARY;
879 FileRead(File file, char *buffer, int amount)
883 Assert(FileIsValid(file));
885 DO_DB(elog(LOG, "FileRead: %d (%s) %ld %d %p",
886 file, VfdCache[file].fileName,
887 VfdCache[file].seekPos, amount, buffer));
890 returnCode = read(VfdCache[file].fd, buffer, amount);
892 VfdCache[file].seekPos += returnCode;
894 VfdCache[file].seekPos = FileUnknownPos;
900 FileWrite(File file, char *buffer, int amount)
904 Assert(FileIsValid(file));
906 DO_DB(elog(LOG, "FileWrite: %d (%s) %ld %d %p",
907 file, VfdCache[file].fileName,
908 VfdCache[file].seekPos, amount, buffer));
913 returnCode = write(VfdCache[file].fd, buffer, amount);
915 /* if write didn't set errno, assume problem is no disk space */
916 if (returnCode != amount && errno == 0)
920 VfdCache[file].seekPos += returnCode;
922 VfdCache[file].seekPos = FileUnknownPos;
928 FileSeek(File file, long offset, int whence)
930 Assert(FileIsValid(file));
932 DO_DB(elog(LOG, "FileSeek: %d (%s) %ld %ld %d",
933 file, VfdCache[file].fileName,
934 VfdCache[file].seekPos, offset, whence));
936 if (FileIsNotOpen(file))
942 elog(ERROR, "FileSeek: invalid offset: %ld", offset);
943 VfdCache[file].seekPos = offset;
946 VfdCache[file].seekPos += offset;
950 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
953 elog(ERROR, "FileSeek: invalid whence: %d", whence);
963 elog(ERROR, "FileSeek: invalid offset: %ld", offset);
964 if (VfdCache[file].seekPos != offset)
965 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
968 if (offset != 0 || VfdCache[file].seekPos == FileUnknownPos)
969 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
972 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
975 elog(ERROR, "FileSeek: invalid whence: %d", whence);
979 return VfdCache[file].seekPos;
983 * XXX not actually used but here for completeness
989 Assert(FileIsValid(file));
990 DO_DB(elog(LOG, "FileTell %d (%s)",
991 file, VfdCache[file].fileName));
992 return VfdCache[file].seekPos;
997 FileTruncate(File file, long offset)
1001 Assert(FileIsValid(file));
1003 DO_DB(elog(LOG, "FileTruncate %d (%s)",
1004 file, VfdCache[file].fileName));
1007 returnCode = ftruncate(VfdCache[file].fd, (size_t) offset);
1013 * Routines that want to use stdio (ie, FILE*) should use AllocateFile
1014 * rather than plain fopen(). This lets fd.c deal with freeing FDs if
1015 * necessary to open the file. When done, call FreeFile rather than fclose.
1017 * Note that files that will be open for any significant length of time
1018 * should NOT be handled this way, since they cannot share kernel file
1019 * descriptors with other files; there is grave risk of running out of FDs
1020 * if anyone locks down too many FDs. Most callers of this routine are
1021 * simply reading a config file that they will read and close immediately.
1023 * fd.c will automatically close all files opened with AllocateFile at
1024 * transaction commit or abort; this prevents FD leakage if a routine
1025 * that calls AllocateFile is terminated prematurely by elog(ERROR).
1027 * Ideally this should be the *only* direct call of fopen() in the backend.
1030 AllocateFile(char *name, char *mode)
1034 DO_DB(elog(LOG, "AllocateFile: Allocated %d", numAllocatedFiles));
1036 if (numAllocatedFiles >= MAX_ALLOCATED_FILES)
1037 elog(ERROR, "AllocateFile: too many private FDs demanded");
1040 if ((file = fopen(name, mode)) != NULL)
1042 allocatedFiles[numAllocatedFiles] = file;
1043 numAllocatedFiles++;
1047 if (errno == EMFILE || errno == ENFILE)
1049 int save_errno = errno;
1051 DO_DB(elog(LOG, "AllocateFile: not enough descs, retry, er= %d",
1054 if (ReleaseLruFile())
1063 FreeFile(FILE *file)
1067 DO_DB(elog(LOG, "FreeFile: Allocated %d", numAllocatedFiles));
1069 /* Remove file from list of allocated files, if it's present */
1070 for (i = numAllocatedFiles; --i >= 0;)
1072 if (allocatedFiles[i] == file)
1074 numAllocatedFiles--;
1075 allocatedFiles[i] = allocatedFiles[numAllocatedFiles];
1080 elog(WARNING, "FreeFile: file was not obtained from AllocateFile");
1088 * Force all VFDs into the physically-closed state, so that the fewest
1089 * possible number of kernel file descriptors are in use. There is no
1090 * change in the logical state of the VFDs.
1097 if (SizeVfdCache > 0)
1099 Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
1100 for (i = 1; i < SizeVfdCache; i++)
1102 if (!FileIsNotOpen(i))
1111 * This routine is called during transaction commit or abort or backend
1112 * exit (it doesn't particularly care which). All still-open temporary-file
1113 * VFDs are closed, which also causes the underlying files to be deleted.
1114 * Furthermore, all "allocated" stdio files are closed.
1117 AtEOXact_Files(void)
1121 if (SizeVfdCache > 0)
1123 Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
1124 for (i = 1; i < SizeVfdCache; i++)
1126 if ((VfdCache[i].fdstate & FD_TEMPORARY) &&
1127 (VfdCache[i].fdstate & FD_TXN_TEMPORARY) &&
1128 VfdCache[i].fileName != NULL)
1133 while (numAllocatedFiles > 0)
1134 FreeFile(allocatedFiles[0]);
1137 * Reset the tempfile name counter to 0; not really necessary, but
1138 * helps keep the names from growing unreasonably long.
1140 tempFileCounter = 0;
1145 * Remove old temporary files
1147 * This should be called during postmaster startup. It will forcibly
1148 * remove any leftover files created by OpenTemporaryFile.
1151 RemovePgTempFiles(void)
1153 char db_path[MAXPGPATH];
1154 char temp_path[MAXPGPATH];
1155 char rm_path[MAXPGPATH];
1158 struct dirent *db_de;
1159 struct dirent *temp_de;
1162 * Cycle through pg_tempfiles for all databases and remove old temp
1165 snprintf(db_path, sizeof(db_path), "%s/base", DataDir);
1166 if ((db_dir = opendir(db_path)) != NULL)
1168 while ((db_de = readdir(db_dir)) != NULL)
1170 if (strcmp(db_de->d_name, ".") == 0 ||
1171 strcmp(db_de->d_name, "..") == 0)
1174 snprintf(temp_path, sizeof(temp_path),
1176 db_path, db_de->d_name,
1178 if ((temp_dir = opendir(temp_path)) != NULL)
1180 while ((temp_de = readdir(temp_dir)) != NULL)
1182 if (strcmp(temp_de->d_name, ".") == 0 ||
1183 strcmp(temp_de->d_name, "..") == 0)
1186 snprintf(rm_path, sizeof(temp_path),
1188 db_path, db_de->d_name,
1192 if (strncmp(temp_de->d_name,
1193 PG_TEMP_FILE_PREFIX,
1194 strlen(PG_TEMP_FILE_PREFIX)) == 0)
1199 * would prefer to use elog here, but it's not up
1200 * and running during postmaster startup...
1203 "Unexpected file found in temporary-files directory: %s\n",