PostgreSQL Source Code  git master
pg_standby.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include "pg_getopt.h"
#include "access/xlog_internal.h"
Include dependency graph for pg_standby.c:

Go to the source code of this file.

Macros

#define NoFailover   0
 
#define SmartFailover   1
 
#define FastFailover   2
 
#define RESTORE_COMMAND_COPY   0
 
#define RESTORE_COMMAND_LINK   1
 
#define XLOG_DATA   0
 
#define XLOG_HISTORY   1
 
#define XLOG_BACKUP_LABEL   2
 
#define SET_RESTORE_COMMAND(cmd, arg1, arg2)   snprintf(restoreCommand, MAXPGPATH, cmd " \"%s\" \"%s\"", arg1, arg2)
 

Functions

static bool SetWALFileNameForCleanup (void)
 
static bool SetWALSegSize (void)
 
static void CustomizableInitialize (void)
 
static bool CustomizableNextWALFileReady (void)
 
static void CustomizableCleanupPriorWALFiles (void)
 
static void CheckForExternalTrigger (void)
 
static bool RestoreWALFileForRecovery (void)
 
static void usage (void)
 
static void sighandler (int sig)
 
static void sigquit_handler (int sig)
 
int main (int argc, char **argv)
 

Variables

const char * progname
 
int WalSegSz = -1
 
int sleeptime = 5
 
int waittime = -1
 
int maxwaittime = 0
 
int keepfiles = 0
 
int maxretries = 3
 
bool debug = false
 
bool need_cleanup = false
 
static volatile sig_atomic_t signaled = false
 
char * archiveLocation
 
char * triggerPath
 
char * xlogFilePath
 
char * nextWALFileName
 
char * restartWALFileName
 
char * priorWALFileName
 
char WALFilePath [MAXPGPATH *2]
 
char restoreCommand [MAXPGPATH]
 
char exclusiveCleanupFileName [MAXFNAMELEN]
 
static int Failover = NoFailover
 
int restoreCommandType
 
int nextWALFileType
 
struct stat stat_buf
 

Macro Definition Documentation

◆ FastFailover

#define FastFailover   2

Definition at line 87 of file pg_standby.c.

Referenced by CheckForExternalTrigger(), and main().

◆ NoFailover

#define NoFailover   0

Definition at line 85 of file pg_standby.c.

◆ RESTORE_COMMAND_COPY

#define RESTORE_COMMAND_COPY   0

Definition at line 91 of file pg_standby.c.

Referenced by CustomizableInitialize(), and main().

◆ RESTORE_COMMAND_LINK

#define RESTORE_COMMAND_LINK   1

Definition at line 92 of file pg_standby.c.

Referenced by CustomizableInitialize(), and main().

◆ SET_RESTORE_COMMAND

#define SET_RESTORE_COMMAND (   cmd,
  arg1,
  arg2 
)    snprintf(restoreCommand, MAXPGPATH, cmd " \"%s\" \"%s\"", arg1, arg2)

Definition at line 100 of file pg_standby.c.

Referenced by CustomizableInitialize().

◆ SmartFailover

#define SmartFailover   1

Definition at line 86 of file pg_standby.c.

Referenced by CheckForExternalTrigger(), and main().

◆ XLOG_BACKUP_LABEL

#define XLOG_BACKUP_LABEL   2

Definition at line 97 of file pg_standby.c.

Referenced by CustomizableNextWALFileReady().

◆ XLOG_DATA

#define XLOG_DATA   0

Definition at line 95 of file pg_standby.c.

Referenced by CustomizableCleanupPriorWALFiles(), and CustomizableNextWALFileReady().

◆ XLOG_HISTORY

#define XLOG_HISTORY   1

Definition at line 96 of file pg_standby.c.

Referenced by main().

Function Documentation

◆ CheckForExternalTrigger()

static void CheckForExternalTrigger ( void  )
static

Definition at line 477 of file pg_standby.c.

References buf, close, Failover, FastFailover, fd(), ftruncate, read, SmartFailover, stat, stat_buf, strerror(), and triggerPath.

Referenced by main().

