PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_rewind.c File Reference
#include "postgres_fe.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include "access/timeline.h"
#include "access/xlog_internal.h"
#include "catalog/catversion.h"
#include "catalog/pg_control.h"
#include "common/controldata_utils.h"
#include "common/file_perm.h"
#include "common/restricted_token.h"
#include "common/string.h"
#include "fe_utils/option_utils.h"
#include "fe_utils/recovery_gen.h"
#include "fe_utils/string_utils.h"
#include "file_ops.h"
#include "filemap.h"
#include "getopt_long.h"
#include "pg_rewind.h"
#include "rewind_source.h"
#include "storage/bufpage.h"
Include dependency graph for pg_rewind.c:

Go to the source code of this file.

Functions

static void usage (const char *progname)
 
static void perform_rewind (filemap_t *filemap, rewind_source *source, XLogRecPtr chkptrec, TimeLineID chkpttli, XLogRecPtr chkptredo)
 
static void createBackupLabel (XLogRecPtr startpoint, TimeLineID starttli, XLogRecPtr checkpointloc)
 
static void digestControlFile (ControlFileData *ControlFile, const char *content, size_t size)
 
static void getRestoreCommand (const char *argv0)
 
static void sanityChecks (void)
 
static TimeLineHistoryEntrygetTimelineHistory (TimeLineID tli, bool is_source, int *nentries)
 
static void findCommonAncestorTimeline (TimeLineHistoryEntry *a_history, int a_nentries, TimeLineHistoryEntry *b_history, int b_nentries, XLogRecPtr *recptr, int *tliIndex)
 
static void ensureCleanShutdown (const char *argv0)
 
static void disconnect_atexit (void)
 
int main (int argc, char **argv)
 
void progress_report (bool finished)
 
static XLogRecPtr MinXLogRecPtr (XLogRecPtr a, XLogRecPtr b)
 
static void checkControlFile (ControlFileData *ControlFile)
 

Variables

static ControlFileData ControlFile_target
 
static ControlFileData ControlFile_source
 
static ControlFileData ControlFile_source_after
 
static const charprogname
 
int WalSegSz
 
chardatadir_target = NULL
 
static chardatadir_source = NULL
 
static charconnstr_source = NULL
 
static charrestore_command = NULL
 
static charconfig_file = NULL
 
static bool debug = false
 
bool showprogress = false
 
bool dry_run = false
 
bool do_sync = true
 
static bool restore_wal = false
 
DataDirSyncMethod sync_method = DATA_DIR_SYNC_METHOD_FSYNC
 
TimeLineHistoryEntrytargetHistory
 
int targetNentries
 
uint64 fetch_size
 
uint64 fetch_done
 
static PGconnconn
 
static rewind_sourcesource
 

Function Documentation

◆ checkControlFile()

static void checkControlFile ( ControlFileData ControlFile)
static

Definition at line 1017 of file pg_rewind.c.

1018{
1019 pg_crc32c crc;
1020
1021 /* Calculate CRC */
1024 FIN_CRC32C(crc);
1025
1026 /* And simply compare it */
1027 if (!EQ_CRC32C(crc, ControlFile->crc))
1028 pg_fatal("unexpected control file CRC");
1029}
#define pg_fatal(...)
uint32 pg_crc32c
Definition pg_crc32c.h:38
#define COMP_CRC32C(crc, data, len)
Definition pg_crc32c.h:177
#define EQ_CRC32C(c1, c2)
Definition pg_crc32c.h:42
#define INIT_CRC32C(crc)
Definition pg_crc32c.h:41
#define FIN_CRC32C(crc)
Definition pg_crc32c.h:182
return crc
static int fb(int x)
pg_crc32c crc
Definition pg_control.h:248
static ControlFileData * ControlFile
Definition xlog.c:584

References COMP_CRC32C, ControlFile, ControlFileData::crc, crc, EQ_CRC32C, fb(), FIN_CRC32C, INIT_CRC32C, and pg_fatal.

◆ createBackupLabel()

static void createBackupLabel ( XLogRecPtr  startpoint,
TimeLineID  starttli,
XLogRecPtr  checkpointloc 
)
static

Definition at line 974 of file pg_rewind.c.

975{
978 char strfbuf[128];
980 struct tm *tmp;
981 char buf[1000];
982 int len;
983
984 XLByteToSeg(startpoint, startsegno, WalSegSz);
986
987 /*
988 * Construct backup label file
989 */
990 stamp_time = time(NULL);
991 tmp = localtime(&stamp_time);
992 strftime(strfbuf, sizeof(strfbuf), "%Y-%m-%d %H:%M:%S %Z", tmp);
993
994 len = snprintf(buf, sizeof(buf),
995 "START WAL LOCATION: %X/%08X (file %s)\n"
996 "CHECKPOINT LOCATION: %X/%08X\n"
997 "BACKUP METHOD: pg_rewind\n"
998 "BACKUP FROM: standby\n"
999 "START TIME: %s\n",
1000 /* omit LABEL: line */
1001 LSN_FORMAT_ARGS(startpoint), xlogfilename,
1002 LSN_FORMAT_ARGS(checkpointloc),
1003 strfbuf);
1004 if (len >= sizeof(buf))
1005 pg_fatal("backup label buffer too small"); /* shouldn't happen */
1006
1007 /* TODO: move old file out of the way, if any. */
1008 open_target_file("backup_label", true); /* BACKUP_LABEL_FILE */
1011}
void close_target_file(void)
Definition file_ops.c:78
void open_target_file(const char *path, bool trunc)
Definition file_ops.c:47
void write_target_range(char *buf, off_t begin, size_t size)
Definition file_ops.c:91
static struct pg_tm tm
Definition localtime.c:148
const void size_t len
int WalSegSz
Definition pg_rewind.c:64
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:261
#define MAXFNAMELEN
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
#define LSN_FORMAT_ARGS(lsn)
Definition xlogdefs.h:47
uint64 XLogSegNo
Definition xlogdefs.h:52

References buf, close_target_file(), fb(), len, LSN_FORMAT_ARGS, MAXFNAMELEN, open_target_file(), pg_fatal, snprintf, tm, WalSegSz, write_target_range(), XLByteToSeg, and XLogFileName().

Referenced by perform_rewind().

◆ digestControlFile()

static void digestControlFile ( ControlFileData ControlFile,
const char content,
size_t  size 
)
static

Definition at line 1036 of file pg_rewind.c.

