On Mon, Oct 3, 2011 at 4:32 PM, Simon Riggs <si...@2ndquadrant.com> wrote:
>> I don't think this should use the rm_safe_restartpoint machinery. As you
>> said, it's not tied to any specific resource manager. And I've actually been
>> thinking that we will get rid of rm_safe_restartpoint altogether in the
>> future. The two things that still use it are the b-tree and gin, and I'd
>> like to change both of those to not require any post-recovery cleanup step
>> to finish multi-page operations, similar to what I did with GiST in 9.1.
>
> I thought that was quite neat doing it that way, but there's no
> specific reason to do it that way I guess. If you're happy to rewrite
> the patch then I guess we're OK.
>
> I certainly would like to get rid of rm_safe_restartpoint in the
> longer term, hopefully sooner.

Though Heikki might be already working on that,... anyway,
the attached patch is the version which doesn't use rm_safe_restartpoint
machinery.

Regards,

-- 
Fujii Masao
NIPPON TELEGRAPH AND TELEPHONE CORPORATION
NTT Open Source Software Center
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 557,563 **** static TimeLineID lastPageTLI = 0;
  static XLogRecPtr minRecoveryPoint;		/* local copy of
  										 * ControlFile->minRecoveryPoint */
  static bool updateMinRecoveryPoint = true;
! static bool reachedMinRecoveryPoint = false;
  
  static bool InRedo = false;
  
--- 557,563 ----
  static XLogRecPtr minRecoveryPoint;		/* local copy of
  										 * ControlFile->minRecoveryPoint */
  static bool updateMinRecoveryPoint = true;
! bool reachedMinRecoveryPoint = false;
  
  static bool InRedo = false;
  
