1 /*-------------------------------------------------------------------------
2  *
3  * pgarch.c
4  *
5  *	PostgreSQL WAL archiver
6  *
7  *	All functions relating to archiver are included here
8  *
9  *	- All functions executed by archiver process
10  *
11  *	- archiver is forked from postmaster, and the two
12  *	processes then communicate using signals. All functions
13  *	executed by postmaster are included in this file.
14  *
15  *	Initial author: Simon Riggs		simon@2ndquadrant.com
16  *
17  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
18  * Portions Copyright (c) 1994, Regents of the University of California
19  *
20  *
21  * IDENTIFICATION
22  *	  src/backend/postmaster/pgarch.c
23  *
24  *-------------------------------------------------------------------------
25  */
26 #include "postgres.h"
27 
28 #include <fcntl.h>
29 #include <signal.h>
30 #include <time.h>
31 #include <sys/stat.h>
32 #include <sys/time.h>
33 #include <sys/wait.h>
34 #include <unistd.h>
35 
36 #include "access/xlog.h"
37 #include "access/xlog_internal.h"
38 #include "libpq/pqsignal.h"
39 #include "miscadmin.h"
40 #include "pgstat.h"
41 #include "postmaster/fork_process.h"
42 #include "postmaster/interrupt.h"
43 #include "postmaster/pgarch.h"
44 #include "postmaster/postmaster.h"
45 #include "storage/dsm.h"
46 #include "storage/fd.h"
47 #include "storage/ipc.h"
48 #include "storage/latch.h"
49 #include "storage/pg_shmem.h"
50 #include "storage/pmsignal.h"
51 #include "utils/guc.h"
52 #include "utils/ps_status.h"
53 
54 
55 /* ----------
56  * Timer definitions.
57  * ----------
58  */
59 #define PGARCH_AUTOWAKE_INTERVAL 60 /* How often to force a poll of the
60 									 * archive status directory; in seconds. */
61 #define PGARCH_RESTART_INTERVAL 10	/* How often to attempt to restart a
62 									 * failed archiver; in seconds. */
63 
64 /*
65  * Maximum number of retries allowed when attempting to archive a WAL
66  * file.
67  */
68 #define NUM_ARCHIVE_RETRIES 3
69 
70 /*
71  * Maximum number of retries allowed when attempting to remove an
72  * orphan archive status file.
73  */
74 #define NUM_ORPHAN_CLEANUP_RETRIES 3
75 
76 
77 /* ----------
78  * Local data
79  * ----------
80  */
81 static time_t last_pgarch_start_time;
82 static time_t last_sigterm_time = 0;
83 
84 /*
85  * Flags set by interrupt handlers for later service in the main loop.
86  */
87 static volatile sig_atomic_t wakened = false;
88 static volatile sig_atomic_t ready_to_stop = false;
89 
90 /* ----------
91  * Local function forward declarations
92  * ----------
93  */
94 #ifdef EXEC_BACKEND
95 static pid_t pgarch_forkexec(void);
96 #endif
97 
98 NON_EXEC_STATIC void PgArchiverMain(int argc, char *argv[]) pg_attribute_noreturn();
99 static void pgarch_waken(SIGNAL_ARGS);
100 static void pgarch_waken_stop(SIGNAL_ARGS);
101 static void pgarch_MainLoop(void);
102 static void pgarch_ArchiverCopyLoop(void);
103 static bool pgarch_archiveXlog(char *xlog);
104 static bool pgarch_readyXlog(char *xlog);
105 static void pgarch_archiveDone(char *xlog);
106 
107 
108 /* ------------------------------------------------------------
109  * Public functions called from postmaster follow
110  * ------------------------------------------------------------
111  */
112 
113 /*
114  * pgarch_start
115  *
116  *	Called from postmaster at startup or after an existing archiver
117  *	died.  Attempt to fire up a fresh archiver process.
118  *
119  *	Returns PID of child process, or 0 if fail.
120  *
121  *	Note: if fail, we will be called again from the postmaster main loop.
122  */
123 int
pgarch_start(void)124 pgarch_start(void)
125 {
126 	time_t		curtime;
127 	pid_t		pgArchPid;
128 
129 	/*
130 	 * Do nothing if no archiver needed
131 	 */
132 	if (!XLogArchivingActive())
133 		return 0;
134 
135 	/*
136 	 * Do nothing if too soon since last archiver start.  This is a safety
137 	 * valve to protect against continuous respawn attempts if the archiver is
138 	 * dying immediately at launch. Note that since we will be re-called from
139 	 * the postmaster main loop, we will get another chance later.
140 	 */
141 	curtime = time(NULL);
142 	if ((unsigned int) (curtime - last_pgarch_start_time) <
143 		(unsigned int) PGARCH_RESTART_INTERVAL)
144 		return 0;
145 	last_pgarch_start_time = curtime;
146 
147 #ifdef EXEC_BACKEND
148 	switch ((pgArchPid = pgarch_forkexec()))
149 #else
150 	switch ((pgArchPid = fork_process()))
151 #endif
152 	{
153 		case -1:
154 			ereport(LOG,
155 					(errmsg("could not fork archiver: %m")));
156 			return 0;
157 
158 #ifndef EXEC_BACKEND
159 		case 0:
160 			/* in postmaster child ... */
161 			InitPostmasterChild();
162 
163 			/* Close the postmaster's sockets */
164 			ClosePostmasterPorts(false);
165 
166 			/* Drop our connection to postmaster's shared memory, as well */
167 			dsm_detach_all();
168 			PGSharedMemoryDetach();
169 
170 			PgArchiverMain(0, NULL);
171 			break;
172 #endif
173 
174 		default:
175 			return (int) pgArchPid;
176 	}
177 
178 	/* shouldn't get here */
179 	return 0;
180 }
181 
182 /* ------------------------------------------------------------
183  * Local functions called by archiver follow
184  * ------------------------------------------------------------
185  */
186 
187 
188 #ifdef EXEC_BACKEND
189 
190 /*
191  * pgarch_forkexec() -
192  *
193  * Format up the arglist for, then fork and exec, archive process
194  */
195 static pid_t
pgarch_forkexec(void)196 pgarch_forkexec(void)
197 {
198 	char	   *av[10];
199 	int			ac = 0;
200 
201 	av[ac++] = "postgres";
202 
203 	av[ac++] = "--forkarch";
204 
205 	av[ac++] = NULL;			/* filled in by postmaster_forkexec */
206 
207 	av[ac] = NULL;
208 	Assert(ac < lengthof(av));
209 
210 	return postmaster_forkexec(ac, av);
211 }
212 #endif							/* EXEC_BACKEND */
213 
214 
215 /*
216  * PgArchiverMain
217  *
218  *	The argc/argv parameters are valid only in EXEC_BACKEND case.  However,
219  *	since we don't use 'em, it hardly matters...
220  */
221 NON_EXEC_STATIC void
PgArchiverMain(int argc,char * argv[])222 PgArchiverMain(int argc, char *argv[])
223 {
224 	/*
225 	 * Ignore all signals usually bound to some action in the postmaster,
226 	 * except for SIGHUP, SIGTERM, SIGUSR1, SIGUSR2, and SIGQUIT.
227 	 */
228 	pqsignal(SIGHUP, SignalHandlerForConfigReload);
229 	pqsignal(SIGINT, SIG_IGN);
230 	pqsignal(SIGTERM, SignalHandlerForShutdownRequest);
231 	pqsignal(SIGQUIT, SignalHandlerForCrashExit);
232 	pqsignal(SIGALRM, SIG_IGN);
233 	pqsignal(SIGPIPE, SIG_IGN);
234 	pqsignal(SIGUSR1, pgarch_waken);
235 	pqsignal(SIGUSR2, pgarch_waken_stop);
236 	/* Reset some signals that are accepted by postmaster but not here */
237 	pqsignal(SIGCHLD, SIG_DFL);
238 	PG_SETMASK(&UnBlockSig);
239 
240 	MyBackendType = B_ARCHIVER;
241 	init_ps_display(NULL);
242 
243 	pgarch_MainLoop();
244 
245 	exit(0);
246 }
247 
248 /* SIGUSR1 signal handler for archiver process */
249 static void
pgarch_waken(SIGNAL_ARGS)250 pgarch_waken(SIGNAL_ARGS)
251 {
252 	int			save_errno = errno;
253 
254 	/* set flag that there is work to be done */
255 	wakened = true;
256 	SetLatch(MyLatch);
257 
258 	errno = save_errno;
259 }
260 
261 /* SIGUSR2 signal handler for archiver process */
262 static void
pgarch_waken_stop(SIGNAL_ARGS)263 pgarch_waken_stop(SIGNAL_ARGS)
264 {
265 	int			save_errno = errno;
266 
267 	/* set flag to do a final cycle and shut down afterwards */
268 	ready_to_stop = true;
269 	SetLatch(MyLatch);
270 
271 	errno = save_errno;
272 }
273 
274 /*
275  * pgarch_MainLoop
276  *
277  * Main loop for archiver
278  */
279 static void
pgarch_MainLoop(void)280 pgarch_MainLoop(void)
281 {
282 	pg_time_t	last_copy_time = 0;
283 	bool		time_to_stop;
284 
285 	/*
286 	 * We run the copy loop immediately upon entry, in case there are
287 	 * unarchived files left over from a previous database run (or maybe the
288 	 * archiver died unexpectedly).  After that we wait for a signal or
289 	 * timeout before doing more.
290 	 */
291 	wakened = true;
292 
293 	/*
294 	 * There shouldn't be anything for the archiver to do except to wait for a
295 	 * signal ... however, the archiver exists to protect our data, so she
296 	 * wakes up occasionally to allow herself to be proactive.
297 	 */
298 	do
299 	{
300 		ResetLatch(MyLatch);
301 
302 		/* When we get SIGUSR2, we do one more archive cycle, then exit */
303 		time_to_stop = ready_to_stop;
304 
305 		/* Check for config update */
306 		if (ConfigReloadPending)
307 		{
308 			ConfigReloadPending = false;
309 			ProcessConfigFile(PGC_SIGHUP);
310 		}
311 
312 		/*
313 		 * If we've gotten SIGTERM, we normally just sit and do nothing until
314 		 * SIGUSR2 arrives.  However, that means a random SIGTERM would
315 		 * disable archiving indefinitely, which doesn't seem like a good
316 		 * idea.  If more than 60 seconds pass since SIGTERM, exit anyway, so
317 		 * that the postmaster can start a new archiver if needed.
318 		 */
319 		if (ShutdownRequestPending)
320 		{
321 			time_t		curtime = time(NULL);
322 
323 			if (last_sigterm_time == 0)
324 				last_sigterm_time = curtime;
325 			else if ((unsigned int) (curtime - last_sigterm_time) >=
326 					 (unsigned int) 60)
327 				break;
328 		}
329 
330 		/* Do what we're here for */
331 		if (wakened || time_to_stop)
332 		{
333 			wakened = false;
334 			pgarch_ArchiverCopyLoop();
335 			last_copy_time = time(NULL);
336 		}
337 
338 		/*
339 		 * Sleep until a signal is received, or until a poll is forced by
340 		 * PGARCH_AUTOWAKE_INTERVAL having passed since last_copy_time, or
341 		 * until postmaster dies.
342 		 */
343 		if (!time_to_stop)		/* Don't wait during last iteration */
344 		{
345 			pg_time_t	curtime = (pg_time_t) time(NULL);
346 			int			timeout;
347 
348 			timeout = PGARCH_AUTOWAKE_INTERVAL - (curtime - last_copy_time);
349 			if (timeout > 0)
350 			{
351 				int			rc;
352 
353 				rc = WaitLatch(MyLatch,
354 							   WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
355 							   timeout * 1000L,
356 							   WAIT_EVENT_ARCHIVER_MAIN);
357 				if (rc & WL_TIMEOUT)
358 					wakened = true;
359 				if (rc & WL_POSTMASTER_DEATH)
360 					time_to_stop = true;
361 			}
362 			else
363 				wakened = true;
364 		}
365 
366 		/*
367 		 * The archiver quits either when the postmaster dies (not expected)
368 		 * or after completing one more archiving cycle after receiving
369 		 * SIGUSR2.
370 		 */
371 	} while (!time_to_stop);
372 }
373 
374 /*
375  * pgarch_ArchiverCopyLoop
376  *
377  * Archives all outstanding xlogs then returns
378  */
379 static void
pgarch_ArchiverCopyLoop(void)380 pgarch_ArchiverCopyLoop(void)
381 {
382 	char		xlog[MAX_XFN_CHARS + 1];
383 
384 	/*
385 	 * loop through all xlogs with archive_status of .ready and archive
386 	 * them...mostly we expect this to be a single file, though it is possible
387 	 * some backend will add files onto the list of those that need archiving
388 	 * while we are still copying earlier archives
389 	 */
390 	while (pgarch_readyXlog(xlog))
391 	{
392 		int			failures = 0;
393 		int			failures_orphan = 0;
394 
395 		for (;;)
396 		{
397 			struct stat stat_buf;
398 			char		pathname[MAXPGPATH];
399 
400 			/*
401 			 * Do not initiate any more archive commands after receiving
402 			 * SIGTERM, nor after the postmaster has died unexpectedly. The
403 			 * first condition is to try to keep from having init SIGKILL the
404 			 * command, and the second is to avoid conflicts with another
405 			 * archiver spawned by a newer postmaster.
406 			 */
407 			if (ShutdownRequestPending || !PostmasterIsAlive())
408 				return;
409 
410 			/*
411 			 * Check for config update.  This is so that we'll adopt a new
412 			 * setting for archive_command as soon as possible, even if there
413 			 * is a backlog of files to be archived.
414 			 */
415 			if (ConfigReloadPending)
416 			{
417 				ConfigReloadPending = false;
418 				ProcessConfigFile(PGC_SIGHUP);
419 			}
420 
421 			/* can't do anything if no command ... */
422 			if (!XLogArchiveCommandSet())
423 			{
424 				ereport(WARNING,
425 						(errmsg("archive_mode enabled, yet archive_command is not set")));
426 				return;
427 			}
428 
429 			/*
430 			 * Since archive status files are not removed in a durable manner,
431 			 * a system crash could leave behind .ready files for WAL segments
432 			 * that have already been recycled or removed.  In this case,
433 			 * simply remove the orphan status file and move on.  unlink() is
434 			 * used here as even on subsequent crashes the same orphan files
435 			 * would get removed, so there is no need to worry about
436 			 * durability.
437 			 */
438 			snprintf(pathname, MAXPGPATH, XLOGDIR "/%s", xlog);
439 			if (stat(pathname, &stat_buf) != 0 && errno == ENOENT)
440 			{
441 				char		xlogready[MAXPGPATH];
442 
443 				StatusFilePath(xlogready, xlog, ".ready");
444 				if (unlink(xlogready) == 0)
445 				{
446 					ereport(WARNING,
447 							(errmsg("removed orphan archive status file \"%s\"",
448 									xlogready)));
449 
450 					/* leave loop and move to the next status file */
451 					break;
452 				}
453 
454 				if (++failures_orphan >= NUM_ORPHAN_CLEANUP_RETRIES)
455 				{
456 					ereport(WARNING,
457 							(errmsg("removal of orphan archive status file \"%s\" failed too many times, will try again later",
458 									xlogready)));
459 
460 					/* give up cleanup of orphan status files */
461 					return;
462 				}
463 
464 				/* wait a bit before retrying */
465 				pg_usleep(1000000L);
466 				continue;
467 			}
468 
469 			if (pgarch_archiveXlog(xlog))
470 			{
471 				/* successful */
472 				pgarch_archiveDone(xlog);
473 
474 				/*
475 				 * Tell the collector about the WAL file that we successfully
476 				 * archived
477 				 */
478 				pgstat_send_archiver(xlog, false);
479 
480 				break;			/* out of inner retry loop */
481 			}
482 			else
483 			{
484 				/*
485 				 * Tell the collector about the WAL file that we failed to
486 				 * archive
487 				 */
488 				pgstat_send_archiver(xlog, true);
489 
490 				if (++failures >= NUM_ARCHIVE_RETRIES)
491 				{
492 					ereport(WARNING,
493 							(errmsg("archiving write-ahead log file \"%s\" failed too many times, will try again later",
494 									xlog)));
495 					return;		/* give up archiving for now */
496 				}
497 				pg_usleep(1000000L);	/* wait a bit before retrying */
498 			}
499 		}
500 	}
501 }
502 
503 /*
504  * pgarch_archiveXlog
505  *
506  * Invokes system(3) to copy one archive file to wherever it should go
507  *
508  * Returns true if successful
509  */
510 static bool
pgarch_archiveXlog(char * xlog)511 pgarch_archiveXlog(char *xlog)
512 {
513 	char		xlogarchcmd[MAXPGPATH];
514 	char		pathname[MAXPGPATH];
515 	char		activitymsg[MAXFNAMELEN + 16];
516 	char	   *dp;
517 	char	   *endp;
518 	const char *sp;
519 	int			rc;
520 
521 	snprintf(pathname, MAXPGPATH, XLOGDIR "/%s", xlog);
522 
523 	/*
524 	 * construct the command to be executed
525 	 */
526 	dp = xlogarchcmd;
527 	endp = xlogarchcmd + MAXPGPATH - 1;
528 	*endp = '\0';
529 
530 	for (sp = XLogArchiveCommand; *sp; sp++)
531 	{
532 		if (*sp == '%')
533 		{
534 			switch (sp[1])
535 			{
536 				case 'p':
537 					/* %p: relative path of source file */
538 					sp++;
539 					strlcpy(dp, pathname, endp - dp);
540 					make_native_path(dp);
541 					dp += strlen(dp);
542 					break;
543 				case 'f':
544 					/* %f: filename of source file */
545 					sp++;
546 					strlcpy(dp, xlog, endp - dp);
547 					dp += strlen(dp);
548 					break;
549 				case '%':
550 					/* convert %% to a single % */
551 					sp++;
552 					if (dp < endp)
553 						*dp++ = *sp;
554 					break;
555 				default:
556 					/* otherwise treat the % as not special */
557 					if (dp < endp)
558 						*dp++ = *sp;
559 					break;
560 			}
561 		}
562 		else
563 		{
564 			if (dp < endp)
565 				*dp++ = *sp;
566 		}
567 	}
568 	*dp = '\0';
569 
570 	ereport(DEBUG3,
571 			(errmsg_internal("executing archive command \"%s\"",
572 							 xlogarchcmd)));
573 
574 	/* Report archive activity in PS display */
575 	snprintf(activitymsg, sizeof(activitymsg), "archiving %s", xlog);
576 	set_ps_display(activitymsg);
577 
578 	rc = system(xlogarchcmd);
579 	if (rc != 0)
580 	{
581 		/*
582 		 * If either the shell itself, or a called command, died on a signal,
583 		 * abort the archiver.  We do this because system() ignores SIGINT and
584 		 * SIGQUIT while waiting; so a signal is very likely something that
585 		 * should have interrupted us too.  Also die if the shell got a hard
586 		 * "command not found" type of error.  If we overreact it's no big
587 		 * deal, the postmaster will just start the archiver again.
588 		 */
589 		int			lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
590 
591 		if (WIFEXITED(rc))
592 		{
593 			ereport(lev,
594 					(errmsg("archive command failed with exit code %d",
595 							WEXITSTATUS(rc)),
596 					 errdetail("The failed archive command was: %s",
597 							   xlogarchcmd)));
598 		}
599 		else if (WIFSIGNALED(rc))
600 		{
601 #if defined(WIN32)
602 			ereport(lev,
603 					(errmsg("archive command was terminated by exception 0x%X",
604 							WTERMSIG(rc)),
605 					 errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
606 					 errdetail("The failed archive command was: %s",
607 							   xlogarchcmd)));
608 #else
609 			ereport(lev,
610 					(errmsg("archive command was terminated by signal %d: %s",
611 							WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
612 					 errdetail("The failed archive command was: %s",
613 							   xlogarchcmd)));
614 #endif
615 		}
616 		else
617 		{
618 			ereport(lev,
619 					(errmsg("archive command exited with unrecognized status %d",
620 							rc),
621 					 errdetail("The failed archive command was: %s",
622 							   xlogarchcmd)));
623 		}
624 
625 		snprintf(activitymsg, sizeof(activitymsg), "failed on %s", xlog);
626 		set_ps_display(activitymsg);
627 
628 		return false;
629 	}
630 	elog(DEBUG1, "archived write-ahead log file \"%s\"", xlog);
631 
632 	snprintf(activitymsg, sizeof(activitymsg), "last was %s", xlog);
633 	set_ps_display(activitymsg);
634 
635 	return true;
636 }
637 
638 /*
639  * pgarch_readyXlog
640  *
641  * Return name of the oldest xlog file that has not yet been archived.
642  * No notification is set that file archiving is now in progress, so
643  * this would need to be extended if multiple concurrent archival
644  * tasks were created. If a failure occurs, we will completely
645  * re-copy the file at the next available opportunity.
646  *
647  * It is important that we return the oldest, so that we archive xlogs
648  * in order that they were written, for two reasons:
649  * 1) to maintain the sequential chain of xlogs required for recovery
650  * 2) because the oldest ones will sooner become candidates for
651  * recycling at time of checkpoint
652  *
653  * NOTE: the "oldest" comparison will consider any .history file to be older
654  * than any other file except another .history file.  Segments on a timeline
655  * with a smaller ID will be older than all segments on a timeline with a
656  * larger ID; the net result being that past timelines are given higher
657  * priority for archiving.  This seems okay, or at least not obviously worth
658  * changing.
659  */
660 static bool
pgarch_readyXlog(char * xlog)661 pgarch_readyXlog(char *xlog)
662 {
663 	/*
664 	 * open xlog status directory and read through list of xlogs that have the
665 	 * .ready suffix, looking for earliest file. It is possible to optimise
666 	 * this code, though only a single file is expected on the vast majority
667 	 * of calls, so....
668 	 */
669 	char		XLogArchiveStatusDir[MAXPGPATH];
670 	DIR		   *rldir;
671 	struct dirent *rlde;
672 	bool		found = false;
673 	bool		historyFound = false;
674 
675 	snprintf(XLogArchiveStatusDir, MAXPGPATH, XLOGDIR "/archive_status");
676 	rldir = AllocateDir(XLogArchiveStatusDir);
677 
678 	while ((rlde = ReadDir(rldir, XLogArchiveStatusDir)) != NULL)
679 	{
680 		int			basenamelen = (int) strlen(rlde->d_name) - 6;
681 		char		basename[MAX_XFN_CHARS + 1];
682 		bool		ishistory;
683 
684 		/* Ignore entries with unexpected number of characters */
685 		if (basenamelen < MIN_XFN_CHARS ||
686 			basenamelen > MAX_XFN_CHARS)
687 			continue;
688 
689 		/* Ignore entries with unexpected characters */
690 		if (strspn(rlde->d_name, VALID_XFN_CHARS) < basenamelen)
691 			continue;
692 
693 		/* Ignore anything not suffixed with .ready */
694 		if (strcmp(rlde->d_name + basenamelen, ".ready") != 0)
695 			continue;
696 
697 		/* Truncate off the .ready */
698 		memcpy(basename, rlde->d_name, basenamelen);
699 		basename[basenamelen] = '\0';
700 
701 		/* Is this a history file? */
702 		ishistory = IsTLHistoryFileName(basename);
703 
704 		/*
705 		 * Consume the file to archive.  History files have the highest
706 		 * priority.  If this is the first file or the first history file
707 		 * ever, copy it.  In the presence of a history file already chosen as
708 		 * target, ignore all other files except history files which have been
709 		 * generated for an older timeline than what is already chosen as
710 		 * target to archive.
711 		 */
712 		if (!found || (ishistory && !historyFound))
713 		{
714 			strcpy(xlog, basename);
715 			found = true;
716 			historyFound = ishistory;
717 		}
718 		else if (ishistory || !historyFound)
719 		{
720 			if (strcmp(basename, xlog) < 0)
721 				strcpy(xlog, basename);
722 		}
723 	}
724 	FreeDir(rldir);
725 
726 	return found;
727 }
728 
729 /*
730  * pgarch_archiveDone
731  *
732  * Emit notification that an xlog file has been successfully archived.
733  * We do this by renaming the status file from NNN.ready to NNN.done.
734  * Eventually, a checkpoint process will notice this and delete both the
735  * NNN.done file and the xlog file itself.
736  */
737 static void
pgarch_archiveDone(char * xlog)738 pgarch_archiveDone(char *xlog)
739 {
740 	char		rlogready[MAXPGPATH];
741 	char		rlogdone[MAXPGPATH];
742 
743 	StatusFilePath(rlogready, xlog, ".ready");
744 	StatusFilePath(rlogdone, xlog, ".done");
745 	(void) durable_rename(rlogready, rlogdone, WARNING);
746 }
747