Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 79 additions & 11 deletions src/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#include <zlib.h>
#endif

static bool
fileEqualCRC(const char *path1, const char *path2, bool path2_is_compressed);

#ifdef HAVE_LIBZ
/* Implementation of zlib compression method */
static int32
Expand Down Expand Up @@ -1021,45 +1024,52 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
FILE *in = NULL;
FILE *out=NULL;
char buf[XLOG_BLCKSZ];
const char *to_path_p = to_path;
const char *to_path_p;
char to_path_temp[MAXPGPATH];
int errno_temp;

#ifdef HAVE_LIBZ
char gz_to_path[MAXPGPATH];
gzFile gz_out = NULL;
if (is_compress)
{
snprintf(gz_to_path, sizeof(gz_to_path), "%s.gz", to_path);
to_path_p = gz_to_path;
}
else
#endif
to_path_p = to_path;

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

/* Check if possible to skip copying */
if (fileExists(to_path_p))
{
if (fileEqualCRC(from_path, to_path_p, is_compress))
return;
/* Do not copy and do not rise error. Just quit as normal. */
else if (!overwrite)
elog(ERROR, "WAL segment \"%s\" already exists.", to_path);
}

/* open backup file for write */
#ifdef HAVE_LIBZ
if (is_compress)
{
snprintf(gz_to_path, sizeof(gz_to_path), "%s.gz", to_path);

if (!overwrite && fileExists(gz_to_path))
elog(ERROR, "WAL segment \"%s\" already exists.", gz_to_path);

snprintf(to_path_temp, sizeof(to_path_temp), "%s.partial", gz_to_path);

gz_out = gzopen(to_path_temp, PG_BINARY_W);
if (gzsetparams(gz_out, compress_level, Z_DEFAULT_STRATEGY) != Z_OK)
elog(ERROR, "Cannot set compression level %d to file \"%s\": %s",
compress_level, to_path_temp, get_gz_error(gz_out, errno));

to_path_p = gz_to_path;
}
else
#endif
{
if (!overwrite && fileExists(to_path))
elog(ERROR, "WAL segment \"%s\" already exists.", to_path);

snprintf(to_path_temp, sizeof(to_path_temp), "%s.partial", to_path);

out = fopen(to_path_temp, PG_BINARY_W);
Expand Down Expand Up @@ -1619,3 +1629,61 @@ check_file_pages(pgFile *file, XLogRecPtr stop_lsn, uint32 checksum_version)

return is_valid;
}

static bool
fileEqualCRC(const char *path1, const char *path2, bool path2_is_compressed)
{
pg_crc32 crc1;
pg_crc32 crc2;

/* Get checksum of backup file */
#ifdef HAVE_LIBZ
if (path2_is_compressed)
{
char buf [1024];
gzFile gz_in = NULL;

INIT_CRC32C(crc2);
gz_in = gzopen(path2, PG_BINARY_R);
if (gz_in == NULL)
{
/* There is no such file or it cannot be read */
elog(LOG,
"Cannot compare WAL file \"%s\" with compressed \"%s\"",
path1, path2);
return false;
}

for (;;)
{
size_t read_len = 0;
read_len = gzread(gz_in, buf, sizeof(buf));
if (read_len != sizeof(buf) && !gzeof(gz_in))
{
/* An error occurred while reading the file */
elog(LOG,
"Cannot compare WAL file \"%s\" with compressed \"%s\"",
path1, path2);
return false;
}
COMP_CRC32C(crc2, buf, read_len);
if (gzeof(gz_in) || read_len == 0)
break;
}
FIN_CRC32C(crc2);

if (gzclose(gz_in) != 0)
elog(ERROR, "Cannot close compressed WAL file \"%s\": %s",
path2, get_gz_error(gz_in, errno));
}
else
#endif
{
crc2 = pgFileGetCRC(path2);
}

/* Get checksum of original file */
crc1 = pgFileGetCRC(path1);

return EQ_CRC32C(crc1, crc2);
}