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-13 04:29:59.000000000 +0900 --- postgresql_with_patch/src/backend/access/transam/xlog.c 2011-06-14 03:50:03.000000000 +0900 *************** *** 556,561 **** --- 556,564 ---- static bool updateMinRecoveryPoint = true; static bool reachedMinRecoveryPoint = false; + /* End of backup reached by backup history file */ + static bool reachedBackuphistStoppoint = false; + static bool InRedo = false; /* Have we launched bgwriter during recovery? */ *************** *** 659,665 **** static void xlog_outrec(StringInfo buf, XLogRecord *record); #endif static void pg_start_backup_callback(int code, Datum arg); ! static bool read_backup_label(XLogRecPtr *checkPointLoc); static void rm_redo_error_callback(void *arg); static int get_sync_bit(int method); --- 662,668 ---- static void xlog_outrec(StringInfo buf, XLogRecord *record); #endif static void pg_start_backup_callback(int code, Datum arg); ! static bool read_backup_label(XLogRecPtr *checkPointLoc, XLogRecPtr *backupStartLoc, XLogRecPtr *backupEndLoc); static void rm_redo_error_callback(void *arg); static int get_sync_bit(int method); *************** *** 5989,5994 **** --- 5992,5999 ---- bool haveBackupLabel = false; XLogRecPtr RecPtr, checkPointLoc, + backupStartLoc = {0 ,0}, + backupEndLoc = {0 ,0}, EndOfLog; uint32 endLogId; uint32 endLogSeg; *************** *** 6128,6134 **** if (StandbyMode) OwnLatch(&XLogCtl->recoveryWakeupLatch); ! if (read_backup_label(&checkPointLoc)) { /* * When a backup_label file is present, we want to roll forward from --- 6133,6139 ---- if (StandbyMode) OwnLatch(&XLogCtl->recoveryWakeupLatch); ! if (read_backup_label(&checkPointLoc, &backupStartLoc, &backupEndLoc)) { /* * When a backup_label file is present, we want to roll forward from *************** *** 6165,6170 **** --- 6170,6185 ---- errhint("If you are not restoring from a backup, try removing the file \"%s/backup_label\".", DataDir))); wasShutdown = false; /* keep compiler quiet */ } + + /* + * Set up values of backup history file to controlfile. + */ + LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); + ControlFile->backuphistStartPoint = backupStartLoc; + ControlFile->backuphistEndPoint = backupEndLoc; + UpdateControlFile(); + LWLockRelease(ControlFileLock); + /* set flag to delete it later */ haveBackupLabel = true; } *************** *** 6209,6214 **** --- 6224,6236 ---- } memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint)); wasShutdown = (record->xl_info == XLOG_CHECKPOINT_SHUTDOWN); + + /* + * Use values of controlfile because backup history file was not + * able to be read. + */ + backupStartLoc = ControlFile->backuphistStartPoint; + backupEndLoc = ControlFile->backuphistEndPoint; } LastRec = RecPtr = checkPointLoc; *************** *** 6586,6591 **** --- 6608,6635 ---- /* Pop the error context stack */ error_context_stack = errcontext.previous; + /* + * Check whether to reach backupEndLoc when backup history + * file was read. + */ + if (backupEndLoc.xlogid != 0 || backupEndLoc.xrecoff != 0) + { + if (XLByteEQ(backupEndLoc, EndRecPtr)) + { + reachedBackuphistStoppoint = true; + elog(DEBUG1, "end of backup reached by backup history file"); + + LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); + + if (XLByteLT(ControlFile->minRecoveryPoint, EndRecPtr)) + ControlFile->minRecoveryPoint = EndRecPtr; + MemSet(&ControlFile->backupStartPoint, 0, sizeof(XLogRecPtr)); + UpdateControlFile(); + + LWLockRelease(ControlFileLock); + } + } + /* * Update shared recoveryLastRecPtr after this record has been * replayed. *************** *** 6945,6951 **** */ if (!reachedMinRecoveryPoint && XLByteLE(minRecoveryPoint, EndRecPtr) && ! XLogRecPtrIsInvalid(ControlFile->backupStartPoint)) { reachedMinRecoveryPoint = true; ereport(LOG, --- 6989,6996 ---- */ if (!reachedMinRecoveryPoint && XLByteLE(minRecoveryPoint, EndRecPtr) && ! (XLogRecPtrIsInvalid(ControlFile->backupStartPoint) || ! reachedBackuphistStoppoint == true)) { reachedMinRecoveryPoint = true; ereport(LOG, *************** *** 8492,8497 **** --- 8537,8588 ---- memcpy(&startpoint, XLogRecGetData(record), sizeof(startpoint)); + /* + * Check whether backup history file is correct when it was read. + * + * When backup-end record reached and backuphistEndPoint did not reach, + * check whether backuphistEndPoint is correct. + * + * When backup-end record reached and backuphistEndPoint reached, + * check whether check target, and check whether backuphistEndPoint + * and lsn are equal. if not , stop startup process , because if has + * already become active hot standby. + */ + if (ControlFile->backuphistEndPoint.xlogid != 0 || ControlFile->backuphistEndPoint.xrecoff != 0) + { + if (!reachedBackuphistStoppoint) + { + if (!XLByteEQ(ControlFile->backuphistEndPoint, lsn)) + ereport(WARNING, + (errmsg("backup-end record's location isn't \"STOP WAL LOCATION\" of backup history file"))); + + LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); + MemSet(&ControlFile->backuphistStartPoint, 0, sizeof(XLogRecPtr)); + MemSet(&ControlFile->backuphistEndPoint, 0, sizeof(XLogRecPtr)); + UpdateControlFile(); + LWLockRelease(ControlFileLock); + } + else + { + if (XLByteEQ(ControlFile->backuphistStartPoint, startpoint)) + { + if(!XLByteEQ(ControlFile->backuphistEndPoint, lsn)) + ereport(FATAL, + (errmsg("backup-end record's data isn't \"START WAL LOCATION\" of backup history file"))); + else + { + reachedBackuphistStoppoint = false; + + LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); + MemSet(&ControlFile->backuphistStartPoint, 0, sizeof(XLogRecPtr)); + MemSet(&ControlFile->backuphistEndPoint, 0, sizeof(XLogRecPtr)); + UpdateControlFile(); + LWLockRelease(ControlFileLock); + } + } + } + } + if (XLByteEQ(ControlFile->backupStartPoint, startpoint)) { /* *************** *** 9717,9732 **** * later than the start of the dump, and so if we rely on it as the start * point, we will fail to restore a consistent database state. * * Returns TRUE if a backup_label was found (and fills the checkpoint * location and its REDO location into *checkPointLoc and RedoStartLSN, * respectively); returns FALSE if not. */ static bool ! read_backup_label(XLogRecPtr *checkPointLoc) { char startxlogfilename[MAXFNAMELEN]; TimeLineID tli; FILE *lfp; char ch; /* --- 9808,9835 ---- * later than the start of the dump, and so if we rely on it as the start * point, we will fail to restore a consistent database state. * + * We also attempt to retrieve the corresponding backup history file. + * If successful, set *backupStartLoc and *backupEndLoc to check to reach + * backup end location by values of backup history file. In the future, + * it is scheduled to use it to acquire online base backup from the hot + * standby. + * * Returns TRUE if a backup_label was found (and fills the checkpoint * location and its REDO location into *checkPointLoc and RedoStartLSN, * respectively); returns FALSE if not. */ static bool ! read_backup_label(XLogRecPtr *checkPointLoc, XLogRecPtr *backupStartLoc, XLogRecPtr *backupEndLoc) { + char histfilename[MAXFNAMELEN]; + char histfilepath[MAXPGPATH]; char startxlogfilename[MAXFNAMELEN]; + char stopxlogfilename[MAXFNAMELEN]; TimeLineID tli; + uint32 _logId; + uint32 _logSeg; FILE *lfp; + FILE *fp; char ch; /* *************** *** 9766,9771 **** --- 9869,9914 ---- errmsg("could not read file \"%s\": %m", BACKUP_LABEL_FILE))); + /* + * See if backup history file is present. + * If label file is not present, this logic doesn't pass. + */ + XLByteToSeg(RedoStartLSN, _logId, _logSeg); + BackupHistoryFileName(histfilename, tli, _logId, _logSeg, + RedoStartLSN.xrecoff % XLogSegSize); + if (InArchiveRecovery) + RestoreArchivedFile(histfilepath, histfilename, "RECOVERYHISTORY", 0); + else + BackupHistoryFilePath(histfilepath, tli, _logId, _logSeg, + RedoStartLSN.xrecoff % XLogSegSize); + + fp = AllocateFile(histfilepath, "r"); + if (fp) + { + if (fscanf(fp, "START WAL LOCATION: %X/%X (file %08X%16s)%c", + &backupStartLoc->xlogid, &backupStartLoc->xrecoff, &tli, startxlogfilename, + &ch) != 5 || ch != '\n') + ereport(FATAL, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("invalid data in file \"%s\"", histfilename))); + /* histfilename == START WAL LOCATION*/ + if (!XLByteEQ(RedoStartLSN, *backupStartLoc)) + ereport(ERROR, + (errmsg("wrong \"START WAL LOCATION\" of backup history file \"%s\"", histfilename))); + + if (fscanf(fp, "STOP WAL LOCATION: %X/%X (file %08X%16s)%c", + &backupEndLoc->xlogid, &backupEndLoc->xrecoff, &tli, stopxlogfilename, + &ch) != 5 || ch != '\n') + ereport(FATAL, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("invalid data in file \"%s\"", histfilename))); + if (ferror(fp) || FreeFile(fp)) + ereport(FATAL, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", + histfilepath))); + } + return true; } 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-13 04:29:59.000000000 +0900 --- postgresql_with_patch/src/bin/pg_controldata/pg_controldata.c 2011-06-14 00:01:17.000000000 +0900 *************** *** 232,237 **** --- 232,243 ---- printf(_("Backup start location: %X/%X\n"), ControlFile.backupStartPoint.xlogid, ControlFile.backupStartPoint.xrecoff); + printf(_("Backup history file's start location: %X/%X\n"), + ControlFile.backuphistStartPoint.xlogid, + ControlFile.backuphistStartPoint.xrecoff); + printf(_("Backup history file's stop location: %X/%X\n"), + ControlFile.backuphistEndPoint.xlogid, + ControlFile.backuphistEndPoint.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/include/catalog/pg_control.h postgresql_with_patch/src/include/catalog/pg_control.h *** postgresql/src/include/catalog/pg_control.h 2011-06-13 04:29:59.000000000 +0900 --- postgresql_with_patch/src/include/catalog/pg_control.h 2011-06-14 14:45:15.000000000 +0900 *************** *** 142,147 **** --- 142,168 ---- XLogRecPtr backupStartPoint; /* + * Startup process keeps backup history file's "START WAL LOCATION" and + * "STOP WAL LOCATION" these two values if it reads backup history file. + * It keeps these two values because it is necessary when startup process + * begins without reading backup label. In the future, it is scheduled + * to use these two values to acquire online base backup from the hot + * standby. + * + * backuphistStartPoint is updated when backup history file is read on + * starting up, and backuphistStartPoint is checked with backup-end record. + * if backup history file is not read , backuphistStartPoint is zero. + * Then, the check by backup history file is not done. When the check is + * completed, it becomes zero. + * + * backuphistEndPoint is updated when backup history file is read on + * starting up, and backuphistEndPoint specifies backup end location. + * Its update is similar to backuphistStartPoint. + */ + XLogRecPtr backuphistStartPoint; + XLogRecPtr backuphistEndPoint; + + /* * Parameter settings that determine if the WAL can be used for archival * or hot standby. */