@@ -37,28 +37,58 @@ static PGresult *HandleCopyStream(PGconn *conn, XLogRecPtr startpos,
3737 uint32 timeline , char * basedir ,
3838 stream_stop_callback stream_stop , int standby_message_timeout ,
3939 char * partial_suffix , XLogRecPtr * stoppos ,
40- bool synchronous );
40+ bool synchronous , bool mark_done );
4141static int CopyStreamPoll (PGconn * conn , long timeout_ms );
4242static int CopyStreamReceive (PGconn * conn , long timeout , char * * buffer );
4343static bool ProcessKeepaliveMsg (PGconn * conn , char * copybuf , int len ,
4444 XLogRecPtr blockpos , int64 * last_status );
4545static bool ProcessXLogDataMsg (PGconn * conn , char * copybuf , int len ,
4646 XLogRecPtr * blockpos , uint32 timeline ,
4747 char * basedir , stream_stop_callback stream_stop ,
48- char * partial_suffix );
48+ char * partial_suffix , bool mark_done );
4949static PGresult * HandleEndOfCopyStream (PGconn * conn , char * copybuf ,
5050 XLogRecPtr blockpos , char * basedir , char * partial_suffix ,
51- XLogRecPtr * stoppos );
51+ XLogRecPtr * stoppos , bool mark_done );
5252static bool CheckCopyStreamStop (PGconn * conn , XLogRecPtr blockpos ,
5353 uint32 timeline , char * basedir ,
5454 stream_stop_callback stream_stop ,
55- char * partial_suffix , XLogRecPtr * stoppos );
55+ char * partial_suffix , XLogRecPtr * stoppos ,
56+ bool mark_done );
5657static long CalculateCopyStreamSleeptime (int64 now , int standby_message_timeout ,
5758 int64 last_status );
5859
5960static bool ReadEndOfStreamingResult (PGresult * res , XLogRecPtr * startpos ,
6061 uint32 * timeline );
6162
63+ static bool
64+ mark_file_as_archived (const char * basedir , const char * fname )
65+ {
66+ int fd ;
67+ static char tmppath [MAXPGPATH ];
68+
69+ snprintf (tmppath , sizeof (tmppath ), "%s/archive_status/%s.done" ,
70+ basedir , fname );
71+
72+ fd = open (tmppath , O_WRONLY | O_CREAT | PG_BINARY , S_IRUSR | S_IWUSR );
73+ if (fd < 0 )
74+ {
75+ fprintf (stderr , _ ("%s: could not create archive status file \"%s\": %s\n" ),
76+ progname , tmppath , strerror (errno ));
77+ return false;
78+ }
79+
80+ if (fsync (fd ) != 0 )
81+ {
82+ fprintf (stderr , _ ("%s: could not fsync file \"%s\": %s\n" ),
83+ progname , tmppath , strerror (errno ));
84+ return false;
85+ }
86+
87+ close (fd );
88+
89+ return true;
90+ }
91+
6292/*
6393 * Open a new WAL file in the specified directory.
6494 *
@@ -152,7 +182,7 @@ open_walfile(XLogRecPtr startpoint, uint32 timeline, char *basedir,
152182 * and returns false, otherwise returns true.
153183 */
154184static bool
155- close_walfile (char * basedir , char * partial_suffix , XLogRecPtr pos )
185+ close_walfile (char * basedir , char * partial_suffix , XLogRecPtr pos , bool mark_done )
156186{
157187 off_t currpos ;
158188
@@ -206,6 +236,19 @@ close_walfile(char *basedir, char *partial_suffix, XLogRecPtr pos)
206236 _ ("%s: not renaming \"%s%s\", segment is not complete\n" ),
207237 progname , current_walfile_name , partial_suffix );
208238
239+ /*
240+ * Mark file as archived if requested by the caller - pg_basebackup needs
241+ * to do so as files can otherwise get archived again after promotion of a
242+ * new node. This is in line with walreceiver.c always doing a
243+ * XLogArchiveForceDone() after a complete segment.
244+ */
245+ if (currpos == XLOG_SEG_SIZE && mark_done )
246+ {
247+ /* writes error message if failed */
248+ if (!mark_file_as_archived (basedir , current_walfile_name ))
249+ return false;
250+ }
251+
209252 lastFlushPosition = pos ;
210253 return true;
211254}
@@ -248,7 +291,8 @@ existsTimeLineHistoryFile(char *basedir, TimeLineID tli)
248291}
249292
250293static bool
251- writeTimeLineHistoryFile (char * basedir , TimeLineID tli , char * filename , char * content )
294+ writeTimeLineHistoryFile (char * basedir , TimeLineID tli , char * filename ,
295+ char * content , bool mark_done )
252296{
253297 int size = strlen (content );
254298 char path [MAXPGPATH ];
@@ -327,6 +371,14 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co
327371 return false;
328372 }
329373
374+ /* Maintain archive_status, check close_walfile() for details. */
375+ if (mark_done )
376+ {
377+ /* writes error message if failed */
378+ if (!mark_file_as_archived (basedir , histfname ))
379+ return false;
380+ }
381+
330382 return true;
331383}
332384
@@ -447,7 +499,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
447499 char * sysidentifier , char * basedir ,
448500 stream_stop_callback stream_stop ,
449501 int standby_message_timeout , char * partial_suffix ,
450- bool synchronous )
502+ bool synchronous , bool mark_done )
451503{
452504 char query [128 ];
453505 char slotcmd [128 ];
@@ -562,7 +614,8 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
562614 /* Write the history file to disk */
563615 writeTimeLineHistoryFile (basedir , timeline ,
564616 PQgetvalue (res , 0 , 0 ),
565- PQgetvalue (res , 0 , 1 ));
617+ PQgetvalue (res , 0 , 1 ),
618+ mark_done );
566619
567620 PQclear (res );
568621 }
@@ -592,7 +645,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
592645 /* Stream the WAL */
593646 res = HandleCopyStream (conn , startpos , timeline , basedir , stream_stop ,
594647 standby_message_timeout , partial_suffix ,
595- & stoppos , synchronous );
648+ & stoppos , synchronous , mark_done );
596649 if (res == NULL )
597650 goto error ;
598651
@@ -757,7 +810,7 @@ static PGresult *
757810HandleCopyStream (PGconn * conn , XLogRecPtr startpos , uint32 timeline ,
758811 char * basedir , stream_stop_callback stream_stop ,
759812 int standby_message_timeout , char * partial_suffix ,
760- XLogRecPtr * stoppos , bool synchronous )
813+ XLogRecPtr * stoppos , bool synchronous , bool mark_done )
761814{
762815 char * copybuf = NULL ;
763816 int64 last_status = -1 ;
@@ -775,7 +828,8 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
775828 * Check if we should continue streaming, or abort at this point.
776829 */
777830 if (!CheckCopyStreamStop (conn , blockpos , timeline , basedir ,
778- stream_stop , partial_suffix , stoppos ))
831+ stream_stop , partial_suffix , stoppos ,
832+ mark_done ))
779833 goto error ;
780834
781835 now = feGetCurrentTimestamp ();
@@ -830,7 +884,8 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
830884 if (r == -2 )
831885 {
832886 PGresult * res = HandleEndOfCopyStream (conn , copybuf , blockpos ,
833- basedir , partial_suffix , stoppos );
887+ basedir , partial_suffix ,
888+ stoppos , mark_done );
834889 if (res == NULL )
835890 goto error ;
836891 else
@@ -847,14 +902,16 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
847902 else if (copybuf [0 ] == 'w' )
848903 {
849904 if (!ProcessXLogDataMsg (conn , copybuf , r , & blockpos ,
850- timeline , basedir , stream_stop , partial_suffix ))
905+ timeline , basedir , stream_stop ,
906+ partial_suffix , true))
851907 goto error ;
852908
853909 /*
854910 * Check if we should continue streaming, or abort at this point.
855911 */
856912 if (!CheckCopyStreamStop (conn , blockpos , timeline , basedir ,
857- stream_stop , partial_suffix , stoppos ))
913+ stream_stop , partial_suffix , stoppos ,
914+ mark_done ))
858915 goto error ;
859916 }
860917 else
@@ -1055,7 +1112,7 @@ static bool
10551112ProcessXLogDataMsg (PGconn * conn , char * copybuf , int len ,
10561113 XLogRecPtr * blockpos , uint32 timeline ,
10571114 char * basedir , stream_stop_callback stream_stop ,
1058- char * partial_suffix )
1115+ char * partial_suffix , bool mark_done )
10591116{
10601117 int xlogoff ;
10611118 int bytes_left ;
@@ -1163,7 +1220,7 @@ ProcessXLogDataMsg(PGconn *conn, char *copybuf, int len,
11631220 /* Did we reach the end of a WAL segment? */
11641221 if (* blockpos % XLOG_SEG_SIZE == 0 )
11651222 {
1166- if (!close_walfile (basedir , partial_suffix , * blockpos ))
1223+ if (!close_walfile (basedir , partial_suffix , * blockpos , mark_done ))
11671224 /* Error message written in close_walfile() */
11681225 return false;
11691226
@@ -1193,7 +1250,7 @@ ProcessXLogDataMsg(PGconn *conn, char *copybuf, int len,
11931250static PGresult *
11941251HandleEndOfCopyStream (PGconn * conn , char * copybuf ,
11951252 XLogRecPtr blockpos , char * basedir , char * partial_suffix ,
1196- XLogRecPtr * stoppos )
1253+ XLogRecPtr * stoppos , bool mark_done )
11971254{
11981255 PGresult * res = PQgetResult (conn );
11991256
@@ -1204,7 +1261,7 @@ HandleEndOfCopyStream(PGconn *conn, char *copybuf,
12041261 */
12051262 if (still_sending )
12061263 {
1207- if (!close_walfile (basedir , partial_suffix , blockpos ))
1264+ if (!close_walfile (basedir , partial_suffix , blockpos , mark_done ))
12081265 {
12091266 /* Error message written in close_walfile() */
12101267 PQclear (res );
@@ -1236,11 +1293,11 @@ HandleEndOfCopyStream(PGconn *conn, char *copybuf,
12361293static bool
12371294CheckCopyStreamStop (PGconn * conn , XLogRecPtr blockpos , uint32 timeline ,
12381295 char * basedir , stream_stop_callback stream_stop ,
1239- char * partial_suffix , XLogRecPtr * stoppos )
1296+ char * partial_suffix , XLogRecPtr * stoppos , bool mark_done )
12401297{
12411298 if (still_sending && stream_stop (blockpos , timeline , false))
12421299 {
1243- if (!close_walfile (basedir , partial_suffix , blockpos ))
1300+ if (!close_walfile (basedir , partial_suffix , blockpos , mark_done ))
12441301 {
12451302 /* Potential error message is written by close_walfile */
12461303 return false;
0 commit comments