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-2025, 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
32static void FileSetPath(char *path, FileSet *fileset, Oid tablespace);
33static void FilePath(char *path, FileSet *fileset, const char *name);
34static 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 */
51void
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 =
64 lengthof(fileset->tablespaces));
65 if (fileset->ntablespaces == 0)
66 {
67 /* If the GUC is empty, use current database's default tablespace */
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 */
91File
92FileSetCreate(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];
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() */
118File
119FileSetOpen(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 */
135bool
136FileSetDelete(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 */
149void
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 */
171static void
172FileSetPath(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 */
185static Oid
186ChooseTablespace(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 */
196static void
197FilePath(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
uint32_t uint32
Definition: c.h:488
#define lengthof(array)
Definition: c.h:745
int GetTempTablespaces(Oid *tableSpaces, int numSpaces)
Definition: fd.c:3115
File PathNameOpenTemporaryFile(const char *path, int mode)
Definition: fd.c:1900
File PathNameCreateTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1860
void PathNameDeleteTemporaryDir(const char *dirname)
Definition: fd.c:1690
bool PathNameDeleteTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1931
void PathNameCreateTemporaryDir(const char *basedir, const char *directory)
Definition: fd.c:1659
void TempTablespacePath(char *path, Oid tablespace)
Definition: fd.c:1778
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:46
Oid MyDatabaseTableSpace
Definition: globals.c:95
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31
int i
Definition: isn.c:72
static PgChecksumMode mode
Definition: pg_checksums.c:55
#define MAXPGPATH
static char * tablespace
Definition: pgbench.c:216
#define snprintf
Definition: port.h:239
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
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