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