PostgreSQL Source Code  git master
fileset.c
Go to the documentation of this file.
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
53 {
54  static uint32 counter = 0;
55 
56  fileset->creator_pid = MyProcPid;
57  fileset->number = counter;
58  counter = (counter + 1) % INT_MAX;
59 
60  /* Capture the tablespace OIDs so that all backends agree on them. */
62  fileset->ntablespaces =
63  GetTempTablespaces(&fileset->tablespaces[0],
64  lengthof(fileset->tablespaces));
65  if (fileset->ntablespaces == 0)
66  {
67  /* If the GUC is empty, use current database's default tablespace */
68  fileset->tablespaces[0] = MyDatabaseTableSpace;
69  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  for (i = 0; i < fileset->ntablespaces; i++)
81  {
82  if (fileset->tablespaces[i] == InvalidOid)
84  }
85  }
86 }
87 
88 /*
89  * Create a new file in the given set.
90  */
91 File
92 FileSetCreate(FileSet *fileset, const char *name)
93 {
94  char path[MAXPGPATH];
95  File file;
96 
97  FilePath(path, fileset, name);
98  file = PathNameCreateTemporaryFile(path, false);
99 
100  /* If we failed, see if we need to create the directory on demand. */
101  if (file <= 0)
102  {
103  char tempdirpath[MAXPGPATH];
104  char filesetpath[MAXPGPATH];
105  Oid tablespace = ChooseTablespace(fileset, name);
106 
107  TempTablespacePath(tempdirpath, tablespace);
108  FileSetPath(filesetpath, fileset, tablespace);
109  PathNameCreateTemporaryDir(tempdirpath, filesetpath);
110  file = PathNameCreateTemporaryFile(path, true);
111  }
112 
113  return file;
114 }
115 
116 /*
117  * Open a file that was created with FileSetCreate() */
118 File
119 FileSetOpen(FileSet *fileset, const char *name, int mode)
120 {
121  char path[MAXPGPATH];
122  File file;
123 
124  FilePath(path, fileset, name);
125  file = PathNameOpenTemporaryFile(path, mode);
126 
127  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 FileSetDelete(FileSet *fileset, const char *name,
137  bool error_on_failure)
138 {
139  char path[MAXPGPATH];
140 
141  FilePath(path, fileset, name);
142 
143  return PathNameDeleteTemporaryFile(path, error_on_failure);
144 }
145 
146 /*
147  * Delete all files in the set.
148  */
149 void
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  for (i = 0; i < fileset->ntablespaces; ++i)
161  {
162  FileSetPath(dirpath, fileset, fileset->tablespaces[i]);
164  }
165 }
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 FileSetPath(char *path, FileSet *fileset, Oid tablespace)
173 {
174  char tempdirpath[MAXPGPATH];
175 
176  TempTablespacePath(tempdirpath, tablespace);
177  snprintf(path, MAXPGPATH, "%s/%s%lu.%u.fileset",
178  tempdirpath, PG_TEMP_FILE_PREFIX,
179  (unsigned long) fileset->creator_pid, fileset->number);
180 }
181 
182 /*
183  * Sorting has to determine which tablespace a given temporary file belongs in.
184  */
185 static Oid
186 ChooseTablespace(const FileSet *fileset, const char *name)
187 {
188  uint32 hash = hash_any((const unsigned char *) name, strlen(name));
189 
190  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 FilePath(char *path, FileSet *fileset, const char *name)
198 {
199  char dirpath[MAXPGPATH];
200 
201  FileSetPath(dirpath, fileset, ChooseTablespace(fileset, name));
202  snprintf(path, MAXPGPATH, "%s/%s", dirpath, name);
203 }
void PrepareTempTablespaces(void)
Definition: tablespace.c:1331
unsigned int uint32
Definition: c.h:506
#define lengthof(array)
Definition: c.h:788
int GetTempTablespaces(Oid *tableSpaces, int numSpaces)
Definition: fd.c:3093
File PathNameOpenTemporaryFile(const char *path, int mode)
Definition: fd.c:1901
File PathNameCreateTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1861
void PathNameDeleteTemporaryDir(const char *dirname)
Definition: fd.c:1691
bool PathNameDeleteTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1932
void PathNameCreateTemporaryDir(const char *basedir, const char *directory)
Definition: fd.c:1660
void TempTablespacePath(char *path, Oid tablespace)
Definition: fd.c:1779
int File
Definition: fd.h:51
#define PG_TEMP_FILE_PREFIX
Definition: file_utils.h:63
File FileSetOpen(FileSet *fileset, const char *name, int mode)
Definition: fileset.c:119
bool FileSetDelete(FileSet *fileset, const char *name, bool error_on_failure)
Definition: fileset.c:136
static void FilePath(char *path, FileSet *fileset, const char *name)
Definition: fileset.c:197
void FileSetInit(FileSet *fileset)
Definition: fileset.c:52
void FileSetDeleteAll(FileSet *fileset)
Definition: fileset.c:150
static void FileSetPath(char *path, FileSet *fileset, Oid tablespace)
Definition: fileset.c:172
static Oid ChooseTablespace(const FileSet *fileset, const char *name)
Definition: fileset.c:186
File FileSetCreate(FileSet *fileset, const char *name)
Definition: fileset.c:92
int MyProcPid
Definition: globals.c:45
Oid MyDatabaseTableSpace
Definition: globals.c:93
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31
int i
Definition: isn.c:73
static PgChecksumMode mode
Definition: pg_checksums.c:56
#define MAXPGPATH
char * tablespace
Definition: pgbench.c:216
#define snprintf
Definition: port.h:238
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715
Oid tablespaces[8]
Definition: fileset.h:27
pid_t creator_pid
Definition: fileset.h:24
uint32 number
Definition: fileset.h:25
int ntablespaces
Definition: fileset.h:26
const char * name