@@ -31,8 +31,8 @@ typedef struct DataPage
3131 char data [BLCKSZ ];
3232} DataPage ;
3333
34- static bool get_compressed_page_meta (FILE * in , const char * fullpath , BackupPageHeader * bph ,
35- pg_crc32 * crc , bool use_crc32c );
34+ static bool get_page_header (FILE * in , const char * fullpath , BackupPageHeader * bph ,
35+ pg_crc32 * crc , bool use_crc32c );
3636
3737#ifdef HAVE_LIBZ
3838/* Implementation of zlib compression method */
@@ -861,6 +861,10 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out,
861861 * If "nblocks" is greater than zero, then skip restoring blocks,
862862 * whose position if greater than "nblocks".
863863 * If map is NULL, then page bitmap cannot be used for restore optimization
864+ * Page bitmap optimize restore of incremental chains, consisting of more than one
865+ * backup. We restoring from newest to oldest and page, once restored, marked in map.
866+ * When the same page, but in older backup, encountered, we check the map, if it is
867+ * marked as already restored, then page is skipped.
864868 */
865869size_t
866870restore_data_file_internal (FILE * in , FILE * out , pgFile * file , uint32 backup_version ,
@@ -930,39 +934,37 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
930934 else
931935 {
932936 /* We get into this function either when restoring old backup
933- * or when merging something. Aligh read_len only in restoring
934- * or merging old backup .
937+ * or when merging something. Align read_len only in restoring
938+ * or merging old backups .
935939 */
936- if (get_compressed_page_meta (in , from_fullpath , & (page ).bph , NULL , false))
940+ if (get_page_header (in , from_fullpath , & (page ).bph , NULL , false))
937941 {
938942 cur_pos_in += sizeof (BackupPageHeader );
939943
940944 /* backward compatibility kludge TODO: remove in 3.0 */
941945 blknum = page .bph .block ;
942946 compressed_size = page .bph .compressed_size ;
943947
944- /* this will backfire when retrying merge of old backups,
945- * just pray that this will never happen.
948+ /* this has a potential to backfire when retrying merge of old backups,
949+ * so we just forbid the retrying of failed merges between versions >= 2.4.0 and
950+ * version < 2.4.0
946951 */
947952 if (backup_version >= 20400 )
948953 read_len = compressed_size ;
949954 else
955+ /* For some unknown and possibly dump reason I/O operations
956+ * in versions < 2.4.0 were always aligned to 8 bytes.
957+ * Now we have to deal with backward compatibility.
958+ */
950959 read_len = MAXALIGN (compressed_size );
951960
952- // elog(INFO, "FILE: %s", from_fullpath);
953- // elog(INFO, "blknum: %i", blknum);
954- //
955- // elog(INFO, "POS: %u", cur_pos_in);
956- // elog(INFO, "SIZE: %i", compressed_size);
957- // elog(INFO, "ASIZE: %i", read_len);
958-
959961 }
960962 else
961963 break ;
962964 }
963965
964966 /*
965- * Backupward compatibility kludge: in the good old days
967+ * Backward compatibility kludge: in the good old days
966968 * n_blocks attribute was available only in DELTA backups.
967969 * File truncate in PAGE and PTRACK happened on the fly when
968970 * special value PageIsTruncated is encountered.
@@ -1006,13 +1008,13 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
10061008 if (compressed_size > BLCKSZ )
10071009 elog (ERROR , "Size of a blknum %i exceed BLCKSZ: %i" , blknum , compressed_size );
10081010
1009- /* incremental restore in LSN mode */
1011+ /* Incremental restore in LSN mode */
10101012 if (map && lsn_map && datapagemap_is_set (lsn_map , blknum ))
10111013 datapagemap_add (map , blknum );
10121014
10131015 if (map && checksum_map && checksum_map [blknum ].checksum != 0 )
10141016 {
1015- // elog(INFO, "HDR CRC: %u, MAP CRC: %u", page_crc, checksum_map[blknum].checksum);
1017+ // elog(INFO, "HDR CRC: %u, MAP CRC: %u", page_crc, checksum_map[blknum].checksum);
10161018 /*
10171019 * The heart of incremental restore in CHECKSUM mode
10181020 * If page in backup has the same checksum and lsn as
@@ -1110,7 +1112,7 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
11101112 write_len += BLCKSZ ;
11111113 cur_pos_out += BLCKSZ ; /* update current write position */
11121114
1113- /* Mark page as restored, to avoid reading this page when restoring parent backups */
1115+ /* Mark page as restored to avoid reading this page when restoring parent backups */
11141116 if (map )
11151117 datapagemap_add (map , blknum );
11161118 }
@@ -1238,7 +1240,7 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
12381240 /* incremental restore */
12391241 if (already_exists )
12401242 {
1241- /* compare checksumms of remote and local files */
1243+ /* compare checksums of already existing file and backup file */
12421244 pg_crc32 file_crc = fio_get_crc32 (to_fullpath , FIO_DB_HOST , false);
12431245
12441246 if (file_crc == tmp_file -> crc )
@@ -1625,7 +1627,7 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
16251627 if (interrupted || thread_interrupted )
16261628 elog (ERROR , "Interrupted during data file validation" );
16271629
1628- /* newer backups have headers in separate storage */
1630+ /* newer backups have page headers in separate storage */
16291631 if (headers )
16301632 {
16311633 n_hdr ++ ;
@@ -1657,7 +1659,7 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
16571659 /* old backups rely on header located directly in data file */
16581660 else
16591661 {
1660- if (get_compressed_page_meta (in , fullpath , & (compressed_page ).bph , & crc , use_crc32c ))
1662+ if (get_page_header (in , fullpath , & (compressed_page ).bph , & crc , use_crc32c ))
16611663 {
16621664 /* Backward compatibility kludge, TODO: remove in 3.0
16631665 * for some reason we padded compressed pages in old versions
@@ -1686,11 +1688,6 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
16861688 else
16871689 len = fread (compressed_page .data , 1 , read_len , in );
16881690
1689- // elog(INFO, "POS: %u", cur_pos_in);
1690- //
1691- // elog(INFO, "LEN: %i", len);
1692- // elog(INFO, "READ_LEN: %i", read_len);
1693-
16941691 if (len != read_len )
16951692 {
16961693 elog (WARNING , "Cannot read block %u file \"%s\": %s" ,
@@ -1886,11 +1883,8 @@ get_lsn_map(const char *fullpath, uint32 checksum_version,
18861883 for (blknum = 0 ; blknum < n_blocks ; blknum ++ )
18871884 {
18881885 size_t read_len = fread (read_buffer , 1 , BLCKSZ , in );
1889- // page_lsn = InvalidXLogRecPtr;
18901886 PageState page_st ;
18911887
1892- // page_st.lsn = InvalidXLogRecPtr
1893-
18941888 /* report error */
18951889 if (ferror (in ))
18961890 elog (ERROR , "Cannot read block %u of \"%s\": %s" ,
@@ -1905,7 +1899,8 @@ get_lsn_map(const char *fullpath, uint32 checksum_version,
19051899 datapagemap_add (lsn_map , blknum );
19061900 }
19071901 else
1908- elog (ERROR , "Failed to read blknum %u from file \"%s\"" , blknum , fullpath );
1902+ elog (ERROR , "Cannot read block %u from file \"%s\": %s" ,
1903+ blknum , fullpath , strerror (errno ));
19091904
19101905 if (feof (in ))
19111906 break ;
@@ -1926,10 +1921,10 @@ get_lsn_map(const char *fullpath, uint32 checksum_version,
19261921 return lsn_map ;
19271922}
19281923
1929- /* */
1924+ /* Every page in data file contains BackupPageHeader, extract it */
19301925bool
1931- get_compressed_page_meta (FILE * in , const char * fullpath , BackupPageHeader * bph ,
1932- pg_crc32 * crc , bool use_crc32c )
1926+ get_page_header (FILE * in , const char * fullpath , BackupPageHeader * bph ,
1927+ pg_crc32 * crc , bool use_crc32c )
19331928{
19341929
19351930 /* read BackupPageHeader */
@@ -1952,26 +1947,18 @@ get_compressed_page_meta(FILE *in, const char *fullpath, BackupPageHeader* bph,
19521947 ftell (in ), fullpath , strerror (errno ));
19531948 }
19541949
1950+ /* In older versions < 2.4.0, when crc for file was calculated, header was
1951+ * not included in crc calculations. Now it is. And now we have
1952+ * the problem of backward compatibility for backups of old versions
1953+ */
19551954 if (crc )
19561955 COMP_FILE_CRC32 (use_crc32c , * crc , bph , read_len );
19571956
19581957 if (bph -> block == 0 && bph -> compressed_size == 0 )
19591958 elog (ERROR , "Empty block in file \"%s\"" , fullpath );
19601959
1961-
1962- // *blknum = header.block;
1963- // *compressed_size = header.compressed_size;
1964-
1965- // elog(INFO, "blknum: %i", header.block);
1966- // elog(INFO, "size: %i", header.compressed_size);
1967- // elog(INFO, "size2: %i", *compressed_size);
1968- //
1969- // elog(INFO, "BLKNUM: %i", *blknum);
1970- // elog(INFO, "File: %s", fullpath);
1971-
19721960 Assert (bph -> compressed_size != 0 );
19731961 return true;
1974-
19751962}
19761963
19771964/* Open local backup file for writing, set permissions and buffering */
@@ -2099,7 +2086,10 @@ send_pages(ConnectionArgs* conn_arg, const char *to_fullpath, const char *from_f
20992086 blknum ++ ;
21002087 }
21012088
2102- /* add one additional header */
2089+ /*
2090+ * Add dummy header, so we can later extract the length of last header
2091+ * as difference between their offsets.
2092+ */
21032093 if (* headers )
21042094 {
21052095 file -> n_headers = hdr_num + 1 ;
@@ -2124,8 +2114,11 @@ send_pages(ConnectionArgs* conn_arg, const char *to_fullpath, const char *from_f
21242114 return n_blocks_read ;
21252115}
21262116
2127- /* attempt to open header file, read content and return as
2117+ /*
2118+ * Attempt to open header file, read content and return as
21282119 * array of headers.
2120+ * TODO: some access optimizations would be great here:
2121+ * less fseeks, buffering, descriptor sharing, etc.
21292122 */
21302123BackupPageHeader2 *
21312124get_data_file_headers (HeaderMap * hdr_map , pgFile * file , uint32 backup_version , bool strict )
@@ -2181,8 +2174,6 @@ get_data_file_headers(HeaderMap *hdr_map, pgFile *file, uint32 backup_version, b
21812174 goto cleanup ;
21822175 }
21832176
2184- // elog(INFO, "zsize: %i, size: %i", file->hdr_size, read_len);
2185-
21862177 /* allocate memory for uncompressed headers */
21872178 headers = pgut_malloc (read_len );
21882179 memset (headers , 0 , read_len );
@@ -2244,7 +2235,7 @@ write_page_headers(BackupPageHeader2 *headers, pgFile *file, HeaderMap *hdr_map,
22442235 if (file -> n_headers <= 0 )
22452236 return ;
22462237
2247- /* when running merge we must save headers into the temp map */
2238+ /* when running merge we must write headers into temp map */
22482239 map_path = (is_merge ) ? hdr_map -> path_tmp : hdr_map -> path ;
22492240 read_len = (file -> n_headers + 1 ) * sizeof (BackupPageHeader2 );
22502241
0 commit comments