1038{
1039 if (size != PG_CONTROL_FILE_SIZE)
1040 pg_fatal("unexpected control file size %zu, expected %d",
1041 size, PG_CONTROL_FILE_SIZE);
1042
1043 memcpy(ControlFile, content, sizeof(ControlFileData));
1044
1045 /* set and validate WalSegSz */
1047
1049 {
1050 pg_log_error(ngettext("invalid WAL segment size in control file (%d byte)",
1051 "invalid WAL segment size in control file (%d bytes)",
1052 WalSegSz),
1053 WalSegSz);
1054 pg_log_error_detail("The WAL segment size must be a power of two between 1 MB and 1 GB.");
1055 exit(1);
1056 }
1057
1058 /* Additional checks on control file */
1060}
#define ngettext(s, p, n)
Definition c.h:1329
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#define pg_log_error(...)
Definition logging.h:108
#define pg_log_error_detail(...)
Definition logging.h:111
#define PG_CONTROL_FILE_SIZE
Definition pg_control.h:266
static void checkControlFile(void)
uint32 xlog_seg_size
Definition pg_control.h:221
#define IsValidWalSegSize(size)

References checkControlFile(), ControlFile, fb(), IsValidWalSegSize, memcpy(), ngettext, PG_CONTROL_FILE_SIZE, pg_fatal, pg_log_error, pg_log_error_detail, WalSegSz, and ControlFileData::xlog_seg_size.

Referenced by main(), and perform_rewind().

◆ disconnect_atexit()

static void disconnect_atexit ( void  )
static

Definition at line 1213 of file pg_rewind.c.

1214{
1215 if (conn != NULL)
1216 PQfinish(conn);
1217}
void PQfinish(PGconn *conn)
static PGconn * conn
Definition pg_rewind.c:88

References conn, fb(), and PQfinish().

Referenced by main().

◆ ensureCleanShutdown()

static void ensureCleanShutdown ( const char argv0)
static

Definition at line 1142 of file pg_rewind.c.

1143{
1144 int ret;
1145 char exec_path[MAXPGPATH];
1147
1148 /* locate postgres binary */
1149 if ((ret = find_other_exec(argv0, "postgres",
1151 exec_path)) < 0)
1152 {
1153 char full_path[MAXPGPATH];
1154
1155 if (find_my_exec(argv0, full_path) < 0)
1157
1158 if (ret == -1)
1159 pg_fatal("program \"%s\" is needed by %s but was not found in the same directory as \"%s\"",
1160 "postgres", progname, full_path);
1161 else
1162 pg_fatal("program \"%s\" was found by \"%s\" but was not the same version as %s",
1163 "postgres", full_path, progname);
1164 }
1165
1166 pg_log_info("executing \"%s\" for target server to complete crash recovery",
1167 exec_path);
1168
1169 /*
1170 * Skip processing if requested, but only after ensuring presence of
1171 * postgres.
1172 */
1173 if (dry_run)
1174 return;
1175
1176 /*
1177 * Finally run postgres in single-user mode. There is no need to use
1178 * fsync here. This makes the recovery faster, and the target data folder
1179 * is synced at the end anyway.
1180 */
1182
1183 /* path to postgres, properly quoted */
1185
1186 /* add set of options with properly quoted data directory */
1187 appendPQExpBufferStr(postgres_cmd, " --single -F -D ");
1189
1190 /* add custom configuration file only if requested */
1191 if (config_file != NULL)
1192 {
1193 appendPQExpBufferStr(postgres_cmd, " -c config_file=");
1195 }
1196
1197 /* finish with the database name, and a properly quoted redirection */
1198 appendPQExpBufferStr(postgres_cmd, " template1 < ");
1200
1201 fflush(NULL);
1202 if (system(postgres_cmd->data) != 0)
1203 {
1204 pg_log_error("postgres single-user mode in target cluster failed");
1205 pg_log_error_detail("Command was: %s", postgres_cmd->data);
1206 exit(1);
1207 }
1208
1210}
int find_my_exec(const char *argv0, char *retpath)
Definition exec.c:161
int find_other_exec(const char *argv0, const char *target, const char *versionstr, char *retpath)
Definition exec.c:311
#define pg_log_info(...)
Definition logging.h:126
#define MAXPGPATH
static char * argv0
Definition pg_ctl.c:94
static char * exec_path
Definition pg_ctl.c:89
char * datadir_target
Definition pg_rewind.c:67
static char * config_file
Definition pg_rewind.c:71
bool dry_run
Definition pg_rewind.c:75
static const char * progname
Definition pg_rewind.c:63
#define DEVNULL
Definition port.h:162
#define PG_BACKEND_VERSIONSTR
Definition port.h:145
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
PQExpBuffer createPQExpBuffer(void)
Definition pqexpbuffer.c:72
void destroyPQExpBuffer(PQExpBuffer str)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void appendShellString(PQExpBuffer buf, const char *str)

References appendPQExpBufferStr(), appendShellString(), argv0, config_file, createPQExpBuffer(), datadir_target, destroyPQExpBuffer(), DEVNULL, dry_run, exec_path, fb(), find_my_exec(), find_other_exec(), MAXPGPATH, PG_BACKEND_VERSIONSTR, pg_fatal, pg_log_error, pg_log_error_detail, pg_log_info, progname, and strlcpy().

Referenced by main().

◆ findCommonAncestorTimeline()

static void findCommonAncestorTimeline ( TimeLineHistoryEntry a_history,
int  a_nentries,
TimeLineHistoryEntry b_history,
int  b_nentries,
XLogRecPtr recptr,
int tliIndex 
)
static

Definition at line 932 of file pg_rewind.c.

935{
936 int i,
937 n;
938
939 /*
940 * Trace the history forward, until we hit the timeline diverge. It may
941 * still be possible that the source and target nodes used the same
942 * timeline number in their history but with different start position
943 * depending on the history files that each node has fetched in previous
944 * recovery processes. Hence check the start position of the new timeline
945 * as well and move down by one extra timeline entry if they do not match.
946 */
948 for (i = 0; i < n; i++)
949 {
950 if (a_history[i].tli != b_history[i].tli ||
951 a_history[i].begin != b_history[i].begin)
952 break;
953 }
954
955 if (i > 0)
956 {
957 i--;
958 *recptr = MinXLogRecPtr(a_history[i].end, b_history[i].end);
959 *tliIndex = i;
960 return;
961 }
962 else
963 {
964 pg_fatal("could not find common ancestor of the source and target cluster's timelines");
965 }
966}
#define Min(x, y)
Definition c.h:1150
int i
Definition isn.c:77
static XLogRecPtr MinXLogRecPtr(XLogRecPtr a, XLogRecPtr b)
Definition pg_rewind.c:855

References fb(), i, Min, MinXLogRecPtr(), and pg_fatal.

Referenced by main().

◆ getRestoreCommand()

static void getRestoreCommand ( const char argv0)
static

Definition at line 1069 of file pg_rewind.c.

