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 "access/xlog_internal.h"
#include "pg_getopt.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 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 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 85 of file pg_standby.c.

Referenced by CheckForExternalTrigger(), and main().

◆ NoFailover

#define NoFailover   0

Definition at line 83 of file pg_standby.c.

◆ RESTORE_COMMAND_COPY

#define RESTORE_COMMAND_COPY   0

Definition at line 89 of file pg_standby.c.

Referenced by CustomizableInitialize(), and main().

◆ RESTORE_COMMAND_LINK

#define RESTORE_COMMAND_LINK   1

Definition at line 90 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 97 of file pg_standby.c.

Referenced by CustomizableInitialize().

◆ SmartFailover

#define SmartFailover   1

Definition at line 84 of file pg_standby.c.

Referenced by CheckForExternalTrigger(), and main().

◆ XLOG_DATA

#define XLOG_DATA   0

Definition at line 93 of file pg_standby.c.

Referenced by CustomizableCleanupPriorWALFiles(), and CustomizableNextWALFileReady().

◆ XLOG_HISTORY

#define XLOG_HISTORY   1

Definition at line 94 of file pg_standby.c.

Referenced by main().

Function Documentation

◆ CheckForExternalTrigger()

static void CheckForExternalTrigger ( void  )
static

Definition at line 464 of file pg_standby.c.

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

Referenced by main().

465 {
466  char buf[32];
467  int fd;
468  int len;
469 
470  /*
471  * Look for a trigger file, if that option has been selected
472  *
473  * We use stat() here because triggerPath is always a file rather than
474  * potentially being in an archive
475  */
476  if (!triggerPath || stat(triggerPath, &stat_buf) != 0)
477  return;
478 
479  /*
480  * An empty trigger file performs smart failover. There's a little race
481  * condition here: if the writer of the trigger file has just created the
482  * file, but not yet written anything to it, we'll treat that as smart
483  * shutdown even if the other process was just about to write "fast" to
484  * it. But that's fine: we'll restore one more WAL file, and when we're
485  * invoked next time, we'll see the word "fast" and fail over immediately.
486  */
487  if (stat_buf.st_size == 0)
488  {
490  fprintf(stderr, "trigger file found: smart failover\n");
491  fflush(stderr);
492  return;
493  }
494 
495  if ((fd = open(triggerPath, O_RDWR, 0)) < 0)
496  {
497  fprintf(stderr, "WARNING: could not open \"%s\": %s\n",
498  triggerPath, strerror(errno));
499  fflush(stderr);
500  return;
501  }
502 
503  if ((len = read(fd, buf, sizeof(buf) - 1)) < 0)
504  {
505  fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
506  triggerPath, strerror(errno));
507  fflush(stderr);
508  close(fd);
509  return;
510  }
511  buf[len] = '\0';
512 
513  if (strncmp(buf, "smart", 5) == 0)
514  {
516  fprintf(stderr, "trigger file found: smart failover\n");
517  fflush(stderr);
518  close(fd);
519  return;
520  }
521 
522  if (strncmp(buf, "fast", 4) == 0)
523  {
525 
526  fprintf(stderr, "trigger file found: fast failover\n");
527  fflush(stderr);
528 
529  /*
530  * Turn it into a "smart" trigger by truncating the file. Otherwise if
531  * the server asks us again to restore a segment that was restored
532  * already, we would return "not found" and upset the server.
533  */
534  if (ftruncate(fd, 0) < 0)
535  {
536  fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
537  triggerPath, strerror(errno));
538  fflush(stderr);
539  }
540  close(fd);
541 
542  return;
543  }
544  close(fd);
545 
546  fprintf(stderr, "WARNING: invalid content in \"%s\"\n", triggerPath);
547  fflush(stderr);
548 }
#define fprintf
Definition: port.h:196
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define SmartFailover
Definition: pg_standby.c:84
struct stat stat_buf
Definition: pg_standby.c:100
static int Failover
Definition: pg_standby.c:87
static char * buf
Definition: pg_test_fsync.c:67
#define FastFailover
Definition: pg_standby.c:85
#define stat(a, b)
Definition: win32_port.h:255
#define strerror
Definition: port.h:205
char * triggerPath
Definition: pg_standby.c:56
#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 248 of file pg_standby.c.

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

Referenced by main().

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

◆ CustomizableInitialize()

static void CustomizableInitialize ( void  )
static

Definition at line 128 of file pg_standby.c.

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

Referenced by main().

