Update copyright for 2022
[pgsql.git] / src / backend / storage / file / fileset.c
blob9c63f2b26771d90ce65d94f0295635b0bb080dfc
1 /*-------------------------------------------------------------------------
3 * fileset.c
4 * Management of named temporary files.
6 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * IDENTIFICATION
10 * src/backend/storage/file/fileset.c
12 * FileSets provide a temporary namespace (think directory) so that files can
13 * be discovered by name.
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.
19 *-------------------------------------------------------------------------
22 #include "postgres.h"
24 #include <limits.h>
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"
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);
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.
44 * The callers are expected to explicitly remove such files by using
45 * FileSetDelete/FileSetDeleteAll.
47 * Files will be distributed over the tablespaces configured in
48 * temp_tablespaces.
50 * Under the covers the set is one or more directories which will eventually
51 * be deleted.
53 void
54 FileSetInit(FileSet *fileset)
56 static uint32 counter = 0;
58 fileset->creator_pid = MyProcPid;
59 fileset->number = counter;
60 counter = (counter + 1) % INT_MAX;
62 /* Capture the tablespace OIDs so that all backends agree on them. */
63 PrepareTempTablespaces();
64 fileset->ntablespaces =
65 GetTempTablespaces(&fileset->tablespaces[0],
66 lengthof(fileset->tablespaces));
67 if (fileset->ntablespaces == 0)
69 /* If the GUC is empty, use current database's default tablespace */
70 fileset->tablespaces[0] = MyDatabaseTableSpace;
71 fileset->ntablespaces = 1;
73 else
75 int i;
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.
82 for (i = 0; i < fileset->ntablespaces; i++)
84 if (fileset->tablespaces[i] == InvalidOid)
85 fileset->tablespaces[i] = MyDatabaseTableSpace;
91 * Create a new file in the given set.
93 File
94 FileSetCreate(FileSet *fileset, const char *name)
96 char path[MAXPGPATH];
97 File file;
99 FilePath(path, fileset, name);
100 file = PathNameCreateTemporaryFile(path, false);
102 /* If we failed, see if we need to create the directory on demand. */
103 if (file <= 0)
105 char tempdirpath[MAXPGPATH];
106 char filesetpath[MAXPGPATH];
107 Oid tablespace = ChooseTablespace(fileset, name);
109 TempTablespacePath(tempdirpath, tablespace);
110 FileSetPath(filesetpath, fileset, tablespace);
111 PathNameCreateTemporaryDir(tempdirpath, filesetpath);
112 file = PathNameCreateTemporaryFile(path, true);
115 return file;
119 * Open a file that was created with FileSetCreate() */
120 File
121 FileSetOpen(FileSet *fileset, const char *name, int mode)
123 char path[MAXPGPATH];
124 File file;
126 FilePath(path, fileset, name);
127 file = PathNameOpenTemporaryFile(path, mode);
129 return file;
133 * Delete a file that was created with FileSetCreate().
135 * Return true if the file existed, false if didn't.
137 bool
138 FileSetDelete(FileSet *fileset, const char *name,
139 bool error_on_failure)
141 char path[MAXPGPATH];
143 FilePath(path, fileset, name);
145 return PathNameDeleteTemporaryFile(path, error_on_failure);
149 * Delete all files in the set.
151 void
152 FileSetDeleteAll(FileSet *fileset)
154 char dirpath[MAXPGPATH];
155 int i;
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.
162 for (i = 0; i < fileset->ntablespaces; ++i)
164 FileSetPath(dirpath, fileset, fileset->tablespaces[i]);
165 PathNameDeleteTemporaryDir(dirpath);
170 * Build the path for the directory holding the files backing a FileSet in a
171 * given tablespace.
173 static void
174 FileSetPath(char *path, FileSet *fileset, Oid tablespace)
176 char tempdirpath[MAXPGPATH];
178 TempTablespacePath(tempdirpath, tablespace);
179 snprintf(path, MAXPGPATH, "%s/%s%lu.%u.fileset",
180 tempdirpath, PG_TEMP_FILE_PREFIX,
181 (unsigned long) fileset->creator_pid, fileset->number);
185 * Sorting has to determine which tablespace a given temporary file belongs in.
187 static Oid
188 ChooseTablespace(const FileSet *fileset, const char *name)
190 uint32 hash = hash_any((const unsigned char *) name, strlen(name));
192 return fileset->tablespaces[hash % fileset->ntablespaces];
196 * Compute the full path of a file in a FileSet.
198 static void
199 FilePath(char *path, FileSet *fileset, const char *name)
201 char dirpath[MAXPGPATH];
203 FileSetPath(dirpath, fileset, ChooseTablespace(fileset, name));
204 snprintf(path, MAXPGPATH, "%s/%s", dirpath, name);