@ -10,9 +10,11 @@
*
*
* NOTES
* NOTES
* See xlogreader . h for more notes on this facility .
* See xlogreader . h for more notes on this facility .
*
* This file is compiled as both front - end and backend code , so it
* may not use ereport , server - defined static variables , etc .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
# include "postgres.h"
# include "postgres.h"
# include "access/transam.h"
# include "access/transam.h"
@ -192,7 +194,7 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
{
{
XLogRecord * record ;
XLogRecord * record ;
XLogRecPtr targetPagePtr ;
XLogRecPtr targetPagePtr ;
bool randAccess = false ;
bool randAccess ;
uint32 len ,
uint32 len ,
total_len ;
total_len ;
uint32 targetRecOff ;
uint32 targetRecOff ;
@ -200,6 +202,13 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
bool gotheader ;
bool gotheader ;
int readOff ;
int readOff ;
/*
* randAccess indicates whether to verify the previous - record pointer of
* the record we ' re reading . We only do this if we ' re reading
* sequentially , which is what we initially assume .
*/
randAccess = false ;
/* reset error state */
/* reset error state */
* errormsg = NULL ;
* errormsg = NULL ;
state - > errormsg_buf [ 0 ] = ' \0 ' ;
state - > errormsg_buf [ 0 ] = ' \0 ' ;
@ -208,6 +217,7 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
if ( RecPtr = = InvalidXLogRecPtr )
if ( RecPtr = = InvalidXLogRecPtr )
{
{
/* No explicit start point; read the record after the one we just read */
RecPtr = state - > EndRecPtr ;
RecPtr = state - > EndRecPtr ;
if ( state - > ReadRecPtr = = InvalidXLogRecPtr )
if ( state - > ReadRecPtr = = InvalidXLogRecPtr )
@ -223,11 +233,13 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
else
else
{
{
/*
/*
* Caller supplied a position to start at .
*
* In this case , the passed - in record pointer should already be
* In this case , the passed - in record pointer should already be
* pointing to a valid record starting position .
* pointing to a valid record starting position .
*/
*/
Assert ( XRecOffIsValid ( RecPtr ) ) ;
Assert ( XRecOffIsValid ( RecPtr ) ) ;
randAccess = true ; /* allow readPageTLI to go backwards too */
randAccess = true ;
}
}
state - > currRecPtr = RecPtr ;
state - > currRecPtr = RecPtr ;
@ -309,8 +321,10 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
/* XXX: more validation should be done here */
/* XXX: more validation should be done here */
if ( total_len < SizeOfXLogRecord )
if ( total_len < SizeOfXLogRecord )
{
{
report_invalid_record ( state , " invalid record length at %X/%X " ,
report_invalid_record ( state ,
( uint32 ) ( RecPtr > > 32 ) , ( uint32 ) RecPtr ) ;
" invalid record length at %X/%X: wanted %lu, got %u " ,
( uint32 ) ( RecPtr > > 32 ) , ( uint32 ) RecPtr ,
SizeOfXLogRecord , total_len ) ;
goto err ;
goto err ;
}
}
gotheader = false ;
gotheader = false ;
@ -463,12 +477,10 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
err :
err :
/*
/*
* Invalidate the xlog page we ' ve cached . We might read from a different
* Invalidate the read state . We might read from a different source after
* source after failure .
* failure .
*/
*/
state - > readSegNo = 0 ;
XLogReaderInvalReadState ( state ) ;
state - > readOff = 0 ;
state - > readLen = 0 ;
if ( state - > errormsg_buf [ 0 ] ! = ' \0 ' )
if ( state - > errormsg_buf [ 0 ] ! = ' \0 ' )
* errormsg = state - > errormsg_buf ;
* errormsg = state - > errormsg_buf ;
@ -572,7 +584,7 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
if ( ! ValidXLogPageHeader ( state , pageptr , hdr ) )
if ( ! ValidXLogPageHeader ( state , pageptr , hdr ) )
goto err ;
goto err ;
/* update cach e information */
/* update read stat e information */
state - > readSegNo = targetSegNo ;
state - > readSegNo = targetSegNo ;
state - > readOff = targetPageOff ;
state - > readOff = targetPageOff ;
state - > readLen = readLen ;
state - > readLen = readLen ;
@ -580,10 +592,19 @@ ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
return readLen ;
return readLen ;
err :
err :
XLogReaderInvalReadState ( state ) ;
return - 1 ;
}
/*
* Invalidate the xlogreader ' s read state to force a re - read .
*/
void
XLogReaderInvalReadState ( XLogReaderState * state )
{
state - > readSegNo = 0 ;
state - > readSegNo = 0 ;
state - > readOff = 0 ;
state - > readOff = 0 ;
state - > readLen = 0 ;
state - > readLen = 0 ;
return - 1 ;
}
}
/*
/*
@ -600,8 +621,9 @@ ValidXLogRecordHeader(XLogReaderState *state, XLogRecPtr RecPtr,
if ( record - > xl_tot_len < SizeOfXLogRecord )
if ( record - > xl_tot_len < SizeOfXLogRecord )
{
{
report_invalid_record ( state ,
report_invalid_record ( state ,
" invalid record length at %X/%X " ,
" invalid record length at %X/%X: wanted %lu, got %u " ,
( uint32 ) ( RecPtr > > 32 ) , ( uint32 ) RecPtr ) ;
( uint32 ) ( RecPtr > > 32 ) , ( uint32 ) RecPtr ,
SizeOfXLogRecord , record - > xl_tot_len ) ;
return false ;
return false ;
}
}
if ( record - > xl_rmid > RM_MAX_ID )
if ( record - > xl_rmid > RM_MAX_ID )
@ -907,11 +929,9 @@ XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr)
err :
err :
out :
out :
/* Reset state to what we had before finding the record */
/* Reset state to what we had before finding the record */
state - > readSegNo = 0 ;
state - > readOff = 0 ;
state - > readLen = 0 ;
state - > ReadRecPtr = saved_state . ReadRecPtr ;
state - > ReadRecPtr = saved_state . ReadRecPtr ;
state - > EndRecPtr = saved_state . EndRecPtr ;
state - > EndRecPtr = saved_state . EndRecPtr ;
XLogReaderInvalReadState ( state ) ;
return found ;
return found ;
}
}