PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 /* Options and defaults */
40 int sleeptime = 5; /* amount of time to sleep between file checks */
41 int waittime = -1; /* how long we have been waiting, -1 no wait
42  * yet */
43 int maxwaittime = 0; /* how long are we prepared to wait for? */
44 int keepfiles = 0; /* number of WAL files to keep, 0 keep all */
45 int maxretries = 3; /* number of retries on restore command */
46 bool debug = false; /* are we debugging? */
47 bool need_cleanup = false; /* do we need to remove files from
48  * archive? */
49 
50 #ifndef WIN32
51 static volatile sig_atomic_t signaled = false;
52 #endif
53 
54 char *archiveLocation; /* where to find the archive? */
55 char *triggerPath; /* where to find the trigger file? */
56 char *xlogFilePath; /* where we are going to restore to */
57 char *nextWALFileName; /* the file we need to get from archive */
58 char *restartWALFileName; /* the file from which we can restart restore */
59 char *priorWALFileName; /* the file we need to get from archive */
60 char WALFilePath[MAXPGPATH]; /* the file path including archive */
61 char restoreCommand[MAXPGPATH]; /* run this to restore */
62 char exclusiveCleanupFileName[MAXFNAMELEN]; /* the file we need to
63  * get from archive */
64 
65 /*
66  * Two types of failover are supported (smart and fast failover).
67  *
68  * The content of the trigger file determines the type of failover. If the
69  * trigger file contains the word "smart" (or the file is empty), smart
70  * failover is chosen: pg_standby acts as cp or ln command itself, on
71  * successful completion all the available WAL records will be applied
72  * resulting in zero data loss. But, it might take a long time to finish
73  * recovery if there's a lot of unapplied WAL.
74  *
75  * On the other hand, if the trigger file contains the word "fast", the
76  * recovery is finished immediately even if unapplied WAL files remain. Any
77  * transactions in the unapplied WAL files are lost.
78  *
79  * An empty trigger file performs smart failover. SIGUSR or SIGINT triggers
80  * fast failover. A timeout causes fast failover (smart failover would have
81  * the same effect, since if the timeout is reached there is no unapplied WAL).
82  */
83 #define NoFailover 0
84 #define SmartFailover 1
85 #define FastFailover 2
86 
87 static int Failover = NoFailover;
88 
89 #define RESTORE_COMMAND_COPY 0
90 #define RESTORE_COMMAND_LINK 1
92 
93 #define XLOG_DATA 0
94 #define XLOG_HISTORY 1
95 #define XLOG_BACKUP_LABEL 2
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 /* =====================================================================
104  *
105  * Customizable section
106  *
107  * =====================================================================
108  *
109  * Currently, this section assumes that the Archive is a locally
110  * accessible directory. If you want to make other assumptions,
111  * such as using a vendor-specific archive and access API, these
112  * routines are the ones you'll need to change. You're
113  * encouraged to submit any changes to pgsql-hackers@postgresql.org
114  * or personally to the current maintainer. Those changes may be
115  * folded in to later versions of this program.
116  */
117 
118 /*
119  * Initialize allows customized commands into the warm standby program.
120  *
121  * As an example, and probably the common case, we use either
122  * cp/ln commands on *nix, or copy/move command on Windows.
123  */
124 static void
126 {
127 #ifdef WIN32
129  switch (restoreCommandType)
130  {
133  break;
135  default:
137  break;
138  }
139 #else
141  switch (restoreCommandType)
142  {
144 #if HAVE_WORKING_LINK
146  break;
147 #endif
149  default:
151  break;
152  }
153 #endif
154 
155  /*
156  * This code assumes that archiveLocation is a directory You may wish to
157  * add code to check for tape libraries, etc.. So, since it is a
158  * directory, we use stat to test if it's accessible
159  */
160  if (stat(archiveLocation, &stat_buf) != 0)
161  {
162  fprintf(stderr, "%s: archive location \"%s\" does not exist\n", progname, archiveLocation);
163  fflush(stderr);
164  exit(2);
165  }
166 }
167 
168 /*
169  * CustomizableNextWALFileReady()
170  *
171  * Is the requested file ready yet?
172  */
173 static bool
175 {
176  if (stat(WALFilePath, &stat_buf) == 0)
177  {
178  /*
179  * If it's a backup file, return immediately. If it's a regular file
180  * return only if it's the right size already.
181  */
183  {
185  return true;
186  }
187  else if (stat_buf.st_size == XLOG_SEG_SIZE)
188  {
189 #ifdef WIN32
190 
191  /*
192  * Windows 'cp' sets the final file size before the copy is
193  * complete, and not yet ready to be opened by pg_standby. So we
194  * wait for sleeptime secs before attempting to restore. If that
195  * is not enough, we will rely on the retry/holdoff mechanism.
196  * GNUWin32's cp does not have this problem.
197  */
198  pg_usleep(sleeptime * 1000000L);
199 #endif
201  return true;
202  }
203 
204  /*
205  * If still too small, wait until it is the correct size
206  */
207  if (stat_buf.st_size > XLOG_SEG_SIZE)
208  {
209  if (debug)
210  {
211  fprintf(stderr, "file size greater than expected\n");
212  fflush(stderr);
213  }
214  exit(3);
215  }
216  }
217 
218  return false;
219 }
220 
221 #define MaxSegmentsPerLogFile ( 0xFFFFFFFF / XLOG_SEG_SIZE )
222 
223 static void
225 {
226  /*
227  * Work out name of prior file from current filename
228  */
229  if (nextWALFileType == XLOG_DATA)
230  {
231  int rc;
232  DIR *xldir;
233  struct dirent *xlde;
234 
235  /*
236  * Assume it's OK to keep failing. The failure situation may change
237  * over time, so we'd rather keep going on the main processing than
238  * fail because we couldn't clean up yet.
239  */
240  if ((xldir = opendir(archiveLocation)) != NULL)
241  {
242  while (errno = 0, (xlde = readdir(xldir)) != NULL)
243  {
244  /*
245  * We ignore the timeline part of the XLOG segment identifiers
246  * in deciding whether a segment is still needed. This
247  * ensures that we won't prematurely remove a segment from a
248  * parent timeline. We could probably be a little more
249  * proactive about removing segments of non-parent timelines,
250  * but that would be a whole lot more complicated.
251  *
252  * We use the alphanumeric sorting property of the filenames
253  * to decide which ones are earlier than the
254  * exclusiveCleanupFileName file. Note that this means files
255  * are not removed in the order they were originally written,
256  * in case this worries you.
257  */
258  if (IsXLogFileName(xlde->d_name) &&
259  strcmp(xlde->d_name + 8, exclusiveCleanupFileName + 8) < 0)
260  {
261 #ifdef WIN32
263 #else
265 #endif
266 
267  if (debug)
268  fprintf(stderr, "\nremoving file \"%s\"", WALFilePath);
269 
270  rc = unlink(WALFilePath);
271  if (rc != 0)
272  {
273  fprintf(stderr, "\n%s: ERROR: could not remove file \"%s\": %s\n",
274  progname, WALFilePath, strerror(errno));
275  break;
276  }
277  }
278  }
279 
280  if (errno)
281  fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
283  if (debug)
284  fprintf(stderr, "\n");
285  }
286  else
287  fprintf(stderr, "%s: could not open archive location \"%s\": %s\n",
289 
290  if (closedir(xldir))
291  fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
293 
294  fflush(stderr);
295  }
296 }
297 
298 /* =====================================================================
299  * End of Customizable section
300  * =====================================================================
301  */
302 
303 /*
304  * SetWALFileNameForCleanup()
305  *
306  * Set the earliest WAL filename that we want to keep on the archive
307  * and decide whether we need_cleanup
308  */
309 static bool
311 {
312  uint32 tli = 1,
313  log = 0,
314  seg = 0;
315  uint32 log_diff = 0,
316  seg_diff = 0;
317  bool cleanup = false;
318 
319  if (restartWALFileName)
320  {
321  /*
322  * Don't do cleanup if the restartWALFileName provided is later than
323  * the xlog file requested. This is an error and we must not remove
324  * these files from archive. This shouldn't happen, but better safe
325  * than sorry.
326  */
327  if (strcmp(restartWALFileName, nextWALFileName) > 0)
328  return false;
329 
331  return true;
332  }
333 
334  if (keepfiles > 0)
335  {
336  sscanf(nextWALFileName, "%08X%08X%08X", &tli, &log, &seg);
337  if (tli > 0 && seg > 0)
338  {
339  log_diff = keepfiles / MaxSegmentsPerLogFile;
340  seg_diff = keepfiles % MaxSegmentsPerLogFile;
341  if (seg_diff > seg)
342  {
343  log_diff++;
344  seg = MaxSegmentsPerLogFile - (seg_diff - seg);
345  }
346  else
347  seg -= seg_diff;
348 
349  if (log >= log_diff)
350  {
351  log -= log_diff;
352  cleanup = true;
353  }
354  else
355  {
356  log = 0;
357  seg = 0;
358  }
359  }
360  }
361 
363 
364  return cleanup;
365 }
366 
367 /*
368  * CheckForExternalTrigger()
369  *
370  * Is there a trigger file? Sets global 'Failover' variable to indicate
371  * what kind of a trigger file it was. A "fast" trigger file is turned
372  * into a "smart" file as a side-effect.
373  */
374 static void
376 {
377  char buf[32];
378  int fd;
379  int len;
380 
381  /*
382  * Look for a trigger file, if that option has been selected
383  *
384  * We use stat() here because triggerPath is always a file rather than
385  * potentially being in an archive
386  */
387  if (!triggerPath || stat(triggerPath, &stat_buf) != 0)
388  return;
389 
390  /*
391  * An empty trigger file performs smart failover. There's a little race
392  * condition here: if the writer of the trigger file has just created the
393  * file, but not yet written anything to it, we'll treat that as smart
394  * shutdown even if the other process was just about to write "fast" to
395  * it. But that's fine: we'll restore one more WAL file, and when we're
396  * invoked next time, we'll see the word "fast" and fail over immediately.
397  */
398  if (stat_buf.st_size == 0)
399  {
401  fprintf(stderr, "trigger file found: smart failover\n");
402  fflush(stderr);
403  return;
404  }
405 
406  if ((fd = open(triggerPath, O_RDWR, 0)) < 0)
407  {
408  fprintf(stderr, "WARNING: could not open \"%s\": %s\n",
409  triggerPath, strerror(errno));
410  fflush(stderr);
411  return;
412  }
413 
414  if ((len = read(fd, buf, sizeof(buf) - 1)) < 0)
415  {
416  fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
417  triggerPath, strerror(errno));
418  fflush(stderr);
419  close(fd);
420  return;
421  }
422  buf[len] = '\0';
423 
424  if (strncmp(buf, "smart", 5) == 0)
425  {
427  fprintf(stderr, "trigger file found: smart failover\n");
428  fflush(stderr);
429  close(fd);
430  return;
431  }
432 
433  if (strncmp(buf, "fast", 4) == 0)
434  {
436 
437  fprintf(stderr, "trigger file found: fast failover\n");
438  fflush(stderr);
439 
440  /*
441  * Turn it into a "smart" trigger by truncating the file. Otherwise if
442  * the server asks us again to restore a segment that was restored
443  * already, we would return "not found" and upset the server.
444  */
445  if (ftruncate(fd, 0) < 0)
446  {
447  fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
448  triggerPath, strerror(errno));
449  fflush(stderr);
450  }
451  close(fd);
452 
453  return;
454  }
455  close(fd);
456 
457  fprintf(stderr, "WARNING: invalid content in \"%s\"\n", triggerPath);
458  fflush(stderr);
459  return;
460 }
461 
462 /*
463  * RestoreWALFileForRecovery()
464  *
465  * Perform the action required to restore the file from archive
466  */
467 static bool
469 {
470  int rc = 0;
471  int numretries = 0;
472 
473  if (debug)
474  {
475  fprintf(stderr, "running restore: ");
476  fflush(stderr);
477  }
478 
479  while (numretries <= maxretries)
480  {
481  rc = system(restoreCommand);
482  if (rc == 0)
483  {
484  if (debug)
485  {
486  fprintf(stderr, "OK\n");
487  fflush(stderr);
488  }
489  return true;
490  }
491  pg_usleep(numretries++ * sleeptime * 1000000L);
492  }
493 
494  /*
495  * Allow caller to add additional info
496  */
497  if (debug)
498  fprintf(stderr, "not restored\n");
499  return false;
500 }
501 
502 static void
503 usage(void)
504 {
505  printf("%s allows PostgreSQL warm standby servers to be configured.\n\n", progname);
506  printf("Usage:\n");
507  printf(" %s [OPTION]... ARCHIVELOCATION NEXTWALFILE XLOGFILEPATH [RESTARTWALFILE]\n", progname);
508  printf("\nOptions:\n");
509  printf(" -c copy file from archive (default)\n");
510  printf(" -d generate lots of debugging output (testing only)\n");
511  printf(" -k NUMFILESTOKEEP if RESTARTWALFILE is not used, remove files prior to limit\n"
512  " (0 keeps all)\n");
513  printf(" -l does nothing; use of link is now deprecated\n");
514  printf(" -r MAXRETRIES max number of times to retry, with progressive wait\n"
515  " (default=3)\n");
516  printf(" -s SLEEPTIME seconds to wait between file checks (min=1, max=60,\n"
517  " default=5)\n");
518  printf(" -t TRIGGERFILE trigger file to initiate failover (no default)\n");
519  printf(" -V, --version output version information, then exit\n");
520  printf(" -w MAXWAITTIME max seconds to wait for a file (0=no limit) (default=0)\n");
521  printf(" -?, --help show this help, then exit\n");
522  printf("\n"
523  "Main intended use as restore_command in recovery.conf:\n"
524  " restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
525  "e.g.\n"
526  " restore_command = 'pg_standby /mnt/server/archiverdir %%f %%p %%r'\n");
527  printf("\nReport bugs to <pgsql-bugs@postgresql.org>.\n");
528 }
529 
530 #ifndef WIN32
531 static void
533 {
534  signaled = true;
535 }
536 
537 /* We don't want SIGQUIT to core dump */
538 static void
540 {
541  pqsignal(SIGINT, SIG_DFL);
542  kill(getpid(), SIGINT);
543 }
544 #endif
545 
546 /*------------ MAIN ----------------------------------------*/
547 int
548 main(int argc, char **argv)
549 {
550  int c;
551 
552  progname = get_progname(argv[0]);
553 
554  if (argc > 1)
555  {
556  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
557  {
558  usage();
559  exit(0);
560  }
561  if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
562  {
563  puts("pg_standby (PostgreSQL) " PG_VERSION);
564  exit(0);
565  }
566  }
567 
568 #ifndef WIN32
569 
570  /*
571  * You can send SIGUSR1 to trigger failover.
572  *
573  * Postmaster uses SIGQUIT to request immediate shutdown. The default
574  * action is to core dump, but we don't want that, so trap it and commit
575  * suicide without core dump.
576  *
577  * We used to use SIGINT and SIGQUIT to trigger failover, but that turned
578  * out to be a bad idea because postmaster uses SIGQUIT to request
579  * immediate shutdown. We still trap SIGINT, but that may change in a
580  * future release.
581  *
582  * There's no way to trigger failover via signal on Windows.
583  */
584  (void) pqsignal(SIGUSR1, sighandler);
585  (void) pqsignal(SIGINT, sighandler); /* deprecated, use SIGUSR1 */
587 #endif
588 
589  while ((c = getopt(argc, argv, "cdk:lr:s:t:w:")) != -1)
590  {
591  switch (c)
592  {
593  case 'c': /* Use copy */
595  break;
596  case 'd': /* Debug mode */
597  debug = true;
598  break;
599  case 'k': /* keepfiles */
600  keepfiles = atoi(optarg);
601  if (keepfiles < 0)
602  {
603  fprintf(stderr, "%s: -k keepfiles must be >= 0\n", progname);
604  exit(2);
605  }
606  break;
607  case 'l': /* Use link */
608 
609  /*
610  * Link feature disabled, possibly permanently. Linking causes
611  * a problem after recovery ends that is not currently
612  * resolved by PostgreSQL. 25 Jun 2009
613  */
614 #ifdef NOT_USED
616 #endif
617  break;
618  case 'r': /* Retries */
619  maxretries = atoi(optarg);
620  if (maxretries < 0)
621  {
622  fprintf(stderr, "%s: -r maxretries must be >= 0\n", progname);
623  exit(2);
624  }
625  break;
626  case 's': /* Sleep time */
627  sleeptime = atoi(optarg);
628  if (sleeptime <= 0 || sleeptime > 60)
629  {
630  fprintf(stderr, "%s: -s sleeptime incorrectly set\n", progname);
631  exit(2);
632  }
633  break;
634  case 't': /* Trigger file */
636  break;
637  case 'w': /* Max wait time */
638  maxwaittime = atoi(optarg);
639  if (maxwaittime < 0)
640  {
641  fprintf(stderr, "%s: -w maxwaittime incorrectly set\n", progname);
642  exit(2);
643  }
644  break;
645  default:
646  fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
647  exit(2);
648  break;
649  }
650  }
651 
652  /*
653  * Parameter checking - after checking to see if trigger file present
654  */
655  if (argc == 1)
656  {
657  fprintf(stderr, "%s: not enough command-line arguments\n", progname);
658  exit(2);
659  }
660 
661  /*
662  * We will go to the archiveLocation to get nextWALFileName.
663  * nextWALFileName may not exist yet, which would not be an error, so we
664  * separate the archiveLocation and nextWALFileName so we can check
665  * separately whether archiveLocation exists, if not that is an error
666  */
667  if (optind < argc)
668  {
669  archiveLocation = argv[optind];
670  optind++;
671  }
672  else
673  {
674  fprintf(stderr, "%s: must specify archive location\n", progname);
675  fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
676  exit(2);
677  }
678 
679  if (optind < argc)
680  {
681  nextWALFileName = argv[optind];
682  optind++;
683  }
684  else
685  {
686  fprintf(stderr, "%s: must specify WAL file name as second non-option argument (use \"%%f\")\n", progname);
687  fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
688  exit(2);
689  }
690 
691  if (optind < argc)
692  {
693  xlogFilePath = argv[optind];
694  optind++;
695  }
696  else
697  {
698  fprintf(stderr, "%s: must specify xlog destination as third non-option argument (use \"%%p\")\n", progname);
699  fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
700  exit(2);
701  }
702 
703  if (optind < argc)
704  {
705  restartWALFileName = argv[optind];
706  optind++;
707  }
708 
710 
712 
713  if (debug)
714  {
715  fprintf(stderr, "Trigger file: %s\n", triggerPath ? triggerPath : "<not set>");
716  fprintf(stderr, "Waiting for WAL file: %s\n", nextWALFileName);
717  fprintf(stderr, "WAL file path: %s\n", WALFilePath);
718  fprintf(stderr, "Restoring to: %s\n", xlogFilePath);
719  fprintf(stderr, "Sleep interval: %d second%s\n",
720  sleeptime, (sleeptime > 1 ? "s" : " "));
721  fprintf(stderr, "Max wait interval: %d %s\n",
722  maxwaittime, (maxwaittime > 0 ? "seconds" : "forever"));
723  fprintf(stderr, "Command for restore: %s\n", restoreCommand);
724  fprintf(stderr, "Keep archive history: ");
725  if (need_cleanup)
726  fprintf(stderr, "%s and later\n", exclusiveCleanupFileName);
727  else
728  fprintf(stderr, "no cleanup required\n");
729  fflush(stderr);
730  }
731 
732  /*
733  * Check for initial history file: always the first file to be requested
734  * It's OK if the file isn't there - all other files need to wait
735  */
737  {
740  exit(0);
741  else
742  {
743  if (debug)
744  {
745  fprintf(stderr, "history file not found\n");
746  fflush(stderr);
747  }
748  exit(1);
749  }
750  }
751 
752  /*
753  * Main wait loop
754  */
755  for (;;)
756  {
757  /* Check for trigger file or signal first */
759 #ifndef WIN32
760  if (signaled)
761  {
763  if (debug)
764  {
765  fprintf(stderr, "signaled to exit: fast failover\n");
766  fflush(stderr);
767  }
768  }
769 #endif
770 
771  /*
772  * Check for fast failover immediately, before checking if the
773  * requested WAL file is available
774  */
775  if (Failover == FastFailover)
776  exit(1);
777 
779  {
780  /*
781  * Once we have restored this file successfully we can remove some
782  * prior WAL files. If this restore fails we mustn't remove any
783  * file because some of them will be requested again immediately
784  * after the failed restore, or when we restart recovery.
785  */
787  {
788  if (need_cleanup)
790 
791  exit(0);
792  }
793  else
794  {
795  /* Something went wrong in copying the file */
796  exit(1);
797  }
798  }
799 
800  /* Check for smart failover if the next WAL file was not available */
801  if (Failover == SmartFailover)
802  exit(1);
803 
804  if (sleeptime <= 60)
805  pg_usleep(sleeptime * 1000000L);
806 
807  waittime += sleeptime;
808  if (waittime >= maxwaittime && maxwaittime > 0)
809  {
811  if (debug)
812  {
813  fprintf(stderr, "Timed out after %d seconds: fast failover\n",
814  waittime);
815  fflush(stderr);
816  }
817  }
818  if (debug)
819  {
820  fprintf(stderr, "WAL file not present yet.");
821  if (triggerPath)
822  fprintf(stderr, " Checking for trigger file...");
823  fprintf(stderr, "\n");
824  fflush(stderr);
825  }
826  }
827 }
static void usage(void)
Definition: pg_standby.c:503
#define SIGUSR1
Definition: win32.h:211
int main(int argc, char **argv)
Definition: pg_standby.c:548
static void CheckForExternalTrigger(void)
Definition: pg_standby.c:375
#define NoFailover
Definition: pg_standby.c:83
int waittime
Definition: pg_standby.c:41
int keepfiles
Definition: pg_standby.c:44
const char * get_progname(const char *argv0)
Definition: path.c:453
static bool CustomizableNextWALFileReady(void)
Definition: pg_standby.c:174
int restoreCommandType
Definition: pg_standby.c:91
static void sigquit_handler(int sig)
Definition: pg_standby.c:539
char exclusiveCleanupFileName[MAXFNAMELEN]
Definition: pg_standby.c:62
int closedir(DIR *)
Definition: dirent.c:113
#define XLogFileNameById(fname, tli, log, seg)
#define MaxSegmentsPerLogFile
Definition: pg_standby.c:221
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
int sleeptime
Definition: pg_standby.c:40
const char * progname
Definition: pg_standby.c:37
Definition: dirent.h:9
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define SIGQUIT
Definition: win32.h:197
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: getopt.c:72
static void CustomizableInitialize(void)
Definition: pg_standby.c:125
#define XLOG_BACKUP_LABEL
Definition: pg_standby.c:95
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:45
int optind
Definition: getopt.c:51
static bool RestoreWALFileForRecovery(void)
Definition: pg_standby.c:468
Definition: dirent.c:25
bool debug
Definition: pg_standby.c:46
#define IsXLogFileName(fname)
struct stat stat_buf
Definition: pg_standby.c:101
static int Failover
Definition: pg_standby.c:87
#define XLOG_DATA
Definition: pg_standby.c:93
#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:65
static void CustomizableCleanupPriorWALFiles(void)
Definition: pg_standby.c:224
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
char restoreCommand[MAXPGPATH]
Definition: pg_standby.c:61
unsigned int uint32
Definition: c.h:268
#define FastFailover
Definition: pg_standby.c:85
int unlink(const char *filename)
#define IsBackupHistoryFileName(fname)
#define MAXFNAMELEN
#define XLOG_HISTORY
Definition: pg_standby.c:94
static void cleanup(void)
Definition: bootstrap.c:848
static int sig
Definition: pg_ctl.c:76
#define SIG_DFL
Definition: win32.h:191
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:168
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define ftruncate(a, b)
Definition: win32.h:67
bool need_cleanup
Definition: pg_standby.c:47
#define NULL
Definition: c.h:229
struct dirent * readdir(DIR *)
Definition: dirent.c:78
#define RESTORE_COMMAND_LINK
Definition: pg_standby.c:90
char * nextWALFileName
Definition: pg_standby.c:57
#define IsTLHistoryFileName(fname)
char WALFilePath[MAXPGPATH]
Definition: pg_standby.c:60
static void sighandler(int sig)
Definition: pg_standby.c:532
char * optarg
Definition: getopt.c:53
const char * strerror(int errnum)
Definition: strerror.c:19
char * xlogFilePath
Definition: pg_standby.c:56
char * triggerPath
Definition: pg_standby.c:55
char d_name[MAX_PATH]
Definition: dirent.h:14
#define close(a)
Definition: win32.h:17
char * archiveLocation
Definition: pg_standby.c:54
char * priorWALFileName
Definition: pg_standby.c:59
#define read(a, b, c)
Definition: win32.h:18
char * restartWALFileName
Definition: pg_standby.c:58
int nextWALFileType
Definition: pg_standby.c:96
static bool SetWALFileNameForCleanup(void)
Definition: pg_standby.c:310
static volatile sig_atomic_t signaled
Definition: pg_standby.c:51
int maxwaittime
Definition: pg_standby.c:43