standby_online_backup_04.patch
application/octet-stream
Filename: standby_online_backup_04.patch
Type: application/octet-stream
Part: 0
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-06-30 10:04:48.000000000 +0900
--- postgresql_with_patch/src/backend/access/transam/xlog.c 2011-07-11 18:46:45.000000000 +0900
***************
*** 6284,6289 ****
--- 6284,6303 ----
/* use volatile pointer to prevent code rearrangement */
volatile XLogCtlData *xlogctl = XLogCtl;
+ /*
+ * get minRecoveryPoint before the value is changed for
+ * getting backup on standby server.
+ * check the result, set to pg_control.
+ */
+ XLogRecPtr prevminRecoveryPoint = ControlFile->minRecoveryPoint;
+ if (!ControlFile->backupserver)
+ {
+ if (prevminRecoveryPoint.xlogid == 0 && prevminRecoveryPoint.xrecoff == 0)
+ ControlFile->backupserver = BACKUPSERVER_MASTER;
+ else
+ ControlFile->backupserver = BACKUPSERVER_SLAVE;
+ }
+
/*
* 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
***************
*** 6592,6597 ****
--- 6606,6631 ----
/* Pop the error context stack */
error_context_stack = errcontext.previous;
+ /*
+ * Check whether to reach minRecoveryPoint when getting backup
+ * on standby server.
+ */
+ if (ControlFile->backupserver == BACKUPSERVER_SLAVE)
+ {
+ if (XLByteLE(prevminRecoveryPoint, EndRecPtr))
+ {
+ elog(DEBUG1, "end of backup reached in the control file");
+
+ LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
+
+ MemSet(&ControlFile->backupStartPoint, 0, sizeof(XLogRecPtr));
+ ControlFile->backupserver = BACKUPSERVER_NONE;
+ UpdateControlFile();
+
+ LWLockRelease(ControlFileLock);
+ }
+ }
+
/*
* Update shared recoveryLastRecPtr after this record has been
* replayed.
***************
*** 8512,8517 ****
--- 8546,8552 ----
if (XLByteLT(ControlFile->minRecoveryPoint, lsn))
ControlFile->minRecoveryPoint = lsn;
MemSet(&ControlFile->backupStartPoint, 0, sizeof(XLogRecPtr));
+ ControlFile->backupserver = BACKUPSERVER_NONE;
UpdateControlFile();
LWLockRelease(ControlFileLock);
***************
*** 8845,8850 ****
--- 8880,8886 ----
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;
***************
*** 8862,8871 ****
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,
--- 8898,8904 ----
errmsg("must be superuser or replication role to run a backup")));
if (RecoveryInProgress())
! duringrecovery = true;
if (!XLogIsNeeded())
ereport(ERROR,
***************
*** 8890,8896 ****
* 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
--- 8923,8930 ----
* 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
***************
*** 8924,8930 ****
}
else
XLogCtl->Insert.nonExclusiveBackups++;
! XLogCtl->Insert.forcePageWrites = true;
LWLockRelease(WALInsertLock);
/* Ensure we release forcePageWrites if fail below */
--- 8958,8965 ----
}
else
XLogCtl->Insert.nonExclusiveBackups++;
! if (!duringrecovery)
! XLogCtl->Insert.forcePageWrites = true;
LWLockRelease(WALInsertLock);
/* Ensure we release forcePageWrites if fail below */
***************
*** 9112,9117 ****
--- 9147,9153 ----
do_pg_stop_backup(char *labelfile, bool waitforarchive)
{
bool exclusive = (labelfile == NULL);
+ bool duringrecovery = false;
XLogRecPtr startpoint;
XLogRecPtr stoppoint;
XLogRecData rdata;
***************
*** 9138,9147 ****
(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,
--- 9174,9180 ----
(errmsg("must be superuser or replication role to run a backup"))));
if (RecoveryInProgress())
! duringrecovery = true;
if (!XLogIsNeeded())
ereport(ERROR,
***************
*** 9168,9174 ****
}
if (!XLogCtl->Insert.exclusiveBackup &&
! XLogCtl->Insert.nonExclusiveBackups == 0)
{
XLogCtl->Insert.forcePageWrites = false;
}
--- 9201,9208 ----
}
if (!XLogCtl->Insert.exclusiveBackup &&
! XLogCtl->Insert.nonExclusiveBackups == 0 &&
! !duringrecovery)
{
XLogCtl->Insert.forcePageWrites = false;
}
***************
*** 9222,9227 ****
--- 9256,9268 ----
}
/*
+ * 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).
*/
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-06-30 10:04:48.000000000 +0900
--- postgresql_with_patch/src/bin/pg_controldata/pg_controldata.c 2011-07-07 18:23:22.000000000 +0900
***************
*** 86,91 ****
--- 86,105 ----
return _("unrecognized wal_level");
}
+ static const char *
+ backupserver_str(BackupServer backupserver)
+ {
+ switch (backupserver)
+ {
+ case BACKUPSERVER_NONE:
+ return "none";
+ case BACKUPSERVER_MASTER:
+ return "master";
+ case BACKUPSERVER_SLAVE:
+ return "slave";
+ }
+ return _("unrecognized backupserver");
+ }
int
main(int argc, char *argv[])
***************
*** 232,237 ****
--- 246,253 ----
printf(_("Backup start location: %X/%X\n"),
ControlFile.backupStartPoint.xlogid,
ControlFile.backupStartPoint.xrecoff);
+ printf(_("Backup from: %s\n"),
+ backupserver_str(ControlFile.backupserver));
printf(_("Current wal_level setting: %s\n"),
wal_level_str(ControlFile.wal_level));
printf(_("Current max_connections setting: %d\n"),
diff -rcN postgresql/src/include/access/xlog.h postgresql_with_patch/src/include/access/xlog.h
*** postgresql/src/include/access/xlog.h 2011-06-30 10:04:48.000000000 +0900
--- postgresql_with_patch/src/include/access/xlog.h 2011-07-07 15:32:57.000000000 +0900
***************
*** 209,214 ****
--- 209,222 ----
} WalLevel;
extern int wal_level;
+ /* where to get backup */
+ typedef enum BackupServer
+ {
+ BACKUPSERVER_NONE = 0,
+ BACKUPSERVER_MASTER,
+ BACKUPSERVER_SLAVE,
+ } BackupServer;
+
#define XLogArchivingActive() (XLogArchiveMode && wal_level >= WAL_LEVEL_ARCHIVE)
#define XLogArchiveCommandSet() (XLogArchiveCommand[0] != '\0')
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-06-30 10:04:48.000000000 +0900
--- postgresql_with_patch/src/include/catalog/pg_control.h 2011-07-11 14:34:09.000000000 +0900
***************
*** 142,147 ****
--- 142,156 ----
XLogRecPtr backupStartPoint;
/*
+ * backupserver is used while postgresql is in recovery mode to
+ * store the location of where the backup comes from.
+ * When Postgres starts recovery operations
+ * it is set to "none". During recovery it is updated to either "master", or "slave".
+ * When recovery operations finish it is updated back to "none".
+ */
+ int backupserver;
+
+ /*
* Parameter settings that determine if the WAL can be used for archival
* or hot standby.
*/