]> granicus.if.org Git - postgresql/blob - src/backend/storage/file/fd.c
Restructure local-buffer handling per recent pghackers discussion.
[postgresql] / src / backend / storage / file / fd.c
1 /*-------------------------------------------------------------------------
2  *
3  * fd.c
4  *        Virtual file descriptor code.
5  *
6  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.93 2002/08/06 02:36:34 tgl Exp $
11  *
12  * NOTES:
13  *
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.)
21  *
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
26  * descriptor).
27  *
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.
32  *
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
37  * POSTGRES source.
38  *-------------------------------------------------------------------------
39  */
40
41 #include "postgres.h"
42
43 #include <sys/types.h>
44 #include <sys/file.h>
45 #include <sys/param.h>
46 #include <sys/stat.h>
47 #include <dirent.h>
48 #include <errno.h>
49 #include <unistd.h>
50 #include <fcntl.h>
51
52 #include "miscadmin.h"
53 #include "storage/fd.h"
54 #include "storage/ipc.h"
55
56
57 /* Filename components for OpenTemporaryFile */
58 #define PG_TEMP_FILES_DIR "pgsql_tmp"
59 #define PG_TEMP_FILE_PREFIX "pgsql_tmp"
60
61
62 /*
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
66  * for ld to use.
67  *
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.
70  *
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.)
74  */
75 #ifndef RESERVE_FOR_LD
76 #define RESERVE_FOR_LD  10
77 #endif
78
79 /*
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.
83  *
84  * I think 10 is an appropriate value so that's what it'll be
85  * for now.
86  */
87 #ifndef FD_MINFREE
88 #define FD_MINFREE 10
89 #endif
90
91 /*
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
94  * we will believe.
95  */
96 int                     max_files_per_process = 1000;
97
98
99 /* Debugging.... */
100
101 #ifdef FDDEBUG
102 #define DO_DB(A) A
103 #else
104 #define DO_DB(A)                                /* A */
105 #endif
106
107 #define VFD_CLOSED (-1)
108
109 #define FileIsValid(file) \
110         ((file) > 0 && (file) < (int) SizeVfdCache && VfdCache[file].fileName != NULL)
111
112 #define FileIsNotOpen(file) (VfdCache[file].fd == VFD_CLOSED)
113
114 #define FileUnknownPos (-1L)
115
116 typedef struct vfd
117 {
118         signed short fd;                        /* current FD, or VFD_CLOSED if none */
119         unsigned short fdstate;         /* bitflags for VFD's state */
120
121 /* these are the assigned bits in fdstate: */
122 #define FD_TEMPORARY    (1 << 0)        /* should be unlinked when closed */
123
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) */
132 } Vfd;
133
134 /*
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.
138  */
139 static Vfd *VfdCache;
140 static Size SizeVfdCache = 0;
141
142 /*
143  * Number of file descriptors known to be in use by VFD entries.
144  */
145 static int      nfile = 0;
146
147 /*
148  * List of stdio FILEs opened with AllocateFile.
149  *
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
152  * allocated files.
153  */
154 #define MAX_ALLOCATED_FILES  32
155
156 static int      numAllocatedFiles = 0;
157 static FILE *allocatedFiles[MAX_ALLOCATED_FILES];
158
159 /*
160  * Number of temporary files opened during the current transaction;
161  * this is used in generation of tempfile names.
162  */
163 static long tempFileCounter = 0;
164
165
166 /*--------------------
167  *
168  * Private Routines
169  *
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
177  *
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.
185  *
186  * example:
187  *
188  *         /--less----\                            /---------\
189  *         v               \                      v                       \
190  *       #0 --more---> LeastRecentlyUsed --more-\ \
191  *        ^\                                                                    | |
192  *         \\less--> MostRecentlyUsedFile       <---/ |
193  *              \more---/                                        \--less--/
194  *
195  *--------------------
196  */
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);
204
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);
209
210 /*
211  * pg_fsync --- same as fsync except does nothing if enableFsync is off
212  */
213 int
214 pg_fsync(int fd)
215 {
216         if (enableFsync)
217                 return fsync(fd);
218         else
219                 return 0;
220 }
221
222 /*
223  * pg_fdatasync --- same as fdatasync except does nothing if enableFsync is off
224  *
225  * Not all platforms have fdatasync; treat as fsync if not available.
226  */
227 int
228 pg_fdatasync(int fd)
229 {
230         if (enableFsync)
231         {
232 #ifdef HAVE_FDATASYNC
233                 return fdatasync(fd);
234 #else
235                 return fsync(fd);
236 #endif
237         }
238         else
239                 return 0;
240 }
241
242 /*
243  * BasicOpenFile --- same as open(2) except can free other FDs if needed
244  *
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.
252  *
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.
257  */
258 int
259 BasicOpenFile(FileName fileName, int fileFlags, int fileMode)
260 {
261         int                     fd;
262
263 tryAgain:
264         fd = open(fileName, fileFlags, fileMode);
265
266         if (fd >= 0)
267                 return fd;                              /* success! */
268
269         if (errno == EMFILE || errno == ENFILE)
270         {
271                 int                     save_errno = errno;
272
273                 DO_DB(elog(LOG, "BasicOpenFile: not enough descs, retry, er= %d",
274                                    errno));
275                 errno = 0;
276                 if (ReleaseLruFile())
277                         goto tryAgain;
278                 errno = save_errno;
279         }
280
281         return -1;                                      /* failure */
282 }
283
284 /*
285  * pg_nofile: determine number of filedescriptors that fd.c is allowed to use
286  */
287 static long
288 pg_nofile(void)
289 {
290         static long no_files = 0;
291
292         /* need do this calculation only once */
293         if (no_files == 0)
294         {
295                 /*
296                  * Ask the system what its files-per-process limit is.
297                  */
298 #ifdef HAVE_SYSCONF
299                 no_files = sysconf(_SC_OPEN_MAX);
300                 if (no_files <= 0)
301                 {
302 #ifdef NOFILE
303                         no_files = (long) NOFILE;
304 #else
305                         no_files = (long) max_files_per_process;
306 #endif
307                         elog(LOG, "pg_nofile: sysconf(_SC_OPEN_MAX) failed; using %ld",
308                                  no_files);
309                 }
310 #else                                                   /* !HAVE_SYSCONF */
311 #ifdef NOFILE
312                 no_files = (long) NOFILE;
313 #else
314                 no_files = (long) max_files_per_process;
315 #endif
316 #endif   /* HAVE_SYSCONF */
317
318                 /*
319                  * Some platforms return hopelessly optimistic values.  Apply a
320                  * configurable upper limit.
321                  */
322                 if (no_files > (long) max_files_per_process)
323                         no_files = (long) max_files_per_process;
324
325                 /*
326                  * Make sure we have enough to get by after reserving some for LD.
327                  */
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);
332
333                 no_files -= RESERVE_FOR_LD;
334         }
335
336         return no_files;
337 }
338
339 #if defined(FDDEBUG)
340
341 static void
342 _dump_lru(void)
343 {
344         int                     mru = VfdCache[0].lruLessRecently;
345         Vfd                *vfdP = &VfdCache[mru];
346         char            buf[2048];
347
348         sprintf(buf, "LRU: MOST %d ", mru);
349         while (mru != 0)
350         {
351                 mru = vfdP->lruLessRecently;
352                 vfdP = &VfdCache[mru];
353                 sprintf(buf + strlen(buf), "%d ", mru);
354         }
355         sprintf(buf + strlen(buf), "LEAST");
356         elog(LOG, buf);
357 }
358 #endif   /* FDDEBUG */
359
360 static void
361 Delete(File file)
362 {
363         Vfd                *vfdP;
364
365         Assert(file != 0);
366
367         DO_DB(elog(LOG, "Delete %d (%s)",
368                            file, VfdCache[file].fileName));
369         DO_DB(_dump_lru());
370
371         vfdP = &VfdCache[file];
372
373         VfdCache[vfdP->lruLessRecently].lruMoreRecently = vfdP->lruMoreRecently;
374         VfdCache[vfdP->lruMoreRecently].lruLessRecently = vfdP->lruLessRecently;
375
376         DO_DB(_dump_lru());
377 }
378
379 static void
380 LruDelete(File file)
381 {
382         Vfd                *vfdP;
383
384         Assert(file != 0);
385
386         DO_DB(elog(LOG, "LruDelete %d (%s)",
387                            file, VfdCache[file].fileName));
388
389         vfdP = &VfdCache[file];
390
391         /* delete the vfd record from the LRU ring */
392         Delete(file);
393
394         /* save the seek position */
395         vfdP->seekPos = (long) lseek(vfdP->fd, 0L, SEEK_CUR);
396         Assert(vfdP->seekPos != -1L);
397
398         /* close the file */
399         if (close(vfdP->fd))
400                 elog(LOG, "LruDelete: failed to close %s: %m",
401                          vfdP->fileName);
402
403         --nfile;
404         vfdP->fd = VFD_CLOSED;
405 }
406
407 static void
408 Insert(File file)
409 {
410         Vfd                *vfdP;
411
412         Assert(file != 0);
413
414         DO_DB(elog(LOG, "Insert %d (%s)",
415                            file, VfdCache[file].fileName));
416         DO_DB(_dump_lru());
417
418         vfdP = &VfdCache[file];
419
420         vfdP->lruMoreRecently = 0;
421         vfdP->lruLessRecently = VfdCache[0].lruLessRecently;
422         VfdCache[0].lruLessRecently = file;
423         VfdCache[vfdP->lruLessRecently].lruMoreRecently = file;
424
425         DO_DB(_dump_lru());
426 }
427
428 static int
429 LruInsert(File file)
430 {
431         Vfd                *vfdP;
432
433         Assert(file != 0);
434
435         DO_DB(elog(LOG, "LruInsert %d (%s)",
436                            file, VfdCache[file].fileName));
437
438         vfdP = &VfdCache[file];
439
440         if (FileIsNotOpen(file))
441         {
442                 while (nfile + numAllocatedFiles >= pg_nofile())
443                 {
444                         if (!ReleaseLruFile())
445                                 break;
446                 }
447
448                 /*
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...
452                  */
453                 vfdP->fd = BasicOpenFile(vfdP->fileName, vfdP->fileFlags,
454                                                                  vfdP->fileMode);
455                 if (vfdP->fd < 0)
456                 {
457                         DO_DB(elog(LOG, "RE_OPEN FAILED: %d", errno));
458                         return vfdP->fd;
459                 }
460                 else
461                 {
462                         DO_DB(elog(LOG, "RE_OPEN SUCCESS"));
463                         ++nfile;
464                 }
465
466                 /* seek to the right position */
467                 if (vfdP->seekPos != 0L)
468                 {
469                         long            returnValue;
470
471                         returnValue = (long) lseek(vfdP->fd, vfdP->seekPos, SEEK_SET);
472                         Assert(returnValue != -1L);
473                 }
474         }
475
476         /*
477          * put it at the head of the Lru ring
478          */
479
480         Insert(file);
481
482         return 0;
483 }
484
485 static bool
486 ReleaseLruFile(void)
487 {
488         DO_DB(elog(LOG, "ReleaseLruFile. Opened %d", nfile));
489
490         if (nfile > 0)
491         {
492                 /*
493                  * There are opened files and so there should be at least one used
494                  * vfd in the ring.
495                  */
496                 Assert(VfdCache[0].lruMoreRecently != 0);
497                 LruDelete(VfdCache[0].lruMoreRecently);
498                 return true;                    /* freed a file */
499         }
500         return false;                           /* no files available to free */
501 }
502
503 static File
504 AllocateVfd(void)
505 {
506         Index           i;
507         File            file;
508
509         DO_DB(elog(LOG, "AllocateVfd. Size %d", SizeVfdCache));
510
511         if (SizeVfdCache == 0)
512         {
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;
519
520                 SizeVfdCache = 1;
521
522                 /*
523                  * register proc-exit call to ensure temp files are dropped at
524                  * exit
525                  */
526                 on_proc_exit(AtEOXact_Files, 0);
527         }
528
529         if (VfdCache[0].nextFree == 0)
530         {
531                 /*
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.
535                  */
536                 Size            newCacheSize = SizeVfdCache * 2;
537                 Vfd                *newVfdCache;
538
539                 if (newCacheSize < 32)
540                         newCacheSize = 32;
541
542                 /*
543                  * Be careful not to clobber VfdCache ptr if realloc fails; we
544                  * will need it during proc_exit cleanup!
545                  */
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;
550
551                 /*
552                  * Initialize the new entries and link them into the free list.
553                  */
554                 for (i = SizeVfdCache; i < newCacheSize; i++)
555                 {
556                         MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
557                         VfdCache[i].nextFree = i + 1;
558                         VfdCache[i].fd = VFD_CLOSED;
559                 }
560                 VfdCache[newCacheSize - 1].nextFree = 0;
561                 VfdCache[0].nextFree = SizeVfdCache;
562
563                 /*
564                  * Record the new size
565                  */
566                 SizeVfdCache = newCacheSize;
567         }
568
569         file = VfdCache[0].nextFree;
570
571         VfdCache[0].nextFree = VfdCache[file].nextFree;
572
573         return file;
574 }
575
576 static void
577 FreeVfd(File file)
578 {
579         Vfd                *vfdP = &VfdCache[file];
580
581         DO_DB(elog(LOG, "FreeVfd: %d (%s)",
582                            file, vfdP->fileName ? vfdP->fileName : ""));
583
584         if (vfdP->fileName != NULL)
585         {
586                 free(vfdP->fileName);
587                 vfdP->fileName = NULL;
588         }
589         vfdP->fdstate = 0x0;
590
591         vfdP->nextFree = VfdCache[0].nextFree;
592         VfdCache[0].nextFree = file;
593 }
594
595 /* filepath()
596  * Convert given pathname to absolute.
597  *
598  * Result is a palloc'd string.
599  *
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.)
604  */
605 static char *
606 filepath(const char *filename)
607 {
608         char       *buf;
609
610         /* Not an absolute path name? Then fill in with database path... */
611         if (*filename != '/')
612         {
613                 buf = (char *) palloc(strlen(DatabasePath) + strlen(filename) + 2);
614                 sprintf(buf, "%s/%s", DatabasePath, filename);
615         }
616         else
617                 buf = pstrdup(filename);
618
619 #ifdef FILEDEBUG
620         printf("filepath: path is %s\n", buf);
621 #endif
622
623         return buf;
624 }
625
626 static int
627 FileAccess(File file)
628 {
629         int                     returnValue;
630
631         DO_DB(elog(LOG, "FileAccess %d (%s)",
632                            file, VfdCache[file].fileName));
633
634         /*
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
637          * FD).
638          */
639
640         if (FileIsNotOpen(file))
641         {
642                 returnValue = LruInsert(file);
643                 if (returnValue != 0)
644                         return returnValue;
645         }
646         else if (VfdCache[0].lruLessRecently != file)
647         {
648                 /*
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
651                  * ring.
652                  */
653
654                 Delete(file);
655                 Insert(file);
656         }
657
658         return 0;
659 }
660
661 /*
662  *      Called when we get a shared invalidation message on some relation.
663  */
664 #ifdef NOT_USED
665 void
666 FileInvalidate(File file)
667 {
668         Assert(FileIsValid(file));
669         if (!FileIsNotOpen(file))
670                 LruDelete(file);
671 }
672 #endif
673
674 static File
675 fileNameOpenFile(FileName fileName,
676                                  int fileFlags,
677                                  int fileMode)
678 {
679         File            file;
680         Vfd                *vfdP;
681
682         if (fileName == NULL)
683                 elog(ERROR, "fileNameOpenFile: NULL fname");
684
685         DO_DB(elog(LOG, "fileNameOpenFile: %s %x %o",
686                            fileName, fileFlags, fileMode));
687
688         file = AllocateVfd();
689         vfdP = &VfdCache[file];
690
691         while (nfile + numAllocatedFiles >= pg_nofile())
692         {
693                 if (!ReleaseLruFile())
694                         break;
695         }
696
697         vfdP->fd = BasicOpenFile(fileName, fileFlags, fileMode);
698
699         if (vfdP->fd < 0)
700         {
701                 FreeVfd(file);
702                 return -1;
703         }
704         ++nfile;
705         DO_DB(elog(LOG, "fileNameOpenFile: success %d",
706                            vfdP->fd));
707
708         Insert(file);
709
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);
714
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;
718         vfdP->seekPos = 0;
719         vfdP->fdstate = 0x0;
720
721         return file;
722 }
723
724 /*
725  * open a file in the database directory ($PGDATA/base/...)
726  */
727 File
728 FileNameOpenFile(FileName fileName, int fileFlags, int fileMode)
729 {
730         File            fd;
731         char       *fname;
732
733         fname = filepath(fileName);
734         fd = fileNameOpenFile(fname, fileFlags, fileMode);
735         pfree(fname);
736         return fd;
737 }
738
739 /*
740  * open a file in an arbitrary directory
741  */
742 File
743 PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
744 {
745         return fileNameOpenFile(fileName, fileFlags, fileMode);
746 }
747
748 /*
749  * Open a temporary file that will disappear when we close it.
750  *
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.
754  */
755 File
756 OpenTemporaryFile(void)
757 {
758         char            tempfilepath[128];
759         File            file;
760
761         /*
762          * Generate a tempfile name that's unique within the current
763          * transaction and database instance.
764          */
765         snprintf(tempfilepath, sizeof(tempfilepath),
766                          "%s/%s%d.%ld", PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
767                          MyProcPid, tempFileCounter++);
768
769         /*
770          * Open the file.  Note: we don't use O_EXCL, in case there is an
771          * orphaned temp file that can be reused.
772          */
773         file = FileNameOpenFile(tempfilepath,
774                                                         O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
775                                                         0600);
776         if (file <= 0)
777         {
778                 char       *dirpath;
779
780                 /*
781                  * We might need to create the pg_tempfiles subdirectory, if no
782                  * one has yet done so.
783                  *
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.
787                  */
788                 dirpath = filepath(PG_TEMP_FILES_DIR);
789                 mkdir(dirpath, S_IRWXU);
790                 pfree(dirpath);
791
792                 file = FileNameOpenFile(tempfilepath,
793                                                                 O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
794                                                                 0600);
795                 if (file <= 0)
796                         elog(ERROR, "Failed to create temporary file %s", tempfilepath);
797         }
798
799         /* Mark it for deletion at close or EOXact */
800         VfdCache[file].fdstate |= FD_TEMPORARY;
801
802         return file;
803 }
804
805 /*
806  * close a file when done with it
807  */
808 void
809 FileClose(File file)
810 {
811         Vfd                *vfdP;
812
813         Assert(FileIsValid(file));
814
815         DO_DB(elog(LOG, "FileClose: %d (%s)",
816                            file, VfdCache[file].fileName));
817
818         vfdP = &VfdCache[file];
819
820         if (!FileIsNotOpen(file))
821         {
822                 /* remove the file from the lru ring */
823                 Delete(file);
824
825                 /* close the file */
826                 if (close(vfdP->fd))
827                         elog(LOG, "FileClose: failed to close %s: %m",
828                                  vfdP->fileName);
829
830                 --nfile;
831                 vfdP->fd = VFD_CLOSED;
832         }
833
834         /*
835          * Delete the file if it was temporary
836          */
837         if (vfdP->fdstate & FD_TEMPORARY)
838         {
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",
843                                  vfdP->fileName);
844         }
845
846         /*
847          * Return the Vfd slot to the free list
848          */
849         FreeVfd(file);
850 }
851
852 /*
853  * close a file and forcibly delete the underlying Unix file
854  */
855 void
856 FileUnlink(File file)
857 {
858         Assert(FileIsValid(file));
859
860         DO_DB(elog(LOG, "FileUnlink: %d (%s)",
861                            file, VfdCache[file].fileName));
862
863         /* force FileClose to delete it */
864         VfdCache[file].fdstate |= FD_TEMPORARY;
865
866         FileClose(file);
867 }
868
869 int
870 FileRead(File file, char *buffer, int amount)
871 {
872         int                     returnCode;
873
874         Assert(FileIsValid(file));
875
876         DO_DB(elog(LOG, "FileRead: %d (%s) %ld %d %p",
877                            file, VfdCache[file].fileName,
878                            VfdCache[file].seekPos, amount, buffer));
879
880         FileAccess(file);
881         returnCode = read(VfdCache[file].fd, buffer, amount);
882         if (returnCode > 0)
883                 VfdCache[file].seekPos += returnCode;
884         else
885                 VfdCache[file].seekPos = FileUnknownPos;
886
887         return returnCode;
888 }
889
890 int
891 FileWrite(File file, char *buffer, int amount)
892 {
893         int                     returnCode;
894
895         Assert(FileIsValid(file));
896
897         DO_DB(elog(LOG, "FileWrite: %d (%s) %ld %d %p",
898                            file, VfdCache[file].fileName,
899                            VfdCache[file].seekPos, amount, buffer));
900
901         FileAccess(file);
902
903         errno = 0;
904         returnCode = write(VfdCache[file].fd, buffer, amount);
905
906         /* if write didn't set errno, assume problem is no disk space */
907         if (returnCode != amount && errno == 0)
908                 errno = ENOSPC;
909
910         if (returnCode > 0)
911                 VfdCache[file].seekPos += returnCode;
912         else
913                 VfdCache[file].seekPos = FileUnknownPos;
914
915         return returnCode;
916 }
917
918 long
919 FileSeek(File file, long offset, int whence)
920 {
921         Assert(FileIsValid(file));
922
923         DO_DB(elog(LOG, "FileSeek: %d (%s) %ld %ld %d",
924                            file, VfdCache[file].fileName,
925                            VfdCache[file].seekPos, offset, whence));
926
927         if (FileIsNotOpen(file))
928         {
929                 switch (whence)
930                 {
931                         case SEEK_SET:
932                                 if (offset < 0)
933                                         elog(ERROR, "FileSeek: invalid offset: %ld", offset);
934                                 VfdCache[file].seekPos = offset;
935                                 break;
936                         case SEEK_CUR:
937                                 VfdCache[file].seekPos += offset;
938                                 break;
939                         case SEEK_END:
940                                 FileAccess(file);
941                                 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
942                                 break;
943                         default:
944                                 elog(ERROR, "FileSeek: invalid whence: %d", whence);
945                                 break;
946                 }
947         }
948         else
949         {
950                 switch (whence)
951                 {
952                         case SEEK_SET:
953                                 if (offset < 0)
954                                         elog(ERROR, "FileSeek: invalid offset: %ld", offset);
955                                 if (VfdCache[file].seekPos != offset)
956                                         VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
957                                 break;
958                         case SEEK_CUR:
959                                 if (offset != 0 || VfdCache[file].seekPos == FileUnknownPos)
960                                         VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
961                                 break;
962                         case SEEK_END:
963                                 VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
964                                 break;
965                         default:
966                                 elog(ERROR, "FileSeek: invalid whence: %d", whence);
967                                 break;
968                 }
969         }
970         return VfdCache[file].seekPos;
971 }
972
973 /*
974  * XXX not actually used but here for completeness
975  */
976 #ifdef NOT_USED
977 long
978 FileTell(File file)
979 {
980         Assert(FileIsValid(file));
981         DO_DB(elog(LOG, "FileTell %d (%s)",
982                            file, VfdCache[file].fileName));
983         return VfdCache[file].seekPos;
984 }
985 #endif
986
987 int
988 FileTruncate(File file, long offset)
989 {
990         int                     returnCode;
991
992         Assert(FileIsValid(file));
993
994         DO_DB(elog(LOG, "FileTruncate %d (%s)",
995                            file, VfdCache[file].fileName));
996
997         FileAccess(file);
998         returnCode = ftruncate(VfdCache[file].fd, (size_t) offset);
999         return returnCode;
1000 }
1001
1002
1003 /*
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.
1007  *
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.
1013  *
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).
1017  *
1018  * Ideally this should be the *only* direct call of fopen() in the backend.
1019  */
1020 FILE *
1021 AllocateFile(char *name, char *mode)
1022 {
1023         FILE       *file;
1024
1025         DO_DB(elog(LOG, "AllocateFile: Allocated %d", numAllocatedFiles));
1026
1027         if (numAllocatedFiles >= MAX_ALLOCATED_FILES)
1028                 elog(ERROR, "AllocateFile: too many private FDs demanded");
1029
1030 TryAgain:
1031         if ((file = fopen(name, mode)) != NULL)
1032         {
1033                 allocatedFiles[numAllocatedFiles] = file;
1034                 numAllocatedFiles++;
1035                 return file;
1036         }
1037
1038         if (errno == EMFILE || errno == ENFILE)
1039         {
1040                 int                     save_errno = errno;
1041
1042                 DO_DB(elog(LOG, "AllocateFile: not enough descs, retry, er= %d",
1043                                    errno));
1044                 errno = 0;
1045                 if (ReleaseLruFile())
1046                         goto TryAgain;
1047                 errno = save_errno;
1048         }
1049
1050         return NULL;
1051 }
1052
1053 void
1054 FreeFile(FILE *file)
1055 {
1056         int                     i;
1057
1058         DO_DB(elog(LOG, "FreeFile: Allocated %d", numAllocatedFiles));
1059
1060         /* Remove file from list of allocated files, if it's present */
1061         for (i = numAllocatedFiles; --i >= 0;)
1062         {
1063                 if (allocatedFiles[i] == file)
1064                 {
1065                         numAllocatedFiles--;
1066                         allocatedFiles[i] = allocatedFiles[numAllocatedFiles];
1067                         break;
1068                 }
1069         }
1070         if (i < 0)
1071                 elog(WARNING, "FreeFile: file was not obtained from AllocateFile");
1072
1073         fclose(file);
1074 }
1075
1076 /*
1077  * closeAllVfds
1078  *
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.
1082  */
1083 void
1084 closeAllVfds(void)
1085 {
1086         Index           i;
1087
1088         if (SizeVfdCache > 0)
1089         {
1090                 Assert(FileIsNotOpen(0));               /* Make sure ring not corrupted */
1091                 for (i = 1; i < SizeVfdCache; i++)
1092                 {
1093                         if (!FileIsNotOpen(i))
1094                                 LruDelete(i);
1095                 }
1096         }
1097 }
1098
1099 /*
1100  * AtEOXact_Files
1101  *
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.
1106  */
1107 void
1108 AtEOXact_Files(void)
1109 {
1110         Index           i;
1111
1112         if (SizeVfdCache > 0)
1113         {
1114                 Assert(FileIsNotOpen(0));               /* Make sure ring not corrupted */
1115                 for (i = 1; i < SizeVfdCache; i++)
1116                 {
1117                         if ((VfdCache[i].fdstate & FD_TEMPORARY) &&
1118                                 VfdCache[i].fileName != NULL)
1119                                 FileClose(i);
1120                 }
1121         }
1122
1123         while (numAllocatedFiles > 0)
1124                 FreeFile(allocatedFiles[0]);
1125
1126         /*
1127          * Reset the tempfile name counter to 0; not really necessary, but
1128          * helps keep the names from growing unreasonably long.
1129          */
1130         tempFileCounter = 0;
1131 }
1132
1133
1134 /*
1135  * Remove old temporary files
1136  *
1137  * This should be called during postmaster startup.  It will forcibly
1138  * remove any leftover files created by OpenTemporaryFile.
1139  */
1140 void
1141 RemovePgTempFiles(void)
1142 {
1143         char            db_path[MAXPGPATH];
1144         char            temp_path[MAXPGPATH];
1145         char            rm_path[MAXPGPATH];
1146         DIR                *db_dir;
1147         DIR                *temp_dir;
1148         struct dirent *db_de;
1149         struct dirent *temp_de;
1150
1151         /*
1152          * Cycle through pg_tempfiles for all databases and remove old temp
1153          * files.
1154          */
1155         snprintf(db_path, sizeof(db_path), "%s/base", DataDir);
1156         if ((db_dir = opendir(db_path)) != NULL)
1157         {
1158                 while ((db_de = readdir(db_dir)) != NULL)
1159                 {
1160                         if (strcmp(db_de->d_name, ".") == 0 ||
1161                                 strcmp(db_de->d_name, "..") == 0)
1162                                 continue;
1163
1164                         snprintf(temp_path, sizeof(temp_path),
1165                                          "%s/%s/%s",
1166                                          db_path, db_de->d_name,
1167                                          PG_TEMP_FILES_DIR);
1168                         if ((temp_dir = opendir(temp_path)) != NULL)
1169                         {
1170                                 while ((temp_de = readdir(temp_dir)) != NULL)
1171                                 {
1172                                         if (strcmp(temp_de->d_name, ".") == 0 ||
1173                                                 strcmp(temp_de->d_name, "..") == 0)
1174                                                 continue;
1175
1176                                         snprintf(rm_path, sizeof(temp_path),
1177                                                          "%s/%s/%s/%s",
1178                                                          db_path, db_de->d_name,
1179                                                          PG_TEMP_FILES_DIR,
1180                                                          temp_de->d_name);
1181
1182                                         if (strncmp(temp_de->d_name,
1183                                                                 PG_TEMP_FILE_PREFIX,
1184                                                                 strlen(PG_TEMP_FILE_PREFIX)) == 0)
1185                                                 unlink(rm_path);
1186                                         else
1187                                         {
1188                                                 /*
1189                                                  * would prefer to use elog here, but it's not up
1190                                                  * and running during postmaster startup...
1191                                                  */
1192                                                 fprintf(stderr,
1193                                                                 "Unexpected file found in temporary-files directory: %s\n",
1194                                                                 rm_path);
1195                                         }
1196                                 }
1197                                 closedir(temp_dir);
1198                         }
1199                 }
1200                 closedir(db_dir);
1201         }
1202 }