1070{
1071 int rc;
1074
1075 if (!restore_wal)
1076 return;
1077
1078 /* find postgres executable */
1079 rc = find_other_exec(argv0, "postgres",
1082
1083 if (rc < 0)
1084 {
1085 char full_path[MAXPGPATH];
1086
1087 if (find_my_exec(argv0, full_path) < 0)
1089
1090 if (rc == -1)
1091 pg_fatal("program \"%s\" is needed by %s but was not found in the same directory as \"%s\"",
1092 "postgres", progname, full_path);
1093 else
1094 pg_fatal("program \"%s\" was found by \"%s\" but was not the same version as %s",
1095 "postgres", full_path, progname);
1096 }
1097
1098 /*
1099 * Build a command able to retrieve the value of GUC parameter
1100 * restore_command, if set.
1101 */
1103
1104 /* path to postgres, properly quoted */
1106
1107 /* add -D switch, with properly quoted data directory */
1110
1111 /* add custom configuration file only if requested */
1112 if (config_file != NULL)
1113 {
1114 appendPQExpBufferStr(postgres_cmd, " -c config_file=");
1116 }
1117
1118 /* add -C switch, for restore_command */
1119 appendPQExpBufferStr(postgres_cmd, " -C restore_command");
1120
1122 if (restore_command == NULL)
1123 pg_fatal("could not read \"restore_command\" from target cluster");
1124
1126
1127 if (strcmp(restore_command, "") == 0)
1128 pg_fatal("\"restore_command\" is not set in the target cluster");
1129
1130 pg_log_debug("using for rewind \"restore_command = \'%s\'\"",
1132
1134}
char * pipe_read_line(char *cmd)
Definition exec.c:353
#define pg_log_debug(...)
Definition logging.h:135
static char * restore_command
Definition pg_rewind.c:70
static bool restore_wal
Definition pg_rewind.c:77
int pg_strip_crlf(char *str)
Definition string.c:154

References appendPQExpBufferStr(), appendShellString(), argv0, config_file, createPQExpBuffer(), datadir_target, destroyPQExpBuffer(), fb(), find_my_exec(), find_other_exec(), MAXPGPATH, PG_BACKEND_VERSIONSTR, pg_fatal, pg_log_debug, pg_strip_crlf(), pipe_read_line(), progname, restore_command, restore_wal, and strlcpy().

Referenced by main().

◆ getTimelineHistory()

static TimeLineHistoryEntry * getTimelineHistory ( TimeLineID  tli,
bool  is_source,
int nentries 
)
static

Definition at line 869 of file pg_rewind.c.

870{
872
873 /*
874 * Timeline 1 does not have a history file, so there is no need to check
875 * and fake an entry with infinite start and end positions.
876 */
877 if (tli == 1)
878 {
880 history->tli = tli;
881 history->begin = history->end = InvalidXLogRecPtr;
882 *nentries = 1;
883 }
884 else
885 {
886 char path[MAXPGPATH];
887 char *histfile;
888
889 TLHistoryFilePath(path, tli);
890
891 /* Get history file from appropriate source */
892 if (is_source)
894 else
896
899 }
900
901 /* In debugging mode, print what we read */
902 if (debug)
903 {
904 int i;
905
906 if (is_source)
907 pg_log_debug("Source timeline history:");
908 else
909 pg_log_debug("Target timeline history:");
910
911 for (i = 0; i < *nentries; i++)
912 {
914
915 entry = &history[i];
916 pg_log_debug("%u: %X/%08X - %X/%08X", entry->tli,
917 LSN_FORMAT_ARGS(entry->begin),
918 LSN_FORMAT_ARGS(entry->end));
919 }
920 }
921
922 return history;
923}
void pg_free(void *ptr)
#define pg_malloc_object(type)
Definition fe_memutils.h:60
char * slurpFile(const char *datadir, const char *path, size_t *filesize)
Definition file_ops.c:337
static bool debug
Definition pg_rewind.c:73
static rewind_source * source
Definition pg_rewind.c:89
TimeLineHistoryEntry * rewind_parseTimeLineHistory(char *buffer, TimeLineID targetTLI, int *nentries)
Definition timeline.c:28
XLogRecPtr begin
Definition timeline.h:28
char *(* fetch_file)(struct rewind_source *, const char *path, size_t *filesize)
static void TLHistoryFilePath(char *path, TimeLineID tli)
#define InvalidXLogRecPtr
Definition xlogdefs.h:28

References TimeLineHistoryEntry::begin, datadir_target, debug, TimeLineHistoryEntry::end, fb(), rewind_source::fetch_file, i, InvalidXLogRecPtr, LSN_FORMAT_ARGS, MAXPGPATH, pg_free(), pg_log_debug, pg_malloc_object, rewind_parseTimeLineHistory(), slurpFile(), source, TLHistoryFilePath(), and TimeLineHistoryEntry::tli.

Referenced by main().

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 121 of file pg_rewind.c.

122{
123 static struct option long_options[] = {
124 {"help", no_argument, NULL, '?'},
125 {"target-pgdata", required_argument, NULL, 'D'},
126 {"write-recovery-conf", no_argument, NULL, 'R'},
127 {"source-pgdata", required_argument, NULL, 1},
128 {"source-server", required_argument, NULL, 2},
129 {"no-ensure-shutdown", no_argument, NULL, 4},
130 {"config-file", required_argument, NULL, 5},
131 {"version", no_argument, NULL, 'V'},
132 {"restore-target-wal", no_argument, NULL, 'c'},
133 {"dry-run", no_argument, NULL, 'n'},
134 {"no-sync", no_argument, NULL, 'N'},
135 {"progress", no_argument, NULL, 'P'},
136 {"debug", no_argument, NULL, 3},
137 {"sync-method", required_argument, NULL, 6},
138 {NULL, 0, NULL, 0}
139 };
140 int option_index;
141 int c;
151 size_t size;
152 char *buffer;
153 bool no_ensure_shutdown = false;
154 bool rewind_needed;
155 bool writerecoveryconf = false;
157
158 pg_logging_init(argv[0]);
159 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_rewind"));
160 progname = get_progname(argv[0]);
161
162 /* Process command-line arguments */
163 if (argc > 1)
164 {
165 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
166 {
168 exit(0);
169 }
170 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
171 {
172 puts("pg_rewind (PostgreSQL) " PG_VERSION);
173 exit(0);
174 }
175 }
176
177 while ((c = getopt_long(argc, argv, "cD:nNPR", long_options, &option_index)) != -1)
178 {
179 switch (c)
180 {
181 case 'c':
182 restore_wal = true;
183 break;
184
185 case 'P':
186 showprogress = true;
187 break;
188
189 case 'n':
190 dry_run = true;
191 break;
192
193 case 'N':
194 do_sync = false;
195 break;
196
197 case 'R':
198 writerecoveryconf = true;
199 break;
200
201 case 3:
202 debug = true;
204 break;
205
206 case 'D': /* -D or --target-pgdata */
208 break;
209
210 case 1: /* --source-pgdata */
212 break;
213
214 case 2: /* --source-server */
216 break;
217
218 case 4:
219 no_ensure_shutdown = true;
220 break;
221
222 case 5:
224 break;
225
226 case 6:
228 exit(1);
229 break;
230
231 default:
232 /* getopt_long already emitted a complaint */
233 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
234 exit(1);
235 }
236 }
237
239 {
240 pg_log_error("no source specified (--source-pgdata or --source-server)");
241 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
242 exit(1);
243 }
244
246 {
247 pg_log_error("only one of --source-pgdata or --source-server can be specified");
248 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
249 exit(1);
250 }
251
252 if (datadir_target == NULL)
253 {
254 pg_log_error("no target data directory specified (--target-pgdata)");
255 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
256 exit(1);
257 }
258
260 {
261 pg_log_error("no source server information (--source-server) specified for --write-recovery-conf");
262 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
263 exit(1);
264 }
265
266 if (optind < argc)
267 {
268 pg_log_error("too many command-line arguments (first is \"%s\")",
269 argv[optind]);
270 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
271 exit(1);
272 }
273
274 /*
275 * Don't allow pg_rewind to be run as root, to avoid overwriting the
276 * ownership of files in the data directory. We need only check for root
277 * -- any other user won't have sufficient permissions to modify files in
278 * the data directory.
279 */
280#ifndef WIN32
281 if (geteuid() == 0)
282 {
283 pg_log_error("cannot be executed by \"root\"");
284 pg_log_error_hint("You must run %s as the PostgreSQL superuser.",
285 progname);
286 exit(1);
287 }
288#endif
289
291
292 /* Set mask based on PGDATA permissions */
294 pg_fatal("could not read permissions of directory \"%s\": %m",
296
298
299 getRestoreCommand(argv[0]);
300
302
303 /* Ok, we have all the options and we're ready to start. */
304 if (dry_run)
305 {
306 pg_log_info("executing in dry-run mode");
307 pg_log_info_detail("The target directory will not be modified.");
308 }
309
310 /* First, connect to remote server. */
311 if (connstr_source)
312 {
314
317
318 if (showprogress)
319 pg_log_info("connected to server");
320
322 }
323 else
325
326 /*
327 * Check the status of the target instance.
328 *
329 * If the target instance was not cleanly shut down, start and stop the
330 * target cluster once in single-user mode to enforce recovery to finish,
331 * ensuring that the cluster can be used by pg_rewind. Note that if
332 * no_ensure_shutdown is specified, pg_rewind ignores this step, and users
333 * need to make sure by themselves that the target cluster is in a clean
334 * state.
335 */
338 pg_free(buffer);
339
340 if (!no_ensure_shutdown &&
343 {
344 ensureCleanShutdown(argv[0]);
345
348 pg_free(buffer);
349 }
350
351 buffer = source->fetch_file(source, XLOG_CONTROL_FILE, &size);
353 pg_free(buffer);
354
355 sanityChecks();
356
357 /*
358 * Usually, the TLI can be found in the latest checkpoint record. But if
359 * the source server is just being promoted (or it's a standby that's
360 * following a primary that's just being promoted), and the checkpoint
361 * requested by the promotion hasn't completed yet, the latest timeline is
362 * in minRecoveryPoint. So we check which is later, the TLI of the
363 * minRecoveryPoint or the latest checkpoint.
364 */
367
368 /* Similarly for the target. */
371
372 /*
373 * Find the common ancestor timeline between the clusters.
374 *
375 * If both clusters are already on the same timeline, there's nothing to
376 * do.
377 */
378 if (target_tli == source_tli)
379 {
380 pg_log_info("source and target cluster are on the same timeline");
381 rewind_needed = false;
383 }
384 else
385 {
388 int sourceNentries;
389
390 /*
391 * Retrieve timelines for both source and target, and find the point
392 * where they diverged.
393 */
396
400
401 pg_log_info("servers diverged at WAL location %X/%08X on timeline %u",
404
405 /*
406 * Convert the divergence LSN to a segment number, that will be used
407 * to decide how WAL segments should be processed.
408 */
410
411 /*
412 * Don't need the source history anymore. The target history is still
413 * needed by the routines in parsexlog.c, when we read the target WAL.
414 */
416
417
418 /*
419 * Determine the end-of-WAL on the target.
420 *
421 * The WAL ends at the last shutdown checkpoint, or at
422 * minRecoveryPoint if it was a standby. (If we supported rewinding a
423 * server that was not shut down cleanly, we would need to replay
424 * until we reach the first invalid record, like crash recovery does.)
425 */
426
427 /* read the checkpoint record on the target to see where it ends. */
430 targetNentries - 1,
432
434 {
436 }
437 else
438 {
440 }
441
442 /*
443 * Check for the possibility that the target is in fact a direct
444 * ancestor of the source. In that case, there is no divergent history
445 * in the target that needs rewinding.
446 */
448 {
449 rewind_needed = true;
450 }
451 else
452 {
453 /* the last common checkpoint record must be part of target WAL */
455
456 rewind_needed = false;
457 }
458 }
459
460 if (!rewind_needed)
461 {
462 pg_log_info("no rewind required");
467 exit(0);
468 }
469
470 /* Initialize hashtable that tracks WAL files protected from removal */
471 keepwal_init();
472
475 pg_log_info("rewinding from last common checkpoint at %X/%08X on timeline %u",
477
478 /* Initialize the hash table to track the status of each file */
480
481 /*
482 * Collect information about all files in the both data directories.
483 */
484 if (showprogress)
485 pg_log_info("reading source file list");
487
488 if (showprogress)
489 pg_log_info("reading target file list");
491
492 /*
493 * Read the target WAL from last checkpoint before the point of fork, to
494 * extract all the pages that were modified on the target cluster after
495 * the fork.
496 */
497 if (showprogress)
498 pg_log_info("reading WAL in target");
501
502 /*
503 * We have collected all information we need from both systems. Decide
504 * what to do with each file.
505 */
507 if (showprogress)
509
510 /* this is too verbose even for verbose mode */
511 if (debug)
513
514 /*
515 * Ok, we're ready to start copying things over.
516 */
517 if (showprogress)
518 {
519 pg_log_info("need to copy %" PRIu64 " MB (total source directory size is %" PRIu64 " MB)",
520 filemap->fetch_size / (1024 * 1024),
521 filemap->total_size / (1024 * 1024));
522
523 fetch_size = filemap->fetch_size;
524 fetch_done = 0;
525 }
526
527 /*
528 * We have now collected all the information we need from both systems,
529 * and we are ready to start modifying the target directory.
530 *
531 * This is the point of no return. Once we start copying things, there is
532 * no turning back!
533 */
535
536 if (showprogress)
537 pg_log_info("syncing target data directory");
539
540 /* Also update the standby configuration, if requested. */
545
546 /* don't need the source connection anymore */
548 if (conn)
549 {
550 PQfinish(conn);
551 conn = NULL;
552 }
553
554 pg_log_info("Done!");
555
556 return 0;
557}
#define Max(x, y)
Definition c.h:1144
#define Assert(condition)
Definition c.h:1002
#define PG_TEXTDOMAIN(domain)
Definition c.h:1362
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition exec.c:430
PGconn * PQconnectdb(const char *conninfo)
Definition fe-connect.c:830
ConnStatusType PQstatus(const PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
char * pg_strdup(const char *in)
Definition fe_memutils.c:91
void traverse_datadir(const char *datadir, process_file_callback_t callback)
Definition file_ops.c:385
void sync_target_dir(void)
Definition file_ops.c:317
int pg_mode_mask
Definition file_perm.c:25
bool GetDataDirectoryCreatePerm(const char *dataDir)
void filehash_init(void)
Definition filemap.c:197
void process_source_file(const char *path, file_type_t type, size_t size, const char *link_target)
Definition filemap.c:280
void print_filemap(filemap_t *filemap)
Definition filemap.c:541
void keepwal_init(void)
Definition filemap.c:243
void process_target_file(const char *path, file_type_t type, size_t size, const char *link_target)
Definition filemap.c:316
void calculate_totals(filemap_t *filemap)
Definition filemap.c:500
filemap_t * decide_file_actions(XLogSegNo last_common_segno)
Definition filemap.c:924
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition getopt_long.c:60
#define no_argument
Definition getopt_long.h:25
#define required_argument
Definition getopt_long.h:26
@ CONNECTION_BAD
Definition libpq-fe.h:91
rewind_source * init_libpq_source(PGconn *conn)
rewind_source * init_local_source(const char *datadir)
void pg_logging_increase_verbosity(void)
Definition logging.c:187
void pg_logging_init(const char *argv0)
Definition logging.c:85
#define pg_log_info_detail(...)
Definition logging.h:129
#define pg_log_error_hint(...)
Definition logging.h:114
void pfree(void *pointer)
Definition mcxt.c:1619
bool parse_sync_method(const char *optarg, DataDirSyncMethod *sync_method)
void extractPageMap(const char *datadir, XLogRecPtr startpoint, int tliIndex, XLogRecPtr endpoint, const char *restoreCommand)
Definition parsexlog.c:66
void findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex, XLogRecPtr *lastchkptrec, TimeLineID *lastchkpttli, XLogRecPtr *lastchkptredo, const char *restoreCommand)
Definition parsexlog.c:168
XLogRecPtr readOneRecord(const char *datadir, XLogRecPtr ptr, int tliIndex, const char *restoreCommand)
Definition parsexlog.c:124
static void usage(void)
static bool writerecoveryconf
@ DB_SHUTDOWNED_IN_RECOVERY
Definition pg_control.h:101
@ DB_SHUTDOWNED
Definition pg_control.h:100
PGDLLIMPORT int optind
Definition getopt.c:47
PGDLLIMPORT char * optarg
Definition getopt.c:49
static ControlFileData ControlFile_source
Definition pg_rewind.c:60
static void sanityChecks(void)
Definition pg_rewind.c:746
static char * datadir_source
Definition pg_rewind.c:68
static void findCommonAncestorTimeline(TimeLineHistoryEntry *a_history, int a_nentries, TimeLineHistoryEntry *b_history, int b_nentries, XLogRecPtr *recptr, int *tliIndex)
Definition pg_rewind.c:932
static void ensureCleanShutdown(const char *argv0)
Definition pg_rewind.c:1142
TimeLineHistoryEntry * targetHistory
Definition pg_rewind.c:81
static ControlFileData ControlFile_target
Definition pg_rewind.c:59
static TimeLineHistoryEntry * getTimelineHistory(TimeLineID tli, bool is_source, int *nentries)
Definition pg_rewind.c:869
static void digestControlFile(ControlFileData *ControlFile, const char *content, size_t size)
Definition pg_rewind.c:1036
static char * connstr_source
Definition pg_rewind.c:69
static void getRestoreCommand(const char *argv0)
Definition pg_rewind.c:1069
bool do_sync
Definition pg_rewind.c:76
uint64 fetch_done
Definition pg_rewind.c:86
int targetNentries
Definition pg_rewind.c:82
uint64 fetch_size
Definition pg_rewind.c:85
DataDirSyncMethod sync_method
Definition pg_rewind.c:78
bool showprogress
Definition pg_rewind.c:74
static void perform_rewind(filemap_t *filemap, rewind_source *source, XLogRecPtr chkptrec, TimeLineID chkpttli, XLogRecPtr chkptredo)
Definition pg_rewind.c:566
static void disconnect_atexit(void)
Definition pg_rewind.c:1213
const char * get_progname(const char *argv0)
Definition path.c:669
char * c
void WriteRecoveryConfig(PGconn *pgconn, const char *target_dir, PQExpBuffer contents)
PQExpBuffer GenerateRecoveryConfig(PGconn *pgconn, const char *replication_slot, char *dbname)
char * GetDbnameFromConnectionOptions(const char *connstr)
void get_restricted_token(void)
TimeLineID ThisTimeLineID
Definition pg_control.h:39
CheckPoint checkPointCopy
Definition pg_control.h:143
XLogRecPtr minRecoveryPoint
Definition pg_control.h:176
XLogRecPtr checkPoint
Definition pg_control.h:141
TimeLineID minRecoveryPointTLI
Definition pg_control.h:177
void(* traverse_files)(struct rewind_source *, process_file_callback_t callback)
void(* destroy)(struct rewind_source *)
#define XLOG_CONTROL_FILE
uint64 XLogRecPtr
Definition xlogdefs.h:21
uint32 TimeLineID
Definition xlogdefs.h:63

References Assert, calculate_totals(), ControlFileData::checkPoint, ControlFileData::checkPointCopy, config_file, conn, CONNECTION_BAD, connstr_source, ControlFile_source, ControlFile_target, datadir_source, datadir_target, DB_SHUTDOWNED, DB_SHUTDOWNED_IN_RECOVERY, debug, decide_file_actions(), rewind_source::destroy, digestControlFile(), disconnect_atexit(), do_sync, dry_run, ensureCleanShutdown(), extractPageMap(), fb(), fetch_done, rewind_source::fetch_file, fetch_size, filehash_init(), findCommonAncestorTimeline(), findLastCheckpoint(), GenerateRecoveryConfig(), get_progname(), get_restricted_token(), GetDataDirectoryCreatePerm(), GetDbnameFromConnectionOptions(), getopt_long(), getRestoreCommand(), getTimelineHistory(), init_libpq_source(), init_local_source(), InvalidXLogRecPtr, keepwal_init(), LSN_FORMAT_ARGS, Max, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, no_argument, optarg, optind, parse_sync_method(), perform_rewind(), pfree(), pg_fatal, pg_free(), pg_log_error, pg_log_error_hint, pg_log_info, pg_log_info_detail, pg_logging_increase_verbosity(), pg_logging_init(), pg_mode_mask, pg_strdup(), PG_TEXTDOMAIN, PQconnectdb(), PQerrorMessage(), PQfinish(), PQstatus(), print_filemap(), process_source_file(), process_target_file(), progname, readOneRecord(), required_argument, restore_command, restore_wal, sanityChecks(), set_pglocale_pgservice(), showprogress, slurpFile(), source, ControlFileData::state, sync_method, sync_target_dir(), targetHistory, targetNentries, CheckPoint::ThisTimeLineID, traverse_datadir(), rewind_source::traverse_files, usage(), writerecoveryconf, WriteRecoveryConfig(), XLByteToSeg, XLOG_CONTROL_FILE, and ControlFileData::xlog_seg_size.

◆ MinXLogRecPtr()

static XLogRecPtr MinXLogRecPtr ( XLogRecPtr  a,
XLogRecPtr  b 
)
static

Definition at line 855 of file pg_rewind.c.

856{
857 if (!XLogRecPtrIsValid(a))
858 return b;
859 else if (!XLogRecPtrIsValid(b))
860 return a;
861 else
862 return Min(a, b);
863}
int b
Definition isn.c:74
int a
Definition isn.c:73
#define XLogRecPtrIsValid(r)
Definition xlogdefs.h:29

References a, b, Min, and XLogRecPtrIsValid.

Referenced by findCommonAncestorTimeline().

◆ perform_rewind()

static void perform_rewind ( filemap_t filemap,
rewind_source source,
XLogRecPtr  chkptrec,
TimeLineID  chkpttli,
XLogRecPtr  chkptredo 
)
static

Definition at line 566 of file pg_rewind.c.

570{
574 size_t size;
575 char *buffer;
576
577 /*
578 * Execute the actions in the file map, fetching data from the source
579 * system as needed.
580 */
581 for (int i = 0; i < filemap->nentries; i++)
582 {
583 file_entry_t *entry = filemap->entries[i];
584
585 /*
586 * If this is a relation file, copy the modified blocks.
587 *
588 * This is in addition to any other changes.
589 */
591 {
593 BlockNumber blkno;
594 off_t offset;
595
597 while (datapagemap_next(iter, &blkno))
598 {
599 offset = blkno * BLCKSZ;
600 source->queue_fetch_range(source, entry->path, offset, BLCKSZ);
601 }
602 pg_free(iter);
603 }
604
605 switch (entry->action)
606 {
607 case FILE_ACTION_NONE:
608 /* nothing else to do */
609 break;
610
611 case FILE_ACTION_COPY:
613 break;
614
616 truncate_target_file(entry->path, entry->source_size);
617 break;
618
621 entry->target_size,
622 entry->source_size - entry->target_size);
623 break;
624
626 remove_target(entry);
627 break;
628
630 create_target(entry);
631 break;
632
634 pg_fatal("no action decided for file \"%s\"", entry->path);
635 break;
636 }
637 }
638
639 /* Complete any remaining range-fetches that we queued up above. */
641
643
644 progress_report(true);
645
646 /*
647 * Fetch the control file from the source last. This ensures that the
648 * minRecoveryPoint is up-to-date.
649 */
650 buffer = source->fetch_file(source, XLOG_CONTROL_FILE, &size);
652 pg_free(buffer);
653
654 /*
655 * Sanity check: If the source is a local system, the control file should
656 * not have changed since we started.
657 *
658 * XXX: We assume it hasn't been modified, but actually, what could go
659 * wrong? The logic handles a libpq source that's modified concurrently,
660 * why not a local datadir?
661 */
662 if (datadir_source &&
664 sizeof(ControlFileData)) != 0)
665 {
666 pg_fatal("source system was modified while pg_rewind was running");
667 }
668
669 if (showprogress)
670 pg_log_info("creating backup label and updating control file");
671
672 /*
673 * Create a backup label file, to tell the target where to begin the WAL
674 * replay. Normally, from the last common checkpoint between the source
675 * and the target. But if the source is a standby server, it's possible
676 * that the last common checkpoint is *after* the standby's restartpoint.
677 * That implies that the source server has applied the checkpoint record,
678 * but hasn't performed a corresponding restartpoint yet. Make sure we
679 * start at the restartpoint's redo point in that case.
680 *
681 * Use the old version of the source's control file for this. The server
682 * might have finished the restartpoint after we started copying files,
683 * but we must begin from the redo point at the time that started copying.
684 */
686 {
690 }
692
693 /*
694 * Update control file of target, to tell the target how far it must
695 * replay the WAL (minRecoveryPoint).
696 */
697 if (connstr_source)
698 {
699 /*
700 * The source is a live server. Like in an online backup, it's
701 * important that we recover all the WAL that was generated while we
702 * were copying files.
703 */
705 {
706 /*
707 * Source is a standby server. We must replay to its
708 * minRecoveryPoint.
709 */
712 }
713 else
714 {
715 /*
716 * Source is a production, non-standby, server. We must replay to
717 * the last WAL insert location.
718 */
720 pg_fatal("source system was in unexpected state at end of rewind");
721
725 }
726 }
727 else
728 {
729 /*
730 * Source is a local data directory. It should've shut down cleanly,
731 * and we must replay to the latest shutdown checkpoint.
732 */
735 }
736
738 ControlFile_new.minRecoveryPoint = endrec;
739 ControlFile_new.minRecoveryPointTLI = endtli;
741 if (!dry_run)
743}
uint32 BlockNumber
Definition block.h:31
void update_controlfile(const char *DataDir, ControlFileData *ControlFile, bool do_sync)
bool datapagemap_next(datapagemap_iterator_t *iter, BlockNumber *blkno)
Definition datapagemap.c:87
datapagemap_iterator_t * datapagemap_iterate(datapagemap_t *map)
Definition datapagemap.c:75
void truncate_target_file(const char *path, off_t newsize)
Definition file_ops.c:212
void remove_target(file_entry_t *entry)
Definition file_ops.c:133
void create_target(file_entry_t *entry)
Definition file_ops.c:159
@ FILE_ACTION_REMOVE
Definition filemap.h:28
@ FILE_ACTION_COPY
Definition filemap.h:22
@ FILE_ACTION_NONE
Definition filemap.h:25
@ FILE_ACTION_COPY_TAIL
Definition filemap.h:23
@ FILE_ACTION_UNDECIDED
Definition filemap.h:19
@ FILE_ACTION_TRUNCATE
Definition filemap.h:27
@ FILE_ACTION_CREATE
Definition filemap.h:21
@ DB_IN_PRODUCTION
Definition pg_control.h:105
@ DB_IN_ARCHIVE_RECOVERY
Definition pg_control.h:104
static void createBackupLabel(XLogRecPtr startpoint, TimeLineID starttli, XLogRecPtr checkpointloc)
Definition pg_rewind.c:974
static ControlFileData ControlFile_source_after
Definition pg_rewind.c:61
void progress_report(bool finished)
Definition pg_rewind.c:804
XLogRecPtr redo
Definition pg_control.h:37
Definition filemap.h:58
datapagemap_t target_pages_to_overwrite
Definition filemap.h:76
const char * path
Definition filemap.h:61
size_t source_size
Definition filemap.h:83
size_t target_size
Definition filemap.h:69
file_action_t action
Definition filemap.h:89
void(* queue_fetch_file)(struct rewind_source *, const char *path, size_t len)
void(* finish_fetch)(struct rewind_source *)
XLogRecPtr(* get_current_wal_insert_lsn)(struct rewind_source *)
void(* queue_fetch_range)(struct rewind_source *, const char *path, off_t offset, size_t len)

References file_entry_t::action, datapagemap::bitmapsize, ControlFileData::checkPoint, ControlFileData::checkPointCopy, close_target_file(), connstr_source, ControlFile_source, ControlFile_source_after, create_target(), createBackupLabel(), datadir_source, datadir_target, datapagemap_iterate(), datapagemap_next(), DB_IN_ARCHIVE_RECOVERY, DB_IN_PRODUCTION, digestControlFile(), do_sync, dry_run, fb(), rewind_source::fetch_file, FILE_ACTION_COPY, FILE_ACTION_COPY_TAIL, FILE_ACTION_CREATE, FILE_ACTION_NONE, FILE_ACTION_REMOVE, FILE_ACTION_TRUNCATE, FILE_ACTION_UNDECIDED, rewind_source::finish_fetch, rewind_source::get_current_wal_insert_lsn, i, Max, memcpy(), ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, file_entry_t::path, pg_fatal, pg_free(), pg_log_info, progress_report(), rewind_source::queue_fetch_file, rewind_source::queue_fetch_range, CheckPoint::redo, remove_target(), showprogress, source, file_entry_t::source_size, ControlFileData::state, file_entry_t::target_pages_to_overwrite, file_entry_t::target_size, CheckPoint::ThisTimeLineID, truncate_target_file(), update_controlfile(), and XLOG_CONTROL_FILE.

Referenced by main().

◆ progress_report()

static void progress_report ( bool  finished)

Definition at line 804 of file pg_rewind.c.

805{
807 int percent;
808 char fetch_done_str[32];
809 char fetch_size_str[32];
811
812 if (!showprogress)
813 return;
814
815 now = time(NULL);
816 if (now == last_progress_report && !finished)
817 return; /* Max once per second */
818
820 percent = fetch_size ? (int) ((fetch_done) * 100 / fetch_size) : 0;
821
822 /*
823 * Avoid overflowing past 100% or the full size. This may make the total
824 * size number change as we approach the end of the backup (the estimate
825 * will always be wrong if WAL is included), but that's better than having
826 * the done column be bigger than the total.
827 */
828 if (percent > 100)
829 percent = 100;
832
834 fetch_done / 1024);
836 fetch_size / 1024);
837
838 fprintf(stderr, _("%*s/%s kB (%d%%) copied"),
840 percent);
841
842 /*
843 * Stay on the same line if reporting to a terminal and we're not done
844 * yet.
845 */
846 fputc((!finished && isatty(fileno(stderr))) ? '\r' : '\n', stderr);
847}
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1613
#define UINT64_FORMAT
Definition c.h:694
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
#define _(x)
Definition elog.c:96
static pg_time_t last_progress_report
Definition pg_amcheck.c:147
int64 pg_time_t
Definition pgtime.h:23

References _, fb(), fetch_done, fetch_size, fprintf, last_progress_report, now(), showprogress, snprintf, and UINT64_FORMAT.

Referenced by perform_rewind().

◆ sanityChecks()

static void sanityChecks ( void  )
static

Definition at line 746 of file pg_rewind.c.

747{
748 /* TODO Check that there's no backup_label in either cluster */
749
750 /* Check system_identifier match */
752 pg_fatal("source and target clusters are from different systems");
753
754 /* check version */
759 {
760 pg_fatal("clusters are not compatible with this version of pg_rewind");
761 }
762
763 /*
764 * Target cluster need to use checksums or hint bit wal-logging, this to
765 * prevent from data corruption that could occur because of hint bits.
766 */
769 {
770 pg_fatal("target server needs to use either data checksums or \"wal_log_hints = on\"");
771 }
772
773 /*
774 * Target cluster better not be running. This doesn't guard against
775 * someone starting the cluster concurrently. Also, this is probably more
776 * strict than necessary; it's OK if the target node was not shut down
777 * cleanly, as long as it isn't running at the moment.
778 */
781 pg_fatal("target server must be shut down cleanly");
782
783 /*
784 * When the source is a data directory, also require that the source
785 * server is shut down. There isn't any very strong reason for this
786 * limitation, but better safe than sorry.
787 */
788 if (datadir_source &&
791 pg_fatal("source data directory must be shut down cleanly");
792}
#define CATALOG_VERSION_NO
Definition catversion.h:60
@ PG_DATA_CHECKSUM_VERSION
Definition checksum.h:29
#define PG_CONTROL_VERSION
Definition pg_control.h:25
uint32 pg_control_version
Definition pg_control.h:133
uint32 data_checksum_version
Definition pg_control.h:232
uint64 system_identifier
Definition pg_control.h:118
uint32 catalog_version_no
Definition pg_control.h:134

References CATALOG_VERSION_NO, ControlFileData::catalog_version_no, ControlFile_source, ControlFile_target, ControlFileData::data_checksum_version, datadir_source, DB_SHUTDOWNED, DB_SHUTDOWNED_IN_RECOVERY, PG_CONTROL_VERSION, ControlFileData::pg_control_version, PG_DATA_CHECKSUM_VERSION, pg_fatal, ControlFileData::state, ControlFileData::system_identifier, and ControlFileData::wal_log_hints.

Referenced by main().

◆ usage()

static void usage ( const char progname)
static

Definition at line 92 of file pg_rewind.c.

93{
94 printf(_("%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n\n"), progname);
95 printf(_("Usage:\n %s [OPTION]...\n\n"), progname);
96 printf(_("Options:\n"));
97 printf(_(" -c, --restore-target-wal use \"restore_command\" in target configuration to\n"
98 " retrieve WAL files from archives\n"));
99 printf(_(" -D, --target-pgdata=DIRECTORY existing data directory to modify\n"));
100 printf(_(" --source-pgdata=DIRECTORY source data directory to synchronize with\n"));
101 printf(_(" --source-server=CONNSTR source server to synchronize with\n"));
102 printf(_(" -n, --dry-run stop before modifying anything\n"));
103 printf(_(" -N, --no-sync do not wait for changes to be written\n"
104 " safely to disk\n"));
105 printf(_(" -P, --progress write progress messages\n"));
106 printf(_(" -R, --write-recovery-conf write configuration for replication\n"
107 " (requires --source-server)\n"));
108 printf(_(" --config-file=FILENAME use specified main server configuration\n"
109 " file when running target cluster\n"));
110 printf(_(" --debug write a lot of debug messages\n"));
111 printf(_(" --no-ensure-shutdown do not automatically fix unclean shutdown\n"));
112 printf(_(" --sync-method=METHOD set method for syncing files to disk\n"));
113 printf(_(" -V, --version output version information, then exit\n"));
114 printf(_(" -?, --help show this help, then exit\n"));
115 printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
116 printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
117}
#define printf(...)
Definition port.h:267

References _, fb(), printf, and progname.

Variable Documentation

◆ config_file

char* config_file = NULL
static

◆ conn

PGconn* conn
static

Definition at line 88 of file pg_rewind.c.

Referenced by disconnect_atexit(), and main().

◆ connstr_source

char* connstr_source = NULL
static

Definition at line 69 of file pg_rewind.c.

Referenced by main(), and perform_rewind().

◆ ControlFile_source

ControlFileData ControlFile_source
static

Definition at line 60 of file pg_rewind.c.

Referenced by main(), perform_rewind(), and sanityChecks().

◆ ControlFile_source_after

ControlFileData ControlFile_source_after
static

Definition at line 61 of file pg_rewind.c.

Referenced by perform_rewind().

◆ ControlFile_target

ControlFileData ControlFile_target
static

Definition at line 59 of file pg_rewind.c.

Referenced by main(), and sanityChecks().

◆ datadir_source

char* datadir_source = NULL
static

Definition at line 68 of file pg_rewind.c.

Referenced by main(), perform_rewind(), and sanityChecks().

◆ datadir_target

◆ debug

bool debug = false
static

Definition at line 73 of file pg_rewind.c.

Referenced by getTimelineHistory(), and main().

◆ do_sync

bool do_sync = true

Definition at line 76 of file pg_rewind.c.

Referenced by main(), and perform_rewind().

◆ dry_run

bool dry_run = false

Definition at line 75 of file pg_rewind.c.

Referenced by ensureCleanShutdown(), main(), and perform_rewind().

◆ fetch_done

uint64 fetch_done

Definition at line 86 of file pg_rewind.c.

Referenced by main(), progress_report(), and write_target_range().

◆ fetch_size

uint64 fetch_size

Definition at line 85 of file pg_rewind.c.

Referenced by main(), postgresAcquireSampleRowsFunc(), and progress_report().

◆ progname

const char* progname
static

Definition at line 63 of file pg_rewind.c.

Referenced by ensureCleanShutdown(), getRestoreCommand(), main(), and usage().

◆ restore_command

char* restore_command = NULL
static

Definition at line 70 of file pg_rewind.c.

Referenced by getRestoreCommand(), and main().

◆ restore_wal

bool restore_wal = false
static

Definition at line 77 of file pg_rewind.c.

Referenced by getRestoreCommand(), and main().

◆ showprogress

bool showprogress = false

Definition at line 74 of file pg_rewind.c.

Referenced by main(), perform_rewind(), and progress_report().

◆ source

rewind_source* source
static

Definition at line 89 of file pg_rewind.c.

Referenced by append_pathkeys(), appendByteaLiteral(), appendStringLiteral(), ApplySetting(), bpchar(), BufFileAppend(), call_bool_check_hook(), call_enum_check_hook(), call_int_check_hook(), call_real_check_hook(), call_string_check_hook(), check_datestyle(), check_default_table_access_method(), check_default_tablespace(), check_default_text_search_config(), check_locale_messages(), check_random_seed(), check_role(), check_session_authorization(), check_temp_buffers(), check_temp_tablespaces(), check_timezone_abbreviations(), compute_remaining_iovec(), CopyIndexTuple(), expr_is_nonnullable(), expr_scanner_init(), exprLocation(), fmgr_security_definer(), gets_fromFile(), getTimelineHistory(), index_truncate_tuple(), initClosestMatch(), InitializeGUCOptionsFromEnvironment(), interval_support(), libpq_destroy(), libpq_fetch_file(), libpq_finish_fetch(), libpq_get_current_wal_insert_lsn(), libpq_queue_fetch_file(), libpq_queue_fetch_range(), libpq_traverse_files(), local_destroy(), local_fetch_file(), local_queue_fetch_file(), local_queue_fetch_range(), local_traverse_files(), main(), MainLoop(), numeric_support(), packGraph(), parse_and_validate_value(), perform_rewind(), pg_set_timing_clock_source(), pg_utf8_islegal(), pg_utf8_string_len(), pglz_compress(), pglz_decompress(), plsample_func_handler(), plsample_trigger_handler(), PQescapeStringInternal(), process_backslash_command(), ProcessGUCArray(), quote_if_needed(), raw_expression_tree_walker_impl(), reconstruct_from_incremental_file(), selectColorTrigrams(), set_config_option(), set_config_option_ext(), set_config_with_handle(), set_debug_options(), set_plan_disabling_options(), SetConfigOption(), string_to_uuid(), strip_quotes(), syntax_error(), TemporalSimplify(), test_pglz_compress(), test_pglz_decompress(), test_timing(), transform_MERGE_to_join(), translate(), var_is_nonnullable(), varbit_support(), varchar(), varchar_support(), varstr_levenshtein(), XLogCompressBackupBlock(), XLogFileRead(), and XLogFileReadAnyTLI().

◆ sync_method

Definition at line 78 of file pg_rewind.c.

Referenced by main().

◆ targetHistory

TimeLineHistoryEntry* targetHistory

Definition at line 81 of file pg_rewind.c.

Referenced by main(), and SimpleXLogPageRead().

◆ targetNentries

int targetNentries

Definition at line 82 of file pg_rewind.c.

Referenced by main(), and SimpleXLogPageRead().

◆ WalSegSz

int WalSegSz

Definition at line 64 of file pg_rewind.c.

Referenced by createBackupLabel(), and digestControlFile().