LCOV - code coverage report
Current view: top level - src/backend/storage/file - fileset.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 45 48 93.8 %
Date: 2024-04-20 02:11:47 Functions: 8 8 100.0 %
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-2024, 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         358 : FileSetInit(FileSet *fileset)
      53             : {
      54             :     static uint32 counter = 0;
      55             : 
      56         358 :     fileset->creator_pid = MyProcPid;
      57         358 :     fileset->number = counter;
      58         358 :     counter = (counter + 1) % INT_MAX;
      59             : 
      60             :     /* Capture the tablespace OIDs so that all backends agree on them. */
      61         358 :     PrepareTempTablespaces();
      62         358 :     fileset->ntablespaces =
      63         358 :         GetTempTablespaces(&fileset->tablespaces[0],
      64             :                            lengthof(fileset->tablespaces));
      65         358 :     if (fileset->ntablespaces == 0)
      66             :     {
      67             :         /* If the GUC is empty, use current database's default tablespace */
      68         358 :         fileset->tablespaces[0] = MyDatabaseTableSpace;
      69         358 :         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         358 : }
      87             : 
      88             : /*
      89             :  * Create a new file in the given set.
      90             :  */
      91             : File
      92        2206 : FileSetCreate(FileSet *fileset, const char *name)
      93             : {
      94             :     char        path[MAXPGPATH];
      95             :     File        file;
      96             : 
      97        2206 :     FilePath(path, fileset, name);
      98        2206 :     file = PathNameCreateTemporaryFile(path, false);
      99             : 
     100             :     /* If we failed, see if we need to create the directory on demand. */
     101        2206 :     if (file <= 0)
     102             :     {
     103             :         char        tempdirpath[MAXPGPATH];
     104             :         char        filesetpath[MAXPGPATH];
     105         328 :         Oid         tablespace = ChooseTablespace(fileset, name);
     106             : 
     107         328 :         TempTablespacePath(tempdirpath, tablespace);
     108         328 :         FileSetPath(filesetpath, fileset, tablespace);
     109         328 :         PathNameCreateTemporaryDir(tempdirpath, filesetpath);
     110         328 :         file = PathNameCreateTemporaryFile(path, true);
     111             :     }
     112             : 
     113        2206 :     return file;
     114             : }
     115             : 
     116             : /*
     117             :  * Open a file that was created with FileSetCreate() */
     118             : File
     119        6734 : FileSetOpen(FileSet *fileset, const char *name, int mode)
     120             : {
     121             :     char        path[MAXPGPATH];
     122             :     File        file;
     123             : 
     124        6734 :     FilePath(path, fileset, name);
     125        6734 :     file = PathNameOpenTemporaryFile(path, mode);
     126             : 
     127        6734 :     return file;
     128             : }
     129             : 
     130             : /*
     131             :  * Delete a file that was created with FileSetCreate().
     132             :  *
     133             :  * Return true if the file existed, false if didn't.
     134             :  */
     135             : bool
     136        2988 : FileSetDelete(FileSet *fileset, const char *name,
     137             :               bool error_on_failure)
     138             : {
     139             :     char        path[MAXPGPATH];
     140             : 
     141        2988 :     FilePath(path, fileset, name);
     142             : 
     143        2988 :     return PathNameDeleteTemporaryFile(path, error_on_failure);
     144             : }
     145             : 
     146             : /*
     147             :  * Delete all files in the set.
     148             :  */
     149             : void
     150         406 : FileSetDeleteAll(FileSet *fileset)
     151             : {
     152             :     char        dirpath[MAXPGPATH];
     153             :     int         i;
     154             : 
     155             :     /*
     156             :      * Delete the directory we created in each tablespace.  Doesn't fail
     157             :      * because we use this in error cleanup paths, but can generate LOG
     158             :      * message on IO error.
     159             :      */
     160         812 :     for (i = 0; i < fileset->ntablespaces; ++i)
     161             :     {
     162         406 :         FileSetPath(dirpath, fileset, fileset->tablespaces[i]);
     163         406 :         PathNameDeleteTemporaryDir(dirpath);
     164             :     }
     165         406 : }
     166             : 
     167             : /*
     168             :  * Build the path for the directory holding the files backing a FileSet in a
     169             :  * given tablespace.
     170             :  */
     171             : static void
     172       12662 : FileSetPath(char *path, FileSet *fileset, Oid tablespace)
     173             : {
     174             :     char        tempdirpath[MAXPGPATH];
     175             : 
     176       12662 :     TempTablespacePath(tempdirpath, tablespace);
     177       12662 :     snprintf(path, MAXPGPATH, "%s/%s%lu.%u.fileset",
     178             :              tempdirpath, PG_TEMP_FILE_PREFIX,
     179       12662 :              (unsigned long) fileset->creator_pid, fileset->number);
     180       12662 : }
     181             : 
     182             : /*
     183             :  * Sorting has to determine which tablespace a given temporary file belongs in.
     184             :  */
     185             : static Oid
     186       12256 : ChooseTablespace(const FileSet *fileset, const char *name)
     187             : {
     188       12256 :     uint32      hash = hash_any((const unsigned char *) name, strlen(name));
     189             : 
     190       12256 :     return fileset->tablespaces[hash % fileset->ntablespaces];
     191             : }
     192             : 
     193             : /*
     194             :  * Compute the full path of a file in a FileSet.
     195             :  */
     196             : static void
     197       11928 : FilePath(char *path, FileSet *fileset, const char *name)
     198             : {
     199             :     char        dirpath[MAXPGPATH];
     200             : 
     201       11928 :     FileSetPath(dirpath, fileset, ChooseTablespace(fileset, name));
     202       11928 :     snprintf(path, MAXPGPATH, "%s/%s", dirpath, name);
     203       11928 : }

Generated by: LCOV version 1.14