|
7 | 7 | * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
8 | 8 | * Portions Copyright (c) 1994, Regents of the University of California
|
9 | 9 | *
|
10 |
| - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.356 2010/01/02 16:57:35 momjian Exp $ |
| 10 | + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.357 2010/01/04 12:50:49 heikki Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
@@ -515,8 +515,7 @@ static void xlog_outrec(StringInfo buf, XLogRecord *record);
|
515 | 515 | #endif
|
516 | 516 | staticvoidissue_xlog_fsync(void);
|
517 | 517 | staticvoidpg_start_backup_callback(intcode,Datumarg);
|
518 |
| -staticboolread_backup_label(XLogRecPtr*checkPointLoc, |
519 |
| -XLogRecPtr*minRecoveryLoc); |
| 518 | +staticboolread_backup_label(XLogRecPtr*checkPointLoc); |
520 | 519 | staticvoidrm_redo_error_callback(void*arg);
|
521 | 520 | staticintget_sync_bit(intmethod);
|
522 | 521 |
|
@@ -5355,7 +5354,6 @@ StartupXLOG(void)
|
5355 | 5354 | boolhaveBackupLabel= false;
|
5356 | 5355 | XLogRecPtrRecPtr,
|
5357 | 5356 | checkPointLoc,
|
5358 |
| -backupStopLoc, |
5359 | 5357 | EndOfLog;
|
5360 | 5358 | uint32endLogId;
|
5361 | 5359 | uint32endLogSeg;
|
@@ -5454,7 +5452,7 @@ StartupXLOG(void)
|
5454 | 5452 | recoveryTargetTLI,
|
5455 | 5453 | ControlFile->checkPointCopy.ThisTimeLineID)));
|
5456 | 5454 |
|
5457 |
| -if (read_backup_label(&checkPointLoc,&backupStopLoc)) |
| 5455 | +if (read_backup_label(&checkPointLoc)) |
5458 | 5456 | {
|
5459 | 5457 | /*
|
5460 | 5458 | * When a backup_label file is present, we want to roll forward from
|
@@ -5597,11 +5595,23 @@ StartupXLOG(void)
|
5597 | 5595 | ControlFile->prevCheckPoint=ControlFile->checkPoint;
|
5598 | 5596 | ControlFile->checkPoint=checkPointLoc;
|
5599 | 5597 | ControlFile->checkPointCopy=checkPoint;
|
5600 |
| -if (backupStopLoc.xlogid!=0||backupStopLoc.xrecoff!=0) |
| 5598 | +if (InArchiveRecovery) |
| 5599 | +{ |
| 5600 | +/* initialize minRecoveryPoint if not set yet */ |
| 5601 | +if (XLByteLT(ControlFile->minRecoveryPoint,checkPoint.redo)) |
| 5602 | +ControlFile->minRecoveryPoint=checkPoint.redo; |
| 5603 | +} |
| 5604 | +else |
5601 | 5605 | {
|
5602 |
| -if (XLByteLT(ControlFile->minRecoveryPoint,backupStopLoc)) |
5603 |
| -ControlFile->minRecoveryPoint=backupStopLoc; |
| 5606 | +XLogRecPtrInvalidXLogRecPtr= {0,0}; |
| 5607 | +ControlFile->minRecoveryPoint=InvalidXLogRecPtr; |
5604 | 5608 | }
|
| 5609 | +/* |
| 5610 | + * set backupStartupPoint if we're starting archive recovery from a |
| 5611 | + * base backup |
| 5612 | + */ |
| 5613 | +if (haveBackupLabel) |
| 5614 | +ControlFile->backupStartPoint=checkPoint.redo; |
5605 | 5615 | ControlFile->time= (pg_time_t)time(NULL);
|
5606 | 5616 | /* No need to hold ControlFileLock yet, we aren't up far enough */
|
5607 | 5617 | UpdateControlFile();
|
@@ -5703,15 +5713,9 @@ StartupXLOG(void)
|
5703 | 5713 |
|
5704 | 5714 | InRedo= true;
|
5705 | 5715 |
|
5706 |
| -if (minRecoveryPoint.xlogid==0&&minRecoveryPoint.xrecoff==0) |
5707 |
| -ereport(LOG, |
5708 |
| -(errmsg("redo starts at %X/%X", |
5709 |
| -ReadRecPtr.xlogid,ReadRecPtr.xrecoff))); |
5710 |
| -else |
5711 |
| -ereport(LOG, |
5712 |
| -(errmsg("redo starts at %X/%X, consistency will be reached at %X/%X", |
5713 |
| -ReadRecPtr.xlogid,ReadRecPtr.xrecoff, |
5714 |
| -minRecoveryPoint.xlogid,minRecoveryPoint.xrecoff))); |
| 5716 | +ereport(LOG, |
| 5717 | +(errmsg("redo starts at %X/%X", |
| 5718 | +ReadRecPtr.xlogid,ReadRecPtr.xrecoff))); |
5715 | 5719 |
|
5716 | 5720 | /*
|
5717 | 5721 | * Let postmaster know we've started redo now, so that it can
|
@@ -5771,7 +5775,8 @@ StartupXLOG(void)
|
5771 | 5775 | * Have we passed our safe starting point?
|
5772 | 5776 | */
|
5773 | 5777 | if (!reachedMinRecoveryPoint&&
|
5774 |
| -XLByteLE(minRecoveryPoint,EndRecPtr)) |
| 5778 | +XLByteLE(minRecoveryPoint,EndRecPtr)&& |
| 5779 | +XLogRecPtrIsInvalid(ControlFile->backupStartPoint)) |
5775 | 5780 | {
|
5776 | 5781 | reachedMinRecoveryPoint= true;
|
5777 | 5782 | ereport(LOG,
|
@@ -5877,7 +5882,9 @@ StartupXLOG(void)
|
5877 | 5882 | * be further ahead --- ControlFile->minRecoveryPoint cannot have been
|
5878 | 5883 | * advanced beyond the WAL we processed.
|
5879 | 5884 | */
|
5880 |
| -if (InRecovery&&XLByteLT(EndOfLog,minRecoveryPoint)) |
| 5885 | +if (InArchiveRecovery&& |
| 5886 | +(XLByteLT(EndOfLog,minRecoveryPoint)|| |
| 5887 | + !XLogRecPtrIsInvalid(ControlFile->backupStartPoint))) |
5881 | 5888 | {
|
5882 | 5889 | if (reachedStopPoint)/* stopped because of stop request */
|
5883 | 5890 | ereport(FATAL,
|
@@ -7312,6 +7319,32 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
|
7312 | 7319 | {
|
7313 | 7320 | /* nothing to do here */
|
7314 | 7321 | }
|
| 7322 | +elseif (info==XLOG_BACKUP_END) |
| 7323 | +{ |
| 7324 | +XLogRecPtrstartpoint; |
| 7325 | +memcpy(&startpoint,XLogRecGetData(record),sizeof(startpoint)); |
| 7326 | + |
| 7327 | +if (XLByteEQ(ControlFile->backupStartPoint,startpoint)) |
| 7328 | +{ |
| 7329 | +/* |
| 7330 | + * We have reached the end of base backup, the point where |
| 7331 | + * pg_stop_backup() was done. The data on disk is now consistent. |
| 7332 | + * Reset backupStartPoint, and update minRecoveryPoint to make |
| 7333 | + * sure we don't allow starting up at an earlier point even if |
| 7334 | + * recovery is stopped and restarted soon after this. |
| 7335 | + */ |
| 7336 | +elog(DEBUG1,"end of backup reached"); |
| 7337 | + |
| 7338 | +LWLockAcquire(ControlFileLock,LW_EXCLUSIVE); |
| 7339 | + |
| 7340 | +if (XLByteLT(ControlFile->minRecoveryPoint,lsn)) |
| 7341 | +ControlFile->minRecoveryPoint=lsn; |
| 7342 | +MemSet(&ControlFile->backupStartPoint,0,sizeof(XLogRecPtr)); |
| 7343 | +UpdateControlFile(); |
| 7344 | + |
| 7345 | +LWLockRelease(ControlFileLock); |
| 7346 | +} |
| 7347 | +} |
7315 | 7348 | }
|
7316 | 7349 |
|
7317 | 7350 | void
|
@@ -7353,6 +7386,14 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
|
7353 | 7386 | {
|
7354 | 7387 | appendStringInfo(buf,"xlog switch");
|
7355 | 7388 | }
|
| 7389 | +elseif (info==XLOG_BACKUP_END) |
| 7390 | +{ |
| 7391 | +XLogRecPtrstartpoint; |
| 7392 | + |
| 7393 | +memcpy(&startpoint,rec,sizeof(XLogRecPtr)); |
| 7394 | +appendStringInfo(buf,"backup end: %X/%X", |
| 7395 | +startpoint.xlogid,startpoint.xrecoff); |
| 7396 | +} |
7356 | 7397 | else
|
7357 | 7398 | appendStringInfo(buf,"UNKNOWN");
|
7358 | 7399 | }
|
@@ -7688,17 +7729,22 @@ pg_start_backup_callback(int code, Datum arg)
|
7688 | 7729 | /*
|
7689 | 7730 | * pg_stop_backup: finish taking an on-line backup dump
|
7690 | 7731 | *
|
7691 |
| - * We remove the backup label file created by pg_start_backup, and instead |
7692 |
| - * create a backup history file in pg_xlog (whence it will immediately be |
7693 |
| - * archived). The backup history file contains the same info found in |
7694 |
| - * the label file, plus the backup-end time and WAL location. |
| 7732 | + * We write an end-of-backup WAL record, and remove the backup label file |
| 7733 | + * created by pg_start_backup, creating a backup history file in pg_xlog |
| 7734 | + * instead (whence it will immediately be archived). The backup history file |
| 7735 | + * contains the same info found in the label file, plus the backup-end time |
| 7736 | + * and WAL location. Before 8.5, the backup-end time was read from the backup |
| 7737 | + * history file at the beginning of archive recovery, but we now use the WAL |
| 7738 | + * record for that and the file is for informational and debug purposes only. |
| 7739 | + * |
7695 | 7740 | * Note: different from CancelBackup which just cancels online backup mode.
|
7696 | 7741 | */
|
7697 | 7742 | Datum
|
7698 | 7743 | pg_stop_backup(PG_FUNCTION_ARGS)
|
7699 | 7744 | {
|
7700 | 7745 | XLogRecPtrstartpoint;
|
7701 | 7746 | XLogRecPtrstoppoint;
|
| 7747 | +XLogRecDatardata; |
7702 | 7748 | pg_time_tstamp_time;
|
7703 | 7749 | charstrfbuf[128];
|
7704 | 7750 | charhistfilepath[MAXPGPATH];
|
@@ -7739,22 +7785,6 @@ pg_stop_backup(PG_FUNCTION_ARGS)
|
7739 | 7785 | XLogCtl->Insert.forcePageWrites= false;
|
7740 | 7786 | LWLockRelease(WALInsertLock);
|
7741 | 7787 |
|
7742 |
| -/* |
7743 |
| - * Force a switch to a new xlog segment file, so that the backup is valid |
7744 |
| - * as soon as archiver moves out the current segment file. We'll report |
7745 |
| - * the end address of the XLOG SWITCH record as the backup stopping point. |
7746 |
| - */ |
7747 |
| -stoppoint=RequestXLogSwitch(); |
7748 |
| - |
7749 |
| -XLByteToSeg(stoppoint,_logId,_logSeg); |
7750 |
| -XLogFileName(stopxlogfilename,ThisTimeLineID,_logId,_logSeg); |
7751 |
| - |
7752 |
| -/* Use the log timezone here, not the session timezone */ |
7753 |
| -stamp_time= (pg_time_t)time(NULL); |
7754 |
| -pg_strftime(strfbuf,sizeof(strfbuf), |
7755 |
| -"%Y-%m-%d %H:%M:%S %Z", |
7756 |
| -pg_localtime(&stamp_time,log_timezone)); |
7757 |
| - |
7758 | 7788 | /*
|
7759 | 7789 | * Open the existing label file
|
7760 | 7790 | */
|
@@ -7782,6 +7812,30 @@ pg_stop_backup(PG_FUNCTION_ARGS)
|
7782 | 7812 | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
7783 | 7813 | errmsg("invalid data in file \"%s\"",BACKUP_LABEL_FILE)));
|
7784 | 7814 |
|
| 7815 | +/* |
| 7816 | + * Write the backup-end xlog record |
| 7817 | + */ |
| 7818 | +rdata.data= (char*) (&startpoint); |
| 7819 | +rdata.len=sizeof(startpoint); |
| 7820 | +rdata.buffer=InvalidBuffer; |
| 7821 | +rdata.next=NULL; |
| 7822 | +stoppoint=XLogInsert(RM_XLOG_ID,XLOG_BACKUP_END,&rdata); |
| 7823 | + |
| 7824 | +/* |
| 7825 | + * Force a switch to a new xlog segment file, so that the backup is valid |
| 7826 | + * as soon as archiver moves out the current segment file. |
| 7827 | + */ |
| 7828 | +RequestXLogSwitch(); |
| 7829 | + |
| 7830 | +XLByteToSeg(stoppoint,_logId,_logSeg); |
| 7831 | +XLogFileName(stopxlogfilename,ThisTimeLineID,_logId,_logSeg); |
| 7832 | + |
| 7833 | +/* Use the log timezone here, not the session timezone */ |
| 7834 | +stamp_time= (pg_time_t)time(NULL); |
| 7835 | +pg_strftime(strfbuf,sizeof(strfbuf), |
| 7836 | +"%Y-%m-%d %H:%M:%S %Z", |
| 7837 | +pg_localtime(&stamp_time,log_timezone)); |
| 7838 | + |
7785 | 7839 | /*
|
7786 | 7840 | * Write the backup history file
|
7787 | 7841 | */
|
@@ -8088,33 +8142,18 @@ pg_xlogfile_name(PG_FUNCTION_ARGS)
|
8088 | 8142 | * later than the start of the dump, and so if we rely on it as the start
|
8089 | 8143 | * point, we will fail to restore a consistent database state.
|
8090 | 8144 | *
|
8091 |
| - * We also attempt to retrieve the corresponding backup history file. |
8092 |
| - * If successful, set *minRecoveryLoc to constrain valid PITR stopping |
8093 |
| - * points. |
8094 |
| - * |
8095 | 8145 | * Returns TRUE if a backup_label was found (and fills the checkpoint
|
8096 | 8146 | * location into *checkPointLoc); returns FALSE if not.
|
8097 | 8147 | */
|
8098 | 8148 | staticbool
|
8099 |
| -read_backup_label(XLogRecPtr*checkPointLoc,XLogRecPtr*minRecoveryLoc) |
| 8149 | +read_backup_label(XLogRecPtr*checkPointLoc) |
8100 | 8150 | {
|
8101 | 8151 | XLogRecPtrstartpoint;
|
8102 |
| -XLogRecPtrstoppoint; |
8103 |
| -charhistfilename[MAXFNAMELEN]; |
8104 |
| -charhistfilepath[MAXPGPATH]; |
8105 | 8152 | charstartxlogfilename[MAXFNAMELEN];
|
8106 |
| -charstopxlogfilename[MAXFNAMELEN]; |
8107 | 8153 | TimeLineIDtli;
|
8108 |
| -uint32_logId; |
8109 |
| -uint32_logSeg; |
8110 | 8154 | FILE*lfp;
|
8111 |
| -FILE*fp; |
8112 | 8155 | charch;
|
8113 | 8156 |
|
8114 |
| -/* Default is to not constrain recovery stop point */ |
8115 |
| -minRecoveryLoc->xlogid=0; |
8116 |
| -minRecoveryLoc->xrecoff=0; |
8117 |
| - |
8118 | 8157 | /*
|
8119 | 8158 | * See if label file is present
|
8120 | 8159 | */
|
@@ -8152,45 +8191,6 @@ read_backup_label(XLogRecPtr *checkPointLoc, XLogRecPtr *minRecoveryLoc)
|
8152 | 8191 | errmsg("could not read file \"%s\": %m",
|
8153 | 8192 | BACKUP_LABEL_FILE)));
|
8154 | 8193 |
|
8155 |
| -/* |
8156 |
| - * Try to retrieve the backup history file (no error if we can't) |
8157 |
| - */ |
8158 |
| -XLByteToSeg(startpoint,_logId,_logSeg); |
8159 |
| -BackupHistoryFileName(histfilename,tli,_logId,_logSeg, |
8160 |
| -startpoint.xrecoff %XLogSegSize); |
8161 |
| - |
8162 |
| -if (InArchiveRecovery) |
8163 |
| -RestoreArchivedFile(histfilepath,histfilename,"RECOVERYHISTORY",0); |
8164 |
| -else |
8165 |
| -BackupHistoryFilePath(histfilepath,tli,_logId,_logSeg, |
8166 |
| -startpoint.xrecoff %XLogSegSize); |
8167 |
| - |
8168 |
| -fp=AllocateFile(histfilepath,"r"); |
8169 |
| -if (fp) |
8170 |
| -{ |
8171 |
| -/* |
8172 |
| - * Parse history file to identify stop point. |
8173 |
| - */ |
8174 |
| -if (fscanf(fp,"START WAL LOCATION: %X/%X (file %24s)%c", |
8175 |
| -&startpoint.xlogid,&startpoint.xrecoff,startxlogfilename, |
8176 |
| -&ch)!=4||ch!='\n') |
8177 |
| -ereport(FATAL, |
8178 |
| -(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
8179 |
| -errmsg("invalid data in file \"%s\"",histfilename))); |
8180 |
| -if (fscanf(fp,"STOP WAL LOCATION: %X/%X (file %24s)%c", |
8181 |
| -&stoppoint.xlogid,&stoppoint.xrecoff,stopxlogfilename, |
8182 |
| -&ch)!=4||ch!='\n') |
8183 |
| -ereport(FATAL, |
8184 |
| -(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
8185 |
| -errmsg("invalid data in file \"%s\"",histfilename))); |
8186 |
| -*minRecoveryLoc=stoppoint; |
8187 |
| -if (ferror(fp)||FreeFile(fp)) |
8188 |
| -ereport(FATAL, |
8189 |
| -(errcode_for_file_access(), |
8190 |
| -errmsg("could not read file \"%s\": %m", |
8191 |
| -histfilepath))); |
8192 |
| -} |
8193 |
| - |
8194 | 8194 | return true;
|
8195 | 8195 | }
|
8196 | 8196 |
|
|