On Wed, Dec 9, 2009 at 6:25 PM, Fujii Masao <masao.fu...@gmail.com> wrote:
> Here is the patch:
>
> - Write an XLOG UNLOGGED record in WAL if WAL-logging is skipped for only
>  the reason that WAL archiving is not enabled and such record has not been
>  written yet.
>
> - Cause archive recovery to end if an XLOG UNLOGGED record is found during
>  it.

Here's an updated version of my "New XLOG record indicating WAL-skipping" patch.
http://archives.postgresql.org/pgsql-hackers/2009-12/msg00788.php

This is rebased to CVS HEAD.

Regards,

-- 
Fujii Masao
NIPPON TELEGRAPH AND TELEPHONE CORPORATION
NTT Open Source Software Center
*** a/src/backend/access/heap/heapam.c
--- b/src/backend/access/heap/heapam.c
***************
*** 1976,1981 **** heap_insert(Relation relation, HeapTuple tup, CommandId cid,
--- 1976,1988 ----
  		PageSetTLI(page, ThisTimeLineID);
  	}
  
+ 	/*
+ 	 * Write an XLOG UNLOGGED record if WAL-logging is skipped for the reason
+ 	 * that WAL archiving is not enabled.
+ 	 */
+ 	if (options & HEAP_INSERT_SKIP_WAL && !relation->rd_istemp)
+ 		XLogSkipLogging();
+ 
  	END_CRIT_SECTION();
  
  	UnlockReleaseBuffer(buffer);
*** a/src/backend/access/nbtree/nbtsort.c
--- b/src/backend/access/nbtree/nbtsort.c
***************
*** 215,220 **** _bt_leafbuild(BTSpool *btspool, BTSpool *btspool2)
--- 215,227 ----
  	 */
  	wstate.btws_use_wal = XLogArchivingActive() && !wstate.index->rd_istemp;
  
+ 	/*
+ 	 * Write an XLOG UNLOGGED record if WAL-logging is skipped for the reason
+ 	 * that WAL archiving is not enabled.
+ 	 */
+ 	if (!XLogArchivingActive() && !wstate.index->rd_istemp)
+ 		XLogSkipLogging();
+ 
  	/* reserve the metapage */
  	wstate.btws_pages_alloced = BTREE_METAPAGE + 1;
  	wstate.btws_pages_written = 0;
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 560,565 **** XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
--- 560,566 ----
  	bool		updrqst;
  	bool		doPageWrites;
  	bool		isLogSwitch = (rmid == RM_XLOG_ID && info == XLOG_SWITCH);
+ 	bool		isLogUnlogged = (rmid == RM_XLOG_ID && info == XLOG_UNLOGGED);
  
  	/* cross-check on whether we should be here or not */
  	if (!XLogInsertAllowed())
***************
*** 709,717 **** begin:;
  	 * error checking in ReadRecord.  This means that all callers of
  	 * XLogInsert must supply at least some not-in-a-buffer data.  However, we
  	 * make an exception for XLOG SWITCH records because we don't want them to
! 	 * ever cross a segment boundary.
  	 */
! 	if (len == 0 && !isLogSwitch)
  		elog(PANIC, "invalid xlog record length %u", len);
  
  	START_CRIT_SECTION();
--- 710,718 ----
  	 * error checking in ReadRecord.  This means that all callers of
  	 * XLogInsert must supply at least some not-in-a-buffer data.  However, we
  	 * make an exception for XLOG SWITCH records because we don't want them to
! 	 * ever cross a segment boundary. Also XLOG UNLOGGED records are exception.
  	 */
! 	if (len == 0 && !isLogSwitch && !isLogUnlogged)
  		elog(PANIC, "invalid xlog record length %u", len);
  
  	START_CRIT_SECTION();
***************
*** 3593,3600 **** ReadRecord(XLogRecPtr *RecPtr, int emode)
  got_record:;
  
  	/*
! 	 * xl_len == 0 is bad data for everything except XLOG SWITCH, where it is
! 	 * required.
  	 */
  	if (record->xl_rmid == RM_XLOG_ID && record->xl_info == XLOG_SWITCH)
  	{
--- 3594,3601 ----
  got_record:;
  
  	/*
! 	 * xl_len == 0 is bad data for everything except XLOG SWITCH and XLOG UNLOGGED,
! 	 * where it is required.
  	 */
  	if (record->xl_rmid == RM_XLOG_ID && record->xl_info == XLOG_SWITCH)
  	{
***************
*** 3606,3611 **** got_record:;
--- 3607,3622 ----
  			goto next_record_is_invalid;
  		}
  	}
