Crash restarts currently don't clean up temporary files, as a debugging aid.
If a left-over file happens to have the same name as a segment file we're
trying to create, we'll just truncate and reuse it, but there is a problem:
BufFileOpenShared() determines how many segment files exist by trying to open
.0, .1, .2, ... until it finds no more files. It might be confused by a junk
file that has the next segment number. To defend against that, make sure we
always create a gap after the end file by unlinking the following name if it
exists. Also make it an error to try to open a BufFile that doesn't exist
(has no segment 0), so as not to encourage the development of client code
that depends on an interface that we can't reliably provide.
Author: Thomas Munro
Reviewed-By: Andres Freund
Discussion: https://postgr.es/m/CAEepm%3D2jhCbC_GFQJaaDhWxLB4EXtT3vVd5czuRNaqF5CWSTog%40mail.gmail.com
char name[MAXPGPATH];
File file;
+ /*
+ * It is possible that there are files left over from before a crash
+ * restart with the same name. In order for BufFileOpenShared()
+ * not to get confused about how many segments there are, we'll unlink
+ * the next segment number if it already exists.
+ */
+ SharedSegmentName(name, buffile->name, segment + 1);
+ SharedFileSetDelete(buffile->fileset, name, true);
+
+ /* Create the new segment. */
SharedSegmentName(name, buffile->name, segment);
file = SharedFileSetCreate(buffile->fileset, name);
* name.
*/
if (nfiles == 0)
- return NULL;
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not open BufFile \"%s\"", name)));
file->numFiles = nfiles;
file->files = files;