PostgreSQL Source Code  git master
pg_standby.c
Go to the documentation of this file.
1 /*
2  * contrib/pg_standby/pg_standby.c
3  *
4  *
5  * pg_standby.c
6  *
7  * Production-ready example of how to create a Warm Standby
8  * database server using continuous archiving as a
9  * replication mechanism
10  *
11  * We separate the parameters for archive and nextWALfile
12  * so that we can check the archive exists, even if the
13  * WAL file doesn't (yet).
14  *
15  * This program will be executed once in full for each file
16  * requested by the warm standby server.
17  *
18  * It is designed to cater to a variety of needs, as well
19  * providing a customizable section.
20  *
21  * Original author: Simon Riggs simon@2ndquadrant.com
22  * Current maintainer: Simon Riggs
23  */
24 #include "postgres_fe.h"
25 
26 #include <ctype.h>
27 #include <dirent.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <signal.h>
31 #include <sys/time.h>
32 
33 #include "pg_getopt.h"
34 
35 #include "access/xlog_internal.h"
36 
37 const char *progname;
38 
39 int WalSegSz = -1;
40 
41 /* Options and defaults */
42 int sleeptime = 5; /* amount of time to sleep between file checks */
43 int waittime = -1; /* how long we have been waiting, -1 no wait
44  * yet */
45 int maxwaittime = 0; /* how long are we prepared to wait for? */
46 int keepfiles = 0; /* number of WAL files to keep, 0 keep all */
47 int maxretries = 3; /* number of retries on restore command */
48 bool debug = false; /* are we debugging? */
49 bool need_cleanup = false; /* do we need to remove files from
50  * archive? */
51 
52 #ifndef WIN32
53 static volatile sig_atomic_t signaled = false;
54 #endif
55 
56 char *archiveLocation; /* where to find the archive? */
57 char *triggerPath; /* where to find the trigger file? */
58 char *xlogFilePath; /* where we are going to restore to */
59 char *nextWALFileName; /* the file we need to get from archive */
60 char *restartWALFileName; /* the file from which we can restart restore */
61 char WALFilePath[MAXPGPATH * 2]; /* the file path including archive */
62 char restoreCommand[MAXPGPATH]; /* run this to restore */
63 char exclusiveCleanupFileName[MAXFNAMELEN]; /* the file we need to get
64  * from archive */
65 
66 /*
67  * Two types of failover are supported (smart and fast failover).
68  *
69  * The content of the trigger file determines the type of failover. If the
70  * trigger file contains the word "smart" (or the file is empty), smart
71  * failover is chosen: pg_standby acts as cp or ln command itself, on
72  * successful completion all the available WAL records will be applied
73  * resulting in zero data loss. But, it might take a long time to finish
74  * recovery if there's a lot of unapplied WAL.
75  *
76  * On the other hand, if the trigger file contains the word "fast", the
77  * recovery is finished immediately even if unapplied WAL files remain. Any
78  * transactions in the unapplied WAL files are lost.
79  *
80  * An empty trigger file performs smart failover. SIGUSR or SIGINT triggers
81  * fast failover. A timeout causes fast failover (smart failover would have
82  * the same effect, since if the timeout is reached there is no unapplied WAL).
83  */
84 #define NoFailover 0
85 #define SmartFailover 1
86 #define FastFailover 2
87 
88 static int Failover = NoFailover;
89 
90 #define RESTORE_COMMAND_COPY 0
91 #define RESTORE_COMMAND_LINK 1
93 
94 #define XLOG_DATA 0
95 #define XLOG_HISTORY 1
97 
98 #define SET_RESTORE_COMMAND(cmd, arg1, arg2) \
99  snprintf(restoreCommand, MAXPGPATH, cmd " \"%s\" \"%s\"", arg1, arg2)
100 
101 struct stat stat_buf;
102 
103 static bool SetWALFileNameForCleanup(void);
104 static bool SetWALSegSize(void);
105 
106 
107 /* =====================================================================
108  *
109  * Customizable section
110  *
111  * =====================================================================
112  *
113  * Currently, this section assumes that the Archive is a locally
114  * accessible directory. If you want to make other assumptions,
115  * such as using a vendor-specific archive and access API, these
116  * routines are the ones you'll need to change. You're
117  * encouraged to submit any changes to pgsql-hackers@lists.postgresql.org
118  * or personally to the current maintainer. Those changes may be
119  * folded in to later versions of this program.
120  */
121 
122 /*
123  * Initialize allows customized commands into the warm standby program.
124  *
125  * As an example, and probably the common case, we use either
126  * cp/ln commands on *nix, or copy/move command on Windows.
127  */
128 static void
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 }
171 
172 /*
173  * CustomizableNextWALFileReady()
174  *
175  * Is the requested file ready yet?
176  */
177 static bool
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 }
247 
248 static void
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 }
322 
323 /* =====================================================================
324  * End of Customizable section
325  * =====================================================================
326  */
327 
328 /*
329  * SetWALFileNameForCleanup()
330  *
331  * Set the earliest WAL filename that we want to keep on the archive
332  * and decide whether we need_cleanup
333  */
334 static bool
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 }
392 
393 /*
394  * Try to set the wal segment size from the WAL file specified by WALFilePath.
395  *
396  * Return true if size could be determined, false otherwise.
397  */
398 static bool
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 }
456 
457 /*
458  * CheckForExternalTrigger()
459  *
460  * Is there a trigger file? Sets global 'Failover' variable to indicate
461  * what kind of a trigger file it was. A "fast" trigger file is turned
462  * into a "smart" file as a side-effect.
463  */
464 static void
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 }
551 
552 /*
553  * RestoreWALFileForRecovery()
554  *
555  * Perform the action required to restore the file from archive
556  */
557 static bool
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 }
591 
592 static void
593 usage(void)
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 }
619 
620 #ifndef WIN32
621 static void
623 {
624  signaled = true;
625 }
626 
627 /* We don't want SIGQUIT to core dump */
628 static void
630 {
631  pqsignal(SIGINT, SIG_DFL);
632  kill(getpid(), SIGINT);
633 }
634 #endif
635 
636 /*------------ MAIN ----------------------------------------*/
637 int
638 main(int argc, char **argv)
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 }
#define IsValidWalSegSize(size)
Definition: xlog_internal.h:97
static void usage(void)
Definition: pg_standby.c:593
int main(int argc, char **argv)
Definition: pg_standby.c:638
#define SIGQUIT
Definition: win32_port.h:155
static void CheckForExternalTrigger(void)
Definition: pg_standby.c:465
#define NoFailover
Definition: pg_standby.c:84
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
char exclusiveCleanupFileName[MAXFNAMELEN]
Definition: pg_standby.c:63
int closedir(DIR *)
Definition: dirent.c:113
#define XLogFileNameById(fname, tli, log, seg)
#define kill(pid, sig)
Definition: win32_port.h:426
#define printf(...)
Definition: port.h:198
int sleeptime
Definition: pg_standby.c:42
const char * progname
Definition: pg_standby.c:37
#define fprintf
Definition: port.h:196
Definition: dirent.h:9
static int fd(const char *x, int i)
Definition: preproc-init.c:105
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: getopt.c:71
static void CustomizableInitialize(void)
Definition: pg_standby.c:129
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:74
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
Definition: dirent.c:25
bool debug
Definition: pg_standby.c:48
#define IsXLogFileName(fname)
struct stat stat_buf
Definition: pg_standby.c:101
static int Failover
Definition: pg_standby.c:88
#define XLOG_DATA
Definition: pg_standby.c:94
#define MAXPGPATH
DIR * opendir(const char *)
Definition: dirent.c:33
#define SET_RESTORE_COMMAND(cmd, arg1, arg2)
Definition: pg_standby.c:98
char * c
static char * buf
Definition: pg_test_fsync.c:68
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
unsigned int uint32
Definition: c.h:358
#define FastFailover
Definition: pg_standby.c:86
#define stat(a, b)
Definition: win32_port.h:255
#define MAXFNAMELEN
#define XLOG_HISTORY
Definition: pg_standby.c:95
static void cleanup(void)
Definition: bootstrap.c:901
static int sig
Definition: pg_ctl.c:84
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:170
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
bool need_cleanup
Definition: pg_standby.c:49
#define SIG_DFL
Definition: win32_port.h:149
#define Assert(condition)
Definition: c.h:732
char WALFilePath[MAXPGPATH *2]
Definition: pg_standby.c:61
#define strerror
Definition: port.h:205
struct dirent * readdir(DIR *)
Definition: dirent.c:77
#define RESTORE_COMMAND_LINK
Definition: pg_standby.c:91
char * nextWALFileName
Definition: pg_standby.c:59
int WalSegSz
Definition: pg_standby.c:39
#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 d_name[MAX_PATH]
Definition: dirent.h:14
#define close(a)
Definition: win32.h:12
char * archiveLocation
Definition: pg_standby.c:56
char data[XLOG_BLCKSZ]
Definition: c.h:1068
#define snprintf
Definition: port.h:192
#define _(x)
Definition: elog.c:84
#define read(a, b, c)
Definition: win32.h:13
char * restartWALFileName
Definition: pg_standby.c:60
int nextWALFileType
Definition: pg_standby.c:96
static bool SetWALFileNameForCleanup(void)
Definition: pg_standby.c:335
static volatile sig_atomic_t signaled
Definition: pg_standby.c:53
static bool SetWALSegSize(void)
Definition: pg_standby.c:399
int maxwaittime
Definition: pg_standby.c:45
#define ftruncate(a, b)
Definition: win32_port.h:60