@@ -99,6 +99,9 @@ typedef struct BackupPageHeader
9999 int32 compressed_size ;
100100} BackupPageHeader ;
101101
102+ /* Special value for compressed_size field */
103+ #define PageIsTruncated -1
104+
102105/* Verify page's header */
103106static bool
104107parse_page (Page page , XLogRecPtr * lsn )
@@ -235,6 +238,8 @@ backup_data_page(pgFile *file, XLogRecPtr prev_backup_start_lsn,
235238 bool page_is_valid = false;
236239 BlockNumber absolute_blknum = file -> segno * RELSEG_SIZE + blknum ;
237240
241+ header .block = blknum ;
242+
238243 /*
239244 * Read the page and verify its header and checksum.
240245 * Under high write load it's possible that we've read partly
@@ -248,19 +253,23 @@ backup_data_page(pgFile *file, XLogRecPtr prev_backup_start_lsn,
248253 in , page );
249254
250255 try_again -- ;
251- /* This block was truncated.*/
252256 if (result == 0 )
253257 {
254- header .compressed_size = -1 ;
258+ /* This block was truncated.*/
259+ // header.compressed_size = PageIsTruncated;
260+ // page_is_valid = true;
261+ /* Page is not actually valid, but it is absent
262+ * and we're not going to reread it or validate */
263+ //elog(WARNING, "backup blkno %u. PageIsTruncated", blknum);
255264 }
256265
257266 if (result == 1 )
258267 page_is_valid = true;
259268 }
260269 }
261270
262- if (!page_is_valid ||
263- (backup_mode == BACKUP_MODE_DIFF_PTRACK ))
271+ if (( !page_is_valid )
272+ || (backup_mode == BACKUP_MODE_DIFF_PTRACK ))
264273 {
265274 size_t page_size = 0 ;
266275 PageHeader phdr = (PageHeader ) page ;
@@ -273,7 +282,8 @@ backup_data_page(pgFile *file, XLogRecPtr prev_backup_start_lsn,
273282 if (page == NULL )
274283 {
275284 /* This block was truncated.*/
276- header .compressed_size = -1 ;
285+ header .compressed_size = PageIsTruncated ;
286+ elog (WARNING , "backup blkno %u. reread PageIsTruncated" , blknum );
277287 }
278288 else if (page_size != BLCKSZ )
279289 {
@@ -283,46 +293,58 @@ backup_data_page(pgFile *file, XLogRecPtr prev_backup_start_lsn,
283293 }
284294 else
285295 {
296+ /*
297+ * We must set checksum here, because it is outdated
298+ * in the block recieved from shared buffers.
299+ */
286300 ((PageHeader ) page )-> pd_checksum = pg_checksum_page (page , absolute_blknum );
287301 }
288302 }
289303
290- if (header .compressed_size != -1 )
304+ if (header .compressed_size != PageIsTruncated )
291305 {
292306 file -> read_size += BLCKSZ ;
293307
294308 compressed_page = malloc (BLCKSZ );
295- header .block = blknum ;
296309 header .compressed_size = do_compress (compressed_page , BLCKSZ ,
297310 page , BLCKSZ , compress_alg );
298311
299312 file -> compress_alg = compress_alg ;
300313
314+ /* if compression failed, reset size of the block */
315+ if (header .compressed_size == -1 )
316+ header .compressed_size = BLCKSZ ;
317+
318+
301319 Assert (header .compressed_size <= BLCKSZ );
302- write_buffer_size = sizeof (header );
303320 }
304321
305- /* The page was successfully compressed */
306- if (header .compressed_size > 0 )
322+ write_buffer_size = sizeof (header );
323+
324+ /* The page was truncated. Write only header
325+ /* to know that we must truncate restored file */
326+ if (header .compressed_size == PageIsTruncated )
307327 {
308328 memcpy (write_buffer , & header , sizeof (header ));
309- memcpy (write_buffer + sizeof (header ), compressed_page , header .compressed_size );
310- write_buffer_size += MAXALIGN (header .compressed_size );
311329 }
312330 /* The page compression failed. Write it as is. */
313- else if (header .compressed_size == 0 )
331+ else if (header .compressed_size == BLCKSZ || header . compressed_size == 0 )
314332 {
315- header .compressed_size = BLCKSZ ;
316333 memcpy (write_buffer , & header , sizeof (header ));
317334 memcpy (write_buffer + sizeof (header ), page , BLCKSZ );
318335 write_buffer_size += header .compressed_size ;
319336 }
320- /* The page is not found, it mean that it was truncated. */
321- else if (header .compressed_size == -1 )
337+ /* The page was successfully compressed */
338+ else if (header .compressed_size > 0 )
322339 {
323340 memcpy (write_buffer , & header , sizeof (header ));
341+ memcpy (write_buffer + sizeof (header ), compressed_page , header .compressed_size );
342+ write_buffer_size += MAXALIGN (header .compressed_size );
324343 }
325344
345+ // elog(WARNING, "backup blkno %u, compressed_size %d write_buffer_size %ld",
346+ // blknum, header.compressed_size, write_buffer_size);
347+
326348 /* Update CRC */
327349 COMP_CRC32C (* crc , & write_buffer , write_buffer_size );
328350
@@ -377,16 +399,6 @@ backup_data_file(const char *from_root, const char *to_root,
377399 return false;
378400 }
379401
380- if ((backup_mode == BACKUP_MODE_DIFF_PAGE ||
381- backup_mode == BACKUP_MODE_DIFF_PTRACK ) &&
382- file -> pagemap .bitmapsize == PageBitmapIsAbsent )
383- {
384- /*
385- * TODO COMPARE FILE CHECKSUMM to this file version from previous backup
386- * if they are equal, skip this file
387- */
388- }
389-
390402 /* reset size summary */
391403 file -> read_size = 0 ;
392404 file -> write_size = 0 ;
@@ -566,30 +578,38 @@ restore_data_file(const char *from_root,
566578 }
567579
568580 if (header .block < blknum )
569- elog (ERROR , "backup is broken at block %u" , blknum );
581+ elog (ERROR , "backup is broken at file->path %s block %u" , file -> path , blknum );
570582
571- if (header .compressed_size != -1 )
583+ if (header .compressed_size == PageIsTruncated )
572584 {
573- //elog(VERBOSE, "file %s, header compressed size %d", file->path, header.compressed_size);
574- Assert (header .compressed_size <= BLCKSZ );
585+ /*
586+ * Backup contains information that this block was truncated.
587+ * Truncate file to this length.
588+ */
589+ ftruncate (fileno (out ), header .block * BLCKSZ );
590+ elog (WARNING , "truncate file %s to block %u" , file -> path , header .block );
591+ break ;
592+ }
575593
576- read_len = fread (compressed_page .data , 1 ,
577- MAXALIGN (header .compressed_size ), in );
578- if (read_len != MAXALIGN (header .compressed_size ))
579- elog (ERROR , "cannot read block %u of \"%s\" read %lu of %d" ,
580- blknum , file -> path , read_len , header .compressed_size );
594+ //elog(VERBOSE, "file %s, header compressed size %d", file->path, header.compressed_size);
595+ Assert (header .compressed_size <= BLCKSZ );
581596
582- if (header .compressed_size != BLCKSZ )
583- {
584- size_t uncompressed_size = 0 ;
597+ read_len = fread (compressed_page .data , 1 ,
598+ MAXALIGN (header .compressed_size ), in );
599+ if (read_len != MAXALIGN (header .compressed_size ))
600+ elog (ERROR , "cannot read block %u of \"%s\" read %lu of %d" ,
601+ blknum , file -> path , read_len , header .compressed_size );
602+
603+ if (header .compressed_size != BLCKSZ )
604+ {
605+ size_t uncompressed_size = 0 ;
585606
586- uncompressed_size = do_decompress (page .data , BLCKSZ ,
587- compressed_page .data ,
588- header .compressed_size , file -> compress_alg );
607+ uncompressed_size = do_decompress (page .data , BLCKSZ ,
608+ compressed_page .data ,
609+ header .compressed_size , file -> compress_alg );
589610
590- if (uncompressed_size != BLCKSZ )
591- elog (ERROR , "page uncompressed to %ld bytes. != BLCKSZ" , uncompressed_size );
592- }
611+ if (uncompressed_size != BLCKSZ )
612+ elog (ERROR , "page uncompressed to %ld bytes. != BLCKSZ" , uncompressed_size );
593613 }
594614
595615 /*
@@ -600,16 +620,7 @@ restore_data_file(const char *from_root,
600620 elog (ERROR , "cannot seek block %u of \"%s\": %s" ,
601621 blknum , to_path , strerror (errno ));
602622
603- if (header .compressed_size == -1 )
604- {
605- /*
606- * Backup contains information that this block was truncated.
607- * Truncate file to this length.
608- */
609- ftruncate (fileno (out ), blknum * BLCKSZ );
610- break ;
611- }
612- else if (header .compressed_size < BLCKSZ )
623+ if (header .compressed_size < BLCKSZ )
613624 {
614625 if (fwrite (page .data , 1 , BLCKSZ , out ) != BLCKSZ )
615626 elog (ERROR , "cannot write block %u of \"%s\": %s" ,
0 commit comments