***************
*** 6841,6852 **** StartupXLOG(void)
  		LocalXLogInsertAllowed = -1;
  
  		/*
- 		 * Check to see if the XLOG sequence contained any unresolved
- 		 * references to uninitialized pages.
- 		 */
- 		XLogCheckInvalidPages();
- 
- 		/*
  		 * Perform a checkpoint to update all our recovery activity to disk.
  		 *
  		 * Note that we write a shutdown checkpoint rather than an on-line
--- 6841,6846 ----
***************
*** 6983,6988 **** CheckRecoveryConsistency(void)
--- 6977,6988 ----
  		XLByteLE(minRecoveryPoint, EndRecPtr) &&
  		XLogRecPtrIsInvalid(ControlFile->backupStartPoint))
  	{
+ 		/*
+ 		 * Check to see if the XLOG sequence contained any unresolved
+ 		 * references to uninitialized pages.
+ 		 */
+ 		XLogCheckInvalidPages();
+ 
  		reachedMinRecoveryPoint = true;
  		ereport(LOG,
  				(errmsg("consistent recovery state reached at %X/%X",
***************
*** 7974,7980 **** RecoveryRestartPoint(const CheckPoint *checkPoint)
  	volatile XLogCtlData *xlogctl = XLogCtl;
  
  	/*
! 	 * Is it safe to checkpoint?  We must ask each of the resource managers
  	 * whether they have any partial state information that might prevent a
  	 * correct restart from this point.  If so, we skip this opportunity, but
  	 * return at the next checkpoint record for another try.
--- 7974,7980 ----
  	volatile XLogCtlData *xlogctl = XLogCtl;
  
  	/*
! 	 * Is it safe to restartpoint?  We must ask each of the resource managers
  	 * whether they have any partial state information that might prevent a
  	 * correct restart from this point.  If so, we skip this opportunity, but
  	 * return at the next checkpoint record for another try.
***************
*** 7994,7999 **** RecoveryRestartPoint(const CheckPoint *checkPoint)
--- 7994,8015 ----
  	}
  
  	/*
+ 	 * Is it safe to restartpoint?  We must check whether there are any
+ 	 * unresolved references to invalid pages that might prevent
+ 	 * a correct restart from this point.  If so, we skip this opportunity,
+ 	 * but return at the next checkpoint record for another try.
+ 	 */
+ 	if (have_invalid_pages())
+ 	{
+ 		elog(trace_recovery(DEBUG2),
+ 			 "could not record restart point at %X/%X because there "
+ 			 "are unresolved references to invalid pages",
+ 			 checkPoint->redo.xlogid,
+ 			 checkPoint->redo.xrecoff);
+ 		return;
+ 	}
+ 
+ 	/*
  	 * Copy the checkpoint record to shared memory, so that bgwriter can use
  	 * it the next time it wants to perform a restartpoint.
  	 */
*** a/src/backend/access/transam/xlogutils.c
--- b/src/backend/access/transam/xlogutils.c
***************
*** 52,57 **** typedef struct xl_invalid_page
--- 52,73 ----
  static HTAB *invalid_page_tab = NULL;
  
  
+ /* Report a reference to an invalid page */
+ static void
+ report_invalid_page(int elevel, RelFileNode node, ForkNumber forkno,
+ 					BlockNumber blkno, bool present)
+ {
+ 	char	   *path = relpathperm(node, forkno);
+ 
+ 	if (present)
+ 		elog(elevel, "page %u of relation %s is uninitialized",
+ 			 blkno, path);
+ 	else
+ 		elog(elevel, "page %u of relation %s does not exist",
+ 			 blkno, path);
+ 	pfree(path);
+ }
+ 
  /* Log a reference to an invalid page */
  static void
  log_invalid_page(RelFileNode node, ForkNumber forkno, BlockNumber blkno,
***************
*** 62,83 **** log_invalid_page(RelFileNode node, ForkNumber forkno, BlockNumber blkno,
  	bool		found;
  
  	/*
  	 * Log references to invalid pages at DEBUG1 level.  This allows some
  	 * tracing of the cause (note the elog context mechanism will tell us
  	 * something about the XLOG record that generated the reference).
  	 */
  	if (log_min_messages <= DEBUG1 || client_min_messages <= DEBUG1)
! 	{
! 		char	   *path = relpathperm(node, forkno);
! 
! 		if (present)
! 			elog(DEBUG1, "page %u of relation %s is uninitialized",
! 				 blkno, path);
! 		else
! 			elog(DEBUG1, "page %u of relation %s does not exist",
! 				 blkno, path);
! 		pfree(path);
! 	}
  
  	if (invalid_page_tab == NULL)
  	{
--- 78,101 ----
  	bool		found;
  
  	/*
+ 	 * Once recovery has reached a consistent state, the invalid-page
+ 	 * table should be empty and remain so. If a reference to an invalid
+ 	 * page is found after consistency is reached, emit PANIC immediately
+ 	 * instead of adding the entry in the invalid-page table.
+ 	 */
+ 	if (reachedMinRecoveryPoint)
+ 	{
+ 		report_invalid_page(WARNING, node, forkno, blkno, present);
+ 		elog(PANIC, "WAL contains references to invalid pages");
+ 	}
+ 
+ 	/*
  	 * Log references to invalid pages at DEBUG1 level.  This allows some
  	 * tracing of the cause (note the elog context mechanism will tell us
  	 * something about the XLOG record that generated the reference).
  	 */
  	if (log_min_messages <= DEBUG1 || client_min_messages <= DEBUG1)
! 		report_invalid_page(DEBUG1, node, forkno, blkno, present);
  
  	if (invalid_page_tab == NULL)
  	{
***************
*** 181,186 **** forget_invalid_pages_db(Oid dbid)
--- 199,214 ----
  	}
  }
  
+ /* Are there any unresolved references to invalid pages? */
+ bool
+ have_invalid_pages(void)
+ {
+ 	if (invalid_page_tab != NULL &&
+ 		hash_get_num_entries(invalid_page_tab) > 0)
+ 		return true;
+ 	return false;
+ }
+ 
  /* Complain about any remaining invalid-page entries */
  void
  XLogCheckInvalidPages(void)
***************
*** 200,214 **** XLogCheckInvalidPages(void)
  	 */
  	while ((hentry = (xl_invalid_page *) hash_seq_search(&status)) != NULL)
  	{
! 		char	   *path = relpathperm(hentry->key.node, hentry->key.forkno);
! 
! 		if (hentry->present)
! 			elog(WARNING, "page %u of relation %s was uninitialized",
! 				 hentry->key.blkno, path);
! 		else
! 			elog(WARNING, "page %u of relation %s did not exist",
! 				 hentry->key.blkno, path);
! 		pfree(path);
  		foundone = true;
  	}
  
--- 228,235 ----
  	 */
  	while ((hentry = (xl_invalid_page *) hash_seq_search(&status)) != NULL)
  	{
! 		report_invalid_page(WARNING, hentry->key.node, hentry->key.forkno,
! 							hentry->key.blkno, hentry->present);
  		foundone = true;
  	}
  
*** a/src/include/access/xlog.h
--- b/src/include/access/xlog.h
***************
*** 189,194 **** typedef enum
--- 189,196 ----
  
  extern XLogRecPtr XactLastRecEnd;
  
+ extern bool reachedMinRecoveryPoint;
+ 
  /* these variables are GUC parameters related to XLOG */
  extern int	CheckPointSegments;
  extern int	wal_keep_segments;
*** a/src/include/access/xlogutils.h
--- b/src/include/access/xlogutils.h
***************
*** 14,19 ****
--- 14,21 ----
  #include "storage/bufmgr.h"
  
  
+ extern bool have_invalid_pages(void);
+ 
  extern void XLogCheckInvalidPages(void);
  
  extern void XLogDropRelation(RelFileNode rnode, ForkNumber forknum);
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to