@ -7,7 +7,7 @@
* Portions Copyright ( c ) 1996 - 2005 , PostgreSQL Global Development Group
* Portions Copyright ( c ) 1996 - 2005 , PostgreSQL Global Development Group
* Portions Copyright ( c ) 1994 , Regents of the University of California
* Portions Copyright ( c ) 1994 , Regents of the University of California
*
*
* $ PostgreSQL : pgsql / src / backend / access / transam / xlog . c , v 1.196 2005 / 06 / 06 17 : 01 : 23 tgl Exp $
* $ PostgreSQL : pgsql / src / backend / access / transam / xlog . c , v 1.197 2005 / 06 / 06 20 : 22 : 57 tgl Exp $
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
@ -434,7 +434,8 @@ static void exitArchiveRecovery(TimeLineID endTLI,
uint32 endLogId , uint32 endLogSeg ) ;
uint32 endLogId , uint32 endLogSeg ) ;
static bool recoveryStopsHere ( XLogRecord * record , bool * includeThis ) ;
static bool recoveryStopsHere ( XLogRecord * record , bool * includeThis ) ;
static void SetBkpBlock ( BkpBlock * bkpb , Buffer buffer ) ;
static bool XLogCheckBuffer ( XLogRecData * rdata ,
XLogRecPtr * lsn , BkpBlock * bkpb ) ;
static bool AdvanceXLInsertBuffer ( void ) ;
static bool AdvanceXLInsertBuffer ( void ) ;
static void XLogWrite ( XLogwrtRqst WriteRqst ) ;
static void XLogWrite ( XLogwrtRqst WriteRqst ) ;
static int XLogFileInit ( uint32 log , uint32 seg ,
static int XLogFileInit ( uint32 log , uint32 seg ,
@ -473,7 +474,7 @@ static void remove_backup_label(void);
/*
/*
* Insert an XLOG record having the specified RMID and info bytes ,
* Insert an XLOG record having the specified RMID and info bytes ,
* with the body of the record being the data chunk ( s ) described by
* with the body of the record being the data chunk ( s ) described by
* the rdata list ( see xlog . h for notes about rdata ) .
* the rdata chain ( see xlog . h for notes about rdata ) .
*
*
* Returns XLOG pointer to end of record ( beginning of next record ) .
* Returns XLOG pointer to end of record ( beginning of next record ) .
* This can be used as LSN for data pages affected by the logged action .
* This can be used as LSN for data pages affected by the logged action .
@ -532,7 +533,7 @@ XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
}
}
/*
/*
* Here we scan the rdata list , determine which buffers must be backed
* Here we scan the rdata chain , determine which buffers must be backed
* up , and compute the CRC values for the data . Note that the record
* up , and compute the CRC values for the data . Note that the record
* header isn ' t added into the CRC initially since we don ' t know the
* header isn ' t added into the CRC initially since we don ' t know the
* final length or info bits quite yet . Thus , the CRC will represent
* final length or info bits quite yet . Thus , the CRC will represent
@ -543,13 +544,13 @@ XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
* below . We could prevent the race by doing all this work while
* below . We could prevent the race by doing all this work while
* holding the insert lock , but it seems better to avoid doing CRC
* holding the insert lock , but it seems better to avoid doing CRC
* calculations while holding the lock . This means we have to be
* calculations while holding the lock . This means we have to be
* careful about modifying the rdata list until we know we aren ' t
* careful about modifying the rdata chain until we know we aren ' t
* going to loop back again . The only change we allow ourselves to
* going to loop back again . The only change we allow ourselves to
* make earlier is to set rdt - > data = NULL in list items we have
* make earlier is to set rdt - > data = NULL in chain items we have
* decided we will have to back up the whole buffer for . This is OK
* decided we will have to back up the whole buffer for . This is OK
* because we will certainly decide the same thing again for those
* because we will certainly decide the same thing again for those
* items if we do it over ; doing it here saves an extra pass over the
* items if we do it over ; doing it here saves an extra pass over the
* list later .
* chain later .
*/
*/
begin : ;
begin : ;
for ( i = 0 ; i < XLR_MAX_BKP_BLOCKS ; i + + )
for ( i = 0 ; i < XLR_MAX_BKP_BLOCKS ; i + + )
@ -575,7 +576,7 @@ begin:;
{
{
if ( rdt - > buffer = = dtbuf [ i ] )
if ( rdt - > buffer = = dtbuf [ i ] )
{
{
/* Buffer already referenced by earlier list item */
/* Buffer already referenced by earlier chain item */
if ( dtbuf_bkp [ i ] )
if ( dtbuf_bkp [ i ] )
rdt - > data = NULL ;
rdt - > data = NULL ;
else if ( rdt - > data )
else if ( rdt - > data )
@ -589,15 +590,9 @@ begin:;
{
{
/* OK, put it in this slot */
/* OK, put it in this slot */
dtbuf [ i ] = rdt - > buffer ;
dtbuf [ i ] = rdt - > buffer ;
if ( XLogCheckBuffer ( rdt , & ( dtbuf_lsn [ i ] ) , & ( dtbuf_xlg [ i ] ) ) )
/*
* XXX We assume page LSN is first data on page
*/
dtbuf_lsn [ i ] = * ( ( XLogRecPtr * ) BufferGetBlock ( rdt - > buffer ) ) ;
if ( XLByteLE ( dtbuf_lsn [ i ] , RedoRecPtr ) )
{
{
dtbuf_bkp [ i ] = true ;
dtbuf_bkp [ i ] = true ;
SetBkpBlock ( & ( dtbuf_xlg [ i ] ) , rdt - > buffer ) ;
rdt - > data = NULL ;
rdt - > data = NULL ;
}
}
else if ( rdt - > data )
else if ( rdt - > data )
@ -612,7 +607,7 @@ begin:;
elog ( PANIC , " can backup at most %d blocks per xlog record " ,
elog ( PANIC , " can backup at most %d blocks per xlog record " ,
XLR_MAX_BKP_BLOCKS ) ;
XLR_MAX_BKP_BLOCKS ) ;
}
}
/* Break out of loop when rdt points to last list item */
/* Break out of loop when rdt points to last chain item */
if ( rdt - > next = = NULL )
if ( rdt - > next = = NULL )
break ;
break ;
rdt = rdt - > next ;
rdt = rdt - > next ;
@ -726,15 +721,15 @@ begin:;
}
}
/*
/*
* Make additional rdata list entries for the backup blocks , so that
* Make additional rdata chain entries for the backup blocks , so that
* we don ' t need to special - case them in the write loop . Note that we
* we don ' t need to special - case them in the write loop . Note that we
* have now irrevocably changed the input rdata list . At the exit of
* have now irrevocably changed the input rdata chain . At the exit of
* this loop , write_len includes the backup block data .
* this loop , write_len includes the backup block data .
*
*
* Also set the appropriate info bits to show which buffers were backed
* Also set the appropriate info bits to show which buffers were backed
* up . The i ' th XLR_SET_BKP_BLOCK bit corresponds to the i ' th
* up . The i ' th XLR_SET_BKP_BLOCK bit corresponds to the i ' th
* distinct buffer value ( ignoring InvalidBuffer ) appearing in the
* distinct buffer value ( ignoring InvalidBuffer ) appearing in the
* rdata list .
* rdata chain .
*/
*/
write_len = len ;
write_len = len ;
for ( i = 0 ; i < XLR_MAX_BKP_BLOCKS ; i + + )
for ( i = 0 ; i < XLR_MAX_BKP_BLOCKS ; i + + )
@ -742,7 +737,7 @@ begin:;
BkpBlock * bkpb ;
BkpBlock * bkpb ;
char * page ;
char * page ;
if ( dtbuf [ i ] = = InvalidBuffer | | ! ( dtbuf_bkp [ i ] ) )
if ( ! dtbuf_bkp [ i ] )
continue ;
continue ;
info | = XLR_SET_BKP_BLOCK ( i ) ;
info | = XLR_SET_BKP_BLOCK ( i ) ;
@ -938,43 +933,64 @@ begin:;
}
}
/*
/*
* Fill a BkpBlock struct given a buffer containing the page to be saved
* Determine whether the buffer referenced by an XLogRecData item has to
*
* be backed up , and if so fill a BkpBlock struct for it . In any case
* This is nontrivial only because it has to decide whether to apply " hole
* save the buffer ' s LSN at * lsn .
* compression " .
*/
*/
static void
static bool
SetBkpBlock ( BkpBlock * bkpb , Buffer buffer )
XLogCheckBuffer ( XLogRecData * rdata ,
XLogRecPtr * lsn , BkpBlock * bkpb )
{
{
PageHeader page ;
PageHeader page ;
uint16 offset ;
uint16 length ;
/* Save page identity info */
page = ( PageHeader ) BufferGetBlock ( rdata - > buffer ) ;
bkpb - > node = BufferGetFileNode ( buffer ) ;
bkpb - > block = BufferGetBlockNumber ( buffer ) ;
/*
* XXX We assume page LSN is first data on * every * page that can be
* passed to XLogInsert , whether it otherwise has the standard page
* layout or not .
*/
* lsn = page - > pd_lsn ;
/* Test whether there is a "hole" containing zeroes in the page */
if ( XLByteLE ( page - > pd_lsn , RedoRecPtr ) )
page = ( PageHeader ) BufferGetBlock ( buffer ) ;
offset = page - > pd_lower ;
/* Check if pd_lower appears sane at all */
if ( offset > = SizeOfPageHeaderData & & offset < BLCKSZ )
{
{
char * spd = ( char * ) page + offset ;
/*
char * epd = ( char * ) page + BLCKSZ ;
* The page needs to be backed up , so set up * bkpb
char * pd = spd ;
*/
bkpb - > node = BufferGetFileNode ( rdata - > buffer ) ;
bkpb - > block = BufferGetBlockNumber ( rdata - > buffer ) ;
while ( pd < epd & & * pd = = ' \0 ' )
if ( rdata - > buffer_std )
pd + + ;
{
/* Assume we can omit data between pd_lower and pd_upper */
uint16 lower = page - > pd_lower ;
uint16 upper = page - > pd_upper ;
length = pd - spd ;
if ( lower > = SizeOfPageHeaderData & &
if ( length = = 0 )
upper > lower & &
offset = 0 ;
upper < = BLCKSZ )
{
bkpb - > hole_offset = lower ;
bkpb - > hole_length = upper - lower ;
}
else
{
/* No "hole" to compress out */
bkpb - > hole_offset = 0 ;
bkpb - > hole_length = 0 ;
}
}
}
else
else
offset = length = 0 ;
{
bkpb - > hole_offset = offset ;
/* Not a standard page header, don't try to eliminate "hole" */
bkpb - > hole_length = length ;
bkpb - > hole_offset = 0 ;
bkpb - > hole_length = 0 ;
}
return true ; /* buffer requires backup */
}
return false ; /* buffer does not need to be backed up */
}
}
/*
/*
@ -5093,9 +5109,9 @@ CreateCheckPoint(bool shutdown, bool force)
/*
/*
* Now insert the checkpoint record into XLOG .
* Now insert the checkpoint record into XLOG .
*/
*/
rdata . buffer = InvalidBuffer ;
rdata . data = ( char * ) ( & checkPoint ) ;
rdata . data = ( char * ) ( & checkPoint ) ;
rdata . len = sizeof ( checkPoint ) ;
rdata . len = sizeof ( checkPoint ) ;
rdata . buffer = InvalidBuffer ;
rdata . next = NULL ;
rdata . next = NULL ;
recptr = XLogInsert ( RM_XLOG_ID ,
recptr = XLogInsert ( RM_XLOG_ID ,
@ -5197,9 +5213,9 @@ XLogPutNextOid(Oid nextOid)
{
{
XLogRecData rdata ;
XLogRecData rdata ;
rdata . buffer = InvalidBuffer ;
rdata . data = ( char * ) ( & nextOid ) ;
rdata . data = ( char * ) ( & nextOid ) ;
rdata . len = sizeof ( Oid ) ;
rdata . len = sizeof ( Oid ) ;
rdata . buffer = InvalidBuffer ;
rdata . next = NULL ;
rdata . next = NULL ;
( void ) XLogInsert ( RM_XLOG_ID , XLOG_NEXTOID , & rdata ) ;
( void ) XLogInsert ( RM_XLOG_ID , XLOG_NEXTOID , & rdata ) ;
/*
/*
@ -5220,9 +5236,9 @@ XLogPutNextMultiXactId(MultiXactId nextMulti)
{
{
XLogRecData rdata ;
XLogRecData rdata ;
rdata . buffer = InvalidBuffer ;
rdata . data = ( char * ) ( & nextMulti ) ;
rdata . data = ( char * ) ( & nextMulti ) ;
rdata . len = sizeof ( MultiXactId ) ;
rdata . len = sizeof ( MultiXactId ) ;
rdata . buffer = InvalidBuffer ;
rdata . next = NULL ;
rdata . next = NULL ;
( void ) XLogInsert ( RM_XLOG_ID , XLOG_NEXTMULTI , & rdata ) ;
( void ) XLogInsert ( RM_XLOG_ID , XLOG_NEXTMULTI , & rdata ) ;
/*
/*