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