@@ -566,8 +566,8 @@ backup_data_file(ConnectionArgs* conn_arg, pgFile *file,
566566datapagemap_iterator_t * iter = NULL ;
567567
568568/* stdio buffers */
569- char in_buffer [ STDIO_BUFSIZE ] ;
570- char out_buffer [ STDIO_BUFSIZE ] ;
569+ char * in_buf = NULL ;
570+ char * out_buf = NULL ;
571571
572572/* sanity */
573573if (file -> size %BLCKSZ != 0 )
@@ -634,17 +634,12 @@ backup_data_file(ConnectionArgs* conn_arg, pgFile *file,
634634from_fullpath ,strerror (errno ));
635635}
636636
637- if (!fio_is_remote_file (in ))
638- setvbuf (in ,in_buffer ,_IOFBF ,STDIO_BUFSIZE );
639-
640637/* open backup file for write */
641638out = fopen (to_fullpath ,PG_BINARY_W );
642639if (out == NULL )
643640elog (ERROR ,"Cannot open backup file \"%s\": %s" ,
644641to_fullpath ,strerror (errno ));
645642
646- setvbuf (out ,out_buffer ,_IOFBF ,STDIO_BUFSIZE );
647-
648643/* update file permission */
649644if (chmod (to_fullpath ,FILE_PERMISSION )== -1 )
650645elog (ERROR ,"Cannot change mode of \"%s\": %s" ,to_fullpath ,
@@ -667,6 +662,24 @@ backup_data_file(ConnectionArgs* conn_arg, pgFile *file,
667662else
668663use_pagemap = true;
669664
665+ if (!fio_is_remote_file (in ))
666+ {
667+ /* enable stdio buffering for local input file,
668+ * unless the pagemap is involved, which
669+ * imply a lot of random access.
670+ */
671+ if (use_pagemap )
672+ setvbuf (in ,NULL ,_IONBF ,BUFSIZ );
673+ else
674+ {
675+ in_buf = pgut_malloc (STDIO_BUFSIZE );
676+ setvbuf (in ,in_buf ,_IOFBF ,STDIO_BUFSIZE );
677+ }
678+ }
679+
680+ /* enable stdio buffering for output file */
681+ out_buf = pgut_malloc (STDIO_BUFSIZE );
682+ setvbuf (out ,out_buf ,_IOFBF ,STDIO_BUFSIZE );
670683
671684/* Remote mode */
672685if (fio_is_remote_file (in ))
@@ -789,6 +802,9 @@ backup_data_file(ConnectionArgs* conn_arg, pgFile *file,
789802elog (ERROR ,"Cannot remove file \"%s\": %s" ,to_fullpath ,
790803strerror (errno ));
791804}
805+
806+ pg_free (in_buf );
807+ pg_free (out_buf );
792808}
793809
794810/*
@@ -837,18 +853,18 @@ backup_non_data_file(pgFile *file, pgFile *prev_file,
837853size_t
838854restore_data_file (parray * parent_chain ,pgFile * dest_file ,FILE * out ,const char * to_fullpath )
839855{
840- int i ;
856+ int i ;
841857size_t total_write_len = 0 ;
842- char buffer [ STDIO_BUFSIZE ] ;
858+ char * in_buf ;
843859
844860for (i = parray_num (parent_chain )- 1 ;i >=0 ;i -- )
845861{
846- char from_root [MAXPGPATH ];
847- char from_fullpath [MAXPGPATH ];
848- FILE * in = NULL ;
862+ char from_root [MAXPGPATH ];
863+ char from_fullpath [MAXPGPATH ];
864+ FILE * in = NULL ;
849865
850- pgFile * * res_file = NULL ;
851- pgFile * tmp_file = NULL ;
866+ pgFile * * res_file = NULL ;
867+ pgFile * tmp_file = NULL ;
852868
853869pgBackup * backup = (pgBackup * )parray_get (parent_chain ,i );
854870
@@ -886,7 +902,8 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out, const char
886902elog (ERROR ,"Cannot open backup file \"%s\": %s" ,from_fullpath ,
887903strerror (errno ));
888904
889- setvbuf (in ,buffer ,_IOFBF ,STDIO_BUFSIZE );
905+ in_buf = pgut_malloc (STDIO_BUFSIZE );
906+ setvbuf (in ,in_buf ,_IOFBF ,STDIO_BUFSIZE );
890907
891908/*
892909 * Restore the file.
@@ -902,6 +919,8 @@ restore_data_file(parray *parent_chain, pgFile *dest_file, FILE *out, const char
902919elog (ERROR ,"Cannot close file \"%s\": %s" ,from_fullpath ,
903920strerror (errno ));
904921}
922+ pg_free (in_buf );
923+
905924return total_write_len ;
906925}
907926
@@ -912,6 +931,21 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
912931BackupPageHeader header ;
913932BlockNumber blknum = 0 ;
914933size_t write_len = 0 ;
934+ off_t cur_pos = 0 ;
935+
936+ /*
937+ * We rely on stdio buffering of input and output.
938+ * For buffering to be efficient, we try to minimize the
939+ * number of lseek syscalls, because it forces buffer flush.
940+ * For that, we track current write position in
941+ * output file and issue fseek only when offset of block to be
942+ * written not equal to current write position, which happens
943+ * a lot when blocks from incremental backup are restored,
944+ * but should never happen in case of blocks from FULL backup.
945+ */
946+ if (fio_fseek (out ,cur_pos )< 0 )
947+ elog (ERROR ,"Cannot seek block %u of \"%s\": %s" ,
948+ blknum ,to_fullpath ,strerror (errno ));
915949
916950for (;;)
917951{
@@ -928,23 +962,24 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
928962/* read BackupPageHeader */
929963read_len = fread (& header ,1 ,sizeof (header ),in );
930964
965+ if (ferror (in ))
966+ elog (ERROR ,"Cannot read header of block %u of \"%s\": %s" ,
967+ blknum ,from_fullpath ,strerror (errno ));
968+
931969if (read_len != sizeof (header ))
932970{
933- int errno_tmp = errno ;
934971if (read_len == 0 && feof (in ))
935972break ;/* EOF found */
936- else if (read_len != 0 && feof (in ))
973+
974+ if (read_len != 0 && feof (in ))
937975elog (ERROR ,"Odd size page found at block %u of \"%s\"" ,
938976blknum ,from_fullpath );
939- else
940- elog (ERROR ,"Cannot read header of block %u of \"%s\": %s" ,
941- blknum ,from_fullpath ,strerror (errno_tmp ));
942977}
943978
944979/* Consider empty blockm. wtf empty block ? */
945980if (header .block == 0 && header .compressed_size == 0 )
946981{
947- elog (VERBOSE ,"Skip empty block of \"%s\"" ,from_fullpath );
982+ elog (WARNING ,"Skip empty block of \"%s\"" ,from_fullpath );
948983continue ;
949984}
950985
@@ -1019,14 +1054,19 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
10191054is_compressed = true;
10201055}
10211056
1022- write_pos = blknum * BLCKSZ ;
1023-
10241057/*
10251058 * Seek and write the restored page.
1059+ * When restoring file from FULL backup, pages are written sequentially,
1060+ * so there is no need to issue fseek for every page.
10261061 */
1027- if (fio_fseek (out ,write_pos )< 0 )
1028- elog (ERROR ,"Cannot seek block %u of \"%s\": %s" ,
1029- blknum ,to_fullpath ,strerror (errno ));
1062+ write_pos = blknum * BLCKSZ ;
1063+
1064+ if (cur_pos != write_pos )
1065+ {
1066+ if (fio_fseek (out ,blknum * BLCKSZ )< 0 )
1067+ elog (ERROR ,"Cannot seek block %u of \"%s\": %s" ,
1068+ blknum ,to_fullpath ,strerror (errno ));
1069+ }
10301070
10311071/* If page is compressed and restore is in remote mode, send compressed
10321072 * page to the remote side.
@@ -1048,6 +1088,7 @@ restore_data_file_internal(FILE *in, FILE *out, pgFile *file, uint32 backup_vers
10481088}
10491089
10501090write_len += BLCKSZ ;
1091+ cur_pos = write_pos + BLCKSZ ;/* update current write position */
10511092}
10521093
10531094elog (VERBOSE ,"Copied file \"%s\": %lu bytes" ,from_fullpath ,write_len );
@@ -1063,8 +1104,8 @@ void
10631104restore_non_data_file_internal (FILE * in ,FILE * out ,pgFile * file ,
10641105const char * from_fullpath ,const char * to_fullpath )
10651106{
1066- ssize_t read_len = 0 ;
1067- char buf [ STDIO_BUFSIZE ] ;/* 64kB buffer */
1107+ size_t read_len = 0 ;
1108+ char * buf = pgut_malloc ( STDIO_BUFSIZE ) ;/* 64kB buffer */
10681109
10691110/* copy content */
10701111for (;;)
@@ -1075,20 +1116,25 @@ restore_non_data_file_internal(FILE *in, FILE *out, pgFile *file,
10751116if (interrupted || thread_interrupted )
10761117elog (ERROR ,"Interrupted during non-data file restore" );
10771118
1078- read_len = fread (buf ,1 ,sizeof (buf ),in );
1079-
1080- if (read_len == 0 && feof (in ))
1081- break ;
1119+ read_len = fread (buf ,1 ,STDIO_BUFSIZE ,in );
10821120
1083- if (read_len < 0 )
1121+ if (ferror ( in ) )
10841122elog (ERROR ,"Cannot read backup file \"%s\": %s" ,
1085- from_fullpath ,strerror (errno ));
1123+ from_fullpath ,strerror (errno ));
10861124
1087- if (fio_fwrite (out ,buf ,read_len )!= read_len )
1088- elog (ERROR ,"Cannot write to \"%s\": %s" ,to_fullpath ,
1089- strerror (errno ));
1125+ if (read_len > 0 )
1126+ {
1127+ if (fio_fwrite (out ,buf ,read_len )!= read_len )
1128+ elog (ERROR ,"Cannot write to \"%s\": %s" ,to_fullpath ,
1129+ strerror (errno ));
1130+ }
1131+
1132+ if (feof (in ))
1133+ break ;
10901134}
10911135
1136+ pg_free (buf );
1137+
10921138elog (VERBOSE ,"Copied file \"%s\": %lu bytes" ,from_fullpath ,file -> write_size );
10931139}
10941140
@@ -1103,7 +1149,6 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
11031149
11041150pgFile * tmp_file = NULL ;
11051151pgBackup * tmp_backup = NULL ;
1106- char buffer [STDIO_BUFSIZE ];
11071152
11081153/* Check if full copy of destination file is available in destination backup */
11091154if (dest_file -> write_size > 0 )
@@ -1176,7 +1221,8 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
11761221elog (ERROR ,"Cannot open backup file \"%s\": %s" ,from_fullpath ,
11771222strerror (errno ));
11781223
1179- setvbuf (in ,buffer ,_IOFBF ,STDIO_BUFSIZE );
1224+ /* disable stdio buffering for non-data files */
1225+ setvbuf (in ,NULL ,_IONBF ,BUFSIZ );
11801226
11811227/* do actual work */
11821228restore_non_data_file_internal (in ,out ,tmp_file ,from_fullpath ,to_fullpath );
@@ -1192,17 +1238,18 @@ restore_non_data_file(parray *parent_chain, pgBackup *dest_backup,
11921238 * Copy file to backup.
11931239 * We do not apply compression to these files, because
11941240 * it is either small control file or already compressed cfs file.
1241+ * TODO: optimize remote copying
11951242 */
11961243void
11971244backup_non_data_file_internal (const char * from_fullpath ,
11981245fio_location from_location ,
11991246const char * to_fullpath ,pgFile * file ,
12001247bool missing_ok )
12011248{
1202- FILE * in ;
1203- FILE * out ;
1204- ssize_t read_len = 0 ;
1205- char buf [ STDIO_BUFSIZE ]; /* 64kB buffer */
1249+ FILE * in ;
1250+ FILE * out ;
1251+ ssize_t read_len = 0 ;
1252+ char * buf ;
12061253pg_crc32 crc ;
12071254
12081255INIT_FILE_CRC32 (true,crc );
@@ -1247,18 +1294,26 @@ backup_non_data_file_internal(const char *from_fullpath,
12471294elog (ERROR ,"Cannot change mode of \"%s\": %s" ,to_fullpath ,
12481295strerror (errno ));
12491296
1297+ /* disable stdio buffering for local input/output files */
1298+ if (!fio_is_remote_file (in ))
1299+ setvbuf (in ,NULL ,_IONBF ,BUFSIZ );
1300+ setvbuf (out ,NULL ,_IONBF ,BUFSIZ );
1301+
1302+ /* allocate 64kB buffer */
1303+ buf = pgut_malloc (STDIO_BUFSIZE );
1304+
12501305/* copy content and calc CRC */
12511306for (;;)
12521307{
1253- read_len = fio_fread (in ,buf ,sizeof (buf ));
1254-
1255- if (read_len == 0 )
1256- break ;
1308+ read_len = fio_fread (in ,buf ,STDIO_BUFSIZE );
12571309
12581310if (read_len < 0 )
12591311elog (ERROR ,"Cannot read from source file \"%s\": %s" ,
12601312from_fullpath ,strerror (errno ));
12611313
1314+ if (read_len == 0 )
1315+ break ;
1316+
12621317if (fwrite (buf ,1 ,read_len ,out )!= read_len )
12631318elog (ERROR ,"Cannot write to \"%s\": %s" ,to_fullpath ,
12641319strerror (errno ));
@@ -1267,6 +1322,19 @@ backup_non_data_file_internal(const char *from_fullpath,
12671322COMP_FILE_CRC32 (true,crc ,buf ,read_len );
12681323
12691324file -> read_size += read_len ;
1325+
1326+ //if (read_len < STDIO_BUFSIZE)
1327+ //{
1328+ //if (!fio_is_remote_file(in))
1329+ //{
1330+ //if (ferror(in))
1331+ //elog(ERROR, "Cannot read from source file \"%s\": %s",
1332+ //from_fullpath, strerror(errno));
1333+ //
1334+ //if (feof(in))
1335+ //break;
1336+ //}
1337+ //}
12701338}
12711339
12721340file -> write_size = (int64 )file -> read_size ;
@@ -1280,6 +1348,7 @@ backup_non_data_file_internal(const char *from_fullpath,
12801348if (fclose (out ))
12811349elog (ERROR ,"Cannot write \"%s\": %s" ,to_fullpath ,strerror (errno ));
12821350fio_fclose (in );
1351+ pg_free (buf );
12831352}
12841353
12851354/*
@@ -1478,9 +1547,13 @@ check_file_pages(pgFile *file, XLogRecPtr stop_lsn, uint32 checksum_version,
14781547
14791548/* read BackupPageHeader */
14801549read_len = fread (& header ,1 ,sizeof (header ),in );
1550+
1551+ if (ferror (in ))
1552+ elog (ERROR ,"Cannot read header of block %u of \"%s\": %s" ,
1553+ blknum ,file -> path ,strerror (errno ));
1554+
14811555if (read_len != sizeof (header ))
14821556{
1483- int errno_tmp = errno ;
14841557if (read_len == 0 && feof (in ))
14851558break ;/* EOF found */
14861559else if (read_len != 0 && feof (in ))
@@ -1489,7 +1562,7 @@ check_file_pages(pgFile *file, XLogRecPtr stop_lsn, uint32 checksum_version,
14891562blknum ,file -> path );
14901563else
14911564elog (WARNING ,"Cannot read header of block %u of \"%s\": %s" ,
1492- blknum ,file -> path ,strerror (errno_tmp ));
1565+ blknum ,file -> path ,strerror (errno ));
14931566return false;
14941567}
14951568