Skip to content

Commit 0e6b0b2

Browse files
committed
PGPRO-2096: For pre 2.0.22 validate using CRC-32C
1 parent 23cf692 commit 0e6b0b2

9 files changed

+85
-14
lines changed

Diff for: gen_probackup_project.pl

+1
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ sub build_pgprobackup
157157
'thread.c'
158158
);
159159
$probackup->AddFile('src/backend/access/transam/xlogreader.c');
160+
$probackup->AddFile('src/backend/utils/hash/pg_crc.c');
160161
$probackup->AddFiles(
161162
'src/bin/pg_basebackup',
162163
'receivelog.c',

Diff for: msvs/template.pg_probackup.vcxproj

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@
165165
</ItemDefinitionGroup>
166166
<ItemGroup>
167167
<ClCompile Include="@PGSRC@\backend\access\transam\xlogreader.c" />
168+
<ClCompile Include="@PGSRC@\backend\utils\hash\pg_crc.c" />
168169
<ClCompile Include="@PGSRC@\bin\pg_basebackup\receivelog.c" />
169170
<ClCompile Include="@PGSRC@\bin\pg_basebackup\streamutil.c" />
170171
<ClCompile Include="@PGSRC@\bin\pg_basebackup\walmethods.c" />

Diff for: msvs/template.pg_probackup96.vcxproj

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@
165165
</ItemDefinitionGroup>
166166
<ItemGroup>
167167
<ClCompile Include="@PGSRC@\backend\access\transam\xlogreader.c" />
168+
<ClCompile Include="@PGSRC@\backend\utils\hash\pg_crc.c" />
168169
<ClCompile Include="@PGSRC@\bin\pg_basebackup\receivelog.c" />
169170
<ClCompile Include="@PGSRC@\bin\pg_basebackup\streamutil.c" />
170171
<ClCompile Include="@PGSRC@\bin\pg_rewind\datapagemap.c" />

Diff for: msvs/template.pg_probackup_2.vcxproj

+1
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
<!-- @PGROOT@\lib;@ADDLIBS@ @PGSRC@ @ADDINCLUDE@ -->
161161
<ItemGroup>
162162
<ClCompile Include="@PGSRC@\backend\access\transam\xlogreader.c" />
163+
<ClCompile Include="@PGSRC@\backend\utils\hash\pg_crc.c" />
163164
<ClCompile Include="@PGSRC@\bin\pg_basebackup\receivelog.c" />
164165
<ClCompile Include="@PGSRC@\bin\pg_basebackup\streamutil.c" />
165166
<ClCompile Include="@PGSRC@\bin\pg_basebackup\walmethods.c" />

Diff for: src/dir.c

+27-5
Original file line numberDiff line numberDiff line change
@@ -259,35 +259,57 @@ pgFileDelete(pgFile *file)
259259
}
260260

261261
pg_crc32
262-
pgFileGetCRC(const char *file_path)
262+
pgFileGetCRC(const char *file_path, bool use_crc32c)
263263
{
264264
FILE *fp;
265265
pg_crc32 crc = 0;
266266
char buf[1024];
267267
size_t len;
268268
int errno_tmp;
269269

270+
#define INIT_FILE_CRC32(crc) \
271+
do { \
272+
if (use_crc32c) \
273+
INIT_CRC32C(crc); \
274+
else \
275+
INIT_TRADITIONAL_CRC32(crc); \
276+
} while (0)
277+
#define COMP_FILE_CRC32(crc, data, len) \
278+
do { \
279+
if (use_crc32c) \
280+
COMP_CRC32C((crc), (data), (len)); \
281+
else \
282+
COMP_TRADITIONAL_CRC32(crc, data, len); \
283+
} while (0)
284+
#define FIN_FILE_CRC32(crc) \
285+
do { \
286+
if (use_crc32c) \
287+
FIN_CRC32C(crc); \
288+
else \
289+
FIN_TRADITIONAL_CRC32(crc); \
290+
} while (0)
291+
270292
/* open file in binary read mode */
271293
fp = fopen(file_path, PG_BINARY_R);
272294
if (fp == NULL)
273295
elog(ERROR, "cannot open file \"%s\": %s",
274296
file_path, strerror(errno));
275297

276298
/* calc CRC of backup file */
277-
INIT_TRADITIONAL_CRC32(crc);
299+
INIT_FILE_CRC32(crc);
278300
while ((len = fread(buf, 1, sizeof(buf), fp)) == sizeof(buf))
279301
{
280302
if (interrupted)
281303
elog(ERROR, "interrupted during CRC calculation");
282-
COMP_TRADITIONAL_CRC32(crc, buf, len);
304+
COMP_FILE_CRC32(crc, buf, len);
283305
}
284306
errno_tmp = errno;
285307
if (!feof(fp))
286308
elog(WARNING, "cannot read \"%s\": %s", file_path,
287309
strerror(errno_tmp));
288310
if (len > 0)
289-
COMP_TRADITIONAL_CRC32(crc, buf, len);
290-
FIN_TRADITIONAL_CRC32(crc);
311+
COMP_FILE_CRC32(crc, buf, len);
312+
FIN_FILE_CRC32(crc);
291313

292314
fclose(fp);
293315

Diff for: src/merge.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ merge_files(void *arg)
503503
* do that.
504504
*/
505505
file->write_size = pgFileSize(to_path_tmp);
506-
file->crc = pgFileGetCRC(to_path_tmp);
506+
file->crc = pgFileGetCRC(to_path_tmp, false);
507507
}
508508
pgFileDelete(file);
509509
}