478 {
479  char buf[32];
480  int fd;
481  int len;
482 
483  /*
484  * Look for a trigger file, if that option has been selected
485  *
486  * We use stat() here because triggerPath is always a file rather than
487  * potentially being in an archive
488  */
489  if (!triggerPath || stat(triggerPath, &stat_buf) != 0)
490  return;
491 
492  /*
493  * An empty trigger file performs smart failover. There's a little race
494  * condition here: if the writer of the trigger file has just created the
495  * file, but not yet written anything to it, we'll treat that as smart
496  * shutdown even if the other process was just about to write "fast" to
497  * it. But that's fine: we'll restore one more WAL file, and when we're
498  * invoked next time, we'll see the word "fast" and fail over immediately.
499  */
500  if (stat_buf.st_size == 0)
501  {
503  fprintf(stderr, "trigger file found: smart failover\n");
504  fflush(stderr);
505  return;
506  }
507 
508  if ((fd = open(triggerPath, O_RDWR, 0)) < 0)
509  {
510  fprintf(stderr, "WARNING: could not open \"%s\": %s\n",
511  triggerPath, strerror(errno));
512  fflush(stderr);
513  return;
514  }
515 
516  if ((len = read(fd, buf, sizeof(buf) - 1)) < 0)
517  {
518  fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
519  triggerPath, strerror(errno));
520  fflush(stderr);
521  close(fd);
522  return;
523  }
524  buf[len] = '\0';
525 
526  if (strncmp(buf, "smart", 5) == 0)
527  {
529  fprintf(stderr, "trigger file found: smart failover\n");
530  fflush(stderr);
531  close(fd);
532  return;
533  }
534 
535  if (strncmp(buf, "fast", 4) == 0)
536  {
538 
539  fprintf(stderr, "trigger file found: fast failover\n");
540  fflush(stderr);
541 
542  /*
543  * Turn it into a "smart" trigger by truncating the file. Otherwise if
544  * the server asks us again to restore a segment that was restored
545  * already, we would return "not found" and upset the server.
546  */
547  if (ftruncate(fd, 0) < 0)
548  {
549  fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
550  triggerPath, strerror(errno));
551  fflush(stderr);
552  }
553  close(fd);
554 
555  return;
556  }
557  close(fd);
558 
559  fprintf(stderr, "WARNING: invalid content in \"%s\"\n", triggerPath);
560  fflush(stderr);
561  return;
562 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define SmartFailover
Definition: pg_standby.c:86
struct stat stat_buf
Definition: pg_standby.c:103
static int Failover
Definition: pg_standby.c:89
static char * buf
Definition: pg_test_fsync.c:67
#define FastFailover
Definition: pg_standby.c:87
#define stat(a, b)
Definition: win32_port.h:266
const char * strerror(int errnum)
Definition: strerror.c:19
char * triggerPath
Definition: pg_standby.c:57
#define close(a)
Definition: win32.h:12
#define read(a, b, c)
Definition: win32.h:13
#define ftruncate(a, b)
Definition: win32_port.h:60

◆ CustomizableCleanupPriorWALFiles()

static void CustomizableCleanupPriorWALFiles ( void  )
static

Definition at line 257 of file pg_standby.c.

References archiveLocation, closedir(), dirent::d_name, debug, exclusiveCleanupFileName, IsXLogFileName, nextWALFileType, opendir(), progname, readdir(), snprintf(), strerror(), WALFilePath, and XLOG_DATA.

Referenced by main().

