avoid_duplicate_archiving_PoC2.patch
text/x-patch
Filename: avoid_duplicate_archiving_PoC2.patch
Type: text/x-patch
Part: 1
Message:
Re: Duplicate history file?
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlogarchive.c | 64 | 1 |
diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c
index 26b023e754..7d94e7f963 100644
--- a/src/backend/access/transam/xlogarchive.c
+++ b/src/backend/access/transam/xlogarchive.c
@@ -382,6 +382,7 @@ KeepFileRestoredFromArchive(const char *path, const char *xlogfname)
{
char xlogfpath[MAXPGPATH];
bool reload = false;
+ bool already_archived = false;
struct stat statbuf;
snprintf(xlogfpath, MAXPGPATH, XLOGDIR "/%s", xlogfname);
@@ -416,6 +417,68 @@ KeepFileRestoredFromArchive(const char *path, const char *xlogfname)
/* same-size buffers, so this never truncates */
strlcpy(oldpath, xlogfpath, MAXPGPATH);
#endif
+ /*
+ * On a standby with archive_mode=always, there's the case where the
+ * same file is archived more than once. If the archive_command rejects
+ * overwriting, WAL-archiving won't go further than the file forever.
+ * Avoid duplicate archiving attempts when the file with the same
+ * content is known to have been already archived or notified.
+ */
+ if (XLogArchiveMode == ARCHIVE_MODE_ALWAYS &&
+ XLogArchiveIsReadyOrDone(xlogfname))
+ {
+ int fd1;
+ int fd2 = -1;
+
+ fd1 = BasicOpenFile(path, O_RDONLY | PG_BINARY);
+ if (fd1 >= 0)
+ fd2 = BasicOpenFile(oldpath, O_RDONLY | PG_BINARY);
+
+ if (fd1 < 0 || fd2 < 0)
+ {
+ ereport(WARNING,
+ (errcode_for_file_access(),
+ errmsg("could not open file \"%s\", skip duplicate check: %m",
+ fd1 < 0 ? path : oldpath)));
+ if (fd1 >= 0)
+ close(fd1);
+ }
+ else
+ {
+ unsigned char srcbuf[XLOG_BLCKSZ];
+ unsigned char dstbuf[XLOG_BLCKSZ];
+ uint32 i;
+
+ /*
+ * Compare the two files' contents. We don't bother
+ * completing if something's wrong meanwhile.
+ */
+ for (i = 0 ; i < wal_segment_size / XLOG_BLCKSZ ; i++)
+ {
+ if (read(fd1, srcbuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+ break;
+
+ if (read(fd2, dstbuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+ break;
+
+ if (memcmp(srcbuf, dstbuf, XLOG_BLCKSZ) != 0)
+ break;
+ }
+
+ close(fd1);
+ close(fd2);
+
+ if (i == wal_segment_size / XLOG_BLCKSZ)
+ {
+ already_archived = true;
+
+ ereport(LOG,
+ (errmsg("log file \"%s\" have been already archived, skip archiving",
+ xlogfname)));
+ }
+ }
+ }
+
if (unlink(oldpath) != 0)
ereport(FATAL,
(errcode_for_file_access(),
@@ -432,7 +495,7 @@ KeepFileRestoredFromArchive(const char *path, const char *xlogfname)
*/
if (XLogArchiveMode != ARCHIVE_MODE_ALWAYS)
XLogArchiveForceDone(xlogfname);
- else
+ else if (!already_archived)
XLogArchiveNotify(xlogfname);
/*