@ -338,17 +338,31 @@ GenericXLogFinish(GenericXLogState *state)
{
{
PageData * pageData = & state - > pages [ i ] ;
PageData * pageData = & state - > pages [ i ] ;
Page page ;
Page page ;
PageHeader pageHeader ;
if ( BufferIsInvalid ( pageData - > buffer ) )
if ( BufferIsInvalid ( pageData - > buffer ) )
continue ;
continue ;
page = BufferGetPage ( pageData - > buffer , NULL , NULL ,
page = BufferGetPage ( pageData - > buffer , NULL , NULL ,
BGP_NO_SNAPSHOT_TEST ) ;
BGP_NO_SNAPSHOT_TEST ) ;
pageHeader = ( PageHeader ) pageData - > image ;
if ( pageData - > fullImage )
if ( pageData - > fullImage )
{
{
/* A full page image does not require anything special */
/*
memcpy ( page , pageData - > image , BLCKSZ ) ;
* A full - page image does not require us to supply any xlog
* data . Just apply the image , being careful to zero the
* " hole " between pd_lower and pd_upper in order to avoid
* divergence between actual page state and what replay would
* produce .
*/
memcpy ( page , pageData - > image , pageHeader - > pd_lower ) ;
memset ( page + pageHeader - > pd_lower , 0 ,
pageHeader - > pd_upper - pageHeader - > pd_lower ) ;
memcpy ( page + pageHeader - > pd_upper ,
pageData - > image + pageHeader - > pd_upper ,
BLCKSZ - pageHeader - > pd_upper ) ;
XLogRegisterBuffer ( i , pageData - > buffer ,
XLogRegisterBuffer ( i , pageData - > buffer ,
REGBUF_FORCE_IMAGE | REGBUF_STANDARD ) ;
REGBUF_FORCE_IMAGE | REGBUF_STANDARD ) ;
}
}
@ -359,7 +373,15 @@ GenericXLogFinish(GenericXLogState *state)
* associated with this page .
* associated with this page .
*/
*/
computeDelta ( pageData , page , ( Page ) pageData - > image ) ;
computeDelta ( pageData , page , ( Page ) pageData - > image ) ;
memcpy ( page , pageData - > image , BLCKSZ ) ;
/* Apply the image, with zeroed "hole" as above */
memcpy ( page , pageData - > image , pageHeader - > pd_lower ) ;
memset ( page + pageHeader - > pd_lower , 0 ,
pageHeader - > pd_upper - pageHeader - > pd_lower ) ;
memcpy ( page + pageHeader - > pd_upper ,
pageData - > image + pageHeader - > pd_upper ,
BLCKSZ - pageHeader - > pd_upper ) ;
XLogRegisterBuffer ( i , pageData - > buffer , REGBUF_STANDARD ) ;
XLogRegisterBuffer ( i , pageData - > buffer , REGBUF_STANDARD ) ;
XLogRegisterBufData ( i , pageData - > delta , pageData - > deltaLen ) ;
XLogRegisterBufData ( i , pageData - > delta , pageData - > deltaLen ) ;
}
}
@ -395,6 +417,7 @@ GenericXLogFinish(GenericXLogState *state)
BGP_NO_SNAPSHOT_TEST ) ,
BGP_NO_SNAPSHOT_TEST ) ,
pageData - > image ,
pageData - > image ,
BLCKSZ ) ;
BLCKSZ ) ;
/* We don't worry about zeroing the "hole" in this case */
MarkBufferDirty ( pageData - > buffer ) ;
MarkBufferDirty ( pageData - > buffer ) ;
}
}
END_CRIT_SECTION ( ) ;
END_CRIT_SECTION ( ) ;
@ -473,6 +496,7 @@ generic_redo(XLogReaderState *record)
if ( action = = BLK_NEEDS_REDO )
if ( action = = BLK_NEEDS_REDO )
{
{
Page page ;
Page page ;
PageHeader pageHeader ;
char * blockDelta ;
char * blockDelta ;
Size blockDeltaSize ;
Size blockDeltaSize ;
@ -481,6 +505,16 @@ generic_redo(XLogReaderState *record)
blockDelta = XLogRecGetBlockData ( record , block_id , & blockDeltaSize ) ;
blockDelta = XLogRecGetBlockData ( record , block_id , & blockDeltaSize ) ;
applyPageRedo ( page , blockDelta , blockDeltaSize ) ;
applyPageRedo ( page , blockDelta , blockDeltaSize ) ;
/*
* Since the delta contains no information about what ' s in the
* " hole " between pd_lower and pd_upper , set that to zero to
* ensure we produce the same page state that application of the
* logged action by GenericXLogFinish did .
*/
pageHeader = ( PageHeader ) page ;
memset ( page + pageHeader - > pd_lower , 0 ,
pageHeader - > pd_upper - pageHeader - > pd_lower ) ;
PageSetLSN ( page , lsn ) ;
PageSetLSN ( page , lsn ) ;
MarkBufferDirty ( buffers [ block_id ] ) ;
MarkBufferDirty ( buffers [ block_id ] ) ;
}
}