@@ -88,7 +88,7 @@ static bool getRecordTimestamp(XLogReaderState *record, TimestampTz *recordXtime
8888
8989typedef struct XLogPageReadPrivate
9090{
91- int thread_num ;
91+ int thread_num ;
9292 const char * archivedir ;
9393 TimeLineID tli ;
9494 uint32 xlog_seg_size ;
@@ -132,8 +132,7 @@ static XLogReaderState *InitXLogPageRead(XLogPageReadPrivate *private_data,
132132 TimeLineID tli , uint32 xlog_seg_size ,
133133 bool allocate_reader );
134134static void CleanupXLogPageRead (XLogReaderState * xlogreader );
135- static void PrintXLogCorruptionMsg (XLogPageReadPrivate * private_data ,
136- int elevel );
135+ static void PrintXLogCorruptionMsg (XLogPageReadPrivate * private_data , int elevel );
137136
138137static XLogSegNo nextSegNoToRead = 0 ;
139138static pthread_mutex_t wal_segment_mutex = PTHREAD_MUTEX_INITIALIZER ;
@@ -239,11 +238,17 @@ doExtractPageMap(void *arg)
239238 */
240239 if (XLogRecPtrIsInvalid (found ))
241240 {
242- elog (WARNING , "Thread [%d]: could not read WAL record at %X/%X. %s" ,
243- private_data -> thread_num ,
244- (uint32 ) (extract_arg -> startpoint >> 32 ),
245- (uint32 ) (extract_arg -> startpoint ),
246- (xlogreader -> errormsg_buf [0 ] != '\0' )?xlogreader -> errormsg_buf :"" );
241+ if (xlogreader -> errormsg_buf [0 ] != '\0' )
242+ elog (WARNING , "Thread [%d]: could not read WAL record at %X/%X: %s" ,
243+ private_data -> thread_num ,
244+ (uint32 ) (extract_arg -> startpoint >> 32 ),
245+ (uint32 ) (extract_arg -> startpoint ),
246+ xlogreader -> errormsg_buf );
247+ else
248+ elog (WARNING , "Thread [%d]: could not read WAL record at %X/%X" ,
249+ private_data -> thread_num ,
250+ (uint32 ) (extract_arg -> startpoint >> 32 ),
251+ (uint32 ) (extract_arg -> startpoint ));
247252 PrintXLogCorruptionMsg (private_data , ERROR );
248253 }
249254 extract_arg -> startpoint = found ;
@@ -766,6 +771,104 @@ wal_contains_lsn(const char *archivedir, XLogRecPtr target_lsn,
766771 return res ;
767772}
768773
774+ /*
775+ * Get last valid LSN within the WAL segment with number 'segno'. If 'start_lsn'
776+ * is in the segment with number 'segno' then start from 'start_lsn', otherwise
777+ * start from offset 0 within the segment.
778+ */
779+ XLogRecPtr
780+ get_last_wal_lsn (const char * archivedir , XLogRecPtr start_lsn ,
781+ XLogSegNo segno , TimeLineID tli , uint32 seg_size )
782+ {
783+ XLogReaderState * xlogreader ;
784+ XLogPageReadPrivate private ;
785+ XLogRecPtr startpoint ;
786+ XLogSegNo start_segno ;
787+ XLogRecPtr res = InvalidXLogRecPtr ;
788+
789+ if (segno == 0 )
790+ elog (ERROR , "Invalid WAL segment number " UINT64_FORMAT , segno );
791+
792+ elog (LOG , "Retreiving last LSN of the segment with number " UINT64_FORMAT ,
793+ segno );
794+
795+ xlogreader = InitXLogPageRead (& private , archivedir , tli , seg_size , true);
796+
797+ /*
798+ * Calculate startpoint. Decide: we should use 'start_lsn' or offset 0.
799+ */
800+ GetXLogSegNo (start_lsn , start_segno , seg_size );
801+ if (start_segno == segno )
802+ startpoint = start_lsn ;
803+ else
804+ {
805+ XLogRecPtr found ;
806+
807+ GetXLogRecPtr (segno , 0 , seg_size , startpoint );
808+ found = XLogFindNextRecord (xlogreader , startpoint );
809+
810+ if (XLogRecPtrIsInvalid (found ))
811+ {
812+ if (xlogreader -> errormsg_buf [0 ] != '\0' )
813+ elog (WARNING , "Could not read WAL record at %X/%X: %s" ,
814+ (uint32 ) (startpoint >> 32 ), (uint32 ) (startpoint ),
815+ xlogreader -> errormsg_buf );
816+ else
817+ elog (WARNING , "Could not read WAL record at %X/%X" ,
818+ (uint32 ) (startpoint >> 32 ), (uint32 ) (startpoint ));
819+ PrintXLogCorruptionMsg (& private , ERROR );
820+ }
821+ startpoint = found ;
822+ }
823+
824+ elog (VERBOSE , "Starting LSN is %X/%X" ,
825+ (uint32 ) (startpoint >> 32 ), (uint32 ) (startpoint ));
826+
827+ while (true)
828+ {
829+ XLogRecord * record ;
830+ char * errormsg ;
831+ XLogSegNo next_segno = 0 ;
832+
833+ if (interrupted )
834+ elog (ERROR , "Interrupted during WAL reading" );
835+
836+ record = XLogReadRecord (xlogreader , startpoint , & errormsg );
837+ if (record == NULL )
838+ {
839+ XLogRecPtr errptr ;
840+
841+ errptr = XLogRecPtrIsInvalid (startpoint ) ? xlogreader -> EndRecPtr :
842+ startpoint ;
843+
844+ if (errormsg )
845+ elog (WARNING , "Could not read WAL record at %X/%X: %s" ,
846+ (uint32 ) (errptr >> 32 ), (uint32 ) (errptr ),
847+ errormsg );
848+ else
849+ elog (WARNING , "Could not read WAL record at %X/%X" ,
850+ (uint32 ) (errptr >> 32 ), (uint32 ) (errptr ));
851+ PrintXLogCorruptionMsg (& private , ERROR );
852+ }
853+
854+ res = xlogreader -> ReadRecPtr ;
855+
856+ /* continue reading at next record */
857+ startpoint = InvalidXLogRecPtr ;
858+
859+ GetXLogSegNo (xlogreader -> EndRecPtr , next_segno , seg_size );
860+ if (next_segno > segno )
861+ break ;
862+ }
863+
864+ CleanupXLogPageRead (xlogreader );
865+ XLogReaderFree (xlogreader );
866+
867+ elog (VERBOSE , "Last LSN is %X/%X" , (uint32 ) (res >> 32 ), (uint32 ) (res ));
868+
869+ return res ;
870+ }
871+
769872#ifdef HAVE_LIBZ
770873/*
771874 * Show error during work with compressed file
@@ -1035,6 +1138,12 @@ PrintXLogCorruptionMsg(XLogPageReadPrivate *private_data, int elevel)
10351138 private_data -> gz_xlogpath );
10361139#endif
10371140 }
1141+ else
1142+ {
1143+ /* Cannot tell what happened specifically */
1144+ elog (elevel , "Thread [%d]: An error occured during WAL reading" ,
1145+ private_data -> thread_num );
1146+ }
10381147}
10391148
10401149/*
0 commit comments