LCOV - differential code coverage report
Current view: top level - src/backend/storage/file - fileset.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 93.8 % 48 45 3 45
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 8 8 8
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * fileset.c
       4                 :  *    Management of named temporary files.
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, 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 CBC         174 : FileSetInit(FileSet *fileset)
      55                 : {
      56                 :     static uint32 counter = 0;
      57                 : 
      58             174 :     fileset->creator_pid = MyProcPid;
      59             174 :     fileset->number = counter;
      60             174 :     counter = (counter + 1) % INT_MAX;
      61                 : 
      62                 :     /* Capture the tablespace OIDs so that all backends agree on them. */
      63             174 :     PrepareTempTablespaces();
      64             174 :     fileset->ntablespaces =
      65             174 :         GetTempTablespaces(&fileset->tablespaces[0],
      66                 :                            lengthof(fileset->tablespaces));
      67             174 :     if (fileset->ntablespaces == 0)
      68                 :     {
      69                 :         /* If the GUC is empty, use current database's default tablespace */
      70             174 :         fileset->tablespaces[0] = MyDatabaseTableSpace;
      71             174 :         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 UBC           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 CBC         174 : }
      89                 : 
      90                 : /*
      91                 :  * Create a new file in the given set.
      92                 :  */
      93                 : File
      94            1439 : FileSetCreate(FileSet *fileset, const char *name)
      95                 : {
      96                 :     char        path[MAXPGPATH];
      97                 :     File        file;
      98                 : 
      99            1439 :     FilePath(path, fileset, name);
     100            1439 :     file = PathNameCreateTemporaryFile(path, false);
     101                 : 
     102                 :     /* If we failed, see if we need to create the directory on demand. */
     103            1439 :     if (file <= 0)
     104                 :     {
     105                 :         char        tempdirpath[MAXPGPATH];
     106                 :         char        filesetpath[MAXPGPATH];
     107             171 :         Oid         tablespace = ChooseTablespace(fileset, name);
     108                 : 
     109             171 :         TempTablespacePath(tempdirpath, tablespace);
     110             171 :         FileSetPath(filesetpath, fileset, tablespace);
     111             171 :         PathNameCreateTemporaryDir(tempdirpath, filesetpath);
     112             171 :         file = PathNameCreateTemporaryFile(path, true);
     113                 :     }
     114                 : 
     115            1439 :     return file;
     116                 : }
     117                 : 
     118                 : /*
     119                 :  * Open a file that was created with FileSetCreate() */
     120                 : File
     121            4059 : FileSetOpen(FileSet *fileset, const char *name, int mode)
     122                 : {
     123                 :     char        path[MAXPGPATH];
     124                 :     File        file;
     125                 : 
     126            4059 :     FilePath(path, fileset, name);
     127            4059 :     file = PathNameOpenTemporaryFile(path, mode);
     128                 : 
     129            4059 :     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            1828 : FileSetDelete(FileSet *fileset, const char *name,
     139                 :               bool error_on_failure)
     140                 : {
     141                 :     char        path[MAXPGPATH];
     142                 : 
     143            1828 :     FilePath(path, fileset, name);
     144                 : 
     145            1828 :     return PathNameDeleteTemporaryFile(path, error_on_failure);
     146                 : }
     147                 : 
     148                 : /*
     149                 :  * Delete all files in the set.
     150                 :  */
     151                 : void
     152             198 : 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             396 :     for (i = 0; i < fileset->ntablespaces; ++i)
     163                 :     {
     164             198 :         FileSetPath(dirpath, fileset, fileset->tablespaces[i]);
     165             198 :         PathNameDeleteTemporaryDir(dirpath);
     166                 :     }
     167             198 : }
     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            7695 : FileSetPath(char *path, FileSet *fileset, Oid tablespace)
     175                 : {
     176                 :     char        tempdirpath[MAXPGPATH];
     177                 : 
     178            7695 :     TempTablespacePath(tempdirpath, tablespace);
     179            7695 :     snprintf(path, MAXPGPATH, "%s/%s%lu.%u.fileset",
     180                 :              tempdirpath, PG_TEMP_FILE_PREFIX,
     181            7695 :              (unsigned long) fileset->creator_pid, fileset->number);
     182            7695 : }
     183                 : 
     184                 : /*
     185                 :  * Sorting has to determine which tablespace a given temporary file belongs in.
     186                 :  */
     187                 : static Oid
     188            7497 : ChooseTablespace(const FileSet *fileset, const char *name)
     189                 : {
     190            7497 :     uint32      hash = hash_any((const unsigned char *) name, strlen(name));
     191                 : 
     192            7497 :     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            7326 : FilePath(char *path, FileSet *fileset, const char *name)
     200                 : {
     201                 :     char        dirpath[MAXPGPATH];
     202                 : 
     203            7326 :     FileSetPath(dirpath, fileset, ChooseTablespace(fileset, name));
     204            7326 :     snprintf(path, MAXPGPATH, "%s/%s", dirpath, name);
     205            7326 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a