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 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 86 of file pg_standby.c.

Referenced by CheckForExternalTrigger(), and main().

◆ NoFailover

#define NoFailover   0

Definition at line 84 of file pg_standby.c.

◆ RESTORE_COMMAND_COPY

#define RESTORE_COMMAND_COPY   0

Definition at line 90 of file pg_standby.c.

Referenced by CustomizableInitialize(), and main().

◆ RESTORE_COMMAND_LINK

#define RESTORE_COMMAND_LINK   1

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

Referenced by CustomizableInitialize().

◆ SmartFailover

#define SmartFailover   1

Definition at line 85 of file pg_standby.c.

Referenced by CheckForExternalTrigger(), and main().

◆ XLOG_DATA

#define XLOG_DATA   0

Definition at line 94 of file pg_standby.c.

Referenced by CustomizableCleanupPriorWALFiles(), and CustomizableNextWALFileReady().

◆ XLOG_HISTORY

#define XLOG_HISTORY   1

Definition at line 95 of file pg_standby.c.

Referenced by main().

Function Documentation

◆ CheckForExternalTrigger()

static void CheckForExternalTrigger ( void  )
static

Definition at line 465 of file pg_standby.c.

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

Referenced by main().

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

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

◆ CustomizableInitialize()

static void CustomizableInitialize ( void  )
static

Definition at line 129 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().

130 {
131 #ifdef WIN32
133  switch (restoreCommandType)
134  {
137  break;
139  default:
141  break;
142  }
143 #else
145  switch (restoreCommandType)
146  {
148 #ifdef HAVE_WORKING_LINK
150  break;
151 #endif
153  default:
155  break;
156  }
157 #endif
158 
159  /*
160  * This code assumes that archiveLocation is a directory You may wish to
161  * add code to check for tape libraries, etc.. So, since it is a
162  * directory, we use stat to test if it's accessible
163  */
164  if (stat(archiveLocation, &stat_buf) != 0)
165  {
166  fprintf(stderr, "%s: archive location \"%s\" does not exist\n", progname, archiveLocation);
167  fflush(stderr);
168  exit(2);
169  }
170 }
int restoreCommandType
Definition: pg_standby.c:92
const char * progname
Definition: pg_standby.c:37
#define fprintf
Definition: port.h:196
#define RESTORE_COMMAND_COPY
Definition: pg_standby.c:90
struct stat stat_buf
Definition: pg_standby.c:101
#define MAXPGPATH
#define SET_RESTORE_COMMAND(cmd, arg1, arg2)
Definition: pg_standby.c:98
#define stat(a, b)
Definition: win32_port.h:255
char WALFilePath[MAXPGPATH *2]
Definition: pg_standby.c:61
#define RESTORE_COMMAND_LINK
Definition: pg_standby.c:91
char * nextWALFileName
Definition: pg_standby.c:59
char * xlogFilePath
Definition: pg_standby.c:58
char * archiveLocation
Definition: pg_standby.c:56
#define snprintf
Definition: port.h:192

◆ CustomizableNextWALFileReady()

static bool CustomizableNextWALFileReady ( void  )
static

Definition at line 178 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().

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

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 638 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.

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

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

Referenced by main().

559 {
560  int rc = 0;
561  int numretries = 0;
562 
563  if (debug)
564  {
565  fprintf(stderr, "running restore: ");
566  fflush(stderr);
567  }
568 
569  while (numretries <= maxretries)
570  {
571  rc = system(restoreCommand);
572  if (rc == 0)
573  {
574  if (debug)
575  {
576  fprintf(stderr, "OK\n");
577  fflush(stderr);
578  }
579  return true;
580  }
581  pg_usleep(numretries++ * sleeptime * 1000000L);
582  }
583 
584  /*
585  * Allow caller to add additional info
586  */
587  if (debug)
588  fprintf(stderr, "not restored\n");
589  return false;
590 }
int sleeptime
Definition: pg_standby.c:42
#define fprintf
Definition: port.h:196
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:62

◆ SetWALFileNameForCleanup()

static bool SetWALFileNameForCleanup ( void  )
static

Definition at line 335 of file pg_standby.c.

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

Referenced by CustomizableNextWALFileReady().

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

◆ SetWALSegSize()

static bool SetWALSegSize ( void  )
static

Definition at line 399 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().

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

◆ sighandler()

static void sighandler ( int  sig)
static

Definition at line 622 of file pg_standby.c.

References signaled.

Referenced by main().

623 {
624  signaled = true;
625 }
static volatile sig_atomic_t signaled
Definition: pg_standby.c:53

◆ sigquit_handler()

static void sigquit_handler ( int  sig)
static

Definition at line 629 of file pg_standby.c.

References kill, pqsignal(), and SIG_DFL.

Referenced by main().

630 {
631  pqsignal(SIGINT, SIG_DFL);
632  kill(getpid(), SIGINT);
633 }
#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 593 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().

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

◆ 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 62 of file pg_standby.c.

Referenced by main(), and RestoreWALFileForRecovery().

◆ restoreCommandType

int restoreCommandType

Definition at line 92 of file pg_standby.c.

Referenced by CustomizableInitialize(), and main().

◆ signaled

volatile sig_atomic_t signaled = false
static

Definition at line 53 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 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().