LCOV - code coverage report
Current view: top level - src/backend/storage/file - fileset.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 93.8 % 48 45
Test Date: 2026-02-28 03:14:59 Functions: 100.0 % 8 8
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * fileset.c
       4              :  *    Management of named temporary files.
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7              :  * Portions Copyright (c) 1994, Regents of the University of California
       8              :  *
       9              :  * IDENTIFICATION
      10              :  *    src/backend/storage/file/fileset.c
      11              :  *
      12              :  * FileSets provide a temporary namespace (think directory) so that files can
      13              :  * be discovered by name.
      14              :  *
      15              :  * FileSets can be used by backends when the temporary files need to be
      16              :  * opened/closed multiple times and the underlying files need to survive across
      17              :  * transactions.
      18              :  *
      19              :  *-------------------------------------------------------------------------
      20              :  */
      21              : 
      22              : #include "postgres.h"
      23              : 
      24              : #include <limits.h>
      25              : 
      26              : #include "commands/tablespace.h"
      27              : #include "common/file_utils.h"
      28              : #include "common/hashfn.h"
      29              : #include "miscadmin.h"
      30              : #include "storage/fileset.h"
      31              : 
      32              : static void FileSetPath(char *path, FileSet *fileset, Oid tablespace);
      33              : static void FilePath(char *path, FileSet *fileset, const char *name);
      34              : static Oid  ChooseTablespace(const FileSet *fileset, const char *name);
      35              : 
      36              : /*
      37              :  * Initialize a space for temporary files. This API can be used by shared
      38              :  * fileset as well as if the temporary files are used only by single backend
      39              :  * but the files need to be opened and closed multiple times and also the
      40              :  * underlying files need to survive across transactions.
      41              :  *
      42              :  * The callers are expected to explicitly remove such files by using
      43              :  * FileSetDelete/FileSetDeleteAll.
      44              :  *
      45              :  * Files will be distributed over the tablespaces configured in
      46              :  * temp_tablespaces.
      47              :  *
      48              :  * Under the covers the set is one or more directories which will eventually
      49              :  * be deleted.
      50              :  */
      51              : void
      52          210 : FileSetInit(FileSet *fileset)
      53              : {
      54              :     static uint32 counter = 0;
      55              : 
      56          210 :     fileset->creator_pid = MyProcPid;
      57          210 :     fileset->number = counter;
      58          210 :     counter = (counter + 1) % INT_MAX;
      59              : 
      60              :     /* Capture the tablespace OIDs so that all backends agree on them. */
      61          210 :     PrepareTempTablespaces();
      62          210 :     fileset->ntablespaces =
      63          210 :         GetTempTablespaces(&fileset->tablespaces[0],
      64              :                            lengthof(fileset->tablespaces));
      65          210 :     if (fileset->ntablespaces == 0)
      66              :     {
      67              :         /* If the GUC is empty, use current database's default tablespace */
      68          210 :         fileset->tablespaces[0] = MyDatabaseTableSpace;
      69          210 :         fileset->ntablespaces = 1;
      70              :     }
      71              :     else
      72              :     {
      73              :         int         i;
      74              : 
      75              :         /*
      76              :          * An entry of InvalidOid means use the default tablespace for the
      77              :          * current database.  Replace that now, to be sure that all users of
      78              :          * the FileSet agree on what to do.
      79              :          */
      80            0 :         for (i = 0; i < fileset->ntablespaces; i++)
      81              :         {
      82            0 :             if (fileset->tablespaces[i] == InvalidOid)
      83            0 :                 fileset->tablespaces[i] = MyDatabaseTableSpace;
      84              :         }
      85              :     }
      86          210 : }
      87              : 
      88              : /*
      89              :  * Create a new file in the given set.
      90              :  */
      91              : File
      92         1481 : FileSetCreate(FileSet *fileset, const char *name)
      93              : {
      94              :     char        path[MAXPGPATH];
      95              :     File        file;
      96              : 
      97         1481 :     FilePath(path, fileset, name);
      98         1481 :     file = PathNameCreateTemporaryFile(path, false);
      99              : 
     100              :     /* If we failed, see if we need to create the directory on demand. */
     101         1481 :     if (file <= 0)
     102              :     {
     103              :         char        tempdirpath[MAXPGPATH];
     104              :         char        filesetpath[MAXPGPATH];
     105          201 :         Oid         tablespace = ChooseTablespace(fileset, name);
     106              : 
     107          201 :         TempTablespacePath(tempdirpath, tablespace);
     108          201 :         FileSetPath(filesetpath, fileset, tablespace);
     109          201 :         PathNameCreateTemporaryDir(tempdirpath, filesetpath);
     110          201 :         file = PathNameCreateTemporaryFile(path, true);
     111              :     }
     112              : 
     113         1481 :     return file;
     114              : }
     115              : 
     116              : /*
     117              :  * Open a file that was created with FileSetCreate()
     118              :  */
     119              : File
     120         4111 : FileSetOpen(FileSet *fileset, const char *name, int mode)
     121              : {
     122              :     char        path[MAXPGPATH];
     123              :     File        file;
     124              : 
     125         4111 :     FilePath(path, fileset, name);
     126         4111 :     file = PathNameOpenTemporaryFile(path, mode);
     127              : 
     128         4111 :     return file;
     129              : }
     130              : 
     131              : /*
     132              :  * Delete a file that was created with FileSetCreate().
     133              :  *
     134              :  * Return true if the file existed, false if didn't.
     135              :  */
     136              : bool
     137         1872 : FileSetDelete(FileSet *fileset, const char *name,
     138              :               bool error_on_failure)
     139              : {
     140              :     char        path[MAXPGPATH];
     141              : 
     142         1872 :     FilePath(path, fileset, name);
     143              : 
     144         1872 :     return PathNameDeleteTemporaryFile(path, error_on_failure);
     145              : }
     146              : 
     147              : /*
     148              :  * Delete all files in the set.
     149              :  */
     150              : void
     151          234 : FileSetDeleteAll(FileSet *fileset)
     152              : {
     153              :     char        dirpath[MAXPGPATH];
     154              :     int         i;
     155              : 
     156              :     /*
     157              :      * Delete the directory we created in each tablespace.  Doesn't fail
     158              :      * because we use this in error cleanup paths, but can generate LOG
     159              :      * message on IO error.
     160              :      */
     161          468 :     for (i = 0; i < fileset->ntablespaces; ++i)
     162              :     {
     163          234 :         FileSetPath(dirpath, fileset, fileset->tablespaces[i]);
     164          234 :         PathNameDeleteTemporaryDir(dirpath);
     165              :     }
     166          234 : }
     167              : 
     168              : /*
     169              :  * Build the path for the directory holding the files backing a FileSet in a
     170              :  * given tablespace.
     171              :  */
     172              : static void
     173         7899 : FileSetPath(char *path, FileSet *fileset, Oid tablespace)
     174              : {
     175              :     char        tempdirpath[MAXPGPATH];
     176              : 
     177         7899 :     TempTablespacePath(tempdirpath, tablespace);
     178         7899 :     snprintf(path, MAXPGPATH, "%s/%s%lu.%u.fileset",
     179              :              tempdirpath, PG_TEMP_FILE_PREFIX,
     180         7899 :              (unsigned long) fileset->creator_pid, fileset->number);
     181         7899 : }
     182              : 
     183              : /*
     184              :  * Sorting has to determine which tablespace a given temporary file belongs in.
     185              :  */
     186              : static Oid
     187         7665 : ChooseTablespace(const FileSet *fileset, const char *name)
     188              : {
     189         7665 :     uint32      hash = hash_bytes((const unsigned char *) name, strlen(name));
     190              : 
     191         7665 :     return fileset->tablespaces[hash % fileset->ntablespaces];
     192              : }
     193              : 
     194              : /*
     195              :  * Compute the full path of a file in a FileSet.
     196              :  */
     197              : static void
     198         7464 : FilePath(char *path, FileSet *fileset, const char *name)
     199              : {
     200              :     char        dirpath[MAXPGPATH];
     201              : 
     202         7464 :     FileSetPath(dirpath, fileset, ChooseTablespace(fileset, name));
     203         7464 :     snprintf(path, MAXPGPATH, "%s/%s", dirpath, name);
     204         7464 : }
        

Generated by: LCOV version 2.0-1