1 /*-------------------------------------------------------------------------
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
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
19 *-------------------------------------------------------------------------
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
50 * Under the covers the set is one or more directories which will eventually
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;
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.
94 FileSetCreate(FileSet
*fileset
, const char *name
)
99 FilePath(path
, fileset
, name
);
100 file
= PathNameCreateTemporaryFile(path
, false);
102 /* If we failed, see if we need to create the directory on demand. */
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);
119 * Open a file that was created with FileSetCreate() */
121 FileSetOpen(FileSet
*fileset
, const char *name
, int mode
)
123 char path
[MAXPGPATH
];
126 FilePath(path
, fileset
, name
);
127 file
= PathNameOpenTemporaryFile(path
, mode
);
133 * Delete a file that was created with FileSetCreate().
135 * Return true if the file existed, false if didn't.
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.
152 FileSetDeleteAll(FileSet
*fileset
)
154 char dirpath
[MAXPGPATH
];
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
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.
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.
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
);