@@ -31,8 +31,8 @@ typedef struct DataPage
31
31
char data [BLCKSZ ];
32
32
} DataPage ;
33
33
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 );
36
36
37
37
#ifdef HAVE_LIBZ
38
38
/* Implementation of zlib compression method */
@@ -861,6 +861,10 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out,
861
861
* If "nblocks" is greater than zero, then skip restoring blocks,
862
862
* whose position if greater than "nblocks".
863
863
* 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.
864
868
*/
865
869
size_t
866
870
restore_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
930
934
else
931
935
{
932
936
/* 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 .
935
939
*/
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))
937
941
{
938
942
cur_pos_in += sizeof (BackupPageHeader );
939
943
940
944
/* backward compatibility kludge TODO: remove in 3.0 */
941
945
blknum = page .bph .block ;
942
946
compressed_size = page .bph .compressed_size ;
943
947
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
946
951
*/
947
952
if (backup_version >= 20400 )
948
953
read_len = compressed_size ;
949
954
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
+ */
950
959
read_len = MAXALIGN (compressed_size );
951
960
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
-
959
961
}
960
962
else
961
963
break ;
962
964
}
963
965
964
966
/*
965
- * Backupward compatibility kludge: in the good old days
967
+ * Backward compatibility kludge: in the good old days
966
968
* n_blocks attribute was available only in DELTA backups.
967
969
* File truncate in PAGE and PTRACK happened on the fly when
968
970
* special value PageIsTruncated is encountered.
@@ -1006,13 +1008,13 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
1006
1008
if (compressed_size > BLCKSZ )
1007
1009
elog (ERROR , "Size of a blknum %i exceed BLCKSZ: %i" , blknum , compressed_size );
1008
1010
1009
- /* incremental restore in LSN mode */
1011
+ /* Incremental restore in LSN mode */
1010
1012
if (map && lsn_map && datapagemap_is_set (lsn_map , blknum ))
1011
1013
datapagemap_add (map , blknum );
1012
1014
1013
1015
if (map && checksum_map && checksum_map [blknum ].checksum != 0 )
1014
1016
{
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);
1016
1018
/*
1017
1019
* The heart of incremental restore in CHECKSUM mode
1018
1020
* 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
1110
1112
write_len += BLCKSZ ;
1111
1113
cur_pos_out += BLCKSZ ; /* update current write position */
1112
1114
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 */
1114
1116
if (map )
1115
1117
datapagemap_add (map , blknum );
1116
1118
}
@@ -1238,7 +1240,7 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
1238
1240
/* incremental restore */
1239
1241
if (already_exists )
1240
1242
{
1241
- /* compare checksumms of remote and local files */
1243
+ /* compare checksums of already existing file and backup file */
1242
1244
pg_crc32 file_crc = fio_get_crc32 (to_fullpath , FIO_DB_HOST , false);
1243
1245
1244
1246
if (file_crc == tmp_file -> crc )
@@ -1625,7 +1627,7 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
1625
1627
if (interrupted || thread_interrupted )
1626
1628
elog (ERROR , "Interrupted during data file validation" );
1627
1629
1628
- /* newer backups have headers in separate storage */
1630
+ /* newer backups have page headers in separate storage */
1629
1631
if (headers )
1630
1632
{
1631
1633
n_hdr ++ ;
@@ -1657,7 +1659,7 @@ validate_file_pages(pgFile *file, const char *fullpath, XLogRecPtr stop_lsn,
1657
1659
/* old backups rely on header located directly in data file */
1658
1660
else
1659
1661
{
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 ))
1661
1663
{
1662
1664
/* Backward compatibility kludge, TODO: remove in 3.0
1663
1665
* 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,
1686
1688
else
1687
1689
len = fread (compressed_page .data , 1 , read_len , in );
1688
1690
1689
- // elog(INFO, "POS: %u", cur_pos_in);
1690
- //
1691
- // elog(INFO, "LEN: %i", len);
1692
- // elog(INFO, "READ_LEN: %i", read_len);
1693
-
1694
1691
if (len != read_len )
1695
1692
{
1696
1693
elog (WARNING , "Cannot read block %u file \"%s\": %s" ,
@@ -1886,11 +1883,8 @@ get_lsn_map(const char *fullpath, uint32 checksum_version,
1886
1883
for (blknum = 0 ; blknum < n_blocks ; blknum ++ )
1887
1884
{
1888
1885
size_t read_len = fread (read_buffer , 1 , BLCKSZ , in );
1889
- // page_lsn = InvalidXLogRecPtr;
1890
1886
PageState page_st ;
1891
1887
1892
- // page_st.lsn = InvalidXLogRecPtr
1893
-
1894
1888
/* report error */
1895
1889
if (ferror (in ))
1896
1890
elog (ERROR , "Cannot read block %u of \"%s\": %s" ,
@@ -1905,7 +1899,8 @@ get_lsn_map(const char *fullpath, uint32 checksum_version,
1905
1899
datapagemap_add (lsn_map , blknum );
1906
1900
}
1907
1901
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 ));
1909
1904
1910
1905
if (feof (in ))
1911
1906
break ;
@@ -1926,10 +1921,10 @@ get_lsn_map(const char *fullpath, uint32 checksum_version,
1926
1921
return lsn_map ;
1927
1922
}
1928
1923
1929
- /* */
1924
+ /* Every page in data file contains BackupPageHeader, extract it */
1930
1925
bool
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 )
1933
1928
{
1934
1929
1935
1930
/* read BackupPageHeader */
@@ -1952,26 +1947,18 @@ get_compressed_page_meta(FILE *in, const char *fullpath, BackupPageHeader* bph,
1952
1947
ftell (in ), fullpath , strerror (errno ));
1953
1948
}
1954
1949
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
+ */
1955
1954
if (crc )
1956
1955
COMP_FILE_CRC32 (use_crc32c , * crc , bph , read_len );
1957
1956
1958
1957
if (bph -> block == 0 && bph -> compressed_size == 0 )
1959
1958
elog (ERROR , "Empty block in file \"%s\"" , fullpath );
1960
1959
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
-
1972
1960
Assert (bph -> compressed_size != 0 );
1973
1961
return true;
1974
-
1975
1962
}
1976
1963
1977
1964
/* 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
2099
2086
blknum ++ ;
2100
2087
}
2101
2088
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
+ */
2103
2093
if (* headers )
2104
2094
{
2105
2095
file -> n_headers = hdr_num + 1 ;
@@ -2124,8 +2114,11 @@ send_pages(ConnectionArgs* conn_arg, const char *to_fullpath, const char *from_f
2124
2114
return n_blocks_read ;
2125
2115
}
2126
2116
2127
- /* attempt to open header file, read content and return as
2117
+ /*
2118
+ * Attempt to open header file, read content and return as
2128
2119
* array of headers.
2120
+ * TODO: some access optimizations would be great here:
2121
+ * less fseeks, buffering, descriptor sharing, etc.
2129
2122
*/
2130
2123
BackupPageHeader2 *
2131
2124
get_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
2181
2174
goto cleanup ;
2182
2175
}
2183
2176
2184
- // elog(INFO, "zsize: %i, size: %i", file->hdr_size, read_len);
2185
-
2186
2177
/* allocate memory for uncompressed headers */
2187
2178
headers = pgut_malloc (read_len );
2188
2179
memset (headers , 0 , read_len );
@@ -2244,7 +2235,7 @@ write_page_headers(BackupPageHeader2 *headers, pgFile *file, HeaderMap *hdr_map,
2244
2235
if (file -> n_headers <= 0 )
2245
2236
return ;
2246
2237
2247
- /* when running merge we must save headers into the temp map */
2238
+ /* when running merge we must write headers into temp map */
2248
2239
map_path = (is_merge ) ? hdr_map -> path_tmp : hdr_map -> path ;
2249
2240
read_len = (file -> n_headers + 1 ) * sizeof (BackupPageHeader2 );
2250
2241
0 commit comments