buffile_change.patch
application/octet-stream
Filename: buffile_change.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/storage/file/buffile.c | 55 | 12 |
| src/backend/storage/file/fd.c | 17 | 11 |
| src/backend/storage/file/sharedfileset.c | 9 | 6 |
| src/backend/utils/sort/logtape.c | 2 | 2 |
| src/backend/utils/sort/sharedtuplestore.c | 3 | 2 |
| src/include/storage/buffile.h | 5 | 2 |
| src/include/storage/fd.h | 2 | 2 |
| src/include/storage/sharedfileset.h | 4 | 2 |
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);