1 /*-------------------------------------------------------------------------
2  *
3  * xlogarchive.c
4  *		Functions for archiving WAL files and restoring from the archive.
5  *
6  *
7  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * src/backend/access/transam/xlogarchive.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 #include "postgres.h"
16 
17 #include <sys/stat.h>
18 #include <sys/wait.h>
19 #include <signal.h>
20 #include <unistd.h>
21 
22 #include "access/xlog.h"
23 #include "access/xlog_internal.h"
24 #include "miscadmin.h"
25 #include "postmaster/startup.h"
26 #include "replication/walsender.h"
27 #include "storage/fd.h"
28 #include "storage/ipc.h"
29 #include "storage/lwlock.h"
30 #include "storage/pmsignal.h"
31 
32 /*
33  * Attempt to retrieve the specified file from off-line archival storage.
34  * If successful, fill "path" with its complete path (note that this will be
35  * a temp file name that doesn't follow the normal naming convention), and
36  * return TRUE.
37  *
38  * If not successful, fill "path" with the name of the normal on-line file
39  * (which may or may not actually exist, but we'll try to use it), and return
40  * FALSE.
41  *
42  * For fixed-size files, the caller may pass the expected size as an
43  * additional crosscheck on successful recovery.  If the file size is not
44  * known, set expectedSize = 0.
45  *
46  * When 'cleanupEnabled' is false, refrain from deleting any old WAL segments
47  * in the archive. This is used when fetching the initial checkpoint record,
48  * when we are not yet sure how far back we need the WAL.
49  */
50 bool
RestoreArchivedFile(char * path,const char * xlogfname,const char * recovername,off_t expectedSize,bool cleanupEnabled)51 RestoreArchivedFile(char *path, const char *xlogfname,
52 					const char *recovername, off_t expectedSize,
53 					bool cleanupEnabled)
54 {
55 	char		xlogpath[MAXPGPATH];
56 	char		xlogRestoreCmd[MAXPGPATH];
57 	char		lastRestartPointFname[MAXPGPATH];
58 	char	   *dp;
59 	char	   *endp;
60 	const char *sp;
61 	int			rc;
62 	struct stat stat_buf;
63 	XLogSegNo	restartSegNo;
64 	XLogRecPtr	restartRedoPtr;
65 	TimeLineID	restartTli;
66 
67 	/* In standby mode, restore_command might not be supplied */
68 	if (recoveryRestoreCommand == NULL)
69 		goto not_available;
70 
71 	/*
72 	 * When doing archive recovery, we always prefer an archived log file even
73 	 * if a file of the same name exists in XLOGDIR.  The reason is that the
74 	 * file in XLOGDIR could be an old, un-filled or partly-filled version
75 	 * that was copied and restored as part of backing up $PGDATA.
76 	 *
77 	 * We could try to optimize this slightly by checking the local copy
78 	 * lastchange timestamp against the archived copy, but we have no API to
79 	 * do this, nor can we guarantee that the lastchange timestamp was
80 	 * preserved correctly when we copied to archive. Our aim is robustness,
81 	 * so we elect not to do this.
82 	 *
83 	 * If we cannot obtain the log file from the archive, however, we will try
84 	 * to use the XLOGDIR file if it exists.  This is so that we can make use
85 	 * of log segments that weren't yet transferred to the archive.
86 	 *
87 	 * Notice that we don't actually overwrite any files when we copy back
88 	 * from archive because the restore_command may inadvertently restore
89 	 * inappropriate xlogs, or they may be corrupt, so we may wish to fallback
90 	 * to the segments remaining in current XLOGDIR later. The
91 	 * copy-from-archive filename is always the same, ensuring that we don't
92 	 * run out of disk space on long recoveries.
93 	 */
94 	snprintf(xlogpath, MAXPGPATH, XLOGDIR "/%s", recovername);
95 
96 	/*
97 	 * Make sure there is no existing file named recovername.
98 	 */
99 	if (stat(xlogpath, &stat_buf) != 0)
100 	{
101 		if (errno != ENOENT)
102 			ereport(FATAL,
103 					(errcode_for_file_access(),
104 					 errmsg("could not stat file \"%s\": %m",
105 							xlogpath)));
106 	}
107 	else
108 	{
109 		if (unlink(xlogpath) != 0)
110 			ereport(FATAL,
111 					(errcode_for_file_access(),
112 					 errmsg("could not remove file \"%s\": %m",
113 							xlogpath)));
114 	}
115 
116 	/*
117 	 * Calculate the archive file cutoff point for use during log shipping
118 	 * replication. All files earlier than this point can be deleted from the
119 	 * archive, though there is no requirement to do so.
120 	 *
121 	 * If cleanup is not enabled, initialise this with the filename of
122 	 * InvalidXLogRecPtr, which will prevent the deletion of any WAL files
123 	 * from the archive because of the alphabetic sorting property of WAL
124 	 * filenames.
125 	 *
126 	 * Once we have successfully located the redo pointer of the checkpoint
127 	 * from which we start recovery we never request a file prior to the redo
128 	 * pointer of the last restartpoint. When redo begins we know that we have
129 	 * successfully located it, so there is no need for additional status
130 	 * flags to signify the point when we can begin deleting WAL files from
131 	 * the archive.
132 	 */
133 	if (cleanupEnabled)
134 	{
135 		GetOldestRestartPoint(&restartRedoPtr, &restartTli);
136 		XLByteToSeg(restartRedoPtr, restartSegNo);
137 		XLogFileName(lastRestartPointFname, restartTli, restartSegNo);
138 		/* we shouldn't need anything earlier than last restart point */
139 		Assert(strcmp(lastRestartPointFname, xlogfname) <= 0);
140 	}
141 	else
142 		XLogFileName(lastRestartPointFname, 0, 0L);
143 
144 	/*
145 	 * construct the command to be executed
146 	 */
147 	dp = xlogRestoreCmd;
148 	endp = xlogRestoreCmd + MAXPGPATH - 1;
149 	*endp = '\0';
150 
151 	for (sp = recoveryRestoreCommand; *sp; sp++)
152 	{
153 		if (*sp == '%')
154 		{
155 			switch (sp[1])
156 			{
157 				case 'p':
158 					/* %p: relative path of target file */
159 					sp++;
160 					StrNCpy(dp, xlogpath, endp - dp);
161 					make_native_path(dp);
162 					dp += strlen(dp);
163 					break;
164 				case 'f':
165 					/* %f: filename of desired file */
166 					sp++;
167 					StrNCpy(dp, xlogfname, endp - dp);
168 					dp += strlen(dp);
169 					break;
170 				case 'r':
171 					/* %r: filename of last restartpoint */
172 					sp++;
173 					StrNCpy(dp, lastRestartPointFname, endp - dp);
174 					dp += strlen(dp);
175 					break;
176 				case '%':
177 					/* convert %% to a single % */
178 					sp++;
179 					if (dp < endp)
180 						*dp++ = *sp;
181 					break;
182 				default:
183 					/* otherwise treat the % as not special */
184 					if (dp < endp)
185 						*dp++ = *sp;
186 					break;
187 			}
188 		}
189 		else
190 		{
191 			if (dp < endp)
192 				*dp++ = *sp;
193 		}
194 	}
195 	*dp = '\0';
196 
197 	ereport(DEBUG3,
198 			(errmsg_internal("executing restore command \"%s\"",
199 							 xlogRestoreCmd)));
200 
201 	/*
202 	 * Check signals before restore command and reset afterwards.
203 	 */
204 	PreRestoreCommand();
205 
206 	/*
207 	 * Copy xlog from archival storage to XLOGDIR
208 	 */
209 	rc = system(xlogRestoreCmd);
210 
211 	PostRestoreCommand();
212 
213 	if (rc == 0)
214 	{
215 		/*
216 		 * command apparently succeeded, but let's make sure the file is
217 		 * really there now and has the correct size.
218 		 */
219 		if (stat(xlogpath, &stat_buf) == 0)
220 		{
221 			if (expectedSize > 0 && stat_buf.st_size != expectedSize)
222 			{
223 				int			elevel;
224 
225 				/*
226 				 * If we find a partial file in standby mode, we assume it's
227 				 * because it's just being copied to the archive, and keep
228 				 * trying.
229 				 *
230 				 * Otherwise treat a wrong-sized file as FATAL to ensure the
231 				 * DBA would notice it, but is that too strong? We could try
232 				 * to plow ahead with a local copy of the file ... but the
233 				 * problem is that there probably isn't one, and we'd
234 				 * incorrectly conclude we've reached the end of WAL and we're
235 				 * done recovering ...
236 				 */
237 				if (StandbyMode && stat_buf.st_size < expectedSize)
238 					elevel = DEBUG1;
239 				else
240 					elevel = FATAL;
241 				ereport(elevel,
242 						(errmsg("archive file \"%s\" has wrong size: %lu instead of %lu",
243 								xlogfname,
244 								(unsigned long) stat_buf.st_size,
245 								(unsigned long) expectedSize)));
246 				return false;
247 			}
248 			else
249 			{
250 				ereport(LOG,
251 						(errmsg("restored log file \"%s\" from archive",
252 								xlogfname)));
253 				strcpy(path, xlogpath);
254 				return true;
255 			}
256 		}
257 		else
258 		{
259 			/* stat failed */
260 			if (errno != ENOENT)
261 				ereport(FATAL,
262 						(errcode_for_file_access(),
263 						 errmsg("could not stat file \"%s\": %m",
264 								xlogpath)));
265 		}
266 	}
267 
268 	/*
269 	 * Remember, we rollforward UNTIL the restore fails so failure here is
270 	 * just part of the process... that makes it difficult to determine
271 	 * whether the restore failed because there isn't an archive to restore,
272 	 * or because the administrator has specified the restore program
273 	 * incorrectly.  We have to assume the former.
274 	 *
275 	 * However, if the failure was due to any sort of signal, it's best to
276 	 * punt and abort recovery.  (If we "return false" here, upper levels will
277 	 * assume that recovery is complete and start up the database!) It's
278 	 * essential to abort on child SIGINT and SIGQUIT, because per spec
279 	 * system() ignores SIGINT and SIGQUIT while waiting; if we see one of
280 	 * those it's a good bet we should have gotten it too.
281 	 *
282 	 * On SIGTERM, assume we have received a fast shutdown request, and exit
283 	 * cleanly. It's pure chance whether we receive the SIGTERM first, or the
284 	 * child process. If we receive it first, the signal handler will call
285 	 * proc_exit, otherwise we do it here. If we or the child process received
286 	 * SIGTERM for any other reason than a fast shutdown request, postmaster
287 	 * will perform an immediate shutdown when it sees us exiting
288 	 * unexpectedly.
289 	 *
290 	 * We treat hard shell errors such as "command not found" as fatal, too.
291 	 */
292 	if (wait_result_is_signal(rc, SIGTERM))
293 		proc_exit(1);
294 
295 	ereport(wait_result_is_any_signal(rc, true) ? FATAL : DEBUG2,
296 			(errmsg("could not restore file \"%s\" from archive: %s",
297 					xlogfname, wait_result_to_str(rc))));
298 
299 not_available:
300 
301 	/*
302 	 * if an archived file is not available, there might still be a version of
303 	 * this file in XLOGDIR, so return that as the filename to open.
304 	 *
305 	 * In many recovery scenarios we expect this to fail also, but if so that
306 	 * just means we've reached the end of WAL.
307 	 */
308 	snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlogfname);
309 	return false;
310 }
311 
312 /*
313  * Attempt to execute an external shell command during recovery.
314  *
315  * 'command' is the shell command to be executed, 'commandName' is a
316  * human-readable name describing the command emitted in the logs. If
317  * 'failOnSignal' is true and the command is killed by a signal, a FATAL
318  * error is thrown. Otherwise a WARNING is emitted.
319  *
320  * This is currently used for recovery_end_command and archive_cleanup_command.
321  */
322 void
ExecuteRecoveryCommand(char * command,char * commandName,bool failOnSignal)323 ExecuteRecoveryCommand(char *command, char *commandName, bool failOnSignal)
324 {
325 	char		xlogRecoveryCmd[MAXPGPATH];
326 	char		lastRestartPointFname[MAXPGPATH];
327 	char	   *dp;
328 	char	   *endp;
329 	const char *sp;
330 	int			rc;
331 	XLogSegNo	restartSegNo;
332 	XLogRecPtr	restartRedoPtr;
333 	TimeLineID	restartTli;
334 
335 	Assert(command && commandName);
336 
337 	/*
338 	 * Calculate the archive file cutoff point for use during log shipping
339 	 * replication. All files earlier than this point can be deleted from the
340 	 * archive, though there is no requirement to do so.
341 	 */
342 	GetOldestRestartPoint(&restartRedoPtr, &restartTli);
343 	XLByteToSeg(restartRedoPtr, restartSegNo);
344 	XLogFileName(lastRestartPointFname, restartTli, restartSegNo);
345 
346 	/*
347 	 * construct the command to be executed
348 	 */
349 	dp = xlogRecoveryCmd;
350 	endp = xlogRecoveryCmd + MAXPGPATH - 1;
351 	*endp = '\0';
352 
353 	for (sp = command; *sp; sp++)
354 	{
355 		if (*sp == '%')
356 		{
357 			switch (sp[1])
358 			{
359 				case 'r':
360 					/* %r: filename of last restartpoint */
361 					sp++;
362 					StrNCpy(dp, lastRestartPointFname, endp - dp);
363 					dp += strlen(dp);
364 					break;
365 				case '%':
366 					/* convert %% to a single % */
367 					sp++;
368 					if (dp < endp)
369 						*dp++ = *sp;
370 					break;
371 				default:
372 					/* otherwise treat the % as not special */
373 					if (dp < endp)
374 						*dp++ = *sp;
375 					break;
376 			}
377 		}
378 		else
379 		{
380 			if (dp < endp)
381 				*dp++ = *sp;
382 		}
383 	}
384 	*dp = '\0';
385 
386 	ereport(DEBUG3,
387 			(errmsg_internal("executing %s \"%s\"", commandName, command)));
388 
389 	/*
390 	 * execute the constructed command
391 	 */
392 	rc = system(xlogRecoveryCmd);
393 	if (rc != 0)
394 	{
395 		/*
396 		 * If the failure was due to any sort of signal, it's best to punt and
397 		 * abort recovery.  See comments in RestoreArchivedFile().
398 		 */
399 		ereport((failOnSignal && wait_result_is_any_signal(rc, true)) ? FATAL : WARNING,
400 		/*------
401 		   translator: First %s represents a recovery.conf parameter name like
402 		  "recovery_end_command", the 2nd is the value of that parameter, the
403 		  third an already translated error message. */
404 				(errmsg("%s \"%s\": %s", commandName,
405 						command, wait_result_to_str(rc))));
406 	}
407 }
408 
409 
410 /*
411  * A file was restored from the archive under a temporary filename (path),
412  * and now we want to keep it. Rename it under the permanent filename in
413  * in pg_wal (xlogfname), replacing any existing file with the same name.
414  */
415 void
KeepFileRestoredFromArchive(char * path,char * xlogfname)416 KeepFileRestoredFromArchive(char *path, char *xlogfname)
417 {
418 	char		xlogfpath[MAXPGPATH];
419 	bool		reload = false;
420 	struct stat statbuf;
421 
422 	snprintf(xlogfpath, MAXPGPATH, XLOGDIR "/%s", xlogfname);
423 
424 	if (stat(xlogfpath, &statbuf) == 0)
425 	{
426 		char		oldpath[MAXPGPATH];
427 
428 #ifdef WIN32
429 		static unsigned int deletedcounter = 1;
430 
431 		/*
432 		 * On Windows, if another process (e.g a walsender process) holds the
433 		 * file open in FILE_SHARE_DELETE mode, unlink will succeed, but the
434 		 * file will still show up in directory listing until the last handle
435 		 * is closed, and we cannot rename the new file in its place until
436 		 * that. To avoid that problem, rename the old file to a temporary
437 		 * name first. Use a counter to create a unique filename, because the
438 		 * same file might be restored from the archive multiple times, and a
439 		 * walsender could still be holding onto an old deleted version of it.
440 		 */
441 		snprintf(oldpath, MAXPGPATH, "%s.deleted%u",
442 				 xlogfpath, deletedcounter++);
443 		if (rename(xlogfpath, oldpath) != 0)
444 		{
445 			ereport(ERROR,
446 					(errcode_for_file_access(),
447 					 errmsg("could not rename file \"%s\" to \"%s\": %m",
448 							xlogfpath, oldpath)));
449 		}
450 #else
451 		/* same-size buffers, so this never truncates */
452 		strlcpy(oldpath, xlogfpath, MAXPGPATH);
453 #endif
454 		if (unlink(oldpath) != 0)
455 			ereport(FATAL,
456 					(errcode_for_file_access(),
457 					 errmsg("could not remove file \"%s\": %m",
458 							xlogfpath)));
459 		reload = true;
460 	}
461 
462 	durable_rename(path, xlogfpath, ERROR);
463 
464 	/*
465 	 * Create .done file forcibly to prevent the restored segment from being
466 	 * archived again later.
467 	 */
468 	if (XLogArchiveMode != ARCHIVE_MODE_ALWAYS)
469 		XLogArchiveForceDone(xlogfname);
470 	else
471 		XLogArchiveNotify(xlogfname);
472 
473 	/*
474 	 * If the existing file was replaced, since walsenders might have it open,
475 	 * request them to reload a currently-open segment. This is only required
476 	 * for WAL segments, walsenders don't hold other files open, but there's
477 	 * no harm in doing this too often, and we don't know what kind of a file
478 	 * we're dealing with here.
479 	 */
480 	if (reload)
481 		WalSndRqstFileReload();
482 
483 	/*
484 	 * Signal walsender that new WAL has arrived. Again, this isn't necessary
485 	 * if we restored something other than a WAL segment, but it does no harm
486 	 * either.
487 	 */
488 	WalSndWakeup();
489 }
490 
491 /*
492  * XLogArchiveNotify
493  *
494  * Create an archive notification file
495  *
496  * The name of the notification file is the message that will be picked up
497  * by the archiver, e.g. we write 0000000100000001000000C6.ready
498  * and the archiver then knows to archive XLOGDIR/0000000100000001000000C6,
499  * then when complete, rename it to 0000000100000001000000C6.done
500  */
501 void
XLogArchiveNotify(const char * xlog)502 XLogArchiveNotify(const char *xlog)
503 {
504 	char		archiveStatusPath[MAXPGPATH];
505 	FILE	   *fd;
506 
507 	/* insert an otherwise empty file called <XLOG>.ready */
508 	StatusFilePath(archiveStatusPath, xlog, ".ready");
509 	fd = AllocateFile(archiveStatusPath, "w");
510 	if (fd == NULL)
511 	{
512 		ereport(LOG,
513 				(errcode_for_file_access(),
514 				 errmsg("could not create archive status file \"%s\": %m",
515 						archiveStatusPath)));
516 		return;
517 	}
518 	if (FreeFile(fd))
519 	{
520 		ereport(LOG,
521 				(errcode_for_file_access(),
522 				 errmsg("could not write archive status file \"%s\": %m",
523 						archiveStatusPath)));
524 		return;
525 	}
526 
527 	/* Notify archiver that it's got something to do */
528 	if (IsUnderPostmaster)
529 		SendPostmasterSignal(PMSIGNAL_WAKEN_ARCHIVER);
530 }
531 
532 /*
533  * Convenience routine to notify using segment number representation of filename
534  */
535 void
XLogArchiveNotifySeg(XLogSegNo segno)536 XLogArchiveNotifySeg(XLogSegNo segno)
537 {
538 	char		xlog[MAXFNAMELEN];
539 
540 	XLogFileName(xlog, ThisTimeLineID, segno);
541 	XLogArchiveNotify(xlog);
542 }
543 
544 /*
545  * XLogArchiveForceDone
546  *
547  * Emit notification forcibly that an XLOG segment file has been successfully
548  * archived, by creating <XLOG>.done regardless of whether <XLOG>.ready
549  * exists or not.
550  */
551 void
XLogArchiveForceDone(const char * xlog)552 XLogArchiveForceDone(const char *xlog)
553 {
554 	char		archiveReady[MAXPGPATH];
555 	char		archiveDone[MAXPGPATH];
556 	struct stat stat_buf;
557 	FILE	   *fd;
558 
559 	/* Exit if already known done */
560 	StatusFilePath(archiveDone, xlog, ".done");
561 	if (stat(archiveDone, &stat_buf) == 0)
562 		return;
563 
564 	/* If .ready exists, rename it to .done */
565 	StatusFilePath(archiveReady, xlog, ".ready");
566 	if (stat(archiveReady, &stat_buf) == 0)
567 	{
568 		(void) durable_rename(archiveReady, archiveDone, WARNING);
569 		return;
570 	}
571 
572 	/* insert an otherwise empty file called <XLOG>.done */
573 	fd = AllocateFile(archiveDone, "w");
574 	if (fd == NULL)
575 	{
576 		ereport(LOG,
577 				(errcode_for_file_access(),
578 				 errmsg("could not create archive status file \"%s\": %m",
579 						archiveDone)));
580 		return;
581 	}
582 	if (FreeFile(fd))
583 	{
584 		ereport(LOG,
585 				(errcode_for_file_access(),
586 				 errmsg("could not write archive status file \"%s\": %m",
587 						archiveDone)));
588 		return;
589 	}
590 }
591 
592 /*
593  * XLogArchiveCheckDone
594  *
595  * This is called when we are ready to delete or recycle an old XLOG segment
596  * file or backup history file.  If it is okay to delete it then return true.
597  * If it is not time to delete it, make sure a .ready file exists, and return
598  * false.
599  *
600  * If <XLOG>.done exists, then return true; else if <XLOG>.ready exists,
601  * then return false; else create <XLOG>.ready and return false.
602  *
603  * The reason we do things this way is so that if the original attempt to
604  * create <XLOG>.ready fails, we'll retry during subsequent checkpoints.
605  */
606 bool
XLogArchiveCheckDone(const char * xlog)607 XLogArchiveCheckDone(const char *xlog)
608 {
609 	char		archiveStatusPath[MAXPGPATH];
610 	struct stat stat_buf;
611 
612 	/* The file is always deletable if archive_mode is "off". */
613 	if (!XLogArchivingActive())
614 		return true;
615 
616 	/*
617 	 * During archive recovery, the file is deletable if archive_mode is not
618 	 * "always".
619 	 */
620 	if (!XLogArchivingAlways() &&
621 		GetRecoveryState() == RECOVERY_STATE_ARCHIVE)
622 		return true;
623 
624 	/*
625 	 * At this point of the logic, note that we are either a primary with
626 	 * archive_mode set to "on" or "always", or a standby with archive_mode
627 	 * set to "always".
628 	 */
629 
630 	/* First check for .done --- this means archiver is done with it */
631 	StatusFilePath(archiveStatusPath, xlog, ".done");
632 	if (stat(archiveStatusPath, &stat_buf) == 0)
633 		return true;
634 
635 	/* check for .ready --- this means archiver is still busy with it */
636 	StatusFilePath(archiveStatusPath, xlog, ".ready");
637 	if (stat(archiveStatusPath, &stat_buf) == 0)
638 		return false;
639 
640 	/* Race condition --- maybe archiver just finished, so recheck */
641 	StatusFilePath(archiveStatusPath, xlog, ".done");
642 	if (stat(archiveStatusPath, &stat_buf) == 0)
643 		return true;
644 
645 	/* Retry creation of the .ready file */
646 	XLogArchiveNotify(xlog);
647 	return false;
648 }
649 
650 /*
651  * XLogArchiveIsBusy
652  *
653  * Check to see if an XLOG segment file is still unarchived.
654  * This is almost but not quite the inverse of XLogArchiveCheckDone: in
655  * the first place we aren't chartered to recreate the .ready file, and
656  * in the second place we should consider that if the file is already gone
657  * then it's not busy.  (This check is needed to handle the race condition
658  * that a checkpoint already deleted the no-longer-needed file.)
659  */
660 bool
XLogArchiveIsBusy(const char * xlog)661 XLogArchiveIsBusy(const char *xlog)
662 {
663 	char		archiveStatusPath[MAXPGPATH];
664 	struct stat stat_buf;
665 
666 	/* First check for .done --- this means archiver is done with it */
667 	StatusFilePath(archiveStatusPath, xlog, ".done");
668 	if (stat(archiveStatusPath, &stat_buf) == 0)
669 		return false;
670 
671 	/* check for .ready --- this means archiver is still busy with it */
672 	StatusFilePath(archiveStatusPath, xlog, ".ready");
673 	if (stat(archiveStatusPath, &stat_buf) == 0)
674 		return true;
675 
676 	/* Race condition --- maybe archiver just finished, so recheck */
677 	StatusFilePath(archiveStatusPath, xlog, ".done");
678 	if (stat(archiveStatusPath, &stat_buf) == 0)
679 		return false;
680 
681 	/*
682 	 * Check to see if the WAL file has been removed by checkpoint, which
683 	 * implies it has already been archived, and explains why we can't see a
684 	 * status file for it.
685 	 */
686 	snprintf(archiveStatusPath, MAXPGPATH, XLOGDIR "/%s", xlog);
687 	if (stat(archiveStatusPath, &stat_buf) != 0 &&
688 		errno == ENOENT)
689 		return false;
690 
691 	return true;
692 }
693 
694 /*
695  * XLogArchiveIsReadyOrDone
696  *
697  * Check to see if an XLOG segment file has a .ready or .done file.
698  * This is similar to XLogArchiveIsBusy(), but returns true if the file
699  * is already archived or is about to be archived.
700  *
701  * This is currently only used at recovery.  During normal operation this
702  * would be racy: the file might get removed or marked with .ready as we're
703  * checking it, or immediately after we return.
704  */
705 bool
XLogArchiveIsReadyOrDone(const char * xlog)706 XLogArchiveIsReadyOrDone(const char *xlog)
707 {
708 	char		archiveStatusPath[MAXPGPATH];
709 	struct stat stat_buf;
710 
711 	/* First check for .done --- this means archiver is done with it */
712 	StatusFilePath(archiveStatusPath, xlog, ".done");
713 	if (stat(archiveStatusPath, &stat_buf) == 0)
714 		return true;
715 
716 	/* check for .ready --- this means archiver is still busy with it */
717 	StatusFilePath(archiveStatusPath, xlog, ".ready");
718 	if (stat(archiveStatusPath, &stat_buf) == 0)
719 		return true;
720 
721 	/* Race condition --- maybe archiver just finished, so recheck */
722 	StatusFilePath(archiveStatusPath, xlog, ".done");
723 	if (stat(archiveStatusPath, &stat_buf) == 0)
724 		return true;
725 
726 	return false;
727 }
728 
729 /*
730  * XLogArchiveIsReady
731  *
732  * Check to see if an XLOG segment file has an archive notification (.ready)
733  * file.
734  */
735 bool
XLogArchiveIsReady(const char * xlog)736 XLogArchiveIsReady(const char *xlog)
737 {
738 	char		archiveStatusPath[MAXPGPATH];
739 	struct stat stat_buf;
740 
741 	StatusFilePath(archiveStatusPath, xlog, ".ready");
742 	if (stat(archiveStatusPath, &stat_buf) == 0)
743 		return true;
744 
745 	return false;
746 }
747 
748 /*
749  * XLogArchiveCleanup
750  *
751  * Cleanup archive notification file(s) for a particular xlog segment
752  */
753 void
XLogArchiveCleanup(const char * xlog)754 XLogArchiveCleanup(const char *xlog)
755 {
756 	char		archiveStatusPath[MAXPGPATH];
757 
758 	/* Remove the .done file */
759 	StatusFilePath(archiveStatusPath, xlog, ".done");
760 	unlink(archiveStatusPath);
761 	/* should we complain about failure? */
762 
763 	/* Remove the .ready file if present --- normally it shouldn't be */
764 	StatusFilePath(archiveStatusPath, xlog, ".ready");
765 	unlink(archiveStatusPath);
766 	/* should we complain about failure? */
767 }
768