PostgreSQL Source Code  git master
archive.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * archive.c
4  * Routines to access WAL archives from frontend
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/fe_utils/archive.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "postgres_fe.h"
17 
18 #include <unistd.h>
19 #include <sys/stat.h>
20 
21 #include "access/xlog_internal.h"
22 #include "common/archive.h"
23 #include "common/logging.h"
24 #include "fe_utils/archive.h"
25 
26 
27 /*
28  * RestoreArchivedFile
29  *
30  * Attempt to retrieve the specified file from off-line archival storage.
31  * If successful, return a file descriptor of the restored file, else
32  * return -1.
33  *
34  * For fixed-size files, the caller may pass the expected size as an
35  * additional crosscheck on successful recovery. If the file size is not
36  * known, set expectedSize = 0.
37  */
38 int
39 RestoreArchivedFile(const char *path, const char *xlogfname,
40  off_t expectedSize, const char *restoreCommand)
41 {
42  char xlogpath[MAXPGPATH];
43  char *xlogRestoreCmd;
44  int rc;
45  struct stat stat_buf;
46 
47  snprintf(xlogpath, MAXPGPATH, "%s/" XLOGDIR "/%s", path, xlogfname);
48 
49  xlogRestoreCmd = BuildRestoreCommand(restoreCommand, xlogpath,
50  xlogfname, NULL);
51  if (xlogRestoreCmd == NULL)
52  {
53  pg_log_fatal("cannot use restore_command with %%r placeholder");
54  exit(1);
55  }
56 
57  /*
58  * Execute restore_command, which should copy the missing file from
59  * archival storage.
60  */
61  rc = system(xlogRestoreCmd);
62  pfree(xlogRestoreCmd);
63 
64  if (rc == 0)
65  {
66  /*
67  * Command apparently succeeded, but let's make sure the file is
68  * really there now and has the correct size.
69  */
70  if (stat(xlogpath, &stat_buf) == 0)
71  {
72  if (expectedSize > 0 && stat_buf.st_size != expectedSize)
73  {
74  pg_log_fatal("unexpected file size for \"%s\": %lld instead of %lld",
75  xlogfname, (long long int) stat_buf.st_size,
76  (long long int) expectedSize);
77  exit(1);
78  }
79  else
80  {
81  int xlogfd = open(xlogpath, O_RDONLY | PG_BINARY, 0);
82 
83  if (xlogfd < 0)
84  {
85  pg_log_fatal("could not open file \"%s\" restored from archive: %m",
86  xlogpath);
87  exit(1);
88  }
89  else
90  return xlogfd;
91  }
92  }
93  else
94  {
95  if (errno != ENOENT)
96  {
97  pg_log_fatal("could not stat file \"%s\": %m",
98  xlogpath);
99  exit(1);
100  }
101  }
102  }
103 
104  /*
105  * If the failure was due to a signal, then it would be misleading to
106  * return with a failure at restoring the file. So just bail out and
107  * exit. Hard shell errors such as "command not found" are treated as
108  * fatal too.
109  */
110  if (wait_result_is_any_signal(rc, true))
111  {
112  pg_log_fatal("restore_command failed: %s",
113  wait_result_to_str(rc));
114  exit(1);
115  }
116 
117  /*
118  * The file is not available, so just let the caller decide what to do
119  * next.
120  */
121  pg_log_error("could not restore file \"%s\" from archive",
122  xlogfname);
123  return -1;
124 }
char * BuildRestoreCommand(const char *restoreCommand, const char *xlogpath, const char *xlogfname, const char *lastRestartPointFname)
Definition: archive.c:39
#define pg_log_error(...)
Definition: logging.h:80
char * wait_result_to_str(int exitstatus)
Definition: wait_error.c:32
#define PG_BINARY
Definition: c.h:1271
void pfree(void *pointer)
Definition: mcxt.c:1169
int RestoreArchivedFile(const char *path, const char *xlogfname, off_t expectedSize, const char *restoreCommand)
Definition: archive.c:39
#define MAXPGPATH
__int64 st_size
Definition: win32_port.h:265
#define XLOGDIR
bool wait_result_is_any_signal(int exit_status, bool include_command_not_found)
Definition: wait_error.c:111
#define snprintf
Definition: port.h:216
#define stat
Definition: win32_port.h:275
#define pg_log_fatal(...)
Definition: logging.h:76