Diff for: src/pg_probackup.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ extern pgFile *pgFileNew(const char *path, bool omit_symlink);
503503
extern pgFile *pgFileInit(const char *path);
504504
extern void pgFileDelete(pgFile *file);
505505
extern void pgFileFree(void *file);
506-
extern pg_crc32 pgFileGetCRC(const char *file_path);
506+
extern pg_crc32 pgFileGetCRC(const char *file_path, bool use_crc32c);
507507
extern int pgFileComparePath(const void *f1, const void *f2);
508508
extern int pgFileComparePathDesc(const void *f1, const void *f2);
509509
extern int pgFileCompareLinked(const void *f1, const void *f2);
@@ -564,7 +564,8 @@ extern void remove_not_digit(char *buf, size_t len, const char *str);
564564
extern const char *base36enc(long unsigned int value);
565565
extern char *base36enc_dup(long unsigned int value);
566566
extern long unsigned int base36dec(const char *text);
567-
extern int parse_server_version(char *server_version_str);
567+
extern uint32 parse_server_version(const char *server_version_str);
568+
extern uint32 parse_program_version(const char *program_version);
568569

569570
#ifdef WIN32
570571
#ifdef _DEBUG

Diff for: src/util.c

+31-5
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,14 @@ time2iso(char *buf, size_t len, time_t time)
280280
}
281281
}
282282

283-
/* Parse string representation of the server version */
284-
int
285-
parse_server_version(char *server_version_str)
283+
/*
284+
* Parse string representation of the server version.
285+
*/
286+
uint32
287+
parse_server_version(const char *server_version_str)
286288
{
287289
int nfields;
288-
int result = 0;
290+
uint32 result = 0;
289291
int major_version = 0;
290292
int minor_version = 0;
291293

@@ -304,7 +306,31 @@ parse_server_version(char *server_version_str)
304306
result = major_version * 10000;
305307
}
306308
else
307-
elog(ERROR, "Unknown server version format");
309+
elog(ERROR, "Unknown server version format %s", server_version_str);
310+
311+
return result;
312+
}
313+
314+
/*
315+
* Parse string representation of the program version.
316+
*/
317+
uint32
318+
parse_program_version(const char *program_version)
319+
{
320+
int nfields;
321+
int major = 0,
322+
minor = 0,
323+
micro = 0;
324+
uint32 result = 0;
325+
326+
if (program_version == NULL || program_version[0] == '\0')
327+
return 0;
328+
329+
nfields = sscanf(program_version, "%d.%d.%d", &major, &minor, &micro);
330+
if (nfields == 3)
331+
result = major * 10000 + minor * 100 + micro;
332+
else
333+
elog(ERROR, "Unknown program version format %s", program_version);
308334

309335
return result;
310336
}

Diff for: src/validate.c

+19-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ static void *pgBackupValidateFiles(void *arg);
1919
static void do_validate_instance(void);
2020

2121
static bool corrupted_backup_found = false;
22+
/* Program version of a current backup */
23+
static uint32 validate_backup_version = 0;
2224

2325
typedef struct
2426
{
@@ -90,6 +92,11 @@ pgBackupValidate(pgBackup *backup)
9092
pg_atomic_clear_flag(&file->lock);
9193
}
9294

95+
/*
96+
* We use program version to calculate checksum in pgBackupValidateFiles()
97+
*/
98+
validate_backup_version = parse_program_version(backup->program_version);
99+
93100
/* init thread args with own file lists */
94101
threads = (pthread_t *) palloc(sizeof(pthread_t) * num_threads);
95102
threads_args = (validate_files_arg *)
@@ -205,7 +212,18 @@ pgBackupValidateFiles(void *arg)
205212
break;
206213
}
207214

208-
crc = pgFileGetCRC(file->path);
215+
/*
216+
* Pre 2.0.22 we use CRC-32C, but in newer version of pg_probackup we
217+
* use CRC-32.
218+
*
219+
* pg_control stores its content and checksum of the content, calculated
220+
* using CRC-32C. If we calculate checksum of the whole pg_control using
221+
* CRC-32C we get same checksum constantly. It might be because of the
222+
* CRC-32C algorithm.
223+
* To avoid this problem we need to use different algorithm, CRC-32 in
224+
* this case.
225+
*/
226+
crc = pgFileGetCRC(file->path, validate_backup_version <= 20021);
209227
if (crc != file->crc)
210228
{
211229
elog(WARNING, "Invalid CRC of backup file \"%s\" : %X. Expected %X",

0 commit comments

Comments
 (0)