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

Generated by: LCOV version 1.13