diff -rcN postgresql/doc/src/sgml/backup.sgml postgresql_with_patch/doc/src/sgml/backup.sgml *** postgresql/doc/src/sgml/backup.sgml 2011-09-12 05:19:14.000000000 +0900 --- postgresql_with_patch/doc/src/sgml/backup.sgml 2011-09-13 15:23:49.000000000 +0900 *************** *** 724,734 **** Making a Base Backup ! The procedure for making a base backup is relatively simple: ! Ensure that WAL archiving is enabled and working. --- 724,736 ---- Making a Base Backup ! The procedure for making a base backup is relatively simple. This can ! also run on hot standby, the procedure is a little different: ! Ensure that WAL archiving is enabled and working. On hot standby then ! this does not need to ensure since there is no WAL archiving originally. *************** *** 780,785 **** --- 782,795 ---- + Copy pg_control file to the backup taken by above-procedure. + This needs on hot standby. This is performed to recovery with Minimum + recovery ending location in pg_control instead of backup end + record. + + + + Again connect to the database as a superuser, and issue the command: SELECT pg_stop_backup(); *************** *** 788,793 **** --- 798,805 ---- the next WAL segment. The reason for the switch is to arrange for the last WAL segment file written during the backup interval to be ready to archive. + On hot standby then this terminates the backup mode but does not perform + an automatic switch. *************** *** 808,813 **** --- 820,827 ---- If you wish to place a time limit on the execution of pg_stop_backup, set an appropriate statement_timeout value. + On hot standby then this does not perform. If WAL archiving is used, + ensure to complete archiving as far as pg_stop_backup result. *************** *** 851,856 **** --- 865,873 ---- effectively forced on during backup mode.) You must ensure that these steps are carried out in sequence, without any possible overlap, or you will invalidate the backup. + On hot standby, full_page_writes is not effectively forced because hot + standby does not write WAL. you must set 'on' full_page_writes on master + during backup mode. *************** *** 933,938 **** --- 950,967 ---- backup dump is which and how far back the associated WAL files go. It is generally better to follow the continuous archiving procedure above. + + + pg_stop_backup result on hot standby is may be incorrect. But + this value is greater than the correct value. If this value is used in + recovery then a phenomenon that WAL is not enough does not happen. + + + + When you run in hotstandby pg_start_backup, and, if promoted + to master when you run the pg_stop_backup, + pg_stop_backup will be failed. Retake the backup then. + diff -rcN postgresql/src/backend/access/transam/xlog.c postgresql_with_patch/src/backend/access/transam/xlog.c *** postgresql/src/backend/access/transam/xlog.c 2011-09-12 05:19:14.000000000 +0900 --- postgresql_with_patch/src/backend/access/transam/xlog.c 2011-09-13 14:55:01.000000000 +0900 *************** *** 664,670 **** #endif static void pg_start_backup_callback(int code, Datum arg); static bool read_backup_label(XLogRecPtr *checkPointLoc, ! bool *backupEndRequired); static void rm_redo_error_callback(void *arg); static int get_sync_bit(int method); --- 664,670 ---- #endif static void pg_start_backup_callback(int code, Datum arg); static bool read_backup_label(XLogRecPtr *checkPointLoc, ! bool *backupEndRequired, char *backupfromstr); static void rm_redo_error_callback(void *arg); static int get_sync_bit(int method); *************** *** 6023,6028 **** --- 6023,6029 ---- uint32 freespace; TransactionId oldestActiveXID; bool backupEndRequired = false; + char backupfromstr[10]; /* * Read control file and check XLOG status looks valid. *************** *** 6061,6067 **** (errmsg("database system was interrupted while in recovery at log time %s", str_time(ControlFile->checkPointCopy.time)), errhint("If this has occurred more than once some data might be corrupted" ! " and you might need to choose an earlier recovery target."))); else if (ControlFile->state == DB_IN_PRODUCTION) ereport(LOG, (errmsg("database system was interrupted; last known up at %s", --- 6062,6069 ---- (errmsg("database system was interrupted while in recovery at log time %s", str_time(ControlFile->checkPointCopy.time)), errhint("If this has occurred more than once some data might be corrupted" ! " and does not take online backup from hot standby" ! " then you might need to choose an earlier recovery target."))); else if (ControlFile->state == DB_IN_PRODUCTION) ereport(LOG, (errmsg("database system was interrupted; last known up at %s", *************** *** 6156,6162 **** if (StandbyMode) OwnLatch(&XLogCtl->recoveryWakeupLatch); ! if (read_backup_label(&checkPointLoc, &backupEndRequired)) { /* * When a backup_label file is present, we want to roll forward from --- 6158,6164 ---- if (StandbyMode) OwnLatch(&XLogCtl->recoveryWakeupLatch); ! if (read_backup_label(&checkPointLoc, &backupEndRequired, backupfromstr)) { /* * When a backup_label file is present, we want to roll forward from *************** *** 6307,6312 **** --- 6309,6328 ---- volatile XLogCtlData *xlogctl = XLogCtl; /* + * set backupEndPoint at the start if we take online backup from + * hot standby. backupEndPoint is used to distinguish whether the + * backup is taken from master or hot stanby. If backupStartPoint + * and backupEndPoint is invalid then this is meaning the first + * recovery. + */ + if (XLogRecPtrIsInvalid(ControlFile->backupStartPoint) && + XLogRecPtrIsInvalid(ControlFile->backupEndPoint)) + { + if (!XLogRecPtrIsInvalid(ControlFile->minRecoveryPoint)) + ControlFile->backupEndPoint = ControlFile->minRecoveryPoint; + } + + /* * Update pg_control to show that we are recovering and to show the * selected checkpoint as the place we are starting from. We also mark * pg_control with any minimum recovery stop point obtained from a *************** *** 6618,6623 **** --- 6634,6660 ---- error_context_stack = errcontext.previous; /* + * Check whether redo reaches minRecoveryPoint if we take online + * backup from hot standby. Because we can not write backup end + * record when we execute pg_stop_backup under the situation. + */ + if (!XLogRecPtrIsInvalid(ControlFile->backupEndPoint)) + { + if (XLByteLE(ControlFile->backupEndPoint, EndRecPtr)) + { + elog(DEBUG1, "end of backup reached in the control file"); + + LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); + + MemSet(&ControlFile->backupStartPoint, 0, sizeof(XLogRecPtr)); + MemSet(&ControlFile->backupEndPoint, 0, sizeof(XLogRecPtr)); + UpdateControlFile(); + + LWLockRelease(ControlFileLock); + } + } + + /* * Update shared recoveryLastRecPtr after this record has been * replayed. */ *************** *** 8414,8423 **** /* * If we see a shutdown checkpoint while waiting for an end-of-backup * record, the backup was canceled and the end-of-backup record will ! * never arrive. */ if (InArchiveRecovery && ! !XLogRecPtrIsInvalid(ControlFile->backupStartPoint)) ereport(ERROR, (errmsg("online backup was canceled, recovery cannot continue"))); --- 8451,8463 ---- /* * If we see a shutdown checkpoint while waiting for an end-of-backup * record, the backup was canceled and the end-of-backup record will ! * never arrive. If the backup is taken from hot standby then this ! * error is not output because there is a case of shutdown on master ! * during taking online backup from hot standby. */ if (InArchiveRecovery && ! !XLogRecPtrIsInvalid(ControlFile->backupStartPoint) && ! XLogRecPtrIsInvalid(ControlFile->backupEndPoint)) ereport(ERROR, (errmsg("online backup was canceled, recovery cannot continue"))); *************** *** 8880,8885 **** --- 8920,8926 ---- do_pg_start_backup(const char *backupidstr, bool fast, char **labelfile) { bool exclusive = (labelfile == NULL); + bool duringrecovery = false; XLogRecPtr checkpointloc; XLogRecPtr startpoint; pg_time_t stamp_time; *************** *** 8890,8908 **** struct stat stat_buf; FILE *fp; StringInfoData labelfbuf; if (!superuser() && !is_authenticated_user_replication_role()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser or replication role to run a backup"))); if (RecoveryInProgress()) ! ereport(ERROR, ! (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), ! errmsg("recovery is in progress"), ! errhint("WAL control functions cannot be executed during recovery."))); ! if (!XLogIsNeeded()) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("WAL level not sufficient for making an online backup"), --- 8931,8956 ---- struct stat stat_buf; FILE *fp; StringInfoData labelfbuf; + char *backupfromstr = BACKUP_FROM_MASTER; if (!superuser() && !is_authenticated_user_replication_role()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser or replication role to run a backup"))); + /* + * check whether during recovery, and determine a string on backup_label. + * If duringrecovery is true here then the subsequent process on WAL (check + * wal_level, RequestXLogSwitch, forcePageWrites and gotUniqueStartpoint + * by RequestCheckpoint) is skipped because hot standby can not write a wal. + */ if (RecoveryInProgress()) ! { ! duringrecovery = true; ! backupfromstr = BACKUP_FROM_SLAVE; ! } ! if (!XLogIsNeeded() && !duringrecovery) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("WAL level not sufficient for making an online backup"), *************** *** 8925,8931 **** * directory was not included in the base backup and the WAL archive was * cleared too before starting the backup. */ ! RequestXLogSwitch(); /* * Mark backup active in shared memory. We must do full-page WAL writes --- 8973,8980 ---- * directory was not included in the base backup and the WAL archive was * cleared too before starting the backup. */ ! if (!duringrecovery) ! RequestXLogSwitch(); /* * Mark backup active in shared memory. We must do full-page WAL writes *************** *** 8959,8965 **** } else XLogCtl->Insert.nonExclusiveBackups++; ! XLogCtl->Insert.forcePageWrites = true; LWLockRelease(WALInsertLock); /* Ensure we release forcePageWrites if fail below */ --- 9008,9015 ---- } else XLogCtl->Insert.nonExclusiveBackups++; ! if (!duringrecovery) ! XLogCtl->Insert.forcePageWrites = true; LWLockRelease(WALInsertLock); /* Ensure we release forcePageWrites if fail below */ *************** *** 9010,9016 **** gotUniqueStartpoint = true; } LWLockRelease(WALInsertLock); ! } while (!gotUniqueStartpoint); XLByteToSeg(startpoint, _logId, _logSeg); XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg); --- 9060,9066 ---- gotUniqueStartpoint = true; } LWLockRelease(WALInsertLock); ! } while (!gotUniqueStartpoint && !duringrecovery); XLByteToSeg(startpoint, _logId, _logSeg); XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg); *************** *** 9033,9038 **** --- 9083,9089 ---- exclusive ? "pg_start_backup" : "streamed"); appendStringInfo(&labelfbuf, "START TIME: %s\n", strfbuf); appendStringInfo(&labelfbuf, "LABEL: %s\n", backupidstr); + appendStringInfo(&labelfbuf, "FROM: %s\n", backupfromstr); /* * Okay, write the file, or return its contents to caller. *************** *** 9105,9111 **** } if (!XLogCtl->Insert.exclusiveBackup && ! XLogCtl->Insert.nonExclusiveBackups == 0) { XLogCtl->Insert.forcePageWrites = false; } --- 9156,9163 ---- } if (!XLogCtl->Insert.exclusiveBackup && ! XLogCtl->Insert.nonExclusiveBackups == 0 && ! !RecoveryInProgress()) { XLogCtl->Insert.forcePageWrites = false; } *************** *** 9149,9154 **** --- 9201,9207 ---- do_pg_stop_backup(char *labelfile, bool waitforarchive) { bool exclusive = (labelfile == NULL); + bool duringrecovery = false; XLogRecPtr startpoint; XLogRecPtr stoppoint; XLogRecData rdata; *************** *** 9168,9192 **** int waits = 0; bool reported_waiting = false; char *remaining; if (!superuser() && !is_authenticated_user_replication_role()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser or replication role to run a backup")))); if (RecoveryInProgress()) ! ereport(ERROR, ! (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), ! errmsg("recovery is in progress"), ! errhint("WAL control functions cannot be executed during recovery."))); ! if (!XLogIsNeeded()) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("WAL level not sufficient for making an online backup"), errhint("wal_level must be set to \"archive\" or \"hot_standby\" at server start."))); /* * OK to update backup counters and forcePageWrites */ LWLockAcquire(WALInsertLock, LW_EXCLUSIVE); --- 9221,9277 ---- int waits = 0; bool reported_waiting = false; char *remaining; + XLogRecPtr checkPointLoc; + bool backupEndRequired = false; + char backupfromstr[10]; if (!superuser() && !is_authenticated_user_replication_role()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser or replication role to run a backup")))); + /* + * check whether during recovery. If duringrecovery is true here then the + * subsequent process on WAL (check wal_level, forcePageWrites, XLogInsert, + * RequestXLogSwitch, write the backup history file and XLogArchivingActive) + * is skipped because hot standby can not write a wal. + */ if (RecoveryInProgress()) ! duringrecovery = true; ! if (!XLogIsNeeded() && !duringrecovery) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("WAL level not sufficient for making an online backup"), errhint("wal_level must be set to \"archive\" or \"hot_standby\" at server start."))); /* + * backupfromstr is taken from backup_label, which is where we + * execute pg_start_backup on. check whether this state is equals it. + * If read_backup_label function returns error, this function is + * failed by error handling after this. + */ + if (read_backup_label(&checkPointLoc, &backupEndRequired, backupfromstr)) + { + if (duringrecovery == false) + { + if (strcmp(backupfromstr, BACKUP_FROM_MASTER) != 0 || + ControlFile->state != DB_IN_PRODUCTION) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("different state than when pg_start_backup is executed"))); + } + else + { + if (strcmp(backupfromstr, BACKUP_FROM_SLAVE) != 0 || + ControlFile->state != DB_IN_ARCHIVE_RECOVERY) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("different state than when pg_start_backup is executed"))); + } + } + + /* * OK to update backup counters and forcePageWrites */ LWLockAcquire(WALInsertLock, LW_EXCLUSIVE); *************** *** 9205,9211 **** } if (!XLogCtl->Insert.exclusiveBackup && ! XLogCtl->Insert.nonExclusiveBackups == 0) { XLogCtl->Insert.forcePageWrites = false; } --- 9290,9297 ---- } if (!XLogCtl->Insert.exclusiveBackup && ! XLogCtl->Insert.nonExclusiveBackups == 0 && ! !duringrecovery) { XLogCtl->Insert.forcePageWrites = false; } *************** *** 9259,9264 **** --- 9345,9357 ---- } /* + * When pg_stop_backup is excuted on hot standby server, the result + * is minRecoveryPoint in the control file. + */ + if (duringrecovery) + return ControlFile->minRecoveryPoint; + + /* * Read and parse the START WAL LOCATION line (this code is pretty crude, * but we are not expecting any variability in the file format). */ *************** *** 9416,9422 **** XLogCtl->Insert.nonExclusiveBackups--; if (!XLogCtl->Insert.exclusiveBackup && ! XLogCtl->Insert.nonExclusiveBackups == 0) { XLogCtl->Insert.forcePageWrites = false; } --- 9509,9516 ---- XLogCtl->Insert.nonExclusiveBackups--; if (!XLogCtl->Insert.exclusiveBackup && ! XLogCtl->Insert.nonExclusiveBackups == 0 && ! !RecoveryInProgress()) { XLogCtl->Insert.forcePageWrites = false; } *************** *** 9790,9802 **** * streamed backup, *backupEndRequired is set to TRUE. */ static bool ! read_backup_label(XLogRecPtr *checkPointLoc, bool *backupEndRequired) { char startxlogfilename[MAXFNAMELEN]; TimeLineID tli; FILE *lfp; char ch; char backuptype[20]; *backupEndRequired = false; --- 9884,9897 ---- * streamed backup, *backupEndRequired is set to TRUE. */ static bool ! read_backup_label(XLogRecPtr *checkPointLoc, bool *backupEndRequired, char *backupfromstr) { char startxlogfilename[MAXFNAMELEN]; TimeLineID tli; FILE *lfp; char ch; char backuptype[20]; + char strbuff[256]; *backupEndRequired = false; *************** *** 9842,9847 **** --- 9937,9957 ---- *backupEndRequired = true; } + fgets(strbuff, sizeof(strbuff), lfp); /* skip one line */ + fgets(strbuff, sizeof(strbuff), lfp); /* skip one line */ + fgets(strbuff, sizeof(strbuff), lfp); /* skip one line */ + + /* + * Read and parse the FROM line. If not read then output WARNING message + * and set BACKUP_FROM_MASTER. + * + */ + strcpy(backupfromstr, BACKUP_FROM_MASTER); + if (fscanf(lfp, "FROM: %s%c", backupfromstr, &ch) != 2 || ch != '\n') + ereport(WARNING, + (errmsg("loaded old file \"%s\", set backup from \"%s\"", + BACKUP_LABEL_FILE, BACKUP_FROM_MASTER))); + if (ferror(lfp) || FreeFile(lfp)) ereport(FATAL, (errcode_for_file_access(), diff -rcN postgresql/src/backend/postmaster/postmaster.c postgresql_with_patch/src/backend/postmaster/postmaster.c *** postgresql/src/backend/postmaster/postmaster.c 2011-09-12 05:19:14.000000000 +0900 --- postgresql_with_patch/src/backend/postmaster/postmaster.c 2011-09-12 05:24:42.000000000 +0900 *************** *** 287,292 **** --- 287,295 ---- static PMState pmState = PM_INIT; static bool ReachedNormalRunning = false; /* T if we've reached PM_RUN */ + static bool ReachedHotStandbyRunning = false; /* T if we've reached PM_HOT_STANDBY */ + static bool WaitBackupForHotStandby = false; /* T if we've moved from PM_WAIT_READONLY + * to PM_WAIT_BACKUP */ bool ClientAuthInProgress = false; /* T during new-client * authentication */ *************** *** 2825,2831 **** * PM_WAIT_BACKUP state ends when online backup mode is not active. */ if (!BackupInProgress()) ! pmState = PM_WAIT_BACKENDS; } if (pmState == PM_WAIT_READONLY) --- 2828,2845 ---- * PM_WAIT_BACKUP state ends when online backup mode is not active. */ if (!BackupInProgress()) ! { ! /* ! * WaitBackupForHotStandby, this flag is if we execute ! * smart shutdown during takeing online backup from hot standby. ! * If the flag is true then we need to change PM_WAIT_BACKENDS ! * at the root of PM_WAIT_READONLY. ! */ ! if (!WaitBackupForHotStandby) ! pmState = PM_WAIT_BACKENDS; ! else ! pmState = PM_WAIT_READONLY; ! } } if (pmState == PM_WAIT_READONLY) *************** *** 2840,2850 **** */ if (CountChildren(BACKEND_TYPE_NORMAL) == 0) { ! if (StartupPID != 0) ! signal_child(StartupPID, SIGTERM); ! if (WalReceiverPID != 0) ! signal_child(WalReceiverPID, SIGTERM); ! pmState = PM_WAIT_BACKENDS; } } --- 2854,2878 ---- */ if (CountChildren(BACKEND_TYPE_NORMAL) == 0) { ! if (!BackupInProgress()) ! { ! if (StartupPID != 0) ! signal_child(StartupPID, SIGTERM); ! if (WalReceiverPID != 0) ! signal_child(WalReceiverPID, SIGTERM); ! pmState = PM_WAIT_BACKENDS; ! } ! else ! { ! /* ! * This is meaning that we execute smart shutdown during ! * online backup from hot standby. we need to allow the ! * connection to the backend by changing PM_WAIT_BACKUP ! * to execute pg_stop_backup. ! */ ! WaitBackupForHotStandby = true; ! pmState = PM_WAIT_BACKUP; ! } } } *************** *** 2993,3006 **** { /* * Terminate backup mode to avoid recovery after a clean fast ! * shutdown. Since a backup can only be taken during normal ! * running (and not, for example, while running under Hot Standby) ! * it only makes sense to do this if we reached normal running. If ! * we're still in recovery, the backup file is one we're ! * recovering *from*, and we must keep it around so that recovery ! * restarts from the right place. */ ! if (ReachedNormalRunning) CancelBackup(); /* Normal exit from the postmaster is here */ --- 3021,3029 ---- { /* * Terminate backup mode to avoid recovery after a clean fast ! * shutdown if we reached normal running or hot standby. */ ! if (ReachedNormalRunning || ReachedHotStandbyRunning) CancelBackup(); /* Normal exit from the postmaster is here */ *************** *** 4157,4162 **** --- 4180,4186 ---- ereport(LOG, (errmsg("database system is ready to accept read only connections"))); + ReachedHotStandbyRunning = true; pmState = PM_HOT_STANDBY; } diff -rcN postgresql/src/bin/pg_controldata/pg_controldata.c postgresql_with_patch/src/bin/pg_controldata/pg_controldata.c *** postgresql/src/bin/pg_controldata/pg_controldata.c 2011-09-12 05:19:14.000000000 +0900 --- postgresql_with_patch/src/bin/pg_controldata/pg_controldata.c 2011-09-12 05:24:42.000000000 +0900 *************** *** 234,239 **** --- 234,242 ---- ControlFile.backupStartPoint.xrecoff); printf(_("End-of-backup record required: %s\n"), ControlFile.backupEndRequired ? _("yes") : _("no")); + printf(_("Backup end location: %X/%X\n"), + ControlFile.backupEndPoint.xlogid, + ControlFile.backupEndPoint.xrecoff); printf(_("Current wal_level setting: %s\n"), wal_level_str(ControlFile.wal_level)); printf(_("Current max_connections setting: %d\n"), diff -rcN postgresql/src/bin/pg_ctl/pg_ctl.c postgresql_with_patch/src/bin/pg_ctl/pg_ctl.c *** postgresql/src/bin/pg_ctl/pg_ctl.c 2011-09-12 05:19:14.000000000 +0900 --- postgresql_with_patch/src/bin/pg_ctl/pg_ctl.c 2011-09-12 05:24:42.000000000 +0900 *************** *** 882,894 **** { /* * If backup_label exists, an online backup is running. Warn the user ! * that smart shutdown will wait for it to finish. However, if ! * recovery.conf is also present, we're recovering from an online ! * backup instead of performing one. */ if (shutdown_mode == SMART_MODE && ! stat(backup_file, &statbuf) == 0 && ! stat(recovery_file, &statbuf) != 0) { print_msg(_("WARNING: online backup mode is active\n" "Shutdown will not complete until pg_stop_backup() is called.\n\n")); --- 882,891 ---- { /* * If backup_label exists, an online backup is running. Warn the user ! * that smart shutdown will wait for it to finish. */ if (shutdown_mode == SMART_MODE && ! stat(backup_file, &statbuf) == 0) { print_msg(_("WARNING: online backup mode is active\n" "Shutdown will not complete until pg_stop_backup() is called.\n\n")); diff -rcN postgresql/src/bin/pg_resetxlog/pg_resetxlog.c postgresql_with_patch/src/bin/pg_resetxlog/pg_resetxlog.c *** postgresql/src/bin/pg_resetxlog/pg_resetxlog.c 2011-09-12 05:19:14.000000000 +0900 --- postgresql_with_patch/src/bin/pg_resetxlog/pg_resetxlog.c 2011-09-12 05:24:42.000000000 +0900 *************** *** 503,509 **** ControlFile.time = (pg_time_t) time(NULL); ControlFile.checkPoint = ControlFile.checkPointCopy.redo; ! /* minRecoveryPoint and backupStartPoint can be left zero */ ControlFile.wal_level = WAL_LEVEL_MINIMAL; ControlFile.MaxConnections = 100; --- 503,509 ---- ControlFile.time = (pg_time_t) time(NULL); ControlFile.checkPoint = ControlFile.checkPointCopy.redo; ! /* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */ ControlFile.wal_level = WAL_LEVEL_MINIMAL; ControlFile.MaxConnections = 100; *************** *** 638,643 **** --- 638,645 ---- ControlFile.backupStartPoint.xlogid = 0; ControlFile.backupStartPoint.xrecoff = 0; ControlFile.backupEndRequired = false; + ControlFile.backupEndPoint.xlogid = 0; + ControlFile.backupEndPoint.xrecoff = 0; /* * Force the defaults for max_* settings. The values don't really matter diff -rcN postgresql/src/include/access/xlog.h postgresql_with_patch/src/include/access/xlog.h *** postgresql/src/include/access/xlog.h 2011-09-12 05:19:14.000000000 +0900 --- postgresql_with_patch/src/include/access/xlog.h 2011-09-12 05:24:42.000000000 +0900 *************** *** 328,331 **** --- 328,335 ---- #define BACKUP_LABEL_FILE "backup_label" #define BACKUP_LABEL_OLD "backup_label.old" + /* These are written in backup label file */ + #define BACKUP_FROM_MASTER "master" + #define BACKUP_FROM_SLAVE "slave" + #endif /* XLOG_H */ diff -rcN postgresql/src/include/catalog/pg_control.h postgresql_with_patch/src/include/catalog/pg_control.h *** postgresql/src/include/catalog/pg_control.h 2011-09-12 05:19:14.000000000 +0900 --- postgresql_with_patch/src/include/catalog/pg_control.h 2011-09-12 05:24:42.000000000 +0900 *************** *** 143,152 **** --- 143,158 ---- * start up. If it's false, but backupStartPoint is set, a backup_label * file was found at startup but it may have been a leftover from a stray * pg_start_backup() call, not accompanied by pg_stop_backup(). + * + * backupEndPoint is set a same value as minRecoveryPoint at the first + * recovery if the backup is taken from hot standby. It is unset if we + * reach the end of backup. It is not set if the backup is taken from + * normal running. */ XLogRecPtr minRecoveryPoint; XLogRecPtr backupStartPoint; bool backupEndRequired; + XLogRecPtr backupEndPoint; /* * Parameter settings that determine if the WAL can be used for archival