+ 	else if (record->xl_rmid == RM_XLOG_ID && record->xl_info == XLOG_UNLOGGED)
+ 	{
+ 		if (record->xl_len != 0)
+ 		{
+ 			ereport(emode,
+ 					(errmsg("invalid xlog unlogged operation record at %X/%X",
+ 							RecPtr->xlogid, RecPtr->xrecoff)));
+ 			goto next_record_is_invalid;
+ 		}
+ 	}
  	else if (record->xl_len == 0)
  	{
  		ereport(emode,
***************
*** 3801,3806 **** got_record:;
--- 3812,3830 ----
  		 */
  		readOff = XLogSegSize - XLOG_BLCKSZ;
  	}
+ 
+ 	/*
+ 	 * Special processing if it's an XLOG UNLOGGED record and we are doing
+ 	 * an archive recovery.
+ 	 */
+ 	if (record->xl_rmid == RM_XLOG_ID && record->xl_info == XLOG_UNLOGGED &&
+ 		InArchiveRecovery)
+ 	{
+ 		ereport(emode,
+ 				(errmsg("unlogged operation record is found at %X/%X",
+ 						RecPtr->xlogid, RecPtr->xrecoff)));
+ 		goto next_record_is_invalid;
+ 	}
  	return (XLogRecord *) buffer;
  
  next_record_is_invalid:;
***************
*** 7204,7209 **** RequestXLogSwitch(void)
--- 7228,7263 ----
  }
  
  /*
+  * Write an XLOG UNLOGGED record.
+  */
+ void
+ XLogSkipLogging(void)
+ {
+ 	XLogRecData rdata;
+ 	static bool skipped = false;
+ 
+ 	/*
+ 	 * If an XLOG UNLOGGED record has already been written since
+ 	 * postmaster has started, we need to do nothing here.
+ 	 *
+ 	 * We can reduce the number of an XLOG UNLOGGED records written
+ 	 * by sharing the flag 'skipped' between backends. But this is
+ 	 * not worthwhile.
+ 	 */
+ 	if (skipped)
+ 		return;
+ 	skipped = true;
+ 
+ 	/* XLOG UNLOGGED, alone among xlog record types, has no data */
+ 	rdata.buffer = InvalidBuffer;
+ 	rdata.data = NULL;
+ 	rdata.len = 0;
+ 	rdata.next = NULL;
+ 
+ 	XLogInsert(RM_XLOG_ID, XLOG_UNLOGGED, &rdata);
+ }
+ 
+ /*
   * XLOG resource manager's routines
   *
   * Definitions of info values are in include/catalog/pg_control.h, though
***************
*** 7345,7350 **** xlog_redo(XLogRecPtr lsn, XLogRecord *record)
--- 7399,7408 ----
  			LWLockRelease(ControlFileLock);
  		}
  	}
+ 	else if (info == XLOG_UNLOGGED)
+ 	{
+ 		/* nothing to do here */
+ 	}
  }
  
  void
***************
*** 7394,7399 **** xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
--- 7452,7461 ----
  		appendStringInfo(buf, "backup end: %X/%X",
  						 startpoint.xlogid, startpoint.xrecoff);
  	}
+ 	else if (info == XLOG_UNLOGGED)
+ 	{
+ 		appendStringInfo(buf, "xlog unlogged");
+ 	}
  	else
  		appendStringInfo(buf, "UNKNOWN");
  }
*** a/src/backend/commands/cluster.c
--- b/src/backend/commands/cluster.c
***************
*** 801,806 **** copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
--- 801,813 ----
  	 */
  	use_wal = XLogArchivingActive() && !NewHeap->rd_istemp;
  
+ 	/*
+ 	 * Write an XLOG UNLOGGED record if WAL-logging is skipped for the reason
+ 	 * that WAL archiving is not enabled.
+ 	 */
+ 	if (!XLogArchivingActive() && !NewHeap->rd_istemp)
+ 		XLogSkipLogging();
+ 
  	/* use_wal off requires rd_targblock be initially invalid */
  	Assert(NewHeap->rd_targblock == InvalidBlockNumber);
  
*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
***************
*** 7050,7055 **** copy_relation_data(SMgrRelation src, SMgrRelation dst,
--- 7050,7062 ----
  	 */
  	use_wal = XLogArchivingActive() && !istemp;
  
+ 	/*
+ 	 * Write an XLOG UNLOGGED record if WAL-logging is skipped for the reason
+ 	 * that WAL archiving is not enabled.
+ 	 */
+ 	if (!XLogArchivingActive() && !istemp)
+ 		XLogSkipLogging();
+ 
  	nblocks = smgrnblocks(src, forkNum);
  
  	for (blkno = 0; blkno < nblocks; blkno++)
*** a/src/include/access/xlog.h
--- b/src/include/access/xlog.h
***************
*** 260,265 **** extern XLogRecPtr GetRedoRecPtr(void);
--- 260,267 ----
  extern XLogRecPtr GetInsertRecPtr(void);
  extern void GetNextXidAndEpoch(TransactionId *xid, uint32 *epoch);
  
+ extern void XLogSkipLogging(void);
+ 
  extern void StartupProcessMain(void);
  
  #endif   /* XLOG_H */
*** a/src/include/catalog/pg_control.h
--- b/src/include/catalog/pg_control.h
***************
*** 63,68 **** typedef struct CheckPoint
--- 63,69 ----
  #define XLOG_NEXTOID					0x30
  #define XLOG_SWITCH						0x40
  #define XLOG_BACKUP_END					0x50
+ #define XLOG_UNLOGGED					0x60
  
  
  /* System status indicator */
-- 
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