129 {
130 #ifdef WIN32
132  switch (restoreCommandType)
133  {
136  break;
138  default:
140  break;
141  }
142 #else
144  switch (restoreCommandType)
145  {
147 #ifdef HAVE_WORKING_LINK
149  break;
150 #endif
152  default:
154  break;
155  }
156 #endif
157 
158  /*
159  * This code assumes that archiveLocation is a directory You may wish to
160  * add code to check for tape libraries, etc.. So, since it is a
161  * directory, we use stat to test if it's accessible
162  */
163  if (stat(archiveLocation, &stat_buf) != 0)
164  {
165  fprintf(stderr, "%s: archive location \"%s\" does not exist\n", progname, archiveLocation);
166  fflush(stderr);
167  exit(2);
168  }
169 }
int restoreCommandType
Definition: pg_standby.c:91
const char * progname
Definition: pg_standby.c:36
#define fprintf
Definition: port.h:196
#define RESTORE_COMMAND_COPY
Definition: pg_standby.c:89
struct stat stat_buf
Definition: pg_standby.c:100
#define MAXPGPATH
#define SET_RESTORE_COMMAND(cmd, arg1, arg2)
Definition: pg_standby.c:97
#define stat(a, b)
Definition: win32_port.h:255
char WALFilePath[MAXPGPATH *2]
Definition: pg_standby.c:60
#define RESTORE_COMMAND_LINK
Definition: pg_standby.c:90
char * nextWALFileName
Definition: pg_standby.c:58
char * xlogFilePath
Definition: pg_standby.c:57
char * archiveLocation
Definition: pg_standby.c:55
#define snprintf
Definition: port.h:192

◆ CustomizableNextWALFileReady()

static bool CustomizableNextWALFileReady ( void  )
static

Definition at line 177 of file pg_standby.c.

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

Referenced by main().

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

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 636 of file pg_standby.c.

References archiveLocation, CheckForExternalTrigger(), CustomizableCleanupPriorWALFiles(), CustomizableInitialize(), CustomizableNextWALFileReady(), debug, Failover, FastFailover, fprintf, 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.

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

◆ RestoreWALFileForRecovery()

static bool RestoreWALFileForRecovery ( void  )
static

Definition at line 556 of file pg_standby.c.

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

Referenced by main().

557 {
558  int rc = 0;
559  int numretries = 0;
560 
561  if (debug)
562  {
563  fprintf(stderr, "running restore: ");
564  fflush(stderr);
565  }
566 
567  while (numretries <= maxretries)
568  {
569  rc = system(restoreCommand);
570  if (rc == 0)
571  {
572  if (debug)
573  {
574  fprintf(stderr, "OK\n");
575  fflush(stderr);
576  }
577  return true;
578  }
579  pg_usleep(numretries++ * sleeptime * 1000000L);
580  }
581 
582  /*
583  * Allow caller to add additional info
584  */
585  if (debug)
586  fprintf(stderr, "not restored\n");
587  return false;
588 }
int sleeptime
Definition: pg_standby.c:41
#define fprintf
Definition: port.h:196
void pg_usleep(long microsec)
Definition: signal.c:53
int maxretries
Definition: pg_standby.c:46
bool debug
Definition: pg_standby.c:47
char restoreCommand[MAXPGPATH]
Definition: pg_standby.c:61

◆ SetWALFileNameForCleanup()

static bool SetWALFileNameForCleanup ( void  )
static

Definition at line 334 of file pg_standby.c.

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

Referenced by CustomizableNextWALFileReady().

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

◆ SetWALSegSize()

static bool SetWALSegSize ( void  )
static

Definition at line 398 of file pg_standby.c.

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

Referenced by CustomizableNextWALFileReady().

399 {
400  bool ret_val = false;
401  int fd;
403 
404  Assert(WalSegSz == -1);
405 
406  if ((fd = open(WALFilePath, O_RDWR, 0)) < 0)
407  {
408  fprintf(stderr, "%s: could not open WAL file \"%s\": %s\n",
409  progname, WALFilePath, strerror(errno));
410  return false;
411  }
412 
413  errno = 0;
414  if (read(fd, buf.data, XLOG_BLCKSZ) == XLOG_BLCKSZ)
415  {
417 
418  WalSegSz = longhdr->xlp_seg_size;
419 
421  {
422  /* successfully retrieved WAL segment size */
423  ret_val = true;
424  }
425  else
426  fprintf(stderr,
427  "%s: WAL segment size must be a power of two between 1MB and 1GB, but the WAL file header specifies %d bytes\n",
428  progname, WalSegSz);
429  }
430  else
431  {
432  /*
433  * Don't complain loudly, this is to be expected for segments being
434  * created.
435  */
436  if (errno != 0)
437  {
438  if (debug)
439  fprintf(stderr, "could not read file \"%s\": %s\n",
440  WALFilePath, strerror(errno));
441  }
442  else
443  {
444  if (debug)
445  fprintf(stderr, "not enough data in file \"%s\"\n",
446  WALFilePath);
447  }
448  }
449 
450  fflush(stderr);
451 
452  close(fd);
453  return ret_val;
454 }
#define IsValidWalSegSize(size)
Definition: xlog_internal.h:97
const char * progname
Definition: pg_standby.c:36
#define fprintf
Definition: port.h:196
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:47
static char * buf
Definition: pg_test_fsync.c:67
#define Assert(condition)
Definition: c.h:739
char WALFilePath[MAXPGPATH *2]
Definition: pg_standby.c:60
#define strerror
Definition: port.h:205
int WalSegSz
Definition: pg_standby.c:38
#define close(a)
Definition: win32.h:12
char data[XLOG_BLCKSZ]
Definition: c.h:1099
#define read(a, b, c)
Definition: win32.h:13

