@@ -34,11 +34,41 @@ static XLogRecPtr lastFlushPosition = InvalidXLogRecPtr;
3434static PGresult * HandleCopyStream (PGconn * conn , XLogRecPtr startpos ,
3535 uint32 timeline , char * basedir ,
3636 stream_stop_callback stream_stop , int standby_message_timeout ,
37- char * partial_suffix , XLogRecPtr * stoppos );
37+ char * partial_suffix , XLogRecPtr * stoppos ,
38+ bool mark_done );
3839
3940static bool ReadEndOfStreamingResult (PGresult * res , XLogRecPtr * startpos ,
4041 uint32 * timeline );
4142
43+ static bool
44+ mark_file_as_archived (const char * basedir , const char * fname )
45+ {
46+ int fd ;
47+ static char tmppath [MAXPGPATH ];
48+
49+ snprintf (tmppath , sizeof (tmppath ), "%s/archive_status/%s.done" ,
50+ basedir , fname );
51+
52+ fd = open (tmppath , O_WRONLY | O_CREAT | PG_BINARY , S_IRUSR | S_IWUSR );
53+ if (fd < 0 )
54+ {
55+ fprintf (stderr , _ ("%s: could not create archive status file \"%s\": %s\n" ),
56+ progname , tmppath , strerror (errno ));
57+ return false;
58+ }
59+
60+ if (fsync (fd ) != 0 )
61+ {
62+ fprintf (stderr , _ ("%s: could not fsync file \"%s\": %s\n" ),
63+ progname , tmppath , strerror (errno ));
64+ return false;
65+ }
66+
67+ close (fd );
68+
69+ return true;
70+ }
71+
4272/*
4373 * Open a new WAL file in the specified directory.
4474 *
@@ -132,7 +162,7 @@ open_walfile(XLogRecPtr startpoint, uint32 timeline, char *basedir,
132162 * and returns false, otherwise returns true.
133163 */
134164static bool
135- close_walfile (char * basedir , char * partial_suffix , XLogRecPtr pos )
165+ close_walfile (char * basedir , char * partial_suffix , XLogRecPtr pos , bool mark_done )
136166{
137167 off_t currpos ;
138168
@@ -186,6 +216,19 @@ close_walfile(char *basedir, char *partial_suffix, XLogRecPtr pos)
186216 _ ("%s: not renaming \"%s%s\", segment is not complete\n" ),
187217 progname , current_walfile_name , partial_suffix );
188218
219+ /*
220+ * Mark file as archived if requested by the caller - pg_basebackup needs
221+ * to do so as files can otherwise get archived again after promotion of a
222+ * new node. This is in line with walreceiver.c always doing a
223+ * XLogArchiveForceDone() after a complete segment.
224+ */
225+ if (currpos == XLOG_SEG_SIZE && mark_done )
226+ {
227+ /* writes error message if failed */
228+ if (!mark_file_as_archived (basedir , current_walfile_name ))
229+ return false;
230+ }
231+
189232 lastFlushPosition = pos ;
190233 return true;
191234}
@@ -228,7 +271,8 @@ existsTimeLineHistoryFile(char *basedir, TimeLineID tli)
228271}
229272
230273static bool
231- writeTimeLineHistoryFile (char * basedir , TimeLineID tli , char * filename , char * content )
274+ writeTimeLineHistoryFile (char * basedir , TimeLineID tli , char * filename ,
275+ char * content , bool mark_done )
232276{
233277 int size = strlen (content );
234278 char path [MAXPGPATH ];
@@ -307,6 +351,14 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co
307351 return false;
308352 }
309353
354+ /* Maintain archive_status, check close_walfile() for details. */
355+ if (mark_done )
356+ {
357+ /* writes error message if failed */
358+ if (!mark_file_as_archived (basedir , histfname ))
359+ return false;
360+ }
361+
310362 return true;
311363}
312364
423475ReceiveXlogStream (PGconn * conn , XLogRecPtr startpos , uint32 timeline ,
424476 char * sysidentifier , char * basedir ,
425477 stream_stop_callback stream_stop ,
426- int standby_message_timeout , char * partial_suffix )
478+ int standby_message_timeout , char * partial_suffix ,
479+ bool mark_done )
427480{
428481 char query [128 ];
429482 char slotcmd [128 ];
@@ -538,7 +591,8 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
538591 /* Write the history file to disk */
539592 writeTimeLineHistoryFile (basedir , timeline ,
540593 PQgetvalue (res , 0 , 0 ),
541- PQgetvalue (res , 0 , 1 ));
594+ PQgetvalue (res , 0 , 1 ),
595+ mark_done );
542596
543597 PQclear (res );
544598 }
@@ -568,7 +622,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
568622 /* Stream the WAL */
569623 res = HandleCopyStream (conn , startpos , timeline , basedir , stream_stop ,
570624 standby_message_timeout , partial_suffix ,
571- & stoppos );
625+ & stoppos , mark_done );
572626 if (res == NULL )
573627 goto error ;
574628
@@ -733,7 +787,7 @@ static PGresult *
733787HandleCopyStream (PGconn * conn , XLogRecPtr startpos , uint32 timeline ,
734788 char * basedir , stream_stop_callback stream_stop ,
735789 int standby_message_timeout , char * partial_suffix ,
736- XLogRecPtr * stoppos )
790+ XLogRecPtr * stoppos , bool mark_done )
737791{
738792 char * copybuf = NULL ;
739793 int64 last_status = -1 ;
@@ -760,7 +814,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
760814 */
761815 if (still_sending && stream_stop (blockpos , timeline , false))
762816 {
763- if (!close_walfile (basedir , partial_suffix , blockpos ))
817+ if (!close_walfile (basedir , partial_suffix , blockpos , mark_done ))
764818 {
765819 /* Potential error message is written by close_walfile */
766820 goto error ;
@@ -859,7 +913,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
859913 */
860914 if (still_sending )
861915 {
862- if (!close_walfile (basedir , partial_suffix , blockpos ))
916+ if (!close_walfile (basedir , partial_suffix , blockpos , mark_done ))
863917 {
864918 /* Error message written in close_walfile() */
865919 PQclear (res );
@@ -1046,7 +1100,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
10461100 /* Did we reach the end of a WAL segment? */
10471101 if (blockpos % XLOG_SEG_SIZE == 0 )
10481102 {
1049- if (!close_walfile (basedir , partial_suffix , blockpos ))
1103+ if (!close_walfile (basedir , partial_suffix , blockpos , mark_done ))
10501104 /* Error message written in close_walfile() */
10511105 goto error ;
10521106
0 commit comments