22
22
#include <common/pg_lzcompress.h>
23
23
#include <zlib.h>
24
24
25
+ /* Implementation of zlib compression method */
25
26
static size_t zlib_compress (void * dst , size_t dst_size , void const * src , size_t src_size )
26
27
{
27
28
uLongf compressed_size = dst_size ;
28
29
int rc = compress2 (dst , & compressed_size , src , src_size , compress_level );
29
30
return rc == Z_OK ? compressed_size : rc ;
30
31
}
31
32
33
+ /* Implementation of zlib compression method */
32
34
static size_t zlib_decompress (void * dst , size_t dst_size , void const * src , size_t src_size )
33
35
{
34
36
uLongf dest_len = dst_size ;
35
37
int rc = uncompress (dst , & dest_len , src , src_size );
36
38
return rc == Z_OK ? dest_len : rc ;
37
39
}
38
40
41
+ /*
42
+ * Compresses source into dest using algorithm. Returns the number of bytes
43
+ * written in the destination buffer, or -1 if compression fails.
44
+ */
39
45
static size_t
40
46
do_compress (void * dst , size_t dst_size , void const * src , size_t src_size , CompressAlg alg )
41
47
{
@@ -53,6 +59,10 @@ do_compress(void* dst, size_t dst_size, void const* src, size_t src_size, Compre
53
59
return -1 ;
54
60
}
55
61
62
+ /*
63
+ * Decompresses source into dest using algorithm. Returns the number of bytes
64
+ * decompressed in the destination buffer, or -1 if decompression fails.
65
+ */
56
66
static size_t
57
67
do_decompress (void * dst , size_t dst_size , void const * src , size_t src_size , CompressAlg alg )
58
68
{
@@ -70,8 +80,10 @@ do_decompress(void* dst, size_t dst_size, void const* src, size_t src_size, Comp
70
80
return -1 ;
71
81
}
72
82
73
-
74
-
83
+ /*
84
+ * When copying datafiles to backup we validate and compress them block
85
+ * by block. Thus special header is required for each data block.
86
+ */
75
87
typedef struct BackupPageHeader
76
88
{
77
89
BlockNumber block ; /* block number */
@@ -125,6 +137,11 @@ backup_data_page(pgFile *file, XLogRecPtr prev_backup_start_lsn,
125
137
header .block = blknum ;
126
138
offset = blknum * BLCKSZ ;
127
139
140
+ /*
141
+ * Read the page and verify its header and checksum.
142
+ * Under high write load it's possible that we've read partly
143
+ * flushed page, so try several times befor throwing an error.
144
+ */
128
145
while (try_checksum -- )
129
146
{
130
147
if (fseek (in , offset , SEEK_SET ) != 0 )
@@ -176,14 +193,14 @@ backup_data_page(pgFile *file, XLogRecPtr prev_backup_start_lsn,
176
193
elog (ERROR , "File: %s blknum %u have wrong page header." , file -> path , blknum );
177
194
}
178
195
179
- /* If the page hasn't changed since previous backup, don't backup it. */
180
- if (!XLogRecPtrIsInvalid (prev_backup_start_lsn )
181
- && !XLogRecPtrIsInvalid (page_lsn )
182
- && page_lsn < prev_backup_start_lsn )
183
- {
184
- * n_skipped += 1 ;
185
- return ;
186
- }
196
+ // /* If the page hasn't changed since previous backup, don't backup it. */
197
+ // if (!XLogRecPtrIsInvalid(prev_backup_start_lsn)
198
+ // && !XLogRecPtrIsInvalid(page_lsn)
199
+ // && page_lsn < prev_backup_start_lsn)
200
+ // {
201
+ // *n_skipped += 1;
202
+ // return;
203
+ // }
187
204
188
205
/* Verify checksum */
189
206
if (current .checksum_version )
@@ -223,12 +240,14 @@ backup_data_page(pgFile *file, XLogRecPtr prev_backup_start_lsn,
223
240
Assert (header .compressed_size <= BLCKSZ );
224
241
write_buffer_size = sizeof (header );
225
242
243
+ /* The page was successfully compressed */
226
244
if (header .compressed_size > 0 )
227
245
{
228
246
memcpy (write_buffer , & header , sizeof (header ));
229
247
memcpy (write_buffer + sizeof (header ), compressed_page .data , header .compressed_size );
230
248
write_buffer_size += MAXALIGN (header .compressed_size );
231
249
}
250
+ /* The page compression failed. Write it as is. */
232
251
else
233
252
{
234
253
header .compressed_size = BLCKSZ ;
@@ -324,8 +343,7 @@ backup_data_file(const char *from_root, const char *to_root,
324
343
325
344
/*
326
345
* Read each page, verify checksum and write it to backup.
327
- * If page map is not empty we scan only changed blocks, otherwise
328
- * backup all pages of the relation.
346
+ * If page map is empty backup all pages of the relation.
329
347
*/
330
348
if (file -> pagemap .bitmapsize == 0 )
331
349
{
@@ -336,6 +354,7 @@ backup_data_file(const char *from_root, const char *to_root,
336
354
n_blocks_read ++ ;
337
355
}
338
356
}
357
+ /* If page map is not empty we scan only changed blocks, */
339
358
else
340
359
{
341
360
datapagemap_iterator_t * iter ;
@@ -371,7 +390,7 @@ backup_data_file(const char *from_root, const char *to_root,
371
390
FIN_CRC32C (file -> crc );
372
391
373
392
/*
374
- * If we have pagemap then file can't be a zero size.
393
+ * If we have pagemap then file in the backup can't be a zero size.
375
394
* Otherwise, we will clear the last file.
376
395
*/
377
396
if (n_blocks_read != 0 && n_blocks_read == n_blocks_skipped )
@@ -385,117 +404,6 @@ backup_data_file(const char *from_root, const char *to_root,
385
404
return true;
386
405
}
387
406
388
- /*
389
- * Restore compressed file that was backed up partly.
390
- */
391
- static void
392
- restore_file_partly (const char * from_root ,const char * to_root , pgFile * file )
393
- {
394
- FILE * in ;
395
- FILE * out ;
396
- size_t read_len = 0 ;
397
- int errno_tmp ;
398
- struct stat st ;
399
- char to_path [MAXPGPATH ];
400
- char buf [BLCKSZ ];
401
- size_t write_size = 0 ;
402
-
403
- join_path_components (to_path , to_root , file -> path + strlen (from_root ) + 1 );
404
- /* open backup mode file for read */
405
- in = fopen (file -> path , "r" );
406
- if (in == NULL )
407
- {
408
- elog (ERROR , "cannot open backup file \"%s\": %s" , file -> path ,
409
- strerror (errno ));
410
- }
411
- out = fopen (to_path , "r+" );
412
-
413
- /* stat source file to change mode of destination file */
414
- if (fstat (fileno (in ), & st ) == -1 )
415
- {
416
- fclose (in );
417
- fclose (out );
418
- elog (ERROR , "cannot stat \"%s\": %s" , file -> path ,
419
- strerror (errno ));
420
- }
421
-
422
- if (fseek (out , 0 , SEEK_END ) < 0 )
423
- elog (ERROR , "cannot seek END of \"%s\": %s" ,
424
- to_path , strerror (errno ));
425
-
426
- /* copy everything from backup to the end of the file */
427
- for (;;)
428
- {
429
- if ((read_len = fread (buf , 1 , sizeof (buf ), in )) != sizeof (buf ))
430
- break ;
431
-
432
- if (fwrite (buf , 1 , read_len , out ) != read_len )
433
- {
434
- errno_tmp = errno ;
435
- /* oops */
436
- fclose (in );
437
- fclose (out );
438
- elog (ERROR , "cannot write to \"%s\": %s" , to_path ,
439
- strerror (errno_tmp ));
440
- }
441
- write_size += read_len ;
442
- }
443
-
444
- errno_tmp = errno ;
445
- if (!feof (in ))
446
- {
447
- fclose (in );
448
- fclose (out );
449
- elog (ERROR , "cannot read backup mode file \"%s\": %s" ,
450
- file -> path , strerror (errno_tmp ));
451
- }
452
-
453
- /* copy odd part. */
454
- if (read_len > 0 )
455
- {
456
- if (fwrite (buf , 1 , read_len , out ) != read_len )
457
- {
458
- errno_tmp = errno ;
459
- /* oops */
460
- fclose (in );
461
- fclose (out );
462
- elog (ERROR , "cannot write to \"%s\": %s" , to_path ,
463
- strerror (errno_tmp ));
464
- }
465
-
466
- write_size += read_len ;
467
- }
468
-
469
-
470
- /* update file permission */
471
- if (chmod (to_path , file -> mode ) == -1 )
472
- {
473
- int errno_tmp = errno ;
474
-
475
- fclose (in );
476
- fclose (out );
477
- elog (ERROR , "cannot change mode of \"%s\": %s" , to_path ,
478
- strerror (errno_tmp ));
479
- }
480
-
481
- if (fflush (out ) != 0 ||
482
- fsync (fileno (out )) != 0 ||
483
- fclose (out ))
484
- elog (ERROR , "cannot write \"%s\": %s" , to_path , strerror (errno ));
485
- fclose (in );
486
- }
487
-
488
- void
489
- restore_compressed_file (const char * from_root ,
490
- const char * to_root ,
491
- pgFile * file )
492
- {
493
- if (!file -> is_partial_copy )
494
- copy_file (from_root , to_root , file );
495
- else
496
- restore_file_partly (from_root , to_root , file );
497
- }
498
-
499
407
/*
500
408
* Restore files in the from_root directory to the to_root directory with
501
409
* same relative path.
@@ -522,7 +430,7 @@ restore_data_file(const char *from_root,
522
430
523
431
/*
524
432
* Open backup file for write. We use "r+" at first to overwrite only
525
- * modified pages for differential restore. If the file is not exists ,
433
+ * modified pages for differential restore. If the file does not exist ,
526
434
* re-open it with "w" to create an empty file.
527
435
*/
528
436
join_path_components (to_path , to_root , file -> path + strlen (from_root ) + 1 );
@@ -856,136 +764,6 @@ copy_wal_file(const char *from_path, const char *to_path)
856
764
fclose (in );
857
765
}
858
766
859
- /*
860
- * Save part of the file into backup.
861
- * skip_size - size of the file in previous backup. We can skip it
862
- * and copy just remaining part of the file
863
- */
864
- bool
865
- copy_file_partly (const char * from_root , const char * to_root ,
866
- pgFile * file , size_t skip_size )
867
- {
868
- char to_path [MAXPGPATH ];
869
- FILE * in ;
870
- FILE * out ;
871
- size_t read_len = 0 ;
872
- int errno_tmp ;
873
- struct stat st ;
874
- char buf [BLCKSZ ];
875
-
876
- /* reset size summary */
877
- file -> read_size = 0 ;
878
- file -> write_size = 0 ;
879
-
880
- /* open backup mode file for read */
881
- in = fopen (file -> path , "r" );
882
- if (in == NULL )
883
- {
884
- /* maybe deleted, it's not error */
885
- if (errno == ENOENT )
886
- return false;
887
-
888
- elog (ERROR , "cannot open source file \"%s\": %s" , file -> path ,
889
- strerror (errno ));
890
- }
891
-
892
- /* open backup file for write */
893
- join_path_components (to_path , to_root , file -> path + strlen (from_root ) + 1 );
894
-
895
- out = fopen (to_path , "w" );
896
- if (out == NULL )
897
- {
898
- int errno_tmp = errno ;
899
- fclose (in );
900
- elog (ERROR , "cannot open destination file \"%s\": %s" ,
901
- to_path , strerror (errno_tmp ));
902
- }
903
-
904
- /* stat source file to change mode of destination file */
905
- if (fstat (fileno (in ), & st ) == -1 )
906
- {
907
- fclose (in );
908
- fclose (out );
909
- elog (ERROR , "cannot stat \"%s\": %s" , file -> path ,
910
- strerror (errno ));
911
- }
912
-
913
- if (fseek (in , skip_size , SEEK_SET ) < 0 )
914
- elog (ERROR , "cannot seek %lu of \"%s\": %s" ,
915
- skip_size , file -> path , strerror (errno ));
916
-
917
- /*
918
- * copy content
919
- * NOTE: Now CRC is not computed for compressed files now.
920
- */
921
- for (;;)
922
- {
923
- if ((read_len = fread (buf , 1 , sizeof (buf ), in )) != sizeof (buf ))
924
- break ;
925
-
926
- if (fwrite (buf , 1 , read_len , out ) != read_len )
927
- {
928
- errno_tmp = errno ;
929
- /* oops */
930
- fclose (in );
931
- fclose (out );
932
- elog (ERROR , "cannot write to \"%s\": %s" , to_path ,
933
- strerror (errno_tmp ));
934
- }
935
-
936
- file -> write_size += sizeof (buf );
937
- file -> read_size += sizeof (buf );
938
- }
939
-
940
- errno_tmp = errno ;
941
- if (!feof (in ))
942
- {
943
- fclose (in );
944
- fclose (out );
945
- elog (ERROR , "cannot read backup mode file \"%s\": %s" ,
946
- file -> path , strerror (errno_tmp ));
947
- }
948
-
949
- /* copy odd part. */
950
- if (read_len > 0 )
951
- {
952
- if (fwrite (buf , 1 , read_len , out ) != read_len )
953
- {
954
- errno_tmp = errno ;
955
- /* oops */
956
- fclose (in );
957
- fclose (out );
958
- elog (ERROR , "cannot write to \"%s\": %s" , to_path ,
959
- strerror (errno_tmp ));
960
- }
961
-
962
- file -> write_size += read_len ;
963
- file -> read_size += read_len ;
964
- }
965
-
966
- /* update file permission */
967
- if (chmod (to_path , st .st_mode ) == -1 )
968
- {
969
- errno_tmp = errno ;
970
- fclose (in );
971
- fclose (out );
972
- elog (ERROR , "cannot change mode of \"%s\": %s" , to_path ,
973
- strerror (errno_tmp ));
974
- }
975
-
976
- /* add meta information needed for recovery */
977
- file -> is_partial_copy = true;
978
-
979
- if (fflush (out ) != 0 ||
980
- fsync (fileno (out )) != 0 ||
981
- fclose (out ))
982
- elog (ERROR , "cannot write \"%s\": %s" , to_path , strerror (errno ));
983
- fclose (in );
984
-
985
- return true;
986
- }
987
-
988
-
989
767
/*
990
768
* Calculate checksum of various files which are not copied from PGDATA,
991
769
* but created in process of backup, such as stream XLOG files,
0 commit comments