@@ -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 */
3437static 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