standby_online_backup_01.patch

application/octet-stream

Filename: standby_online_backup_01.patch
Type: application/octet-stream
Part: 0
Message: Online base backup from the hot-standby

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: context
File+
src/backend/access/transam/xlog.c 147 4
src/bin/pg_controldata/pg_controldata.c 6 0
src/include/catalog/pg_control.h 21 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-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.
  	 */