Skip to content

Commit 4befefa

Browse files
Skip copy WAL file to archive if already exists
1 parent 8505e78 commit 4befefa

File tree

1 file changed

+79
-11
lines changed

1 file changed

+79
-11
lines changed

src/data.c

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ typedef union DataPage
2929
char data[BLCKSZ];
3030
} DataPage;
3131

32+
static bool
33+
fileEqualCRC(const char *path1, const char *path2, bool path2_is_compressed);
34+
3235
#ifdef HAVE_LIBZ
3336
/* Implementation of zlib compression method */
3437
static int32
@@ -1092,45 +1095,52 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
10921095
FILE *in = NULL;
10931096
FILE *out=NULL;
10941097
char buf[XLOG_BLCKSZ];
1095-
const char *to_path_p = to_path;
1098+
const char *to_path_p;
10961099
char to_path_temp[MAXPGPATH];
10971100
int errno_temp;
10981101

10991102
#ifdef HAVE_LIBZ
11001103
char gz_to_path[MAXPGPATH];
11011104
gzFile gz_out = NULL;
1105+
if (is_compress)
1106+
{
1107+
snprintf(gz_to_path, sizeof(gz_to_path), "%s.gz", to_path);
1108+
to_path_p = gz_to_path;
1109+
}
1110+
else
11021111
#endif
1112+
to_path_p = to_path;
11031113

11041114
/* open file for read */
11051115
in = fopen(from_path, PG_BINARY_R);
11061116
if (in == NULL)
11071117
elog(ERROR, "Cannot open source WAL file \"%s\": %s", from_path,
11081118
strerror(errno));
11091119

1120+
/* Check if possible to skip copying */
1121+
if (fileExists(to_path_p))
1122+
{
1123+
if (fileEqualCRC(from_path, to_path_p, is_compress))
1124+
return;
1125+
/* Do not copy and do not rise error. Just quit as normal. */
1126+
else if (!overwrite)
1127+
elog(ERROR, "WAL segment \"%s\" already exists.", to_path);
1128+
}
1129+
11101130
/* open backup file for write */
11111131
#ifdef HAVE_LIBZ
11121132
if (is_compress)
11131133
{
1114-
snprintf(gz_to_path, sizeof(gz_to_path), "%s.gz", to_path);
1115-
1116-
if (!overwrite && fileExists(gz_to_path))
1117-
elog(ERROR, "WAL segment \"%s\" already exists.", gz_to_path);
1118-
11191134
snprintf(to_path_temp, sizeof(to_path_temp), "%s.partial", gz_to_path);
11201135

11211136
gz_out = gzopen(to_path_temp, PG_BINARY_W);
11221137
if (gzsetparams(gz_out, compress_level, Z_DEFAULT_STRATEGY) != Z_OK)
11231138
elog(ERROR, "Cannot set compression level %d to file \"%s\": %s",
11241139
compress_level, to_path_temp, get_gz_error(gz_out, errno));
1125-
1126-
to_path_p = gz_to_path;
11271140
}
11281141
else
11291142
#endif
11301143
{
1131-
if (!overwrite && fileExists(to_path))
1132-
elog(ERROR, "WAL segment \"%s\" already exists.", to_path);
1133-
11341144
snprintf(to_path_temp, sizeof(to_path_temp), "%s.partial", to_path);
11351145

11361146
out = fopen(to_path_temp, PG_BINARY_W);
@@ -1724,3 +1734,61 @@ check_file_pages(pgFile *file, XLogRecPtr stop_lsn,
17241734

17251735
return is_valid;
17261736
}
1737+
1738+
static bool
1739+
fileEqualCRC(const char *path1, const char *path2, bool path2_is_compressed)
1740+
{
1741+
pg_crc32 crc_from;
1742+
pg_crc32 crc_to;
1743+
1744+
/* Get checksum of backup file */
1745+
#ifdef HAVE_LIBZ
1746+
if (path2_is_compressed)
1747+
{
1748+
char buf [1024];
1749+
gzFile gz_in = NULL;
1750+
1751+
INIT_CRC32C(crc_to);
1752+
gz_in = gzopen(path2, PG_BINARY_R);
1753+
if (gz_in == NULL)
1754+
{
1755+
/* There is no such file or it cannot be read */
1756+
elog(LOG,
1757+
"Cannot compare WAL file \"%s\" with compressed \"%s\"",
1758+
path1, path2);
1759+
return false;
1760+
}
1761+
1762+
for (;;)
1763+
{
1764+
size_t read_len = 0;
1765+
read_len = gzread(gz_in, buf, sizeof(buf));
1766+
if (read_len != sizeof(buf) && !gzeof(gz_in))
1767+
{
1768+
/* An error occurred while reading the file */
1769+
elog(LOG,
1770+
"Cannot compare WAL file \"%s\" with compressed \"%s\"",
1771+
path1, path2);
1772+
return false;
1773+
}
1774+
COMP_CRC32C(crc_to, buf, read_len);
1775+
if (gzeof(gz_in) || read_len == 0)
1776+
break;
1777+
}
1778+
FIN_CRC32C(crc_to);
1779+
1780+
if (gzclose(gz_in) != 0)
1781+
elog(ERROR, "Cannot close compressed WAL file \"%s\": %s",
1782+
path2, get_gz_error(gz_in, errno));
1783+
}
1784+
else
1785+
#endif
1786+
{
1787+
crc_to = pgFileGetCRC(path2);
1788+
}
1789+
1790+
/* Get checksum of original file */
1791+
crc_from = pgFileGetCRC(path1);
1792+
1793+
return EQ_CRC32C(crc_from, crc_to);
1794+
}

0 commit comments

Comments
 (0)