19
19
#include "storage/block.h"
20
20
#include "storage/bufpage.h"
21
21
#include "storage/checksum_impl.h"
22
+ #include <common/pg_lzcompress.h>
23
+ #include <zlib.h>
24
+
25
+ static size_t zlib_compress (void * dst , size_t dst_size , void const * src , size_t src_size )
26
+ {
27
+ uLongf compressed_size = dst_size ;
28
+ int rc = compress2 (dst , & compressed_size , src , src_size , compress_level );
29
+ return rc == Z_OK ? compressed_size : rc ;
30
+ }
31
+
32
+ static size_t zlib_decompress (void * dst , size_t dst_size , void const * src , size_t src_size )
33
+ {
34
+ uLongf dest_len = dst_size ;
35
+ int rc = uncompress (dst , & dest_len , src , src_size );
36
+ return rc == Z_OK ? dest_len : rc ;
37
+ }
38
+
39
+ static size_t
40
+ do_compress (void * dst , size_t dst_size , void const * src , size_t src_size , CompressAlg alg )
41
+ {
42
+ switch (alg )
43
+ {
44
+ case NONE_COMPRESS :
45
+ case NOT_DEFINED_COMPRESS :
46
+ return -1 ;
47
+ case ZLIB_COMPRESS :
48
+ return zlib_compress (dst , dst_size , src , src_size );
49
+ case PGLZ_COMPRESS :
50
+ return pglz_compress (src , src_size , dst , PGLZ_strategy_always );
51
+ }
52
+
53
+ return -1 ;
54
+ }
55
+
56
+ static size_t
57
+ do_decompress (void * dst , size_t dst_size , void const * src , size_t src_size , CompressAlg alg )
58
+ {
59
+ switch (alg )
60
+ {
61
+ case NONE_COMPRESS :
62
+ case NOT_DEFINED_COMPRESS :
63
+ return -1 ;
64
+ case ZLIB_COMPRESS :
65
+ return zlib_decompress (dst , dst_size , src , src_size );
66
+ case PGLZ_COMPRESS :
67
+ return pglz_decompress (src , src_size , dst , dst_size );
68
+ }
69
+
70
+ return -1 ;
71
+ }
72
+
73
+
22
74
23
75
typedef struct BackupPageHeader
24
76
{
25
77
BlockNumber block ; /* block number */
78
+ int32 compressed_size ;
26
79
} BackupPageHeader ;
27
80
28
81
/* Verify page's header */
@@ -61,8 +114,10 @@ backup_data_page(pgFile *file, XLogRecPtr prev_backup_start_lsn,
61
114
BackupPageHeader header ;
62
115
off_t offset ;
63
116
DataPage page ; /* used as read buffer */
64
- size_t write_buffer_size = sizeof (header ) + BLCKSZ ;
65
- char write_buffer [write_buffer_size ];
117
+ DataPage compressed_page ; /* used as read buffer */
118
+ size_t write_buffer_size ;
119
+ /* maximum size of write buffer */
120
+ char write_buffer [BLCKSZ + sizeof (header )];
66
121
size_t read_len = 0 ;
67
122
XLogRecPtr page_lsn ;
68
123
int try_checksum = 100 ;
@@ -162,9 +217,31 @@ backup_data_page(pgFile *file, XLogRecPtr prev_backup_start_lsn,
162
217
163
218
file -> read_size += read_len ;
164
219
165
- memcpy (write_buffer , & header , sizeof (header ));
166
- /* TODO implement block compression here? */
167
- memcpy (write_buffer + sizeof (header ), page .data , BLCKSZ );
220
+ header .compressed_size = do_compress (compressed_page .data , sizeof (compressed_page .data ),
221
+ page .data , sizeof (page .data ), compress_alg );
222
+
223
+ file -> compress_alg = compress_alg ;
224
+
225
+ Assert (header .compressed_size <= BLCKSZ );
226
+ write_buffer_size = sizeof (header );
227
+
228
+ if (header .compressed_size > 0 )
229
+ {
230
+ memcpy (write_buffer , & header , sizeof (header ));
231
+ memcpy (write_buffer + sizeof (header ), compressed_page .data , header .compressed_size );
232
+ write_buffer_size += MAXALIGN (header .compressed_size );
233
+ }
234
+ else
235
+ {
236
+ header .compressed_size = BLCKSZ ;
237
+ memcpy (write_buffer , & header , sizeof (header ));
238
+ memcpy (write_buffer + sizeof (header ), page .data , BLCKSZ );
239
+ write_buffer_size += header .compressed_size ;
240
+ }
241
+
242
+ /* Update CRC */
243
+ COMP_CRC32C (* crc , & write_buffer , write_buffer_size );
244
+
168
245
/* write data page */
169
246
if (fwrite (write_buffer , 1 , write_buffer_size , out ) != write_buffer_size )
170
247
{
@@ -175,10 +252,6 @@ backup_data_page(pgFile *file, XLogRecPtr prev_backup_start_lsn,
175
252
file -> path , blknum , strerror (errno_tmp ));
176
253
}
177
254
178
- /* update CRC */
179
- COMP_CRC32C (* crc , & header , sizeof (header ));
180
- COMP_CRC32C (* crc , page .data , BLCKSZ );
181
-
182
255
file -> write_size += write_buffer_size ;
183
256
}
184
257
@@ -468,7 +541,8 @@ restore_data_file(const char *from_root,
468
541
for (blknum = 0 ; ; blknum ++ )
469
542
{
470
543
size_t read_len ;
471
- DataPage page ; /* used as read buffer */
544
+ DataPage compressed_page ; /* used as read buffer */
545
+ DataPage page ;
472
546
473
547
/* read BackupPageHeader */
474
548
read_len = fread (& header , 1 , sizeof (header ), in );
@@ -482,18 +556,35 @@ restore_data_file(const char *from_root,
482
556
"odd size page found at block %u of \"%s\"" ,
483
557
blknum , file -> path );
484
558
else
485
- elog (ERROR , "cannot read block %u of \"%s\": %s" ,
559
+ elog (ERROR , "cannot read header of block %u of \"%s\": %s" ,
486
560
blknum , file -> path , strerror (errno_tmp ));
487
561
}
488
562
489
563
if (header .block < blknum )
490
- elog (ERROR , "backup is broken at block %u" ,
491
- blknum );
564
+ elog (ERROR , "backup is broken at block %u" , blknum );
492
565
566
+ /* TODO fix this assert */
567
+ Assert (header .compressed_size <= BLCKSZ );
493
568
494
- if (fread (page .data , 1 , BLCKSZ , in ) != BLCKSZ )
495
- elog (ERROR , "cannot read block %u of \"%s\": %s" ,
496
- blknum , file -> path , strerror (errno ));
569
+ read_len = fread (compressed_page .data , 1 ,
570
+ MAXALIGN (header .compressed_size ), in );
571
+ if (read_len != MAXALIGN (header .compressed_size ))
572
+ elog (ERROR , "cannot read block %u of \"%s\" read %lu of %d" ,
573
+ blknum , file -> path , read_len , header .compressed_size );
574
+
575
+ if (header .compressed_size < BLCKSZ )
576
+ {
577
+ size_t uncompressed_size = 0 ;
578
+
579
+ uncompressed_size = do_decompress (page .data , BLCKSZ ,
580
+ compressed_page .data ,
581
+ header .compressed_size , file -> compress_alg );
582
+
583
+ if (uncompressed_size != BLCKSZ )
584
+ elog (ERROR , "page uncompressed to %ld bytes. != BLCKSZ" , uncompressed_size );
585
+ }
586
+ else
587
+ memcpy (page .data , compressed_page .data , BLCKSZ );
497
588
498
589
/* update checksum because we are not save whole */
499
590
if (backup -> checksum_version )
0 commit comments