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()
118 */
119File
120FileSetOpen(FileSet *fileset, const char *name, int mode)
121{
122 char path[MAXPGPATH];
123 File file;
124
125 FilePath(path, fileset, name);
126 file = PathNameOpenTemporaryFile(path, mode);
127
128 return file;
129}
130
131/*
132 * Delete a file that was created with FileSetCreate().
133 *
134 * Return true if the file existed, false if didn't.
135 */
136bool
137FileSetDelete(FileSet *fileset, const char *name,
138 bool error_on_failure)
139{
140 char path[MAXPGPATH];
141
142 FilePath(path, fileset, name);
143
144 return PathNameDeleteTemporaryFile(path, error_on_failure);
145}
146
147/*
148 * Delete all files in the set.
149 */
150void
152{
153 char dirpath[MAXPGPATH];
154 int i;
155
156 /*
157 * Delete the directory we created in each tablespace. Doesn't fail
158 * because we use this in error cleanup paths, but can generate LOG
159 * message on IO error.
160 */
161 for (i = 0; i < fileset->ntablespaces; ++i)
162 {
163 FileSetPath(dirpath, fileset, fileset->tablespaces[i]);
165 }
166}
167
168/*
169 * Build the path for the directory holding the files backing a FileSet in a
170 * given tablespace.
171 */
172static void
173FileSetPath(char *path, FileSet *fileset, Oid tablespace)
174{
175 char tempdirpath[MAXPGPATH];
176
177 TempTablespacePath(tempdirpath, tablespace);
178 snprintf(path, MAXPGPATH, "%s/%s%lu.%u.fileset",
179 tempdirpath, PG_TEMP_FILE_PREFIX,
180 (unsigned long) fileset->creator_pid, fileset->number);
181}
182
183/*
184 * Sorting has to determine which tablespace a given temporary file belongs in.
185 */
186static Oid
187ChooseTablespace(const FileSet *fileset, const char *name)
188{
189 uint32 hash = hash_bytes((const unsigned char *) name, strlen(name));
190
191 return fileset->tablespaces[hash % fileset->ntablespaces];
192}
193
194/*
195 * Compute the full path of a file in a FileSet.
196 */
197static void
198FilePath(char *path, FileSet *fileset, const char *name)
199{
200 char dirpath[MAXPGPATH];
201
202 FileSetPath(dirpath, fileset, ChooseTablespace(fileset, name));
203 snprintf(path, MAXPGPATH, "%s/%s", dirpath, name);
204}
void PrepareTempTablespaces(void)
Definition: tablespace.c:1331
uint32_t uint32
Definition: c.h:552
#define lengthof(array)
Definition: c.h:801
int GetTempTablespaces(Oid *tableSpaces, int numSpaces)
Definition: fd.c:3137
File PathNameOpenTemporaryFile(const char *path, int mode)
Definition: fd.c:1885
File PathNameCreateTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1845
void PathNameDeleteTemporaryDir(const char *dirname)
Definition: fd.c:1675
bool PathNameDeleteTemporaryFile(const char *path, bool error_on_failure)
Definition: fd.c:1916
void PathNameCreateTemporaryDir(const char *basedir, const char *directory)
Definition: fd.c:1644
void TempTablespacePath(char *path, Oid tablespace)
Definition: fd.c:1763
int File
Definition: fd.h:51
#define PG_TEMP_FILE_PREFIX
Definition: file_utils.h:64
File FileSetOpen(FileSet *fileset, const char *name, int mode)
Definition: fileset.c:120
bool FileSetDelete(FileSet *fileset, const char *name, bool error_on_failure)
Definition: fileset.c:137
static void FilePath(char *path, FileSet *fileset, const char *name)
Definition: fileset.c:198
void FileSetInit(FileSet *fileset)
Definition: fileset.c:52
void FileSetDeleteAll(FileSet *fileset)
Definition: fileset.c:151
static void FileSetPath(char *path, FileSet *fileset, Oid tablespace)
Definition: fileset.c:173
static Oid ChooseTablespace(const FileSet *fileset, const char *name)
Definition: fileset.c:187
File FileSetCreate(FileSet *fileset, const char *name)
Definition: fileset.c:92
int MyProcPid
Definition: globals.c:47
Oid MyDatabaseTableSpace
Definition: globals.c:96
uint32 hash_bytes(const unsigned char *k, int keylen)
Definition: hashfn.c:146
int i
Definition: isn.c:77
static PgChecksumMode mode
Definition: pg_checksums.c:56
#define MAXPGPATH
static char * tablespace
Definition: pgbench.c:217
#define snprintf
Definition: port.h:260
#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