@@ -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_p );
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 );
@@ -1408,75 +1418,13 @@ get_wal_file(const char *from_path, const char *to_path)
14081418 * but created in process of backup, such as stream XLOG files,
14091419 * PG_TABLESPACE_MAP_FILE and PG_BACKUP_LABEL_FILE.
14101420 */
1411- bool
1421+ void
14121422calc_file_checksum (pgFile * file )
14131423{
1414- FILE * in ;
1415- size_t read_len = 0 ;
1416- int errno_tmp ;
1417- char buf [BLCKSZ ];
1418- struct stat st ;
1419- pg_crc32 crc ;
1420-
14211424 Assert (S_ISREG (file -> mode ));
1422- INIT_TRADITIONAL_CRC32 (crc );
1423-
1424- /* reset size summary */
1425- file -> read_size = 0 ;
1426- file -> write_size = 0 ;
1427-
1428- /* open backup mode file for read */
1429- in = fopen (file -> path , PG_BINARY_R );
1430- if (in == NULL )
1431- {
1432- FIN_TRADITIONAL_CRC32 (crc );
1433- file -> crc = crc ;
1434-
1435- /* maybe deleted, it's not error */
1436- if (errno == ENOENT )
1437- return false;
1438-
1439- elog (ERROR , "cannot open source file \"%s\": %s" , file -> path ,
1440- strerror (errno ));
1441- }
1442-
1443- /* stat source file to change mode of destination file */
1444- if (fstat (fileno (in ), & st ) == -1 )
1445- {
1446- fclose (in );
1447- elog (ERROR , "cannot stat \"%s\": %s" , file -> path ,
1448- strerror (errno ));
1449- }
1450-
1451- for (;;)
1452- {
1453- read_len = fread (buf , 1 , sizeof (buf ), in );
1454-
1455- if (read_len == 0 )
1456- break ;
1457-
1458- /* update CRC */
1459- COMP_TRADITIONAL_CRC32 (crc , buf , read_len );
1460-
1461- file -> write_size += read_len ;
1462- file -> read_size += read_len ;
1463- }
1464-
1465- errno_tmp = errno ;
1466- if (!feof (in ))
1467- {
1468- fclose (in );
1469- elog (ERROR , "cannot read backup mode file \"%s\": %s" ,
1470- file -> path , strerror (errno_tmp ));
1471- }
1472-
1473- /* finish CRC calculation and store into pgFile */
1474- FIN_TRADITIONAL_CRC32 (crc );
1475- file -> crc = crc ;
1476-
1477- fclose (in );
14781425
1479- return true;
1426+ file -> crc = pgFileGetCRC (file -> path , false, false, & file -> read_size );
1427+ file -> write_size = file -> read_size ;
14801428}
14811429
14821430/*
@@ -1724,3 +1672,56 @@ check_file_pages(pgFile *file, XLogRecPtr stop_lsn,
17241672
17251673 return is_valid ;
17261674}
1675+
1676+ static bool
1677+ fileEqualCRC (const char * path1 , const char * path2 , bool path2_is_compressed )
1678+ {
1679+ pg_crc32 crc1 ;
1680+ pg_crc32 crc2 ;
1681+
1682+ /* Get checksum of backup file */
1683+ #ifdef HAVE_LIBZ
1684+ if (path2_is_compressed )
1685+ {
1686+ char buf [1024 ];
1687+ gzFile gz_in = NULL ;
1688+
1689+ INIT_CRC32C (crc2 );
1690+ gz_in = gzopen (path2 , PG_BINARY_R );
1691+ if (gz_in == NULL )
1692+ /* File cannot be read */
1693+ elog (ERROR ,
1694+ "Cannot compare WAL file \"%s\" with compressed \"%s\"" ,
1695+ path1 , path2 );
1696+
1697+ for (;;)
1698+ {
1699+ size_t read_len = 0 ;
1700+ read_len = gzread (gz_in , buf , sizeof (buf ));
1701+ if (read_len != sizeof (buf ) && !gzeof (gz_in ))
1702+ /* An error occurred while reading the file */
1703+ elog (ERROR ,
1704+ "Cannot compare WAL file \"%s\" with compressed \"%s\"" ,
1705+ path1 , path2 );
1706+
1707+ COMP_CRC32C (crc2 , buf , read_len );
1708+ if (gzeof (gz_in ) || read_len == 0 )
1709+ break ;
1710+ }
1711+ FIN_CRC32C (crc2 );
1712+
1713+ if (gzclose (gz_in ) != 0 )
1714+ elog (ERROR , "Cannot close compressed WAL file \"%s\": %s" ,
1715+ path2 , get_gz_error (gz_in , errno ));
1716+ }
1717+ else
1718+ #endif
1719+ {
1720+ crc2 = pgFileGetCRC (path2 , false, true, NULL );
1721+ }
1722+
1723+ /* Get checksum of original file */
1724+ crc1 = pgFileGetCRC (path1 , false, true, NULL );
1725+
1726+ return EQ_CRC32C (crc1 , crc2 );
1727+ }
0 commit comments