0008-Teach-copy_file-to-concatenate-segmented-files.patch
text/x-patch
Filename: 0008-Teach-copy_file-to-concatenate-segmented-files.patch
Type: text/x-patch
Part: 7
Message:
Large files for relations
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: format-patch
Series: patch 0008
Subject: Teach copy_file() to concatenate segmented files.
| File | + | − |
|---|---|---|
| src/backend/storage/file/copydir.c | 42 | 1 |
From f83a0a9f80614e18b780e7636e5c2e567b2f701e Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sun, 30 Apr 2023 15:36:20 +1200
Subject: [PATCH 08/11] Teach copy_file() to concatenate segmented files.
This means that relations are automatically converted to large file
format during COPY DATABASE ... STRATEGY=FILE_COPY and ALTER TABLE ...
SET TABLESPACE operations.
---
src/backend/storage/file/copydir.c | 43 +++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/src/backend/storage/file/copydir.c b/src/backend/storage/file/copydir.c
index 497d357d8c..0b472f1ac2 100644
--- a/src/backend/storage/file/copydir.c
+++ b/src/backend/storage/file/copydir.c
@@ -71,7 +71,19 @@ copydir(const char *fromdir, const char *todir, bool recurse)
copydir(fromfile, tofile, true);
}
else if (xlde_type == PGFILETYPE_REG)
+ {
+ const char *s;
+
+ /*
+ * Skip legacy segment files ending in ".N". copy_file() will deal
+ * with those.
+ */
+ s = strrchr(fromfile, '.');
+ if (s && strspn(s + 1, "0123456789") == strlen(s + 1))
+ continue;
+
copy_file(fromfile, tofile);
+ }
}
FreeDir(xldir);
@@ -117,6 +129,7 @@ void
copy_file(const char *fromfile, const char *tofile)
{
char *buffer;
+ int segno;
int srcfd;
int dstfd;
int nbytes;
@@ -154,6 +167,8 @@ copy_file(const char *fromfile, const char *tofile)
buffer = palloc(COPY_BUF_SIZE);
#endif
+ segno = 0;
+
/*
* Open the files
*/
@@ -248,8 +263,34 @@ copy_file(const char *fromfile, const char *tofile)
}
}
+ /*
+ * If we ran out of source data on the expected boundary of a legacy
+ * relation file segment, try opening the next segment.
+ */
if (nbytes == 0)
- break;
+ {
+ char nextpath[MAXPGPATH];
+ int nextfd;
+
+ if (offset % (RELSEG_SIZE * BLCKSZ) != 0)
+ break;
+
+ snprintf(nextpath, sizeof(nextpath), "%s.%d", fromfile, ++segno);
+ nextfd = OpenTransientFile(nextpath, O_RDONLY | PG_BINARY);
+ if (nextfd < 0)
+ {
+ if (errno == ENOENT)
+ break;
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not open file \"%s\": %m", nextpath)));
+ }
+ if (CloseTransientFile(srcfd) != 0)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not close file \"%s\": %m", fromfile)));
+ srcfd = nextfd;
+ }
}
if (offset > flush_offset)
--
2.40.1