Skip to content

Commit 269812a

Browse files
committed
PGPRO-692: archive-push/archive-get to .temp file first, then rename()
1 parent 7925496 commit 269812a

File tree

1 file changed

+88
-41
lines changed

1 file changed

+88
-41
lines changed

src/data.c

Lines changed: 88 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -716,14 +716,14 @@ copy_file(const char *from_root, const char *to_root, pgFile *file)
716716
* Show error during work with compressed file
717717
*/
718718
static const char *
719-
get_gz_error(gzFile gzf)
719+
get_gz_error(gzFile gzf, int errnum)
720720
{
721-
int errnum;
721+
int gz_errnum;
722722
const char *errmsg;
723723

724-
errmsg = gzerror(gzf, &errnum);
725-
if (errnum == Z_ERRNO)
726-
return strerror(errno);
724+
errmsg = gzerror(gzf, &gz_errnum);
725+
if (gz_errnum == Z_ERRNO)
726+
return strerror(errnum);
727727
else
728728
return errmsg;
729729
}
@@ -765,6 +765,8 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
765765
FILE *out;
766766
char buf[XLOG_BLCKSZ];
767767
const char *to_path_p = to_path;
768+
char to_path_temp[MAXPGPATH];
769+
int errno_temp;
768770

769771
#ifdef HAVE_LIBZ
770772
char gz_to_path[MAXPGPATH];
@@ -786,10 +788,12 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
786788
if (!overwrite && fileExists(gz_to_path))
787789
elog(ERROR, "WAL segment \"%s\" already exists.", gz_to_path);
788790

789-
gz_out = gzopen(gz_to_path, "wb");
791+
snprintf(to_path_temp, sizeof(to_path_temp), "%s.temp", gz_to_path);
792+
793+
gz_out = gzopen(to_path_temp, "wb");
790794
if (gzsetparams(gz_out, compress_level, Z_DEFAULT_STRATEGY) != Z_OK)
791795
elog(ERROR, "Cannot set compression level %d to file \"%s\": %s",
792-
compress_level, gz_to_path, get_gz_error(gz_out));
796+
compress_level, to_path_temp, get_gz_error(gz_out, errno));
793797

794798
to_path_p = gz_to_path;
795799
}
@@ -799,10 +803,12 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
799803
if (!overwrite && fileExists(to_path))
800804
elog(ERROR, "WAL segment \"%s\" already exists.", to_path);
801805

802-
out = fopen(to_path, "w");
806+
snprintf(to_path_temp, sizeof(to_path_temp), "%s.temp", to_path);
807+
808+
out = fopen(to_path_temp, "w");
803809
if (out == NULL)
804810
elog(ERROR, "Cannot open destination WAL file \"%s\": %s",
805-
to_path, strerror(errno));
811+
to_path_temp, strerror(errno));
806812
}
807813

808814
/* copy content */
@@ -814,9 +820,11 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
814820

815821
if (ferror(in))
816822
{
817-
unlink(to_path_p);
818-
elog(ERROR, "Cannot read source WAL file \"%s\": %s",
819-
from_path, strerror(errno));
823+
errno_temp = errno;
824+
unlink(to_path_temp);
825+
elog(ERROR,
826+
"Cannot read source WAL file \"%s\": %s",
827+
from_path, strerror(errno_temp));
820828
}
821829

822830
if (read_len > 0)
@@ -826,19 +834,21 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
826834
{
827835
if (gzwrite(gz_out, buf, read_len) != read_len)
828836
{
829-
unlink(to_path_p);
837+
errno_temp = errno;
838+
unlink(to_path_temp);
830839
elog(ERROR, "Cannot write to compressed WAL file \"%s\": %s",
831-
gz_to_path, get_gz_error(gz_out));
840+
to_path_temp, get_gz_error(gz_out, errno_temp));
832841
}
833842
}
834843
else
835844
#endif
836845
{
837846
if (fwrite(buf, 1, read_len, out) != read_len)
838847
{
839-
unlink(to_path_p);
848+
errno_temp = errno;
849+
unlink(to_path_temp);
840850
elog(ERROR, "Cannot write to WAL file \"%s\": %s",
841-
to_path, strerror(errno));
851+
to_path_temp, strerror(errno_temp));
842852
}
843853
}
844854
}
@@ -852,11 +862,11 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
852862
{
853863
if (gzclose(gz_out) != 0)
854864
{
855-
unlink(to_path_p);
865+
errno_temp = errno;
866+
unlink(to_path_temp);
856867
elog(ERROR, "Cannot close compressed WAL file \"%s\": %s",
857-
gz_to_path, get_gz_error(gz_out));
868+
to_path_temp, get_gz_error(gz_out, errno_temp));
858869
}
859-
elog(INFO, "WAL file compressed to \"%s\"", gz_to_path);
860870
}
861871
else
862872
#endif
@@ -865,21 +875,36 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress,
865875
fsync(fileno(out)) != 0 ||
866876
fclose(out))
867877
{
868-
unlink(to_path_p);
878+
errno_temp = errno;
879+
unlink(to_path_temp);
869880
elog(ERROR, "Cannot write WAL file \"%s\": %s",
870-
to_path, strerror(errno));
881+
to_path_temp, strerror(errno_temp));
871882
}
872883
}
873884

874885
if (fclose(in))
875886
{
876-
unlink(to_path_p);
887+
errno_temp = errno;
888+
unlink(to_path_temp);
877889
elog(ERROR, "Cannot close source WAL file \"%s\": %s",
878-
from_path, strerror(errno));
890+
from_path, strerror(errno_temp));
879891
}
880892