◆ sighandler()

static void sighandler ( int  sig)
static

Definition at line 620 of file pg_standby.c.

References signaled.

Referenced by main().

621 {
622  signaled = true;
623 }
static volatile sig_atomic_t signaled
Definition: pg_standby.c:52

◆ sigquit_handler()

static void sigquit_handler ( int  sig)
static

Definition at line 627 of file pg_standby.c.

References kill, pqsignal(), and SIG_DFL.

Referenced by main().

628 {
629  pqsignal(SIGINT, SIG_DFL);
630  kill(getpid(), SIGINT);
631 }
#define kill(pid, sig)
Definition: win32_port.h:426
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:170
#define SIG_DFL
Definition: win32_port.h:149

◆ usage()

static void usage ( void  )
static

Definition at line 591 of file pg_standby.c.

References printf, and progname.

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

592 {
593  printf("%s allows PostgreSQL warm standby servers to be configured.\n\n", progname);
594  printf("Usage:\n");
595  printf(" %s [OPTION]... ARCHIVELOCATION NEXTWALFILE XLOGFILEPATH [RESTARTWALFILE]\n", progname);
596  printf("\nOptions:\n");
597  printf(" -c copy file from archive (default)\n");
598  printf(" -d generate lots of debugging output (testing only)\n");
599  printf(" -k NUMFILESTOKEEP if RESTARTWALFILE is not used, remove files prior to limit\n"
600  " (0 keeps all)\n");
601  printf(" -l does nothing; use of link is now deprecated\n");
602  printf(" -r MAXRETRIES max number of times to retry, with progressive wait\n"
603  " (default=3)\n");
604  printf(" -s SLEEPTIME seconds to wait between file checks (min=1, max=60,\n"
605  " default=5)\n");
606  printf(" -t TRIGGERFILE trigger file to initiate failover (no default)\n");
607  printf(" -V, --version output version information, then exit\n");
608  printf(" -w MAXWAITTIME max seconds to wait for a file (0=no limit) (default=0)\n");
609  printf(" -?, --help show this help, then exit\n");
610  printf("\n"
611  "Main intended use as restore_command in postgresql.conf:\n"
612  " restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
613  "e.g.\n"
614  " restore_command = 'pg_standby /mnt/server/archiverdir %%f %%p %%r'\n");
615  printf("\nReport bugs to <pgsql-bugs@lists.postgresql.org>.\n");
616 }
#define printf(...)
Definition: port.h:198
const char * progname
Definition: pg_standby.c:36

Variable Documentation

◆ archiveLocation

char* archiveLocation

Definition at line 55 of file pg_standby.c.

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

◆ debug

◆ exclusiveCleanupFileName

char exclusiveCleanupFileName[MAXFNAMELEN]

◆ Failover

int Failover = NoFailover
static

Definition at line 87 of file pg_standby.c.

Referenced by CheckForExternalTrigger(), and main().

◆ keepfiles

int keepfiles = 0

Definition at line 45 of file pg_standby.c.

Referenced by main(), and SetWALFileNameForCleanup().

◆ maxretries

int maxretries = 3

Definition at line 46 of file pg_standby.c.

Referenced by main(), and RestoreWALFileForRecovery().

◆ maxwaittime

int maxwaittime = 0

Definition at line 44 of file pg_standby.c.

Referenced by main().

◆ need_cleanup

bool need_cleanup = false

Definition at line 48 of file pg_standby.c.

Referenced by CustomizableNextWALFileReady(), and main().

◆ nextWALFileName

char* nextWALFileName

◆ nextWALFileType

int nextWALFileType

◆ progname

◆ restartWALFileName

char* restartWALFileName

Definition at line 59 of file pg_standby.c.

Referenced by main(), and SetWALFileNameForCleanup().

◆ restoreCommand

char restoreCommand[MAXPGPATH]

Definition at line 61 of file pg_standby.c.

Referenced by main(), and RestoreWALFileForRecovery().

◆ restoreCommandType

int restoreCommandType

Definition at line 91 of file pg_standby.c.

Referenced by CustomizableInitialize(), and main().

◆ signaled

volatile sig_atomic_t signaled = false
static

Definition at line 52 of file pg_standby.c.

Referenced by ConditionVariableCancelSleep(), main(), sighandler(), and SignalSomeChildren().

◆ sleeptime

◆ stat_buf

struct stat stat_buf

◆ triggerPath

char* triggerPath

Definition at line 56 of file pg_standby.c.

Referenced by CheckForExternalTrigger(), and main().

◆ waittime

int waittime = -1

Definition at line 42 of file pg_standby.c.

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

◆ WALFilePath

◆ WalSegSz

◆ xlogFilePath

char* xlogFilePath

Definition at line 57 of file pg_standby.c.

Referenced by CustomizableInitialize(), and main().