diff options
author | Robert Haas <rhaas@postgresql.org> | 2011-02-15 21:28:48 -0500 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2011-02-15 21:30:23 -0500 |
commit | 4695da5ae97bbb58d274887fd68edbe88d03ebcb (patch) | |
tree | cbb34db9883cccc6a12061207aa74433267d43a0 /src | |
parent | 8ddc05fb01ee2c423bf5613426726351e860d4b4 (diff) | |
download | postgresql-4695da5ae97bbb58d274887fd68edbe88d03ebcb.tar.gz postgresql-4695da5ae97bbb58d274887fd68edbe88d03ebcb.zip |
pg_ctl promote
Fujii Masao, reviewed by Robert Haas, Stephen Frost, and Magnus Hagander.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/xlog.c | 49 | ||||
-rw-r--r-- | src/backend/postmaster/postmaster.c | 8 | ||||
-rw-r--r-- | src/bin/pg_ctl/pg_ctl.c | 74 | ||||
-rw-r--r-- | src/include/access/xlog.h | 1 |
4 files changed, 126 insertions, 6 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 4dc8dc6e391..6fdaaff9140 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -62,6 +62,7 @@ /* File path names (all relative to $PGDATA) */ #define RECOVERY_COMMAND_FILE "recovery.conf" #define RECOVERY_COMMAND_DONE "recovery.done" +#define PROMOTE_SIGNAL_FILE "promote" /* User-settable parameters */ @@ -565,6 +566,7 @@ typedef struct xl_restore_point */ static volatile sig_atomic_t got_SIGHUP = false; static volatile sig_atomic_t shutdown_requested = false; +static volatile sig_atomic_t promote_triggered = false; /* * Flag set when executing a restore command, to tell SIGTERM signal handler @@ -9669,6 +9671,14 @@ StartupProcSigUsr1Handler(SIGNAL_ARGS) latch_sigusr1_handler(); } +/* SIGUSR2: set flag to finish recovery */ +static void +StartupProcTriggerHandler(SIGNAL_ARGS) +{ + promote_triggered = true; + WakeupRecovery(); +} + /* SIGHUP: set flag to re-read config file at next convenient time */ static void StartupProcSigHupHandler(SIGNAL_ARGS) @@ -9746,7 +9756,7 @@ StartupProcessMain(void) pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, StartupProcSigUsr1Handler); - pqsignal(SIGUSR2, SIG_IGN); + pqsignal(SIGUSR2, StartupProcTriggerHandler); /* * Reset some signals that are accepted by postmaster but not here @@ -10192,9 +10202,9 @@ emode_for_corrupt_record(int emode, XLogRecPtr RecPtr) } /* - * Check to see if the trigger file exists. If it does, request postmaster - * to shut down walreceiver, wait for it to exit, remove the trigger - * file, and return true. + * Check to see whether the user-specified trigger file exists and whether a + * promote request has arrived. If either condition holds, request postmaster + * to shut down walreceiver, wait for it to exit, and return true. */ static bool CheckForStandbyTrigger(void) @@ -10205,6 +10215,16 @@ CheckForStandbyTrigger(void) if (triggered) return true; + if (promote_triggered) + { + ereport(LOG, + (errmsg("received promote request"))); + ShutdownWalRcv(); + promote_triggered = false; + triggered = true; + return true; + } + if (TriggerFile == NULL) return false; @@ -10221,6 +10241,27 @@ CheckForStandbyTrigger(void) } /* + * Check to see if a promote request has arrived. Should be + * called by postmaster after receiving SIGUSR1. + */ +bool +CheckPromoteSignal(void) +{ + struct stat stat_buf; + + if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0) + { + /* + * Since we are in a signal handler, it's not safe + * to elog. We silently ignore any error from unlink. + */ + unlink(PROMOTE_SIGNAL_FILE); + return true; + } + return false; +} + +/* * Wake up startup process to replay newly arrived WAL, or to notice that * failover has been requested. */ diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 8f77d1bfc97..997af5bf072 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -4284,6 +4284,14 @@ sigusr1_handler(SIGNAL_ARGS) WalReceiverPID = StartWalReceiver(); } + if (CheckPromoteSignal() && StartupPID != 0 && + (pmState == PM_STARTUP || pmState == PM_RECOVERY || + pmState == PM_HOT_STANDBY || pmState == PM_WAIT_READONLY)) + { + /* Tell startup process to finish recovery */ + signal_child(StartupPID, SIGUSR2); + } + PG_SETMASK(&UnBlockSig); errno = save_errno; diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c index 6c87f158f3f..2fab5c98fdc 100644 --- a/src/bin/pg_ctl/pg_ctl.c +++ b/src/bin/pg_ctl/pg_ctl.c @@ -62,6 +62,7 @@ typedef enum START_COMMAND, STOP_COMMAND, RESTART_COMMAND, + PROMOTE_COMMAND, RELOAD_COMMAND, STATUS_COMMAND, KILL_COMMAND, @@ -96,6 +97,7 @@ static char postopts_file[MAXPGPATH]; static char pid_file[MAXPGPATH]; static char backup_file[MAXPGPATH]; static char recovery_file[MAXPGPATH]; +static char promote_file[MAXPGPATH]; #if defined(WIN32) || defined(__CYGWIN__) static DWORD pgctl_start_type = SERVICE_AUTO_START; @@ -124,6 +126,7 @@ static void do_init(void); static void do_start(void); static void do_stop(void); static void do_restart(void); +static void do_promote(void); static void do_reload(void); static void do_status(void); static void do_kill(pgpid_t pid); @@ -872,7 +875,7 @@ do_stop(void) /* - * restart/reload routines + * restart/promote/reload routines */ static void @@ -965,6 +968,66 @@ do_restart(void) do_start(); } +static void +do_promote(void) +{ + FILE *prmfile; + pgpid_t pid; + struct stat statbuf; + + pid = get_pgpid(); + + if (pid == 0) /* no pid file */ + { + write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file); + write_stderr(_("Is server running?\n")); + exit(1); + } + else if (pid < 0) /* standalone backend, not postmaster */ + { + pid = -pid; + write_stderr(_("%s: cannot promote server; " + "single-user server is running (PID: %ld)\n"), + progname, pid); + exit(1); + } + + /* If recovery.conf doesn't exist, the server is not in standby mode */ + if (stat(recovery_file, &statbuf) != 0) + { + write_stderr(_("%s: cannot promote server; " + "server is not in standby mode\n"), + progname); + exit(1); + } + + if ((prmfile = fopen(promote_file, "w")) == NULL) + { + write_stderr(_("%s: could not create promote signal file \"%s\": %s\n"), + progname, promote_file, strerror(errno)); + exit(1); + } + if (fclose(prmfile)) + { + write_stderr(_("%s: could not write promote signal file \"%s\": %s\n"), + progname, promote_file, strerror(errno)); + exit(1); + } + + sig = SIGUSR1; + if (kill((pid_t) pid, sig) != 0) + { + write_stderr(_("%s: could not send promote signal (PID: %ld): %s\n"), + progname, pid, strerror(errno)); + if (unlink(promote_file) != 0) + write_stderr(_("%s: could not remove promote signal file \"%s\": %s\n"), + progname, promote_file, strerror(errno)); + exit(1); + } + + print_msg(_("server promoting\n")); +} + static void do_reload(void) @@ -1617,7 +1680,7 @@ do_advice(void) static void do_help(void) { - printf(_("%s is a utility to start, stop, restart, reload configuration files,\n" + printf(_("%s is a utility to start, stop, restart, promote, reload configuration files,\n" "report the status of a PostgreSQL server, or signal a PostgreSQL process.\n\n"), progname); printf(_("Usage:\n")); printf(_(" %s init[db] [-D DATADIR] [-s] [-o \"OPTIONS\"]\n"), progname); @@ -1625,6 +1688,7 @@ do_help(void) printf(_(" %s stop [-W] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n"), progname); printf(_(" %s restart [-w] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n" " [-o \"OPTIONS\"]\n"), progname); + printf(_(" %s promote [-D DATADIR] [-s]\n"), progname); printf(_(" %s reload [-D DATADIR] [-s]\n"), progname); printf(_(" %s status [-D DATADIR]\n"), progname); printf(_(" %s kill SIGNALNAME PID\n"), progname); @@ -1950,6 +2014,8 @@ main(int argc, char **argv) ctl_command = STOP_COMMAND; else if (strcmp(argv[optind], "restart") == 0) ctl_command = RESTART_COMMAND; + else if (strcmp(argv[optind], "promote") == 0) + ctl_command = PROMOTE_COMMAND; else if (strcmp(argv[optind], "reload") == 0) ctl_command = RELOAD_COMMAND; else if (strcmp(argv[optind], "status") == 0) @@ -2036,6 +2102,7 @@ main(int argc, char **argv) snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data); snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data); snprintf(recovery_file, MAXPGPATH, "%s/recovery.conf", pg_data); + snprintf(promote_file, MAXPGPATH, "%s/promote", pg_data); } switch (ctl_command) @@ -2055,6 +2122,9 @@ main(int argc, char **argv) case RESTART_COMMAND: do_restart(); break; + case PROMOTE_COMMAND: + do_promote(); + break; case RELOAD_COMMAND: do_reload(); break; diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index 1803d5ab201..7cd07a25d22 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -313,6 +313,7 @@ extern TimeLineID GetRecoveryTargetTLI(void); extern void HandleStartupProcInterrupts(void); extern void StartupProcessMain(void); +extern bool CheckPromoteSignal(void); extern void WakeupRecovery(void); /* |