881893
/* update file permission. */
882-
copy_meta(from_path, to_path_p, true);
894+
copy_meta(from_path, to_path_temp, true);
895+
896+
if (rename(to_path_temp, to_path_p) < 0)
897+
{
898+
errno_temp = errno;
899+
unlink(to_path_temp);
900+
elog(ERROR, "Cannot rename WAL file \"%s\" to \"%s\": %s",
901+
to_path_temp, to_path_p, strerror(errno_temp));
902+
}
903+
904+
#ifdef HAVE_LIBZ
905+
if (is_compress)
906+
elog(INFO, "WAL file compressed to \"%s\"", gz_to_path);
907+
#endif
883908
}
884909

885910
/*
@@ -892,6 +917,8 @@ get_wal_file(const char *from_path, const char *to_path)
892917
FILE *out;
893918
char buf[XLOG_BLCKSZ];
894919
const char *from_path_p = from_path;
920+
char to_path_temp[MAXPGPATH];
921+
int errno_temp;
895922
bool is_decompress = false;
896923

897924
#ifdef HAVE_LIBZ
@@ -935,10 +962,12 @@ get_wal_file(const char *from_path, const char *to_path)
935962
}
936963

937964
/* open backup file for write */
938-
out = fopen(to_path, "w");
965+
snprintf(to_path_temp, sizeof(to_path_temp), "%s.temp", to_path);
966+
967+
out = fopen(to_path_temp, "w");
939968
if (out == NULL)
940969
elog(ERROR, "Cannot open destination WAL file \"%s\": %s",
941-
to_path, strerror(errno));
970+
to_path_temp, strerror(errno));
942971

943972
/* copy content */
944973
for (;;)
@@ -951,9 +980,10 @@ get_wal_file(const char *from_path, const char *to_path)
951980
read_len = gzread(gz_in, buf, sizeof(buf));
952981
if (read_len != sizeof(buf) && !gzeof(gz_in))
953982
{
954-
unlink(to_path);
983+
errno_temp = errno;
984+
unlink(to_path_temp);
955985
elog(ERROR, "Cannot read compressed WAL file \"%s\": %s",
956-
gz_from_path, get_gz_error(gz_in));
986+
gz_from_path, get_gz_error(gz_in, errno_temp));
957987
}
958988
}
959989
else
@@ -962,19 +992,21 @@ get_wal_file(const char *from_path, const char *to_path)
962992
read_len = fread(buf, 1, sizeof(buf), in);
963993
if (ferror(in))
964994
{
965-
unlink(to_path);
995+
errno_temp = errno;
996+
unlink(to_path_temp);
966997
elog(ERROR, "Cannot read source WAL file \"%s\": %s",
967-
from_path, strerror(errno));
998+
from_path, strerror(errno_temp));
968999
}
9691000
}
9701001

9711002
if (read_len > 0)
9721003
{
9731004
if (fwrite(buf, 1, read_len, out) != read_len)
9741005
{
975-
unlink(to_path);
976-
elog(ERROR, "Cannot write to WAL file \"%s\": %s", to_path,
977-
strerror(errno));
1006+
errno_temp = errno;
1007+
unlink(to_path_temp);
1008+
elog(ERROR, "Cannot write to WAL file \"%s\": %s", to_path_temp,
1009+
strerror(errno_temp));
9781010
}
9791011
}
9801012

@@ -997,35 +1029,50 @@ get_wal_file(const char *from_path, const char *to_path)
9971029
fsync(fileno(out)) != 0 ||
9981030
fclose(out))
9991031
{
1000-
unlink(to_path);
1032+
errno_temp = errno;
1033+
unlink(to_path_temp);
10011034
elog(ERROR, "Cannot write WAL file \"%s\": %s",
1002-
to_path, strerror(errno));
1035+
to_path_temp, strerror(errno_temp));
10031036
}
10041037

10051038
#ifdef HAVE_LIBZ
10061039
if (is_decompress)
10071040
{
10081041
if (gzclose(gz_in) != 0)
10091042
{
1010-
unlink(to_path);
1043+
errno_temp = errno;
1044+
unlink(to_path_temp);
10111045
elog(ERROR, "Cannot close compressed WAL file \"%s\": %s",
1012-
gz_from_path, get_gz_error(gz_in));
1046+
gz_from_path, get_gz_error(gz_in, errno_temp));
10131047
}
1014-
elog(INFO, "WAL file decompressed from \"%s\"", gz_from_path);
10151048
}
10161049
else
10171050
#endif
10181051
{
10191052
if (fclose(in))
10201053
{
1021-
unlink(to_path);
1054+
errno_temp = errno;
1055+
unlink(to_path_temp);
10221056
elog(ERROR, "Cannot close source WAL file \"%s\": %s",
1023-
from_path, strerror(errno));
1057+
from_path, strerror(errno_temp));
10241058
}
10251059
}
10261060

10271061
/* update file permission. */
1028-
copy_meta(from_path_p, to_path, true);
1062+
copy_meta(from_path_p, to_path_temp, true);
1063+
1064+
if (rename(to_path_temp, to_path) < 0)
1065+
{
1066+
errno_temp = errno;
1067+
unlink(to_path_temp);
1068+
elog(ERROR, "Cannot rename WAL file \"%s\" to \"%s\": %s",
1069+
to_path_temp, to_path, strerror(errno_temp));
1070+
}
1071+
1072+
#ifdef HAVE_LIBZ
1073+
if (is_decompress)
1074+
elog(INFO, "WAL file decompressed from \"%s\"", gz_from_path);
1075+
#endif
10291076
}
10301077

10311078
/*

0 commit comments

Comments
 (0)