diff -r -c postgresql-8.4.orig/src/backend/access/transam/xlog.c postgresql-8.4/src/backend/access/transam/xlog.c *** postgresql-8.4.orig/src/backend/access/transam/xlog.c 2008-04-22 13:40:25.000000000 +0200 --- postgresql-8.4/src/backend/access/transam/xlog.c 2008-04-22 13:48:17.000000000 +0200 *************** *** 6577,6582 **** --- 6577,6583 ---- * create a backup history file in pg_xlog (whence it will immediately be * archived). The backup history file contains the same info found in * the label file, plus the backup-end time and WAL location. + * Note: different from CancelBackup which just cancels online backup mode. */ Datum pg_stop_backup(PG_FUNCTION_ARGS) *************** *** 7063,7065 **** --- 7064,7110 ---- pfree(buf.data); } + + /* + * BackupInProgress: check if online backup mode is active + * + * This is done by checking for existence of the "backup_label" file. + */ + bool + BackupInProgress(void) + { + struct stat stat_buf; + + return (stat(BACKUP_LABEL_FILE, &stat_buf) < 0) ? false : true; + } + + /* + * CancelBackup: rename the "backup_label" file to cancel backup mode + * + * If the "backup_label" file exists, it will be renamed to "backup_label.old". + * Note that this will render an online backup in progress useless. + * To correctly finish an online backup, pg_stop_backup must be called. + */ + void + CancelBackup(void) + { + struct stat stat_buf; + + /* if the file is not there, return */ + if (stat(BACKUP_LABEL_FILE, &stat_buf) < 0) + return; + + unlink(BACKUP_LABEL_OLD); + if (rename(BACKUP_LABEL_FILE, BACKUP_LABEL_OLD) == 0) + { + ereport(LOG, + (errmsg("online backup mode cancelled, \"%s\" renamed to \"%s\"", + BACKUP_LABEL_FILE, BACKUP_LABEL_OLD))); + } + else + { + ereport(LOG, + (errmsg("system error %d renaming \"%s\" to \"%s\", backup mode not cancelled", + errno, BACKUP_LABEL_FILE, BACKUP_LABEL_OLD))); + } + } diff -r -c postgresql-8.4.orig/src/backend/postmaster/postmaster.c postgresql-8.4/src/backend/postmaster/postmaster.c *** postgresql-8.4.orig/src/backend/postmaster/postmaster.c 2008-04-01 15:18:52.000000000 +0200 --- postgresql-8.4/src/backend/postmaster/postmaster.c 2008-04-22 13:48:17.000000000 +0200 *************** *** 253,258 **** --- 253,259 ---- PM_INIT, /* postmaster starting */ PM_STARTUP, /* waiting for startup subprocess */ PM_RUN, /* normal "database is alive" state */ + PM_WAIT_BACKUP, /* waiting for online backup mode to end */ PM_WAIT_BACKENDS, /* waiting for live backends to exit */ PM_SHUTDOWN, /* waiting for bgwriter to do shutdown ckpt */ PM_SHUTDOWN_2, /* waiting for archiver to finish */ *************** *** 1724,1731 **** static enum CAC_state canAcceptConnections(void) { ! /* Can't start backends when in startup/shutdown/recovery state. */ ! if (pmState != PM_RUN) { if (Shutdown > NoShutdown) return CAC_SHUTDOWN; /* shutdown is pending */ --- 1725,1736 ---- static enum CAC_state canAcceptConnections(void) { ! /* ! * Can't start backends when in startup/shutdown/recovery state. ! * In state PM_WAIT_BACKUP we must allow connections so that ! * a superuser can end online backup mode. ! */ ! if ((pmState != PM_RUN) && (pmState != PM_WAIT_BACKUP)) { if (Shutdown > NoShutdown) return CAC_SHUTDOWN; /* shutdown is pending */ *************** *** 1965,1975 **** /* and the walwriter too */ if (WalWriterPID != 0) signal_child(WalWriterPID, SIGTERM); ! pmState = PM_WAIT_BACKENDS; } /* ! * Now wait for backends to exit. If there are none, * PostmasterStateMachine will take the next step. */ PostmasterStateMachine(); --- 1970,1981 ---- /* and the walwriter too */ if (WalWriterPID != 0) signal_child(WalWriterPID, SIGTERM); ! pmState = PM_WAIT_BACKUP; } /* ! * Now wait for online backup mode to end and ! * backends to exit. If that is already the case, * PostmasterStateMachine will take the next step. */ PostmasterStateMachine(); *************** *** 2011,2016 **** --- 2017,2029 ---- * PostmasterStateMachine will take the next step. */ PostmasterStateMachine(); + + /* + * terminate backup mode to avoid recovery after a + * clean fast shutdown. + */ + CancelBackup(); + break; case SIGQUIT: *************** *** 2552,2557 **** --- 2565,2584 ---- static void PostmasterStateMachine(void) { + if (pmState == PM_WAIT_BACKUP) + { + /* + * PM_WAIT_BACKUP state ends when online backup mode is no longer + * active. In this state canAcceptConnections() will still allow + * client connections, which is necessary because a superuser + * has to call pg_stop_backup() to end online backup mode. + */ + if (!BackupInProgress()) + { + pmState = PM_WAIT_BACKENDS; + } + } + /* * If we are in a state-machine state that implies waiting for backends to * exit, see if they're all gone, and change state if so. diff -r -c postgresql-8.4.orig/src/bin/pg_ctl/pg_ctl.c postgresql-8.4/src/bin/pg_ctl/pg_ctl.c *** postgresql-8.4.orig/src/bin/pg_ctl/pg_ctl.c 2008-04-01 15:18:55.000000000 +0200 --- postgresql-8.4/src/bin/pg_ctl/pg_ctl.c 2008-04-22 13:48:17.000000000 +0200 *************** *** 144,149 **** --- 144,150 ---- static char postopts_file[MAXPGPATH]; static char pid_file[MAXPGPATH]; static char conf_file[MAXPGPATH]; + static char backup_file[MAXPGPATH]; #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE) static void unlimit_core_size(void); *************** *** 731,736 **** --- 732,738 ---- { int cnt; pgpid_t pid; + struct stat statbuf; pid = get_pgpid(); *************** *** 763,768 **** --- 765,776 ---- } else { + if ((shutdown_mode == SMART_MODE) && (stat(backup_file, &statbuf) == 0)) + { + print_msg(_("WARNING: online backup mode is active; must be ended\n" + " with pg_stop_backup() for shutdown to complete\n\n")); + } + print_msg(_("waiting for server to shut down...")); for (cnt = 0; cnt < wait_seconds; cnt++) *************** *** 799,804 **** --- 807,813 ---- { int cnt; pgpid_t pid; + struct stat statbuf; pid = get_pgpid(); *************** *** 833,838 **** --- 842,853 ---- exit(1); } + if ((shutdown_mode == SMART_MODE) && (stat(backup_file, &statbuf) == 0)) + { + print_msg(_("WARNING: online backup mode is active; must be ended\n" + " with pg_stop_backup() for shutdown to complete\n\n")); + } + print_msg(_("waiting for server to shut down...")); /* always wait for restart */ *************** *** 1883,1888 **** --- 1898,1904 ---- snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data); snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data); snprintf(conf_file, MAXPGPATH, "%s/postgresql.conf", pg_data); + snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data); } switch (ctl_command) diff -r -c postgresql-8.4.orig/src/include/miscadmin.h postgresql-8.4/src/include/miscadmin.h *** postgresql-8.4.orig/src/include/miscadmin.h 2008-04-01 15:18:56.000000000 +0200 --- postgresql-8.4/src/include/miscadmin.h 2008-04-22 13:48:17.000000000 +0200 *************** *** 330,333 **** --- 330,337 ---- extern void process_shared_preload_libraries(void); extern void process_local_preload_libraries(void); + /* in access/transam/xlog.c */ + extern bool BackupInProgress(void); + extern void CancelBackup(void); + #endif /* MISCADMIN_H */