258 {
259  /*
260  * Work out name of prior file from current filename
261  */
262  if (nextWALFileType == XLOG_DATA)
263  {
264  int rc;
265  DIR *xldir;
266  struct dirent *xlde;
267 
268  /*
269  * Assume it's OK to keep failing. The failure situation may change
270  * over time, so we'd rather keep going on the main processing than
271  * fail because we couldn't clean up yet.
272  */
273  if ((xldir = opendir(archiveLocation)) != NULL)
274  {
275  while (errno = 0, (xlde = readdir(xldir)) != NULL)
276  {
277  /*
278  * We ignore the timeline part of the XLOG segment identifiers
279  * in deciding whether a segment is still needed. This
280  * ensures that we won't prematurely remove a segment from a
281  * parent timeline. We could probably be a little more
282  * proactive about removing segments of non-parent timelines,
283  * but that would be a whole lot more complicated.
284  *
285  * We use the alphanumeric sorting property of the filenames
286  * to decide which ones are earlier than the
287  * exclusiveCleanupFileName file. Note that this means files
288  * are not removed in the order they were originally written,
289  * in case this worries you.
290  */
291  if (IsXLogFileName(xlde->d_name) &&
292  strcmp(xlde->d_name + 8, exclusiveCleanupFileName + 8) < 0)
293  {
294 #ifdef WIN32
295  snprintf(WALFilePath, sizeof(WALFilePath), "%s\\%s", archiveLocation, xlde->d_name);
296 #else
297  snprintf(WALFilePath, sizeof(WALFilePath), "%s/%s", archiveLocation, xlde->d_name);
298 #endif
299 
300  if (debug)
301  fprintf(stderr, "\nremoving file \"%s\"", WALFilePath);
302 
303  rc = unlink(WALFilePath);
304  if (rc != 0)
305  {
306  fprintf(stderr, "\n%s: ERROR: could not remove file \"%s\": %s\n",
307  progname, WALFilePath, strerror(errno));
308  break;
309  }
310  }
311  }
312 
313  if (errno)
314  fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
316  if (debug)
317  fprintf(stderr, "\n");
318  }
319  else
320  fprintf(stderr, "%s: could not open archive location \"%s\": %s\n",
322 
323  if (closedir(xldir))
324  fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
326 
327  fflush(stderr);
328  }
329 }
char exclusiveCleanupFileName[MAXFNAMELEN]
Definition: pg_standby.c:64
int closedir(DIR *)
Definition: dirent.c:111
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
const char * progname
Definition: pg_standby.c:37
Definition: dirent.h:9
Definition: dirent.c:25
bool debug
Definition: pg_standby.c:48
#define IsXLogFileName(fname)
#define XLOG_DATA
Definition: pg_standby.c:95
DIR * opendir(const char *)
Definition: dirent.c:33
char WALFilePath[MAXPGPATH *2]
Definition: pg_standby.c:62
struct dirent * readdir(DIR *)
Definition: dirent.c:77
const char * strerror(int errnum)
Definition: strerror.c:19
char d_name[MAX_PATH]
Definition: dirent.h:14
char * archiveLocation
Definition: pg_standby.c:56
int nextWALFileType
Definition: pg_standby.c:98

◆ CustomizableInitialize()

static void CustomizableInitialize ( void  )
static

Definition at line 131 of file pg_standby.c.

References archiveLocation, MAXPGPATH, nextWALFileName, progname, RESTORE_COMMAND_COPY, RESTORE_COMMAND_LINK, restoreCommandType, SET_RESTORE_COMMAND, snprintf(), stat, stat_buf, WALFilePath, and xlogFilePath.

Referenced by main().

132 {
133 #ifdef WIN32
135  switch (restoreCommandType)
136  {
139  break;
141  default:
143  break;
144  }
145 #else
147  switch (restoreCommandType)
148  {
150 #if HAVE_WORKING_LINK
152  break;
153 #endif
155  default:
157  break;
158  }
159 #endif
160 
161  /*
162  * This code assumes that archiveLocation is a directory You may wish to
163  * add code to check for tape libraries, etc.. So, since it is a
164  * directory, we use stat to test if it's accessible
165  */
166  if (stat(archiveLocation, &stat_buf) != 0)
167  {
168  fprintf(stderr, "%s: archive location \"%s\" does not exist\n", progname, archiveLocation);
169  fflush(stderr);
170  exit(2);
171  }
172 }
int restoreCommandType
Definition: pg_standby.c:93
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
const char * progname
Definition: pg_standby.c:37
#define RESTORE_COMMAND_COPY
Definition: pg_standby.c:91
struct stat stat_buf
Definition: pg_standby.c:103
#define MAXPGPATH
#define SET_RESTORE_COMMAND(cmd, arg1, arg2)
Definition: pg_standby.c:100
#define stat(a, b)
Definition: win32_port.h:266
char WALFilePath[MAXPGPATH *2]
Definition: pg_standby.c:62
#define RESTORE_COMMAND_LINK
Definition: pg_standby.c:92
char * nextWALFileName
Definition: pg_standby.c:59
char * xlogFilePath
Definition: pg_standby.c:58
char * archiveLocation
Definition: pg_standby.c:56

◆ CustomizableNextWALFileReady()

static bool CustomizableNextWALFileReady ( void  )
static

Definition at line 180 of file pg_standby.c.

References _, debug, exclusiveCleanupFileName, IsBackupHistoryFileName, IsXLogFileName, need_cleanup, nextWALFileName, nextWALFileType, pg_usleep(), SetWALFileNameForCleanup(), SetWALSegSize(), sleeptime, stat, stat_buf, WALFilePath, WalSegSz, XLOG_BACKUP_LABEL, and XLOG_DATA.

Referenced by main().

181 {
182  if (stat(WALFilePath, &stat_buf) == 0)
183  {
184  /*
185  * If we've not seen any WAL segments, we don't know the WAL segment
186  * size, which we need. If it looks like a WAL segment, determine size
187  * of segments for the cluster.
188  */
190  {
191  if (SetWALSegSize())
192  {
193  /*
194  * Successfully determined WAL segment size. Can compute
195  * cleanup cutoff now.
196  */
198  if (debug)
199  {
200  fprintf(stderr,
201  _("WAL segment size: %d \n"), WalSegSz);
202  fprintf(stderr, "Keep archive history: ");
203 
204  if (need_cleanup)
205  fprintf(stderr, "%s and later\n",
207  else
208  fprintf(stderr, "no cleanup required\n");
209  }
210  }
211  }
212 
213  /*
214  * If it's a backup file, return immediately. If it's a regular file
215  * return only if it's the right size already.
216  */
218  {
220  return true;
221  }
222  else if (WalSegSz > 0 && stat_buf.st_size == WalSegSz)
223  {
224 #ifdef WIN32
225 
226  /*
227  * Windows 'cp' sets the final file size before the copy is
228  * complete, and not yet ready to be opened by pg_standby. So we
229  * wait for sleeptime secs before attempting to restore. If that
230  * is not enough, we will rely on the retry/holdoff mechanism.
231  * GNUWin32's cp does not have this problem.
232  */
233  pg_usleep(sleeptime * 1000000L);
234 #endif
236  return true;
237  }
238 
239  /*
240  * If still too small, wait until it is the correct size
241  */
242  if (WalSegSz > 0 && stat_buf.st_size > WalSegSz)
243  {
244  if (debug)
245  {
246  fprintf(stderr, "file size greater than expected\n");
247  fflush(stderr);
248  }
249  exit(3);
250  }
251  }
252 
253  return false;
254 }
char exclusiveCleanupFileName[MAXFNAMELEN]
Definition: pg_standby.c:64
int sleeptime
Definition: pg_standby.c:42
#define XLOG_BACKUP_LABEL
Definition: pg_standby.c:97
void pg_usleep(long microsec)
Definition: signal.c:53
bool debug
Definition: pg_standby.c:48
#define IsXLogFileName(fname)
struct stat stat_buf
Definition: pg_standby.c:103
#define XLOG_DATA
Definition: pg_standby.c:95
#define IsBackupHistoryFileName(fname)
#define stat(a, b)
Definition: win32_port.h:266
bool need_cleanup
Definition: pg_standby.c:49
char WALFilePath[MAXPGPATH *2]
Definition: pg_standby.c:62
char * nextWALFileName
Definition: pg_standby.c:59
int WalSegSz
Definition: pg_standby.c:39
#define _(x)
Definition: elog.c:84
int nextWALFileType
Definition: pg_standby.c:98
static bool SetWALFileNameForCleanup(void)
Definition: pg_standby.c:343
static bool SetWALSegSize(void)
Definition: pg_standby.c:407

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 650 of file pg_standby.c.

References archiveLocation, CheckForExternalTrigger(), CustomizableCleanupPriorWALFiles(), CustomizableInitialize(), CustomizableNextWALFileReady(), debug, Failover, FastFailover, get_progname(), getopt(), IsTLHistoryFileName, keepfiles, maxretries, maxwaittime, need_cleanup, nextWALFileName, nextWALFileType, optarg, optind, pg_strdup(), pg_usleep(), pqsignal(), progname, restartWALFileName, RESTORE_COMMAND_COPY, RESTORE_COMMAND_LINK, restoreCommand, restoreCommandType, RestoreWALFileForRecovery(), sighandler(), signaled, SIGQUIT, sigquit_handler(), SIGUSR1, sleeptime, SmartFailover, triggerPath, usage(), waittime, WALFilePath, XLOG_HISTORY, and xlogFilePath.

651 {
652  int c;
653 
654  progname = get_progname(argv[0]);
655 
656  if (argc > 1)
657  {
658  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
659  {
660  usage();
661  exit(0);
662  }
663  if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
664  {
665  puts("pg_standby (PostgreSQL) " PG_VERSION);
666  exit(0);
667  }
668  }
669 
670 #ifndef WIN32
671 
672  /*
673  * You can send SIGUSR1 to trigger failover.
674  *
675  * Postmaster uses SIGQUIT to request immediate shutdown. The default
676  * action is to core dump, but we don't want that, so trap it and commit
677  * suicide without core dump.
678  *
679  * We used to use SIGINT and SIGQUIT to trigger failover, but that turned
680  * out to be a bad idea because postmaster uses SIGQUIT to request
681  * immediate shutdown. We still trap SIGINT, but that may change in a
682  * future release.
683  *
684  * There's no way to trigger failover via signal on Windows.
685  */
686  (void) pqsignal(SIGUSR1, sighandler);
687  (void) pqsignal(SIGINT, sighandler); /* deprecated, use SIGUSR1 */
689 #endif
690 
691  while ((c = getopt(argc, argv, "cdk:lr:s:t:w:")) != -1)
692  {
693  switch (c)
694  {
695  case 'c': /* Use copy */
697  break;
698  case 'd': /* Debug mode */
699  debug = true;
700  break;
701  case 'k': /* keepfiles */
702  keepfiles = atoi(optarg);
703  if (keepfiles < 0)
704  {
705  fprintf(stderr, "%s: -k keepfiles must be >= 0\n", progname);
706  exit(2);
707  }
708  break;
709  case 'l': /* Use link */
710 
711  /*
712  * Link feature disabled, possibly permanently. Linking causes
713  * a problem after recovery ends that is not currently
714  * resolved by PostgreSQL. 25 Jun 2009
715  */
716 #ifdef NOT_USED
718 #endif
719  break;
720  case 'r': /* Retries */
721  maxretries = atoi(optarg);
722  if (maxretries < 0)
723  {
724  fprintf(stderr, "%s: -r maxretries must be >= 0\n", progname);
725  exit(2);
726  }
727  break;
728  case 's': /* Sleep time */
729  sleeptime = atoi(optarg);
730  if (sleeptime <= 0 || sleeptime > 60)
731  {
732  fprintf(stderr, "%s: -s sleeptime incorrectly set\n", progname);
733  exit(2);
734  }
735  break;
736  case 't': /* Trigger file */
738  break;
739  case 'w': /* Max wait time */
740  maxwaittime = atoi(optarg);
741  if (maxwaittime < 0)
742  {
743  fprintf(stderr, "%s: -w maxwaittime incorrectly set\n", progname);
744  exit(2);
745  }
746  break;
747  default:
748  fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
749  exit(2);
750  break;
751  }
752  }
753 
754  /*
755  * Parameter checking - after checking to see if trigger file present
756  */
757  if (argc == 1)
758  {
759  fprintf(stderr, "%s: not enough command-line arguments\n", progname);
760  exit(2);
761  }
762 
763  /*
764  * We will go to the archiveLocation to get nextWALFileName.
765  * nextWALFileName may not exist yet, which would not be an error, so we
766  * separate the archiveLocation and nextWALFileName so we can check
767  * separately whether archiveLocation exists, if not that is an error
768  */
769  if (optind < argc)
770  {
771  archiveLocation = argv[optind];
772  optind++;
773  }
774  else
775  {
776  fprintf(stderr, "%s: must specify archive location\n", progname);
777  fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
778  exit(2);
779  }
780 
781  if (optind < argc)
782  {
783  nextWALFileName = argv[optind];
784  optind++;
785  }
786  else
787  {
788  fprintf(stderr, "%s: must specify WAL file name as second non-option argument (use \"%%f\")\n", progname);
789  fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
790  exit(2);
791  }
792 
793  if (optind < argc)
794  {
795  xlogFilePath = argv[optind];
796  optind++;
797  }
798  else
799  {
800  fprintf(stderr, "%s: must specify xlog destination as third non-option argument (use \"%%p\")\n", progname);
801  fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
802  exit(2);
803  }
804 
805  if (optind < argc)
806  {
807  restartWALFileName = argv[optind];
808  optind++;
809  }
810 
812 
813  if (debug)
814  {
815  fprintf(stderr, "Trigger file: %s\n", triggerPath ? triggerPath : "<not set>");
816  fprintf(stderr, "Waiting for WAL file: %s\n", nextWALFileName);
817  fprintf(stderr, "WAL file path: %s\n", WALFilePath);
818  fprintf(stderr, "Restoring to: %s\n", xlogFilePath);
819  fprintf(stderr, "Sleep interval: %d second%s\n",
820  sleeptime, (sleeptime > 1 ? "s" : " "));
821  fprintf(stderr, "Max wait interval: %d %s\n",
822  maxwaittime, (maxwaittime > 0 ? "seconds" : "forever"));
823  fprintf(stderr, "Command for restore: %s\n", restoreCommand);
824  fflush(stderr);
825  }
826 
827  /*
828  * Check for initial history file: always the first file to be requested
829  * It's OK if the file isn't there - all other files need to wait
830  */
832  {
835  exit(0);
836  else
837  {
838  if (debug)
839  {
840  fprintf(stderr, "history file not found\n");
841  fflush(stderr);
842  }
843  exit(1);
844  }
845  }
846 
847  /*
848  * Main wait loop
849  */
850  for (;;)
851  {
852  /* Check for trigger file or signal first */
854 #ifndef WIN32
855  if (signaled)
856  {
858  if (debug)
859  {
860  fprintf(stderr, "signaled to exit: fast failover\n");
861  fflush(stderr);
862  }
863  }
864 #endif
865 
866  /*
867  * Check for fast failover immediately, before checking if the
868  * requested WAL file is available
869  */
870  if (Failover == FastFailover)
871  exit(1);
872 
874  {
875  /*
876  * Once we have restored this file successfully we can remove some
877  * prior WAL files. If this restore fails we mustn't remove any
878  * file because some of them will be requested again immediately
879  * after the failed restore, or when we restart recovery.
880  */
882  {
883  if (need_cleanup)
885 
886  exit(0);
887  }
888  else
889  {
890  /* Something went wrong in copying the file */
891  exit(1);
892  }
893  }
894 
895  /* Check for smart failover if the next WAL file was not available */
896  if (Failover == SmartFailover)
897  exit(1);
898 
899  if (sleeptime <= 60)
900  pg_usleep(sleeptime * 1000000L);
901 
902  waittime += sleeptime;
903  if (waittime >= maxwaittime && maxwaittime > 0)
904  {
906  if (debug)
907  {
908  fprintf(stderr, "Timed out after %d seconds: fast failover\n",
909  waittime);
910  fflush(stderr);
911  }
912  }
913  if (debug)
914  {
915  fprintf(stderr, "WAL file not present yet.");
916  if (triggerPath)
917  fprintf(stderr, " Checking for trigger file...");
918  fprintf(stderr, "\n");
919  fflush(stderr);
920  }
921  }
922 }
static void usage(void)
Definition: pg_standby.c:605
#define SIGQUIT
Definition: win32_port.h:164
static void CheckForExternalTrigger(void)
Definition: pg_standby.c:477
int waittime
Definition: pg_standby.c:43
int keepfiles
Definition: pg_standby.c:46
#define SIGUSR1
Definition: win32_port.h:177
const char * get_progname(const char *argv0)
Definition: path.c:453
static bool CustomizableNextWALFileReady(void)
Definition: pg_standby.c:180
int restoreCommandType
Definition: pg_standby.c:93
static void sigquit_handler(int sig)
Definition: pg_standby.c:641
int sleeptime
Definition: pg_standby.c:42
const char * progname
Definition: pg_standby.c:37
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: getopt.c:72
static void CustomizableInitialize(void)
Definition: pg_standby.c:131
void pg_usleep(long microsec)
Definition: signal.c:53
#define SmartFailover
Definition: pg_standby.c:86
#define RESTORE_COMMAND_COPY
Definition: pg_standby.c:91
int maxretries
Definition: pg_standby.c:47
int optind
Definition: getopt.c:51
static bool RestoreWALFileForRecovery(void)
Definition: pg_standby.c:570
bool debug
Definition: pg_standby.c:48
static int Failover
Definition: pg_standby.c:89
char * c
static void CustomizableCleanupPriorWALFiles(void)
Definition: pg_standby.c:257
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
char restoreCommand[MAXPGPATH]
Definition: pg_standby.c:63
#define FastFailover
Definition: pg_standby.c:87
#define XLOG_HISTORY
Definition: pg_standby.c:96
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:168
bool need_cleanup
Definition: pg_standby.c:49
char WALFilePath[MAXPGPATH *2]
Definition: pg_standby.c:62
#define RESTORE_COMMAND_LINK
Definition: pg_standby.c:92
char * nextWALFileName
Definition: pg_standby.c:59
#define IsTLHistoryFileName(fname)
static void sighandler(int sig)
Definition: pg_standby.c:634
char * optarg
Definition: getopt.c:53
char * xlogFilePath
Definition: pg_standby.c:58
char * triggerPath
Definition: pg_standby.c:57
char * archiveLocation
Definition: pg_standby.c:56
char * restartWALFileName
Definition: pg_standby.c:60
int nextWALFileType
Definition: pg_standby.c:98
static volatile sig_atomic_t signaled
Definition: pg_standby.c:53
int maxwaittime
Definition: pg_standby.c:45

◆ RestoreWALFileForRecovery()

static bool RestoreWALFileForRecovery ( void  )
static

Definition at line 570 of file pg_standby.c.

References debug, maxretries, pg_usleep(), restoreCommand, and sleeptime.

Referenced by main().

571 {
572  int rc = 0;
573  int numretries = 0;
574 
575  if (debug)
576  {
577  fprintf(stderr, "running restore: ");
578  fflush(stderr);
579  }
580 
581  while (numretries <= maxretries)
582  {
583  rc = system(restoreCommand);
584  if (rc == 0)
585  {
586  if (debug)
587  {
588  fprintf(stderr, "OK\n");
589  fflush(stderr);
590  }
591  return true;
592  }
593  pg_usleep(numretries++ * sleeptime * 1000000L);
594  }
595 
596  /*
597  * Allow caller to add additional info
598  */
599  if (debug)
600  fprintf(stderr, "not restored\n");
601  return false;
602 }
int sleeptime
Definition: pg_standby.c:42
void pg_usleep(long microsec)
Definition: signal.c:53
int maxretries
Definition: pg_standby.c:47
bool debug
Definition: pg_standby.c:48
char restoreCommand[MAXPGPATH]
Definition: pg_standby.c:63

◆ SetWALFileNameForCleanup()

static bool SetWALFileNameForCleanup ( void  )
static

Definition at line 343 of file pg_standby.c.

References cleanup(), exclusiveCleanupFileName, keepfiles, nextWALFileName, restartWALFileName, strlcpy(), WalSegSz, and XLogFileNameById.

Referenced by CustomizableNextWALFileReady().

344 {
345  uint32 tli = 1,
346  log = 0,
347  seg = 0;
348  uint32 log_diff = 0,
349  seg_diff = 0;
350  bool cleanup = false;
351  int max_segments_per_logfile = (0xFFFFFFFF / WalSegSz);
352 
353  if (restartWALFileName)
354  {
355  /*
356  * Don't do cleanup if the restartWALFileName provided is later than
357  * the xlog file requested. This is an error and we must not remove
358  * these files from archive. This shouldn't happen, but better safe
359  * than sorry.
360  */
361  if (strcmp(restartWALFileName, nextWALFileName) > 0)
362  return false;
363 
365  return true;
366  }
367 
368  if (keepfiles > 0)
369  {
370  sscanf(nextWALFileName, "%08X%08X%08X", &tli, &log, &seg);
371  if (tli > 0 && seg > 0)
372  {
373  log_diff = keepfiles / max_segments_per_logfile;
374  seg_diff = keepfiles % max_segments_per_logfile;
375  if (seg_diff > seg)
376  {
377  log_diff++;
378  seg = max_segments_per_logfile - (seg_diff - seg);
379  }
380  else
381  seg -= seg_diff;
382 
383  if (log >= log_diff)
384  {
385  log -= log_diff;
386  cleanup = true;
387  }
388  else
389  {
390  log = 0;
391  seg = 0;
392  }
393  }
394  }
395 
397 
398  return cleanup;
399 }
int keepfiles
Definition: pg_standby.c:46
char exclusiveCleanupFileName[MAXFNAMELEN]
Definition: pg_standby.c:64
#define XLogFileNameById(fname, tli, log, seg)
unsigned int uint32
Definition: c.h:306
static void cleanup(void)
Definition: bootstrap.c:873
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * nextWALFileName
Definition: pg_standby.c:59
int WalSegSz
Definition: pg_standby.c:39
char * restartWALFileName
Definition: pg_standby.c:60

◆ SetWALSegSize()

static bool SetWALSegSize ( void  )
static

Definition at line 407 of file pg_standby.c.

References Assert, buf, close, debug, fd(), IsValidWalSegSize, pg_free(), pg_malloc(), progname, read, strerror(), WALFilePath, WalSegSz, and XLogLongPageHeaderData::xlp_seg_size.

Referenced by CustomizableNextWALFileReady().

408 {
409  bool ret_val = false;
410  int fd;
411 
412  /* malloc this buffer to ensure sufficient alignment: */
413  char *buf = (char *) pg_malloc(XLOG_BLCKSZ);
414 
415  Assert(WalSegSz == -1);
416 
417  if ((fd = open(WALFilePath, O_RDWR, 0)) < 0)
418  {
419  fprintf(stderr, "%s: could not open WAL file \"%s\": %s\n",
420  progname, WALFilePath, strerror(errno));
421  pg_free(buf);
422  return false;
423  }
424 
425  errno = 0;
426  if (read(fd, buf, XLOG_BLCKSZ) == XLOG_BLCKSZ)
427  {
428  XLogLongPageHeader longhdr = (XLogLongPageHeader) buf;
429 
430  WalSegSz = longhdr->xlp_seg_size;
431 
433  {
434  /* successfully retrieved WAL segment size */
435  ret_val = true;
436  }
437  else
438  fprintf(stderr,
439  "%s: WAL segment size must be a power of two between 1MB and 1GB, but the WAL file header specifies %d bytes\n",
440  progname, WalSegSz);
441  }
442  else
443  {
444  /*
445  * Don't complain loudly, this is to be expected for segments being
446  * created.
447  */
448  if (errno != 0)
449  {
450  if (debug)
451  fprintf(stderr, "could not read file \"%s\": %s\n",
452  WALFilePath, strerror(errno));
453  }
454  else
455  {
456  if (debug)
457  fprintf(stderr, "not enough data in file \"%s\"\n",
458  WALFilePath);
459  }
460  }
461 
462  fflush(stderr);
463 
464  close(fd);
465  pg_free(buf);
466  return ret_val;
467 }
#define IsValidWalSegSize(size)
Definition: xlog_internal.h:97
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
const char * progname
Definition: pg_standby.c:37
static int fd(const char *x, int i)
Definition: preproc-init.c:105
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:74
bool debug
Definition: pg_standby.c:48
static char * buf
Definition: pg_test_fsync.c:67
#define Assert(condition)
Definition: c.h:680
char WALFilePath[MAXPGPATH *2]
Definition: pg_standby.c:62
void pg_free(void *ptr)
Definition: fe_memutils.c:105
int WalSegSz
Definition: pg_standby.c:39
const char * strerror(int errnum)
Definition: strerror.c:19
#define close(a)
Definition: win32.h:12
#define read(a, b, c)
Definition: win32.h:13

◆ sighandler()

static void sighandler ( int  sig)
static

Definition at line 634 of file pg_standby.c.

References signaled.

Referenced by main().

635 {
636  signaled = true;
637 }
static volatile sig_atomic_t signaled
Definition: pg_standby.c:53

◆ sigquit_handler()

static void sigquit_handler ( int  sig)
static

Definition at line 641 of file pg_standby.c.

References kill, pqsignal(), and SIG_DFL.

Referenced by main().

642 {
643  pqsignal(SIGINT, SIG_DFL);
644  kill(getpid(), SIGINT);
645 }
#define kill(pid, sig)
Definition: win32_port.h:437
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:168
#define SIG_DFL
Definition: win32_port.h:158

◆ usage()

static void usage ( void  )
static

Definition at line 605 of file pg_standby.c.

References progname.

Referenced by exec_command_slash_command_help(), main(), parse_psql_options(), and pg_notification_queue_usage().

606 {
607  printf("%s allows PostgreSQL warm standby servers to be configured.\n\n", progname);
608  printf("Usage:\n");
609  printf(" %s [OPTION]... ARCHIVELOCATION NEXTWALFILE XLOGFILEPATH [RESTARTWALFILE]\n", progname);
610  printf("\nOptions:\n");
611  printf(" -c copy file from archive (default)\n");
612  printf(" -d generate lots of debugging output (testing only)\n");
613  printf(" -k NUMFILESTOKEEP if RESTARTWALFILE is not used, remove files prior to limit\n"
614  " (0 keeps all)\n");
615  printf(" -l does nothing; use of link is now deprecated\n");
616  printf(" -r MAXRETRIES max number of times to retry, with progressive wait\n"
617  " (default=3)\n");
618  printf(" -s SLEEPTIME seconds to wait between file checks (min=1, max=60,\n"
619  " default=5)\n");
620  printf(" -t TRIGGERFILE trigger file to initiate failover (no default)\n");
621  printf(" -V, --version output version information, then exit\n");
622  printf(" -w MAXWAITTIME max seconds to wait for a file (0=no limit) (default=0)\n");
623  printf(" -?, --help show this help, then exit\n");
624  printf("\n"
625  "Main intended use as restore_command in recovery.conf:\n"
626  " restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
627  "e.g.\n"
628  " restore_command = 'pg_standby /mnt/server/archiverdir %%f %%p %%r'\n");
629  printf("\nReport bugs to <pgsql-bugs@postgresql.org>.\n");
630 }
const char * progname
Definition: pg_standby.c:37

Variable Documentation

◆ archiveLocation

char* archiveLocation

Definition at line 56 of file pg_standby.c.

Referenced by CustomizableCleanupPriorWALFiles(), CustomizableInitialize(), and main().

◆ debug

◆ exclusiveCleanupFileName

char exclusiveCleanupFileName[MAXFNAMELEN]

◆ Failover

int Failover = NoFailover
static

Definition at line 89 of file pg_standby.c.

Referenced by CheckForExternalTrigger(), and main().

◆ keepfiles

int keepfiles = 0

Definition at line 46 of file pg_standby.c.

Referenced by main(), and SetWALFileNameForCleanup().

◆ maxretries

int maxretries = 3

Definition at line 47 of file pg_standby.c.

Referenced by main(), and RestoreWALFileForRecovery().

◆ maxwaittime

int maxwaittime = 0

Definition at line 45 of file pg_standby.c.

Referenced by main().

◆ need_cleanup

bool need_cleanup = false

Definition at line 49 of file pg_standby.c.

Referenced by CustomizableNextWALFileReady(), and main().

◆ nextWALFileName

char* nextWALFileName

◆ nextWALFileType

int nextWALFileType

◆ priorWALFileName

char* priorWALFileName

Definition at line 61 of file pg_standby.c.

◆ progname

◆ restartWALFileName

char* restartWALFileName

Definition at line 60 of file pg_standby.c.

Referenced by main(), and SetWALFileNameForCleanup().

◆ restoreCommand

char restoreCommand[MAXPGPATH]

Definition at line 63 of file pg_standby.c.

Referenced by main(), and RestoreWALFileForRecovery().

◆ restoreCommandType

int restoreCommandType

Definition at line 93 of file pg_standby.c.

Referenced by CustomizableInitialize(), and main().

◆ signaled

volatile sig_atomic_t signaled = false
static

◆ sleeptime

◆ stat_buf

struct stat stat_buf

◆ triggerPath

char* triggerPath

Definition at line 57 of file pg_standby.c.

Referenced by CheckForExternalTrigger(), and main().

◆ waittime

int waittime = -1

Definition at line 43 of file pg_standby.c.

Referenced by AutoVacLauncherMain(), main(), and pg_timer_thread().

◆ WALFilePath

◆ WalSegSz

◆ xlogFilePath

char* xlogFilePath

Definition at line 58 of file pg_standby.c.

Referenced by CustomizableInitialize(), and main().