diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c index 35e8f12e62..0399f11607 100644 --- a/src/backend/storage/file/buffile.c +++ b/src/backend/storage/file/buffile.c @@ -100,7 +100,7 @@ static void extendBufFile(BufFile *file); static void BufFileLoadBuffer(BufFile *file); static void BufFileDumpBuffer(BufFile *file); static int BufFileFlush(BufFile *file); -static File MakeNewSharedSegment(BufFile *file, int segment); +static File MakeNewSharedSegment(BufFile *file, int segment, bool eoxact_close); /* * Create BufFile and perform the common initialization. @@ -156,7 +156,7 @@ extendBufFile(BufFile *file) if (file->fileset == NULL) pfile = OpenTemporaryFile(file->isInterXact); else - pfile = MakeNewSharedSegment(file, file->numFiles); + pfile = MakeNewSharedSegment(file, file->numFiles, true); Assert(pfile >= 0); @@ -219,7 +219,7 @@ SharedSegmentName(char *name, const char *buffile_name, int segment) * Create a new segment file backing a shared BufFile. */ static File -MakeNewSharedSegment(BufFile *buffile, int segment) +MakeNewSharedSegment(BufFile *buffile, int segment, bool eoxact_close) { char name[MAXPGPATH]; File file; @@ -235,7 +235,7 @@ MakeNewSharedSegment(BufFile *buffile, int segment) /* Create the new segment. */ SharedSegmentName(name, buffile->name, segment); - file = SharedFileSetCreate(buffile->fileset, name); + file = SharedFileSetCreate(buffile->fileset, name, eoxact_close); /* SharedFileSetCreate would've errored out */ Assert(file > 0); @@ -255,7 +255,8 @@ MakeNewSharedSegment(BufFile *buffile, int segment) * unrelated SharedFileSet objects. */ BufFile * -BufFileCreateShared(SharedFileSet *fileset, const char *name) +BufFileCreateShared(SharedFileSet *fileset, const char *name, + bool eoxact_close) { BufFile *file; @@ -263,7 +264,7 @@ BufFileCreateShared(SharedFileSet *fileset, const char *name) file->fileset = fileset; file->name = pstrdup(name); file->files = (File *) palloc(sizeof(File)); - file->files[0] = MakeNewSharedSegment(file, 0); + file->files[0] = MakeNewSharedSegment(file, 0, eoxact_close); file->readOnly = false; return file; @@ -277,7 +278,8 @@ BufFileCreateShared(SharedFileSet *fileset, const char *name) * backends and render it read-only. */ BufFile * -BufFileOpenShared(SharedFileSet *fileset, const char *name) +BufFileOpenShared(SharedFileSet *fileset, const char *name, bool eoxact_close, + bool read_only) { BufFile *file; char segment_name[MAXPGPATH]; @@ -301,7 +303,8 @@ BufFileOpenShared(SharedFileSet *fileset, const char *name) } /* Try to load a segment. */ SharedSegmentName(segment_name, name, nfiles); - files[nfiles] = SharedFileSetOpen(fileset, segment_name); + files[nfiles] = SharedFileSetOpen(fileset, segment_name, eoxact_close, + read_only); if (files[nfiles] <= 0) break; ++nfiles; @@ -321,7 +324,7 @@ BufFileOpenShared(SharedFileSet *fileset, const char *name) file = makeBufFileCommon(nfiles); file->files = files; - file->readOnly = true; /* Can't write to files opened this way */ + file->readOnly = read_only; /* Can't write to files opened this way */ file->fileset = fileset; file->name = pstrdup(name); @@ -670,11 +673,14 @@ BufFileSeek(BufFile *file, int fileno, off_t offset, int whence) newFile = file->curFile; newOffset = (file->curOffset + file->pos) + offset; break; -#ifdef NOT_USED case SEEK_END: - /* could be implemented, not needed currently */ + /* + * Get the file size of the last file to get the last offset + * of that file. + */ + newFile = file->numFiles - 1; + newOffset = FileSize(file->files[file->numFiles - 1]); break; -#endif default: elog(ERROR, "invalid whence: %d", whence); return EOF; @@ -843,3 +849,40 @@ BufFileAppend(BufFile *target, BufFile *source) return startBlock; } + +/* + * Truncate the file upto the given fileno and the offsets. + */ +void +BufFileTruncateShared(BufFile *file, int fileno, off_t offset) +{ + int newFile = file->numFiles; + off_t newOffset; + char segment_name[MAXPGPATH]; + int i; + + /* Loop over all the files upto the fileno which we want to truncate. */ + for (i = file->numFiles - 1; i >= fileno; i--) + { + /* + * Except the fileno, we can directly delete other files. If the + * offset is 0 then we can delete the fileno file as well unless it + * is the first file. + */ + if ((i != fileno || offset == 0) && fileno != 0) + { + SharedSegmentName(segment_name, file->name, i); + SharedFileSetDelete(file->fileset, segment_name, true); + newFile--; + newOffset = MAX_PHYSICAL_FILESIZE; + } + else + { + FileTruncate(file->files[i], offset, WAIT_EVENT_BUFFILE_READ); + newOffset = offset; + } + } + + file->numFiles = newFile; + file->curOffset = newOffset; +} diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 7dc6dd2f15..0fa98585f9 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -1403,13 +1403,14 @@ ReportTemporaryFileUsage(const char *path, off_t size) * before the file was opened. */ static void -RegisterTemporaryFile(File file) +RegisterTemporaryFile(File file, bool eoxact_close) { ResourceOwnerRememberFile(CurrentResourceOwner, file); VfdCache[file].resowner = CurrentResourceOwner; /* Backup mechanism for closing at end of xact. */ - VfdCache[file].fdstate |= FD_CLOSE_AT_EOXACT; + if (eoxact_close) + VfdCache[file].fdstate |= FD_CLOSE_AT_EOXACT; have_xact_temporary_files = true; } @@ -1616,7 +1617,7 @@ OpenTemporaryFile(bool interXact) /* Register it with the current resource owner */ if (!interXact) - RegisterTemporaryFile(file); + RegisterTemporaryFile(file, true); return file; } @@ -1707,7 +1708,8 @@ OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError) * the prefix isn't needed. */ File -PathNameCreateTemporaryFile(const char *path, bool error_on_failure) +PathNameCreateTemporaryFile(const char *path, bool error_on_failure, + bool eoxact_close) { File file; @@ -1733,7 +1735,7 @@ PathNameCreateTemporaryFile(const char *path, bool error_on_failure) VfdCache[file].fdstate |= FD_TEMP_FILE_LIMIT; /* Register it for automatic close. */ - RegisterTemporaryFile(file); + RegisterTemporaryFile(file, eoxact_close); return file; } @@ -1741,18 +1743,22 @@ PathNameCreateTemporaryFile(const char *path, bool error_on_failure) /* * Open a file that was created with PathNameCreateTemporaryFile, possibly in * another backend. Files opened this way don't count against the - * temp_file_limit of the caller, are read-only and are automatically closed - * at the end of the transaction but are not deleted on close. + * temp_file_limit of the caller, are read-only if the flag is set and are + * automatically closed at the end of the transaction if the eoxact_close is + * setbut are not deleted on close. */ File -PathNameOpenTemporaryFile(const char *path) +PathNameOpenTemporaryFile(const char *path, bool eoxact_close, bool read_only) { File file; ResourceOwnerEnlargeFiles(CurrentResourceOwner); - /* We open the file read-only. */ - file = PathNameOpenFile(path, O_RDONLY | PG_BINARY); + /* We open the file read-only if instructed by the caller. */ + if (read_only) + file = PathNameOpenFile(path, O_RDONLY | PG_BINARY); + else + file = PathNameOpenFile(path, O_RDWR | PG_BINARY); /* If no such file, then we don't raise an error. */ if (file <= 0 && errno != ENOENT) @@ -1764,7 +1770,7 @@ PathNameOpenTemporaryFile(const char *path) if (file > 0) { /* Register it for automatic close. */ - RegisterTemporaryFile(file); + RegisterTemporaryFile(file, eoxact_close); } return file; diff --git a/src/backend/storage/file/sharedfileset.c b/src/backend/storage/file/sharedfileset.c index f7206c9175..9b87bcad3d 100644 --- a/src/backend/storage/file/sharedfileset.c +++ b/src/backend/storage/file/sharedfileset.c @@ -68,7 +68,8 @@ SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg) } /* Register our cleanup callback. */ - on_dsm_detach(seg, SharedFileSetOnDetach, PointerGetDatum(fileset)); + if (seg) + on_dsm_detach(seg, SharedFileSetOnDetach, PointerGetDatum(fileset)); } /* @@ -102,13 +103,14 @@ SharedFileSetAttach(SharedFileSet *fileset, dsm_segment *seg) * Create a new file in the given set. */ File -SharedFileSetCreate(SharedFileSet *fileset, const char *name) +SharedFileSetCreate(SharedFileSet *fileset, const char *name, + bool eoxact_close) { char path[MAXPGPATH]; File file; SharedFilePath(path, fileset, name); - file = PathNameCreateTemporaryFile(path, false); + file = PathNameCreateTemporaryFile(path, false, eoxact_close); /* If we failed, see if we need to create the directory on demand. */ if (file <= 0) @@ -120,7 +122,7 @@ SharedFileSetCreate(SharedFileSet *fileset, const char *name) TempTablespacePath(tempdirpath, tablespace); SharedFileSetPath(filesetpath, fileset, tablespace); PathNameCreateTemporaryDir(tempdirpath, filesetpath); - file = PathNameCreateTemporaryFile(path, true); + file = PathNameCreateTemporaryFile(path, true, eoxact_close); } return file; @@ -131,13 +133,14 @@ SharedFileSetCreate(SharedFileSet *fileset, const char *name) * another backend. */ File -SharedFileSetOpen(SharedFileSet *fileset, const char *name) +SharedFileSetOpen(SharedFileSet *fileset, const char *name, bool eoxact_close, + bool read_only) { char path[MAXPGPATH]; File file; SharedFilePath(path, fileset, name); - file = PathNameOpenTemporaryFile(path); + file = PathNameOpenTemporaryFile(path, eoxact_close, read_only); return file; } diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c index 666a7c0e81..212a607e63 100644 --- a/src/backend/utils/sort/logtape.c +++ b/src/backend/utils/sort/logtape.c @@ -544,7 +544,7 @@ ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared, lt = <s->tapes[i]; pg_itoa(i, filename); - file = BufFileOpenShared(fileset, filename); + file = BufFileOpenShared(fileset, filename, true, true); filesize = BufFileSize(file); /* @@ -701,7 +701,7 @@ LogicalTapeSetCreate(int ntapes, TapeShare *shared, SharedFileSet *fileset, char filename[MAXPGPATH]; pg_itoa(worker, filename); - lts->pfile = BufFileCreateShared(fileset, filename); + lts->pfile = BufFileCreateShared(fileset, filename, true); } else lts->pfile = BufFileCreateTemp(false); diff --git a/src/backend/utils/sort/sharedtuplestore.c b/src/backend/utils/sort/sharedtuplestore.c index c3ab494a45..6ea52cb5a5 100644 --- a/src/backend/utils/sort/sharedtuplestore.c +++ b/src/backend/utils/sort/sharedtuplestore.c @@ -315,7 +315,8 @@ sts_puttuple(SharedTuplestoreAccessor *accessor, void *meta_data, /* Create one. Only this backend will write into it. */ sts_filename(name, accessor, accessor->participant); - accessor->write_file = BufFileCreateShared(accessor->fileset, name); + accessor->write_file = BufFileCreateShared(accessor->fileset, name, + true); /* Set up the shared state for this backend's file. */ participant = &accessor->sts->participants[accessor->participant]; @@ -563,7 +564,7 @@ sts_parallel_scan_next(SharedTuplestoreAccessor *accessor, void *meta_data) sts_filename(name, accessor, accessor->read_participant); accessor->read_file = - BufFileOpenShared(accessor->fileset, name); + BufFileOpenShared(accessor->fileset, name, true, true); } /* Seek and load the chunk header. */ diff --git a/src/include/storage/buffile.h b/src/include/storage/buffile.h index 60433f35b4..0f628dd2b8 100644 --- a/src/include/storage/buffile.h +++ b/src/include/storage/buffile.h @@ -46,9 +46,12 @@ extern int BufFileSeekBlock(BufFile *file, long blknum); extern int64 BufFileSize(BufFile *file); extern long BufFileAppend(BufFile *target, BufFile *source); -extern BufFile *BufFileCreateShared(SharedFileSet *fileset, const char *name); +extern BufFile *BufFileCreateShared(SharedFileSet *fileset, const char *name, + bool eoxact_close); extern void BufFileExportShared(BufFile *file); -extern BufFile *BufFileOpenShared(SharedFileSet *fileset, const char *name); +extern BufFile *BufFileOpenShared(SharedFileSet *fileset, const char *name, + bool eoxact_close, bool read_only); extern void BufFileDeleteShared(SharedFileSet *fileset, const char *name); +extern void BufFileTruncateShared(BufFile *file, int fileno, off_t offset); #endif /* BUFFILE_H */ diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h index 8cd125d7df..8c4e684f51 100644 --- a/src/include/storage/fd.h +++ b/src/include/storage/fd.h @@ -93,8 +93,8 @@ extern int FileGetRawFlags(File file); extern mode_t FileGetRawMode(File file); /* Operations used for sharing named temporary files */ -extern File PathNameCreateTemporaryFile(const char *name, bool error_on_failure); -extern File PathNameOpenTemporaryFile(const char *name); +extern File PathNameCreateTemporaryFile(const char *name, bool error_on_failure, bool eoxact_close); +extern File PathNameOpenTemporaryFile(const char *path, bool eoxact_close, bool read_only); extern bool PathNameDeleteTemporaryFile(const char *name, bool error_on_failure); extern void PathNameCreateTemporaryDir(const char *base, const char *name); extern void PathNameDeleteTemporaryDir(const char *name); diff --git a/src/include/storage/sharedfileset.h b/src/include/storage/sharedfileset.h index 2d6cf077e5..c661efaaaa 100644 --- a/src/include/storage/sharedfileset.h +++ b/src/include/storage/sharedfileset.h @@ -36,8 +36,10 @@ typedef struct SharedFileSet extern void SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg); extern void SharedFileSetAttach(SharedFileSet *fileset, dsm_segment *seg); -extern File SharedFileSetCreate(SharedFileSet *fileset, const char *name); -extern File SharedFileSetOpen(SharedFileSet *fileset, const char *name); +extern File SharedFileSetCreate(SharedFileSet *fileset, const char *name, + bool eoxact_close); +extern File SharedFileSetOpen(SharedFileSet *fileset, const char *name, + bool eoxact_close, bool read_only); extern bool SharedFileSetDelete(SharedFileSet *fileset, const char *name, bool error_on_failure); extern void SharedFileSetDeleteAll(SharedFileSet *fileset);